<commit_before>(function($, window, undefined) {

  /* Plugin defaults options */
  var pluginName = 'ascensor',
    defaults = {
      ascensorName: "ascensor",           // First, choose the ascensor name
      ascensorFloorName: null,            // Choose name for each floor
      childType: "div",                   // Specify the child type if there are no 'div'
      windowsOn: 0,                       // Choose the floor to start on
      direction: "y",                     // specify if direction is x,y or chocolate
      loop: true,                         // specify if direction is x,y or chocolate
      ascensorMap: "",                    // If you choose chocolate for direction, speficy position
      time: "1000",                       // Specify speed of transition
      easing: "linear",                   // Specify easing option
      keyNavigation: true,                // choose if you want direction key support
      queued: false,                      // choose if you want direction scroll queued
      queuedDirection: "x",                // choose if you want direction scroll queued "x" or "y" (default : "x")
      overflow: "scroll"
    };

  /* Plugin defaults definitions */
  function Plugin(element, options) {
    this.element = element;
    this.options = $.extend({}, defaults, options);
    this._defaults = defaults;
    this._name = pluginName;
    this.init();
  }

  Plugin.prototype.init = function() {

    /* Settings */
    var self = this,
      node = this.element,
      nodeChildren = $(node).children(self.options.childType),

      //floor counter settings
      floorActive = self.options.windowsOn,
      floorCounter = -1,

      //height/width settings
      WW,
      WH,

      //plugins settings
      direction = self.options.direction,

      //hash
      hash;

    /* Start plugin actions */

    //define position,height & width
    $(node).css("position", "absolute").width(WW).height(WH);
    $(node).css("overflow", self.options.overflow);

    //define height & width
    $(nodeChildren).width(WW).height(WH)

    //for each floor
    .each(function() {

      //count floor
      floorCounter+=1;

      //give class and spcific id
      $(this).attr("id", self.options.ascensorName + "Floor" + floorCounter).addClass(self.options.ascensorName + "Floor");
    });

    // if direction is x or chocolate
    if (self.options.direction === "x" || self.options.direction === "chocolate") {

      //children position = absolute
      $(nodeChildren).css({"position":"absolute", "overflow":"auto"});
    }

    /* Hash function */
    function hashChange(onLoad) {

      //if the url have an "hash"
      if (window.location.hash) {

        //cut the "#/" part
        hash = window.location.hash.split("/").pop();

        //for each floorName given
        $(self.options.ascensorFloorName).each(function(index, floorName) {

          //compare with the hash, if equal
          if (hash === self.options.ascensorFloorName[index]) {
            //the floor become the index of equivalent floorName
            floorActive = index;

            //remove and add class "link active" to the current link
            $("." + self.options.ascensorName + "Link").removeClass(self.options.ascensorName + "LinkActive").eq(floorActive).addClass(self.options.ascensorName + "LinkActive");

            //Scroll to the target floor

            if(!onLoad){
              targetScroll(floorActive, self.options.time, true);
            }
          }

        });

      }

    }

    /* Resize function */
    function resize() {

      //update WW & WH variables
      WW = $(document).width();
      WH = $(document).height();

      //node and node children get have window widht & height
      $(nodeChildren).width(WW).height(WH);

      $(node).width(WW).height(WH);

      //if direction is y
      if (self.options.direction === "y") {

        //stop animation and update node scrollTop
        $(node).stop().scrollTop((floorActive) * WH);
      }

      //if direction is x
      if (self.options.direction === "x") {

        //stop animation and update scrollLeft
        $(node).stop().scrollLeft((floorActive) * WW);

        //deplace each children depending on index and left margin
        $(nodeChildren).each(function(index) {
          $(this).css("left", index * WW);
        });
      }

      //if direction is chocolate
      if (self.options.direction === "chocolate") {

        //for each children
        $(nodeChildren).each(function(index) {
          //deplace each children in x/y, depending on the index position
          $(this).css({
            "left": (self.options.ascensorMap[index][1]) * WW,
            "top": (self.options.ascensorMap[index][0]) * WH
          });

        });
        //stop animation and update scrollLeft & scrollTop
        $(node).stop().scrollLeft((self.options.ascensorMap[floorActive][1]) * WW).scrollTop((self.options.ascensorMap[floorActive][0]) * WH);
      }
    }

    //bind to resize
    $(window).resize(function() {
      resize();
    }).load(function() {
      resize();
    }).resize();

    //if browser is mobile
    if (window.DeviceOrientationEvent) {

      //add orientation check
      $(window).bind('orientationchange', function() {
        resize();
      });
    }

    /* Scroll function */
    function targetScroll(floor, time, hashChange) {

      if(hashChange){
        scrollStart();
      }

      //if direction is y
      if (self.options.direction === "y") {

        //stop animation and animate the "scrollTop" to the targeted floor
        $(node).stop().animate({
          scrollTop: (floor) * WH
        },
        time,
        self.options.easing, function() {
          scrollEnd();
        });
      }

      //if direction is x
      if (self.options.direction === "x") {

        //stop animation and animate the "scrollLeft" to the targeted floor
        $(node).stop().animate({
          scrollLeft: (floor) * WW
        },
        time,
        self.options.easing, function() {
          scrollEnd();
        });
      }

      //if direction is chocolate
      if (self.options.direction === "chocolate") {

        //get target axis

        //if queued options is true
        if (self.options.queued) {

          //queued direction is "x"
          if (self.options.queuedDirection === "x") {

            //if target is on the same horizontal level
            if ($(node).scrollLeft() ===  self.options.ascensorMap[floor][1] * WW) {
              //stop animation and animate the "scrollTop" to the targeted floor
              $(node).stop().animate({
                scrollTop: (self.options.ascensorMap[floor][0]) * WH
              },
              time,
              self.options.easing, function() {
                scrollEnd();
              });

              //if target is not on the same level
            } else {

              //stop animation, first  animate the "scrollLeft" to the targeted floor
              $(node).stop().animate({
                scrollLeft: (self.options.ascensorMap[floor][1]) * WW
              },
              time,
              self.options.easing,

              //and then animate the "scrollTop" to the targeted floor
              function() {
                $(node).stop().animate({
                  scrollTop: (self.options.ascensorMap[floor][0]) * WH
                },
                time,
                self.options.easing, function() {
                  scrollEnd();
                });
              });
            }

            //if queued direction is set on y
          } else if (self.options.queuedDirection === "y") {

            //if target is on the same vertical level
            if ($(node).scrollTop() === self.options.ascensorMap[floor][0] * WH) {

              //stop animation and animate the "scrollLeft" to the targeted floor
              $(node).stop().animate({
                scrollLeft: (self.options.ascensorMap[floor][1]) * WW
              },
              time,
              self.options.easing, function() {
                scrollEnd();
              });

              //if target is not on the same vertical level
            } else {

              //stop animation, first  animate the "scrollTop" to the targeted floor
              $(node).stop().animate({
                scrollTop: (self.options.ascensorMap[floor][0]) * WH
              },
              time,
              self.options.easing,

              //and then animate the "scrollLeft" to the targeted floor
              function() {
                $(node).stop().animate({
                  scrollLeft: (self.options.ascensorMap[floor][1]) * WW
                },
                time,
                self.options.easing, function() {
                  scrollEnd();
                });
              });
            }

          }

          //if queued option is false
        } else {

          //stop animation,  animate the "scrollLeft" & "scrollTop" to the targeted floor
          $(node).stop().animate({
            scrollLeft: (self.options.ascensorMap[floor][1]) * WW,
            scrollTop: (self.options.ascensorMap[floor][0]) * WH
          },
          time,
          self.options.easing, function() {
            scrollEnd();
          });
        }

      }

      if (!hashChange) {
        if (self.options.ascensorFloorName !== null) {
          //update url hash
          window.location.hash = "/" + self.options.ascensorFloorName[floor];
        }
      }

      //remove linkActive class on every link
      $("." + self.options.ascensorName + "Link").removeClass(self.options.ascensorName + "LinkActive");

      //add LinkActive class to equivalent Link
      $("." + self.options.ascensorName + "Link" + floor).addClass(self.options.ascensorName + "LinkActive");

      //update floorActive variable
      floorActive = floor;
    }

    //check key function
    function checkKey(e) {
      if($("input, textarea, button").is(":focus")){
        return false;
      }
      switch (e.which) {

        //keyDown
      case 40:
      case 83:
        $(node).trigger({
          type:"ascensorDown",
          floor: floorActive
        });
        break;

        //keyUp
      case 38:
      case 87:
        $(node).trigger({
          type:"ascensorUp",
          floor: floorActive
        });
        break;

        //keyLeft
      case 37:
      case 65:
        $(node).trigger({
          type:"ascensorLeft",
          floor: floorActive
        });
        break;

        //keyright
      case 39:
      case 68:
        $(node).trigger({
          type:"ascensorRight",
          floor: floorActive
        });
        break;
      }
    }

    if (self.options.keyNavigation) {
        $(document).keydown(checkKey);
    }

    function scrollStart(){
      $(node).trigger({
        type:"ascensorStart",
        floor: floorActive
      });
    }

    function scrollEnd(){
      $(node).trigger({
        type:"ascensorEnd",
        floor: floorActive
      });
    }

    function down() {
      if (self.options.direction == "y") {
        $(node).trigger({
          type:"ascensorNext",
          floor: floorActive
        });
      } else if (self.options.direction == "chocolate") {
        chocolatedirection(1, 0);
      }
    }

    function up() {
      if (self.options.direction == "y") {
        $(node).trigger({
          type:"ascensorPrev",
          floor: floorActive
        });
      } else if (self.options.direction == "chocolate") {
        chocolatedirection(-1, 0);
      }

    }

    function left() {
      if (self.options.direction == "x") {
        $(node).trigger({
          type:"ascensorPrev",
          floor: floorActive
        });
      } else if (self.options.direction == "chocolate") {
        chocolatedirection(0, -1);
      }
    }

    function right() {
      if (self.options.direction == "x") {
        $(node).trigger({
          type:"ascensorNext",
          floor: floorActive
        });
      } else if (self.options.direction == "chocolate") {
        chocolatedirection(0, 1);
      }
    }

    function prev() {
      var prevFloor = floorActive - 1;
      if (prevFloor < 0) {
        if (self.options.loop) {
          prevFloor = floorCounter;
        } else {
          prevFloor = 0;
        }
      }
      targetScroll(prevFloor, self.options.time);
    }

    function next() {
      var nextFloor = floorActive + 1;
      if (nextFloor > floorCounter) {
        if (self.options.loop) {
          nextFloor = 0;
        } else {
          nextFloor = floorCounter;
        }
      }
      targetScroll(nextFloor, self.options.time);
    }

    function chocolatedirection(addCoordY, addCoordX) {

      var floorReference = [self.options.ascensorMap[floorActive][0]+addCoordY, self.options.ascensorMap[floorActive][1]+addCoordX ];

      $.each(self.options.ascensorMap, function(index) {
       if (floorReference.toString() == self.options.ascensorMap[index].toString()) {
          targetScroll(index, self.options.time);
        }
      });
    }

    $(node).on("ascensorLeft", function() {
      left();
    });

    $(node).on("ascensorRight", function() {
      right();
    });

    $(node).on("ascensorUp", function() {
      up();
    });

    $(node).on("ascensorDown", function() {
      down();
    });

    $(node).on("ascensorNext", function() {
      next();
    });

    $(node).on("ascensorPrev", function() {
      prev();
    });

    //on ascensor prev link click
    $("." + self.options.ascensorName + "LinkPrev").on("click", function() {
      prev();
    });

    //on ascensor next click
    $("." + self.options.ascensorName + "LinkNext").on("click", function() {
      next();
    });

	// on ancensor left click
	$("." + self.options.ascensorName + "LinkLeft").on("click", function() {
      left();
    });

	// on ancensor right click
	$("." + self.options.ascensorName + "LinkRight").on("click", function() {
      right();
    });

	// on ancensor up click
	$("." + self.options.ascensorName + "LinkUp").on("click", function() {
      down();
    });

	// on ancensor down click
	$("." + self.options.ascensorName + "LinkDown").on("click", function() {
      up();
  });

  $("." + self.options.ascensorName + "Link").on("click", function() {

    //look for the second class and split the number
    var floorReference = parseInt(($(this).attr("class").split(" ")[1].split(self.options.ascensorName + "Link"))[1], 10);

    //target the floor number
    targetScroll(floorReference, self.options.time);

  });

  //scroll to active floor at start
  targetScroll(floorActive, 1, true);

  //when hash change, start hashchange function
  $(window).on("hashchange", function() {
    hashChange();
  });

    //start hashChange function at document loading
  hashChange(true);

    //end plugin action
  };

  $.fn[pluginName] = function(options) {
    return this.each(function() {
      if (!$.data(this, 'plugin_' + pluginName)) {
        $.data(this, 'plugin_' + pluginName, new Plugin(this, options));
      }
    });
  };

}(jQuery, window));<commit_msg>jQuery TouchSwipe Integration<commit_after>(function($, window, undefined) {

  /* Plugin defaults options */
  var pluginName = 'ascensor',
    defaults = {
      ascensorName: "ascensor",           // First, choose the ascensor name
      ascensorFloorName: null,            // Choose name for each floor
      childType: "div",                   // Specify the child type if there are no 'div'
      windowsOn: 0,                       // Choose the floor to start on
      direction: "y",                     // specify if direction is x,y or chocolate
      loop: true,                         // specify if direction is x,y or chocolate
      ascensorMap: "",                    // If you choose chocolate for direction, speficy position
      time: "1000",                       // Specify speed of transition
      easing: "linear",                   // Specify easing option
      keyNavigation: true,                // choose if you want direction key support
      touchSwipeIntegration: false,       // choose if you want swipe event support (requires http://labs.rampinteractive.co.uk/touchSwipe/)
      queued: false,                      // choose if you want direction scroll queued
      queuedDirection: "x",                // choose if you want direction scroll queued "x" or "y" (default : "x")
      overflow: "scroll"
    };

  /* Plugin defaults definitions */
  function Plugin(element, options) {
    this.element = element;
    this.options = $.extend({}, defaults, options);
    this._defaults = defaults;
    this._name = pluginName;
    this.init();
  }

  Plugin.prototype.init = function() {

    /* Settings */
    var self = this,
      node = this.element,
      nodeChildren = $(node).children(self.options.childType),

      //floor counter settings
      floorActive = self.options.windowsOn,
      floorCounter = -1,

      //height/width settings
      WW,
      WH,

      //plugins settings
      direction = self.options.direction,

      //hash
      hash;

    /* Start plugin actions */

    //define position,height & width
    $(node).css("position", "absolute").width(WW).height(WH);
    $(node).css("overflow", self.options.overflow);

    //define height & width
    $(nodeChildren).width(WW).height(WH)

    //for each floor
    .each(function() {

      //count floor
      floorCounter+=1;

      //give class and spcific id
      $(this).attr("id", self.options.ascensorName + "Floor" + floorCounter).addClass(self.options.ascensorName + "Floor");
    });

    // if direction is x or chocolate
    if (self.options.direction === "x" || self.options.direction === "chocolate") {

      //children position = absolute
      $(nodeChildren).css({"position":"absolute", "overflow":"auto"});
    }

    /* Hash function */
    function hashChange(onLoad) {

      //if the url have an "hash"
      if (window.location.hash) {

        //cut the "#/" part
        hash = window.location.hash.split("/").pop();

        //for each floorName given
        $(self.options.ascensorFloorName).each(function(index, floorName) {

          //compare with the hash, if equal
          if (hash === self.options.ascensorFloorName[index]) {
            //the floor become the index of equivalent floorName
            floorActive = index;

            //remove and add class "link active" to the current link
            $("." + self.options.ascensorName + "Link").removeClass(self.options.ascensorName + "LinkActive").eq(floorActive).addClass(self.options.ascensorName + "LinkActive");

            //Scroll to the target floor

            if(!onLoad){
              targetScroll(floorActive, self.options.time, true);
            }
          }

        });

      }

    }

    /* Resize function */
    function resize() {

      //update WW & WH variables
      WW = $(document).width();
      WH = $(document).height();

      //node and node children get have window widht & height
      $(nodeChildren).width(WW).height(WH);

      $(node).width(WW).height(WH);

      //if direction is y
      if (self.options.direction === "y") {

        //stop animation and update node scrollTop
        $(node).stop().scrollTop((floorActive) * WH);
      }

      //if direction is x
      if (self.options.direction === "x") {

        //stop animation and update scrollLeft
        $(node).stop().scrollLeft((floorActive) * WW);

        //deplace each children depending on index and left margin
        $(nodeChildren).each(function(index) {
          $(this).css("left", index * WW);
        });
      }

      //if direction is chocolate
      if (self.options.direction === "chocolate") {

        //for each children
        $(nodeChildren).each(function(index) {
          //deplace each children in x/y, depending on the index position
          $(this).css({
            "left": (self.options.ascensorMap[index][1]) * WW,
            "top": (self.options.ascensorMap[index][0]) * WH
          });

        });
        //stop animation and update scrollLeft & scrollTop
        $(node).stop().scrollLeft((self.options.ascensorMap[floorActive][1]) * WW).scrollTop((self.options.ascensorMap[floorActive][0]) * WH);
      }
    }

    //bind to resize
    $(window).resize(function() {
      resize();
    }).load(function() {
      resize();
    }).resize();

    //if browser is mobile
    if (window.DeviceOrientationEvent) {

      //add orientation check
      $(window).bind('orientationchange', function() {
        resize();
      });
    }

    /* Scroll function */
    function targetScroll(floor, time, hashChange) {

      if(hashChange){
        scrollStart();
      }

      //if direction is y
      if (self.options.direction === "y") {

        //stop animation and animate the "scrollTop" to the targeted floor
        $(node).stop().animate({
          scrollTop: (floor) * WH
        },
        time,
        self.options.easing, function() {
          scrollEnd();
        });
      }

      //if direction is x
      if (self.options.direction === "x") {

        //stop animation and animate the "scrollLeft" to the targeted floor
        $(node).stop().animate({
          scrollLeft: (floor) * WW
        },
        time,
        self.options.easing, function() {
          scrollEnd();
        });
      }

      //if direction is chocolate
      if (self.options.direction === "chocolate") {

        //get target axis

        //if queued options is true
        if (self.options.queued) {

          //queued direction is "x"
          if (self.options.queuedDirection === "x") {

            //if target is on the same horizontal level
            if ($(node).scrollLeft() ===  self.options.ascensorMap[floor][1] * WW) {
              //stop animation and animate the "scrollTop" to the targeted floor
              $(node).stop().animate({
                scrollTop: (self.options.ascensorMap[floor][0]) * WH
              },
              time,
              self.options.easing, function() {
                scrollEnd();
              });

              //if target is not on the same level
            } else {

              //stop animation, first  animate the "scrollLeft" to the targeted floor
              $(node).stop().animate({
                scrollLeft: (self.options.ascensorMap[floor][1]) * WW
              },
              time,
              self.options.easing,

              //and then animate the "scrollTop" to the targeted floor
              function() {
                $(node).stop().animate({
                  scrollTop: (self.options.ascensorMap[floor][0]) * WH
                },
                time,
                self.options.easing, function() {
                  scrollEnd();
                });
              });
            }

            //if queued direction is set on y
          } else if (self.options.queuedDirection === "y") {

            //if target is on the same vertical level
            if ($(node).scrollTop() === self.options.ascensorMap[floor][0] * WH) {

              //stop animation and animate the "scrollLeft" to the targeted floor
              $(node).stop().animate({
                scrollLeft: (self.options.ascensorMap[floor][1]) * WW
              },
              time,
              self.options.easing, function() {
                scrollEnd();
              });

              //if target is not on the same vertical level
            } else {

              //stop animation, first  animate the "scrollTop" to the targeted floor
              $(node).stop().animate({
                scrollTop: (self.options.ascensorMap[floor][0]) * WH
              },
              time,
              self.options.easing,

              //and then animate the "scrollLeft" to the targeted floor
              function() {
                $(node).stop().animate({
                  scrollLeft: (self.options.ascensorMap[floor][1]) * WW
                },
                time,
                self.options.easing, function() {
                  scrollEnd();
                });
              });
            }

          }

          //if queued option is false
        } else {

          //stop animation,  animate the "scrollLeft" & "scrollTop" to the targeted floor
          $(node).stop().animate({
            scrollLeft: (self.options.ascensorMap[floor][1]) * WW,
            scrollTop: (self.options.ascensorMap[floor][0]) * WH
          },
          time,
          self.options.easing, function() {
            scrollEnd();
          });
        }

      }

      if (!hashChange) {
        if (self.options.ascensorFloorName !== null) {
          //update url hash
          window.location.hash = "/" + self.options.ascensorFloorName[floor];
        }
      }

      //remove linkActive class on every link
      $("." + self.options.ascensorName + "Link").removeClass(self.options.ascensorName + "LinkActive");

      //add LinkActive class to equivalent Link
      $("." + self.options.ascensorName + "Link" + floor).addClass(self.options.ascensorName + "LinkActive");

      //update floorActive variable
      floorActive = floor;
    }

    //check key function
    function checkKey(e) {
      if($("input, textarea, button").is(":focus")){
        return false;
      }
      switch (e.which) {

        //keyDown
      case 40:
      case 83:
        $(node).trigger({
          type:"ascensorDown",
          floor: floorActive
        });
        break;

        //keyUp
      case 38:
      case 87:
        $(node).trigger({
          type:"ascensorUp",
          floor: floorActive
        });
        break;

        //keyLeft
      case 37:
      case 65:
        $(node).trigger({
          type:"ascensorLeft",
          floor: floorActive
        });
        break;

        //keyright
      case 39:
      case 68:
        $(node).trigger({
          type:"ascensorRight",
          floor: floorActive
        });
        break;
      }
    }

    if (self.options.keyNavigation) {
        $(document).keydown(checkKey);
    }

      //Enable swiping...
    if (self.options.touchSwipeIntegration){
        $(node).swipe( {
          //Generic swipe handler for all directions
          swipe:function(event, direction, distance, duration, fingerCount) {
           //  this[direction]();
           var ascensorDirStr="";
           if (direction=="up") ascensorDirStr="Down";
           else if (direction=="down") ascensorDirStr="Up";
           else if (direction=="left") ascensorDirStr="Right";
           else if (direction=="right") ascensorDirStr="Left";
             $(node).trigger({
                      type: "ascensor"+ascensorDirStr,
                      floor: floorActive
                  });
          },
            threshold:70
        });
    }

    function scrollStart(){
      $(node).trigger({
        type:"ascensorStart",
        floor: floorActive
      });
    }

    function scrollEnd(){
      $(node).trigger({
        type:"ascensorEnd",
        floor: floorActive
      });
    }

    function down() {
      if (self.options.direction == "y") {
        $(node).trigger({
          type:"ascensorNext",
          floor: floorActive
        });
      } else if (self.options.direction == "chocolate") {
        chocolatedirection(1, 0);
      }
    }

    function up() {
      if (self.options.direction == "y") {
        $(node).trigger({
          type:"ascensorPrev",
          floor: floorActive
        });
      } else if (self.options.direction == "chocolate") {
        chocolatedirection(-1, 0);
      }

    }

    function left() {
      if (self.options.direction == "x") {
        $(node).trigger({
          type:"ascensorPrev",
          floor: floorActive
        });
      } else if (self.options.direction == "chocolate") {
        chocolatedirection(0, -1);
      }
    }

    function right() {
      if (self.options.direction == "x") {
        $(node).trigger({
          type:"ascensorNext",
          floor: floorActive
        });
      } else if (self.options.direction == "chocolate") {
        chocolatedirection(0, 1);
      }
    }

    function prev() {
      var prevFloor = floorActive - 1;
      if (prevFloor < 0) {
        if (self.options.loop) {
          prevFloor = floorCounter;
        } else {
          prevFloor = 0;
        }
      }
      targetScroll(prevFloor, self.options.time);
    }

    function next() {
      var nextFloor = floorActive + 1;
      if (nextFloor > floorCounter) {
        if (self.options.loop) {
          nextFloor = 0;
        } else {
          nextFloor = floorCounter;
        }
      }
      targetScroll(nextFloor, self.options.time);
    }

    function chocolatedirection(addCoordY, addCoordX) {

      var floorReference = [self.options.ascensorMap[floorActive][0]+addCoordY, self.options.ascensorMap[floorActive][1]+addCoordX ];

      $.each(self.options.ascensorMap, function(index) {
       if (floorReference.toString() == self.options.ascensorMap[index].toString()) {
          targetScroll(index, self.options.time);
        }
      });
    }

    $(node).on("ascensorLeft", function() {
      left();
    });

    $(node).on("ascensorRight", function() {
      right();
    });

    $(node).on("ascensorUp", function() {
      up();
    });

    $(node).on("ascensorDown", function() {
      down();
    });

    $(node).on("ascensorNext", function() {
      next();
    });

    $(node).on("ascensorPrev", function() {
      prev();
    });

    //on ascensor prev link click
    $("." + self.options.ascensorName + "LinkPrev").on("click", function() {
      prev();
    });

    //on ascensor next click
    $("." + self.options.ascensorName + "LinkNext").on("click", function() {
      next();
    });

	// on ancensor left click
	$("." + self.options.ascensorName + "LinkLeft").on("click", function() {
      left();
    });

	// on ancensor right click
	$("." + self.options.ascensorName + "LinkRight").on("click", function() {
      right();
    });

	// on ancensor up click
	$("." + self.options.ascensorName + "LinkUp").on("click", function() {
      down();
    });

	// on ancensor down click
	$("." + self.options.ascensorName + "LinkDown").on("click", function() {
      up();
  });

  $("." + self.options.ascensorName + "Link").on("click", function() {

    //look for the second class and split the number
    var floorReference = parseInt(($(this).attr("class").split(" ")[1].split(self.options.ascensorName + "Link"))[1], 10);

    //target the floor number
    targetScroll(floorReference, self.options.time);

  });

  //scroll to active floor at start
  targetScroll(floorActive, 1, true);

  //when hash change, start hashchange function
  $(window).on("hashchange", function() {
    hashChange();
  });

    //start hashChange function at document loading
  hashChange(true);

    //end plugin action
  };

  $.fn[pluginName] = function(options) {
    return this.each(function() {
      if (!$.data(this, 'plugin_' + pluginName)) {
        $.data(this, 'plugin_' + pluginName, new Plugin(this, options));
      }
    });
  };

}(jQuery, window));
<|endoftext|>


<commit_before>import Ember from 'ember';

export default Ember.Component.extend({
  tagName: "div",
  overrideClass: 'draggable-object',
  classNameBindings: ["isDraggingObject:is-dragging-object:", 'overrideClass'],
  attributeBindings: ['draggable'],
  isDraggable: true,
  title: Ember.computed.alias('content.title'),

  draggable: Ember.computed('isDraggable', function() {
    var isDraggable = this.get('isDraggable');

    if (isDraggable) {
      return true;
    }
    else {
      return null;
    }
  }),

  dragStart: function(event) {

    var dataTransfer = event.dataTransfer;

    var obj = this.get('content');
    var id = this.get('coordinator').setObject(obj, { source: this });

    dataTransfer.setData('Text', id);

    if (obj) {
      Ember.set(obj, 'isDraggingObject', true);
    }
    this.set('isDraggingObject', true);
    this.sendAction('dragStartAction', obj);
  },

  dragEnd: function() {
    var obj = this.get('content');

    if (obj) {
      Ember.set(obj, 'isDraggingObject', false);
    }
    this.set('isDraggingObject', false);
    this.sendAction('dragEndAction', obj);
  },

  actions: {
    selectForDrag: function() {
      var obj = this.get('content');
      var hashId = this.get('coordinator').setObject(obj, { source: this });
      this.get('coordinator').set("clickedId", hashId);
    }
  }
});
<commit_msg>Prevents actions when the component is not draggable<commit_after>import Ember from 'ember';

export default Ember.Component.extend({
  tagName: "div",
  overrideClass: 'draggable-object',
  classNameBindings: ["isDraggingObject:is-dragging-object:", 'overrideClass'],
  attributeBindings: ['draggable'],
  isDraggable: true,
  title: Ember.computed.alias('content.title'),

  draggable: Ember.computed('isDraggable', function() {
    var isDraggable = this.get('isDraggable');

    if (isDraggable) {
      return true;
    }
    else {
      return null;
    }
  }),

  dragStart: function(event) {
    if (!this.get('isDraggable')) {
      event.preventDefault();
      return;
    }

    var dataTransfer = event.dataTransfer;

    var obj = this.get('content');
    var id = this.get('coordinator').setObject(obj, { source: this });

    dataTransfer.setData('Text', id);

    if (obj) {
      Ember.set(obj, 'isDraggingObject', true);
    }
    this.set('isDraggingObject', true);
    this.sendAction('dragStartAction', obj);
  },

  dragEnd: function() {
    if (!this.get('isDraggable')) {
      return;
    }

    var obj = this.get('content');

    if (obj) {
      Ember.set(obj, 'isDraggingObject', false);
    }
    this.set('isDraggingObject', false);
    this.sendAction('dragEndAction', obj);
  },

  actions: {
    selectForDrag: function() {
      var obj = this.get('content');
      var hashId = this.get('coordinator').setObject(obj, { source: this });
      this.set('coordinator.clickedId', hashId);
    }
  }
});
<|endoftext|>


<commit_before>import React, { Component } from 'react'
import HouseholdService from '../services/HouseholdService'

class Household extends Component {
  constructor(props) {
    super(props)

    this.state = {
      name: ''
    }
  }
  componentWillReceiveProps(nextProps) {
    const { id } = nextProps.match.params

    HouseholdService.fetchHousehold(id)
      .then(household => this.setState({
        name: household.name
      }))
  }

  componentDidMount() {
    const { id } = this.props.match.params
    HouseholdService.fetchHousehold(id)
      .then(household => this.setState({
        name: household.name
      }))
  }

  render() {
    const { name } = this.state
    return (

{name}

    )

  }
}

export default Household<commit_msg>Connect Household component to redux<commit_after>import React, { Component } from 'react'
import { connect } from 'react-redux'
import HouseholdService from '../services/HouseholdService'

class Household extends Component {
  render() {
    const { households } = this.props
    const id = this.props.match.params.id
    const household = households.find(h => h.id == id)
    if (household) {
      return (

{household.name}

      )
    } else {
      return null
    }

  }
}

export default connect(state => {
  return {
    households: state.households
  }
})(Household)<|endoftext|>


<commit_before>import { Meteor } from 'meteor/meteor';

import { Topic } from '/imports/topic'
import { Minutes } from '/imports/minutes'

Session.setDefault("topicEditTopicId", null);

let _minutesID; // the ID of these minutes

Template.topicEdit.onCreated(function () {
    _minutesID = this.data;
    console.log("Template topicEdit created with minutesID "+_minutesID);
});

Template.topicEdit.onRendered(function () {
    $.material.init();
    $('#id_selResponsible').select2({
        placeholder: 'Select...',
        tags: true,
        tokenSeparators: [',', ';']
    });
});

Template.topicEdit.onDestroyed(function () {
    //add your statement here
});

var getEditTopic = function() {
    let topicId = Session.get("topicEditTopicId");

    if (_minutesID == null ||  topicId == null) {
        return false;
    }

    return new Topic(_minutesID, topicId);
};

var getPossibleResponsibles = function() {
    let possibleResponsibles = [];          // sorted later on
    let possibleResponsiblesUnique = {};    // ensure uniqueness
    let buffer = [];                        // userIds and names from different sources, may have doubles

    // add regular participants from current minutes
    let aMin = new Minutes(_minutesID);
    for (let i in aMin.participants) {
        buffer.push(aMin.participants[i].userId);
    }

    // add the "additional participants" from current minutes as simple strings
    let participantsAdditional = aMin.participantsAdditional;
    if (participantsAdditional) {
        let splitted = participantsAdditional.split(/[,;]/);
        for (let i in splitted) {
            buffer.push(splitted[i].trim());
        }
    }

    // add the responsibles from current topic
    let topic = getEditTopic();
    if (topic) {
        buffer.concat(topic._topicDoc.responsibles);
    }

    for (let i in buffer) {
        let aResponsibleId = buffer[i];
        if (! possibleResponsiblesUnique[aResponsibleId]) { // not seen?
            possibleResponsiblesUnique[aResponsibleId] = true;
            let aResponsibleName = aResponsibleId;
            let aUser = Meteor.users.findOne(aResponsibleId);
            if (aUser) {
                aResponsibleName = aUser.username;
            }
            possibleResponsibles.push({username: aResponsibleName, userId: aResponsibleId});
        }
    }

    return possibleResponsibles;
};

Template.topicEdit.helpers({
    'getTopicSubject': function() {
        let topic = getEditTopic();
        return (topic) ? topic._topicDoc.subject : "";
    }
});

Template.topicEdit.events({
    "click #btnTopicSave": function (evt, tmpl) {
        evt.preventDefault();

        var aSubject = tmpl.find("#id_subject").value;
        var multiResponsibles = $('#id_selResponsible').val();

        let editTopic = getEditTopic();

        let topicDoc = {};

        if (editTopic) {
            _.extend(topicDoc, editTopic._topicDoc);
        }

        topicDoc.subject = aSubject;
        topicDoc.responsibles = multiResponsibles;

        let aTopic = new Topic(_minutesID, topicDoc);
        aTopic.save((error) => {
            if (error) {
                Session.set('errorTitle', 'Validation error');
                Session.set('errorReason', error.reason);
            } else {
                $('#dlgAddTopic').modal('hide')
            }
        });
    },

    "hidden.bs.modal #dlgAddTopic": function (evt, tmpl) {
        $('#frmDlgAddTopic')[0].reset();
        let subjectNode = tmpl.$("#id_subject");
        subjectNode.parent().removeClass("has-error");

        // reset the session vars to indicate that edit mode has been closed
        Session.set("topicEditTopicId", null);
    },

    "show.bs.modal #dlgAddTopic": function (evt, tmpl) {
        let selectResponsibles = $('#id_selResponsible');
        selectResponsibles.val(null)        // clear <option>s and selections
            .find('option')
            .remove()
            .end();
        let possResp = getPossibleResponsibles();
        for (let i in possResp) {
            selectResponsibles.append('<option value="'+ possResp[i].userId +'">'+ possResp[i].username +'</option>');
        }

        let topic = getEditTopic();
        if (topic && topic._topicDoc && topic._topicDoc.responsibles) {
            console.log(topic._topicDoc.responsibles);
            selectResponsibles.val(topic._topicDoc.responsibles);
        }
        selectResponsibles.trigger("change");
    },

    "shown.bs.modal #dlgAddTopic": function (evt, tmpl) {
        $('#dlgAddTopic input').trigger("change");    // ensure new values trigger placeholder animation
        tmpl.find("#id_subject").focus();
    },

    "select2:selecting #id_selResponsible"(evt, tmpl) {
        // console.log(evt);
        console.log("selecting:"+evt.params.args.data.id + "/"+evt.params.args.data.text);
        // evt.preventDefault();
        // return false;
    },

    "select2:select #id_selResponsible"(evt, tmpl) {
        // console.log(evt);
        console.log("select:"+evt.params.data.id + "/"+evt.params.data.text);
    }

});
<commit_msg>WIP: topic responsibles via select2.js<commit_after>import { Meteor } from 'meteor/meteor';

import { Topic } from '/imports/topic'
import { Minutes } from '/imports/minutes'

Session.setDefault("topicEditTopicId", null);

let _minutesID; // the ID of these minutes

Template.topicEdit.onCreated(function () {
    _minutesID = this.data;
    console.log("Template topicEdit created with minutesID "+_minutesID);
});

Template.topicEdit.onRendered(function () {
    $.material.init();
});

Template.topicEdit.onDestroyed(function () {
    //add your statement here
});

var getEditTopic = function() {
    let topicId = Session.get("topicEditTopicId");

    if (_minutesID == null ||  topicId == null) {
        return false;
    }

    return new Topic(_minutesID, topicId);
};

var getPossibleResponsibles = function() {
    let possibleResponsibles = [];          // sorted later on
    let possibleResponsiblesUnique = {};    // ensure uniqueness
    let buffer = [];                        // userIds and names from different sources, may have doubles

    // add regular participants from current minutes
    let aMin = new Minutes(_minutesID);
    for (let i in aMin.participants) {
        buffer.push(aMin.participants[i].userId);
    }

    // add the "additional participants" from current minutes as simple strings
    let participantsAdditional = aMin.participantsAdditional;
    if (participantsAdditional) {
        let splitted = participantsAdditional.split(/[,;]/);
        for (let i in splitted) {
            buffer.push(splitted[i].trim());
        }
    }

    // add the responsibles from current topic
    let topic = getEditTopic();
    if (topic) {
        buffer.concat(topic._topicDoc.responsibles);
    }

    for (let i in buffer) {
        let aResponsibleId = buffer[i];
        if (! possibleResponsiblesUnique[aResponsibleId]) { // not seen?
            possibleResponsiblesUnique[aResponsibleId] = true;
            let aResponsibleName = aResponsibleId;
            let aUser = Meteor.users.findOne(aResponsibleId);
            if (aUser) {
                aResponsibleName = aUser.username;
            }
            possibleResponsibles.push({id: aResponsibleId, text: aResponsibleName});
        }
    }

    return possibleResponsibles;
};

// get those registered users that are not already added to select2 via
// getPossibleResponsibles()
var getRemainingUsers = function (participants) {
    let participantsIds = [];
    let remainingUsers = [];
    for (let i in participants) {
        if (participants[i].id.length > 15) {   // Meteor _ids default to 17 chars
            participantsIds.push(participants[i].id);
        }
    }

    // format return object suiting for select2.js
    let users = Meteor.users.find({_id: {$nin: participantsIds}}).fetch();
    for (let i in users) {
        remainingUsers.push ({id: users[i]._id, text: users[i].username});
    }
    return remainingUsers;
};

function configureSelect2Responsibles() {
    let selectResponsibles = $('#id_selResponsible');
    selectResponsibles.find('optgroup')     // clear all <option>s
        .remove();
    let possResp = getPossibleResponsibles();
    let remainingUsers = getRemainingUsers(possResp);
    let selectOptions = [{
        text: "Participants",
        children: possResp
    }, {
        text: "Other Users",
        children: remainingUsers
    }];
    selectResponsibles.select2({
        placeholder: 'Select...',
        tags: true,                     // Allow freetext adding
        tokenSeparators: [',', ';'],
        data: selectOptions             // push <option>s data
    });

    // select the options that where stored with this topic last time
    let topic = getEditTopic();
    if (topic && topic._topicDoc && topic._topicDoc.responsibles) {
        selectResponsibles.val(topic._topicDoc.responsibles);
    }
    selectResponsibles.trigger("change");
}

Template.topicEdit.helpers({
    'getTopicSubject': function() {
        let topic = getEditTopic();
        return (topic) ? topic._topicDoc.subject : "";
    }
});

Template.topicEdit.events({
    "click #btnTopicSave": function (evt, tmpl) {
        evt.preventDefault();

        var aSubject = tmpl.find("#id_subject").value;
        var multiResponsibles = $('#id_selResponsible').val();

        let editTopic = getEditTopic();

        let topicDoc = {};

        if (editTopic) {
            _.extend(topicDoc, editTopic._topicDoc);
        }

        topicDoc.subject = aSubject;
        topicDoc.responsibles = multiResponsibles;

        let aTopic = new Topic(_minutesID, topicDoc);
        aTopic.save((error) => {
            if (error) {
                Session.set('errorTitle', 'Validation error');
                Session.set('errorReason', error.reason);
            } else {
                $('#dlgAddTopic').modal('hide')
            }
        });
    },

    "hidden.bs.modal #dlgAddTopic": function (evt, tmpl) {
        $('#frmDlgAddTopic')[0].reset();
        let subjectNode = tmpl.$("#id_subject");
        subjectNode.parent().removeClass("has-error");

        // reset the session vars to indicate that edit mode has been closed
        Session.set("topicEditTopicId", null);
    },

    "show.bs.modal #dlgAddTopic": function (evt, tmpl) {
        configureSelect2Responsibles();
    },

    "shown.bs.modal #dlgAddTopic": function (evt, tmpl) {
        $('#dlgAddTopic input').trigger("change");    // ensure new values trigger placeholder animation
        tmpl.find("#id_subject").focus();
    },

    "select2:selecting #id_selResponsible"(evt, tmpl) {
        // console.log(evt);
        console.log("selecting:"+evt.params.args.data.id + "/"+evt.params.args.data.text);
        // evt.preventDefault();
        // return false;
    },

    "select2:select #id_selResponsible"(evt, tmpl) {
        // console.log(evt);
        console.log("select:"+evt.params.data.id + "/"+evt.params.data.text);
    }

});
<|endoftext|>


<commit_before>(function () {
    'use strict';

    var cfg              = require('nconf'),
        when             = require('when'),
        moment           = require('moment'),
        provider         = require('../providers').postProvider,
        pagination       = require('../helpers/pagination'),
        paginationRegexp = new RegExp(cfg.get('app:paginationUrl').replace(':page', '\\d+')),
        yearRegExp       = /^1|2\d{3}$/,
        monthRegExp      = /^0|1\d$/,
        dayRegExp        = /^0|1|2|3\d$/,
        pageNumberRegExp = /^\d+$/;

    exports.middleware = function (req, res, next) {
        when.join(
                provider.labelsInfo({ live:true }),
                provider.archiveInfo()
            )
            .spread(function (labels, archives) {
                res.locals.labels = labels;
                res.locals.archives = archives;
            })
            .then(next);
    };

    exports.index = function(req, res) {
        var limit = cfg.get('app:postsPerPage'),
            page = req.params.page || 1,
            skip = limit * (page - 1);

        when.join(
                provider.findAll({ live:true, page:false, limit:limit, skip:skip, sortBy:'-publishedAt' }),
                provider.count({ page:false, live: true })
            )
            .spread(function (posts, count) {
                res.locals.posts = posts;
                res.locals.pagination = pagination(req, count);

                res.render('index');
            })
            .otherwise(function (err) {
                res.send(500, err.toString());
            });
    };

    exports.year = function (req, res) {
        var limit = cfg.get('app:postsPerPage'),
            page = req.params.page || 1,
            skip = limit * (page - 1), year = +req.params.year;

        when.join(
                provider.findByDate({ live:true, page:false, year:year, skip:skip, limit:limit }),
                provider.count({ year:year, page:false, live:true })
            )
            .then(function (results) {
                res.locals.posts = results[0];
                res.locals.year = year;
                res.locals.pagination = pagination(req, results[1]);

                res.render('index');
            });
    };

    exports.month = function (req, res) {
        var limit = cfg.get('app:postsPerPage'),
            page = req.params.page || 1,
            skip = limit * (page - 1),
            year = +req.params.year,
            month = +req.params.month;

        when.join(
                provider.findByDate({ live:true, page:false, month:month, year:year, skip:skip, limit:limit }),
                provider.count({ month:month, year:year, page:false, live:true })
            )
            .spread(function (posts, count) {
                res.locals.posts = posts;
                res.locals.year = year;
                res.locals.month = month;
                res.locals.date = moment([year, month - 1]);
                res.locals.pagination = pagination(req, count);

                res.render('index');
            });
    };

    exports.day = function (req, res) {
        var limit = cfg.get('app:postsPerPage'),
            page = req.params.page || 1,
            skip = limit * (page - 1),
            year = +req.params.year,
            month = +req.params.month,
            day = +req.params.day;

        when.join(
                provider.findByDate({ live:true, page:false, day:day, month:month, year: year, skip:skip, limit:limit }),
                provider.count({ day:day, month:month, year:year, page:false, live:true })
            )
            .then(function (results) {
                res.locals.posts = results[0];
                res.locals.year = year;
                res.locals.month = month;
                res.locals.day = day;
                res.locals.date = moment([year, month - 1, day]);
                res.locals.pagination = pagination(req, results[1]);

                res.render('index');
            });
    };

    exports.post = function (req, res, next) {
        when(
            provider.findBySlug(req.params.slug, { live:true })
        ).then(function (post) {

                // if there is no post with the given slug, check if there is no other route
                // which could handle that request e.g. /:year
                if (!post) { return next('route'); }

                res.locals.post = post;
                res.render(post.page ? 'page' : 'post');
            }).otherwise(function (error) {
                res.send(500);
            });
    };

    exports.searchByLabel = function (req, res) {
        var limit = cfg.get('app:postsPerPage'),
            page = req.params.page || 1,
            skip = limit * (page - 1);

        when.join(
                provider.findByLabel({ live:true, page:false, label:req.params.label, skip:skip, limit:limit }),
                provider.count({ label:req.params.label, page:false, live:true })
            )
            .spread(function (posts, count) {
                res.locals.posts = posts;
                res.locals.pagination = pagination(req, count);
                res.locals.label = req.params.label;

                res.render('index');
            });
    };

    exports.pageParam = function (req, res, next, page) {
        if (!page.match(pageNumberRegExp)) { return next('route'); }
        if (+page > 1) { next(); }
        else {
            // Redirect to URL with no pagination if page 1 is used e.g. /page/1
            var path = req.path.replace(paginationRegexp, '');
            path = ('' === path) ? '/' : path;
            res.redirect(path);
        }
    };

    exports.formatParam = function (req, res, next, format) {
        if (['html', 'json'].indexOf(format) >= 0) { next(); }
        else { next('route'); }
    };

    exports.yearParam = function (req, res, next, year) {
        if (year.match(yearRegExp)) { next(); }
        else { next('route'); }
    };

    exports.monthParam = function (req, res, next, month) {
        if (month.match(monthRegExp) && moment([+req.params.year, +month-1]).isValid()) { next(); }
        else { next('route'); }
    };

    exports.dayParam = function (req, res, next, day) {
        if (day.match(dayRegExp) &&
            moment([+req.params.year, +req.params.month-1, +req.params.day]).isValid()) { next(); }
        else { next('route'); }
    };

}());<commit_msg>Frontend sorting fix<commit_after>(function () {
    'use strict';

    var cfg              = require('nconf'),
        when             = require('when'),
        moment           = require('moment'),
        provider         = require('../providers').postProvider,
        pagination       = require('../helpers/pagination'),
        paginationRegexp = new RegExp(cfg.get('app:paginationUrl').replace(':page', '\\d+')),
        yearRegExp       = /^1|2\d{3}$/,
        monthRegExp      = /^0|1\d$/,
        dayRegExp        = /^0|1|2|3\d$/,
        pageNumberRegExp = /^\d+$/;

    module.exports.middleware = function (req, res, next) {
        when.join(
                provider.labelsInfo({ live:true }),
                provider.archiveInfo()
            )
            .spread(function (labels, archives) {
                res.locals.labels = labels;
                res.locals.archives = archives;
            })
            .then(next);
    };

    module.exports.index = function(req, res) {
        var limit = cfg.get('app:postsPerPage'),
            page = req.params.page || 1,
            skip = limit * (page - 1);

        when.join(
                provider.findAll({ live:true, page:false, limit:limit, skip:skip, sortBy:'-publishedAt' }),
                provider.count({ page:false, live: true })
            )
            .spread(function (posts, count) {
                res.locals.posts = posts;
                res.locals.pagination = pagination(req, count);

                res.render('index');
            })
            .otherwise(function (err) {
                res.send(500, err.toString());
            });
    };

    module.exports.year = function (req, res) {
        var limit = cfg.get('app:postsPerPage'),
            page = req.params.page || 1,
            skip = limit * (page - 1), year = +req.params.year;

        when.join(
                provider.findByDate({
                    live: true, page: false, year: year, skip: skip, limit: limit, sortBy: '-publishedAt' }),
                provider.count({ year: year, page: false, live: true })
            )
            .then(function (results) {
                res.locals.posts = results[0];
                res.locals.year = year;
                res.locals.pagination = pagination(req, results[1]);

                res.render('index');
            });
    };

    module.exports.month = function (req, res) {
        var limit = cfg.get('app:postsPerPage'),
            page = req.params.page || 1,
            skip = limit * (page - 1),
            year = +req.params.year,
            month = +req.params.month;

        when.join(
                provider.findByDate({
                    live: true, page: false,
                    month: month, year: year,
                    skip: skip, limit: limit, sortBy: '-publishedAt' }),
                provider.count({ month: month, year: year, page: false, live: true })
            )
            .spread(function (posts, count) {
                res.locals.posts = posts;
                res.locals.year = year;
                res.locals.month = month;
                res.locals.date = moment([year, month - 1]);
                res.locals.pagination = pagination(req, count);

                res.render('index');
            });
    };

    module.exports.day = function (req, res) {
        var limit = cfg.get('app:postsPerPage'),
            page = req.params.page || 1,
            skip = limit * (page - 1),
            year = +req.params.year,
            month = +req.params.month,
            day = +req.params.day;

        when.join(
                provider.findByDate({
                    live: true, page: false,
                    day: day, month: month, year: year,
                    skip: skip, limit: limit,
                    sortBy: '-publishedAt'
                }),
                provider.count({ day: day, month: month, year: year, page: false, live: true })
            )
            .then(function (results) {
                res.locals.posts = results[0];
                res.locals.year = year;
                res.locals.month = month;
                res.locals.day = day;
                res.locals.date = moment([year, month - 1, day]);
                res.locals.pagination = pagination(req, results[1]);

                res.render('index');
            });
    };

    module.exports.post = function (req, res, next) {
        when.resolve(
                provider.findBySlug(req.params.slug, { live: true })
            )
            .then(function (post) {

                // if there is no post with the given slug, check if there is no other route
                // which could handle that request e.g. /:year
                if (!post) {
                    return next('route');
                }

                res.locals.post = post;
                res.render(post.page ? 'page' : 'post');
            })
            .otherwise(function () {
                res.send(500);
            });
    };

    module.exports.searchByLabel = function (req, res) {
        var limit = cfg.get('app:postsPerPage'),
            page = req.params.page || 1,
            skip = limit * (page - 1);

        when.join(
                provider.findByLabel({
                    live: true, page: false,
                    label: req.params.label,
                    skip: skip, limit: limit, sortBy: '-publishedAt' }),
                provider.count({ label: req.params.label, page: false, live: true })
            )
            .spread(function (posts, count) {
                res.locals.posts = posts;
                res.locals.pagination = pagination(req, count);
                res.locals.label = req.params.label;

                res.render('index');
            });
    };

    module.exports.pageParam = function (req, res, next, page) {
        if (!page.match(pageNumberRegExp)) {
            return next('route');
        }
        if (+page > 1) {
            next();
        }
        else {
            // Redirect to URL with no pagination if page 1 is used e.g. /page/1
            var path = req.path.replace(paginationRegexp, '');
            path = ('' === path) ? '/' : path;
            res.redirect(path);
        }
    };

    module.exports.formatParam = function (req, res, next, format) {
        if (['html', 'json'].indexOf(format) >= 0) {
            next();
        }
        else {
            next('route');
        }
    };

    module.exports.yearParam = function (req, res, next, year) {
        if (year.match(yearRegExp)) {
            next();
        }
        else {
            next('route');
        }
    };

    module.exports.monthParam = function (req, res, next, month) {
        if (month.match(monthRegExp) && moment([+req.params.year, +month - 1]).isValid()) {
            next();
        }
        else {
            next('route');
        }
    };

    module.exports.dayParam = function (req, res, next, day) {
        if (day.match(dayRegExp) && moment([+req.params.year, +req.params.month - 1, +req.params.day]).isValid()) {
            next();
        }
        else {
            next('route');
        }
    };

}());<|endoftext|>


<commit_before>/**
 * Show.js
 *
 * @description :: TODO: You might write a short summary of how this model works and what it represents here.
 * @docs        :: http://sailsjs.org/documentation/concepts/models-and-orm/models
 */

module.exports = {

  attributes: {
    name: {
      type: 'string',
      required: true
    }
  }
};

<commit_msg>Add description and imageUrl to Show<commit_after>/**
 * Show.js
 *
 * @description :: TODO: You might write a short summary of how this model works and what it represents here.
 * @docs        :: http://sailsjs.org/documentation/concepts/models-and-orm/models
 */

module.exports = {

  attributes: {
    name: {
      type: 'string',
      required: true
    },
    description: {
      type: 'string'
    },
    imageUrl: {
      type: 'string'
    }
  }
};

<|endoftext|>


<commit_before>$(function() {

	'use strict';

	var client = ZAFClient.init(),
		attachments = [],
		comment_path = "ticket.comments",

		$container = $('#container'),
		$download = $('#download'),
		$list = $('#list'),
		$message = $('#message'),
		$status = $('#status'),
		$progress = $('#progress'),
		$interface = $('#interface'),
		$expand = $('#expand')
	;

	client.on('app.registered', function(event) {
		$progress.hide();
		findAttachments()
		.then(function() {
			attachments
			.sort(function(a,b) {
				return a.filename > b.filename ? 1 : a.filename < b.filename ? -1 : 0;
			});
			displayAttachments();
			$download.show();
		})
		.catch(function(err) {
			message(err);
			$download.hide();
		})
		.then(function() {
			$container.show();
		});
	});

	client.on('ticket.comments.changed', function(event) {
		// console.log(event);
	});

	$download.on("click", function() {
		hide($interface);
		show($status);

		status("Fetching attachments...");

		downloadAttachments().
		then(function() {
			status("ZIP done!");
			setTimeout(function() {
				hide($status);
				hide($progress);
				$progress.percent = 0;
				show($interface);
			}, 2000);
		});
	});

	$message.on("click", function() {
		$list.toggle(0, function() {
			client.invoke('resize', { height: $container.css("height") });
		});
	});

	function findAttachments() {
		return client.get(comment_path)
			.then(function(response) {
				var comments = $.makeArray(response[comment_path]);
				var allAttachments = $.map(comments, function(comment) {
					return []
						.concat(comment.imageAttachments)
						.concat(comment.nonImageAttachments);
				});
				attachments = deduplicate(allAttachments);
				return new Promise(function(resolve, reject) {
					var attachmentsFound = $.isArray(attachments) && attachments.length > 0;
					layout({attachmentsFound: attachmentsFound});
					if (!attachmentsFound) {
						reject("No attachments found in this ticket.");
					} else {
						resolve();
					}
				});
			});
	}

	function layout(prefs) {
		var attachmentsFound = prefs.attachmentsFound;
		var height = attachmentsFound ? "4rem" : "2rem";
		client.invoke('resize', { height: height });
	}

	function displayAttachments() {
		var html = $.map(attachments, function(attachment) {
			return (
				"
" +
				""+attachment.filename+"" +
				"
"
			)
		});
		$list
		.append(html)
		.toggle();
		message(
			"" +
				attachments.length +
				" attachment" +
				(attachments.length == 1 ? "" : "s") +
			" found in this ticket."
		);
	}

	function makeZip() {
		var zip = new JSZip();
		$.each(attachments, function(index, attachment) {
			zip.file(
				attachment.filename,
				urlToPromise(attachment.contentUrl),
				{
					binary:true
				}
			);
		});
		return zip;
	}

	function downloadAttachments() {
		var first = true;
		return makeZip()
		.generateAsync({type:"blob"}, function updateCallback(metadata) {

			if (first) {
				$progress.show();
				first = false;
			}

			var percent = metadata.percent;
			$progress.percent = percent;
			status("Making ZIP: " + percent.toFixed(2) + "%");
		})
		.then(function (blob) {
			client.context().then(function(context) {
				var filename = "Zendesk-";
				filename += context.ticketId;
				filename += "-attachments-";
				filename += new Date().getTime();
				filename += ".zip";
				saveAs(blob, filename);
			})
		});
	}

	function message(message) {
		display($message, message);
	}

	function status(message) {
		display($status, message);
	}

	function display($element, message) {
		$element.html(message);
	}

	function show($element) {
		$element.show(600);
	}

	function hide($element) {
		$element.hide(600);
	}

	/**
	* Set the width of the colored part of the progress bar.
	*/
	Object.defineProperty($progress, "percent", {
		set: function(percent) {
			this
			.find("#progress-bar")
			.attr('aria-valuenow', percent)
			.width(percent+"%");
		}
	});

	/**
	 * Fetch the content and return the associated promise.
	 * @param {String} url the url of the content to fetch.
	 * @return {Promise} the promise containing the data.
	 */
	function urlToPromise(url) {
		return new Promise(function(resolve, reject) {
			JSZipUtils.getBinaryContent(url, function (err, data) {
				if(err) {
					reject(err);
				} else {
					resolve(data);
				}
			});
		});
	}

    /**
        Append a string to filename before the extension.
    */
    function appendStringToFilename(filename, string) {
        var dotIndex = filename.lastIndexOf(".");
        if (dotIndex == -1) {
            return filename + string;
        } else {
            return filename.substring(0, dotIndex) + string + filename.substring(dotIndex);
        }
    }

    // Modified from
    // https://stackoverflow.com/a/34972148/1110820
    // Takes an array of attachments and appends numbers
    // to the filenames to get rid of duplicates.
    // (Like Windows filenames.)
	function deduplicate(attachments) {

		var c = {},
		t = function(x, n) { return appendStringToFilename(x, "(" + n + ")"); };

		return attachments.map(function(attachment) {
			var n = c[attachment.filename] || 0;
			c[attachment.filename] = n + 1;

			if (!n) {
				return attachment;
			}

			while (c[t(attachment.filename, n)]) {
				n++;
			}

			c[t(attachment.filename, n)] = 1;
			attachment.filename = t(attachment.filename, n);
			return attachment;
		});

	}

});<commit_msg>Refactor a little<commit_after>$(function() {

	'use strict';

	var client = ZAFClient.init(),
		attachments = [], // attachments is "global" so we don't have to get the list repeatedly

		COMMENT_PATH = "ticket.comments",

		$container = $('#container'),
		$download = $('#download'),
		$list = $('#list'),
		$message = $('#message'),
		$status = $('#status'),
		$progress = $('#progress'),
		$interface = $('#interface'),
		$expand = $('#expand')
	;

	client.on('app.registered', function(event) {
		$progress.hide();
		findAttachments()
		.then(function() {
			attachments.sort(defaultSort);
			displayAttachments();
			$download.show();
		})
		.catch(function(err) {
			message(err);
			$download.hide();
		})
		.then(function() {
			$container.show();
		});
	});

	client.on('ticket.comments.changed', function(event) {
		// console.log(event);
	});

	$download.on("click", function() {
		hide($interface);
		show($status);

		status("Fetching attachments...");

		downloadAttachments()
		.then(function() {
			status("ZIP done!");
			setTimeout(function() {
				hide($status);
				hide($progress);
				$progress.percent = 0;
				show($interface);
			}, 2000);
		});
	});

	$message.on("click", function() {
		$list.toggle(0, function() { // expand the list, and...
			client.invoke('resize', { height: $container.css("height") }); // ...expand the app so you can see the list
		});
	});

	function defaultSort(a, b) {
		return a.filename > b.filename ? 1 : a.filename  0;
					layout({attachmentsFound: attachmentsFound});
					if (!attachmentsFound) {
						reject("No attachments found in this ticket.");
					} else {
						resolve();
					}
				});
			});
	}

	function getAllAttachments(response) {
		var comments = $.makeArray(response[COMMENT_PATH]);
		var allAttachments = $.map(comments, function(comment) {
			return []
				.concat(comment.imageAttachments)
				.concat(comment.nonImageAttachments);
		});
		return deduplicate(allAttachments);
	}

	function layout(prefs) {
		var attachmentsFound = prefs.attachmentsFound;
		var height = attachmentsFound ? "4rem" : "2rem";
		client.invoke('resize', { height: height });
	}

	function displayAttachments() {
		var html = $.map(attachments, function(attachment) {
			return (
				"
" +
				""+attachment.filename+"" +
				"
"
			)
		});
		$list
		.append(html)
		.toggle();
		message(
			"" +
				attachments.length +
				" attachment" +
				(attachments.length == 1 ? "" : "s") +
			" found in this ticket."
		);
	}

	function makeZip() {
		var zip = new JSZip();
		$.each(attachments, function(index, attachment) {
			zip.file(
				attachment.filename,
				urlToPromise(attachment.contentUrl),
				{
					binary:true
				}
			);
		});
		return zip;
	}

	function downloadAttachments() {
		var first = true;
		return makeZip()
		.generateAsync({type:"blob"}, function updateCallback(metadata) {

			if (first) {
				$progress.show();
				first = false;
			}

			var percent = metadata.percent;
			$progress.percent = percent;
			status("Making ZIP: " + percent.toFixed(2) + "%");
		})
		.then(function (blob) {
			client.context().then(function(context) {
				var filename = "Zendesk-";
				filename += context.ticketId;
				filename += "-attachments-";
				filename += new Date().getTime();
				filename += ".zip";
				saveAs(blob, filename);
			})
		});
	}

	function message(message) {
		display($message, message);
	}

	function status(message) {
		display($status, message);
	}

	function display($element, message) {
		$element.html(message);
	}

	function show($element) {
		$element.show(600);
	}

	function hide($element) {
		$element.hide(600);
	}

	/**
	* Set the width of the colored part of the progress bar.
	*/
	Object.defineProperty($progress, "percent", {
		set: function(percent) {
			this
			.find("#progress-bar")
			.attr('aria-valuenow', percent)
			.width(percent+"%");
		}
	});

	/**
	 * Fetch the content and return the associated promise.
	 * @param {String} url the url of the content to fetch.
	 * @return {Promise} the promise containing the data.
	 */
	function urlToPromise(url) {
		return new Promise(function(resolve, reject) {
			JSZipUtils.getBinaryContent(url, function (err, data) {
				if(err) {
					reject(err);
				} else {
					resolve(data);
				}
			});
		});
	}

    /**
        Append a string to filename before the extension.
    */
    function appendStringToFilename(filename, string) {
        var dotIndex = filename.lastIndexOf(".");
        if (dotIndex == -1) {
            return filename + string;
        } else {
            return filename.substring(0, dotIndex) + string + filename.substring(dotIndex);
        }
    }

    // Modified from
    // https://stackoverflow.com/a/34972148/1110820
    // Takes an array of attachments and appends numbers
    // to the filenames to get rid of duplicates.
    // (Like Windows filenames.)
	function deduplicate(attachments) {

		var c = {},
		t = function(x, n) { return appendStringToFilename(x, "(" + n + ")"); };

		return attachments.map(function(attachment) {
			var n = c[attachment.filename] || 0;
			c[attachment.filename] = n + 1;

			if (!n) {
				return attachment;
			}

			while (c[t(attachment.filename, n)]) {
				n++;
			}

			c[t(attachment.filename, n)] = 1;
			attachment.filename = t(attachment.filename, n);
			return attachment;
		});

	}

});<|endoftext|>


<commit_before>// Copyright (c) 2013, Web Notes Technologies Pvt. Ltd.
// License: GNU General Public License v3. See license.txt

wn.require('app/setup/doctype/contact_control/contact_control.js');

cur_frm.cscript.onload = function(doc,dt,dn){

}

cur_frm.cscript.refresh = function(doc,dt,dn) {
	cur_frm.cscript.make_dashboard(doc);
	if(sys_defaults.supp_master_name == 'Supplier Name')
		hide_field('naming_series');
	else
		unhide_field('naming_series');

	if(doc.__islocal){
    	hide_field(['address_html','contact_html']);
	}
	else{
	  	unhide_field(['address_html','contact_html']);
		// make lists
		cur_frm.cscript.make_address(doc,dt,dn);
		cur_frm.cscript.make_contact(doc,dt,dn);

		cur_frm.communication_view = new wn.views.CommunicationList({
			list: wn.model.get("Communication", {"supplier": doc.name}),
			parent: cur_frm.fields_dict.communication_html.wrapper,
			doc: doc
		})
  }
}

cur_frm.cscript.make_dashboard = function(doc) {
	cur_frm.dashboard.reset();
	if(doc.__islocal)
		return;
	cur_frm.dashboard.set_headline('Loading...')

	cur_frm.dashboard.add_doctype_badge("Supplier Quotation", "supplier");
	cur_frm.dashboard.add_doctype_badge("Purchase Order", "supplier");
	cur_frm.dashboard.add_doctype_badge("Purchase Receipt", "supplier");
	cur_frm.dashboard.add_doctype_badge("Purchase Invoice", "supplier");

	return wn.call({
		type: "GET",
		method:"buying.doctype.supplier.supplier.get_dashboard_info",
		args: {
			supplier: cur_frm.doc.name
		},
		callback: function(r) {
			cur_frm.dashboard.set_headline(
				wn._("Total Billing This Year: ") + ""
				+ format_currency(r.message.total_billing, cur_frm.doc.default_currency)
				+ ' / ' + wn._("Unpaid") + ": "
				+ format_currency(r.message.total_unpaid, cur_frm.doc.default_currency)
				+ '');
			cur_frm.dashboard.set_badge_count(r.message);
		}
	})
}

cur_frm.cscript.make_address = function() {
	if(!cur_frm.address_list) {
		cur_frm.address_list = new wn.ui.Listing({
			parent: cur_frm.fields_dict['address_html'].wrapper,
			page_length: 5,
			new_doctype: "Address",
			get_query: function() {
				return "select name, address_type, address_line1, address_line2, city, state, country, pincode, fax, email_id, phone, is_primary_address, is_shipping_address from tabAddress where supplier='"+cur_frm.docname+"' and docstatus != 2 order by is_primary_address desc"
			},
			as_dict: 1,
			no_results_message: 'No addresses created',
			render_row: cur_frm.cscript.render_address_row,
		});
		// note: render_address_row is defined in contact_control.js
	}
	cur_frm.address_list.run();
}

cur_frm.cscript.make_contact = function() {
	if(!cur_frm.contact_list) {
		cur_frm.contact_list = new wn.ui.Listing({
			parent: cur_frm.fields_dict['contact_html'].wrapper,
			page_length: 5,
			new_doctype: "Contact",
			get_query: function() {
				return "select name, first_name, last_name, email_id, phone, mobile_no, department, designation, is_primary_contact from tabContact where supplier='"+cur_frm.docname+"' and docstatus != 2 order by is_primary_contact desc"
			},
			as_dict: 1,
			no_results_message: 'No contacts created',
			render_row: cur_frm.cscript.render_contact_row,
		});
		// note: render_contact_row is defined in contact_control.js
	}
	cur_frm.contact_list.run();
}<commit_msg>Fix translate supplier.js<commit_after>// Copyright (c) 2013, Web Notes Technologies Pvt. Ltd.
// License: GNU General Public License v3. See license.txt

wn.require('app/setup/doctype/contact_control/contact_control.js');

cur_frm.cscript.onload = function(doc,dt,dn){

}

cur_frm.cscript.refresh = function(doc,dt,dn) {
	cur_frm.cscript.make_dashboard(doc);
	if(sys_defaults.supp_master_name == 'Supplier Name')
		hide_field('naming_series');
	else
		unhide_field('naming_series');

	if(doc.__islocal){
    	hide_field(['address_html','contact_html']);
	}
	else{
	  	unhide_field(['address_html','contact_html']);
		// make lists
		cur_frm.cscript.make_address(doc,dt,dn);
		cur_frm.cscript.make_contact(doc,dt,dn);

		cur_frm.communication_view = new wn.views.CommunicationList({
			list: wn.model.get("Communication", {"supplier": doc.name}),
			parent: cur_frm.fields_dict.communication_html.wrapper,
			doc: doc
		})
  }
}

cur_frm.cscript.make_dashboard = function(doc) {
	cur_frm.dashboard.reset();
	if(doc.__islocal)
		return;
	cur_frm.dashboard.set_headline('Loading...')

	cur_frm.dashboard.add_doctype_badge("Supplier Quotation", "supplier");
	cur_frm.dashboard.add_doctype_badge("Purchase Order", "supplier");
	cur_frm.dashboard.add_doctype_badge("Purchase Receipt", "supplier");
	cur_frm.dashboard.add_doctype_badge("Purchase Invoice", "supplier");

	return wn.call({
		type: "GET",
		method:"buying.doctype.supplier.supplier.get_dashboard_info",
		args: {
			supplier: cur_frm.doc.name
		},
		callback: function(r) {
			cur_frm.dashboard.set_headline(
				wn._("Total Billing This Year: ") + ""
				+ format_currency(r.message.total_billing, cur_frm.doc.default_currency)
				+ ' / ' + wn._("Unpaid") + ": "
				+ format_currency(r.message.total_unpaid, cur_frm.doc.default_currency)
				+ '');
			cur_frm.dashboard.set_badge_count(r.message);
		}
	})
}

cur_frm.cscript.make_address = function() {
	if(!cur_frm.address_list) {
		cur_frm.address_list = new wn.ui.Listing({
			parent: cur_frm.fields_dict['address_html'].wrapper,
			page_length: 5,
			new_doctype: "Address",
			get_query: function() {
				return "select name, address_type, address_line1, address_line2, city, state, country, pincode, fax, email_id, phone, is_primary_address, is_shipping_address from tabAddress where supplier='"+cur_frm.docname+"' and docstatus != 2 order by is_primary_address desc"
			},
			as_dict: 1,
			no_results_message: wn._('No addresses created'),
			render_row: cur_frm.cscript.render_address_row,
		});
		// note: render_address_row is defined in contact_control.js
	}
	cur_frm.address_list.run();
}

cur_frm.cscript.make_contact = function() {
	if(!cur_frm.contact_list) {
		cur_frm.contact_list = new wn.ui.Listing({
			parent: cur_frm.fields_dict['contact_html'].wrapper,
			page_length: 5,
			new_doctype: "Contact",
			get_query: function() {
				return "select name, first_name, last_name, email_id, phone, mobile_no, department, designation, is_primary_contact from tabContact where supplier='"+cur_frm.docname+"' and docstatus != 2 order by is_primary_contact desc"
			},
			as_dict: 1,
			no_results_message: wn._('No contacts created'),
			render_row: cur_frm.cscript.render_contact_row,
		});
		// note: render_contact_row is defined in contact_control.js
	}
	cur_frm.contact_list.run();
}<|endoftext|>


<commit_before>// jshint node: true
'use strict';

var lt = function (a, b) { return a < b; };
var le = function (a, b) { return !lt(b, a); };

/*
 * @param {ListSlice} s -- slice to be sorted
 * @param {Number} sorted -- number of elements that are already sorted
 */
function binarysort(s, sorted) {
  var p;
  sorted = sorted || 1;
  var sList = s.list;
  var start = s.base + sorted,
      end = s.base + s.length;
  while (start < end) {
    var l = s.base;
    var r = start;
    var pivot = sList[r];
    while (l < r) {
      p = l + (r - l >> 1);
      if (lt(pivot, sList[p])) {
        r = p;
      } else {
        l = p + 1;
      }
    }
    for (p = start; p !== l; p--) {
      sList[p] = sList[p - 1];
    }
    sList[l] = pivot;
    start++;
  }
}

function TimSort(list) {
  this.list = list;
}

TimSort.prototype.MIN_GALLOP = 7;

TimSort.prototype.sort = function () {
  var remaining = new ListSlice(this.list, 0, this.list.length);
  if (remaining.length < 2) { return; }

  this.minGallop = this.MIN_GALLOP;
  this.pending = [];
  var minrun = this.minrun(remaining.length);

  while (remaining.length > 0) {
    var run = this.countRun(remaining);
    if (run.descending) {
      run.reverse();
    }
    if (run.length < minrun) {
      var sorted = run.length;
      run.length = Math.min(minrun, remaining.length);
      binarysort(run, sorted);
    }
    remaining.advance(run.length);
    this.pending.push(run);
    this.mergeCollapse();
  }
  this.mergeForceCollapse();
};

TimSort.prototype.mergeCollapse = function () {
  var p = this.pending;
  while (p.length > 1) {
    var plen = p.length;
    var lastLen = p[plen - 1].length;
    var secondLastLen = p[plen - 2].length;
    if (plen >= 3 &&
        p[plen - 3].length <= (secondLastLen + lastLen)) {
      if (p[plen - 3].length < lastLen) {
        this.mergeAt(-3);
      } else {
        this.mergeAt(-2);
      }
    } else if (secondLastLen <= lastLen) {
      this.mergeAt(-2);
    } else {
      break;
    }
  }
};

TimSort.prototype.mergeForceCollapse = function () {
  var p = this.pending;
  while (p.length > 1) {
    var plen = p.length;
    if (plen >= 3 && p[plen-3].length < p[plen-1].length) {
      this.mergeAt(-3);
    } else {
      this.mergeAt(-2);
    }
  }
};

TimSort.prototype.mergeAt = function (fromEnd) {
  var i = this.pending.length + fromEnd;
  var a = this.pending[i];
  var b = this.pending[i + 1];

  this.pending[i] = new ListSlice(this.list, a.base, a.length + b.length);
  this.pending.splice(i + 1, 1);

  var k = this.gallop(b.first(), a, 0, true);
  a.advance(k);
  if (a.length === 0) {
    return;
  }

  b.length = this.gallop(a.last(), b, b.length-1, false);
  if (b.length === 0) {
    return;
  }

  if (a.length <= b.length) {
    this.mergeLo(a, b);
  } else {
    this.mergeHi(a, b);
  }

};

TimSort.prototype.countRun = function (s) {
  var descending, runLen, p;
  if (s.length < 2) {
    runLen = s.length;
    descending = false;
  } else {
    runLen = 2;
    descending = lt(s.get(s.base + 1), s.first());
    var start = s.base + 2, sliceEnd = s.base + s.length;
    if (descending) {
      for (p = start; p < sliceEnd; p++) {
        if (!lt(s.get(p), s.get(p - 1))) {
          break;
        }
        runLen++;
      }
    } else {
      for (p = start; p < sliceEnd; p++) {
        if (lt(s.get(p), s.get(p - 1))) {
          break;
        }
        runLen++;
      }
    }
  }
  return new ListSlice(s.list, s.base, runLen, descending);
};

TimSort.prototype.gallop = function (key, s, hint, rightmost) {
  var lower;
  if (rightmost) {
    lower = le;
  } else {
    lower = lt;
  }

  var p = s.base + hint;
  var lastOffset = 0;    // last offset
  var maxOffset, offset = 1;
  if (lower(s.get(p), key)) {
    maxOffset = s.length - hint;
    while (offset < maxOffset) {
      if (lower(s.get(p + offset), key)) {
        lastOffset = offset;
        offset++;
      } else {
        break;
      }
    }

    if (offset > maxOffset) {
      offset = maxOffset;
    }
    lastOffset += hint;
    offset += hint;
  } else {
    maxOffset = hint + 1;
    while (offset < maxOffset) {
      if (lower(s.get(p - offset), key)) {
        break;
      } else {
        lastOffset = offset;
        offset++;
      }
    }
    if (offset > maxOffset) {
      offset = maxOffset;
    }
    var oldLastOffset = lastOffset;
    lastOffset = hint - offset;
    offset = hint - oldLastOffset;
  }

  lastOffset += 1;
  while (lastOffset < offset) {
    var m = lastOffset + (offset - lastOffset >> 1);
    if (lower(s.get(s.base + m), key)) {
      lastOffset = m + 1;
    } else {
      offset = m;
    }
  }
  return offset;
};

TimSort.prototype.mergeLo = function (a, b) {
  var p;
  var dest = a.base;
  var list = this.list;
  a = a.copy();
  list[dest] = b.popleft();
  dest += 1;
  if (a.length === 1 || b.length === 0) {
    return;
  }

  while (true) {
    var aCount = 0;
    var bCount = 0;

    var minGallop = this.minGallop;
    while (bCount < minGallop && aCount < minGallop) {
      // merge while keeping track of which side won
      if (lt(b.first(), a.first())) {
        list[dest++] = b.popleft();
        if (b.length === 0) {
          return this.finishMergeLo(a, b, dest);
        }
        bCount++;
        aCount = 0;
      } else {
        list[dest++] = a.popleft();
        if (a.length === 1) {
          return this.finishMergeLo(a, b, dest);
        }
        aCount++;
        bCount = 0;
      }
    }

    this.minGallop++;
    while (true) {
      this.minGallop -= this.minGallop > 1;
      aCount = this.gallop(b.first(), a, 0, true);

      for (p = a.base; p < a.base + aCount; p++) {
        list[dest] = a.get(p);
        dest++;
      }
      a.advance(aCount);

      if (a.length <= 1) { return this.finishMergeLo(a, b, dest); }

      list[dest] = b.popleft();
      dest++;
      if (b.length === 0) { return this.finishMergeLo(a, b, dest); }

      bCount = this.gallop(a.first(), b, 0, false);
      for (p = b.base; p < b.base + bCount; p++) {
        list[dest] = b.get(p);
        dest++;
      }
      b.advance(bCount);
      if (b.length === 0) { return this.finishMergeLo(a, b, dest); }

      list[dest] = a.popleft();
      dest++;
      if (a.length === 1) { return this.finishMergeLo(a, b, dest); }

      if (aCount < this.MIN_GALLOP && bCount < this.MIN_GALLOP) {
        break;
      }
    }

    this.minGallop++;
  }
};

TimSort.prototype.finishMergeLo = function (a, b, dest) {
  var list = this.list;
  for (var p = b.base; p < b.base + b.length; p++) {
    list[dest] = b.get(p);
    dest++;
  }
  for (p = a.base; p < a.base + a.length; p++) {
    list[dest] = a.get(p);
    dest++;
  }
};

TimSort.prototype.mergeHi = function (a, b) {

  var p, nextA, nextB;
  var dest = b.base + b.length;
  b = b.copy();

  dest -= 1;
  var list = this.list;
  list[dest] = a.popright();
  if (a.length === 0 || b.length === 1) {
    return;
  }

  while (true) {
    var aCount = 0;
    var bCount = 0;

    var minGallop = this.minGallop;
    while (aCount < minGallop && bCount < minGallop) {
      nextA = a.last();
      nextB = b.last();
      if (lt(nextB, nextA)) {
        list[--dest] = nextA;
        if (--a.length === 0) {
          return this.finishMergeHi(a, b, dest);
        }
        aCount += 1;
        bCount = 0;
      } else {
        list[--dest] = nextB;
        if (--b.length === 1) {
          return this.finishMergeHi(a, b, dest);
        }
        bCount += 1;
        aCount = 0;
      }
    }

    this.minGallop++;
    while (true) {
      this.minGallop -= this.minGallop > 1;

      nextB = b.last();
      var k = this.gallop(nextB, a, a.length - 1, true);
      aCount = a.length - k;

      for (p = a.base + a.length - 1; p !== a.base + k - 1; p--) {
        dest--;
        list[dest] = a.get(p);
      }

      a.length -= aCount;
      if (a.length === 0) { return this.finishMergeHi(a, b, dest); }

      dest--;
      list[dest] = b.popright();
      if (b.length === 1) { return this.finishMergeHi(a, b, dest); }

      nextA = a.last();
      k = this.gallop(nextA, b, b.length - 1, false);
      bCount = b.length - k;

      for (p = b.base + b.length - 1; p !== b.base + k - 1; p--) {
        dest--;
        list[dest] = b.get(p);
      }
      b.length -= bCount;

      if (b.length <= 1) { return this.finishMergeHi(a, b, dest); }

      dest--;
      list[dest] = a.popright();
      if (a.length === 0) {
        return this.finishMergeHi(a, b, dest);
      }

      if (aCount < this.MIN_GALLOP && bCount < this.MIN_GALLOP) {
        break;
      }
    }
    this.minGallop++;
  }
};

TimSort.prototype.finishMergeHi = function (a, b, dest) {
  var list = this.list;
  for (var p = a.base + a.length - 1; p !== a.base - 1; p--) {
    dest--;
    list[dest] = a.get(p);
  }
  for (p = b.base + b.length - 1; p !== b.base - 1; p--) {
    dest--;
    list[dest] = b.get(p);
  }
};

TimSort.prototype.minrun = function (n) {
  var r = 0;    // becomes 1 if any 1 bits are shifted off
  while (n >= 64) {
      r |= n & 1;
      n >>= 1;
  }
  return n + r;
};

function ListSlice(list, base, length, descending) {
  this.list = list;
  this.base = base;
  this.length = length;
  this.descending = descending;
}

ListSlice.prototype.copy = function () {
  var start = this.base;
  var stop = this.base + this.length;
  return new ListSlice(this.list.slice(start, stop), 0, this.length);
};

ListSlice.prototype.advance = function (n) {
  this.base += n;
  this.length -= n;
};

ListSlice.prototype.get = function (index) {
  return this.list[index];
};

ListSlice.prototype.set = function (index, value) {
  this.list[index] = value;
};

ListSlice.prototype.popleft = function () {
  var result = this.get(this.base);
  this.base += 1;
  this.length -= 1;
  return result;
};

ListSlice.prototype.popright = function () {
  this.length -= 1;
  return this.get(this.base + this.length);
};

ListSlice.prototype.reverse = function () {
  var list = this.list;
  var lo = this.base;
  var hi = lo + this.length - 1;
  while (lo < hi) {
    var listHi = list[hi];
    var listLo = list[lo];
    list[lo] = listHi;
    list[hi] = listLo;
    lo++;
    hi--;
  }
};

ListSlice.prototype.last = function () {
  return this.list[this.base + this.length - 1];
};

ListSlice.prototype.first = function () {
  return this.list[this.base];
};

module.exports = TimSort;<commit_msg>various optimizations, refactors<commit_after>'use strict';

/*
 * Binary insertion sort
 *
 * @param {ListSlice} s -- slice to be sorted
 * @param {Number} sorted -- number of elements that are already sorted
 */
function binarysort(s, sorted, cmp) {
  sorted = sorted || 1;
  var sList = s.list,
      sBase = s.base,
      start = sBase + sorted,
      end = sBase + s.length;
  for (; start < end; start++) {
    var l = sBase,
        r = start,
        pivot = sList[r];
    if (cmp(sList[r-1], pivot)) {
      continue;
    }
    while (l < r) {
      var p = l + (r - l >> 1);
      if (cmp(pivot, sList[p])) {
        r = p;
      } else {
        l = p + 1;
      }
    }
    // swap elements over to make room for pivot
    for (var i = start; i !== l; i--) {
      sList[i] = sList[i - 1];
    }
    sList[l] = pivot;
  }
}

function TimSort(list, lt) {
  this.list = list;
  this.lt = this.lt || lt;
  if (lt) {
    this.le = null;
  }
}

TimSort.prototype.MIN_GALLOP = 7;
TimSort.prototype.lt = function (a, b) { return a < b; };
TimSort.prototype.le = function (a, b) { return a <= b; };

TimSort.prototype.sort = function () {
  var remaining = new ListSlice(this.list, 0, this.list.length);
  if (remaining.length < 2) { return; }

  this.minGallop = this.MIN_GALLOP;
  this.pending = [];
  var minrun = this.minrun(remaining.length);

  while (remaining.length > 0) {
    var run = this.countRun(remaining);
    if (run.descending) {
      run.reverse();
    }
    if (run.length < minrun) {
      var sorted = run.length;
      run.length = Math.min(minrun, remaining.length);
      binarysort(run, sorted, this.lt);
    }
    remaining.advance(run.length);
    this.pending.push(run);
    this.mergeCollapse();
  }
  this.mergeForceCollapse();
};

TimSort.prototype.mergeCollapse = function () {
  var p = this.pending;
  while (p.length > 1) {
    var plen = p.length;
    var lastLen = p[plen - 1].length;
    var secondLastLen = p[plen - 2].length;
    if (plen >= 3 &&
        p[plen - 3].length <= (secondLastLen + lastLen)) {
      if (p[plen - 3].length < lastLen) {
        this.mergeAt(-3);
      } else {
        this.mergeAt(-2);
      }
    } else if (secondLastLen <= lastLen) {
      this.mergeAt(-2);
    } else {
      break;
    }
  }
};

TimSort.prototype.mergeForceCollapse = function () {
  var p = this.pending;
  while (p.length > 1) {
    var plen = p.length;
    if (plen >= 3 && p[plen-3].length < p[plen-1].length) {
      this.mergeAt(-3);
    } else {
      this.mergeAt(-2);
    }
  }
};

TimSort.prototype.mergeAt = function (fromEnd) {
  var pending = this.pending;
  var i = pending.length + fromEnd;
  var a = pending[i];
  var b = pending[i + 1];

  pending[i] = new ListSlice(this.list, a.base, a.length + b.length);
  pending.splice(i + 1, 1);

  var k = this.gallop(b.first(), a, 0, true);
  a.advance(k);
  if (a.length === 0) {
    return;
  }

  b.length = this.gallop(a.last(), b, b.length-1, false);
  if (b.length === 0) {
    return;
  }

  if (a.length <= b.length) {
    this.mergeLo(a, b);
  } else {
    this.mergeHi(a, b);
  }

};

TimSort.prototype.countRun = function (s) {
  if (s.length < 2) {
    return new ListSlice(s.list, s.base, s.length, false);
  }

  var lt = this.lt,
      runLen = 2,
      descending = lt(s.get(s.base + 1), s.first()),
      i = s.base + 2,
      end = s.base + s.length;
  if (descending) {
    for (; i < end && lt(s.get(i), s.get(i - 1)); i++) {
      runLen++;
    }
  } else {
    for (; i < end && !lt(s.get(i), s.get(i - 1)); i++) {
      runLen++;
    }
  }
  return new ListSlice(s.list, s.base, runLen, descending);
};

TimSort.prototype.gallop = function (key, s, hint, rightmost) {
  var lower, lt = this.lt, le = this.le;
  if (rightmost) {
    lower = le || function (a, b) { return !lt(b, a); };
  } else {
    lower = lt;
  }

  var p = s.base + hint;
  var sList = s.list;
  var lastOffset = 0;
  var maxOffset, offset = 1;
  if (lower(sList[p], key)) {
    maxOffset = s.length - hint;
    for (; offset < maxOffset && lower(sList[p + offset], key); offset++) {
      lastOffset = offset;
    }
    if (offset > maxOffset) {
      offset = maxOffset;
    }
    lastOffset += hint;
    offset += hint;
  } else {
    maxOffset = hint + 1;
    for (; offset < maxOffset && !lower(sList[p - offset], key); offset++) {
      lastOffset = offset;
    }
    if (offset > maxOffset) {
      offset = maxOffset;
    }
    var oldLastOffset = lastOffset;
    lastOffset = hint - offset;
    offset = hint - oldLastOffset;
  }

  lastOffset += 1;
  while (lastOffset < offset) {
    var m = lastOffset + (offset - lastOffset >> 1);
    if (lower(sList[s.base + m], key)) {
      lastOffset = m + 1;
    } else {
      offset = m;
    }
  }
  return offset;
};

TimSort.prototype.mergeLo = function (a, b) {
  var p,
      dest = a.base,
      list = this.list,
      lt = this.lt;
  a = a.copy();
  var aList = a.list, bList = b.list;
  list[dest] = b.popleft();
  dest += 1;
  if (a.length === 1 || b.length === 0) {
    return;
  }

  while (true) {
    var aCount = 0;
    var bCount = 0;

    var minGallop = this.minGallop;
    while (bCount < minGallop && aCount < minGallop) {
      // merge while keeping track of which side won
      if (lt(b.first(), a.first())) {
        list[dest++] = b.popleft();
        if (b.length === 0) {
          return this.finishMergeLo(a, b, dest);
        }
        bCount++;
        aCount = 0;
      } else {
        list[dest++] = a.popleft();
        if (a.length === 1) {
          return this.finishMergeLo(a, b, dest);
        }
        aCount++;
        bCount = 0;
      }
    }
    this.minGallop++;

    while (true) {
      this.minGallop -= this.minGallop > 1;
      aCount = this.gallop(b.first(), a, 0, true);

      for (p = a.base; p < a.base + aCount; p++) {
        list[dest] = aList[p];
        dest++;
      }
      a.advance(aCount);

      if (a.length < 2) { return this.finishMergeLo(a, b, dest); }

      list[dest] = b.popleft();
      dest++;
      if (b.length === 0) { return this.finishMergeLo(a, b, dest); }

      bCount = this.gallop(a.first(), b, 0, false);
      for (p = b.base; p < b.base + bCount; p++) {
        list[dest] = bList[p];
        dest++;
      }
      b.advance(bCount);
      if (b.length === 0) { return this.finishMergeLo(a, b, dest); }

      list[dest] = a.popleft();
      dest++;
      if (a.length === 1) { return this.finishMergeLo(a, b, dest); }

      if (aCount < this.MIN_GALLOP && bCount < this.MIN_GALLOP) {
        break;
      }
    }

    this.minGallop++;
  }
};

TimSort.prototype.finishMergeLo = function (a, b, dest) {
  var list = this.list;
  for (var p = b.base; p < b.base + b.length; p++) {
    list[dest] = b.get(p);
    dest++;
  }
  for (p = a.base; p < a.base + a.length; p++) {
    list[dest] = a.get(p);
    dest++;
  }
};

TimSort.prototype.mergeHi = function (a, b) {
  var p, nextA, nextB;
  var lt = this.lt;
  var dest = b.base + b.length;
  b = b.copy();
  var aList = a.list, bList = b.list;

  dest -= 1;
  var list = this.list;
  list[dest] = a.popright();
  if (a.length === 0 || b.length === 1) {
    return;
  }

  while (true) {
    var aCount = 0;
    var bCount = 0;

    var minGallop = this.minGallop;
    while (aCount < minGallop && bCount < minGallop) {
      nextA = a.last();
      nextB = b.last();
      if (lt(nextB, nextA)) {
        list[--dest] = nextA;
        if (--a.length === 0) {
          return this.finishMergeHi(a, b, dest);
        }
        aCount += 1;
        bCount = 0;
      } else {
        list[--dest] = nextB;
        if (--b.length === 1) {
          return this.finishMergeHi(a, b, dest);
        }
        bCount += 1;
        aCount = 0;
      }
    }

    this.minGallop++;
    while (true) {
      this.minGallop -= this.minGallop > 1;

      nextB = b.last();
      var k = this.gallop(nextB, a, a.length - 1, true);
      aCount = a.length - k;

      for (p = a.base + a.length - 1; p !== a.base + k - 1; p--) {
        dest--;
        list[dest] = aList[p];
      }

      a.length -= aCount;
      if (a.length === 0) { return this.finishMergeHi(a, b, dest); }

      dest--;
      list[dest] = b.popright();
      if (b.length === 1) { return this.finishMergeHi(a, b, dest); }

      nextA = a.last();
      k = this.gallop(nextA, b, b.length - 1, false);
      bCount = b.length - k;

      for (p = b.base + b.length - 1; p !== b.base + k - 1; p--) {
        dest--;
        list[dest] = bList[p];
      }
      b.length -= bCount;

      if (b.length < 2) { return this.finishMergeHi(a, b, dest); }

      dest--;
      list[dest] = a.popright();
      if (a.length === 0) {
        return this.finishMergeHi(a, b, dest);
      }

      if (aCount < this.MIN_GALLOP && bCount < this.MIN_GALLOP) {
        break;
      }
    }
    this.minGallop++;
  }
};

TimSort.prototype.finishMergeHi = function (a, b, dest) {
  var list = this.list;
  for (var p = a.base + a.length - 1; p !== a.base - 1; p--) {
    dest--;
    list[dest] = a.get(p);
  }
  for (p = b.base + b.length - 1; p !== b.base - 1; p--) {
    dest--;
    list[dest] = b.get(p);
  }
};

TimSort.prototype.minrun = function (n) {
  var r = 0;    // becomes 1 if any 1 bits are shifted off
  while (n >= 64) {
      r |= n & 1;
      n >>= 1;
  }
  return n + r;
};

function ListSlice(list, base, length, descending) {
  this.list = list;
  this.base = base;
  this.length = length;
  this.descending = descending;
}

ListSlice.prototype.copy = function () {
  var start = this.base;
  var stop = this.base + this.length;
  return new ListSlice(this.list.slice(start, stop), 0, this.length);
};

ListSlice.prototype.advance = function (n) {
  this.base += n;
  this.length -= n;
};

ListSlice.prototype.get = function (index) {
  return this.list[index];
};

ListSlice.prototype.set = function (index, value) {
  this.list[index] = value;
};

ListSlice.prototype.popleft = function () {
  var result = this.list[this.base];
  this.base += 1;
  this.length -= 1;
  return result;
};

ListSlice.prototype.popright = function () {
  this.length -= 1;
  return this.list[this.base + this.length];
};

ListSlice.prototype.reverse = function () {
  var list = this.list;
  var lo = this.base;
  var hi = lo + this.length - 1;
  while (lo < hi) {
    var listHi = list[hi];
    var listLo = list[lo];
    list[lo] = listHi;
    list[hi] = listLo;
    lo++;
    hi--;
  }
};

ListSlice.prototype.last = function () {
  return this.list[this.base + this.length - 1];
};

ListSlice.prototype.first = function () {
  return this.list[this.base];
};

module.exports = TimSort;<|endoftext|>


<commit_before>var server = require('./app/server'),
    CONFIG = require('config').server;

server.start(CONFIG.port);<commit_msg>Updated to use configuration from yaml file.<commit_after>(function () {
    var CONFIG = require('config'),
        server = require(process.env.HOME + CONFIG.Default.serverRoot + '/app/server');

    server.start(CONFIG.server.port);
}());
<|endoftext|>