<commit_before>/**
 * Dropdown module.
 * @module foundation.dropdown
 * @requires foundation.util.keyboard
 * @requires foundation.util.box
 */
!function($, Foundation){
  'use strict';
  /**
   * Creates a new instance of a dropdown.
   * @class
   * @param {jQuery} element - jQuery object to make into an accordion menu.
   * @param {Object} options - Overrides to the default plugin settings.
   */
  function Dropdown(element, options){
    this.$element = element;
    this.options = $.extend({}, Dropdown.defaults, this.$element.data(), options);
    this._init();

    Foundation.registerPlugin(this, 'Dropdown');
    Foundation.Keyboard.register('Dropdown', {
      'ENTER': 'open',
      'SPACE': 'open',
      'ESCAPE': 'close',
      'TAB': 'tab_forward',
      'SHIFT_TAB': 'tab_backward'
    });
  }

  Dropdown.defaults = {
    /**
     * Amount of time to delay opening a submenu on hover event.
     * @option
     * @example 250
     */
    hoverDelay: 250,
    /**
     * Allow submenus to open on hover events
     * @option
     * @example false
     */
    hover: false,
    /**
     * Don't close dropdown when hovering over dropdown pane
     * @option
     * @example true
     */
    hoverPane: false,
    /**
     * Number of pixels between the dropdown pane and the triggering element on open.
     * @option
     * @example 1
     */
    vOffset: 1,
    /**
     * Number of pixels between the dropdown pane and the triggering element on open.
     * @option
     * @example 1
     */
    hOffset: 1,
    /**
     * Class applied to adjust open position. JS will test and fill this in.
     * @option
     * @example 'top'
     */
    positionClass: '',
    /**
     * Allow the plugin to trap focus to the dropdown pane if opened with keyboard commands.
     * @option
     * @example false
     */
    trapFocus: false,
    /**
     * Allow the plugin to set focus to the first focusable element within the pane, regardless of method of opening.
     * @option
     * @example true
     */
    autoFocus: false,
    /**
     * Allows a click on the body to close the dropdown.
     * @option
     * @example true
     */
    closeOnClick: false
  };
  /**
   * Initializes the plugin by setting/checking options and attributes, adding helper variables, and saving the anchor.
   * @function
   * @private
   */
  Dropdown.prototype._init = function(){
    var $id = this.$element.attr('id');

    this.$anchor = $('[data-toggle="' + $id + '"]') || $('[data-open="' + $id + '"]');
    this.$anchor.attr({
      'aria-controls': $id,
      'data-is-focus': false,
      'data-yeti-box': $id,
      'aria-haspopup': true,
      'aria-expanded': false
      // 'data-resize': $id
    });

    this.options.positionClass = this.getPositionClass();
    this.counter = 4;
    this.usedPositions = [];
    this.$element.attr({
      'aria-hidden': 'true',
      'data-yeti-box': $id,
      'data-resize': $id,
      'aria-labelledby': this.$anchor[0].id || Foundation.GetYoDigits(6, 'dd-anchor')
    });
    this._events();
  };
  /**
   * Helper function to determine current orientation of dropdown pane.
   * @function
   * @returns {String} position - string value of a position class.
   */
  Dropdown.prototype.getPositionClass = function(){
    var position = this.$element[0].className.match(/(top|left|right)/g);
        position = position ? position[0] : '';
    return position;
  };
  /**
   * Adjusts the dropdown panes orientation by adding/removing positioning classes.
   * @function
   * @private
   * @param {String} position - position class to remove.
   */
  Dropdown.prototype._reposition = function(position){
    this.usedPositions.push(position ? position : 'bottom');
    //default, try switching to opposite side
    if(!position && (this.usedPositions.indexOf('top') < 0)){
      this.$element.addClass('top');
    }else if(position === 'top' && (this.usedPositions.indexOf('bottom') < 0)){
      this.$element.removeClass(position);
    }else if(position === 'left' && (this.usedPositions.indexOf('right') < 0)){
      this.$element.removeClass(position)
          .addClass('right');
    }else if(position === 'right' && (this.usedPositions.indexOf('left') < 0)){
      this.$element.removeClass(position)
          .addClass('left');
    }

    //if default change didn't work, try bottom or left first
    else if(!position && (this.usedPositions.indexOf('top') > -1) && (this.usedPositions.indexOf('left') < 0)){
      this.$element.addClass('left');
    }else if(position === 'top' && (this.usedPositions.indexOf('bottom') > -1) && (this.usedPositions.indexOf('left') < 0)){
      this.$element.removeClass(position)
          .addClass('left');
    }else if(position === 'left' && (this.usedPositions.indexOf('right') > -1) && (this.usedPositions.indexOf('bottom') < 0)){
      this.$element.removeClass(position);
    }else if(position === 'right' && (this.usedPositions.indexOf('left') > -1) && (this.usedPositions.indexOf('bottom') < 0)){
      this.$element.removeClass(position);
    }
    //if nothing cleared, set to bottom
    else{
      this.$element.removeClass(position);
    }
    this.classChanged = true;
    this.counter--;
  };
  /**
   * Sets the position and orientation of the dropdown pane, checks for collisions.
   * Recursively calls itself if a collision is detected, with a new position class.
   * @function
   * @private
   */
  Dropdown.prototype._setPosition = function(){
    if(this.$anchor.attr('aria-expanded') === 'false'){ return false; }
    var position = this.getPositionClass(),
        $eleDims = Foundation.Box.GetDimensions(this.$element),
        $anchorDims = Foundation.Box.GetDimensions(this.$anchor),
        _this = this,
        direction = (position === 'left' ? 'left' : ((position === 'right') ? 'left' : 'top')),
        param = (direction === 'top') ? 'height' : 'width',
        offset = (param === 'height') ? this.options.vOffset : this.options.hOffset;

    if(($eleDims.width >= $eleDims.windowDims.width) || (!this.counter && !Foundation.Box.ImNotTouchingYou(this.$element))){
      this.$element.offset(Foundation.Box.GetOffsets(this.$element, this.$anchor, 'center bottom', this.options.vOffset, this.options.hOffset, true)).css({
        'width': $eleDims.windowDims.width - (this.options.hOffset * 2),
        'height': 'auto'
      });
      this.classChanged = true;
      return false;
    }

    this.$element.offset(Foundation.Box.GetOffsets(this.$element, this.$anchor, position, this.options.vOffset, this.options.hOffset));

    while(!Foundation.Box.ImNotTouchingYou(this.$element) && this.counter){
      this._reposition(position);
      this._setPosition();
    }
  };
  /**
   * Adds event listeners to the element utilizing the triggers utility library.
   * @function
   * @private
   */
  Dropdown.prototype._events = function(){
    var _this = this;
    this.$element.on({
      'open.zf.trigger': this.open.bind(this),
      'close.zf.trigger': this.close.bind(this),
      'toggle.zf.trigger': this.toggle.bind(this),
      'resizeme.zf.trigger': this._setPosition.bind(this)
    });

    if(this.options.hover){
      this.$anchor.off('mouseenter.zf.dropdown mouseleave.zf.dropdown')
          .on('mouseenter.zf.dropdown', function(){
            clearTimeout(_this.timeout);
            _this.timeout = setTimeout(function(){
              _this.open();
              _this.$anchor.data('hover', true);
            }, _this.options.hoverDelay);
          }).on('mouseleave.zf.dropdown', function(){
            clearTimeout(_this.timeout);
            _this.timeout = setTimeout(function(){
              _this.close();
              _this.$anchor.data('hover', false);
            }, _this.options.hoverDelay);
          });
      if(this.options.hoverPane){
        this.$element.off('mouseenter.zf.dropdown mouseleave.zf.dropdown')
            .on('mouseenter.zf.dropdown', function(){
              clearTimeout(_this.timeout);
            }).on('mouseleave.zf.dropdown', function(){
              clearTimeout(_this.timeout);
              _this.timeout = setTimeout(function(){
                _this.close();
                _this.$anchor.data('hover', false);
              }, _this.options.hoverDelay);
            });
      }
    }
    this.$anchor.add(this.$element).on('keydown.zf.dropdown', function(e) {

      var $target = $(this),
        visibleFocusableElements = Foundation.Keyboard.findFocusable(_this.$element);

      Foundation.Keyboard.handleKey(e, 'Dropdown', {
        tab_forward: function() {
          if (_this.$element.find(':focus').is(visibleFocusableElements.eq(-1))) { // left modal downwards, setting focus to first element
            if (_this.options.trapFocus) { // if focus shall be trapped
              visibleFocusableElements.eq(0).focus();
              e.preventDefault();
            } else { // if focus is not trapped, close dropdown on focus out
              _this.close();
            }
          }
        },
        tab_backward: function() {
          if (_this.$element.find(':focus').is(visibleFocusableElements.eq(0)) || _this.$element.is(':focus')) { // left modal upwards, setting focus to last element
            if (_this.options.trapFocus) { // if focus shall be trapped
              visibleFocusableElements.eq(-1).focus();
              e.preventDefault();
            } else { // if focus is not trapped, close dropdown on focus out
              _this.close();
            }
          }
        },
        open: function() {
          if ($target.is(_this.$anchor)) {
            _this.open();
            _this.$element.attr('tabindex', -1).focus();
            e.preventDefault();
          }
        },
        close: function() {
          _this.close();
          _this.$anchor.focus();
        }
      });
    });
  };
  /**
   * Adds an event handler to the body to close any dropdowns on a click.
   * @function
   * @private
   */
  Dropdown.prototype._addBodyHandler = function(){
     var $body = $(document.body).not(this.$element),
         _this = this;
     $body.off('click.zf.dropdown')
          .on('click.zf.dropdown', function(e){
            if(_this.$anchor.is(e.target) || _this.$anchor.find(e.target).length) {
              return;
            }
            if(_this.$element.find(e.target).length) {
              return;
            }
            _this.close();
            $body.off('click.zf.dropdown');
          });
  };
  /**
   * Opens the dropdown pane, and fires a bubbling event to close other dropdowns.
   * @function
   * @fires Dropdown#closeme
   * @fires Dropdown#show
   */
  Dropdown.prototype.open = function(){
    // var _this = this;
    /**
     * Fires to close other open dropdowns
     * @event Dropdown#closeme
     */
    this.$element.trigger('closeme.zf.dropdown', this.$element.attr('id'));
    this.$anchor.addClass('hover')
        .attr({'aria-expanded': true});
    // this.$element/*.show()*/;
    this._setPosition();
    this.$element.addClass('is-open')
        .attr({'aria-hidden': false});

    if(this.options.autoFocus){
      var $focusable = Foundation.Keyboard.findFocusable(this.$element);
      if($focusable.length){
        $focusable.eq(0).focus();
      }
    }

    if(this.options.closeOnClick){ this._addBodyHandler(); }

    /**
     * Fires once the dropdown is visible.
     * @event Dropdown#show
     */
     this.$element.trigger('show.zf.dropdown', [this.$element]);
    //why does this not work correctly for this plugin?
    // Foundation.reflow(this.$element, 'dropdown');
    // Foundation._reflow(this.$element.attr('data-dropdown'));
  };

  /**
   * Closes the open dropdown pane.
   * @function
   * @fires Dropdown#hide
   */
  Dropdown.prototype.close = function(){
    if(!this.$element.hasClass('is-open')){
      return false;
    }
    this.$element.removeClass('is-open')
        .attr({'aria-hidden': true});

    this.$anchor.removeClass('hover')
        .attr('aria-expanded', false);

    if(this.classChanged){
      var curPositionClass = this.getPositionClass();
      if(curPositionClass){
        this.$element.removeClass(curPositionClass);
      }
      this.$element.addClass(this.options.positionClass)
          /*.hide()*/.css({height: '', width: ''});
      this.classChanged = false;
      this.counter = 4;
      this.usedPositions.length = 0;
    }
    this.$element.trigger('hide.zf.dropdown', [this.$element]);
    // Foundation.reflow(this.$element, 'dropdown');
  };
  /**
   * Toggles the dropdown pane's visibility.
   * @function
   */
  Dropdown.prototype.toggle = function(){
    if(this.$element.hasClass('is-open')){
      if(this.$anchor.data('hover')) return;
      this.close();
    }else{
      this.open();
    }
  };
  /**
   * Destroys the dropdown.
   * @function
   */
  Dropdown.prototype.destroy = function(){
    this.$element.off('.zf.trigger').hide();
    this.$anchor.off('.zf.dropdown');

    Foundation.unregisterPlugin(this);
  };

  Foundation.plugin(Dropdown, 'Dropdown');
}(jQuery, window.Foundation);
<commit_msg>Improved Dropdown docs<commit_after>/**
 * Dropdown module.
 * @module foundation.dropdown
 * @requires foundation.util.keyboard
 * @requires foundation.util.box
 * @requires foundation.util.triggers
 */
!function($, Foundation){
  'use strict';
  /**
   * Creates a new instance of a dropdown.
   * @class
   * @param {jQuery} element - jQuery object to make into a dropdown menu.
   *        Object should be of the dropdown panel, rather than its anchor.
   * @param {Object} options - Overrides to the default plugin settings.
   */
  function Dropdown(element, options){
    this.$element = element;
    this.options = $.extend({}, Dropdown.defaults, this.$element.data(), options);
    this._init();

    Foundation.registerPlugin(this, 'Dropdown');
    Foundation.Keyboard.register('Dropdown', {
      'ENTER': 'open',
      'SPACE': 'open',
      'ESCAPE': 'close',
      'TAB': 'tab_forward',
      'SHIFT_TAB': 'tab_backward'
    });
  }

  Dropdown.defaults = {
    /**
     * Amount of time to delay opening a submenu on hover event.
     * @option
     * @example 250
     */
    hoverDelay: 250,
    /**
     * Allow submenus to open on hover events
     * @option
     * @example false
     */
    hover: false,
    /**
     * Don't close dropdown when hovering over dropdown pane
     * @option
     * @example true
     */
    hoverPane: false,
    /**
     * Number of pixels between the dropdown pane and the triggering element on open.
     * @option
     * @example 1
     */
    vOffset: 1,
    /**
     * Number of pixels between the dropdown pane and the triggering element on open.
     * @option
     * @example 1
     */
    hOffset: 1,
    /**
     * Class applied to adjust open position. JS will test and fill this in.
     * @option
     * @example 'top'
     */
    positionClass: '',
    /**
     * Allow the plugin to trap focus to the dropdown pane if opened with keyboard commands.
     * @option
     * @example false
     */
    trapFocus: false,
    /**
     * Allow the plugin to set focus to the first focusable element within the pane, regardless of method of opening.
     * @option
     * @example true
     */
    autoFocus: false,
    /**
     * Allows a click on the body to close the dropdown.
     * @option
     * @example true
     */
    closeOnClick: false
  };
  /**
   * Initializes the plugin by setting/checking options and attributes, adding helper variables, and saving the anchor.
   * @function
   * @private
   */
  Dropdown.prototype._init = function(){
    var $id = this.$element.attr('id');

    this.$anchor = $('[data-toggle="' + $id + '"]') || $('[data-open="' + $id + '"]');
    this.$anchor.attr({
      'aria-controls': $id,
      'data-is-focus': false,
      'data-yeti-box': $id,
      'aria-haspopup': true,
      'aria-expanded': false
      // 'data-resize': $id
    });

    this.options.positionClass = this.getPositionClass();
    this.counter = 4;
    this.usedPositions = [];
    this.$element.attr({
      'aria-hidden': 'true',
      'data-yeti-box': $id,
      'data-resize': $id,
      'aria-labelledby': this.$anchor[0].id || Foundation.GetYoDigits(6, 'dd-anchor')
    });
    this._events();
  };
  /**
   * Helper function to determine current orientation of dropdown pane.
   * @function
   * @returns {String} position - string value of a position class.
   */
  Dropdown.prototype.getPositionClass = function(){
    var position = this.$element[0].className.match(/(top|left|right)/g);
        position = position ? position[0] : '';
    return position;
  };
  /**
   * Adjusts the dropdown panes orientation by adding/removing positioning classes.
   * @function
   * @private
   * @param {String} position - position class to remove.
   */
  Dropdown.prototype._reposition = function(position){
    this.usedPositions.push(position ? position : 'bottom');
    //default, try switching to opposite side
    if(!position && (this.usedPositions.indexOf('top') < 0)){
      this.$element.addClass('top');
    }else if(position === 'top' && (this.usedPositions.indexOf('bottom') < 0)){
      this.$element.removeClass(position);
    }else if(position === 'left' && (this.usedPositions.indexOf('right') < 0)){
      this.$element.removeClass(position)
          .addClass('right');
    }else if(position === 'right' && (this.usedPositions.indexOf('left') < 0)){
      this.$element.removeClass(position)
          .addClass('left');
    }

    //if default change didn't work, try bottom or left first
    else if(!position && (this.usedPositions.indexOf('top') > -1) && (this.usedPositions.indexOf('left') < 0)){
      this.$element.addClass('left');
    }else if(position === 'top' && (this.usedPositions.indexOf('bottom') > -1) && (this.usedPositions.indexOf('left') < 0)){
      this.$element.removeClass(position)
          .addClass('left');
    }else if(position === 'left' && (this.usedPositions.indexOf('right') > -1) && (this.usedPositions.indexOf('bottom') < 0)){
      this.$element.removeClass(position);
    }else if(position === 'right' && (this.usedPositions.indexOf('left') > -1) && (this.usedPositions.indexOf('bottom') < 0)){
      this.$element.removeClass(position);
    }
    //if nothing cleared, set to bottom
    else{
      this.$element.removeClass(position);
    }
    this.classChanged = true;
    this.counter--;
  };
  /**
   * Sets the position and orientation of the dropdown pane, checks for collisions.
   * Recursively calls itself if a collision is detected, with a new position class.
   * @function
   * @private
   */
  Dropdown.prototype._setPosition = function(){
    if(this.$anchor.attr('aria-expanded') === 'false'){ return false; }
    var position = this.getPositionClass(),
        $eleDims = Foundation.Box.GetDimensions(this.$element),
        $anchorDims = Foundation.Box.GetDimensions(this.$anchor),
        _this = this,
        direction = (position === 'left' ? 'left' : ((position === 'right') ? 'left' : 'top')),
        param = (direction === 'top') ? 'height' : 'width',
        offset = (param === 'height') ? this.options.vOffset : this.options.hOffset;

    if(($eleDims.width >= $eleDims.windowDims.width) || (!this.counter && !Foundation.Box.ImNotTouchingYou(this.$element))){
      this.$element.offset(Foundation.Box.GetOffsets(this.$element, this.$anchor, 'center bottom', this.options.vOffset, this.options.hOffset, true)).css({
        'width': $eleDims.windowDims.width - (this.options.hOffset * 2),
        'height': 'auto'
      });
      this.classChanged = true;
      return false;
    }

    this.$element.offset(Foundation.Box.GetOffsets(this.$element, this.$anchor, position, this.options.vOffset, this.options.hOffset));

    while(!Foundation.Box.ImNotTouchingYou(this.$element) && this.counter){
      this._reposition(position);
      this._setPosition();
    }
  };
  /**
   * Adds event listeners to the element utilizing the triggers utility library.
   * @function
   * @private
   */
  Dropdown.prototype._events = function(){
    var _this = this;
    this.$element.on({
      'open.zf.trigger': this.open.bind(this),
      'close.zf.trigger': this.close.bind(this),
      'toggle.zf.trigger': this.toggle.bind(this),
      'resizeme.zf.trigger': this._setPosition.bind(this)
    });

    if(this.options.hover){
      this.$anchor.off('mouseenter.zf.dropdown mouseleave.zf.dropdown')
          .on('mouseenter.zf.dropdown', function(){
            clearTimeout(_this.timeout);
            _this.timeout = setTimeout(function(){
              _this.open();
              _this.$anchor.data('hover', true);
            }, _this.options.hoverDelay);
          }).on('mouseleave.zf.dropdown', function(){
            clearTimeout(_this.timeout);
            _this.timeout = setTimeout(function(){
              _this.close();
              _this.$anchor.data('hover', false);
            }, _this.options.hoverDelay);
          });
      if(this.options.hoverPane){
        this.$element.off('mouseenter.zf.dropdown mouseleave.zf.dropdown')
            .on('mouseenter.zf.dropdown', function(){
              clearTimeout(_this.timeout);
            }).on('mouseleave.zf.dropdown', function(){
              clearTimeout(_this.timeout);
              _this.timeout = setTimeout(function(){
                _this.close();
                _this.$anchor.data('hover', false);
              }, _this.options.hoverDelay);
            });
      }
    }
    this.$anchor.add(this.$element).on('keydown.zf.dropdown', function(e) {

      var $target = $(this),
        visibleFocusableElements = Foundation.Keyboard.findFocusable(_this.$element);

      Foundation.Keyboard.handleKey(e, 'Dropdown', {
        tab_forward: function() {
          if (_this.$element.find(':focus').is(visibleFocusableElements.eq(-1))) { // left modal downwards, setting focus to first element
            if (_this.options.trapFocus) { // if focus shall be trapped
              visibleFocusableElements.eq(0).focus();
              e.preventDefault();
            } else { // if focus is not trapped, close dropdown on focus out
              _this.close();
            }
          }
        },
        tab_backward: function() {
          if (_this.$element.find(':focus').is(visibleFocusableElements.eq(0)) || _this.$element.is(':focus')) { // left modal upwards, setting focus to last element
            if (_this.options.trapFocus) { // if focus shall be trapped
              visibleFocusableElements.eq(-1).focus();
              e.preventDefault();
            } else { // if focus is not trapped, close dropdown on focus out
              _this.close();
            }
          }
        },
        open: function() {
          if ($target.is(_this.$anchor)) {
            _this.open();
            _this.$element.attr('tabindex', -1).focus();
            e.preventDefault();
          }
        },
        close: function() {
          _this.close();
          _this.$anchor.focus();
        }
      });
    });
  };
  /**
   * Adds an event handler to the body to close any dropdowns on a click.
   * @function
   * @private
   */
  Dropdown.prototype._addBodyHandler = function(){
     var $body = $(document.body).not(this.$element),
         _this = this;
     $body.off('click.zf.dropdown')
          .on('click.zf.dropdown', function(e){
            if(_this.$anchor.is(e.target) || _this.$anchor.find(e.target).length) {
              return;
            }
            if(_this.$element.find(e.target).length) {
              return;
            }
            _this.close();
            $body.off('click.zf.dropdown');
          });
  };
  /**
   * Opens the dropdown pane, and fires a bubbling event to close other dropdowns.
   * @function
   * @fires Dropdown#closeme
   * @fires Dropdown#show
   */
  Dropdown.prototype.open = function(){
    // var _this = this;
    /**
     * Fires to close other open dropdowns
     * @event Dropdown#closeme
     */
    this.$element.trigger('closeme.zf.dropdown', this.$element.attr('id'));
    this.$anchor.addClass('hover')
        .attr({'aria-expanded': true});
    // this.$element/*.show()*/;
    this._setPosition();
    this.$element.addClass('is-open')
        .attr({'aria-hidden': false});

    if(this.options.autoFocus){
      var $focusable = Foundation.Keyboard.findFocusable(this.$element);
      if($focusable.length){
        $focusable.eq(0).focus();
      }
    }

    if(this.options.closeOnClick){ this._addBodyHandler(); }

    /**
     * Fires once the dropdown is visible.
     * @event Dropdown#show
     */
     this.$element.trigger('show.zf.dropdown', [this.$element]);
    //why does this not work correctly for this plugin?
    // Foundation.reflow(this.$element, 'dropdown');
    // Foundation._reflow(this.$element.attr('data-dropdown'));
  };

  /**
   * Closes the open dropdown pane.
   * @function
   * @fires Dropdown#hide
   */
  Dropdown.prototype.close = function(){
    if(!this.$element.hasClass('is-open')){
      return false;
    }
    this.$element.removeClass('is-open')
        .attr({'aria-hidden': true});

    this.$anchor.removeClass('hover')
        .attr('aria-expanded', false);

    if(this.classChanged){
      var curPositionClass = this.getPositionClass();
      if(curPositionClass){
        this.$element.removeClass(curPositionClass);
      }
      this.$element.addClass(this.options.positionClass)
          /*.hide()*/.css({height: '', width: ''});
      this.classChanged = false;
      this.counter = 4;
      this.usedPositions.length = 0;
    }
    this.$element.trigger('hide.zf.dropdown', [this.$element]);
    // Foundation.reflow(this.$element, 'dropdown');
  };
  /**
   * Toggles the dropdown pane's visibility.
   * @function
   */
  Dropdown.prototype.toggle = function(){
    if(this.$element.hasClass('is-open')){
      if(this.$anchor.data('hover')) return;
      this.close();
    }else{
      this.open();
    }
  };
  /**
   * Destroys the dropdown.
   * @function
   */
  Dropdown.prototype.destroy = function(){
    this.$element.off('.zf.trigger').hide();
    this.$anchor.off('.zf.dropdown');

    Foundation.unregisterPlugin(this);
  };

  Foundation.plugin(Dropdown, 'Dropdown');
}(jQuery, window.Foundation);
<|endoftext|>


<commit_before>/**
 * @license jqGrid Polish Translation
 * Łukasz Schab lukasz@freetree.pl
 * http://FreeTree.pl
 *
 * Updated names, abbreviations, currency and date/time formats for Polish norms (also corresponding with CLDR v21.0.1 --> http://cldr.unicode.org/index)
 * Tomasz Pęczek tpeczek@gmail.com
 * http://tpeczek.blogspot.com; http://tpeczek.codeplex.com
 *
 * Dual licensed under the MIT and GPL licenses:
 * http://www.opensource.org/licenses/mit-license.php
 * http://www.gnu.org/licenses/gpl.html
**/

/*jslint white: true */
/*global jQuery */
(function (factory) {
	"use strict";
	if (typeof define === "function" && define.amd) {
		// AMD. Register as an anonymous module.
		define(["jquery"], factory);
	} else if (typeof exports === "object") {
		// Node/CommonJS
		factory(require("jquery"));
	} else {
		// Browser globals
		factory(jQuery);
	}
}(function ($) {
"use strict";
var locInfo = {
	isRTL: false,
	defaults: {
		recordtext: "Pokaż {0} - {1} z {2}",
		emptyrecords: "Brak rekordów do pokazania",
		loadtext: "Ładowanie...",
		pgtext: "Strona {0} z {1}",
		pgfirst: "First Page",
		pglast: "Last Page",
		pgnext: "Next Page",
		pgprev: "Previous Page",
		pgrecs: "Records per Page",
		showhide: "Toggle Expand Collapse Grid",
		savetext: "Trwa zapisywanie..."
	},
	search: {
		caption: "Wyszukiwanie...",
		Find: "Szukaj",
		Reset: "Czyść",
		odata: [
			{ oper: "eq", text: "dokładnie" },
			{ oper: "ne", text: "różne od" },
			{ oper: "lt", text: "mniejsze od" },
			{ oper: "le", text: "mniejsze lub równe" },
			{ oper: "gt", text: "większe od" },
			{ oper: "ge", text: "większe lub równe" },
			{ oper: "bw", text: "zaczyna się od" },
			{ oper: "bn", text: "nie zaczyna się od" },
			{ oper: "in", text: "jest w" },
			{ oper: "ni", text: "nie jest w" },
			{ oper: "ew", text: "kończy się na" },
			{ oper: "en", text: "nie kończy się na" },
			{ oper: "cn", text: "zawiera" },
			{ oper: "nc", text: "nie zawiera" },
			{ oper: "nu", text: "is null" },
			{ oper: "nn", text: "is not null" }
		],
		groupOps: [
			{ op: "AND", text: "oraz" },
			{ op: "OR",  text: "lub" }
		],
		addGroupTitle: "Add subgroup",
		deleteGroupTitle: "Delete group",
		addRuleTitle: "Add rule",
		deleteRuleTitle: "Delete rule",
		operandTitle: "Click to select search operation.",
		resetTitle: "Reset Search Value"
	},
	edit: {
		addCaption: "Dodaj rekord",
		editCaption: "Edytuj rekord",
		bSubmit: "Zapisz",
		bCancel: "Anuluj",
		bClose: "Zamknij",
		saveData: "Dane zostały zmienione! Zapisać zmiany?",
		bYes: "Tak",
		bNo: "Nie",
		bExit: "Anuluj",
		msg: {
			required: "Pole jest wymagane",
			number: "Proszę wpisać poprawną liczbę",
			minValue: "wartość musi być większa lub równa od",
			maxValue: "wartość musi być mniejsza lub równa od",
			email: "nie jest poprawnym adresem e-mail",
			integer: "Proszę wpisać poprawną liczbę",
			date: "Proszę podaj poprawną datę",
			url: "jest niewłaściwym adresem URL. Pamiętaj o prefiksie ('http://' lub 'https://')",
			nodefined: " niezdefiniowane!",
			novalue: " wymagana jest wartość zwracana!",
			customarray: "Funkcja niestandardowa powinna zwracać tablicę!",
			customfcheck: "Funkcja niestandardowa powinna być obecna w przypadku niestandardowego sprawdzania!"
		}
	},
	view: {
		caption: "Pokaż rekord",
		bClose: "Zamknij"
	},
	del: {
		caption: "Usuń",
		msg: "Czy usunąć wybrany rekord(y)?",
		bSubmit: "Usuń",
		bCancel: "Anuluj"
	},
	nav: {
		edittext: "",
		edittitle: "Edytuj wybrany wiersz",
		addtext: "",
		addtitle: "Dodaj nowy wiersz",
		deltext: "",
		deltitle: "Usuń wybrany wiersz",
		searchtext: "",
		searchtitle: "Wyszukaj rekord",
		refreshtext: "",
		refreshtitle: "Przeładuj",
		alertcap: "Uwaga",
		alerttext: "Proszę wybrać wiersz",
		viewtext: "",
		viewtitle: "Pokaż wybrany wiersz",
		savetext: "",
		savetitle: "Save row",
		canceltext: "",
		canceltitle: "Cancel row editing"
	},
	col: {
		caption: "Pokaż/Ukryj kolumny",
		bSubmit: "Zatwierdź",
		bCancel: "Anuluj"
	},
	errors: {
		errcap: "Błąd",
		nourl: "Brak adresu url",
		norecords: "Brak danych",
		model: "Długość colNames <> colModel!"
	},
	formatter: {
		integer: { thousandsSeparator: " ", defaultValue: "0" },
		number: { decimalSeparator: ",", thousandsSeparator: " ", decimalPlaces: 2, defaultValue: "0,00" },
		currency: { decimalSeparator: ",", thousandsSeparator: " ", decimalPlaces: 2, prefix: "", suffix: " zł", defaultValue: "0,00" },
		date: {
			dayNames:   [
				"niedz.", "pon.", "wt.", "śr.", "czw.", "pt.", "sob.",
				"niedziela", "poniedziałek", "wtorek", "środa", "czwartek", "piątek", "sobota"
			],
			monthNames: [
				"sty", "lut", "mar", "kwi", "maj", "cze", "lip", "sie", "wrz", "paź", "lis", "gru",
				"styczeń", "luty", "marzec", "kwiecień", "maj", "czerwiec", "lipiec", "sierpień", "wrzesień", "październik", "listopad", "grudzień"
				],
			AmPm: ["", "", "", ""],
			S: function () { return ""; },
			srcformat: "Y-m-d",
			newformat: "d.m.Y",
			masks: {
				ShortDate: "d.m.y",
				LongDate: "l, j F Y",
				FullDateTime: "l, j F Y H:i:s",
				MonthDay: "j F",
				ShortTime: "H:i",
				LongTime: "H:i:s",
				YearMonth: "F Y"
			}
		}
	}
};
$.jgrid = $.jgrid || {};
$.extend(true, $.jgrid, {
	defaults: {
		locale: "pl"
	},
	locales: {
		// In general the property name is free, but it's recommended to use the names based on
		// http://www.iana.org/assignments/language-subtag-registry/language-subtag-registry
		// http://rishida.net/utils/subtags/ and RFC 5646. See Appendix A of RFC 5646 for examples.
		// One can use the lang attribute to specify language tags in HTML, and the xml:lang attribute for XML
		// if it exists. See http://www.w3.org/International/articles/language-tags/#extlang
		pl: $.extend({}, locInfo, { name: "polski", nameEnglish: "Polish" }),
		"pl-PL": $.extend({}, locInfo, { name: "polski (Polska)", nameEnglish: "Polish (Poland)" })
	}
});
}));
<commit_msg>Update grid.locale-pl.js<commit_after>/**
 * @license jqGrid Polish Translation
 * Łukasz Schab lukasz@freetree.pl
 * http://FreeTree.pl
 *
 * Updated names, abbreviations, currency and date/time formats for Polish norms (also corresponding with CLDR v21.0.1 --> http://cldr.unicode.org/index)
 * Tomasz Pęczek tpeczek@gmail.com
 * http://tpeczek.blogspot.com; http://tpeczek.codeplex.com
 *
 * 22-01-2015: Updated locale strings
 * Robert 'Wooya' Gaudyn <wogaew@wp.pl>
 *
 * Dual licensed under the MIT and GPL licenses:
 * http://www.opensource.org/licenses/mit-license.php
 * http://www.gnu.org/licenses/gpl.html
**/

/*jslint white: true */
/*global jQuery */
(function (factory) {
	"use strict";
	if (typeof define === "function" && define.amd) {
		// AMD. Register as an anonymous module.
		define(["jquery"], factory);
	} else if (typeof exports === "object") {
		// Node/CommonJS
		factory(require("jquery"));
	} else {
		// Browser globals
		factory(jQuery);
	}
}(function ($) {
"use strict";
var locInfo = {
	isRTL: false,
	defaults: {
		recordtext: "Pokaż {0} - {1} z {2}",
		emptyrecords: "Brak rekordów do pokazania",
		loadtext: "Ładowanie...",
		pgtext: "Strona {0} z {1}",
		pgfirst: "Pierwsza strona",
		pglast: "Ostatnia strona",
		pgnext: "Nasętpna strona",
		pgprev: "Poprzednia strona",
		pgrecs: "Rekordów na stronę",
		showhide: "Przełącz zwinięcie/rozwinięcie tabeli",
		savetext: "Trwa zapisywanie..."
	},
	search: {
		caption: "Wyszukiwanie...",
		Find: "Szukaj",
		Reset: "Czyść",
		odata: [
			{ oper: "eq", text: "dokładnie" },
			{ oper: "ne", text: "różne od" },
			{ oper: "lt", text: "mniejsze od" },
			{ oper: "le", text: "mniejsze lub równe" },
			{ oper: "gt", text: "większe od" },
			{ oper: "ge", text: "większe lub równe" },
			{ oper: "bw", text: "zaczyna się od" },
			{ oper: "bn", text: "nie zaczyna się od" },
			{ oper: "in", text: "jest w" },
			{ oper: "ni", text: "nie jest w" },
			{ oper: "ew", text: "kończy się na" },
			{ oper: "en", text: "nie kończy się na" },
			{ oper: "cn", text: "zawiera" },
			{ oper: "nc", text: "nie zawiera" },
			{ oper: "nu", text: "jest null" },
			{ oper: "nn", text: "nie jest null" }
		],
		groupOps: [
			{ op: "AND", text: "oraz" },
			{ op: "OR",  text: "lub" }
		],
		addGroupTitle: "Dodaj podgrupę",
		deleteGroupTitle: "Usuń grupę",
		addRuleTitle: "Dodaj regułę",
		deleteRuleTitle: "Usuń regułę",
		operandTitle: "Kliknij, aby wybrać operację wyszukiwania.",
		resetTitle: "Zresetuj wartość wyszukiwania"
	},
	edit: {
		addCaption: "Dodaj rekord",
		editCaption: "Edytuj rekord",
		bSubmit: "Zapisz",
		bCancel: "Anuluj",
		bClose: "Zamknij",
		saveData: "Dane zostały zmienione! Zapisać zmiany?",
		bYes: "Tak",
		bNo: "Nie",
		bExit: "Anuluj",
		msg: {
			required: "Pole jest wymagane",
			number: "Proszę wpisać poprawną liczbę",
			minValue: "Wartość musi być większa lub równa od",
			maxValue: "Wartość musi być mniejsza lub równa od",
			email: "nie jest poprawnym adresem e-mail",
			integer: "Proszę wpisać poprawną liczbę",
			date: "Proszę podaj poprawną datę",
			url: "jest niewłaściwym adresem URL. Pamiętaj o prefiksie ('http://' lub 'https://')",
			nodefined: " niezdefiniowane!",
			novalue: " wymagana jest wartość zwracana!",
			customarray: "Funkcja niestandardowa powinna zwracać tablicę!",
			customfcheck: "Funkcja niestandardowa powinna być obecna w przypadku niestandardowego sprawdzania!"
		}
	},
	view: {
		caption: "Pokaż rekord",
		bClose: "Zamknij"
	},
	del: {
		caption: "Usuń",
		msg: "Czy usunąć wybrany rekord(y)?",
		bSubmit: "Usuń",
		bCancel: "Anuluj"
	},
	nav: {
		edittext: "",
		edittitle: "Edytuj wybrany wiersz",
		addtext: "",
		addtitle: "Dodaj nowy wiersz",
		deltext: "",
		deltitle: "Usuń wybrany wiersz",
		searchtext: "",
		searchtitle: "Wyszukaj rekord",
		refreshtext: "",
		refreshtitle: "Przeładuj",
		alertcap: "Uwaga",
		alerttext: "Proszę wybrać wiersz",
		viewtext: "",
		viewtitle: "Pokaż wybrany wiersz",
		savetext: "",
		savetitle: "Zapisz wiersz",
		canceltext: "",
		canceltitle: "Anuluj edycję wiersza"
	},
	col: {
		caption: "Pokaż/Ukryj kolumny",
		bSubmit: "Zatwierdź",
		bCancel: "Anuluj"
	},
	errors: {
		errcap: "Błąd",
		nourl: "Brak adresu url",
		norecords: "Brak danych",
		model: "Długość colNames <> colModel!"
	},
	formatter: {
		integer: { thousandsSeparator: " ", defaultValue: "0" },
		number: { decimalSeparator: ",", thousandsSeparator: " ", decimalPlaces: 2, defaultValue: "0,00" },
		currency: { decimalSeparator: ",", thousandsSeparator: " ", decimalPlaces: 2, prefix: "", suffix: " zł", defaultValue: "0,00" },
		date: {
			dayNames:   [
				"niedz.", "pon.", "wt.", "śr.", "czw.", "pt.", "sob.",
				"niedziela", "poniedziałek", "wtorek", "środa", "czwartek", "piątek", "sobota"
			],
			monthNames: [
				"sty", "lut", "mar", "kwi", "maj", "cze", "lip", "sie", "wrz", "paź", "lis", "gru",
				"styczeń", "luty", "marzec", "kwiecień", "maj", "czerwiec", "lipiec", "sierpień", "wrzesień", "październik", "listopad", "grudzień"
				],
			AmPm: ["", "", "", ""],
			S: function () { return ""; },
			srcformat: "Y-m-d",
			newformat: "d.m.Y",
			masks: {
				ShortDate: "d.m.y",
				LongDate: "l, j F Y",
				FullDateTime: "l, j F Y H:i:s",
				MonthDay: "j F",
				ShortTime: "H:i",
				LongTime: "H:i:s",
				YearMonth: "F Y"
			}
		}
	}
};
$.jgrid = $.jgrid || {};
$.extend(true, $.jgrid, {
	defaults: {
		locale: "pl"
	},
	locales: {
		// In general the property name is free, but it's recommended to use the names based on
		// http://www.iana.org/assignments/language-subtag-registry/language-subtag-registry
		// http://rishida.net/utils/subtags/ and RFC 5646. See Appendix A of RFC 5646 for examples.
		// One can use the lang attribute to specify language tags in HTML, and the xml:lang attribute for XML
		// if it exists. See http://www.w3.org/International/articles/language-tags/#extlang
		pl: $.extend({}, locInfo, { name: "polski", nameEnglish: "Polish" }),
		"pl-PL": $.extend({}, locInfo, { name: "polski (Polska)", nameEnglish: "Polish (Poland)" })
	}
});
}));
<|endoftext|>


<commit_before>var lastTrack = "";

function updateNowPlaying() {
	var newTrack = $(".active.music > .fnn-title").text();

	if (newTrack != lastTrack) {
		var indexOfSeperator = newTrack.indexOf("-");
		var artist = newTrack.substring(0, indexOfSeperator).trim();
		var song = newTrack.substring(indexOfSeperator+1, newTrack.length);

		chrome.runtime.sendMessage({type: 'validate', artist: artist, track: song}, function(response) {
		// on success send nowPlaying song
			var duration = 180;
		     if (response != false) {
		        var song = response;
		        chrome.runtime.sendMessage({type: 'nowPlaying', artist: song.artist, track: song.track, duration: duration});
		     }
		     // on failure send nowPlaying 'unknown song'
		     else {
		        chrome.runtime.sendMessage({type: 'nowPlaying', duration: duration});
		     }
		     lastTrack = newTrack;
		});
	};
}

var addListener = function() {
		$("#live").live("DOMSubtreeModified", function(e) {
	    	if ($(".active.music").length > 0)
	    	{
		    	setTimeout(updateNowPlaying, 500);
			}
		});
}

$(function() {
    $(window).unload(function() {
		chrome.runtime.sendMessage({type: 'reset'});
		return true;
    });

});

chrome.runtime.onMessage.addListener(
   function(request, sender, sendResponse) {
         switch(request.type) {

             // background calls this to see if the script is already injected
             case 'ping':
                 sendResponse(true);
                 break;
         }
   }
);

addListener();
<commit_msg>added comments, cleaning up formatting<commit_after>var lastTrack = "";

function updateNowPlaying() {
	var newTrack = $(".active.music > .fnn-title").text();

	if (newTrack != lastTrack) {
		var indexOfSeperator = newTrack.indexOf("-");
		var artist = newTrack.substring(0, indexOfSeperator).trim();
		var song = newTrack.substring(indexOfSeperator+1, newTrack.length);

		chrome.runtime.sendMessage({type: 'validate', artist: artist, track: song}, function(response) {
			 var duration = 180; //no duration information available in radio.nrk.no
		     if (response != false) {
		        var song = response;
		        chrome.runtime.sendMessage({type: 'nowPlaying', artist: song.artist, track: song.track, duration: duration});
		     }
		     else {
		        chrome.runtime.sendMessage({type: 'nowPlaying', duration: duration});
		     }
		     lastTrack = newTrack;
		});
	};
}

var addListener = function() {
	$("#live").live("DOMSubtreeModified", function(e) {
    	if ($(".active.music").length > 0)
    	{
	    	setTimeout(updateNowPlaying, 500);
		}
	});
}

$(function() {
    $(window).unload(function() {
		chrome.runtime.sendMessage({type: 'reset'});
		return true;
    });
});

chrome.runtime.onMessage.addListener(
   function(request, sender, sendResponse) {
         switch(request.type) {
             case 'ping':
                 sendResponse(true);
                 break;
         }
   }
);

addListener();<|endoftext|>


<commit_before>/*
* jQuery Mobile Framework : "popup" plugin
* Copyright (c) jQuery Project
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*/

(function($, undefined) {

$.widget("mobile.popup", $.mobile.widget, {
	options: {
		theme: null,
		overlayTheme: null,
		shadow: true,
		corners: true,
		fade: true,
		transition: $.mobile.defaultDialogTransition,
		initSelector: ":jqmData(role='popup')"
	},

	_create: function() {
		var ui = {
					screen    : "#ui-popup-screen",
					container : "#ui-popup-container"
				},
				proto = $(
"
" +
"

" +
"

" +
"
"
),
				thisPage = (this.element.closest(".ui-page") || $("body")),
				self = this;

		// Assign the relevant parts of the proto
		for (var key in ui)
			ui[key] = proto.find(ui[key]).removeAttr("id");

		// Apply the proto
		thisPage.append(ui.screen);
		ui.container.insertAfter(ui.screen);
		ui.container.append(this.element);

		// Define instance variables
		$.extend (this, {
			_ui     : ui,
			_isOpen : false
		});

		$.each (this.options, function(key) {
			self._setOption(key, self.options[key], true);
		});

		ui.screen.bind("vclick", function(e) {
			self.close();
		});
	},

	_setTheme: function(dst, theme, unconditional) {
		var classes = (dst.attr("class") || "").split(" "),
		    alreadyAdded = true,
		    currentTheme = null,
			matches;

		while (classes.length > 0) {
			currentTheme = classes.pop();
			matches = currentTheme.match(/^ui-body-([a-z])$/);
			if (matches && matches.length > 1) {
				currentTheme = matches[1];
				break;
			}
			else
				currentTheme = null;
		}

		if (theme !== currentTheme || unconditional) {
			dst.removeClass("ui-body-" + currentTheme);
			if (theme !== null)
				dst.addClass("ui-body-" + theme);
		}
	},

	_set_theme: function(value, unconditional) {
		if (value === null)
			value = "";

		if (value.match(/^[a-z]$/) || value === "") {
			this._setTheme(this.element, value, unconditional);
		}
	},

	_set_overlayTheme: function(value, unconditional) {
		if (value === null)
			value = "";
		if (value.match(/^[a-z]$/) || value === "") {
			this._setTheme(this._ui.container, value, unconditional);
			// The screen must always have some kind of background for fade to work, so, if the theme is being unset,
			// set the background to "a".
			this._setTheme(this._ui.screen, (value === "" ? "a" : value), unconditional);
		}
		else
			console.log("Warning: " + value + " is not a valid overlay theme! Please specify a single letter a-z or an empty string!");
	},

	_set_shadow: function(value, unconditional) {
		value = this._parseBoolean(value);
		if (this._ui.container.hasClass("ui-overlay-shadow") != value || unconditional)
			this._ui.container[value ? "addClass" : "removeClass"]("ui-overlay-shadow");
	},

	_set_corners: function(value, unconditional) {
		value = this._parseBoolean(value);
		if (this._ui.container.hasClass("ui-corner-all") != value || unconditional)
			this._ui.container[value ? "addClass" : "removeClass"]("ui-corner-all");
	},

	_parseBoolean: function(value) {
		if (typeof value === "boolean")
			return value;
		else {
			value = value.toLowerCase();
			return (value === "true" || value === "yes" || value === "1");
		}
	},

	_set_fade: function(value, unconditional) {
		this.options.fade = this._parseBoolean(value);
	},

	_set_transition: function(value, unconditional) {
		if (this.options.transition != value || unconditional) {
			this._ui.container
				.removeClass(this.options.transition)
				.addClass(value);
			this.options.transition = value;
		}
	},

	_setOption: function(key, value, unconditional) {
		if (unconditional === undefined)
			unconditional = false;
		if (this["_set_" + key] !== undefined)
			this["_set_" + key](value, unconditional);
	},

	_placementCoords: function(x, y) {
		// Try and center the overlay over the given coordinates
		var ret,
		    menuHeight = this._ui.container.outerHeight(true),
		    menuWidth = this._ui.container.outerWidth(true),
		    scrollTop = $( window ).scrollTop(),
		    screenHeight = window.innerHeight,
		    screenWidth = window.innerWidth,
		    halfheight = menuHeight / 2,
		    maxwidth = parseFloat( this._ui.container.css( "max-width" ) ),
		    roomtop = y - scrollTop,
		    roombot = scrollTop + screenHeight - y,
		    newtop, newleft;

		if ( roomtop > menuHeight / 2 && roombot > menuHeight / 2 ) {
		  newtop = y - halfheight;
		}
		else {
		  // 30px tolerance off the edges
		  newtop = roomtop > roombot ? scrollTop + screenHeight - menuHeight - 30 : scrollTop + 30;
		}

		// If the menuwidth is smaller than the screen center is
		if ( menuWidth < maxwidth ) {
		  newleft = ( screenWidth - menuWidth ) / 2;
		}
		else {
		  //otherwise insure a >= 30px offset from the left
		  newleft = x - menuWidth / 2;

		  // 10px tolerance off the edges
		  if ( newleft < 10 ) {
		    newleft = 10;
		  }
		  else
			if ( ( newleft + menuWidth ) > screenWidth ) {
		    newleft = screenWidth - menuWidth - 10;
		  }
		}

		return { x : newleft, y : newtop };
	},

	_bindHashChange: function(){
		var self = this;
		$( window ).one( "hashchange.popup", function(){
			self.close( true );
		});
	},

	_unbindHashChange: function(){
		$( window ).unbind( "hashchange.popup" );
	},

	open: function(x, y) {
		if (!this._isOpen) {
			var self = this,
			    coords = this._placementCoords(
			    	(undefined === x ? window.innerWidth  / 2 : x),
			    	(undefined === y ? window.innerHeight / 2 : y));

			this._ui.screen
				.height($(document).height())
				.removeClass("ui-screen-hidden");

			if (this.options.fade)
				this._ui.screen.animate({opacity: 0.5}, "fast");

			this._ui.container
				.removeClass("ui-selectmenu-hidden")
				.css({
					left: coords.x,
					 top: coords.y
				})
				.addClass("in")
				.animationComplete(function() {
					self._ui.screen.height($(document).height());
				});

			// listen for hashchange that will occur when we set it to null dialog hash
			$( window ).one( "hashchange", function(){
				self._bindHashChange();
			});

			// set hash to non-linkable dialog url
			$.mobile.path.set( "&ui-state=dialog" );

			this._isOpen = true;
		}
	},

	close: function( fromHash ) {
		if (this._isOpen) {
			var self = this,
		    	hideScreen = function() {
		    		self._ui.screen.addClass("ui-screen-hidden");
		    		self._isOpen = false;
		    		self.element.trigger("closed");
		    		self._ui.screen.removeAttr("style");
		    	};

			this._ui.container
				.removeClass("in")
				.addClass("reverse out")
				.animationComplete(function() {
					self._ui.container
						.removeClass("reverse out")
						.addClass("ui-selectmenu-hidden")
						.removeAttr("style");
				});

				if (this.options.fade)
					this._ui.screen.animate({opacity: 0.0}, "fast", hideScreen);
				else
					hideScreen();

				// unbind listener that comes with opening popup
				this._unbindHashChange();

				// if the close event did not come from an internal hash listener, reset URL back
				if( !fromHash ){
					window.history.back();
				}
		}
	}
});

$(document).bind("pagecreate create", function(e) {
	$($.mobile.popup.prototype.options.initSelector, e.target)
		.not(":jqmData(role='none'), :jqmData(role='nojs')")
		.popup();

	$("a[href^='#']:jqmData(rel='popup')").each(function() {
		var btn = $(this),
				popup = $(btn.attr("href"));

		if (popup[0]) {
			// If the popup has a theme set, prevent it from being clobbered by the associated button
			if ((popup.popup("option", "overlayTheme") || "").match(/[a-z]/))
				popup.jqmData("overlay-theme-set", true);
			btn
				.attr({
					"aria-haspopup": true,
					"aria-owns": btn.attr("href")
				})
				.removeAttr("href")
				.bind("vclick", function(e) {
					// When /this/ button causes a popup, align the popup's theme with that of the button, unless the popup has a theme pre-set
					if (!popup.jqmData("overlay-theme-set"))
						popup.popup("option", "overlayTheme", btn.jqmData("theme"))
					popup.popup("open",
						btn.offset().left + btn.outerWidth()  / 2,
						btn.offset().top  + btn.outerHeight() / 2);
					if (e.stopPropagation)
						e.stopPropagation();
					if (e.preventDefault)
						e.preventDefault();
				});
		}
		else
			console.log("popup menu " + btn.attr("href") + " not found.");
	});
});

})(jQuery);
<commit_msg>[popup] Giving _setOption-related methods nicer names<commit_after>/*
* jQuery Mobile Framework : "popup" plugin
* Copyright (c) jQuery Project
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*/

(function($, undefined) {

$.widget("mobile.popup", $.mobile.widget, {
	options: {
		theme: null,
		overlayTheme: null,
		shadow: true,
		corners: true,
		fade: true,
		transition: $.mobile.defaultDialogTransition,
		initSelector: ":jqmData(role='popup')"
	},

	_create: function() {
		var ui = {
					screen    : "#ui-popup-screen",
					container : "#ui-popup-container"
				},
				proto = $(
"
" +
"

" +
"

" +
"
"
),
				thisPage = (this.element.closest(".ui-page") || $("body")),
				self = this;

		// Assign the relevant parts of the proto
		for (var key in ui)
			ui[key] = proto.find(ui[key]).removeAttr("id");

		// Apply the proto
		thisPage.append(ui.screen);
		ui.container.insertAfter(ui.screen);
		ui.container.append(this.element);

		// Define instance variables
		$.extend (this, {
			_ui     : ui,
			_isOpen : false
		});

		$.each (this.options, function(key) {
			self._setOption(key, self.options[key], true);
		});

		ui.screen.bind("vclick", function(e) {
			self.close();
		});
	},

	_realSetTheme: function(dst, theme, unconditional) {
		var classes = (dst.attr("class") || "").split(" "),
		    alreadyAdded = true,
		    currentTheme = null,
			matches;

		while (classes.length > 0) {
			currentTheme = classes.pop();
			matches = currentTheme.match(/^ui-body-([a-z])$/);
			if (matches && matches.length > 1) {
				currentTheme = matches[1];
				break;
			}
			else
				currentTheme = null;
		}

		if (theme !== currentTheme || unconditional) {
			dst.removeClass("ui-body-" + currentTheme);
			if (theme !== null)
				dst.addClass("ui-body-" + theme);
		}
	},

	_setTheme: function(value, unconditional) {
		if (value === null)
			value = "";

		if (value.match(/^[a-z]$/) || value === "") {
			this._realSetTheme(this.element, value, unconditional);
		}
	},

	_setOverlayTheme: function(value, unconditional) {
		if (value === null)
			value = "";
		if (value.match(/^[a-z]$/) || value === "") {
			this._realSetTheme(this._ui.container, value, unconditional);
			// The screen must always have some kind of background for fade to work, so, if the theme is being unset,
			// set the background to "a".
			this._realSetTheme(this._ui.screen, (value === "" ? "a" : value), unconditional);
		}
	},

	_setShadow: function(value, unconditional) {
		value = this._parseBoolean(value);
		if (this._ui.container.hasClass("ui-overlay-shadow") != value || unconditional)
			this._ui.container[value ? "addClass" : "removeClass"]("ui-overlay-shadow");
	},

	_setCorners: function(value, unconditional) {
		value = this._parseBoolean(value);
		if (this._ui.container.hasClass("ui-corner-all") != value || unconditional)
			this._ui.container[value ? "addClass" : "removeClass"]("ui-corner-all");
	},

	_parseBoolean: function(value) {
		if (typeof value === "boolean")
			return value;
		else {
			value = value.toLowerCase();
			return (value === "true" || value === "yes" || value === "1");
		}
	},

	_setFade: function(value, unconditional) {
		this.options.fade = this._parseBoolean(value);
	},

	_setTransition: function(value, unconditional) {
		if (this.options.transition != value || unconditional) {
			this._ui.container
				.removeClass(this.options.transition)
				.addClass(value);
			this.options.transition = value;
		}
	},

	_setOption: function(key, value, unconditional) {
		var setter = "_set" + key.replace(/^[a-z]/, function(c) {return c.toUpperCase();});

		if (unconditional === undefined)
			unconditional = false;

		if (this[setter] !== undefined)
			this[setter](value, unconditional);
		else
			$.mobile.widget.prototype._setOption.apply(this, arguments);
	},

	_placementCoords: function(x, y) {
		// Try and center the overlay over the given coordinates
		var ret,
		    menuHeight = this._ui.container.outerHeight(true),
		    menuWidth = this._ui.container.outerWidth(true),
		    scrollTop = $( window ).scrollTop(),
		    screenHeight = window.innerHeight,
		    screenWidth = window.innerWidth,
		    halfheight = menuHeight / 2,
		    maxwidth = parseFloat( this._ui.container.css( "max-width" ) ),
		    roomtop = y - scrollTop,
		    roombot = scrollTop + screenHeight - y,
		    newtop, newleft;

		if ( roomtop > menuHeight / 2 && roombot > menuHeight / 2 ) {
		  newtop = y - halfheight;
		}
		else {
		  // 30px tolerance off the edges
		  newtop = roomtop > roombot ? scrollTop + screenHeight - menuHeight - 30 : scrollTop + 30;
		}

		// If the menuwidth is smaller than the screen center is
		if ( menuWidth < maxwidth ) {
		  newleft = ( screenWidth - menuWidth ) / 2;
		}
		else {
		  //otherwise insure a >= 30px offset from the left
		  newleft = x - menuWidth / 2;

		  // 10px tolerance off the edges
		  if ( newleft < 10 ) {
		    newleft = 10;
		  }
		  else
			if ( ( newleft + menuWidth ) > screenWidth ) {
		    newleft = screenWidth - menuWidth - 10;
		  }
		}

		return { x : newleft, y : newtop };
	},

	_bindHashChange: function(){
		var self = this;
		$( window ).one( "hashchange.popup", function(){
			self.close( true );
		});
	},

	_unbindHashChange: function(){
		$( window ).unbind( "hashchange.popup" );
	},

	open: function(x, y) {
		if (!this._isOpen) {
			var self = this,
			    coords = this._placementCoords(
			    	(undefined === x ? window.innerWidth  / 2 : x),
			    	(undefined === y ? window.innerHeight / 2 : y));

			this._ui.screen
				.height($(document).height())
				.removeClass("ui-screen-hidden");

			if (this.options.fade)
				this._ui.screen.animate({opacity: 0.5}, "fast");

			this._ui.container
				.removeClass("ui-selectmenu-hidden")
				.css({
					left: coords.x,
					 top: coords.y
				})
				.addClass("in")
				.animationComplete(function() {
					self._ui.screen.height($(document).height());
				});

			// listen for hashchange that will occur when we set it to null dialog hash
			$( window ).one( "hashchange", function(){
				self._bindHashChange();
			});

			// set hash to non-linkable dialog url
			$.mobile.path.set( "&ui-state=dialog" );

			this._isOpen = true;
		}
	},

	close: function( fromHash ) {
		if (this._isOpen) {
			var self = this,
		    	hideScreen = function() {
		    		self._ui.screen.addClass("ui-screen-hidden");
		    		self._isOpen = false;
		    		self.element.trigger("closed");
		    		self._ui.screen.removeAttr("style");
		    	};

			this._ui.container
				.removeClass("in")
				.addClass("reverse out")
				.animationComplete(function() {
					self._ui.container
						.removeClass("reverse out")
						.addClass("ui-selectmenu-hidden")
						.removeAttr("style");
				});

				if (this.options.fade)
					this._ui.screen.animate({opacity: 0.0}, "fast", hideScreen);
				else
					hideScreen();

				// unbind listener that comes with opening popup
				this._unbindHashChange();

				// if the close event did not come from an internal hash listener, reset URL back
				if( !fromHash ){
					window.history.back();
				}
		}
	}
});

$(document).bind("pagecreate create", function(e) {
	$($.mobile.popup.prototype.options.initSelector, e.target)
		.not(":jqmData(role='none'), :jqmData(role='nojs')")
		.popup();

	$("a[href^='#']:jqmData(rel='popup')").each(function() {
		var btn = $(this),
				popup = $(btn.attr("href"));

		if (popup[0]) {
			// If the popup has a theme set, prevent it from being clobbered by the associated button
			if ((popup.popup("option", "overlayTheme") || "").match(/[a-z]/))
				popup.jqmData("overlay-theme-set", true);
			btn
				.attr({
					"aria-haspopup": true,
					"aria-owns": btn.attr("href")
				})
				.removeAttr("href")
				.bind("vclick", function(e) {
					// When /this/ button causes a popup, align the popup's theme with that of the button, unless the popup has a theme pre-set
					if (!popup.jqmData("overlay-theme-set"))
						popup.popup("option", "overlayTheme", btn.jqmData("theme"))
					popup.popup("open",
						btn.offset().left + btn.outerWidth()  / 2,
						btn.offset().top  + btn.outerHeight() / 2);
					if (e.stopPropagation)
						e.stopPropagation();
					if (e.preventDefault)
						e.preventDefault();
				});
		}
		else
			console.log("popup menu " + btn.attr("href") + " not found.");
	});
});

})(jQuery);
<|endoftext|>


<commit_before>(function($){

  var msMethods = {
    'init' : function(options){
      this.settings = {

      };
      if(options) {
        this.settings = $.extend(this.settings, options);
      }

      var multiSelects = this;
      multiSelects.hide();

      multiSelects.each(function(){
        var ms = $(this),
            container = $('

').detach(),
            selectableContainer = $('

').detach(),
            selectedContainer = $('

').detach(),
            selectableUl = $('

').detach(),
            selectedUl = $('

').detach();

        ms.data('settings', multiSelects.settings);
        ms.children('option').each(function(){
          var selectableLi = $('
'+$(this).text()+'
').detach();

          selectableLi.click(function(){
            ms.multiSelect('select', $(this).attr('ms-value'));
          });
          selectableUl.append(selectableLi);
        });
        selectableContainer.append(selectableUl);
        selectedContainer.append(selectedUl);
        container.append(selectableContainer);
        container.append(selectedContainer);
        ms.after(container);
        ms.children('option:selected').each(function(){
          ms.multiSelect('select', $(this).val(), 'init');
        });
      });
    },
    'select' : function(value, method){
      var ms = this,
          msValues = (ms.val() ? ms.val() : []),
          alreadyPresent = $.inArray(value, msValues);

      if(alreadyPresent == -1 || method == 'init'){
        var selectedLi = $('
'+ms.find('option[value="'+value+'"]').text()+'
').detach(),
            newValues = $.merge(msValues, [value]),
            selectableUl = $('#ms-'+ms.attr('id')+' .ms-selectable ul'),
            selectedUl = $('#ms-'+ms.attr('id')+' .ms-selection ul'),
            selectableLi = selectableUl.children('li[ms-value="'+value+'"]');

        selectableLi.hide();
        ms.val(newValues);
        selectedLi.click(function(){
          ms.multiSelect('deselect', $(this).attr('ms-value'));
        });
        selectedUl.append(selectedLi);
        if (typeof ms.data('settings').afterSelect == 'function' && method != 'init') {
          ms.data('settings').afterSelect.call(this, value, text);
        }
      }
    },
    'deselect' : function(value){
      var ms = this,
          msValues = (ms.val() ? ms.val() : []),
          present = false,
          newValues = $.map(msValues, function(e){ if(e != value){ return e; }else{ present = true}});

      if(present){
        var selectableUl = $('#ms-'+ms.attr('id')+' .ms-selectable ul'),
            selectedUl = $('#ms-'+ms.attr('id')+' .ms-selection ul'),
            selectableLi = selectableUl.children('li[ms-value="'+value+'"]'),
            selectedLi = selectedUl.children('li[ms-value="'+value+'"]').detach();

        ms.val(newValues);
        selectableLi.show();
        selectedLi.remove();
        if (typeof ms.data('settings').afterDeselect == 'function') {
          ms.data('settings').afterDeselect.call(this, value, selectedLi.text());
        }
      }
    },
    'select_all' : function(){
      var ms = this;
      ms.children('option').each(function(){
        ms.multiSelect('select', $(this).val(), 'select_all');
      });
    },
    'deselect_all' :function(){
      var ms = this;
      ms.children('option').each(function(){
        ms.multiSelect('deselect', $(this).val(), 'deselect_all');
      });
    }
  }

  $.fn.multiSelect = function(method){
    if ( msMethods[method] ) {
      return msMethods[method].apply( this, Array.prototype.slice.call( arguments, 1 ));
    } else if ( typeof method === 'object' || ! method ) {
      return msMethods.init.apply( this, arguments );
    } else {
      if(console.log) console.log( 'Method ' +  method + ' does not exist on jquery.multiSelect' );
    }
  }
})(jQuery);<commit_msg>Oops! fix bug on afterSelect<commit_after>(function($){

  var msMethods = {
    'init' : function(options){
      this.settings = {

      };
      if(options) {
        this.settings = $.extend(this.settings, options);
      }

      var multiSelects = this;
      multiSelects.hide();

      multiSelects.each(function(){
        var ms = $(this),
            container = $('

').detach(),
            selectableContainer = $('

').detach(),
            selectedContainer = $('

').detach(),
            selectableUl = $('

').detach(),
            selectedUl = $('

').detach();

        ms.data('settings', multiSelects.settings);
        ms.children('option').each(function(){
          var selectableLi = $('
'+$(this).text()+'
').detach();

          selectableLi.click(function(){
            ms.multiSelect('select', $(this).attr('ms-value'));
          });
          selectableUl.append(selectableLi);
        });
        selectableContainer.append(selectableUl);
        selectedContainer.append(selectedUl);
        container.append(selectableContainer);
        container.append(selectedContainer);
        ms.after(container);
        ms.children('option:selected').each(function(){
          ms.multiSelect('select', $(this).val(), 'init');
        });
      });
    },
    'select' : function(value, method){
      var ms = this,
          msValues = (ms.val() ? ms.val() : []),
          alreadyPresent = $.inArray(value, msValues),
          text = ms.find('option[value="'+value+'"]').text();

      if(alreadyPresent == -1 || method == 'init'){
        var selectedLi = $('
'+text+'
').detach(),
            newValues = $.merge(msValues, [value]),
            selectableUl = $('#ms-'+ms.attr('id')+' .ms-selectable ul'),
            selectedUl = $('#ms-'+ms.attr('id')+' .ms-selection ul'),
            selectableLi = selectableUl.children('li[ms-value="'+value+'"]');

        selectableLi.hide();
        ms.val(newValues);
        selectedLi.click(function(){
          ms.multiSelect('deselect', $(this).attr('ms-value'));
        });
        selectedUl.append(selectedLi);
        if (typeof ms.data('settings').afterSelect == 'function' && method != 'init') {
          ms.data('settings').afterSelect.call(this, value, text);
        }
      }
    },
    'deselect' : function(value){
      var ms = this,
          msValues = (ms.val() ? ms.val() : []),
          present = false,
          newValues = $.map(msValues, function(e){ if(e != value){ return e; }else{ present = true}});

      if(present){
        var selectableUl = $('#ms-'+ms.attr('id')+' .ms-selectable ul'),
            selectedUl = $('#ms-'+ms.attr('id')+' .ms-selection ul'),
            selectableLi = selectableUl.children('li[ms-value="'+value+'"]'),
            selectedLi = selectedUl.children('li[ms-value="'+value+'"]').detach();

        ms.val(newValues);
        selectableLi.show();
        selectedLi.remove();
        if (typeof ms.data('settings').afterDeselect == 'function') {
          ms.data('settings').afterDeselect.call(this, value, selectedLi.text());
        }
      }
    },
    'select_all' : function(){
      var ms = this;
      ms.children('option').each(function(){
        ms.multiSelect('select', $(this).val(), 'select_all');
      });
    },
    'deselect_all' :function(){
      var ms = this;
      ms.children('option').each(function(){
        ms.multiSelect('deselect', $(this).val(), 'deselect_all');
      });
    }
  }

  $.fn.multiSelect = function(method){
    if ( msMethods[method] ) {
      return msMethods[method].apply( this, Array.prototype.slice.call( arguments, 1 ));
    } else if ( typeof method === 'object' || ! method ) {
      return msMethods.init.apply( this, arguments );
    } else {
      if(console.log) console.log( 'Method ' +  method + ' does not exist on jquery.multiSelect' );
    }
  }
})(jQuery);<|endoftext|>


<commit_before>/*
 *  The MIT License (MIT)
 *
 * Copyright (c) 2016-2017 The Regents of the University of California
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
 * associated documentation files (the "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the
 * following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all copies or substantial
 * portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,  FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 *
 */

/**
 * Created by dat on 3/21/17.
 */
var hic = (function (hic) {

    var labels =
        {
                     NONE: 'None',
                       VC: 'Coverage',
                  VC_SQRT: 'Coverage (Sqrt)',
                       KR: 'Balanced',
                 INTER_VC: 'Interchromosomal Coverage',
            INTER_VC_SQRT: 'Interchromosomal Coverage (Sqrt)',
                 INTER_KR: 'Interchromosomal Balanced',
                    GW_VC: 'Genome-wide Coverage',
               GW_VC_SQRT: 'Genome-wide Coverage (Sqrt)',
                    GW_KR: 'Genome-wide Balanced'
        };

    hic.NormalizationWidget = function (browser) {
        var self = this,
            $label,
            $option,
            config;

        this.browser = browser;

        $label = $('
');
        $label.text('Normalization');

        this.$normalization_selector = $('<select name="select">');
        this.$normalization_selector.attr('name', 'dataset_selector');
        this.$normalization_selector.on('change', function (e) {
            self.browser.setNormalization($(this).val());
        });

        this.$container = $('
');
        this.$container.append($label);
        this.$container.append(this.$normalization_selector);

        hic.GlobalEventBus.subscribe("MapLoad", this);

    };

    hic.NormalizationWidget.prototype.receiveEvent = function (event) {

        if (event.type === "MapLoad") {

            var dataset = event.data,
                normalizationTypes,
                elements,
                norm = this.browser.state.normalization;

            normalizationTypes = dataset.normalizationTypes;
            elements = _.map(normalizationTypes, function (normalization) {
                var label,
                    isSelected,
                    titleString,
                    valueString;

                label = labels[ normalization ];
                isSelected = (norm === normalization);

                titleString = (label === undefined ? '' : ' title = "' + label + '" ');
                valueString = ' value=' + normalization + (isSelected ? ' selected' : '');

                return '<option' + titleString + valueString + '>' + label + '</option>';
            });

            this.$normalization_selector.empty();
            this.$normalization_selector.append(elements.join(''));
        }
    };

    return hic;

})
(hic || {});
<commit_msg>normalization select options. Padded text.<commit_after>/*
 *  The MIT License (MIT)
 *
 * Copyright (c) 2016-2017 The Regents of the University of California
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
 * associated documentation files (the "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the
 * following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all copies or substantial
 * portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,  FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 *
 */

/**
 * Created by dat on 3/21/17.
 */
var hic = (function (hic) {

    var labels =
        {
                     NONE: 'None',
                       VC: 'Coverage',
                  VC_SQRT: 'Coverage (Sqrt)',
                       KR: 'Balanced',
                 INTER_VC: 'Interchromosomal Coverage',
            INTER_VC_SQRT: 'Interchromosomal Coverage (Sqrt)',
                 INTER_KR: 'Interchromosomal Balanced',
                    GW_VC: 'Genome-wide Coverage',
               GW_VC_SQRT: 'Genome-wide Coverage (Sqrt)',
                    GW_KR: 'Genome-wide Balanced'
        };

    hic.NormalizationWidget = function (browser) {
        var self = this,
            $label,
            $option,
            config;

        this.browser = browser;

        $label = $('
');
        $label.text('Normalization');

        this.$normalization_selector = $('<select name="select">');
        this.$normalization_selector.attr('name', 'dataset_selector');
        this.$normalization_selector.on('change', function (e) {
            self.browser.setNormalization($(this).val());
        });

        this.$container = $('
');
        this.$container.append($label);
        this.$container.append(this.$normalization_selector);

        hic.GlobalEventBus.subscribe("MapLoad", this);

    };

    hic.NormalizationWidget.prototype.receiveEvent = function (event) {

        if (event.type === "MapLoad") {

            var dataset = event.data,
                normalizationTypes,
                elements,
                norm = this.browser.state.normalization;

            normalizationTypes = dataset.normalizationTypes;
            elements = _.map(normalizationTypes, function (normalization) {
                var label,
                    labelPresentation,
                    isSelected,
                    titleString,
                    valueString;

                label = labels[ normalization ];
                isSelected = (norm === normalization);
                titleString = (label === undefined ? '' : ' title = "' + label + '" ');
                valueString = ' value=' + normalization + (isSelected ? ' selected' : '');

                labelPresentation = '&nbsp &nbsp' + label + '&nbsp &nbsp';
                return '<option' + titleString + valueString + '>' + labelPresentation + '</option>';
            });

            this.$normalization_selector.empty();
            this.$normalization_selector.append(elements.join(''));
        }
    };

    return hic;

})
(hic || {});
<|endoftext|>


<commit_before>// Pattern which Plone livesearch functionality on an input
//
// Author: Ryan Foster
// Contact: ryan@rynamic.com
// Version: 1.0
//
// Adapted from livesearch.js in Plone.
//
// License:
//
// Copyright (C) 2013 Plone Foundation
//
// This program is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 of the License.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License along with
// this program; if not, write to the Free Software Foundation, Inc., 51
// Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//

/*jshint bitwise:true, curly:true, eqeqeq:true, immed:true, latedef:true,
  newcap:true, noarg:true, noempty:true, nonew:true, plusplus:true,
  undef:true, strict:true, trailing:true, browser:true, evil:true */
/*global define:false */

define([
  'jquery',
  'js/patterns/base',
  'js/patterns/toggle'
], function($, Base, Toggle) {
  "use strict";

  var Livesearch = Base.extend({
    name: "livesearch",
    timeout: null,
    $results: null,
    $input: null,
    toggle: null,
    cache: {},
    defaults: {
      delay: 400, // ms after keyup before search
      param: 'SearchableText', // query string param to pass to search url
      highlight: 'pat-livesearch-highlight', // class to add to items when selected
      chars: 3, // number of chars user should type before searching
      toggle: {
        target: '.pat-livesearch-container', // the element to show/hide when performing search
        value: 'show'
      },
      results: {
        target: '.pat-livesearch-results', // the element to fill with results
        content: null, // element from the result to grab
        item: 'li', // selector for items in results
        link: 'a' // selector for primary link element inside of item
      },
      input: '.pat-livesearch-input' // input selector
    },

    init: function() {
      var self = this;
      var $toggle, $results;

      this.$results = $(self.options.results.target);

      if (!self.options.url) {
        $.error('No url provided for livesearch results ' + self.$el);
      }

      self.$input = $(self.options.input);

      if (self.$input.length < 1) {
        $.error('Input element not found ' + self.$el);
      }

      if (self.options.toggle) {
        $toggle = $(self.options.toggle.target);
        if ($toggle.length > 0) {
          self.toggle = new Toggle($toggle, self.options.toggle);
        }
      }

      self.$input.on('keyup', function(event) {
        self._handler(event);
      });
    },

    search: function() {
      var self = this;
      var term = this.$input.val();

      if (self.cache[term]) {
        self.fillResults(self.cache[term]);
      }

      var params = {};
      var query;
      params[self.options.param] = term;
      query = $.param(params);

      $.get(
        self.options.url,
        query,
        function(data) {
          self.cache[term] = data;
          self.fillResults(data);
        }
      );
    },

    fillResults: function(data) {
      var self = this;
      if (self.$results.length > 0) {
        var content = data;
        if (self.options.results.content !== null) {
          content = $(data).find(self.options.results.content);
        }
        $(content).find(self.options.results.item)
        self.$results.html(content);
        self.show();
        window.clearInterval(self.timeout);
      }
    },

    show: function() {
      if (this.toggle) {
        this.toggle.add();
      }
    },

    hide: function() {
      if (this.toggle) {
        this.toggle.remove();
      }
    },

    _keyUp: function() {
      var self = this;
      var hl = self.options.highlight;
      var $selected = self.$results.find('.'+hl);
      if ($selected.length < 1) {
        $selected = self.$results.find(self.options.results.item).last();
        $selected.addClass(hl);
        return;
      } else {
        $selected.removeClass(hl);
        if ($selected.prev().length) {
          $selected = $selected.prev();
        } else {
          $selected = self.$results.find(self.options.results.item).last();
        }
        $selected.addClass(hl);
      }
    },

    _keyDown: function() {
      var self = this;
      var hl = self.options.highlight;
      var $selected = self.$results.find('.'+hl);
      if ($selected.length < 1) {
        $selected = self.$results.find(self.options.results.item).first();
        $selected.addClass(hl);
        return;
      } else {
        $selected.removeClass(hl);
        if ($selected.next().length) {
          $selected = $selected.next();
        } else {
          $selected = self.$results.find(self.options.results.item).first();
        }
        $selected.addClass(hl);
      }
    },

    _keyEscape: function() {
      this.hide();
    },

    _keyEnter: function() {
      var self = this;
      var hl = self.options.highlight;
      self.$results.find('.'+hl)
        .find(self.options.results.link)
        .trigger('click');
    },

    _handler: function(event) {
      var self = this;
      window.clearTimeout(self.timeout);
      switch (event.keyCode) {
        case 13:
          self._keyEnter();
          return;
        case 38:
          self._keyUp();
          return;
        case 40:
          self._keyDown();
          return;
        case 27:
          self._keyEscape();
          return;
        case 37: break; // keyLeft
        case 39: break; // keyRight
        default:
          if (self.$input.val().length >= self.options.chars) {
            self.timeout = window.setInterval(
              function(){
                self.search();
              }, self.options.delay);
          }
      }
    }

  });

  return Livesearch;

});

<commit_msg>fix for borked toggling of search results<commit_after>// Pattern which Plone livesearch functionality on an input
//
// Author: Ryan Foster
// Contact: ryan@rynamic.com
// Version: 1.0
//
// Adapted from livesearch.js in Plone.
//
// License:
//
// Copyright (C) 2013 Plone Foundation
//
// This program is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 of the License.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License along with
// this program; if not, write to the Free Software Foundation, Inc., 51
// Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//

/*jshint bitwise:true, curly:true, eqeqeq:true, immed:true, latedef:true,
  newcap:true, noarg:true, noempty:true, nonew:true, plusplus:true,
  undef:true, strict:true, trailing:true, browser:true, evil:true */
/*global define:false */

define([
  'jquery',
  'js/patterns/base',
  'js/patterns/toggle'
], function($, Base, Toggle) {
  "use strict";

  var Livesearch = Base.extend({
    name: "livesearch",
    timeout: null,
    $results: null,
    $input: null,
    toggle: null,
    cache: {},
    defaults: {
      delay: 400, // ms after keyup before search
      param: 'SearchableText', // query string param to pass to search url
      highlight: 'pat-livesearch-highlight', // class to add to items when selected
      chars: 3, // number of chars user should type before searching
      toggle: {
        target: '.pat-livesearch-container', // the element to show/hide when performing search
        value: 'show',
        event: 'foo'
      },
      results: {
        target: '.pat-livesearch-results', // the element to fill with results
        content: null, // element from the result to grab
        item: 'li', // selector for items in results
        link: 'a' // selector for primary link element inside of item
      },
      input: '.pat-livesearch-input' // input selector
    },

    init: function() {
      var self = this;
      var $toggle, $results;

      this.$results = $(self.options.results.target);

      if (!self.options.url) {
        $.error('No url provided for livesearch results ' + self.$el);
      }

      self.$input = $(self.options.input);

      if (self.$input.length < 1) {
        $.error('Input element not found ' + self.$el);
      }

      if (self.options.toggle) {
        $toggle = $(self.options.toggle.target);
        if ($toggle.length > 0) {
          self.toggle = new Toggle(self.$input, self.options.toggle);
          self.toggle.remove();
        }
      }

      self.$input.on('keyup', function(event) {
        return self._handler(event);
      });
    },

    search: function() {
      var self = this;
      var term = this.$input.val();

      if (self.cache[term]) {
        self.fillResults(self.cache[term]);
      }

      var params = {};
      var query;
      params[self.options.param] = term;
      query = $.param(params);
      $.get(
        self.options.url,
        query,
        function(data) {
          self.cache[term] = data;
          self.fillResults(data);
        }
      );
    },

    fillResults: function(data) {
      var self = this;
      if (self.$results.length > 0) {
        var content = data;
        if (self.options.results.content !== null) {
          content = $(data).find(self.options.results.content);
        }
        $(content).find(self.options.results.item)
        self.$results.html(content);
        self.show();
        window.clearInterval(self.timeout);
      }
    },

    show: function() {
      if (this.toggle) {
        this.toggle.add();
      }
    },

    hide: function() {
      if (this.toggle) {
        this.toggle.remove();
      }
    },

    _keyUp: function() {
      var self = this;
      var hl = self.options.highlight;
      var $selected = self.$results.find('.'+hl);
      if ($selected.length < 1) {
        $selected = self.$results.find(self.options.results.item).last();
        $selected.addClass(hl);
        return;
      } else {
        $selected.removeClass(hl);
        if ($selected.prev().length) {
          $selected = $selected.prev();
        } else {
          $selected = self.$results.find(self.options.results.item).last();
        }
        $selected.addClass(hl);
      }
    },

    _keyDown: function() {
      var self = this;
      var hl = self.options.highlight;
      var $selected = self.$results.find('.'+hl);
      if ($selected.length < 1) {
        $selected = self.$results.find(self.options.results.item).first();
        $selected.addClass(hl);
        return;
      } else {
        $selected.removeClass(hl);
        if ($selected.next().length) {
          $selected = $selected.next();
        } else {
          $selected = self.$results.find(self.options.results.item).first();
        }
        $selected.addClass(hl);
      }
    },

    _keyEscape: function() {
      this.hide();
    },

    _keyEnter: function() {
      var self = this;
      var hl = self.options.highlight;
      var target = self.$results.find('.'+hl)
        .find(self.options.results.link).attr('href');
      window.location = target;
    },

    _handler: function(event) {
      var self = this;
      window.clearTimeout(self.timeout);
      switch (event.keyCode) {
        case 13:
          self._keyEnter();
          break;
        case 38:
          self._keyUp();
          return false;
        case 40:
          self._keyDown();
          return false;
        case 27:
          self._keyEscape();
          break;
        case 37: break; // keyLeft
        case 39: break; // keyRight
        default:
          if (self.$input.val().length >= self.options.chars) {
            self.timeout = window.setInterval(
              function(){
                self.search();
              }, self.options.delay);
          }
      }
    }

  });

  return Livesearch;

});
<|endoftext|>


<commit_before>BR.tracksLoader = function(map, layersControl, routing) {
    TracksLoader = L.Control.FileLayerLoad.extend({
        options: {
            layer: L.geoJson,
            layerOptions: { style: { color: 'blue' }, interactive: false },
            addToMap: false,
            // File size limit in kb (default: 1024) ?
            fileSizeLimit: 1024
        },

        _initContainer: function() {
            var thisLoader = this.loader;

            var fileInput;
            var container = L.DomUtil.get('navbarLoadTracksContainer');

            // Create an invisible file input
            fileInput = L.DomUtil.create('input', 'hidden', container);
            fileInput.type = 'file';
            fileInput.multiple = 'multiple';
            if (!this.options.formats) {
                fileInput.accept = '.gpx,.kml,.json,.geojson';
            } else {
                fileInput.accept = this.options.formats.join(',');
            }
            fileInput.style.display = 'none';
            // Load on file change
            fileInput.addEventListener(
                'change',
                function() {
                    thisLoader.loadMultiple(this.files);
                    // reset so that the user can upload the same file again if they want to
                    this.value = '';
                },
                false
            );

            var link = L.DomUtil.get('navbarLoadTracks');
            L.DomEvent.disableClickPropagation(link);
            L.DomEvent.on(link, 'click', function(e) {
                fileInput.click();
                e.preventDefault();
            });
            // dummy, no own representation, triggered in loading menu
            return L.DomUtil.create('div');
        }
    });
    var tracksLoaderControl = new TracksLoader();
    tracksLoaderControl.addTo(map);

    tracksLoaderControl.loader.on('data:loaded', function(event) {
        var eventLayer = event.layer,
            routingMarkers = [];
        for (var layerIdx = 0; layerIdx < eventLayer.getLayers().length; layerIdx++) {
            var layer = eventLayer.getLayers()[layerIdx];
            if (layer.feature && layer.feature.properties && layer.feature.properties.type) {
                var layerType = layer.feature.properties.type;
                if (layerType === 'from' || layerType === 'via' || layerType === 'to') {
                    routingMarkers.push(layer.getLatLng());
                }
            }
        }
        if (routingMarkers.length > 0) {
            routing.setWaypoints(routingMarkers, function(event) {
                var err = event.error;
                BR.message.showError(
                    i18next.t('warning.tracks-load-error', {
                        error: err && err.message ? err.message : err
                    })
                );
            });
        }
        layersControl.addOverlay(eventLayer, event.filename);
        eventLayer.addTo(map);
    });

    tracksLoaderControl.loader.on('data:error', function(event) {
        var err = event.error;
        BR.message.showError(
            i18next.t('warning.tracks-load-error', {
                error: err && err.message ? err.message : err
            })
        );
    });

    return tracksLoaderControl;
};
<commit_msg>Remove gap in control bar by hiding empty dummy track loader button<commit_after>BR.tracksLoader = function(map, layersControl, routing) {
    TracksLoader = L.Control.FileLayerLoad.extend({
        options: {
            layer: L.geoJson,
            layerOptions: { style: { color: 'blue' }, interactive: false },
            addToMap: false,
            // File size limit in kb (default: 1024) ?
            fileSizeLimit: 1024
        },

        _initContainer: function() {
            var thisLoader = this.loader;

            var fileInput;
            var container = L.DomUtil.get('navbarLoadTracksContainer');

            // Create an invisible file input
            fileInput = L.DomUtil.create('input', 'hidden', container);
            fileInput.type = 'file';
            fileInput.multiple = 'multiple';
            if (!this.options.formats) {
                fileInput.accept = '.gpx,.kml,.json,.geojson';
            } else {
                fileInput.accept = this.options.formats.join(',');
            }
            fileInput.style.display = 'none';
            // Load on file change
            fileInput.addEventListener(
                'change',
                function() {
                    thisLoader.loadMultiple(this.files);
                    // reset so that the user can upload the same file again if they want to
                    this.value = '';
                },
                false
            );

            var link = L.DomUtil.get('navbarLoadTracks');
            L.DomEvent.disableClickPropagation(link);
            L.DomEvent.on(link, 'click', function(e) {
                fileInput.click();
                e.preventDefault();
            });
            // dummy, no own representation, triggered in loading menu
            var dummy = L.DomUtil.create('div');
            dummy.hidden = true;
            return dummy;
        }
    });
    var tracksLoaderControl = new TracksLoader();
    tracksLoaderControl.addTo(map);

    tracksLoaderControl.loader.on('data:loaded', function(event) {
        var eventLayer = event.layer,
            routingMarkers = [];
        for (var layerIdx = 0; layerIdx < eventLayer.getLayers().length; layerIdx++) {
            var layer = eventLayer.getLayers()[layerIdx];
            if (layer.feature && layer.feature.properties && layer.feature.properties.type) {
                var layerType = layer.feature.properties.type;
                if (layerType === 'from' || layerType === 'via' || layerType === 'to') {
                    routingMarkers.push(layer.getLatLng());
                }
            }
        }
        if (routingMarkers.length > 0) {
            routing.setWaypoints(routingMarkers, function(event) {
                var err = event.error;
                BR.message.showError(
                    i18next.t('warning.tracks-load-error', {
                        error: err && err.message ? err.message : err
                    })
                );
            });
        }
        layersControl.addOverlay(eventLayer, event.filename);
        eventLayer.addTo(map);
    });

    tracksLoaderControl.loader.on('data:error', function(event) {
        var err = event.error;
        BR.message.showError(
            i18next.t('warning.tracks-load-error', {
                error: err && err.message ? err.message : err
            })
        );
    });

    return tracksLoaderControl;
};
<|endoftext|>