/*jslint undef: true, newcap: true */

(function($,window,document,undef) {

  /**
   * All global parameters for shopplan A will be defined here. Since we need to encapsulate we put these in an settings object.
   */
  if (!window.globalShopUrls) {
    window.globalShopUrls = {
      htmlUrl: "",
      layoutUrl: '/layout.rebranding_integratie',
      extchattool: 'http://shop-rebranding.telfort.nl/chat'
    };
  }

  if (!window.console) {
    window.console = {
      log: function () {}
    };
  }

  $(function() {
	/*
    var docolorboxes = function () {
      $("a[rel=slideshow]").colorbox({
        width: "750px"
      }).filter(":not(:first-child)").hide();

      $(".lightbox-inline").each(function () {
        $($(this).attr("href")).css("padding", "1em");
      }).colorbox({
        width: "750px",
        inline: true
      });

      $(".lightbox-xhr").colorbox({
        width: "750px",
        inline: false
      });

      $(".phone-image > a").colorbox({
        width: "750px",
        transition: "none",
        scalePhotos: false,
        scrolling: false,
        inline: false
      });
    };
    if (!$.colorbox) {
      $.getScript(globalShopUrls.layoutUrl + "/javascript/template/jquery.colorbox.js", docolorboxes);
    }
    else {
      docolorboxes.call(this);
    }
	*/

    /*$(document).bind("cbox_load", function () {
      $("#cboxClose").html("<a class=\"lightbox-button-close\" href=\"#\">Sluiten</a>").click(function() {
      return false;
      });
    });*/

    $("a.button-engaging-nexticon").each(function() {
      if ($(this)[0].hash == '#sluiten') {
        $(this).click(function () {
          $.colorbox.close();
          return false;
        });
      }
    });

    $(document).bind("cbox_loaded", function () {
      $("#cboxLoadedContent .button-engaging").modernBox({ applyPngFix: false });
    });
  });

  $(window).load(function() {
    var userFlashMessage = $.metavalue("userFlash");
    if (userFlashMessage) {
      $.displayAlert({
        //Default options
        title: "",
        text: userFlashMessage,
        buttons: {
          ok: "Ga verder"
        },
        callback: function (result) {
          if (result == 'ok') {
            $.colorbox.close();
          }
        }
      });
    }
  });

  $.fn.enabled = function (enabled) {
    if (typeof enabled != "undefined") {
      return this.each(function () {
        this.disabled = !enabled;
      });
    }

    if (this.length == 1) {
      return !this.get(0).disabled;
    }
    return $.makeArray(this.map(function(i, el) { return !el.disabled; }));
  };

  $.fn.checked = function (checked) {
    if (typeof checked != "undefined") {
      return this.each(function () {
        this.checked = !!checked;
      });
    }

    if (this.length == 1) {
      return !!this.get(0).checked;
    }
    return $.makeArray(this.map(function(i, el) { return !!el.checked; }));
  };

  /**
   *  Will remove all classes that has a part of the param in it.
   *  @param classNameFragment NOT NULL fragment in the class to search for and to remove. When not matched, nothing is altered on the element
   */
  $.fn.removeClassByFragmentName = function(classNameFragment) {
    return this.each(function () {
      this.className = (this.className || "")
        .split(" ")
        .where(function(i, c) {
          return c.indexOf(classNameFragment) == -1;
        })
        .join(" ");
    });
  };

/*
  $.metavalue = function (name) {
    name = $.trim(name).toLowerCase();
    var metas = $("head > meta").filter(function () {
      var t = $(this);
      return $.trim(t.attr("name")).toLowerCase() == name || $.trim(t.attr("http-equiv")).toLowerCase() == name;
    });
    if (metas.length === 0) {
      return "";
    }
    if (metas.length == 1) {
      return metas.attr("content");
    }
    return metas.map(function () {
      return $(this).attr("content");
    });
  };
*/

  $.fn.joinall = function () {
    return $(Array.prototype.concat.apply($.makeArray(this), $.map(arguments, function (a) {
      return $.makeArray(a);
    })));
  };

  $.joinall = function () {
    return $(Array.prototype.concat.apply([], $.map(arguments, function (a) {
      return $.makeArray(a);
    })));
  };

  /**
   * Maakt een lightbox-style alert() of confirm() voor korte mededelingen of vragen
   * PHIRO : 20100921 : Rewritten for use with ColorBox lightbox.
   * @param {Object} options Een object met opties.
   * @param {String} options.title De titel van de melding.
   * @param {String} options.text De tekst (mag ook html zijn) van de melding.
   * @param {String} options.buttons De knoppen die onder de melding moeten verschijnen. Als buttons falsy is, dan komen er geen knoppen.
   * @param {String} options.buttons.ok De tekst voor de blauwe ok-knop rechtsonderin de melding. Een falsy waarde verwijdert de knop.
   * @param {String} options.buttons.cancel De tekst voor de neutrale terug-knop linksonderin de melding. Een falsy waarde verwijdert de knop.
   * @param {String} options.callback De callback die wordt aangeroepen nadat de melding gesloten is. De parameter "result" van deze melding kan de waarden "ok", "cancel" of "close" krijgen, die corresponderen met resp. de ok-knop, de cancel-knop, en de sluiten/wegklikken/esc.
   */
  $.displayAlert = function (options) {

    options = $.extend(true, {
      //Default options
      title: "",
      text: "",
      buttons: {
        ok: "Continue"
      },
      height: "131px",
      width: "500px",
      callback: function () {},
      cleanup: function () {}
    }, options);


    var createCallback = function (button) {
      if ($.isFunction(options.callback)) {
        return function () {
          options.callback.call(this, button);
        };
      }
    };
    var container = $("<div class='contentwrapper' />"),
        buttons;
    if (options.title) {
      container.append($("<h2/>", {
        html: options.title,
        className: 'warningmessage'
      }));
    }
    if (options.text) {
      container.append($("<p/>", {
        html: options.text
      }))
    }
    var opts = {};
    if (options.buttons && (options.buttons.ok || options.buttons.cancel)) {
      buttons = $("<div/>", {
        className: "button-container"
      });
      if (options.buttons.cancel) {
        buttons.append(
        $("<a/>", {
          click: createCallback("cancel"),
          className: "button button-previous",
          id: "messageBoxCancelButton"
        }).append($("<span/>", {
          text: options.buttons.cancel
        })));
      }
      if (options.buttons.ok) {
        buttons.append(
        $("<button/>", {
          click: createCallback("ok"),
          className: "button button-engaging button-engaging-nexticon",
          id: "messageBoxOkButton"
        }).append($("<span/>", {
          text: options.buttons.ok
        })));



      }
      container.append(buttons);
      opts = {
        html: container,
        close: "Annuleer",
        transition: "none",
        height: options.height,
        //Offset showing the whole wrapperdiv
        width: options.width,
        scrolling: false,
        onClosed: options.cleanup
      };


    }
    //Since ie seems to squash the height a little, we augment it here a little.
    if ($.browser.msie) {
      if (options.heigth) {
        opts.height = (parseInt(options.heigth) + 75) + "px";
      }
      $(".lightbox-content").css('background-color', 'white');
    }
    $.colorbox(opts, options.callback);

  };

  //PHIRO - END BLOCK ***************************************************************************************************************
  //****************************

  //Load event application,
  $(function () {
    //attributeSelector
    var merkenBlok = $("#merkenblok"); //Block of all checkboxes for branche, needed for filtering
    var kenmerkenBlok = $("#kenmerkenblok"); //Block of all checkboxes for attributes, needed for filtering
    var alleTelefoons = null; //All telephones , whatever filtering is set on the page. source : telefoons*.json
    var alleAbonnementen = null; //All subscriptions, needed for filtering and selection source : abonnementen*.json
    //var sliderReferenceAbonnementen = null; //All subscriptions of 24 months to assess the telephone selection.
    var geselecteerdeData = null; //The filtered set of telephones
    var currentSubscription = null; //Geselecteerde abonnement waar de prijzen op uitgerekend moeten worden.
    var currentSMSSub = null;
    var currentDataSub = null; //Current datasubscription. Set by backend and processed by Javascript onload.
    var currentProductType = $("meta[name='productvorm']").attr('content');; //Will hold belbundel or prepaid for the type of phones to show.

    var currentSliderPos = 0; //Is the current slider pos.
    var currentSorting = "standaard"; //Default will sort in the order of the JSON phones.
    var telephoneBoxesOnPage = 12; //The number of telephones on a page, defaults to 12 .
    var numberOfTelephones = 0; //Number of telephones in total loaded from the json.
    var initialLoadSequence = true; //True when loaded for the first time, else always false.
    // Filter values placeholders
    //var filter_aboPrice = 9999;  //Current value of the budget slider.
    var filter_branch = []; //Selection of selected bracnes in the branches block. (ID's)
    var filter_attr = []; //Selection of selected bracnes in the attributes block. (ID's)
    var phonesPanel = $(".phonespanel:first");

    var isSliderSelectorChangeOrigin = false; //Will be true when the change is made by the slider, will select the prices and subscriptions belonging to the slider value. If false it will show the default subscription value.
    var tekstenPagingLink = {
      toonAlleTelefoons: "Alle resultaten op één pagina",
      toonAantalTelefoons: "Alle resultaten op meerdere pagina's"

    } //Teksten link

    $(".select-smaller-hidden").removeClass("select-smaller-hidden"); //Show the hidden elements by javascript. These components are hidden because they are dependant on javascript to function.

    //Vul de verzameling merken.
    //Initialisation number settings
    merkenBlok
      .add(kenmerkenBlok)
      .find("input").enabled(false).end()
      .find("a").addClass("span-disabled")
      .children("span:last-child").text("(0)");

    //end init settings
    //PHIRO - START BLOCK - This is copied from the default.src.js on portal20, on default.src.js merge, remove this block. *************
    if ($.fn.telfortComparer) {
      $.easing.easeInOutQuad = function (x, t, b, c, d) {
        if ((t /= d / 2) < 1) {
          return c / 2 * t * t + b
        };
        return -c / 2 * ((--t) * (t - 2) - 1) + b;
      };
      $(".button-engaging-comparer").telfortComparer({
        abonids: function (phoneids) {
          return $.map(phoneids, function (phoneid) {
            var phone = geselecteerdeData.phones.find(function (i, p) {
              return p.id == phoneid;
            });
            return phone && phone.abonnement ? phone.abonnement.id || 0 : 0;
          });
        },
        animationeasing: {
          add: "easeInOutQuad",
          remove: "easeInOutQuad",
          compare: "swing"
        },
        deleteCallBack: function (id) {
          $.each(alleTelefoons.phones, function (ix, val) {
            if (val.id == id) {
              val.vergelijkBoxChecked = false;
              return;
            }
          });
        }
      });
    }

    /*
     * Dit object is verantwoordelijk voor het weergeven van de paginering.
     *
     * Methodes:
     *   update()
     *     Alles updaten. Je hoeft niets te berekenen of wat ook. Aanroepen zonder argumenten is voldoende om de paginering weer
     *     overeen te laten komen met de status van de huidige weergave.
     */
    var paging = (function() {

      var container = $(".paging"),
          all = $("> :not(.sortoption)", container),
          prev = $(".button-previous", container),
          next = $(".button-next", container),
          prevpipe = prev.next(),
          nextpipe = next.prev(),
          showall = $(".showall", container),
          filler = $("<span/>", { className: "pagenumber-filler", text: "..." });

      var getpagelist = function() {
        var navoptions = { className: "pagenumber-navigation", href: "#" }, result = { };

        result[1] =            $("<a/>", navoptions).text("1");
        result[this.pageCount] =    $("<a/>", navoptions).text(this.pageCount);
        result[this.currentPage] =     $("<a/>", navoptions).text(this.currentPage);
        result[this.currentPage - 1] = $("<a/>", navoptions).text(this.currentPage - 1);
        result[this.currentPage - 2] = $("<a/>", navoptions).text(this.currentPage - 2);
        result[this.currentPage + 1] = $("<a/>", navoptions).text(this.currentPage + 1);
        result[this.currentPage + 2] = $("<a/>", navoptions).text(this.currentPage + 2);

        if (!result[2]) {
          result[2] = filler.clone(false);
        }
        if (!result[this.pageCount - 1]) {
          result[this.pageCount - 1] = filler.clone(false);
        }
        return result;
      }

      var rebuild = function() {
        //Initieel de hidden class eraf halen, anders blijft ie onzichtbaar
        container.removeClass("paging-hidden");

        //Alles tussen prevpipe en nextpipe wegflikkeren
        prevpipe.nextAll().not(nextpipe.nextAll().andSelf()).remove();

        var pages, i, el;

        //Get the list of to be shown pages only when there is more than one page. If there is one page, do no show at all.
        if (this.pageCount > 1) {
          pages = getpagelist.call(this);

          for (i = 1; i <= this.pageCount; i++) {
            if (pages[i]) {
              pages[i].insertBefore(nextpipe).addClass(i == this.currentPage ? "current" : undef);
            }
          }
        }
      };

      var update = function() {
        if (this.showingAll) {
          $(".pagenumber-navigation, .pagenumber-filler", container).hide();
          all.not(showall).hide();
          showall.text(tekstenPagingLink.toonAantalTelefoons).show();
        }
        else {
          rebuild.call(this);
          showall.text(tekstenPagingLink.toonAlleTelefoons);
          if (this.pageCount <= 1) {
            all.hide();
          }
          else {
            $(".pagenumber-navigation, .pagenumber-filler", container).show();
            prev.add(prevpipe)[this.currentPage > 1 ? "show" : "hide"]();
            next.add(nextpipe)[this.currentPage < this.pageCount ? "show" : "hide"]();
          }
        }
      };

      var result = {
        update: update,
        currentPage: 1,
        pageCount: 0,
        showingAll: false,
        onshowall: function(showall) { },
        onnavigate: function(button, type) { }
      };

      var nextprevEvent = function(type) {
        return function() {
          result.currentPage += type === "next" ? 1 : -1;
          if ($.isFunction(result.onnavigate)) {
            result.onnavigate.call(this, type, result.currentPage);
          }
          $.navi.set("pg", result.currentPage);
          result.update();
          window.scrollTo(0, 0);
          return false;
        };
      };

      $(".pagenumber-navigation", container).live("click", function() {
        result.currentPage = Number($(this).text());
        if ($.isFunction(result.onnavigate)) {
          result.onnavigate.call(this, result.currentPage, result.currentPage);
        }
        $.navi.set("pg", result.currentPage);
        result.update();
        window.scrollTo(0, 0);
        return false;
      });

      showall.click(function() {
        result.showingAll = !result.showingAll;
        if ($.isFunction(result.onshowall)) {
          result.onshowall.call(this, result.showingAll);
        }
        result.currentPage = result.showingAll ? result.currentPage : 1;
        result.update();
        return false;
      });

      next.click(nextprevEvent("next"));
      prev.click(nextprevEvent("prev"));

      result.showingAll = document.location.href.indexOf("alle-telefoons") >= 0;

      return result;

    }());


    /*
     * Dit object is verantwoordelijk voor het sorteren van de telefoon-collecties
     *
     * Methodes:
     *   sort(collection, key)
     *     Sorteert de collectie telefoons en returnt em. De collectie zelf wijzigt ook.
     *     @collection
     *       De collectie telefoons die gesorteerd wordt. Als geen of een ongeldige collectie, dan gebeurt er niets.
     *     @key
     *       De key waarmee gesorteerd wordt: "standaard", "name_asc", "name_desc", "price_asc" of "price_desc".
     *       Als er geen of een ongeldige key wordt meegegeven, dan wordt "standaard" gekozen.
     *   available(key)
     *     Checkt of een sorteringskey bestaat. Geeft ook false als geen of een ongeldige key meegegeven wordt.
     *     @key
     *       De key waarmee gesorteerd wordt.
     */
    var sorter = (function() {

      var sorters = {
        standaard: function(a, b) {
          a = a && a.sortkeys ? a.sortkeys.default_index : null;
          b = b && b.sortkeys ? b.sortkeys.default_index : null;
          return a < b ? -1 : (b < a ? 1 : 0);
        },
        name_asc: function(a, b) {
          a = a && a.sortkeys ? a.sortkeys.naam_index : null;
          b = b && b.sortkeys ? b.sortkeys.naam_index : null;
          return a < b ? -1 : (b < a ? 1 : 0);
        },
        name_desc: function(a, b) {
          a = a && a.sortkeys ? a.sortkeys.naam_index : null;
          b = b && b.sortkeys ? b.sortkeys.naam_index : null;
          return a < b ? 1 : (b < a ? -1 : 0);
        },
        price_asc: function(a, b) {
          a = (a ? (a.abonnement ? a.abonnement.prijseenmalig : a.prijseenmalig) : 0) || 0;
          b = (b ? (b.abonnement ? b.abonnement.prijseenmalig : b.prijseenmalig) : 0) || 0;
          return Math.round(a - b);
        },
        price_desc: function(a, b) {
          a = (a ? (a.abonnement ? a.abonnement.prijseenmalig : a.prijseenmalig) : 0) || 0;
          b = (b ? (b.abonnement ? b.abonnement.prijseenmalig : b.prijseenmalig) : 0) || 0;
          return -Math.round(a - b);
        }
      };

      return {
        sort: function(collection, key) {
          if (collection && $.isArray(collection.phones)) {
            collection.phones.sort(sorters[key] || sorters.standaard);
          }
          return collection;
        },
        available: function(key) {
          return !!sorters[key];
        }
      };

    }());


    /*
     * Dit object is verantwoordelijk voor het weergeven/verbergen van de "bezig met laden" message.
     *
     * Methodes:
     *   show()
     *     Geeft de loading-message weer met een 500ms fade-in en returnt onmiddelijk.
     *   hide()
     *     Verbergt de loading-message met een 500ms fade-out en verwijdert daarna de elementen uit de DOM.
     */
    var processingIcon = (function() {

      var background = $("<div/>", { className: "loading-background", offset: phonesPanel.offset(), width: phonesPanel.width(), height: phonesPanel.height() }).append($("<div/>", { className: "loading-message", text: "Uw toestellen worden geladen" })).hide(),
          shows = 0, callbacks = [];

      var docallbacks = function() {
        while (callbacks.length) {
          callbacks.pop().call(this);
        }
      };

      return {
        show: function(callback) {
          if (!phonesPanel.length) {
            return;
          }

          if ($.isFunction(callback)) {
            callbacks.push(callback);
          }
          if (shows++ <= 0) {
            background
              .appendTo("body")
              .stop()
              .fadeTo(500, 0.9, function() {
                docallbacks.call(this);
              });
          }
        },
        hide: function() {
          if (--shows <= 0) {
            docallbacks.call(background);
            background.fadeTo(500, 0, function() {
              if (shows <= 0) {
                background.detach();
                shows = 0;
              }
            });
          }
        }
      };

    }());


    paging.onnavigate = function(button, page) {
      goToPage(page);
    };
    paging.onshowall = function(showall) {
      showTelephoneBoxesOnPageByNumberShown(showall ? geselecteerdeData.phones.length : telephoneBoxesOnPage);

      //Om te zorgen dat de telefoontjes in de vergelijkknop niet wegschieten
      if ($.msieVersion() > 0 && $.msieVersion() <= 7) {
        $(window).resize();
      }
    };


    //Check for the preset meta tag vor Brand and Attributes
    var merkSelected = $.metavalue("geselecteerdMerk");
    var kenmerkSelected = $.metavalue("geselecteerdKenmerk");


    $("#selectsort").change(function() {
      currentSorting = this.value;

      if (!sorter.available(currentSorting) || currentSorting == "standaard") {
        $.navi.remove("sf", "sa");
      }
      else {
        $.navi.set("sf", currentSorting);
      }

      setPageData(sorter.sort(geselecteerdeData, currentSorting));
      goToPage(paging.currentPage);
    });

    /**
     *  Will attach the lighbox events to the links in the phoneboxes.
     *  On all cases save the initial load, this happens in the associatePhoneBoxToPhone method, on initial load this method is called
     *  from the onslide event of the slider or, on the prepaid page, the initial load.
     *
     */

    function placeLightboxEventsToPhoneBoxLinks() {
      if ($(".phone-image a").length) {
          $(".phone-image a").colorbox({
            width: "768px",
            height: "396px",
            initialWidth: "768px",
            initialHeight: "396px",
            transition: "none",
            scalePhotos: false,
            scrolling: false,
            inline: false
          });
      }
    }

    /**
     * The worker method to create and fill the phoneboxes on the form.
     *
     */

    function showTelephoneBoxesOnPageByNumberShown(numberToShowOnPage) {

      //remove all but the first telephone cell
      $(".clear", phonesPanel).remove();

      //Boxen weghalen als er teveel staan, en toevoegen als er te weinig staan
      var phoneBoxes = $(".phonebox", phonesPanel), phoneBox = phoneBoxes.first(), newBoxes = [];
      if (phoneBoxes.length < numberToShowOnPage) {
        for (var i = 0; i < numberToShowOnPage - phoneBoxes.length; i++) {
          newBoxes.push(phoneBox.clone(false).appendTo(phonesPanel).get(0));
        }
        phoneBoxes = phoneBoxes.add(newBoxes);
      }
      else if (phoneBoxes.length > numberToShowOnPage) {
        phoneBoxes = phoneBoxes.eq(numberToShowOnPage - 1)
          .nextAll().remove()         //Alles wat na het maximum aantal boxen komt, verwijderen,
          .end().prevAll().andSelf(); //En de rest in phoneBoxes bewaren voor verdere verwerking
      }

      phoneBoxes.each(function(i, box) {
        var j = i + 1;
        $(box)[(j % 3) === 0 ? "addClass" : "removeClass"]("phonebox-last")
          .find(".checkbox-compare")
            .find("input").attr("id", "compare-" + j).end()
            .find("label").attr("for", "compare-" + j);
      });

      //$("<div/>", { className: "clear" }).appendTo(phonesPanel);

      //Now parse and fill all telephones into the phoneboxes;
      processPhones(geselecteerdeData, 0);
    }

    /**
     * Enumerate the phones starting with position startIX getting the data drom the
     * data param.
     * @param data NOT NULL - Phone collection
     * @param startIX NOT NULL - Positive number, not zero.
     */

    function processPhones(data, startIX) {

      var counter = startIX;

      $(".phonebox").each(function (ix) {
        var phonesOnPage = paging.showingAll ? $(geselecteerdeData.phones).length : numberOfTelephones;
        if (ix < phonesOnPage) {
          if (counter >= phonesOnPage) {
            $(this).css("display", "none");
            return;
          }
          else {
            $(this).css("display", "block").show();
          }
          if (typeof data.phones[counter] == 'undefined') {
            $(this).css("display", "none");
          }
          else {
            associatePhoneBoxToPhone($(this), data.phones[counter]);
            counter++;
          }
        } else {
          $(this).css("display", "none");
        }
      });
      placeLightboxEventsToPhoneBoxLinks();
    }

    /**
     * Initiates the page change with alle the phone reloading from the selected collection
     * of phones.
     */

    function goToPage(pageNo) {

      var startCell = (pageNo - 1) * telephoneBoxesOnPage;
      //alert('goToPage');
      processPhones(geselecteerdeData, startCell);
    }

    /**
     * Will parse the data file for 'telephoneBoxesOnPage' new phones to be placed on the page.
     */

    function setPagination(data) {
      //How many phones are there. We need this to establish how the phones are shown
      numberOfTelephones = $(data.phones).length;

      $("#toestelnum").text("(" + numberOfTelephones + ")");
      //How many full  pages can we make with the number of phones. We round up because we need to
      //show the remainder in its own page.

      paging.pageCount = Math.ceil(numberOfTelephones / telephoneBoxesOnPage);

      //Now set the pagination links.
      paging.update();
    }




    /**
     * Place the data from one phone object in the phonebox div
     * @param phoneBoxDIVElement NOT NULL - target element where the data needs to go.
     * @param dataSinglePhone NOT NULL - JSON data object containing one phone object.
     */

    function associatePhoneBoxToPhone(phoneBoxDIVElement, dataSinglePhone) {

      //var i,abo,subscriptionToSet;

      var phoneID = $("input[name=phoneid]", phoneBoxDIVElement).val();
      var checked = $("input[name^=compare]", phoneBoxDIVElement).checked();
      $.each(geselecteerdeData.phones, function (ix, val) {
        if (phoneID && val.artikel.id == phoneID) {
          val.vergelijkBoxChecked = checked;
          return;
        }
      });

      var phoneInfo = $(".phone-info", phoneBoxDIVElement);
      var actionType, checkbox;
      var actionNum = 0;

      checkbox = $("input[type=checkbox]", phoneBoxDIVElement);
      if (dataSinglePhone.vergelijkBoxChecked) {

        if (checkbox) {
          $(checkbox).checked(true);
        }
      } else {
        dataSinglePhone.vergelijkBoxChecked = false;
        if (checkbox) {
          $(checkbox).checked(false);
        }
      }


      if (dataSinglePhone.artikel.icon) {
        actionType = dataSinglePhone.artikel.icon;

        if (actionType) {
          $(".property-small", phoneBoxDIVElement).removeClassByFragmentName("property-small-").addClass("property-small-" + actionType);
        } else {
          $(".property-small", phoneBoxDIVElement).removeClassByFragmentName("property-small-").addClass("property-small-hidden");
        }
        $(".property-small", phoneBoxDIVElement).show();
      } else {
        $(".property-small", phoneBoxDIVElement).removeClassByFragmentName("property-small-").addClass("property-small-hidden");
      }
      $(".phonetype a", phoneInfo).html(dataSinglePhone.artikel.merk + "<br/> " + dataSinglePhone.artikel.type);
      //Set the values for a previous set subscription


      if (!dataSinglePhone.abonnement) {
        dataSinglePhone.abonnement = dataSinglePhone.abonnementen ? dataSinglePhone.abonnementen.find(function(i, a) { return a.id == currentSubscription; }) : null;
      }
      if (!dataSinglePhone.abonnement) {
        dataSinglePhone.abonnement = dataSinglePhone.abonnementen ? dataSinglePhone.abonnementen.find(function(i, a) { return a.id == dataSinglePhone.artikel.default_abon; }) : null;
      }

      var promoLine_1, promoLine_2, nonPromoPrice;
      var promoAbo = !dataSinglePhone.abonnement ? (dataSinglePhone.abonnementen ? dataSinglePhone.abonnementen[0] : null) : dataSinglePhone.abonnement;

      if (currentSubscription) {
        promoLine_1 = "";
        promoLine_2 = "";
      }
      else {
        promoLine_1 = promoAbo ? promoAbo.promotekst_1 : "";
        promoLine_2 = promoAbo ? promoAbo.promotekst_2 : "";
        nonPromoPrice = promoAbo ? promoAbo.prijspermaand : "";
      }
      if (currentProductType == "prepaid") {
        promoLine_1 = "";
        promoLine_2 = "";
      }
      if (!promoLine_1 && !promoLine_2 && nonPromoPrice) {
        promoLine_2 = "Prijs € " + formatCurrency(nonPromoPrice) + " p/m";
      }
      $(".subscription", phoneInfo).html((promoLine_1 || "") + "<br/>" + (promoLine_2 || "") + "<input class='hiddenID' type='hidden' name='phoneid' value='" + dataSinglePhone.artikel.id + "'/>");




      //TODO Bassies are now pointing to the old site picktures. these need to be changed in the JSON once the correct bassies are delivered.
      $(".phone-image img", phoneBoxDIVElement)
        .attr({
          src: dataSinglePhone.urls.thumbnail,
          alt: dataSinglePhone.artikel.merk + " " + dataSinglePhone.artikel.type,
          title: dataSinglePhone.artikel.merk + " " + dataSinglePhone.artikel.type
        })
        .css("cursor", "pointer")
        .unbind("click")
        .bind("click", (function(url) { return function() { document.location.href = url; }; }(dataSinglePhone.urls.info)));
		
      $(".phone-info > h2", phoneBoxDIVElement).html("<a href='" + dataSinglePhone.urls.info + "' class='phone-detail-title'>" + dataSinglePhone.artikel.naam + "</a>");

      var priceSection = $(".phone-info > .price", phoneBoxDIVElement),
          levensCyclus = dataSinglePhone.artikel.levenscyclus,
          bookable = levensCyclus == "reserveerbaar",
          expected = levensCyclus == "verwacht",
          button = $("a:last", phoneBoxDIVElement),
          sliderstate = $.fn.slider ? $("#slider").slider("command").state() : null,
          urlabonid;

      button.remove();

      if (bookable || expected) {
          var o = $("<a class=\"button button-engaging button-engaging-nexticon button-engaging-secondary\"><span></span></a>")
            .attr("href", dataSinglePhone.urls[bookable ? "info" : "clang_url"])
            .children().text(bookable ? "Reserveer" : "Schrijf in").end();
		  if(expected){
			o.attr("rel", "lightbox normal iframe");
		  }
        phoneBoxDIVElement.append(o);
		$("a[rel='lightbox normal iframe']",phoneBoxDIVElement).telfortLightbox();
      }
      else {
        // if (geen budget-filtering) geen abonid in url stoppen!
        if (dataSinglePhone.abonnement) {
            urlabonid = !sliderstate || sliderstate.max == sliderstate.position ? "" : "?abonid=" + dataSinglePhone.abonnement.id;
            phoneBoxDIVElement.append("<a class='button button-engaging button-engaging-nexticon ' title='" + dataSinglePhone.artikel.merk + " " + dataSinglePhone.artikel.type + " bestellen' href='" + dataSinglePhone.urls.info + urlabonid + "'><span>Meer info</span></a>");
        }
        else {
            phoneBoxDIVElement.append("<a class='button button-engaging button-engaging-nexticon ' title='" + dataSinglePhone.artikel.merk + " " + dataSinglePhone.artikel.type + " bestellen' href='" + dataSinglePhone.urls.info + "'><span>Meer info</span></a>");
        }
      }
      //for IE, redraw the specialized button renderer so it looks like the CCS3 version. Since we recreated the element, we need to rerender.
      /*if (Modernizr) {
        button = $("a:last", phoneBoxDIVElement).modernBox({
          applyPngFix: false
        });
      }*/

      //Reset the price values. We recreate them later.

      $(priceSection).empty();
      if (dataSinglePhone.prijseenmalig !== null) {


        // Abonnement starting price
        var totaalPrijs = 0, korting = 0;
        $.each([dataSinglePhone.abonnement, dataSinglePhone.artikel, dataSinglePhone], function(i, obj) {
          if (obj && obj.prijseenmalig) {
            totaalPrijs = +obj.prijseenmalig;
            return false;
          }
        });

        // Deduct kortingen if any
        if(dataSinglePhone.abonnement && $.isPlainObject(dataSinglePhone.abonnement.bundel_kortingen)) {
          var dataLookup = currentDataSub;
          var smsLookup = currentSMSSub;

          if(!currentSubscription) {
            if(!dataLookup) dataLookup = dataSinglePhone.abonnement.default_data;
          }

          if(dataSinglePhone.abonnement.bundel_kortingen[dataLookup]) {
            totaalPrijs -= Number(dataSinglePhone.abonnement.bundel_kortingen[dataLookup]) || 0;
          }

          if(dataSinglePhone.abonnement.bundel_kortingen[smsLookup]) {
            totaalPrijs -= Number(dataSinglePhone.abonnement.bundel_kortingen[smsLookup]) || 0;
          }
        }


        if (totaalPrijs < 0) {
          totaalPrijs = 0;
        }

        var price = String(Math.round(totaalPrijs * 100) / 100); //Convert to string
        var decimaleScheider = price.indexOf(".");

        if (totaalPrijs === 0) {
          priceSection.append($("<span/>", {
            className: "euro",
            text: "Gratis"
          }));
        }
        else {
          if (decimaleScheider != -1) {
            priceSection
              .append($("<span/>", { className: "euro", text: price.substr(0, decimaleScheider) + "," }))
              .append($("<span/>", { className: "eurocent", text: price.substr(decimaleScheider + 1, 2) }));
          }
          else {
            priceSection
              .append($("<span/>", { className: "euro", text: price + "," }))
              .append($("<span/>", { className: "eurocent", text: "00" }));
          }
        }
      }
      else {
        priceSection.append("<span class='price-text'></span>");
      }

      $(".phone-image a", phoneBoxDIVElement).attr('href', dataSinglePhone.urls.detail.replace(' ', '-')); //Since the urls is build from several fields, there may be spaces. these are replaced by hyphens

      //Rest van de links implementeren als de resources er ook staan.
    }


    var replaceForSearch = function (valueToReplace) {
      return $.trim(valueToReplace).replace(/\s+/g, "-").toLowerCase();
    };


    /**
     *  Count the number of phones by brand (merk) and attributes (Kenmerken)
     *  @param doNotWriteToElement - if true, it will not attempt to write the values to the elements but returns the
     *                               collections in a return array. This is for unittest purposes.
     *  @param alternativeDataset  - If not null, this set is used for processing phones, else the namespace
     *                               global variable geselecteerdeData will be used. This is for unittest purposes
     */

    var setMerkAndKenmerkenCounters = (function() {

      var selectors = {
        branches: ".filterSelector.branchSelector",
        attributes: ".filterSelector.attrSelector",
        $load: function() {
          if (this.$loaded) { return; }
          for (var selector in this) {
            if (typeof this[selector] == "string") {
              this[selector] = $(selectors[selector]);
            }
          }
          this.$loaded = true;
        }
      };

      var fillSelectors = function(selector, properties) {
        selectors.$load();
        selectors[selector].each(function() {
          var count = +properties[this.id] || 0;
          $(this).parent().parent()
            .find("label > a")[count ? "removeClass" : "addClass"]("span-disabled").end()
            .find("label > a > span:last-child").text("(" + count + ")").end()
            .find("input").enabled(count);
        });
      };

      return function(doNotWriteToElement, alternativeDataset) {
        var dataSet = alternativeDataset || geselecteerdeData,
            i, j, phone, merk, kenmerkenPhone, kenmerkArray, canAddToCount, kenmerk,
            kenmerkenToSearchFor = filter_attr,
            merken = [], kenmerken = [];

        alleTelefoons.phones.each(function(i, phone) {
          var merk = replaceForSearch(phone.artikel.merkcat);
          if (merk) {
            if (kenmerkenToSearchFor.length) {
              if (phone.artikel.specs.Functies) {
                var kenmerkenPhone = phone.artikel.specs.Functies.toLowerCase();
                if (kenmerkenToSearchFor.find(function(i, k) { return kenmerkenPhone.indexOf(k) == -1; })) {
                  return;
                }
              }
              else {
                return;
              }
            }
            merken[merk] = (+merken[merk] || 0) + 1;
          }
        });

        dataSet.phones.each(function(i, phone) {
          var ken = phone.artikel.specs.Functies;
          if (ken) {
            ken.split(",").each(function(i, k) {
              kenmerken[k = replaceForSearch(k)] = (+kenmerken[k] || 0) + 1;
            });
          }
        });

        if (!kenmerken["verwacht"]) {
          kenmerken["verwacht"] = 0;
        }

        if (doNotWriteToElement) {
          return;
        }

        //Set the numbers, is candidate for backend automating. Write to elements or return the values.
        fillSelectors("branches", merken);
        fillSelectors("attributes", kenmerken);
      };
    }());


    /**
     * Is used for the slider selection algorithm. (C33 of FRS 1.4)
     * Loads all subscriptions
     */

    //Msaly: deze lijkt niet meer gebruikt te worden, vandaar de twee underscores ervoor gezet.
    function __setSetAbonnement() {

      //Step one : Always take the 24 month subscriptions as base, these are ordered by price
      var abbos24 = alleAbonnementen.abonnementen.belbundel['24']['bundels'];
      //Step two : Establish highest price on the abonnement
      var counter = 0;

      var highestPriceObject;
      var highestPrice = 0;
      var lowestPrice = abbos24[0].prijspermaand;

      //Find the most and least expensive subscription
      for (counter; counter < abbos24.length; ++counter) {
        if (highestPrice < abbos24[counter].prijspermaand) {
          highestPrice = abbos24[counter].prijspermaand;
          highestPriceObject = abbos24[counter];
        }
        if (lowestPrice > abbos24[counter].prijspermaand) {
          lowestPrice = abbos24[counter].prijspermaand;
        }


      }
      // take the most expensive sms subscription
      counter = 0;
      var smss = highestPriceObject['sms'];
      var higestSMSPrice = 0;
      for (counter = 0; counter < smss.length; ++counter) {
        if (higestSMSPrice < smss[counter].prijspermaand) {
          higestSMSPrice = smss[counter].prijspermaand;
        }
      }
      // take the most expensive data subscription
      counter = 0;
      var higestDataPrice = 0;
      var datas = highestPriceObject['data'];
      for (counter; counter < datas.length; ++counter) {
        if (higestDataPrice < datas[counter].prijspermaand) {
          higestDataPrice = datas[counter].prijspermaand;
        }

      }
      //Find the most expesive set of abonnements
      var higestPriceTotal = highestPrice + higestSMSPrice + higestDataPrice;

      higestPriceTotal = (Math.round((higestPriceTotal - 2.5) / 5) + 1) * 5;
      lowestPrice = (Math.round((lowestPrice + 2.5) / 5) - 1) * 5;
      if (lowestPrice < 0) {
        lowestPrice = 0;
      }
      //Set the return value
      var retVal = {
        highRate: higestPriceTotal,
        lowRate: lowestPrice
      };

      //Step 3Now sort all the abonnements into a list sorted by price to be used with the slider.
      //
      //Three substeps
      // 3.1 List of subscriptions ordered by price.

      var newEntry;
      var subscriptionsByPrice = [];
      for (counter = 0; counter < abbos24.length; ++counter) {
        newEntry = {
          id: abbos24[counter].id,
          name: abbos24[counter].naam,
          priceSubscription: abbos24[counter].prijspermaand,
          priceTotal: abbos24[counter].prijspermaand
        };
        subscriptionsByPrice[subscriptionsByPrice.length] = newEntry;

      }
      //sliderReferenceAbonnementen = subscriptionsByPrice;

      return retVal;

    }





    /**
     * !! Entry point page change.
     * @param dataPhone (Object)  NOT NULL collection of phone objects to be processed and paginated.
     */

    function setPageData(dataPhone) {
      geselecteerdeData = dataPhone;
      var messageTitle, messageText;

      var numberOfPhones = $(dataPhone.phones).length
      if (numberOfPhones == 0 || messageText) {

        if (kenmerkSelected || merkSelected) {

          messageTitle = "Geen resultaten";
          if (kenmerkSelected) {
            if (!messageText) {
              messageText = "Er zijn geen telefoons met kenmerk " + kenmerkSelected + " gevonden";
            }

          } else if (merkSelected) {
            if (!messageText) {
              messageText = "Er zijn geen telefoons gevonden van het merk " + merkSelected;
            }


          }

        } else {
          messageTitle = "Geen resultaten";
          if (!messageText) {
            messageText = "Deze selectie levert geen telefoons op, maak een andere selectie.";
          }
        }
        $(".waitForLoading").remove(); //Remove the wait for loader lightbox immediately, else the two lightboxes interfere with eachother.
        $.displayAlert({
          //Default options
          title: messageTitle,
          text: messageText,
          buttons: {
            ok: "Ga verder"
          },
          callback: function (result) {
            if (result == 'ok') {
              $.colorbox.close();
              processingIcon.show(function() {
                geselecteerdeData = alleTelefoons; //Reset all selections and start with all phones.
                $("span:contains('Merken')").parent().find("input[type='checkbox']").checked(false);
                $("span:contains('Kenmerken')").parent().find("input[type='checkbox']").checked(false);
                try {
                  $("#slider").slider("command").setposition(95);
                }
                catch (e) { }

                $.refilterSelection(100, 'aboPrijs');
                $("#slider_counter").text(" Max");
                processingIcon.hide();
              });
            }
          }
        });




      }
      else {
        //If there is a parametered brand or attribute set, set the breadcrumb as well.
        if (kenmerkSelected && merkSelected) {
          addToBreadCrumb(kenmerkSelected, merkSelected);
        }
        else if (kenmerkSelected) {
          addToBreadCrumb(kenmerkSelected);
        }
        else if (merkSelected) {
          addToBreadCrumb(merkSelected);
        }
        else {
          addToBreadCrumb();
        }

        setMerkAndKenmerkenCounters();
        setPagination(dataPhone);

        processPhones(dataPhone, 0);
      }
      if (numberOfPhones > telephoneBoxesOnPage) {
        $("a.showall").show();
      } else {
        $("a.showall").hide();
      }
      //Remove the initial merken en kenmerken settings, we will not need them anymore.
      kenmerkSelected = "";
      merkSelected = "";

      paging.update();

    }

    /**
     * Filter step 2,3,4
     * Worker method. Will filter the phones on branche and attributes. Will use the price selected collection of phones to
     * filter.
     * @param newCollection     NOT NULL collection of phones filtered on price (slider)
     * @param testMerken        NOT NULL Merken to filter
     * @param testKenmerken     NOT NULL Kenmerken to filter
     */
    $.filterOnBAndA = function (newCollection, testMerken, testKenmerken) {


      var i, j, k, phone, canBeAddedToCollection, isMerkAanwezig, zijnAlleKenmerkenAanwezig, merk, kenmerk;

      var kenmerken = testKenmerken;
      var merken = testMerken;;
      var filteredCollection = {
        phones: []
      };

      // X AND Y are empty : Do nothing
      if ($(merken).length == 0 && $(kenmerken).length == 0) {
        filteredCollection = newCollection;
      }
      //New we are left with X and/or Y not empty. We start the count of the shown objects as well
      isMerkAanwezig = true;
      for (i = 0; i < $(newCollection.phones).length; ++i) {
        phone = newCollection.phones[i];
        canBeAddedToCollection = true; //Assume that you can add the phone to the collection, till proven wrong.
        if ($(merken).length != 0) {
          isMerkAanwezig = false;
          for (j = 0; j < $(merken).length; ++j) {
            merk = phone.artikel.merkcat.toLowerCase().replace('-', ' ');
            if (merk.indexOf(merken[j].toLowerCase().replace('-', ' ')) != -1) {
              isMerkAanwezig = true;
              break;
            }
          }
          canBeAddedToCollection = isMerkAanwezig;
        }
        zijnAlleKenmerkenAanwezig = true;

        if ($(kenmerken).length != 0 && canBeAddedToCollection) {
          kenmerk = phone.artikel.specs.Functies;
          if (kenmerk) {
            kenmerk = kenmerk.toLowerCase().replace('-', ' ');

            for (k = 0; k < $(kenmerken).length; ++k) {

              kenmerken[k] = kenmerken[k].toLowerCase().replace('-', ' ');
              //alert('kenmerk ' + kenmerk + "\nkenmerken[i] " +  kenmerken[k]);
              if (kenmerk.indexOf(kenmerken[k]) == -1) {
                zijnAlleKenmerkenAanwezig = false;
                break;
              }
            }
          } else {
            //If there are no kenmerken, then there is no match.
            zijnAlleKenmerkenAanwezig = false;
          }

        }

        canBeAddedToCollection = canBeAddedToCollection && zijnAlleKenmerkenAanwezig;
        if (canBeAddedToCollection) {
          filteredCollection.phones.push(phone);

        }
      }
      geselecteerdeData = filteredCollection;
      return filteredCollection;
    }



    $.filterOnCheckboxSelections = function (newCollection) {
      //Fill collection X

      filter_branch = $.makeArray($(".filterSelector.branchSelector").map(function () {
        return this.checked ? this.value : null;
      }));

      //Fill collection Y
      filter_attr = $.makeArray($(".filterSelector:not(.branchSelector)").map(function () {
        return this.checked ? this.value : null;
      }));

      var filterSettings = {
        merken: filter_branch,
        kenmerken: filter_attr
      };

      var bracheAndAttributeFiltering = ($(filter_branch).length !== 0) || ($(filter_attr).length !== 0); //X AND Y are empty
      //Filter step 2,3,4
      return $.filterAlgoritm_stepTwoTillFour(bracheAndAttributeFiltering, newCollection, filterSettings);

    }




/* Filter Step 1,2,3,4
         * Filters the telephones on price per month and the selected branche and attributes checkboxes
         * When none of the checkboxes are selected, there is no filtering on branches and attributes.
         * Filter algorithm:
         * Consider : All filter_branch as collection X , all filter_attr as collection Y
         *      For each element from X one instance need to be present to be selected in the collection.
         *      For each element from Y all instances need to be present to be selected in the collection.
         *      When X is empty AND Y is empty then ALL elements are included in the selection.
         * @param val - NOT NULL Positive number, price per month as cutoff point
         * @param origin - Which price has been altered? Default is abo price.
         * @param doNotDoScreenActions - When true the screen actions are not executed
         * @param bypass - When true the slider setting will be bypassed
         */
    $.refilterSelection = function (val, origin, doNotDoScreenActions, bypass) {
      var newCollection = { phones: [] };

      //Filter on the slider values first
      if (val || bypass) {

        // Filter step 1;
        newCollection = $.filterAlgoritm_stepOne(newCollection);
      } else {

        newCollection = alleTelefoons;
      }

      if (currentDataSub) {
        newCollection.phones = $.map(newCollection.phones, function(phone) {
          if (!phone.abonnement && phone.abonnementen && currentSubscription) {
            phone.abonnement = $.grep(phone.abonnementen, function(abo) { return abo.id == currentSubscription; })[0];
          }
          if (phone.abonnement && phone.abonnement.bundel_kortingen && !(currentDataSub in phone.abonnement.bundel_kortingen)) {
            return null;
          }
          return phone;
        });
      }

      newCollection = $.filterOnCheckboxSelections(newCollection);

      sorter.sort(newCollection, currentSorting);
      if (!doNotDoScreenActions) {
        setPageData(newCollection);
        processingIcon.hide();
      }
	  
	  var currentPage = $.navi.get("pg") || 1;
	  if(currentPage > paging.pageCount){currentPage = 1;}
	  $.navi.set("pg", currentPage);
	  goToPage(currentPage);
	  console.log(paging.pageCount);
	  paging.update();
    }

    /**
     *  Screen independant algorithm for filtering for branche and attributes
     *  @param bracheAndAttributeFiltering if true, it will filter on X and Y, else it will skip this and return the collection.
     *  @param newCollection NOT NULL Valid phone collection
     *  @param filterSettings NOT NULL, Object with the filtered settings
     *  @return filtered collection
     */
    $.filterAlgoritm_stepTwoTillFour = function (bracheAndAttributeFiltering, newCollection, filterSettings) {

      if (bracheAndAttributeFiltering) {
        newCollection = $.filterOnBAndA(newCollection, filterSettings.merken, filterSettings.kenmerken);
      }
      return newCollection;
    }


    /**
     *  Screen independant algorithm for filtering for branche and attributes
     *  Will use the subscription collection to filter the correct phones.
     *  Will assume the subscriptions are ordered from expensive to cheap.
     *  @param newCollection The collection where the filtered phones are added to when they qualify for the parameters.
     *  @return filtered collection
     */
    $.filterAlgoritm_stepOne = function (newCollection) {

      var phone, abo, aboName, phoneCounter, k, j, sliderPos, sac, sac_addon, aboObj, aboAddOnObj, aboSelectedObj;
      phoneCounter = 0;

      sliderPos = parseInt(currentSliderPos, 10);

      var alleTelefoonsCount = alleTelefoons.phones.length;
      if (alleTelefoons && alleTelefoons.phones && alleTelefoons.phones[0]) {
        if (alleTelefoons.phones[0].abonnementen) {
          for (j = 0; j < alleTelefoonsCount; ++j) {

            phone = alleTelefoons.phones[j];

            //Search the subscription on the phone : If prepaid, abonnementen does not exist as an object.
            sac = 0;
            sac_addon = 0;
            for (k = 0; k < phone.abonnementen.length; ++k) {
              abo = phone.abonnementen[k];
              if (sac == 0 && abo.slider_afgerond <= sliderPos) {
                sac = abo.slider_sac;
                aboObj = abo;
              }
              if (sac_addon == 0 && abo.slider_afgerond_addon <= sliderPos) {
                sac_addon = abo.slider_sac_addon;
                aboAddOnObj = abo;
              }

            }

            if (aboObj && aboAddOnObj) {
              if (aboObj.slider_sac < aboAddOnObj.slider_sac_addon) {
                aboSelectedObj = aboObj;
              } else {
                aboSelectedObj = aboAddOnObj;
              }

            } else {
              if (aboObj) {
                aboSelectedObj = aboObj;
              }
              if (aboAddOnObj) {
                aboSelectedObj = aboAddOnObj;
              }
            }

            if (aboSelectedObj) {
              phone.prijseenmalig = aboSelectedObj.prijseenmalig;
              //Added two virtual fields with the text for the promo texts.
              if (!aboSelectedObj.promotekst_1) {
                aboSelectedObj.promotekst_1 = "Prijs " + aboSelectedObj.prijspermaand + " p/m";
              }
              if (!aboSelectedObj.promotekst_2) {
                aboSelectedObj.promotekst_2 = "";
              }
              //Create virtual subscription to load the current selected subscription.
              phone.abonnement = $.extend({ }, aboSelectedObj); //Create a copy

              //For price processing
              newCollection.phones[phoneCounter++] = phone;
            }



          }

        } else {

          newCollection = alleTelefoons
        }
      }

      return newCollection;
    }

    function filtertOptionsMerken(selectedElement) {


      filter_branch = $(".filterSelector.branchSelector").map(function () {
        return this.checked ? this.value : null;
      });
      filter_attr = $(".filterSelector.attrSelector").map(function () {
        return this.checked ? this.value : null;
      });
      $.refilterSelection(null, 'checkboxes');
      $.navi.replace({
        mk: $.makeArray(filter_branch),
        at: $.makeArray(filter_attr)
      });
    }

    //Make the checkboxes findable for the filter function filtertOptionsMerken()
    $("fieldset.section-small div div span input").addClass("filterSelector");
    $("a.branchSelector, a.attrSelector").unbind("click").bind('click', function (event) {
      if ($(this).hasClass("span-disabled") || $(this).find("span").hasClass("span-disabled")) {
        return false;
      } //When the span is disabled, do not fire the event. We avoid a lot of function bind swapping by simply intercepting the filtering process.
      var input = $(this).parent().parent().find(".checkbox-wrapper > input").get(0);
      if (!input) {
        return false;
      }
      input.checked = !input.checked;
      $(input).triggerHandler("click");
      return false; //Block the href command.
    });


    /**
     * Adds a string to the breadcrumb and the title. Will return the first character as aan uppercase letter, the rest as lowecase.
     * @param valueToAdd    String to add to the title and the breadcrumb
     */

    function addToBreadCrumb(part1, part2, url) {

     //Short phonenames in uppercase, the rest in lower.
      var part1fixed = captalizeWords(part1); //All words in uppercase

      //No array for the strings (line part1[0]) since this will throw an error in IE6
      if (part2) {
        part2 = captalizeWords(part2); //The words are in lower case. But the first char in uppercase.
      }

      //Alles wat na "Telefoons" komt, wegflikkeren
      var path = $("#clickpath > a[href$=telefoons/]").nextAll().remove().end();

      if (part1) {
        if (!url) {
          url = $(document.getElementById(part1)).parents(".checkbox-field:first").find("label > a").attr("href");
        }
        path
          .after($("<a/>", { href: url, text: part1fixed }))
          .after($("<span/>", { text: " \\ " }));
      }

      if (part2) {
        part1fixed = part2 + " " + part1fixed;
      }

      var subscriptionText = "met abonnement";
      if (currentProductType == "prepaid") {
        subscriptionText = "met prepaid"
      }
      $("#content > h1").text(document.title = (part1fixed ? part1fixed + " telefoons " : "Telefoons ") + subscriptionText);

    }

    /**
     *  Replaces dashes by spaces and the divides the string into words with space as separator.
     *  The it capitalizes the first letter.
     *  If a word is shorter than three letters, it's all capitals.
     *  @param valueToAdd NOT NULL String
     *  @returns processed string as described before. If there are no dashes it is seen as one word and returned with the first letter capitalized
     */

    function captalizeWords(valueToAdd) {
      return String(valueToAdd || "").replace(/[^\s-]+/g, function($0) {
        if ($0.length <= 3) {
          return $0.toUpperCase();
        }
        return $0.substr(0, 1).toUpperCase() + $0.substr(1);
      });
    }


    /**
     * Helper function for formatting currency string.
     * TODO : Move to default.src
     */

    function formatCurrency(num) {
      num = num.toString().replace(/\$|\,/g, '');
      if (isNaN(num)) num = "0";
      var sign = (num == (num = Math.abs(num)));
      num = Math.floor(num * 100 + 0.50000000001);
      var cents = num % 100;
      num = Math.floor(num / 100).toString();
      if (cents < 10) cents = "0" + cents;
      for (var i = 0; i < Math.floor((num.length - (1 + i)) / 3); i++)
      num = num.substring(0, num.length - (4 * i + 3)) + ',' + num.substring(num.length - (4 * i + 3));
      return (((sign) ? '' : '-') + num + ',' + cents);
    }


    var brandClickProcessor = function() {
      var mapper = function() {
        return {
          value: replaceForSearch(this.value),
          url: $(this).parents(".checkbox-field:first").find("label > a").attr("href")
        };
      };

      processingIcon.show(function() {

        filtertOptionsMerken($(this));

        var selectedKenmerken = $.makeArray($("input.attrSelector:checked").map(mapper));
        var selectedMerken = $.makeArray($("input.branchSelector:checked").map(mapper));

        if (selectedKenmerken.length == 1 && selectedMerken.length == 0) {

          //Één kenmerk en geen merken
          addToBreadCrumb(selectedKenmerken[0].value, null, selectedKenmerken[0].url);
        }
        else if (selectedKenmerken.length == 0 && selectedMerken.length == 1) {

          //Geen kenmerken en één merk
          addToBreadCrumb(selectedMerken[0].value, null, selectedMerken[0].url);
        }
        else if (selectedKenmerken.length == 1 && selectedMerken.length == 1) {

          //Één kenmerk en één merk
          addToBreadCrumb(selectedKenmerken[0].value, selectedMerken[0].value, selectedKenmerken[0].url);
        }
        else if (selectedKenmerken.length > 1 && selectedMerken.length == 1) {

          //Meerdere kenmerken en één merk
          addToBreadCrumb(selectedMerken[0].value, null, selectedMerken[0].url);
        }
        else if (selectedKenmerken.length == 1 && selectedMerken.length > 1) {

          //Één kenmerk en meerdere merken
          addToBreadCrumb(selectedKenmerken[0].value, null, selectedKenmerken[0].url);
        }
        else {

          //Meerdere kenmerken en meerdere merken, of geen kenmerken en geen merken
          addToBreadCrumb();
        }

      });

    }
    merkenBlok.find("input[type='checkbox']").bind('click', brandClickProcessor);
    kenmerkenBlok.find("input[type='checkbox']").bind('click', brandClickProcessor);

    /**
     *  HERE STARTS CHECKOUT PAGES SPECIFIC CODE
     *   Check is set for the checkout pages, this one needs to be set when this id is present.
     *   Since the default for all pages using this lib is to reset all checkboxes to false, this one is added
     *   for overriding the default.
     */
    $("#nummervermelding").checked(true);
    $("#telefonisch_bestellen").unbind("click").bind("click", function () {
      window.open('http://62.58.200.196/callme_telfort/callbackform.asp', 'chat', 'width=626,height=565,left=100,top=100,scrollbars=no,resizable=no');
    });

    /** END CHECKOUT SPECIFIC CODE */

    /**
     * We set up the slide here. It overwrites the dropdown option. So we hide the dropdown then we show the
     * the slider. Since the plugin is used on more than one page, the select dropdown box needs to exist for the
     * slider to be created and placed.
     * If there is a slider , this is either a pre or a beldbundel page.
     * HERE STARTS TOESTELOVERZICHT SPECIFIC CODE
     */

    //if ($("#select").length > 0 || currentProductType == "prepaid") {
    $(".lightbox-button-close,.lightbox-close").live('click', function () {
      $.colorbox.close();
    });

    //Reset the checkboxes

    $("fieldset.section-small div div span input").checked(false);

    $("<div id='sliderToestel' class='slider'></div>").insertAfter("#toestelPrijsLabel");
    $("<div id='slider' class='slider'></div>").insertAfter("#select");

    $("#select").remove();
    currentSubscription = $("meta[name='geselecteerdAbonnement']").attr('content');
    isSliderSelectorChangeOrigin = !(currentSubscription);
    currentSMSSub = $("meta[name='geselecteerdSMS']").attr('content');
    currentDataSub = $("meta[name='geselecteerdData']").attr('content');

    $("<div id='slider_counter'>max</div>").insertAfter("#slider");
    $("<div id='sliderToestel_counter'>&euro; 50</div>").insertAfter("#sliderToestel");
    //retrieve the JSON file containing all the telephones. During the session we store these values
    //globally. Select the first page after loading.
    //There is the selection to let the page show subscriptions or prepaid.
    var telefoonJSONPath;
    var sideBar = $("#sidebar").find("div p a ");
    if (currentProductType == "prepaid") {

      telefoonJSONPath = $("meta[name='jsonPhones']").attr('content');
      $("#slider").hide();
      $("#slider_counter").hide();
      //$(sideBar).text("telefoons met abonnementen").attr('href', '/telefoons/');
      //$(".content-wrapper-subscription").remove();
      $(".section-small .select-smaller > label").hide();
      document.title = "Telefoons met prepaid";

    } else if (currentProductType == "postpaid" || currentProductType == "belbundel") {

      telefoonJSONPath = $("meta[name='jsonPhones']").attr('content');
      $("#slider").show();
      $("#slider_counter").show();
      $(sideBar).removeAttr("rel").attr("rel", "normal");
      //$(sideBar).text("prepaid").attr('href', '/telefoons-prepaid/');
      $(".content-wrapper-subscription").show();
      $(".section-small .select-smaller > label").show();
      document.title = "Telefoons met abonnement";

    }
    /**
     *  Will set prices for the first page of the phones after reading the telephone JSON
     *  Also the
     *
     */

    function setInitialPrices() {

      var subscriptionToSet, abo, dataSinglePhone, i, j, useDefaultSubscription;
      if (currentSubscription) {
        subscriptionToSet = currentSubscription;
        var subscriptionText = $(".subscription-info-data").find("p").text();
        if (subscriptionText) {
          subscriptionText = $.trim(subscriptionText);
          var months = subscriptionText.substr(0, 2);
          if (months == "24") {
            $(".subscription-info-order").addClass("subscription-info-order-closed"); //Hide infoblock for 12 month subscriptions
          }
          else {
            $(".subscription-info-order").removeClass("subscription-info-order-closed"); //Show infoblock for 12 month subscriptions
          }

        }
      }
      else if (!isSliderSelectorChangeOrigin) {
        useDefaultSubscription = true;
      }

      if (subscriptionToSet || useDefaultSubscription) {
        for (j = 0; j < $(alleTelefoons.phones).length; ++j) {
          dataSinglePhone = alleTelefoons.phones[j];
          if (dataSinglePhone) {
            if (useDefaultSubscription) {
              subscriptionToSet = dataSinglePhone.artikel.default_abon;
            }
            for (i = 0; i < $(dataSinglePhone.abonnementen).length; ++i) {
              abo = dataSinglePhone.abonnementen[i];
              if (abo != null) {
                if (abo.looptijd == 24) {
                  if (subscriptionToSet == abo.id) {
                    if (!abo.promotekst_1) {
                      abo.promotekst_1 = "Prijs € " + abo.prijspermaand;
                    }
                    if (!abo.promotekst_2) {
                      abo.promotekst_2 = "";
                    }

                    dataSinglePhone.abonnement = $.extend({ }, abo); //Create a copy
                    dataSinglePhone.prijseenmalig = abo.prijseenmalig;
                    break;
                  }
                }
              }
            }
          }
        }
      }
    }



    if (merkenBlok.length) {
      //Oh oh wat een schijtconstructie. Dit hoort hier niet, dit hoort in een toesteloverzicht-specifiek javascriptje.

      $.getJSON(telefoonJSONPath, function (data) {
        //PAGING default settings ***** Remove the default hiding status on the paging elements.*********
        $(".endpaging, .showall, a.button-next, #selectsort").removeClass("paging-default");
        //END PAGING default settings ******************************************************************

        alleTelefoons = data;
        if (!alleTelefoons.phones) {

          if (alleTelefoons.aanbiedingen) { //With actionblocks
            alleTelefoons = {
              phones: alleTelefoons.aanbiedingen
            };
          } else {
            alleTelefoons = { //Without action blocks
              phones: alleTelefoons
            };
          }
        }

        geselecteerdeData = alleTelefoons;

        $.each(($.navi.get("mk") || merkSelected || "").split(","), function(i, merk) {
          merkSelected = merk;
          var checkbox = document.getElementById(merk);
          if (checkbox) { checkbox.checked = true; }
        });

        $.each(($.navi.get("at") || kenmerkSelected || "").split(","), function(i, ken) {
          kenmerkSelected = ken;
          var checkbox = document.getElementById(ken);
          if (checkbox) { checkbox.checked = true; }
        });

        $.refilterSelection();

        (function(selectedPage) {
          paging.currentPage = Number(selectedPage);
          setTimeout(function(){goToPage(paging.currentPage);}, 1);
          paging.update();
        }($.navi.get("pg") || 1));

        setInitialPrices();

        //load the slider library
        if ($("slider")) {

          var rangesForSlider = {
            lowRate: 5,
            highRate: 100
          };
          //Delayed load to alleviate timing problems in the slider.
          //Also, the slider lib will only be loaded on the Toesteloverzicht pagina.

          $.getScript(globalShopUrls.layoutUrl + '/javascript/template/slider.src.js', function () {
            $("#slider").slider({
              min: rangesForSlider['lowRate'],
              max: rangesForSlider['highRate'],
              position: rangesForSlider['highRate'],
              enabled: (currentSubscription == null) ? true : false,
              step: 10,
              onsliding: function (pos) {
                if (pos === rangesForSlider['highRate']) {
                  $(this).next().text(" Max");
                } else {
                  $(this).next().text("€ " + pos);
                }
              },
              onslide: function (pos) {

                if (initialLoadSequence) {

                  var messageTitle, messageText;
                  var userFlashMessage = $("meta[name='userFlash']").attr('content');
                  $("meta[name='userFlash']").attr('content', "");
                  if (userFlashMessage) {
                    messageText = userFlashMessage;
                    userFlashMessage = false;
                    $.displayAlert({
                      //Default options
                      title: "Geen telefoons in deze selectie",
                      text: messageText,
                      buttons: {
                        ok: "Ga verder"
                      },
                      callback: function (result) {
                        if (result == 'ok') {

                          //processingIcon.show();
                          geselecteerdeData = alleTelefoons; //Reset all selections and start with all phones.
                          $("span:contains('Merken')").parent().find("input[type='checkbox']").checked(false);
                          $("span:contains('Kenmerken')").parent().find("input[type='checkbox']").checked(false);
                          try {
                            $("#slider").slider("command").setposition(95);
                          }
                          catch (e) {
                            alert("13 " + e.message)
                          }
                          $.refilterSelection(100, 'aboPrijs');
                          $("#slider_counter").text(" Max");
                          $.colorbox.close();
                          //processingIcon.hide();


                        }
                      }
                    });
                  }

                  initialLoadSequence = false;
                  geselecteerdeData = $.filterOnCheckboxSelections(geselecteerdeData);
                  setMerkAndKenmerkenCounters();
                  setPagination(geselecteerdeData);
                  placeLightboxEventsToPhoneBoxLinks();
                  return;
                }
                processingIcon.show(function() {
                  if (isSliderSelectorChangeOrigin) {
                    currentSliderPos = pos;
                    $.navi.set("pr", pos);
                    $.refilterSelection(pos, 'aboPrijs');
                  }
                  else {
                    isSliderSelectorChangeOrigin = true;
                    $.refilterSelection();
                  }
                });
              }
            });
            setDisabledEvents();
          });

        } else {
          if (initialLoadSequence) {
            initialLoadSequence = false;
            geselecteerdeData = $.filterOnCheckboxSelections(geselecteerdeData);
            setMerkAndKenmerkenCounters();
            setPagination(geselecteerdeData);
            placeLightboxEventsToPhoneBoxLinks();
            return;
          }
        }


        if (currentProductType == "prepaid") {
          $.refilterSelection();
          processingIcon.hide();
        }

      });
    }

    var disbledSliderEventProcessor = function () {

      $.displayAlert({
        //Default options
        title: "Let op!",
        text: "Bij het veranderen van je maandbedrag, vervalt je gekozen abonnement.",
        buttons: {
          ok: "Ga verder",
          cancel: "Annuleer"
        },
        callback: function (result) {
          if (result == 'ok') {

            $("#slider").slider("command").setenabled(true);
            currentSubscription = null;
            currentDataSub = null;
            resetSubscriptionSettings();
            setInitialPrices();
            //$.refilterSelection (100, 'aboPrijs');
            $("#slider").slider("command").setposition(100);

            $("#slider_counter").text(" Max");

            //Since we are no longer disabled, remove the event from the stack.
            $(".slider-filler, .slider-handle").unbind('mousedown', disabledSliderEventWrapper);
            $(".slider-filler, .slider-handle").unbind('click', disabledSliderEventWrapper);

            $.colorbox.close();

          } else if (result == 'cancel') {
            $.colorbox.close();
          }
        }
      });


    }


    function resetSubscriptionSettings() {
      $.ajax({
        cache: false,
        url: $.metavalue("rugzakClear")
      }); //Reset the subscription on the backend. It is fire and forget.
      setInitialPrices();
      $(".content-wrapper-subscription").hide();
      $(".subscription-info").hide();
    }
    /**
     * Wraps the event with a conditional statement. Will than call the event processor itself
     */
    var disabledSliderEventWrapper;
    /**
     *  Will be called to set the events on the disabled slider when there is a subscription set.
     *
     */

    function setDisabledEvents() {

      if (!disabledSliderEventWrapper) {
        disabledSliderEventWrapper = function (event) {

          if (event.which == 1 && !$("#slider").slider("command").state.enabled) {
            disbledSliderEventProcessor();
          }
        }
      }

      if (currentSubscription) {


        try {
          $(".slider-filler, .slider-handle").bind({
            mousedown: disabledSliderEventWrapper,
            click: disabledSliderEventWrapper
          });
        } catch (ex) {
          alert("Error processing disabled slider events " + ex.name + " , " + ex.message);
        }

      }
    }

  });

  jQuery.extend(this.jQuery, {
    parseJsonPhoneData : function(data) {
      //Alle telefoons laden. Mag buiten document ready, omdat het alleen data ophaalt en klaarzet (nog) niets met het document doet
      //Deze functie pakt een subset uit de telefoons-json en houdt deze vast zolang de pagina in leven is (TODO: in sessionStorage zetten?)
      var promoblocks = data.actieblokken, items = data.aanbiedingen || [],
        keygetter = function(i, abo) {
          return abo.id.replace(/^abon_(\d+)$/, "$1");
        },
        valuegetter = function(i, abo) {
          var result = {
            naam: abo.naam,
            prijseenmalig: (abo.prijseenmalig || 0) - getBundelKorting(abo)- getSmsKorting(abo),
            prijspermaand: abo.prijspermaand,
            promotekst_1: abo.promotekst_1,
            promotekst_2: abo.promotekst_2
          };
          if (result.prijseenmalig < 0) {
            result.prijseenmalig = 0;
          }
          return result;
        },
        getBundelKorting = function(abo) {
          if ($.metavalue('geselecteerdData') && abo.bundel_kortingen) {
            var dataSel = $.metavalue('geselecteerdData');
          }
          else if (!$.metavalue('geselecteerdAbonnement') && abo.default_data && abo.bundel_kortingen) {
            var dataSel = abo.default_data;
          }
          else {
            return 0;
          }
          for (var i in abo.bundel_kortingen) {
            if (i == dataSel) {
              return abo.bundel_kortingen[i];
            }
          }
          return 0;
        },
        getSmsKorting = function(abo) {
          if ($.metavalue('geselecteerdSMS') && abo.bundel_kortingen) {
            var smsSel = $.metavalue('geselecteerdSMS');
            for (var i in abo.bundel_kortingen) {
              if (i == smsSel) {
                return abo.bundel_kortingen[i];
              }
            }
          }
          return 0;
        };
      var output = {};
      for (var i = 0, item, art; i < items.length; i++) {
        item = data.aanbiedingen[i];
        art = item.artikel;
        output[art.id.replace(/^artikel_(\d+)$/, "$1")] = {
          naam: art.naam,
          leverbaar: art.levenscyclus == "leverbaar",
          recensies_gem: art.recensies_gem,
          recensies_aantal: art.recensies_aantal,
          default_abon: art.default_abon,
          actie_blok: promoblocks[item.actieblokid],
          urls: item.urls,
          prijseenmalig: item.prijseenmalig,
          priceplans: item.abonnementen ? item.abonnementen.toObject(keygetter, valuegetter) : null,
		  artikel_icon: art.icon
        };
      }
      return output;
    }
  });

}(this.jQuery,this,this.document));

