<commit_before>/*
* MultiSelect v0.9
* Copyright (c) 2012 Louis Cuny
*
* This program is free software. It comes without any warranty, to
* the extent permitted by applicable law. You can redistribute it
* and/or modify it under the terms of the Do What The Fuck You Want
* To Public License, Version 2, as published by Sam Hocevar. See
* http://sam.zoy.org/wtfpl/COPYING for more details.
*/

!function ($) {

  "use strict"; // jshint ;_;

 /* MULTISELECT CLASS DEFINITION
  * ====================== */

  var MultiSelect = function (element, options) {
    this.options = options;
    this.$element = $(element);
    this.$container = $('

');
    this.$selectableContainer = $('

');
    this.$selectionContainer = $('

');
    this.$selectableUl = $('

');
    this.$selectionUl = $('

');
  }

  MultiSelect.prototype = {
    constructor: MultiSelect,

    init: function(){
      var that = this,
          ms = this.$element;

      if (ms.next('.ms-container').length == 0){
        ms.css({ position: 'absolute', left: '-9999px' });
        ms.attr('id', ms.attr('id') ? ms.attr('id') : 'ms-'+Math.ceil(Math.random()*1000));

        var optgroupLabel = null,
            optgroupId = null,
            optgroupCpt = 0,
            scroll = 0;

        ms.find('optgroup, option').each(function(){
          if ($(this).is('optgroup')){
            optgroupLabel = $(this).attr('label');
            optgroupId = 'ms-'+ms.attr('id')+'-optgroup-'+optgroupCpt;

            that.$selectableUl.append(
              '
\

\

'+optgroupLabel+'
\

\

');
            that.$selectionUl.append(
              '
\

\

'+optgroupLabel+'
\

\

');
            optgroupCpt++;
          } else {

            var attributes = "";

            for (var cpt = 0; cpt < this.attributes.length; cpt++){
              var attr = this.attributes[cpt];

              attributes += attr.name+'="'+attr.value+'" ';
            }
            var selectableLi = $('
'+$(this).text()+'
'),
                selectedLi = selectableLi.clone();

            var value = $(this).val();
            selectableLi.addClass('ms-elem-selectable').attr('id', value+'-selectable');
            selectedLi.addClass('ms-elem-selection').attr('id', value+'-selection').hide();

            that.$selectionUl.find('.ms-optgroup-label').hide();

            if ($(this).prop('disabled') || ms.prop('disabled')){
              selectableLi.prop('disabled', true);
              selectableLi.addClass(that.options.disabledClass);
            }

            if (optgroupId){
              that.$selectableUl.children('#'+optgroupId+'-selectable').find('ul').first().append(selectableLi);
              that.$selectionUl.children('#'+optgroupId+'-selection').find('ul').first().append(selectedLi);
            } else {
              that.$selectableUl.append(selectableLi);
              that.$selectionUl.append(selectedLi);
            }
          }
        });

        if (that.options.selectableHeader){
          that.$selectableContainer.append(that.options.selectableHeader);
        }
        that.$selectableContainer.append(that.$selectableUl);

        if (that.options.selectionHeader){
          that.$selectionContainer.append(that.options.selectionHeader);
        }
        this.$selectionContainer.append(that.$selectionUl);

        that.$container.append(that.$selectableContainer);
        that.$container.append(that.$selectionContainer);
        ms.after(that.$container);
        that.$selectableUl.on('mouseenter', '.ms-elem-selectable', function(){
          $('li', that.$container).removeClass('ms-hover');
          $(this).addClass('ms-hover');
        }).on('mouseout', function(){
          $('li', that.$container).removeClass('ms-hover');
        });

        if(that.options.dblClick) {
          that.$selectableUl.on('dblclick', '.ms-elem-selectable', function(){
            that.select($(this).attr('id').replace(/-selectable/, ''));
          });
          that.$selectionUl.on('dblclick', '.ms-elem-selection', function(){
            that.deselect($(this).attr('id').replace(/-selection/, ''));
          });
        } else {
          that.$selectableUl.on('click', '.ms-elem-selectable', function(){
            that.select($(this).attr('id').replace(/-selectable/, ''));
          });
          that.$selectionUl.on('click', '.ms-elem-selection', function(){
            that.deselect($(this).attr('id').replace(/-selection/, ''));
          });
        }

        that.$selectionUl.on('mouseenter', '.ms-elem-selection', function(){
          $('li', that.$selectionUl).removeClass('ms-hover');
          $(this).addClass('ms-hover');
        }).on('mouseout', function(){
          $('li', that.$selectionUl).removeClass('ms-hover');
        });

        that.$selectableUl.on('focusin', function(){
          $(this).addClass('ms-focus');
          that.$selectionUl.focusout();
        }).on('focusout', function(){
          $(this).removeClass('ms-focus');
          $('li', that.$container).removeClass('ms-hover');
        });

        that.$selectionUl.on('focusin', function(){
          $(this).addClass('ms-focus');
        }).on('focusout', function(){
          $(this).removeClass('ms-focus');
          $('li', that.$container).removeClass('ms-hover');
        });

        ms.on('focusin', function(){
          that.$selectableUl.focus();
        }).on('focusout', function(){
          that.$selectableUl.removeClass('ms-focus');
          that.$selectionUl.removeClass('ms-focus');
        });

        ms.onKeyDown = function(e, keyContainer){
          var selectables = $('.'+keyContainer+' li:visible:not(.ms-optgroup-label, .ms-optgroup-container)', that.$container),
              selectablesLength = selectables.length,
              selectableFocused = $('.'+keyContainer+' li.ms-hover', that.$container),
              selectableFocusedIndex = $('.'+keyContainer+' li:visible:not(.ms-optgroup-label, .ms-optgroup-container)', this.$container).index(selectableFocused),
              liHeight = selectables.first().outerHeight(),
              numberOfItemsDisplayed = Math.ceil(that.$container.outerHeight()/liHeight),
              scrollStart = Math.ceil(numberOfItemsDisplayed/4);

          selectables.removeClass('ms-hover');
          if (e.keyCode == 32){ // space
            var method = keyContainer == 'ms-selectable' ? 'select' : 'deselect';
            if (keyContainer == 'ms-selectable'){
              that.select(selectableFocused.first().attr('id'));
            } else {
              that.deselect(selectableFocused.first().attr('id'));
            }

          } else if (e.keyCode == 40){ // Down
            var nextIndex = (selectableFocusedIndex+1 != selectablesLength) ? selectableFocusedIndex+1 : 0,
                nextSelectableLi = selectables.eq(nextIndex);

            nextSelectableLi.addClass('ms-hover');
            if (nextIndex > scrollStart){
              scroll += liHeight;
            } else if (nextIndex == 0){
              scroll = 0;
            }
            $('.'+keyContainer+' ul', that.$container).scrollTop(scroll);
          } else if (e.keyCode == 38){ // Up
            var prevIndex = (selectableFocusedIndex-1 >= 0) ? selectableFocusedIndex-1 : selectablesLength-1,
                prevSelectableLi = selectables.eq(prevIndex);
            selectables.removeClass('ms-hover');
            prevSelectableLi.addClass('ms-hover');
            if (selectablesLength-prevIndex+1 < scrollStart){
              scroll = liHeight*(selectablesLength-scrollStart);
            } else {
              scroll -= liHeight;
            }
            $('.'+keyContainer+' ul', that.$container).scrollTop(scroll);
          } else if (e.keyCode == 37 || e.keyCode == 39){ // Right and Left
            if (that.$selectableUl.hasClass('ms-focus')){
              that.$selectableUl.focusout();
              that.$selectionUl.focusin();
            } else {
              that.$selectableUl.focusin();
              that.$selectionUl.focusout();
            }
          }
        }

        ms.on('keydown', function(e){
          if (ms.is(':focus')){
            var keyContainer = that.$selectableUl.hasClass('ms-focus') ? 'ms-selectable' : 'ms-selection';
            ms.onKeyDown(e, keyContainer);
          }
        });
      }

      var selectedValues = ms.find('option:selected').map(function(){ return $(this).val() }).get();
      that.select(selectedValues, 'init')

      if (typeof that.options.afterInit == 'function') {
        that.options.afterInit.call(this, this.$container);
      }
    },
    'refresh' : function() {
      $("#ms-"+this.$element.attr("id")).remove();
      this.init(this.options);
    },
    'select' : function(value, method){
      if (typeof value == 'string')
        value = [value]
      var that = this,
          ms = this.$element,
          selectables = this.$selectableUl.find('#' + value.join('-selectable, #')+'-selectable').filter(':not(.'+that.options.disabledClass+')'),
          selections = this.$selectionUl.find('#' + value.join('-selection, #') + '-selection'),
          options = ms.find('option:val('+value +')');

      if (selectables.length > 0){
        selectables.addClass('ms-selected').hide();
        selections.addClass('ms-selected').show();
        options.prop('selected', true);

        var selectableOptgroups = that.$selectableUl.children('.ms-optgroup-container');
        if (selectableOptgroups.length > 0){
          selectableOptgroups.each(function(){
            var selectablesLi = $(this).find('.ms-elem-selectable');
            if (selectablesLi.length == selectablesLi.filter('.ms-selected').length){
              $(this).find('.ms-optgroup-label').hide();
            }
          });

          var selectionOptgroups = that.$selectionUl.children('.ms-optgroup-container');
          selectionOptgroups.each(function(){
            var selectionsLi = $(this).find('.ms-elem-selection');
            if (selectionsLi.filter('.ms-selected').length > 0){
              $(this).find('.ms-optgroup-label').show();
            }
          });
        }
        if (method != 'init'){
          ms.focus();
          ms.trigger('change');
          if (typeof that.options.afterSelect == 'function') {
            that.options.afterSelect.call(this, value);
          }
        }
      }
    },
    'deselect' : function(value){
      if (typeof value == 'string')
        value = [value]
      var that = this,
          ms = this.$element,
          selectables = this.$selectableUl.find('#' + value.join('-selectable, #')+'-selectable'),
          selections = this.$selectionUl.find('#' + value.join('-selection, #')+'-selection').filter('.ms-selected'),
          options = ms.find('option:val('+value +')');

      if (selections.length > 0){
        selectables.removeClass('ms-selected').show();
        selections.removeClass('ms-selected').hide();
        options.prop('selected', false);

        var selectableOptgroups = that.$selectableUl.children('.ms-optgroup-container');
        if (selectableOptgroups.length > 0){
          selectableOptgroups.each(function(){
            var selectablesLi = $(this).find('.ms-elem-selectable');
            if (selectablesLi.filter(':not(.ms-selected)').length > 0){
              $(this).find('.ms-optgroup-label').show();
            }
          });

          var selectionOptgroups = that.$selectionUl.children('.ms-optgroup-container');
          selectionOptgroups.each(function(){
            var selectionsLi = $(this).find('.ms-elem-selection');
            if (selectionsLi.filter('.ms-selected').length == 0){
              $(this).find('.ms-optgroup-label').hide();
            }
          });
        }
        this.$selectionUl.focusin();
        ms.trigger('change');
        if (typeof that.options.afterDeselect == 'function') {
          that.options.afterDeselect.call(this, value);
        }
      }
    },
    'select_all' : function(){
      var ms = this.$element;

      ms.find('option').prop('selected', true);
      this.$selectableUl.find('.ms-elem-selectable').addClass('ms-selected').hide();
      this.$selectionUl.find('.ms-optgroup-label').show();
      this.$selectableUl.find('.ms-optgroup-label').hide();
      this.$selectionUl.find('.ms-elem-selection').addClass('ms-selected').show();
      this.$selectionUl.focusin();
      ms.trigger('change');
    },
    'deselect_all' : function(){
      var ms = this.$element;

      ms.find('option').prop('selected', false);
      this.$selectableUl.find('.ms-elem-selectable').removeClass('ms-selected').show();
      this.$selectionUl.find('.ms-optgroup-label').hide();
      this.$selectableUl.find('.ms-optgroup-label').show();
      this.$selectionUl.find('.ms-elem-selection').removeClass('ms-selected').hide();
      ms.focus();
      ms.trigger('change');
    }
  }

  /* MULTISELECT PLUGIN DEFINITION
   * ======================= */

  $.fn.multiSelect = function () {
    var option = arguments[0],
        args = arguments;

    return this.each(function () {
      var $this = $(this),
          data = $this.data('multiselect'),
          options = $.extend({}, $.fn.multiSelect.defaults, $this.data(), typeof option == 'object' && option);

      if (!data) $this.data('multiselect', (data = new MultiSelect(this, options)))

      if (typeof option == 'string'){
        data[option](args[1])
      } else {
        data.init();
      }
    })
  }

  $.fn.multiSelect.defaults = {
    disabledClass : 'disabled',
    dblClick : false
  }

  $.fn.multiSelect.Constructor = MultiSelect

  $.extend($.expr[':'], {
     val: function(elem, i, attr) {
       return elem.value === attr[3];
     }
  });

}(window.jQuery);<commit_msg>fix keyboard selection<commit_after>/*
* MultiSelect v0.9
* Copyright (c) 2012 Louis Cuny
*
* This program is free software. It comes without any warranty, to
* the extent permitted by applicable law. You can redistribute it
* and/or modify it under the terms of the Do What The Fuck You Want
* To Public License, Version 2, as published by Sam Hocevar. See
* http://sam.zoy.org/wtfpl/COPYING for more details.
*/

!function ($) {

  "use strict"; // jshint ;_;

 /* MULTISELECT CLASS DEFINITION
  * ====================== */

  var MultiSelect = function (element, options) {
    this.options = options;
    this.$element = $(element);
    this.$container = $('

');
    this.$selectableContainer = $('

');
    this.$selectionContainer = $('

');
    this.$selectableUl = $('

');
    this.$selectionUl = $('

');
  }

  MultiSelect.prototype = {
    constructor: MultiSelect,

    init: function(){
      var that = this,
          ms = this.$element;

      if (ms.next('.ms-container').length == 0){
        ms.css({ position: 'absolute', left: '-9999px' });
        ms.attr('id', ms.attr('id') ? ms.attr('id') : 'ms-'+Math.ceil(Math.random()*1000));

        var optgroupLabel = null,
            optgroupId = null,
            optgroupCpt = 0,
            scroll = 0;

        ms.find('optgroup, option').each(function(){
          if ($(this).is('optgroup')){
            optgroupLabel = $(this).attr('label');
            optgroupId = 'ms-'+ms.attr('id')+'-optgroup-'+optgroupCpt;

            that.$selectableUl.append(
              '
\

\

'+optgroupLabel+'
\

\

');
            that.$selectionUl.append(
              '
\

\

'+optgroupLabel+'
\

\

');
            optgroupCpt++;
          } else {

            var attributes = "";

            for (var cpt = 0; cpt < this.attributes.length; cpt++){
              var attr = this.attributes[cpt];

              attributes += attr.name+'="'+attr.value+'" ';
            }
            var selectableLi = $('
'+$(this).text()+'
'),
                selectedLi = selectableLi.clone();

            var value = $(this).val();
            selectableLi.addClass('ms-elem-selectable').attr('id', value+'-selectable');
            selectedLi.addClass('ms-elem-selection').attr('id', value+'-selection').hide();

            that.$selectionUl.find('.ms-optgroup-label').hide();

            if ($(this).prop('disabled') || ms.prop('disabled')){
              selectableLi.prop('disabled', true);
              selectableLi.addClass(that.options.disabledClass);
            }

            if (optgroupId){
              that.$selectableUl.children('#'+optgroupId+'-selectable').find('ul').first().append(selectableLi);
              that.$selectionUl.children('#'+optgroupId+'-selection').find('ul').first().append(selectedLi);
            } else {
              that.$selectableUl.append(selectableLi);
              that.$selectionUl.append(selectedLi);
            }
          }
        });

        if (that.options.selectableHeader){
          that.$selectableContainer.append(that.options.selectableHeader);
        }
        that.$selectableContainer.append(that.$selectableUl);

        if (that.options.selectionHeader){
          that.$selectionContainer.append(that.options.selectionHeader);
        }
        this.$selectionContainer.append(that.$selectionUl);

        that.$container.append(that.$selectableContainer);
        that.$container.append(that.$selectionContainer);
        ms.after(that.$container);
        that.$selectableUl.on('mouseenter', '.ms-elem-selectable', function(){
          $('li', that.$container).removeClass('ms-hover');
          $(this).addClass('ms-hover');
        }).on('mouseout', function(){
          $('li', that.$container).removeClass('ms-hover');
        });

        if(that.options.dblClick) {
          that.$selectableUl.on('dblclick', '.ms-elem-selectable', function(){
            that.select($(this).attr('id').replace(/-selectable/, ''));
          });
          that.$selectionUl.on('dblclick', '.ms-elem-selection', function(){
            that.deselect($(this).attr('id').replace(/-selection/, ''));
          });
        } else {
          that.$selectableUl.on('click', '.ms-elem-selectable', function(){
            that.select($(this).attr('id').replace(/-selectable/, ''));
          });
          that.$selectionUl.on('click', '.ms-elem-selection', function(){
            that.deselect($(this).attr('id').replace(/-selection/, ''));
          });
        }

        that.$selectionUl.on('mouseenter', '.ms-elem-selection', function(){
          $('li', that.$selectionUl).removeClass('ms-hover');
          $(this).addClass('ms-hover');
        }).on('mouseout', function(){
          $('li', that.$selectionUl).removeClass('ms-hover');
        });

        that.$selectableUl.on('focusin', function(){
          $(this).addClass('ms-focus');
          that.$selectionUl.focusout();
        }).on('focusout', function(){
          $(this).removeClass('ms-focus');
          $('li', that.$container).removeClass('ms-hover');
        });

        that.$selectionUl.on('focusin', function(){
          $(this).addClass('ms-focus');
        }).on('focusout', function(){
          $(this).removeClass('ms-focus');
          $('li', that.$container).removeClass('ms-hover');
        });

        ms.on('focusin', function(){
          that.$selectableUl.focus();
        }).on('focusout', function(){
          that.$selectableUl.removeClass('ms-focus');
          that.$selectionUl.removeClass('ms-focus');
        });

        ms.onKeyDown = function(e, keyContainer){
          var selectables = $('.'+keyContainer+' li:visible:not(.ms-optgroup-label, .ms-optgroup-container)', that.$container),
              selectablesLength = selectables.length,
              selectableFocused = $('.'+keyContainer+' li.ms-hover', that.$container),
              selectableFocusedIndex = $('.'+keyContainer+' li:visible:not(.ms-optgroup-label, .ms-optgroup-container)', this.$container).index(selectableFocused),
              liHeight = selectables.first().outerHeight(),
              numberOfItemsDisplayed = Math.ceil(that.$container.outerHeight()/liHeight),
              scrollStart = Math.ceil(numberOfItemsDisplayed/4);

          selectables.removeClass('ms-hover');
          if (e.keyCode == 32){ // space
            var method = keyContainer == 'ms-selectable' ? 'select' : 'deselect';
            if (keyContainer == 'ms-selectable'){
              that.select(selectableFocused.first().attr('id').replace('-selectable', ''));
            } else {
              that.deselect(selectableFocused.first().attr('id').replace('-selection', ''));
            }

          } else if (e.keyCode == 40){ // Down
            var nextIndex = (selectableFocusedIndex+1 != selectablesLength) ? selectableFocusedIndex+1 : 0,
                nextSelectableLi = selectables.eq(nextIndex);

            nextSelectableLi.addClass('ms-hover');
            if (nextIndex > scrollStart){
              scroll += liHeight;
            } else if (nextIndex == 0){
              scroll = 0;
            }
            $('.'+keyContainer+' ul', that.$container).scrollTop(scroll);
          } else if (e.keyCode == 38){ // Up
            var prevIndex = (selectableFocusedIndex-1 >= 0) ? selectableFocusedIndex-1 : selectablesLength-1,
                prevSelectableLi = selectables.eq(prevIndex);
            selectables.removeClass('ms-hover');
            prevSelectableLi.addClass('ms-hover');
            if (selectablesLength-prevIndex+1 < scrollStart){
              scroll = liHeight*(selectablesLength-scrollStart);
            } else {
              scroll -= liHeight;
            }
            $('.'+keyContainer+' ul', that.$container).scrollTop(scroll);
          } else if (e.keyCode == 37 || e.keyCode == 39){ // Right and Left
            if (that.$selectableUl.hasClass('ms-focus')){
              that.$selectableUl.focusout();
              that.$selectionUl.focusin();
            } else {
              that.$selectableUl.focusin();
              that.$selectionUl.focusout();
            }
          }
        }

        ms.on('keydown', function(e){
          if (ms.is(':focus')){
            var keyContainer = that.$selectableUl.hasClass('ms-focus') ? 'ms-selectable' : 'ms-selection';
            ms.onKeyDown(e, keyContainer);
          }
        });
      }

      var selectedValues = ms.find('option:selected').map(function(){ return $(this).val() }).get();
      that.select(selectedValues, 'init')

      if (typeof that.options.afterInit == 'function') {
        that.options.afterInit.call(this, this.$container);
      }
    },
    'refresh' : function() {
      $("#ms-"+this.$element.attr("id")).remove();
      this.init(this.options);
    },
    'select' : function(value, method){
      if (typeof value == 'string')
        value = [value]
      var that = this,
          ms = this.$element,
          selectables = this.$selectableUl.find('#' + value.join('-selectable, #')+'-selectable').filter(':not(.'+that.options.disabledClass+')'),
          selections = this.$selectionUl.find('#' + value.join('-selection, #') + '-selection'),
          options = ms.find('option:val('+value +')');

      if (selectables.length > 0){
        selectables.addClass('ms-selected').hide();
        selections.addClass('ms-selected').show();
        options.prop('selected', true);

        var selectableOptgroups = that.$selectableUl.children('.ms-optgroup-container');
        if (selectableOptgroups.length > 0){
          selectableOptgroups.each(function(){
            var selectablesLi = $(this).find('.ms-elem-selectable');
            if (selectablesLi.length == selectablesLi.filter('.ms-selected').length){
              $(this).find('.ms-optgroup-label').hide();
            }
          });

          var selectionOptgroups = that.$selectionUl.children('.ms-optgroup-container');
          selectionOptgroups.each(function(){
            var selectionsLi = $(this).find('.ms-elem-selection');
            if (selectionsLi.filter('.ms-selected').length > 0){
              $(this).find('.ms-optgroup-label').show();
            }
          });
        }
        if (method != 'init'){
          ms.focus();
          ms.trigger('change');
          if (typeof that.options.afterSelect == 'function') {
            that.options.afterSelect.call(this, value);
          }
        }
      }
    },
    'deselect' : function(value){
      if (typeof value == 'string')
        value = [value]
      var that = this,
          ms = this.$element,
          selectables = this.$selectableUl.find('#' + value.join('-selectable, #')+'-selectable'),
          selections = this.$selectionUl.find('#' + value.join('-selection, #')+'-selection').filter('.ms-selected'),
          options = ms.find('option:val('+value +')');

      if (selections.length > 0){
        selectables.removeClass('ms-selected').show();
        selections.removeClass('ms-selected').hide();
        options.prop('selected', false);

        var selectableOptgroups = that.$selectableUl.children('.ms-optgroup-container');
        if (selectableOptgroups.length > 0){
          selectableOptgroups.each(function(){
            var selectablesLi = $(this).find('.ms-elem-selectable');
            if (selectablesLi.filter(':not(.ms-selected)').length > 0){
              $(this).find('.ms-optgroup-label').show();
            }
          });

          var selectionOptgroups = that.$selectionUl.children('.ms-optgroup-container');
          selectionOptgroups.each(function(){
            var selectionsLi = $(this).find('.ms-elem-selection');
            if (selectionsLi.filter('.ms-selected').length == 0){
              $(this).find('.ms-optgroup-label').hide();
            }
          });
        }
        this.$selectionUl.focusin();
        ms.trigger('change');
        if (typeof that.options.afterDeselect == 'function') {
          that.options.afterDeselect.call(this, value);
        }
      }
    },
    'select_all' : function(){
      var ms = this.$element;

      ms.find('option').prop('selected', true);
      this.$selectableUl.find('.ms-elem-selectable').addClass('ms-selected').hide();
      this.$selectionUl.find('.ms-optgroup-label').show();
      this.$selectableUl.find('.ms-optgroup-label').hide();
      this.$selectionUl.find('.ms-elem-selection').addClass('ms-selected').show();
      this.$selectionUl.focusin();
      ms.trigger('change');
    },
    'deselect_all' : function(){
      var ms = this.$element;

      ms.find('option').prop('selected', false);
      this.$selectableUl.find('.ms-elem-selectable').removeClass('ms-selected').show();
      this.$selectionUl.find('.ms-optgroup-label').hide();
      this.$selectableUl.find('.ms-optgroup-label').show();
      this.$selectionUl.find('.ms-elem-selection').removeClass('ms-selected').hide();
      ms.focus();
      ms.trigger('change');
    }
  }

  /* MULTISELECT PLUGIN DEFINITION
   * ======================= */

  $.fn.multiSelect = function () {
    var option = arguments[0],
        args = arguments;

    return this.each(function () {
      var $this = $(this),
          data = $this.data('multiselect'),
          options = $.extend({}, $.fn.multiSelect.defaults, $this.data(), typeof option == 'object' && option);

      if (!data) $this.data('multiselect', (data = new MultiSelect(this, options)))

      if (typeof option == 'string'){
        data[option](args[1])
      } else {
        data.init();
      }
    })
  }

  $.fn.multiSelect.defaults = {
    disabledClass : 'disabled',
    dblClick : false
  }

  $.fn.multiSelect.Constructor = MultiSelect

  $.extend($.expr[':'], {
     val: function(elem, i, attr) {
       return elem.value === attr[3];
     }
  });

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


<commit_before>/*
* MultiSelect v0.7
* Copyright (c) 2012 Louis Cuny
*
* Dual licensed under the MIT and GPL licenses:
*    http://www.opensource.org/licenses/mit-license.php
*    http://www.gnu.org/licenses/gpl.html
*
*/

(function($){
  var msMethods = {
    'init' : function(options){
      this.settings = {
        disabledClass : 'disabled',
        selectCallbackOnInit: false,
        keepOrder : false
      };
      if(options) {
        this.settings = $.extend(this.settings, options);
      }
      var multiSelects = this;
      multiSelects.css('position', 'absolute').css('left', '-9999px');
      multiSelects.each(function(){
        var ms = $(this);

        if (ms.next('.ms-container').length == 0){
          ms.attr('id', ms.attr('id') ? ms.attr('id') : 'ms-'+Math.ceil(Math.random()*1000));
          var container = $('

'),
              selectableContainer = $('

'),
              selectedContainer = $('

'),
              selectableUl = $('

'),
              selectedUl = $('

');

          ms.data('settings', multiSelects.settings);

          var optgroupLabel = null,
              optgroupId = null,
              optgroupCpt = 0,
              scroll = 0;
          ms.find('optgroup,option').each(function(){
            if ($(this).is('optgroup')){
              optgroupLabel = $(this).attr('label');
              optgroupId = 'ms-'+ms.attr('id')+'-optgroup-'+optgroupCpt;
              selectableUl.append($('

'+
                                  optgroupLabel+'

'));
              optgroupCpt++;
            }
            if ($(this).is("option:not(option[value=''])")){
              var klass = $(this).attr('class') ? ' '+$(this).attr('class') : '';
              var selectableLi = $('
'+$(this).text()+'
');

              if ($(this).attr('title'))
                selectableLi.attr('title', $(this).attr('title'));
              if ($(this).attr('disabled') || ms.attr('disabled')){
                selectableLi.attr('disabled', 'disabled');
                selectableLi.addClass(multiSelects.settings.disabledClass);
              }
              selectableLi.click(function(){
                ms.multiSelect('select', $(this).attr('ms-value'));
              });
              var container = optgroupId ? selectableUl.children('#'+optgroupId).find('ul').first() : selectableUl;
              container.append(selectableLi);
            }
          });
          if (multiSelects.settings.selectableHeader){
            selectableContainer.append(multiSelects.settings.selectableHeader);
          }
          selectableContainer.append(selectableUl);
          if (multiSelects.settings.selectedHeader){
            selectedContainer.append(multiSelects.settings.selectedHeader);
          }
          selectedContainer.append(selectedUl);
          container.append(selectableContainer);
          container.append(selectedContainer);
          ms.after(container);
          ms.find('option:selected').each(function(){
            ms.multiSelect('select', $(this).val(), 'init');
          });

          $('.ms-elem-selectable', selectableUl).on('mouseenter', function(){
            $('li', container).removeClass('ms-hover');
            $(this).addClass('ms-hover');
          }).on('mouseout', function(){
            $('li', container).removeClass('ms-hover');
          });

          selectableUl.on('focusin', function(){
            $(this).addClass('ms-focus');
            selectedUl.focusout();
          }).on('focusout', function(){
            $(this).removeClass('ms-focus');
            $('li', container).removeClass('ms-hover');
          });

          selectedUl.on('focusin', function(){
            $(this).addClass('ms-focus');
          }).on('focusout', function(){
            $(this).removeClass('ms-focus');
            $('li', container).removeClass('ms-hover');
          });

          ms.on('focusin', function(){
            selectableUl.focus();
          }).on('focusout', function(){
            selectableUl.removeClass('ms-focus');
            selectedUl.removeClass('ms-focus');
          });

          ms.onKeyDown = function(e, keyContainer){
            var selectables = $('.'+keyContainer+' li:visible:not(.ms-optgroup-label, .ms-optgroup-container)', container),
                selectablesLength = selectables.length,
                selectableFocused = $('.'+keyContainer+' li.ms-hover', container),
                selectableFocusedIndex = $('.'+keyContainer+' li:visible:not(.ms-optgroup-label, .ms-optgroup-container)', container).index(selectableFocused),
                liHeight = selectables.first().outerHeight(),
                numberOfItemsDisplayed = Math.ceil(container.outerHeight()/liHeight),
                scrollStart = Math.ceil(numberOfItemsDisplayed/4);

            selectables.removeClass('ms-hover');
            if (e.keyCode == 32){ // space
              var method = keyContainer == 'ms-selectable' ? 'select' : 'deselect';
              ms.multiSelect(method, selectableFocused.first().attr('ms-value'));

            } else if (e.keyCode == 40){ // Down
              var nextIndex = (selectableFocusedIndex+1 != selectablesLength) ? selectableFocusedIndex+1 : 0,
                  nextSelectableLi = selectables.eq(nextIndex);

              nextSelectableLi.addClass('ms-hover');
              if (nextIndex > scrollStart){
                scroll += liHeight;
              } else if (nextIndex == 0){
                scroll = 0;
              }
              $('.'+keyContainer+' ul', container).scrollTop(scroll);
            } else if (e.keyCode == 38){ // Up
              var prevIndex = (selectableFocusedIndex-1 >= 0) ? selectableFocusedIndex-1 : selectablesLength-1,
                  prevSelectableLi = selectables.eq(prevIndex);
              selectables.removeClass('ms-hover');
              prevSelectableLi.addClass('ms-hover');
              if (selectablesLength-prevIndex+1 < scrollStart){
                scroll = liHeight*(selectablesLength-scrollStart);
              } else {
                scroll -= liHeight;
              }
              $('.'+keyContainer+' ul', container).scrollTop(scroll);
            } else if (e.keyCode == 37 || e.keyCode == 39){ // Right and Left
              if (selectableUl.hasClass('ms-focus')){
                selectableUl.focusout();
                selectedUl.focusin();
              } else {
                selectableUl.focusin();
                selectedUl.focusout();
              }
            }
          }

          ms.on('keydown', function(e){
            if (ms.is(':focus')){
              var keyContainer = selectableUl.hasClass('ms-focus') ? 'ms-selectable' : 'ms-selection';
              ms.onKeyDown(e, keyContainer);
            }
          });
        }
      });
    },
    'refresh' : function() {
      $("#ms-"+$(this).attr("id")).remove();
      $(this).multiSelect("init", $(this).data("settings"));
    },
    'select' : function(value, method){
      var ms = this,
          selectedOption = ms.find('option[value="'+value +'"]'),
          text = selectedOption.text(),
          klass = selectedOption.attr('class'),
          titleAttr = selectedOption.attr('title');

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

      if (method == 'init'){
        haveToSelect = !selectableLi.hasClass(ms.data('settings').disabledClass) && selectedOption.attr('selected');
      } else {
        haveToSelect = !selectableLi.hasClass(ms.data('settings').disabledClass);
      }
      if (haveToSelect && value && value != '' && selectedUl.children('li[ms-value="'+value+'"]').length == 0){
        ms.focus();
        var parentOptgroup = selectableLi.parent('.ms-optgroup');
        if (parentOptgroup.length > 0)
          if (parentOptgroup.children('.ms-elem-selectable:not(:hidden)').length == 1)
            parentOptgroup.children('.ms-optgroup-label').hide();
        selectableLi.addClass('ms-selected');
        selectableLi.hide();
        selectedOption.attr('selected', 'selected');
        if(titleAttr){
          selectedLi.attr('title', titleAttr)
        }
        if (selectableLi.hasClass(ms.data('settings').disabledClass)){
          selectedLi.addClass(ms.data('settings').disabledClass);
        } else {
          selectedLi.click(function(){
            ms.multiSelect('deselect', $(this).attr('ms-value'));
          });
        }

        var selectedUlLis = selectedUl.children('.ms-elem-selected');
        if (method != 'init' && ms.data('settings').keepOrder && selectedUlLis.length > 0) {

          var getIndexOf = function(value) {
            elems = selectableUl.children('.ms-elem-selectable');
            return(elems.index(elems.closest('[ms-value="'+value+'"]')));
          }

          var index = getIndexOf(selectedLi.attr('ms-value'));
          if (index == 0)
            selectedUl.prepend(selectedLi);
          else {
            for (i = index - 1; i >= 0; i--){
              if (selectedUlLis[i] && getIndexOf($(selectedUlLis[i]).attr('ms-value')) < index) {
                $(selectedUlLis[i]).after(selectedLi);
                break;
              } else if (i == 0) {
                $(selectedUlLis[i]).before(selectedLi);
              }
            }
          }
        } else {
          selectedUl.append(selectedLi);
        }
        selectedLi.on('mouseenter', function(){
          $('li', selectedUl).removeClass('ms-hover');
          $(this).addClass('ms-hover');
        }).on('mouseout', function(){
          $('li', selectedUl).removeClass('ms-hover');
        });
        if (ms.find("option[value='']")){
          ms.find("option[value='']").removeAttr('selected');
        }
        if (method == "select_all" && parentOptgroup.children('.ms-elem-selectable').length > 0){
          parentOptgroup.children('.ms-optgroup-label').hide();
        }
        if(method != 'init' || ms.data('settings').selectCallbackOnInit){
          ms.trigger('change');
          selectedUl.trigger('change');
          selectableUl.trigger('change');
          if (typeof ms.data('settings').afterSelect == 'function' &&
              (method != 'init' || ms.data('settings').selectCallbackOnInit)) {
            ms.data('settings').afterSelect.call(this, value, text);
          }
        }
      }
    },
    'deselect' : function(value){
      var ms = this,
          selectedUl = $('#ms-'+ms.attr('id')+' .ms-selection ul'),
          selectedOption = ms.find('option[value="'+value +'"]'),
          selectedLi = selectedUl.children('li[ms-value="'+value+'"]');

      if(selectedLi){
        selectedUl.focusin();
        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+'"]');

        var parentOptgroup = selectableLi.parent('.ms-optgroup');
        if (parentOptgroup.length > 0){
          parentOptgroup.children('.ms-optgroup-label').addClass('ms-collapse').show();
          parentOptgroup.children('.ms-elem-selectable:not(.ms-selected)').show();
        }
        selectedOption.removeAttr('selected');
        selectableLi.show();
        selectableLi.removeClass('ms-selected');
        selectedLi.remove();
        selectedUl.trigger('change');
        selectableUl.trigger('change');
        ms.trigger('change');
        if (typeof ms.data('settings').afterDeselect == 'function') {
          ms.data('settings').afterDeselect.call(this, value, selectedLi.text());
        }
      }
    },
    'select_all' : function(visible){
      var ms = this,
          selectableUl = $('#ms-'+ms.attr('id')+' .ms-selectable ul');

      ms.find("option:not(option[value=''])").each(function(){
        var value = $(this).val();
        if (visible){
          var selectableLi = selectableUl.children('li[ms-value="'+value+'"]');
          if (selectableLi.filter(':visible').length > 0){
            ms.multiSelect('select', value, 'select_all');
          }
        } else {
          ms.multiSelect('select', value, 'select_all');
        }
      });
    },
    'deselect_all' : function(){
      var ms = this;
      ms.find("option:not(option[value=''])").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' );
    }
    return false;
  };
})(jQuery);
<commit_msg>do not focus on intit<commit_after>/*
* MultiSelect v0.7
* Copyright (c) 2012 Louis Cuny
*
* Dual licensed under the MIT and GPL licenses:
*    http://www.opensource.org/licenses/mit-license.php
*    http://www.gnu.org/licenses/gpl.html
*
*/

(function($){
  var msMethods = {
    'init' : function(options){
      this.settings = {
        disabledClass : 'disabled',
        selectCallbackOnInit: false,
        keepOrder : false
      };
      if(options) {
        this.settings = $.extend(this.settings, options);
      }
      var multiSelects = this;
      multiSelects.css('position', 'absolute').css('left', '-9999px');
      multiSelects.each(function(){
        var ms = $(this);

        if (ms.next('.ms-container').length == 0){
          ms.attr('id', ms.attr('id') ? ms.attr('id') : 'ms-'+Math.ceil(Math.random()*1000));
          var container = $('

'),
              selectableContainer = $('

'),
              selectedContainer = $('

'),
              selectableUl = $('

'),
              selectedUl = $('

');

          ms.data('settings', multiSelects.settings);

          var optgroupLabel = null,
              optgroupId = null,
              optgroupCpt = 0,
              scroll = 0;
          ms.find('optgroup,option').each(function(){
            if ($(this).is('optgroup')){
              optgroupLabel = $(this).attr('label');
              optgroupId = 'ms-'+ms.attr('id')+'-optgroup-'+optgroupCpt;
              selectableUl.append($('

'+
                                  optgroupLabel+'

'));
              optgroupCpt++;
            }
            if ($(this).is("option:not(option[value=''])")){
              var klass = $(this).attr('class') ? ' '+$(this).attr('class') : '';
              var selectableLi = $('
'+$(this).text()+'
');

              if ($(this).attr('title'))
                selectableLi.attr('title', $(this).attr('title'));
              if ($(this).attr('disabled') || ms.attr('disabled')){
                selectableLi.attr('disabled', 'disabled');
                selectableLi.addClass(multiSelects.settings.disabledClass);
              }
              selectableLi.click(function(){
                ms.multiSelect('select', $(this).attr('ms-value'));
              });
              var container = optgroupId ? selectableUl.children('#'+optgroupId).find('ul').first() : selectableUl;
              container.append(selectableLi);
            }
          });
          if (multiSelects.settings.selectableHeader){
            selectableContainer.append(multiSelects.settings.selectableHeader);
          }
          selectableContainer.append(selectableUl);
          if (multiSelects.settings.selectedHeader){
            selectedContainer.append(multiSelects.settings.selectedHeader);
          }
          selectedContainer.append(selectedUl);
          container.append(selectableContainer);
          container.append(selectedContainer);
          ms.after(container);
          ms.find('option:selected').each(function(){
            ms.multiSelect('select', $(this).val(), 'init');
          });

          $('.ms-elem-selectable', selectableUl).on('mouseenter', function(){
            $('li', container).removeClass('ms-hover');
            $(this).addClass('ms-hover');
          }).on('mouseout', function(){
            $('li', container).removeClass('ms-hover');
          });

          selectableUl.on('focusin', function(){
            $(this).addClass('ms-focus');
            selectedUl.focusout();
          }).on('focusout', function(){
            $(this).removeClass('ms-focus');
            $('li', container).removeClass('ms-hover');
          });

          selectedUl.on('focusin', function(){
            $(this).addClass('ms-focus');
          }).on('focusout', function(){
            $(this).removeClass('ms-focus');
            $('li', container).removeClass('ms-hover');
          });

          ms.on('focusin', function(){
            selectableUl.focus();
          }).on('focusout', function(){
            selectableUl.removeClass('ms-focus');
            selectedUl.removeClass('ms-focus');
          });

          ms.onKeyDown = function(e, keyContainer){
            var selectables = $('.'+keyContainer+' li:visible:not(.ms-optgroup-label, .ms-optgroup-container)', container),
                selectablesLength = selectables.length,
                selectableFocused = $('.'+keyContainer+' li.ms-hover', container),
                selectableFocusedIndex = $('.'+keyContainer+' li:visible:not(.ms-optgroup-label, .ms-optgroup-container)', container).index(selectableFocused),
                liHeight = selectables.first().outerHeight(),
                numberOfItemsDisplayed = Math.ceil(container.outerHeight()/liHeight),
                scrollStart = Math.ceil(numberOfItemsDisplayed/4);

            selectables.removeClass('ms-hover');
            if (e.keyCode == 32){ // space
              var method = keyContainer == 'ms-selectable' ? 'select' : 'deselect';
              ms.multiSelect(method, selectableFocused.first().attr('ms-value'));

            } else if (e.keyCode == 40){ // Down
              var nextIndex = (selectableFocusedIndex+1 != selectablesLength) ? selectableFocusedIndex+1 : 0,
                  nextSelectableLi = selectables.eq(nextIndex);

              nextSelectableLi.addClass('ms-hover');
              if (nextIndex > scrollStart){
                scroll += liHeight;
              } else if (nextIndex == 0){
                scroll = 0;
              }
              $('.'+keyContainer+' ul', container).scrollTop(scroll);
            } else if (e.keyCode == 38){ // Up
              var prevIndex = (selectableFocusedIndex-1 >= 0) ? selectableFocusedIndex-1 : selectablesLength-1,
                  prevSelectableLi = selectables.eq(prevIndex);
              selectables.removeClass('ms-hover');
              prevSelectableLi.addClass('ms-hover');
              if (selectablesLength-prevIndex+1 < scrollStart){
                scroll = liHeight*(selectablesLength-scrollStart);
              } else {
                scroll -= liHeight;
              }
              $('.'+keyContainer+' ul', container).scrollTop(scroll);
            } else if (e.keyCode == 37 || e.keyCode == 39){ // Right and Left
              if (selectableUl.hasClass('ms-focus')){
                selectableUl.focusout();
                selectedUl.focusin();
              } else {
                selectableUl.focusin();
                selectedUl.focusout();
              }
            }
          }

          ms.on('keydown', function(e){
            if (ms.is(':focus')){
              var keyContainer = selectableUl.hasClass('ms-focus') ? 'ms-selectable' : 'ms-selection';
              ms.onKeyDown(e, keyContainer);
            }
          });
        }
      });
    },
    'refresh' : function() {
      $("#ms-"+$(this).attr("id")).remove();
      $(this).multiSelect("init", $(this).data("settings"));
    },
    'select' : function(value, method){
      var ms = this,
          selectedOption = ms.find('option[value="'+value +'"]'),
          text = selectedOption.text(),
          klass = selectedOption.attr('class'),
          titleAttr = selectedOption.attr('title');

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

      if (method == 'init'){
        haveToSelect = !selectableLi.hasClass(ms.data('settings').disabledClass) && selectedOption.attr('selected');
      } else {
        haveToSelect = !selectableLi.hasClass(ms.data('settings').disabledClass);
        ms.focus();
      }
      if (haveToSelect && value && value != '' && selectedUl.children('li[ms-value="'+value+'"]').length == 0){
        var parentOptgroup = selectableLi.parent('.ms-optgroup');
        if (parentOptgroup.length > 0)
          if (parentOptgroup.children('.ms-elem-selectable:not(:hidden)').length == 1)
            parentOptgroup.children('.ms-optgroup-label').hide();
        selectableLi.addClass('ms-selected');
        selectableLi.hide();
        selectedOption.attr('selected', 'selected');
        if(titleAttr){
          selectedLi.attr('title', titleAttr)
        }
        if (selectableLi.hasClass(ms.data('settings').disabledClass)){
          selectedLi.addClass(ms.data('settings').disabledClass);
        } else {
          selectedLi.click(function(){
            ms.multiSelect('deselect', $(this).attr('ms-value'));
          });
        }

        var selectedUlLis = selectedUl.children('.ms-elem-selected');
        if (method != 'init' && ms.data('settings').keepOrder && selectedUlLis.length > 0) {

          var getIndexOf = function(value) {
            elems = selectableUl.children('.ms-elem-selectable');
            return(elems.index(elems.closest('[ms-value="'+value+'"]')));
          }

          var index = getIndexOf(selectedLi.attr('ms-value'));
          if (index == 0)
            selectedUl.prepend(selectedLi);
          else {
            for (i = index - 1; i >= 0; i--){
              if (selectedUlLis[i] && getIndexOf($(selectedUlLis[i]).attr('ms-value')) < index) {
                $(selectedUlLis[i]).after(selectedLi);
                break;
              } else if (i == 0) {
                $(selectedUlLis[i]).before(selectedLi);
              }
            }
          }
        } else {
          selectedUl.append(selectedLi);
        }
        selectedLi.on('mouseenter', function(){
          $('li', selectedUl).removeClass('ms-hover');
          $(this).addClass('ms-hover');
        }).on('mouseout', function(){
          $('li', selectedUl).removeClass('ms-hover');
        });
        if (ms.find("option[value='']")){
          ms.find("option[value='']").removeAttr('selected');
        }
        if (method == "select_all" && parentOptgroup.children('.ms-elem-selectable').length > 0){
          parentOptgroup.children('.ms-optgroup-label').hide();
        }
        if(method != 'init' || ms.data('settings').selectCallbackOnInit){
          ms.trigger('change');
          selectedUl.trigger('change');
          selectableUl.trigger('change');
          if (typeof ms.data('settings').afterSelect == 'function' &&
              (method != 'init' || ms.data('settings').selectCallbackOnInit)) {
            ms.data('settings').afterSelect.call(this, value, text);
          }
        }
      }
    },
    'deselect' : function(value){
      var ms = this,
          selectedUl = $('#ms-'+ms.attr('id')+' .ms-selection ul'),
          selectedOption = ms.find('option[value="'+value +'"]'),
          selectedLi = selectedUl.children('li[ms-value="'+value+'"]');

      if(selectedLi){
        selectedUl.focusin();
        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+'"]');

        var parentOptgroup = selectableLi.parent('.ms-optgroup');
        if (parentOptgroup.length > 0){
          parentOptgroup.children('.ms-optgroup-label').addClass('ms-collapse').show();
          parentOptgroup.children('.ms-elem-selectable:not(.ms-selected)').show();
        }
        selectedOption.removeAttr('selected');
        selectableLi.show();
        selectableLi.removeClass('ms-selected');
        selectedLi.remove();
        selectedUl.trigger('change');
        selectableUl.trigger('change');
        ms.trigger('change');
        if (typeof ms.data('settings').afterDeselect == 'function') {
          ms.data('settings').afterDeselect.call(this, value, selectedLi.text());
        }
      }
    },
    'select_all' : function(visible){
      var ms = this,
          selectableUl = $('#ms-'+ms.attr('id')+' .ms-selectable ul');

      ms.find("option:not(option[value=''])").each(function(){
        var value = $(this).val();
        if (visible){
          var selectableLi = selectableUl.children('li[ms-value="'+value+'"]');
          if (selectableLi.filter(':visible').length > 0){
            ms.multiSelect('select', value, 'select_all');
          }
        } else {
          ms.multiSelect('select', value, 'select_all');
        }
      });
    },
    'deselect_all' : function(){
      var ms = this;
      ms.find("option:not(option[value=''])").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' );
    }
    return false;
  };
})(jQuery);
<|endoftext|>


<commit_before>/*
Copyright (c) 2015, Geomatics and Cartographic Research Centre, Carleton
University
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

 - Redistributions of source code must retain the above copyright notice,
   this list of conditions and the following disclaimer.
 - Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.
 - Neither the name of the Geomatics and Cartographic Research Centre,
   Carleton University nor the names of its contributors may be used to
   endorse or promote products derived from this software without specific
   prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

;(function($,$n2) {
"use strict";

var
 _loc = function(str,args){ return $n2.loc(str,'nunaliit2',args); }
 ,DH = 'n2.canvasGrid'
 ;

// --------------------------------------------------------------------------
/*
This canvas displays a grid of elements provided by an element generator. The original purpose
for this canvas is to provide a simple way to display a photo grid which are referenced linked
to specific documents.

The attribute for each grid cell is described here:
 - 	id: a doc id for use as a reference link and as the label of grid cell
 - 	gridImage: an object which contains two properties (doc and attachment) to provide the required
 	information for the insertMediaView show service.
 	- gridImage.doc: provides the doc id of the image
	- gridImage.attachement: provided the filename of the attachment
*/
var GridCanvas = $n2.Class('GridCanvas',{

	canvasId: null,

	sourceModelId: null,

	elementGenerator: null,

	dispatchService: null,

	showService: null,

	elementsById: null,

	intentView: null,

	initialize: function(opts_){
		var opts = $n2.extend({
			canvasId: null
			,sourceModelId: null
			,elementGenerator: null
			,config: null
			,moduleDisplay: null
			,elemIdToDocId: null
			,onSuccess: function(){}
			,onError: function(err){}
		},opts_);

		var _this = this;

		try {
			this.canvasId = opts.canvasId;
			this.sourceModelId = opts.sourceModelId;
			this.elementGenerator = opts.elementGenerator;

			var config = opts.config;
			if( config ){
				if( config.directory ){
					this.dispatchService = config.directory.dispatchService;
					this.showService = config.directory.showService;
				};
			};

			this.elementsById = {};

	 		// Element generator
	 		if( this.elementGenerator ){
				this.elementGenerator.setElementsChangedListener(function(added, updated, removed){
					_this._elementsChanged(added, updated, removed);
				});
				this.elementGenerator.setIntentChangedListener(function(updated){
					_this._intentChanged(updated);
				});
	 		};

	 		// Register to events
	 		if( this.dispatchService ){
	 			var f = function(m){
	 				_this._handleDispatch(m);
	 			};

	 			this.dispatchService.register(DH,'modelGetInfo',f);
	 			this.dispatchService.register(DH,'modelStateUpdated',f);
	 		};

	 		this._createGrid();

	 		$n2.log(this._classname,this);

		} catch(e) {
			var error = new Error('Unable to create '+this._classname+': '+err);
			opts.onError(error);
		};

 		opts.onSuccess();
 	},

	_getElem: function(){
		var $elem = $('#'+this.canvasId);
		if( $elem.length < 1 ){
			return undefined;
		};
		return $elem;
	},

 	_createGrid: function(){
		var _this = this;

		var $elem = this._getElem();
		if( $elem ){
			$elem
				.empty()
				.addClass('n2gridcanvas')
				.click(function(e){
					_this._backgroundClicked();
				});
		};
 	},

	_backgroundClicked: function(){
		if( this.dispatchService ){
			this.dispatchService.send(DH,{
				type: 'userUnselect'
			});
		};
	},

 	_elementsChanged: function(addedElements, updatedElements, removedElements){
 		var _this = this;

 		// Remove elements that are no longer there
		for(var i=0,e=removedElements.length; i<e; ++i){
			var removed = removedElements[i];
			delete this.elementsById[removed.id];
		};

		// Add elements
		for(var i=0,e=addedElements.length; i<e; ++i){
			var addedElement = addedElements[i];
			this.elementsById[addedElement.id] = addedElement;
		};

		// Update elements
		for(var i=0,e=updatedElements.length; i<e; ++i){
			var updated = updatedElements[i];
			this.elementsById[ updated.id ] = updated;
		};

		this._redrawGrid();
 	},

 	_redrawGrid: function() {
		var _this = this;
		var $elem = this._getElem();
		var $grid = $('.n2gridcanvas');

		$grid.empty();

		for (var element in this.elementsById){

			// Create an empty grid cell
			var $gridCell = $('<div>')
				.attr('class','n2gridcanvas_cell')
				.css('background-color','#EFEFEF')
				.appendTo($grid);

			var $gridCellImage = $('<div>')
				.attr('class','n2gridcanvas_cell_image')
				.appendTo($gridCell);

			var $gridCellLabel = $('<div>')
				.attr('class','n2gridcanvas_cell_label')
				.appendTo($gridCell);

			// Add image to grid cell if available
			if( this.elementsById[element].gridImage ){
				var cellImage = this.elementsById[element].gridImage;
				var $GridImage = $('<span>')
				.attr('class','n2s_insertMediaView')
				.attr('nunaliit-document',cellImage.doc)
				.attr('nunaliit-attachment',cellImage.attachment)
				.appendTo($gridCellImage);
			};

			// Add label/referencelink to grid cell if available
			if ( this.elementsById[element].id ){
				var $GridLabel = $('<span>')
				.attr('class','n2s_referenceLink')
				.attr('nunaliit-document',this.elementsById[element].id)
				.appendTo($gridCellLabel);
			};
		};

		this.showService.fixElementAndChildren($grid);
	},

 	_sourceModelUpdated: function(state){
 		this.elementGenerator.sourceModelUpdated(state);
 	},

 	_handleDispatch: function(m){
 		if( 'modelGetInfo' === m.type ){
 			if( m.modelId === this.modelId ){
 				m.modelInfo = this._getModelInfo();
 			};

 		} else if( 'modelStateUpdated' === m.type ) {
 			if( this.sourceModelId === m.modelId ){
 				if( m.state ){
 					this._sourceModelUpdated(m.state);
 				};
 			};
 		};
 	}
});

//--------------------------------------------------------------------------
function HandleCanvasAvailableRequest(m){
	if( m.canvasType === 'grid' ){
		m.isAvailable = true;
	};
};

//--------------------------------------------------------------------------
function HandleCanvasDisplayRequest(m){
	if( m.canvasType === 'grid' ){

		var options = {};
		if( m.canvasOptions ){
			for(var key in m.canvasOptions){
				options[key] = m.canvasOptions[key];
			};
		};

 		if( !options.elementGenerator ){
 			// If not defined, use the one specified by type
 			options.elementGenerator = $n2.canvasElementGenerator.CreateElementGenerator({
 	 			type: options.elementGeneratorType
 	 			,options: options.elementGeneratorOptions
 	 			,config: m.config
 	 		});
 		};

		options.canvasId = m.canvasId;
		options.config = m.config;
		options.onSuccess = m.onSuccess;
		options.onError = m.onError;

		new GridCanvas(options);
	};
};

//--------------------------------------------------------------------------
$n2.canvasGrid = {
	GridCanvas: GridCanvas
	,HandleCanvasAvailableRequest: HandleCanvasAvailableRequest
	,HandleCanvasDisplayRequest: HandleCanvasDisplayRequest
};

})(jQuery,nunaliit2);
<commit_msg>nunaliit2-js: Performance improvements for Grid Canvas<commit_after>/*
Copyright (c) 2015, Geomatics and Cartographic Research Centre, Carleton
University
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

 - Redistributions of source code must retain the above copyright notice,
   this list of conditions and the following disclaimer.
 - Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.
 - Neither the name of the Geomatics and Cartographic Research Centre,
   Carleton University nor the names of its contributors may be used to
   endorse or promote products derived from this software without specific
   prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

;(function($,$n2) {
"use strict";

var
 _loc = function(str,args){ return $n2.loc(str,'nunaliit2',args); }
 ,DH = 'n2.canvasGrid'
 ;

// --------------------------------------------------------------------------
/*
This canvas displays a grid of elements provided by an element generator. The original purpose
for this canvas is to provide a simple way to display a photo grid which are referenced linked
to specific documents.

The attribute for each grid cell is described here:
 - 	id: a doc id for use as a reference link and as the label of grid cell
 - 	gridImage: an object which contains two properties (doc and attachment) to provide the required
 	information for the insertMediaView show service.
 	- gridImage.doc: provides the doc id of the image
	- gridImage.attachement: provided the filename of the attachment
*/
var GridCanvas = $n2.Class('GridCanvas',{

	canvasId: null,

	sourceModelId: null,

	elementGenerator: null,

	dispatchService: null,

	showService: null,

	elementsById: null,

	intentView: null,

	initialize: function(opts_){
		var opts = $n2.extend({
			canvasId: null
			,sourceModelId: null
			,elementGenerator: null
			,config: null
			,moduleDisplay: null
			,elemIdToDocId: null
			,onSuccess: function(){}
			,onError: function(err){}
		},opts_);

		var _this = this;

		try {
			this.canvasId = opts.canvasId;
			this.sourceModelId = opts.sourceModelId;
			this.elementGenerator = opts.elementGenerator;

			var config = opts.config;
			if( config ){
				if( config.directory ){
					this.dispatchService = config.directory.dispatchService;
					this.showService = config.directory.showService;
				};
			};

			this.elementsById = {};

	 		// Element generator
	 		if( this.elementGenerator ){
				this.elementGenerator.setElementsChangedListener(function(added, updated, removed){
					_this._elementsChanged(added, updated, removed);
				});
				this.elementGenerator.setIntentChangedListener(function(updated){
					_this._intentChanged(updated);
				});
	 		};

	 		// Register to events
	 		if( this.dispatchService ){
	 			var f = function(m){
	 				_this._handleDispatch(m);
	 			};

	 			this.dispatchService.register(DH,'modelGetInfo',f);
	 			this.dispatchService.register(DH,'modelStateUpdated',f);
	 			this.dispatchService.register(DH,'windowResized',f);
	 		};

	 		this._createGrid();

	 		$n2.log(this._classname,this);

		} catch(e) {
			var error = new Error('Unable to create '+this._classname+': '+err);
			opts.onError(error);
		};

 		opts.onSuccess();
 	},

	_getElem: function(){
		var $elem = $('#'+this.canvasId);
		if( $elem.length < 1 ){
			return undefined;
		};
		return $elem;
	},

 	_createGrid: function(){
		var _this = this;

		var $elem = this._getElem();
		if( $elem ){
			$elem
				.empty()
				.addClass('n2gridcanvas')
				.click(function(e){
					_this._backgroundClicked();
				})
				.scroll(function(){
					_this._scrollChanged( $(this) );
					return false;
				});
		};
 	},

	_backgroundClicked: function(){
		if( this.dispatchService ){
			this.dispatchService.send(DH,{
				type: 'userUnselect'
			});
		};
	},

 	_elementsChanged: function(addedElements, updatedElements, removedElements){
 		var _this = this;

 		// Remove elements that are no longer there
		for(var i=0,e=removedElements.length; i<e; ++i){
			var removed = removedElements[i];
			delete this.elementsById[removed.id];
		};

		// Add elements
		for(var i=0,e=addedElements.length; i<e; ++i){
			var addedElement = addedElements[i];
			this.elementsById[addedElement.id] = addedElement;
		};

		// Update elements
		for(var i=0,e=updatedElements.length; i<e; ++i){
			var updated = updatedElements[i];
			this.elementsById[ updated.id ] = updated;
		};

		this._redrawGrid();
 	},

 	_redrawGrid: function() {
		var _this = this;
		var $elem = this._getElem();
		var $grid = $('.n2gridcanvas');

		$grid.empty();

		for (var elementId in this.elementsById){
			// Create an empty grid cell
			var $gridCell = $('<div>')
				.addClass('n2gridcanvas_cell')
				.attr('n2-element-id', elementId)
				.css('background-color','#EFEFEF')
				.appendTo($grid);
		};

		this._reloadTiles();
	},

	/*
	 * Attempts to load the content of the visible tiles
	 */
	_reloadTiles: function(){
		var _this = this;

		var $canvas = this._getElem();

		var canvasWidth = $canvas.width();
		var canvasHeight = $canvas.height();
		var canvasOffsetTop = $canvas.scrollTop();
		var canvasOffsetLeft = $canvas.scrollLeft();

		$canvas.find('.n2gridcanvas_cell').each(function(){
			var $cell = $(this);

			var cellPosition = $cell.position();
			var cellHeight = $cell.height();
			var cellWidth = $cell.width();

			var show = true;
			if( cellPosition.top > canvasHeight ){
				show = false;
			} else if( (cellPosition.top + cellHeight) < 0 ){
				show = false;
			} else if( cellPosition.left > canvasWidth ){
				show = false;
			} else if( (cellPosition.left + cellWidth) < 0 ){
				show = false;
			};

			if( show ){
				if( $cell.hasClass('n2gridcanvas_cell_show') ){
					// Already done
				} else {
					_this._displayTile($cell);
					$cell.addClass('n2gridcanvas_cell_show');
				};
			} else {
				if( $cell.hasClass('n2gridcanvas_cell_show') ){
					$cell.empty().removeClass('n2gridcanvas_cell_show');
				};
			};
		});
	},

	_displayTile: function($cell){
		var elementId = $cell.attr('n2-element-id');
		var element = this.elementsById[elementId];

		if( element ){
			$cell.empty();

			var $gridCellImage = $('<div>')
				.addClass('n2gridcanvas_cell_image')
				.appendTo($cell);

			var $gridCellLabel = $('<div>')
				.addClass('n2gridcanvas_cell_label')
				.appendTo($cell);

			// Add image to grid cell if available
			if( element.gridImage ){
				var cellImage = element.gridImage;
				var $GridImage = $('<span>')
				.attr('class','n2s_insertMediaView')
				.attr('nunaliit-document',cellImage.doc)
				.attr('nunaliit-attachment',cellImage.attachment)
				.appendTo($gridCellImage);
			};

			// Add label/referencelink to grid cell if available
			if ( this.elementsById[elementId].id ){
				var $GridLabel = $('<span>')
				.attr('class','n2s_referenceLink')
				.attr('nunaliit-document',element.id)
				.appendTo($gridCellLabel);
			};

			this.showService.fixElementAndChildren($cell);
		};
	},

	_scrollChanged: function( $canvas ){
		var _this = this;

		var scrollTop = $canvas.scrollTop();
		var scrollLeft = $canvas.scrollLeft();

		// Wait a bit before loading images
		this.lastScrollTop = scrollTop;
		this.lastScrollLeft = scrollLeft;
		window.setTimeout(function(){
			if( _this.lastScrollTop === scrollTop
			 && _this.lastScrollLeft === scrollLeft ){
				_this._reloadTiles();
			};
		},200);
	},

 	_sourceModelUpdated: function(state){
 		this.elementGenerator.sourceModelUpdated(state);
 	},

 	_handleDispatch: function(m){
 		if( 'modelGetInfo' === m.type ){
 			if( m.modelId === this.modelId ){
 				m.modelInfo = this._getModelInfo();
 			};

 		} else if( 'modelStateUpdated' === m.type ) {
 			if( this.sourceModelId === m.modelId ){
 				if( m.state ){
 					this._sourceModelUpdated(m.state);
 				};
 			};
 		} else if( 'windowResized' === m.type ) {
 			this._reloadTiles();
 		};
 	}
});

//--------------------------------------------------------------------------
function HandleCanvasAvailableRequest(m){
	if( m.canvasType === 'grid' ){
		m.isAvailable = true;
	};
};

//--------------------------------------------------------------------------
function HandleCanvasDisplayRequest(m){
	if( m.canvasType === 'grid' ){

		var options = {};
		if( m.canvasOptions ){
			for(var key in m.canvasOptions){
				options[key] = m.canvasOptions[key];
			};
		};

 		if( !options.elementGenerator ){
 			// If not defined, use the one specified by type
 			options.elementGenerator = $n2.canvasElementGenerator.CreateElementGenerator({
 	 			type: options.elementGeneratorType
 	 			,options: options.elementGeneratorOptions
 	 			,config: m.config
 	 		});
 		};

		options.canvasId = m.canvasId;
		options.config = m.config;
		options.onSuccess = m.onSuccess;
		options.onError = m.onError;

		new GridCanvas(options);
	};
};

//--------------------------------------------------------------------------
$n2.canvasGrid = {
	GridCanvas: GridCanvas
	,HandleCanvasAvailableRequest: HandleCanvasAvailableRequest
	,HandleCanvasDisplayRequest: HandleCanvasDisplayRequest
};

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


<commit_before>/**
 * @namespace Lyria
 * Lyria namespace decleration
 */
;(function(window, document, Lyria, $, undefined) {
  'use strict';

  /**
   * The scene director is the manager for all scenes
   *
   */
  Lyria.SceneDirector = (function() {

    function SceneDirector(container, parent) {

      if (container instanceof Lyria.Viewport) {
        this.viewport = container;
      } else {
        this.viewport = new Lyria.Viewport(container, parent);
      }

      this.sceneList = {};
      this.currentScene = null;
      this.onSceneChange = function(scene) {};

    }

    // Properties
    SceneDirector.prototype.sceneClassName = 'scene';

    // Methods
    SceneDirector.prototype.add = function(scene, options) {

      if (!(scene instanceof Lyria.Scene)) {
        if (Lyria.Scenes[scene]) {
          scene = Lyria.Scenes[scene];
        } else {
          throw 'No valid scene found.';
        }
      }

      scene.parent = this;
      this.sceneList[scene.name] = scene;

      if (this.viewport.$container) {
        if ($('#' + scene.name).length === 0) {
          this.viewport.$container.prepend($(document.createElement('div'))
                       .attr('id', scene.name)
                       .attr('class', SceneDirector.prototype.sceneClassName));

          if (scene.content) {
            $('#' + scene.name).html(scene.content);
          }
        }
      }

      return this;
    };

    SceneDirector.prototype.show = function(scene, options, callback) {

      if (this.onSceneChange) {
        this.onSceneChange(scene);
      }

      // More than one scene visible at the same time
      if ($('.' + SceneDirector.prototype.sceneClassName + ':visible')) {
        $('.' + SceneDirector.prototype.sceneClassName).hide();
      }

      if (this.currentScene) {
        if (this.currentScene.transition && this.currentScene.length) {
          $('#' + this.currentScene).hide(this.currentScene.transition.length, function() {
            $('.' + SceneDirector.prototype.sceneClassName).hide();
          });
        } else {
          $('.' + SceneDirector.prototype.sceneClassName).hide();
        }

        if (this.currentScene.onDeactivated) {
          this.currentScene.onDeactivated(options);
        }

      }

      $.each(this.sceneList, function(key, value) {
        if (key === scene) {

          if (scene.transition && scene.transition.length) {
            $('#' + scene).show(scene.transition.length);
          } else {
            $('#' + scene).show();
          }
          this.currentScene = value;
          if (this.currentScene.onActive) {
            this.currentScene.onActive(options);
          }

          if (callback)
            callback(scene);

          return false;
        }
      });
    };

    SceneDirector.prototype.render = function() {
      if (!this.currentScene.render) {
        return;
      }
      this.currentScene.render();
    };

    SceneDirector.prototype.update = function(dt) {
      if (!this.currentScene.update) {
        return;
      }
      this.currentScene.update(dt);
    };

    return SceneDirector;

  })();

})(this, this.document, this.Lyria = this.Lyria || {}, this.jQuery);
<commit_msg>SceneDirector handles event binding when adding a scene<commit_after>/**
 * @namespace Lyria
 * Lyria namespace decleration
 */
;(function(window, document, Lyria, $, undefined) {'use strict';

  /**
   * The scene director is the manager for all scenes
   *
   */
  Lyria.SceneDirector = (function() {

    function SceneDirector(container, parent) {

      if ( container instanceof Lyria.Viewport) {
        this.viewport = container;
      } else {
        this.viewport = new Lyria.Viewport(container, parent);
      }

      this.sceneList = {};
      this.currentScene = null;
      this.onSceneChange = function(scene) {
      };

    }

    // Properties
    SceneDirector.prototype.sceneClassName = 'scene';

    // Methods
    SceneDirector.prototype.add = function(scene, options) {

      if (!( scene instanceof Lyria.Scene)) {
        if (Lyria.Scenes[scene]) {
          scene = Lyria.Scenes[scene];
        } else {
          throw 'No valid scene found.';
        }
      }

      scene.parent = this;
      this.sceneList[scene.name] = scene;

      if (this.viewport.$container) {
        if ($('#' + scene.name).length === 0) {
          this.viewport.$container.prepend($(document.createElement('div')).attr('id', scene.name).attr('class', SceneDirector.prototype.sceneClassName));

          if (scene.content) {
            $('#' + scene.name).html(scene.content);
          }

          // Bind events
          if (scene.events && !$.isEmptyObject(scene.events)) {
            $.each(scene.events, function(key, value) {
              if (( typeof value === 'object') && (key !== 'delegate')) {
                $(scene.events.delegate).on(value, key, {
                  scene: scene
                });
              }
            });
          }
        }
      }

      return this;
    };

    SceneDirector.prototype.show = function(scene, options, callback) {

      if (this.onSceneChange) {
        this.onSceneChange(scene);
      }

      // More than one scene visible at the same time
      if ($('.' + SceneDirector.prototype.sceneClassName + ':visible')) {
        $('.' + SceneDirector.prototype.sceneClassName).hide();
      }

      if (this.currentScene) {
        if (this.currentScene.transition && this.currentScene.length) {
          $('#' + this.currentScene).hide(this.currentScene.transition.length, function() {
            $('.' + SceneDirector.prototype.sceneClassName).hide();
          });
        } else {
          $('.' + SceneDirector.prototype.sceneClassName).hide();
        }

        if (this.currentScene.onDeactivated) {
          this.currentScene.onDeactivated(options);
        }

      }

      $.each(this.sceneList, function(key, value) {
        if (key === scene) {

          if (scene.transition && scene.transition.length) {
            $('#' + scene).show(scene.transition.length);
          } else {
            $('#' + scene).show();
          }
          this.currentScene = value;
          if (this.currentScene.onActive) {
            this.currentScene.onActive(options);
          }

          if (callback)
            callback(scene);

          return false;
        }
      });
    };

    SceneDirector.prototype.render = function() {
      if (!this.currentScene.render) {
        return;
      }
      this.currentScene.render();
    };

    SceneDirector.prototype.update = function(dt) {
      if (!this.currentScene.update) {
        return;
      }
      this.currentScene.update(dt);
    };

    return SceneDirector;

  })();

})(this, this.document, this.Lyria = this.Lyria || {}, this.jQuery);
<|endoftext|>


<commit_before>/* @author: Mark McCann (www.markmccann.me) @license: None, Public Domain */
!function(n,e,t,s){var i="modality",r=n("body")[0],a="click",o={autoBind:!0,clickOffToClose:!0,closeOnEscape:!0,effect:"",enabled:!0,innerClass:"mm-wrap",modalClass:"modality-modal",onClose:"",onOpen:"",openClass:"mm-show",openOnLoad:!1,userClass:""},l=function(n){for(var e=0;e<n.length;e++)"function"==typeof n[e]&&n[e]()},d=function(n,e){return""!=n[e]?" "+n[e]:""},u=function(n,e){for(var t=n.length;t--;)if(n[t][0][0]===e[0])return t;return!1},c=function(n){return n===parseInt(n,10)},f=function(e,t){var s=this,i=n(e).attr("id"),a=n.extend({},o,t),l=n(e).wrap('

').show(),u=l.parents("."+a.modalClass);return triggers=n('a[href="#'+i+'"], [data-modality="#'+i+'"]'),n.extend(s,{defaults:o,id:i,settings:a,wrapper:u,triggers:[],modal:l}),a.autoBind&&triggers.each(function(){s.addTrigger(n(this))}),a.clickOffToClose&&u.click(function(n){n.preventDefault(),n.target==s.wrapper[0]&&s.close()}),a.closeOnEscape&&n(r).keyup(function(n){27==n.keyCode&&s.close()}),-1!=navigator.appVersion.indexOf("MSIE 7.")&&u.prepend('

'),a.openOnLoad&&s.open(),s};n.extend(f.prototype,{open:function(n){return this.wrapper.add(r).addClass(this.settings.openClass),l([this.settings.onOpen,n]),this},close:function(n){return this.wrapper.add(r).removeClass(this.settings.openClass),l([this.settings.onClose,n]),this},toggle:function(n){return this.isOpen()?this.close(n):this.open(n)},isOpen:function(){return this.wrapper.hasClass(this.settings.openClass)},addTrigger:function(n){var e=this,t=e.triggers,s=u(t,n),i=[n,function(n){n.preventDefault(),e.toggle()}];return c(s)?t[s]=i:t.push(i),e.settings.enabled&&i[0].bind(a,i[1]),e},removeTrigger:function(n){var e=this,t=e.triggers,s=u(t,n);return c(s)&&(t[s][0].unbind(a,t[s][1]),t.splice(s,1)),e},enable:function(){var n=this,e=n.triggers,t=e.length;if(!n.settings.enabled){n.settings.enabled=!0;for(var s=0;t>s;s++)e[s][0].bind(a,e[s][1])}return n},disable:function(){var n=this,e=n.triggers,t=e.length;if(n.settings.enabled){n.settings.enabled=!1;for(var s=0;t>s;s++)e[s][0].unbind(a,e[s][1])}return n}}),n.extend(f,{instances:{},init:function(n,e){var t={},i=this,r=0;return n.each(function(){var n=new i(this,e);i.instances[n.id]=t[r]=n}),t[1]===s?t[0]:t}}),n[i]=f,n.fn[i]=function(e){return n[i].init(this,e)}}(jQuery,window,document);
<commit_msg>Update modality.jquery.min.js<commit_after>/* @author: Mark McCann (www.markmccann.me) @license: None, Public Domain */
!function(n,e,t,s){var i="modality",r=n("body")[0],a="click",o={autoBind:!0,clickOffToClose:!0,closeOnEscape:!0,effect:"",enabled:!0,innerClass:"mm-wrap",modalClass:"modality-modal",onClose:"",onOpen:"",openClass:"mm-show",openOnLoad:!1,userClass:""},l=function(n){for(var e=0;e<n.length;e++)"function"==typeof n[e]&&n[e]()},d=function(n,e){return""!=n[e]?" "+n[e]:""},u=function(n,e){for(var t=n.length;t--;)if(n[t][0][0]===e[0])return t;return!1},c=function(n){return n===parseInt(n,10)},f=function(e,t){var s=this,i=n(e).attr("id"),a=n.extend({},o,t),l=n(e).wrap('

').show(),u=l.parents("."+a.modalClass);return triggers=n('a[href="#'+i+'"], [data-target="#'+i+'"]'),n.extend(s,{defaults:o,id:i,settings:a,wrapper:u,triggers:[],modal:l}),a.autoBind&&triggers.each(function(){s.addTrigger(n(this))}),a.clickOffToClose&&u.click(function(n){n.preventDefault(),n.target==s.wrapper[0]&&s.close()}),a.closeOnEscape&&n(r).keyup(function(n){27==n.keyCode&&s.close()}),-1!=navigator.appVersion.indexOf("MSIE 7.")&&u.prepend('

'),a.openOnLoad&&s.open(),s};n.extend(f.prototype,{open:function(n){return this.wrapper.add(r).addClass(this.settings.openClass),l([this.settings.onOpen,n]),this},close:function(n){return this.wrapper.add(r).removeClass(this.settings.openClass),l([this.settings.onClose,n]),this},toggle:function(n){return this.isOpen()?this.close(n):this.open(n)},isOpen:function(){return this.wrapper.hasClass(this.settings.openClass)},addTrigger:function(n){var e=this,t=e.triggers,s=u(t,n),i=[n,function(n){n.preventDefault(),e.toggle()}];return c(s)?t[s]=i:t.push(i),e.settings.enabled&&i[0].bind(a,i[1]),e},removeTrigger:function(n){var e=this,t=e.triggers,s=u(t,n);return c(s)&&(t[s][0].unbind(a,t[s][1]),t.splice(s,1)),e},enable:function(){var n=this,e=n.triggers,t=e.length;if(!n.settings.enabled){n.settings.enabled=!0;for(var s=0;t>s;s++)e[s][0].bind(a,e[s][1])}return n},disable:function(){var n=this,e=n.triggers,t=e.length;if(n.settings.enabled){n.settings.enabled=!1;for(var s=0;t>s;s++)e[s][0].unbind(a,e[s][1])}return n}}),n.extend(f,{instances:{},init:function(n,e){var t={},i=this,r=0;return n.each(function(){var n=new i(this,e);i.instances[n.id]=t[r]=n}),t[1]===s?t[0]:t}}),n[i]=f,n.fn[i]=function(e){return n[i].init(this,e)}}(jQuery,window,document);
<|endoftext|>


<commit_before>/******************************************
* Claimer Model
*/
app.Models.Claimer = app.Models.GenericModel.extend({

	urlRoot : "/api/open_object/partners",

	defaults:{
		name: null,
		type_id: null,
		technical_service_id: null,
		technical_site_id: null,
	},

	getId: function(){
		return this.get('id');
	},

	setId: function(value){
		if( value == 'undefined') return;
        this.set({ id : value });
	},

	getName : function() {
        return this.get('name');
    },
    setName : function(value) {
    	if( value == 'undefined') return;
        this.set({ name : value });
    },

	getTypeId : function() {
		return this.get('type_id');
	},

	setTypeId : function(value) {
		if( value == 'undefined') return;
		this.set({ type_id : value });
	},

	getTechnicalService : function(type) {
		if(this.get('technical_service_id')){

			switch (type){
				case 'id':
					return this.get('technical_service_id')[0];
				break;
				case 'json':
					return {id: this.get('technical_service_id')[0], name: this.get('technical_service_id')[1]};
				break;
				default:
					return this.get('technical_service_id')[1];
			}
		}
		else{
			return false;
		}
	},
	setTechnicalService : function(value) {
		this.set({ technical_service_id : value });
	},

	getTechnicalSite : function(type) {
		if(this.get('technical_site_id')){

			switch (type){
				case 'id':
					return this.get('technical_site_id')[0];
				break;
				case 'json':
					return {id: this.get('technical_site_id')[0], name: this.get('technical_site_id')[1]};
				break;
				default:
					return this.get('technical_site_id')[1];
			}
		}
		else{
			return false;
		}
	},
	setTechnicalSite : function(value) {
		this.set({ technical_site_id : value });
	},

	getClaimerType : function() {
		return this.get('type_id');
	},

	setClaimerType : function(value) {
		this.set({ type_id : value });
	},

	// Returns addresses collection fetched this is used in view to serialize object before template
	getAddresses: function () {
		var address_ids = this.get('address');
		var collection = new app.Collections.ClaimersContacts
		if (address_ids == false) {
			return collection;
		} else {

			collection.fetch({
					data   : {filters: {0: {field: 'id', operator: 'in', value: this.get('address')}}},
					reset : true
				}
			).done( function () {
					collection.trigger('fetchDone');
				})
			return collection;
		}

	},
	getInformations: function () {
		return {name: this.get('name')};
	},

	// Returns the many2one id fields in form of an object {name:'name',id:'id'}
	objectifiedTypeId : function () {
		return app.Helpers.Main.many2oneObjectify(this.get('type_id'))
	},
	objectifiedTechnicalServiceId : function () {
		return app.Helpers.Main.many2oneObjectify(this.get('technical_service_id'))
	},
	objectifiedTechnicalSiteId : function () {
		return app.Helpers.Main.many2oneObjectify(this.get('technical_site_id'))
	},

});
<commit_msg>updated filters of getAdresses method of ClaimerModel to retrieve correct addresses<commit_after>/******************************************
* Claimer Model
*/
app.Models.Claimer = app.Models.GenericModel.extend({

	urlRoot : "/api/open_object/partners",

	defaults:{
		name: null,
		type_id: null,
		technical_service_id: null,
		technical_site_id: null,
	},

	getId: function(){
		return this.get('id');
	},

	setId: function(value){
		if( value == 'undefined') return;
        this.set({ id : value });
	},

	getName : function() {
        return this.get('name');
    },
    setName : function(value) {
    	if( value == 'undefined') return;
        this.set({ name : value });
    },

	getTypeId : function() {
		return this.get('type_id');
	},

	setTypeId : function(value) {
		if( value == 'undefined') return;
		this.set({ type_id : value });
	},

	getTechnicalService : function(type) {
		if(this.get('technical_service_id')){

			switch (type){
				case 'id':
					return this.get('technical_service_id')[0];
				break;
				case 'json':
					return {id: this.get('technical_service_id')[0], name: this.get('technical_service_id')[1]};
				break;
				default:
					return this.get('technical_service_id')[1];
			}
		}
		else{
			return false;
		}
	},
	setTechnicalService : function(value) {
		this.set({ technical_service_id : value });
	},

	getTechnicalSite : function(type) {
		if(this.get('technical_site_id')){

			switch (type){
				case 'id':
					return this.get('technical_site_id')[0];
				break;
				case 'json':
					return {id: this.get('technical_site_id')[0], name: this.get('technical_site_id')[1]};
				break;
				default:
					return this.get('technical_site_id')[1];
			}
		}
		else{
			return false;
		}
	},
	setTechnicalSite : function(value) {
		this.set({ technical_site_id : value });
	},

	getClaimerType : function() {
		return this.get('type_id');
	},

	setClaimerType : function(value) {
		this.set({ type_id : value });
	},

	// Returns addresses collection fetched this is used in view to serialize object before template
	getAddresses: function () {
//		var address_ids = this.get('address');
		var collection = new app.Collections.ClaimersContacts
//		if (address_ids == false) {
//			return collection;
//		} else {

			collection.fetch({
//					data   : {filters: {0: {field: 'id', operator: 'in', value: this.get('address')}}},
					data   : {filters: {0: {field: 'partner_id.id', operator: '=', value: this.get('id')}}},
					reset : true
				}
			).done( function () {
					collection.trigger('fetchDone');
				})
			return collection;
//		}

	},
	getInformations: function () {
		return {name: this.get('name')};
	},

	// Returns the many2one id fields in form of an object {name:'name',id:'id'}
	objectifiedTypeId : function () {
		return app.Helpers.Main.many2oneObjectify(this.get('type_id'))
	},
	objectifiedTechnicalServiceId : function () {
		return app.Helpers.Main.many2oneObjectify(this.get('technical_service_id'))
	},
	objectifiedTechnicalSiteId : function () {
		return app.Helpers.Main.many2oneObjectify(this.get('technical_site_id'))
	},

});
<|endoftext|>


<commit_before>/*!
 * SWIF-OpenSTC
 * Copyright 2013-2014 Siclic <contact@siclic.fr>
 * Licensed under AGPL-3.0 (https://www.gnu.org/licenses/agpl.txt)
 */

define([
	'backbone',
	'moment',

], function(Backbone, moment){

	'use strict';

	/******************************************
	* Generic Model
	*/
	var GenericModel = Backbone.Model.extend({

		defaults:{
			id : null,
		},

		searchable_fields: [
			{ key: 'name',  type: 'text' }
		],

		getId : function() {
			return this.get('id');
		},
		setId : function(value, silent) {
			this.set({ id: value }, {silent: silent});
		},

		getName : function() {
			return _.titleize(this.get('name').toLowerCase());
		},
		setName : function(value, silent) {
			this.set({ name: value }, {silent: silent});
		},

		getActions : function(){
			return this.get('actions');
		},

		getDateFr: function(field){
			var val = this.getAttribute(field,'');
			if(val !== ''){
				val = moment(val).format('DD/MM/YYYY');
			}
			return val;
		},

		//method to retrieve attribute with standard return form
		getAttribute: function(key,default_value){
			var val = this.get(key);
			if(_.isUndefined(default_value)){
				default_value = false;
			}
			if(!_.isUndefined(val) && val !== '' && val !== false && val !== null){
				return val;
			}
			else{
				return default_value;
			}
		},

		/**
		 * @return array : empty array if value of 'fieldName' not refer to a *2many save-value, else return value of 'fieldName'
			a correct *2many save-value is an Array of Array (correctVal = [ [0,0,{...}] ], [4,ID],... ] )
		 */
		check2ManyAction: function(fieldName){
			var ret = [];
			var field = this.getAttribute(fieldName,[]);
			_.each(field, function(value){
				//if value is number, means that it refers to an ID (from a fetch), we want only to keep action values.
				//Not the best way to do that, must be reracto soon
				if(!_.isNumber(value)){
					ret.push(value);
				}
			});

			return ret;
		},

		checkMany2OneAction: function(fieldName){
			var val = this.getAttribute(fieldName,false);
			if(_.isArray(val)){
				val = val[0];
			}
			return val;
		},

		/**
		 * to move to GenericCollection
		 */
		getSaveVals: function(attributes){
			var fields = {};
			var self = this;
			if(!_.isUndefined(attributes)){
				_.each(attributes, function(field){
					fields[field] = self.collection.fieldsMetadata[field];
				});
			}
			else{
				fields = this.collection.fieldsMetadata;
			}
			var ret = {};
			if(!_.isUndefined(this.collection)){
				_.map(fields, function(fieldDefinition, fieldName){
					if(!_.contains(self.readonlyFields, fieldName)){
						switch(fieldDefinition.type){
						case 'many2one':
							ret[fieldName] = self.checkMany2OneAction(fieldName);
							break;
						case 'one2many':
							ret[fieldName] = self.check2ManyAction(fieldName);
							break;
						case 'many2many':
							ret[fieldName] = self.check2ManyAction(fieldName);
							break;
						default:
							ret[fieldName] = self.getAttribute(fieldName, false);
						}
					}
				});
			}
			else{
				console.warning('Swif error: Could not save model because not any collection is linked with, and so can not retrieve metadata fields.');
			}
			console.log(ret);
			return ret;
		},

		saveToBackend: function(){
			var self = this;
			var vals = this.getSaveVals();
			var ret = this.save(vals,{patch:!this.isNew(), wait:true}).then(function(data){
				if(self.isNew()){
					self.set({id:data});
				}
				return self.fetch();
			});
			return ret;

		},
		fetchMetadata: function(){
			var self = this;
			return $.ajax({
				url      : this.urlRoot,
				method   : 'HEAD',
				dataType : 'text',
				success  : function(data,status,request){

					self.fieldsMetadata = {};
					//for backward compatibility only
					if(_.isUndefined(self.collection)){
						self.collection = {};
					}
					//Set advanced filters for collection with metadatas
					try {
						self.fieldsMetadata = JSON.parse(request.getResponseHeader('Model-Fields'));
						//for backward compatibility only
						self.collection.fieldsMetadata = self.fieldsMetadata;
						_.each(self.advanced_searchable_fields, function(fieldToKeep){
							var field = _.find(self.fieldsMetadata,function(value,key){
								return fieldToKeep.key == key;
							});
							_.extend(fieldToKeep, field);
						});
					}
					catch(e){
						console.log('Meta data are not valid');
					}

					//Get model Id to obtain his filters
					self.modelId = request.getResponseHeader('Model-Id');

				}

			});
		},
	});

	return GenericModel;

});<commit_msg>updated GenericModel to add getDatetime method (applying user timezone)<commit_after>/*!
 * SWIF-OpenSTC
 * Copyright 2013-2014 Siclic <contact@siclic.fr>
 * Licensed under AGPL-3.0 (https://www.gnu.org/licenses/agpl.txt)
 */

define([
	'backbone',
	'appHelpers',
	'moment',

], function(Backbone, AppHelpers, moment){

	'use strict';

	/******************************************
	* Generic Model
	*/
	var GenericModel = Backbone.Model.extend({

		defaults:{
			id : null,
		},

		searchable_fields: [
			{ key: 'name',  type: 'text' }
		],

		getId : function() {
			return this.get('id');
		},
		setId : function(value, silent) {
			this.set({ id: value }, {silent: silent});
		},

		getName : function() {
			return _.titleize(this.get('name').toLowerCase());
		},
		setName : function(value, silent) {
			this.set({ name: value }, {silent: silent});
		},

		getActions : function(){
			return this.get('actions');
		},

		getDateFr: function(field){
			var val = this.getAttribute(field,'');
			if(val !== ''){
				val = moment(val).format('DD/MM/YYYY');
			}
			return val;
		},

		getDatetime: function(field){
			var val = this.getAttribute(field,'1970-01-01 00:00:00');
			val = AppHelpers.convertDateToTz(val);
			return val.format('YYYY-MM-DD HH:mm:ss');
		},

		//method to retrieve attribute with standard return form
		getAttribute: function(key,default_value){
			var val = this.get(key);
			if(_.isUndefined(default_value)){
				default_value = false;
			}
			if(!_.isUndefined(val) && val !== '' && val !== false && val !== null){
				return val;
			}
			else{
				return default_value;
			}
		},

		/**
		 * @return array : empty array if value of 'fieldName' not refer to a *2many save-value, else return value of 'fieldName'
			a correct *2many save-value is an Array of Array (correctVal = [ [0,0,{...}] ], [4,ID],... ] )
		 */
		check2ManyAction: function(fieldName){
			var ret = [];
			var field = this.getAttribute(fieldName,[]);
			_.each(field, function(value){
				//if value is number, means that it refers to an ID (from a fetch), we want only to keep action values.
				//Not the best way to do that, must be reracto soon
				if(!_.isNumber(value)){
					ret.push(value);
				}
			});

			return ret;
		},

		checkMany2OneAction: function(fieldName){
			var val = this.getAttribute(fieldName,false);
			if(_.isArray(val)){
				val = val[0];
			}
			return val;
		},

		/**
		 * to move to GenericCollection
		 */
		getSaveVals: function(attributes){
			var fields = {};
			var self = this;
			if(!_.isUndefined(attributes)){
				_.each(attributes, function(field){
					fields[field] = self.collection.fieldsMetadata[field];
				});
			}
			else{
				fields = this.collection.fieldsMetadata;
			}
			var ret = {};
			if(!_.isUndefined(this.collection)){
				_.map(fields, function(fieldDefinition, fieldName){
					if(!_.contains(self.readonlyFields, fieldName)){
						switch(fieldDefinition.type){
						case 'many2one':
							ret[fieldName] = self.checkMany2OneAction(fieldName);
							break;
						case 'one2many':
							ret[fieldName] = self.check2ManyAction(fieldName);
							break;
						case 'many2many':
							ret[fieldName] = self.check2ManyAction(fieldName);
							break;
						default:
							ret[fieldName] = self.getAttribute(fieldName, false);
						}
					}
				});
			}
			else{
				console.warning('Swif error: Could not save model because not any collection is linked with, and so can not retrieve metadata fields.');
			}
			console.log(ret);
			return ret;
		},

		saveToBackend: function(){
			var self = this;
			var vals = this.getSaveVals();
			var ret = this.save(vals,{patch:!this.isNew(), wait:true}).then(function(data){
				if(self.isNew()){
					self.set({id:data});
				}
				return self.fetch();
			});
			return ret;

		},
		fetchMetadata: function(){
			var self = this;
			return $.ajax({
				url      : this.urlRoot,
				method   : 'HEAD',
				dataType : 'text',
				success  : function(data,status,request){

					self.fieldsMetadata = {};
					//for backward compatibility only
					if(_.isUndefined(self.collection)){
						self.collection = {};
					}
					//Set advanced filters for collection with metadatas
					try {
						self.fieldsMetadata = JSON.parse(request.getResponseHeader('Model-Fields'));
						//for backward compatibility only
						self.collection.fieldsMetadata = self.fieldsMetadata;
						_.each(self.advanced_searchable_fields, function(fieldToKeep){
							var field = _.find(self.fieldsMetadata,function(value,key){
								return fieldToKeep.key == key;
							});
							_.extend(fieldToKeep, field);
						});
					}
					catch(e){
						console.log('Meta data are not valid');
					}

					//Get model Id to obtain his filters
					self.modelId = request.getResponseHeader('Model-Id');

				}

			});
		},
	});

	return GenericModel;

});<|endoftext|>