<commit_before>/**
 * Gumi v1.1.0
 * Usage: http://b1lly.github.io/gumi
 * GitHub: http://github.com/b1lly/gumi
 */

;(function($, window, document, undefined) {
  var defaults = {
    buttonClass: 'gumi-btn-default',
    buttonSelectedClass: 'gumi-btn-selected',
    optionDisabledClass: 'gumi-option-disabled',
    dropdownClass: 'gumi-dropdown-default',
    onChange: function() {},
    onOpen: function() {},
    onCancel: function() {
      this.reset();
    }
  };

  /**
   * @constructor
   */
  var Gumi = function(elem, options) {
    this.elem = elem;
    this.$elem = $(elem);
    this.$elem.addClass('gumi-wrap');

    // Reference to the button that shows the current selected option
    // and also handles the click event to show the dropdown
    this.$button = $('<button />');

    // Contains a reference to the dropdown list of options
    this.$dropdown = this.$elem.find('ul').hide();

    // Native form select element that gumi links too
    this.$select = $('<select />');

    this.selectedIndex = 0;
    this.selectedLabel = undefined;
    this.selectedValue = undefined;

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

    this._load = true;
    this._defaults = defaults;
    this._initialSelected = undefined;

    this._init();
  };

  /**
   * Build out our Gumi prototype and methods
   */
  Gumi.prototype = {
    constructor: Gumi,

    /**
     * Initialize the Gumi selectbox
     */
    _init: function() {
      this._createButton();
      this._createSelect();
      this._createDropdown();
      this._bindDropdown();
      this._bindSelectOption();
    },

    /**
     * Handle creating our button based on a variety of cases
     */
    _createButton: function() {
      var that = this;

      // Handle using a button that exists (or use our default)
      // and create the structure our button label layout
      var $button = this.$elem.find('button'),
          $label = $('');

      if ($button.length) {
        this.$button = $button;
      }

      // Show the arrow icon on the label by default, unless otherwise specified
      if (!this.$button.attr('data-arrow-icn') ||
          this.$button.data('arrow-icn') === true) {
        $label.append(' ');
      }

      // Only show the close icon if specified
      // The binding get's handled in the '_bindDropdown()' method
      if (this.$button.data('cancel-icn') &&
          this.selectedIndex != this._initialSelected) {
        $label.append(' ');
      }

      this.$button.html($('
').append($label).html());
    },

    /**
     * Creates a hidden "<select>" based on
     * the list items from the ul jQuery selector
     */
    _createSelect: function() {
      // Adds the properties and options to our select
      // and get the selectedIndex from the option parsing
      this._updateSelect();

      // Attach our native select to the DOM
      this.$elem.append(this.$select);

      this._load = false;
    },

    /**
     * Updates the "<select>" properties, options and values
     * based on the current list of options from the "
"
     */
    _updateSelect: function() {
      var that = this,
          selectedIndex = 0;

      // Copy some attributes over to our select
      this.$select
        .addClass(this.options.dropdownClass)
        .addClass(this.$button.data('class'))
        .attr('name', this.$button.data('name'))
        .prop('required', this.$button.data('required'))
        .hide();

      // Add 'data' params to the select as HTML data-attributes
      this._deserializeParams();

      // Add the list options to our select options
      this.$elem.find('li').each(function(index) {
        var $self = $(this),
            val = $self.data('value');

        var value = val === undefined && val !== '' ? $self.html() : String(val),
            label = $self.data('label') || $self.html() || value;

        // Figure out which one should be selected by default
        if ($self.data('selected') === true) {
          selectedIndex = index;
        }

        // Handle custom styling for disabled class
        if ($self.data('disabled') === true) {
          $self.addClass(that.options.optionDisabledClass);
        }

        // Only show options that are selectable
        if ($self.data('selectable') === false) {
          $self.hide();
        }

        $('<option />')
          .val(value)
          .append(label)
          .addClass($self.attr('class'))
          .appendTo(that.$select);
      });

      // Set the initial selected
      this._initialSelected = selectedIndex;

      // Set the default option
      this.setSelectedOption(selectedIndex);

      return selectedIndex;
    },

    /**
     * Creates the clickable button to show
     * the dropdown, and attaches "optional"
     * custom classes to both the button and the dropdown
     */
    _createDropdown: function() {
      this.$button
        .addClass('gumi-btn')
        .addClass(this.options.buttonClass);

      // Insert the button before the dropdown
      this.$elem.prepend(this.$button);

      // Styling should hide the dropdown by default
      this.$dropdown
        .addClass('gumi-dropdown')
        .addClass(this.options.dropdownClass);
    },

    /**
     * Handle the interaction for showing and hiding the dropdown options
     */
    _bindDropdown: function() {
      var that = this;

      this.$button.on('click.Gumi', function(e) {
        e.preventDefault();
        e.stopPropagation();

        // We want to reset all other dropdowns on the page
        // to avoid having multiple dropdowns open at a time
        that._resetDropdowns(that.$elem);

        // Handle the user clicking the 'cancel' icon
        if ($(e.target).hasClass('js-gumi-cancel')) {
          that.options.onCancel.call(that);
          return;
        }

        // Handles clicking the button toggling
        that.$button.toggleClass(that.options.buttonSelectedClass);
        that.$dropdown.toggle();

        if (that.$dropdown.is(':visible')) {
          that.options.onOpen.call(that.$elem);
        }
      });

      $(document).off('click.Gumi');
      $(document).on('click.Gumi', function(e) {
        if ($(e.target).closest('.gumi-dropdown').length === 0) {
          that._resetDropdowns();
        }
      });
    },

    /**
     * When a user selects an option, we need to update our native
     * <select> in addition to our instance data
     */
    _bindSelectOption: function() {
      var that = this;

      that.$dropdown.on('click.Gumi', 'li', function(e) {
        var $self = $(this);
        e.stopPropagation();

        if (!$self.data('disabled')) {
          that.setSelectedOption($(this).index());
          that.closeDropdown();
        }
      });
    },

    /**
     * Resets all dropdowns on the page to default state, excluding callee
     * @param {jQueryObject} $elem Optional element to exclude from reset
     */
    _resetDropdowns: function($elem) {
      $('.gumi-wrap').not($elem).each(function() {
        $(this).data('gumi').closeDropdown();
      });
    },

    /**
     * Takes a serialized string of params and converts it to a map of data
     * based on the data attribute 'params' on the button node
     * e.g. { 'key' : 'val' }
     */
    _deserializeParams: function() {
      var params = this.$button.data('params'),
          data = {};

      if (!params) {
        return;
      }

      if (typeof params === 'string') {
        params = params.split(' ');

        var currentParam;
        for (var i = 0, len = params.length; i < len; i ++) {
          currentParam = params[i].split('=');
          data[currentParam[0]] = currentParam[1];
        }

        this._addDataToSelect(data);
      }
    },

    /**
     * Adds HTML5 Data attributes/values to the select
     * @param {object} data Map of data key to data value e.g. { 'height': 300 }
     */
    _addDataToSelect: function(data) {
      for (var key in data) {
        this.$select.data(key, data[key]);
      }
    },

    /**
     * Sync the markup with the hidden select
     */
    update: function() {
      this.$elem.find('select').empty();
      this._updateSelect();
    },

    /**
     * Set the selected option based on it's value
     * @param {string|number|boolean} value The value of the option to look for in our list
     */
    setSelected: function(value) {
      var $option = this.$select.find('option[value="' + value + '"]');

      if ($option.length) {
        this.setSelectedOption($option.index());
      }
    },

    /**
     * Sets the selected state to the native select box
     * based on the index. Also updates the instance and the label on the button
     * @param {number} opt_index Index of the select option to select (defaults 0)
     */
    setSelectedOption: function(opt_index) {
      opt_index = opt_index || 0;

      var label;
      var $option = this.$select.find('option').eq(opt_index);

      this.selectedIndex = opt_index;
      this.selectedLabel = this.$dropdown.eq(opt_index).data('label') || $option.text();
      this.selectedValue = $option.val();

      $option
        .prop('selected', true)
        .trigger('change');

      if (this._load === false ||
          (this._load === true && !this.$button.data('default-value'))) {
        this.$button.find('span em').text(this.selectedLabel);

        // Trigger our custom callback
        this.options.onChange.call(this.$select);
      }
    },

    /**
     * Public interface to bind a custom change event handler
     * @param {string} evt The event type to listen to
     * @param {function} fn The function callback for the event
     */
    onEvent: function(evt, fn) {
      if (typeof fn === 'function') {
        if (this.options[evt]) {
          this.options[evt] = fn;
        }
      }
    },

    /**
     * Hides the dropdown and removes the selected state of the button
     */
    closeDropdown: function() {
      this.$button.removeClass(this.options.buttonSelectedClass);
      this.$dropdown.hide();
    },

    /**
     * Resets the dropdown to it's original state during initialization
     */
    reset: function() {
      this.setSelectedOption(this._initialSelected);
    }
  };

  /**
   * Simple jQuery API for Gumi
   */
  $.fn.gumi = function(options) {
    var args = arguments,
        that = this;

    return this.each(function(index) {
      // Tries to get the instance of gumi that is referenced by the node
      var gumi = $.data(this, 'gumi');

      // If there's no gumi instance, assume we're initializing
      if (!gumi) {
        $.data(this, 'gumi', new Gumi(this, options));

        // Broadcast a "we're finished loading" event
        if (index === that.length - 1) {
          $(this).trigger('ready.Gumi');
        }
      } else {
        // Otherwise, access our public API (if viable)
        if (typeof options === 'string' &&
            typeof gumi[options] === 'function') {
          gumi[options].apply(gumi, Array.prototype.slice.call(args, 1));
        }
      }
    });
  };
})(jQuery, window, document);<commit_msg>last minor comment fix<commit_after>/**
 * Gumi v1.1.0
 * Usage: http://b1lly.github.io/gumi
 * GitHub: http://github.com/b1lly/gumi
 */

;(function($, window, document, undefined) {
  var defaults = {
    buttonClass: 'gumi-btn-default',
    buttonSelectedClass: 'gumi-btn-selected',
    optionDisabledClass: 'gumi-option-disabled',
    dropdownClass: 'gumi-dropdown-default',
    onChange: function() {},
    onOpen: function() {},
    onCancel: function() {
      this.reset();
    }
  };

  /**
   * @constructor
   */
  var Gumi = function(elem, options) {
    this.elem = elem;
    this.$elem = $(elem);
    this.$elem.addClass('gumi-wrap');

    // Reference to the button that shows the current selected option
    // and also handles the click event to show the dropdown
    this.$button = $('<button />');

    // Contains a reference to the dropdown list of options
    this.$dropdown = this.$elem.find('ul').hide();

    // Native form select element that gumi links too
    this.$select = $('<select />');

    this.selectedIndex = 0;
    this.selectedLabel = undefined;
    this.selectedValue = undefined;

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

    this._load = true;
    this._defaults = defaults;
    this._initialSelected = undefined;

    this._init();
  };

  /**
   * Build out our Gumi prototype and methods
   */
  Gumi.prototype = {
    constructor: Gumi,

    /**
     * Initialize the Gumi selectbox
     */
    _init: function() {
      this._createButton();
      this._createSelect();
      this._createDropdown();
      this._bindDropdown();
      this._bindSelectOption();
    },

    /**
     * Handle creating our button based on a variety of cases
     */
    _createButton: function() {
      var that = this;

      // Handle using a button that exists (or use our default)
      // and create the structure of our button label layout
      var $button = this.$elem.find('button'),
          $label = $('');

      if ($button.length) {
        this.$button = $button;
      }

      // Show the arrow icon on the label by default, unless otherwise specified
      if (!this.$button.attr('data-arrow-icn') ||
          this.$button.data('arrow-icn') === true) {
        $label.append(' ');
      }

      // Only show the close icon if specified
      // The binding get's handled in the '_bindDropdown()' method
      if (this.$button.data('cancel-icn') &&
          this.selectedIndex != this._initialSelected) {
        $label.append(' ');
      }

      this.$button.html($('
').append($label).html());
    },

    /**
     * Creates a hidden "<select>" based on
     * the list items from the ul jQuery selector
     */
    _createSelect: function() {
      // Adds the properties and options to our select
      // and get the selectedIndex from the option parsing
      this._updateSelect();

      // Attach our native select to the DOM
      this.$elem.append(this.$select);

      this._load = false;
    },

    /**
     * Updates the "<select>" properties, options and values
     * based on the current list of options from the "
"
     */
    _updateSelect: function() {
      var that = this,
          selectedIndex = 0;

      // Copy some attributes over to our select
      this.$select
        .addClass(this.options.dropdownClass)
        .addClass(this.$button.data('class'))
        .attr('name', this.$button.data('name'))
        .prop('required', this.$button.data('required'))
        .hide();

      // Add 'data' params to the select as HTML data-attributes
      this._deserializeParams();

      // Add the list options to our select options
      this.$elem.find('li').each(function(index) {
        var $self = $(this),
            val = $self.data('value');

        var value = val === undefined && val !== '' ? $self.html() : String(val),
            label = $self.data('label') || $self.html() || value;

        // Figure out which one should be selected by default
        if ($self.data('selected') === true) {
          selectedIndex = index;
        }

        // Handle custom styling for disabled class
        if ($self.data('disabled') === true) {
          $self.addClass(that.options.optionDisabledClass);
        }

        // Only show options that are selectable
        if ($self.data('selectable') === false) {
          $self.hide();
        }

        $('<option />')
          .val(value)
          .append(label)
          .addClass($self.attr('class'))
          .appendTo(that.$select);
      });

      // Set the initial selected
      this._initialSelected = selectedIndex;

      // Set the default option
      this.setSelectedOption(selectedIndex);

      return selectedIndex;
    },

    /**
     * Creates the clickable button to show
     * the dropdown, and attaches "optional"
     * custom classes to both the button and the dropdown
     */
    _createDropdown: function() {
      this.$button
        .addClass('gumi-btn')
        .addClass(this.options.buttonClass);

      // Insert the button before the dropdown
      this.$elem.prepend(this.$button);

      // Styling should hide the dropdown by default
      this.$dropdown
        .addClass('gumi-dropdown')
        .addClass(this.options.dropdownClass);
    },

    /**
     * Handle the interaction for showing and hiding the dropdown options
     */
    _bindDropdown: function() {
      var that = this;

      this.$button.on('click.Gumi', function(e) {
        e.preventDefault();
        e.stopPropagation();

        // We want to reset all other dropdowns on the page
        // to avoid having multiple dropdowns open at a time
        that._resetDropdowns(that.$elem);

        // Handle the user clicking the 'cancel' icon
        if ($(e.target).hasClass('js-gumi-cancel')) {
          that.options.onCancel.call(that);
          return;
        }

        // Handles clicking the button toggling
        that.$button.toggleClass(that.options.buttonSelectedClass);
        that.$dropdown.toggle();

        if (that.$dropdown.is(':visible')) {
          that.options.onOpen.call(that.$elem);
        }
      });

      $(document).off('click.Gumi');
      $(document).on('click.Gumi', function(e) {
        if ($(e.target).closest('.gumi-dropdown').length === 0) {
          that._resetDropdowns();
        }
      });
    },

    /**
     * When a user selects an option, we need to update our native
     * <select> in addition to our instance data
     */
    _bindSelectOption: function() {
      var that = this;

      that.$dropdown.on('click.Gumi', 'li', function(e) {
        var $self = $(this);
        e.stopPropagation();

        if (!$self.data('disabled')) {
          that.setSelectedOption($(this).index());
          that.closeDropdown();
        }
      });
    },

    /**
     * Resets all dropdowns on the page to default state, excluding callee
     * @param {jQueryObject} $elem Optional element to exclude from reset
     */
    _resetDropdowns: function($elem) {
      $('.gumi-wrap').not($elem).each(function() {
        $(this).data('gumi').closeDropdown();
      });
    },

    /**
     * Takes a serialized string of params and converts it to a map of data
     * based on the data attribute 'params' on the button node
     * e.g. { 'key' : 'val' }
     */
    _deserializeParams: function() {
      var params = this.$button.data('params'),
          data = {};

      if (!params) {
        return;
      }

      if (typeof params === 'string') {
        params = params.split(' ');

        var currentParam;
        for (var i = 0, len = params.length; i < len; i ++) {
          currentParam = params[i].split('=');
          data[currentParam[0]] = currentParam[1];
        }

        this._addDataToSelect(data);
      }
    },

    /**
     * Adds HTML5 Data attributes/values to the select
     * @param {object} data Map of data key to data value e.g. { 'height': 300 }
     */
    _addDataToSelect: function(data) {
      for (var key in data) {
        this.$select.data(key, data[key]);
      }
    },

    /**
     * Sync the markup with the hidden select
     */
    update: function() {
      this.$elem.find('select').empty();
      this._updateSelect();
    },

    /**
     * Set the selected option based on it's value
     * @param {string|number|boolean} value The value of the option to look for in our list
     */
    setSelected: function(value) {
      var $option = this.$select.find('option[value="' + value + '"]');

      if ($option.length) {
        this.setSelectedOption($option.index());
      }
    },

    /**
     * Sets the selected state to the native select box
     * based on the index. Also updates the instance and the label on the button
     * @param {number} opt_index Index of the select option to select (defaults 0)
     */
    setSelectedOption: function(opt_index) {
      opt_index = opt_index || 0;

      var label;
      var $option = this.$select.find('option').eq(opt_index);

      this.selectedIndex = opt_index;
      this.selectedLabel = this.$dropdown.eq(opt_index).data('label') || $option.text();
      this.selectedValue = $option.val();

      $option
        .prop('selected', true)
        .trigger('change');

      if (this._load === false ||
          (this._load === true && !this.$button.data('default-value'))) {
        this.$button.find('span em').text(this.selectedLabel);

        // Trigger our custom callback
        this.options.onChange.call(this.$select);
      }
    },

    /**
     * Public interface to bind a custom change event handler
     * @param {string} evt The event type to listen to
     * @param {function} fn The function callback for the event
     */
    onEvent: function(evt, fn) {
      if (typeof fn === 'function') {
        if (this.options[evt]) {
          this.options[evt] = fn;
        }
      }
    },

    /**
     * Hides the dropdown and removes the selected state of the button
     */
    closeDropdown: function() {
      this.$button.removeClass(this.options.buttonSelectedClass);
      this.$dropdown.hide();
    },

    /**
     * Resets the dropdown to it's original state during initialization
     */
    reset: function() {
      this.setSelectedOption(this._initialSelected);
    }
  };

  /**
   * Simple jQuery API for Gumi
   */
  $.fn.gumi = function(options) {
    var args = arguments,
        that = this;

    return this.each(function(index) {
      // Tries to get the instance of gumi that is referenced by the node
      var gumi = $.data(this, 'gumi');

      // If there's no gumi instance, assume we're initializing
      if (!gumi) {
        $.data(this, 'gumi', new Gumi(this, options));

        // Broadcast a "we're finished loading" event
        if (index === that.length - 1) {
          $(this).trigger('ready.Gumi');
        }
      } else {
        // Otherwise, access our public API (if viable)
        if (typeof options === 'string' &&
            typeof gumi[options] === 'function') {
          gumi[options].apply(gumi, Array.prototype.slice.call(args, 1));
        }
      }
    });
  };
})(jQuery, window, document);<|endoftext|>


<commit_before>var _ = require('lodash'),
    Chance = require('chance'),
    jsonPath = require('jsonpath')

var hazy = {}

hazy.config = {
  global: {
    seed: null
  }
}

hazy.meta = {
  types: {
    basic  : ['bool', 'character', 'integer', 'natural', 'string'],
    text   : ['paragraph', 'sentence', 'syllable', 'word'],
    person : ['age', 'birthday', 'cpf', 'first', 'gender', 'last', 'name', 'prefix', 'ssn', 'suffix'],
    mobile : ['android_id', 'apple_token', 'bb_pin', 'wp7_anid', 'wp8_anid2'],
    web    : ['color', 'domain', 'email', 'fbid', 'google_analytics', 'hashtag', 'ip', 'ipv6', 'klout', 'tld', 'twitter', 'url'],
    geo    : ['address', 'altitude', 'areacode', 'city', 'coordinates', 'country', 'depth', 'geohash', 'latitude', 'longitude', 'phone', 'postal', 'province', 'state', 'street', 'zip'],
    time   : ['ampm', 'date', 'hammertime', 'hour', 'millisecond', 'minute', 'month', 'second', 'timestamp', 'year'],
    misc   : ['guid', 'hash', 'hidden', 'n', 'normal', 'radio', 'rpg', 'tv', 'unique', 'weighted']

    // aliases
    // '?' : 'bool',
    // '#' : 'number',
    // '_' : 'string',
    // '$' : this.finance,
  }
}

hazy.lang = {
  expression: /\|(:|~|@)(.*?)?\|/,

  tokens: {
    "|": function(prev, next) { // expression start/end
      var isPrevToken    = this.validate(prev),
          isNextTokenEnd = /\|/.test(next)

      if (isPrevToken || isNextTokenEnd) {
        throw hazy.lang.exception('Cannot define an empty expression')
      }

      if (!next) {
        // return true
        // TODO - return a special value saying that this is the end of the token expression sequence
      }
    },

    ":": function(prev, next) { // property accessor
      if (!prev) {
        throw 'Syntax error, : requires a left operand'
      }

      return prev[next]
    },

    "~": function(prev, next, rest) { // random data
      var randProp   = next.split(':')[0] // match text to next : or |
          randVal    = next.split(':')[1]
          canUseProp = hazy.random.hasOwnProperty(randProp)

      if (canUseProp) {
        var randObjByProp  = hazy.random[randProp]
            randObjSubType = randVal // get property of random operator following ":"

        if (!randObjByProp || !randObjByProp[randObjSubType]) {
          throw hazy.lang.exception('Invalid random data type "' + randObjSubType + '". Supported:', hazy.meta.types[randProp])
        }

        return randObjByProp[randObjSubType]()
      } else {
        throw hazy.lang.exception('Invalid random data category "' + randProp + '". Supported', hazy.meta.types)
      }
    },

    "@": function(prev, next) { // link to stub
      return hazy.stub.get(next)
    },

    validate: function(token) {
      return this.hasOwnProperty(token)
    },

    process: function(token, prev, next, rest) {
      return _.bindKey(hazy.lang.tokens, token, prev, next, rest)()
    }
  },

  process: function(str) {
    var matches = str.match(this.expression)
    var results = []

    _.forEach(matches, function(match, i) {
      var isToken = hazy.lang.tokens.validate(match)

      if (isToken) {
        var prevMatch   = matches[i - 1],
            nextMatch   = matches[i + 1],
            restMatches = _.drop(matches, i + 1),
            expResult   = this.tokens.process(match, prevMatch, nextMatch, restMatches)

        if (expResult) {
          results.push(expResult)
        }
      }
    }, this)

    results = _.reduce(results, function(total, n) { return total + n })

    // replace tokens in original string with processed replacements
    if (_.isString(results)) {
      return str.replace(this.expression, results)
    }

    return results || str
  },

  exception: function(msg) {
    return '[Hazy syntax error] ' + msg
  }
}

hazy.random = _.mapValues(hazy.meta.types, function(value, key) {
  var hazyRandObj = {}

  _.forEach(value, function(v) {
     hazyRandObj[v] = function() { return new Chance()[v]() }
  })

  return hazyRandObj
})

hazy.stub = {
  pool: {},

  get: function(key) {
    return this.pool[key]
  },

  // FIXME - allow for optional non-lazy override. by defult this should return a function
  register: function(name, stub) {
    this.pool[name] = this.process(stub)
  },

  process: function(stub) { // dynamically process stub values by type (object, string, array, or function)
    var processedStub = {}

    if (_.isPlainObject(stub)) {
      _.mapKeys(stub, function(value, key) {
        var processedKey = hazy.lang.process(key),
            nextStub     = value

        processedStub[processedKey] = this.process(nextStub)
      }, this)
    }

    if (_.isArray(stub)) {
      return _.map(stub, hazy.lang.process)
    }

    if (_.isString(stub)) {
      return hazy.lang.process(stub)
    }

    if (_.isFunction(stub)) {
      return stub(null, hazy.config.global.seed) // TODO - provide/support per-instance seed and the object key
    }

    // TODO - determine if current stub matches a regex or name
    // hazy.stub.

    return processedStub
  },

  load: function(file) { // TODO - load from FS
    if (_.isArray(file)) {
      _.forEach(file, function() {

      })
    } else {

    }
  },

  write: function() {
    // TODO - write to FS
  }
}

hazy.pattern = {
  pool: {},

  appliesTo: function(stub) { // determines if a seed can be populated to the provided function
    return this.pool.hasOwnProperty(stub)
  },

  register: function(path, value) {
    this.pool[path] = value
  },

  addConfig: function(config) {
    var stubName       = config.stub,
        patternPath    = config.path,
        patternHandler = config.handler,
        patternKey     = stubName || stubPath

    if (!_.contains(this.pool, stubName)) {
      throw 'Stub is not registered in pool, failed to register pattern ' + stubName
    }

    this.pool[patternKey] = {name: stubName, path: stubPath, handler: patternHandler}
  }
}

hazy.seed   = _.cloneDeep(hazy.pattern)
hazy.filter = _.cloneDeep(hazy.pattern)
<commit_msg>work towards pattern matching (jsonpath)<commit_after>var _ = require('lodash'),
    Chance = require('chance'),
    jsonPath = require('jsonpath')

var hazy = {}

hazy.config = {
  seed: null,
  matchers: {
    use: true
  }
}

hazy.meta = {
  types: {
    basic  : ['bool', 'character', 'integer', 'natural', 'string'],
    text   : ['paragraph', 'sentence', 'syllable', 'word'],
    person : ['age', 'birthday', 'cpf', 'first', 'gender', 'last', 'name', 'prefix', 'ssn', 'suffix'],
    mobile : ['android_id', 'apple_token', 'bb_pin', 'wp7_anid', 'wp8_anid2'],
    web    : ['color', 'domain', 'email', 'fbid', 'google_analytics', 'hashtag', 'ip', 'ipv6', 'klout', 'tld', 'twitter', 'url'],
    geo    : ['address', 'altitude', 'areacode', 'city', 'coordinates', 'country', 'depth', 'geohash', 'latitude', 'longitude', 'phone', 'postal', 'province', 'state', 'street', 'zip'],
    time   : ['ampm', 'date', 'hammertime', 'hour', 'millisecond', 'minute', 'month', 'second', 'timestamp', 'year'],
    misc   : ['guid', 'hash', 'hidden', 'n', 'normal', 'radio', 'rpg', 'tv', 'unique', 'weighted']

    // aliases
    // '?' : 'bool',
    // '#' : 'number',
    // '_' : 'string',
    // '$' : this.finance,
  }
}

hazy.lang = {
  expression: /\|(:|~|@)(.*?)?\|/,

  tokens: {
    "|": function(prev, next) { // expression start/end
      var isPrevToken    = this.validate(prev),
          isNextTokenEnd = /\|/.test(next)

      if (isPrevToken || isNextTokenEnd) {
        throw hazy.lang.exception('Cannot define an empty expression')
      }

      if (!next) {
        // return true
        // TODO - return a special value saying that this is the end of the token expression sequence
      }
    },

    ":": function(prev, next) { // property accessor
      if (!prev) {
        throw 'Syntax error, : requires a left operand'
      }

      return prev[next]
    },

    "~": function(prev, next, rest) { // random data
      var randProp   = next.split(':')[0] // match text to next : or |
          randVal    = next.split(':')[1]
          canUseProp = hazy.random.hasOwnProperty(randProp)

      if (canUseProp) {
        var randObjByProp  = hazy.random[randProp]
            randObjSubType = randVal // get property of random operator following ":"

        if (!randObjByProp || !randObjByProp[randObjSubType]) {
          throw hazy.lang.exception('Invalid random data type "' + randObjSubType + '". Supported:', hazy.meta.types[randProp])
        }

        return randObjByProp[randObjSubType]()
      } else {
        throw hazy.lang.exception('Invalid random data category "' + randProp + '". Supported', hazy.meta.types)
      }
    },

    "@": function(prev, next) { // link to stub
      return hazy.stub.get(next)
    },

    validate: function(token) {
      return this.hasOwnProperty(token)
    },

    process: function(token, prev, next, rest) {
      return _.bindKey(hazy.lang.tokens, token, prev, next, rest)()
    }
  },

  process: function(str) {
    var matches = str.match(this.expression)
    var results = []

    _.forEach(matches, function(match, i) {
      var isToken = hazy.lang.tokens.validate(match)

      if (isToken) {
        var prevMatch   = matches[i - 1],
            nextMatch   = matches[i + 1],
            restMatches = _.drop(matches, i + 1),
            expResult   = this.tokens.process(match, prevMatch, nextMatch, restMatches)

        if (expResult) {
          results.push(expResult)
        }
      }
    }, this)

    results = _.reduce(results, function(total, n) { return total + n })

    // replace tokens in original string with processed replacements
    if (_.isString(results)) {
      return str.replace(this.expression, results)
    }

    return results || str
  },

  exception: function(msg) {
    return '[Hazy syntax error] ' + msg
  }
}

hazy.random = _.mapValues(hazy.meta.types, function(value, key) {
  var hazyRandObj = {}

  _.forEach(value, function(v) {
     hazyRandObj[v] = function() { return new Chance()[v]() }
  })

  return hazyRandObj
})

hazy.stub = {
  pool: {},

  get: function(key) {
    return this.pool[key]
  },

  // FIXME - allow for optional non-lazy override. by defult this should return a function
  register: function(name, stub) {
    this.pool[name] = this.process(stub)
  },

  process: function(stub) { // dynamically process stub values by type (object, string, array, or function)
    var processedStub = {}

    if (_.isPlainObject(stub)) {
      _.mapKeys(stub, function(value, key) {
        var processedKey = hazy.lang.process(key),
            nextStub     = value

        processedStub[processedKey] = this.process(nextStub)
      }, this)
    }

    if (_.isArray(stub)) {
      return _.map(stub, hazy.lang.process)
    }

    if (_.isString(stub)) {
      return hazy.lang.process(stub)
    }

    if (_.isFunction(stub)) {
      return stub(null, hazy.config.seed) // TODO - provide/support per-instance seed and the object key
    }

    // TODO - determine if current stub matches a regex or name
    // hazy.stub.
    if (hazy.config.matchers.use && hazy.matcher.hasMatch(stub)) {
      console.log('MATCHED ', stub)
    }

    return processedStub
  },

  load: function(file) { // TODO - load from FS
    if (_.isArray(file)) {
      _.forEach(file, function() {

      })
    } else {

    }
  },

  write: function() {
    // TODO - write to FS
  }
}

// Matching filters which can be injected into your application before stubs are allocated to the stub pool

hazy.matcher = {
  pool: {},

  register: function(path, value) {
    this.pool[path] = value
  },

  addConfig: function(config) {
    var stubName       = config.stub,
        matcherPath    = config.path,
        matcherHandler = config.handler,
        matcherKey     = stubName || matcherPath

    // TODO - ensure stub is not yet processed in the stub pool before adding a matcher config

    this.pool[matcherKey] = {name: stubName, path: matcherPath, handler: matcherHandler}
  },

  hasMatch: function(stub) { // determines if a pattern applies to the provided stub (TODO - clearly optimize, madhax)
    var inPool      = _.isString(stub) && this.pool.hasOwnProperty(stub)
        matchExists = inPool || _.every(_.mapKeys(hazy.matcher.pool, function(v,pattern) {
          return _.isString(stub) && !_.isUndefined(
            jsonPath.query(pattern, stub)
          )
        }), true)

    return matchExists
  },
}

<|endoftext|>


<commit_before>jQuery(function($) {

  $(".add-friend").live('click', function(){
    clicked = $(this)
    url = clicked.attr("href");
    loading_for_button(this);
    $.post(url, function(data){
      clicked.fadeOut();
      display_notice(data);
    });
    return false;
  })

  $(".join-community").live('click', function(){
    clicked = $(".join-community");
    url = clicked.attr("href");
    loading_for_button(this);
    $.post(url, function(data){
      clicked.fadeOut(function(){
        clicked.css("display","none");
        clicked.parent().parent().find(".leave-community").fadeIn();
        clicked.parent().parent().find(".leave-community").css("display", "");
      });
      clicked.css("cursor","");
      $(".small-loading").remove();
      display_notice(data.message);
    }, "json");
    return false;
  })

  $(".leave-community").live('click', function(){
    clicked = $(".leave-community");
    url = clicked.attr("href");
    loading_for_button(this);
    $.post(url, function(data){
      if(data.redirect_to){
        document.location.href = data.redirect_to;
      }
      else if(data.reload){
        document.location.reload(true);
      }
      else{
        clicked.fadeOut(function(){
          clicked.css("display","none");
          clicked.parent().parent().find(".join-community").fadeIn();
          clicked.parent().parent().find(".join-community").css("display", "");
        });
        clicked.css("cursor","");
        $(".small-loading").remove();

        display_notice(data.message);
      }
    }, "json");
    return false;
  })

  $(".person-trigger").click(function(){
    clicked = $(this);
    url = clicked.attr("url");
    $.get(url, function(data){
      if(data == "true"){
        clicked.parent().find(".add-friend").fadeOut(function(){
          clicked.parent().find(".send-an-email").fadeIn();
        })
      }
      else if(data == "false"){
        clicked.parent().find(".send-an-email").fadeOut(function(){
          clicked.parent().find(".add-friend").fadeIn();
        });
      }
    })
  })

  $(".community-trigger").click(function(){
    clicked = $(this);
    url = clicked.attr("url");
    $.get(url, function(data){
      if(data == "true"){
        clicked.parent().find(".join-community").fadeOut(function(){
          clicked.parent().find(".leave-community").fadeIn();
          clicked.parent().find(".send-an-email").fadeIn();
        });
      }
      else if(data == "false"){
        clicked.parent().find(".send-an-email").fadeOut();
        clicked.parent().find(".leave-community").fadeOut(function(){
          clicked.parent().find(".join-community").fadeIn();
        });
      }
    })
  })

  $(".enterprise-trigger").click(function(){
    clicked = $(this);
    url = clicked.attr("url");
    $.get(url, function(data){
      if(data == "true")
        clicked.parent().find(".send-an-email").fadeIn();
      else if(data == "false")
        clicked.parent().find(".send-an-email").fadeOut();
    })
  })

  $(".comment-trigger").live('click', function(){
    clicked = $(this);
    url = clicked.attr("url");
    $.get(url, function(data){
      ids = [];
      if(data && data.ids) {
        for(var i=0; i<data.ids.length; i++) {
          clicked.parent().find(data.ids[i]).fadeIn();
          ids.push(data.ids[i]);
        }
      }
      clicked.parent().find('.comment-action-extra').each(function() {
        if($.inArray('#'+$(this).attr('id'), ids))
          $(this).fadeOut();
      });
    })
    return false;
  })

});
<commit_msg>Fix javascript for join and leave communities<commit_after>jQuery(function($) {

  $(".add-friend").live('click', function(){
    clicked = $(this);
    url = clicked.attr("href");
    loading_for_button(this);
    $.post(url, function(data){
      clicked.fadeOut();
      display_notice(data);
    });
    return false;
  })

  $(".join-community").live('click', function(){
    clicked = $(this);
    url = clicked.attr("href");
    loading_for_button(this);
    $.post(url, function(data){
      clicked.fadeOut(function(){
        clicked.css("display","none");
        clicked.parent().parent().find(".leave-community").fadeIn();
        clicked.parent().parent().find(".leave-community").css("display", "");
      });
      clicked.css("cursor","");
      $(".small-loading").remove();
      display_notice(data.message);
    }, "json");
    return false;
  })

  $(".leave-community").live('click', function(){
    clicked = $(this);
    url = clicked.attr("href");
    loading_for_button(this);
    $.post(url, function(data){
      if(data.redirect_to){
        document.location.href = data.redirect_to;
      }
      else if(data.reload){
        document.location.reload(true);
      }
      else{
        clicked.fadeOut(function(){
          clicked.css("display","none");
          clicked.parent().parent().find(".join-community").fadeIn();
          clicked.parent().parent().find(".join-community").css("display", "");
        });
        clicked.css("cursor","");
        $(".small-loading").remove();

        display_notice(data.message);
      }
    }, "json");
    return false;
  })

  $(".person-trigger").click(function(){
    clicked = $(this);
    url = clicked.attr("url");
    $.get(url, function(data){
      if(data == "true"){
        clicked.parent().find(".add-friend").fadeOut(function(){
          clicked.parent().find(".send-an-email").fadeIn();
        })
      }
      else if(data == "false"){
        clicked.parent().find(".send-an-email").fadeOut(function(){
          clicked.parent().find(".add-friend").fadeIn();
        });
      }
    })
  })

  $(".community-trigger").click(function(){
    clicked = $(this);
    url = clicked.attr("url");
    $.get(url, function(data){
      if(data == "true"){
        clicked.parent().find(".join-community").fadeOut(function(){
          clicked.parent().find(".leave-community").fadeIn();
          clicked.parent().find(".send-an-email").fadeIn();
        });
      }
      else if(data == "false"){
        clicked.parent().find(".send-an-email").fadeOut();
        clicked.parent().find(".leave-community").fadeOut(function(){
          clicked.parent().find(".join-community").fadeIn();
        });
      }
    })
  })

  $(".enterprise-trigger").click(function(){
    clicked = $(this);
    url = clicked.attr("url");
    $.get(url, function(data){
      if(data == "true")
        clicked.parent().find(".send-an-email").fadeIn();
      else if(data == "false")
        clicked.parent().find(".send-an-email").fadeOut();
    })
  })

  $(".comment-trigger").live('click', function(){
    clicked = $(this);
    url = clicked.attr("url");
    $.get(url, function(data){
      ids = [];
      if(data && data.ids) {
        for(var i=0; i<data.ids.length; i++) {
          clicked.parent().find(data.ids[i]).fadeIn();
          ids.push(data.ids[i]);
        }
      }
      clicked.parent().find('.comment-action-extra').each(function() {
        if($.inArray('#'+$(this).attr('id'), ids))
          $(this).fadeOut();
      });
    })
    return false;
  })

});
<|endoftext|>


<commit_before>//** Smooth Navigational Menu- By Dynamic Drive DHTML code library: http://www.dynamicdrive.com
//** Script Download/ instructions page: http://www.dynamicdrive.com/dynamicindex1/ddlevelsmenu/
//** Menu created: Nov 12, 2008

//** Dec 12th, 08" (v1.01): Fixed Shadow issue when multiple LIs within the same UL (level) contain sub menus: http://www.dynamicdrive.com/forums/showthread.php?t=39177&highlight=smooth

//** Feb 11th, 09" (v1.02): The currently active main menu item (LI A) now gets a CSS class of ".selected", including sub menu items.

//** May 1st, 09" (v1.3):
//** 1) Now supports vertical (side bar) menu mode- set "orientation" to 'v'
//** 2) In IE6, shadows are now always disabled

//** July 27th, 09" (v1.31): Fixed bug so shadows can be disabled if desired.
//** Feb 2nd, 10" (v1.4): Adds ability to specify delay before sub menus appear and disappear, respectively. See showhidedelay variable below

//** Dec 17th, 10" (v1.5): Updated menu shadow to use CSS3 box shadows when the browser is FF3.5+, IE9+, Opera9.5+, or Safari3+/Chrome. Only .js file changed.

var ddsmoothmenu = {

  //Specify full URL to down and right arrow images (23 is padding-right added to top level LIs with drop downs):
  arrowimages: {
    down:['downarrowclass', '../images/down.gif', 23],
    right:['rightarrowclass', '../images/right.gif']
  },
  transition: {
    overtime:0,
    outtime:0
  }, //duration of slide in/ out animation, in milliseconds
  shadow: {
    enable:true,
    offsetx:5,
    offsety:5
  }, //enable shadow?
  showhidedelay: {
    showdelay: 0, hidedelay: 0
  }, //set delay in milliseconds before sub menus appear and disappear, respectively

///////Stop configuring beyond here///////////////////////////

  detectwebkit: navigator.userAgent.toLowerCase().indexOf("applewebkit")!=-1, //detect WebKit browsers (Safari, Chrome etc)
  detectie6: document.all && !window.XMLHttpRequest,
  css3support: window.msPerformance || (!document.all && document.querySelector), //detect browsers that support CSS3 box shadows (ie9+ or FF3.5+, Safari3+, Chrome etc)

getajaxmenu:function($, setting){ //function to fetch external page containing the panel DIVs
    var $menucontainer=$('#'+setting.contentsource[0]); //reference empty div on page that will hold menu
    $menucontainer.html("Loading Menu...");
    $.ajax({
        url: setting.contentsource[1], //path to external menu file
        async: true,
        error:function(ajaxrequest){
            $menucontainer.html('Error fetching content. Server Response: '+ajaxrequest.responseText)
        },
        success:function(content){
            $menucontainer.html(content)
            ddsmoothmenu.buildmenu($, setting)
        }
    });
},

buildmenu:function($, setting) {
    var smoothmenu = ddsmoothmenu;
    var $mainmenu = $("#"+setting.mainmenuid+">ul"); //reference main menu UL
    var $headers = $mainmenu.find("ul").parent();
    $headers.hover(
        function(e) {
            $(this).children('a:eq(0)').addClass('selected');
        },
        function(e) {
            $(this).children('a:eq(0)').removeClass('selected');
        }
    );
    $headers.each(function(i){ //loop through each LI header
        var $curobj=$(this); //reference current LI header
        var $subul=$(this).find('ul:eq(0)').css({display:'block'});
        var self = this;
        $subul.data('timers', {});
        this._dimensions={w:this.offsetWidth, h:this.offsetHeight, subulw:$subul.outerWidth, subulh:$subul.outerHeight};
        this.istopheader=$curobj.parents("ul").length==1? true : false; //is top level header?
        $subul.css({top:this.istopheader && setting.orientation!='v'? this._dimensions.h+"px" : 0}); //this is where height of $subul determined
        if (smoothmenu.shadow.enable && !smoothmenu.css3support){ //if shadows enabled and browser doesn't support CSS3 box shadows
            this._shadowoffset={x:(this.istopheader?$subul.offset().left+smoothmenu.shadow.offsetx : this._dimensions.w), y:(this.istopheader? $subul.offset().top+smoothmenu.shadow.offsety : $curobj.position().top)}; //store this shadow's offsets
            if (this.istopheader)
                $parentshadow=$(document.body);
            else{
                var $parentLi=$curobj.parents("li:eq(0)");
                $parentshadow=$parentLi.get(0).$shadow;
            }
            this.$shadow=$('

').prependTo($parentshadow).css({left:this._shadowoffset.x+'px', top:this._shadowoffset.y+'px'});  //insert shadow DIV and set it to parent node for the next shadow div
        }

        $curobj.hover(
            function(e){
                var $targetul=$subul; //reference UL to reveal
                var header=$curobj.get(0); //reference header LI as DOM object
                clearTimeout($targetul.data('timers').hidetimer);
                $targetul.data('timers').showtimer=setTimeout(function(){
                    header._offsets={left:$curobj.offset().left, top:$curobj.offset().top};
                    var menuleft=header.istopheader && setting.orientation!='v'? 0 : header._dimensions.w;
                    menuleft=(header._offsets.left+menuleft+header._dimensions.subulw>$(window).width())? (header.istopheader && setting.orientation!='v'? -header._dimensions.subulw+header._dimensions.w : -header._dimensions.w) : menuleft; //calculate this sub menu's offsets from its parent
                    if ($targetul.queue().length<=1){ //if 1 or less queued animations
                        $targetul.css({left:menuleft+"px", width:header._dimensions.subulw+'px'}).animate({height:'show',opacity:'show'}, ddsmoothmenu.transition.overtime);
                        if (smoothmenu.shadow.enable && !smoothmenu.css3support){
                            var shadowleft=header.istopheader? $targetul.offset().left+ddsmoothmenu.shadow.offsetx : menuleft;
                            var shadowtop=header.istopheader?$targetul.offset().top+smoothmenu.shadow.offsety : header._shadowoffset.y;
                            if (!header.istopheader && ddsmoothmenu.detectwebkit){ //in WebKit browsers, restore shadow's opacity to full
                                header.$shadow.css({opacity:1});
                            }
                            header.$shadow.css({overflow:'', width:header._dimensions.subulw+'px', left:shadowleft+'px', top:shadowtop+'px'}).animate({height:header._dimensions.subulh+'px'}, ddsmoothmenu.transition.overtime);
                        }
                    }

                    // Hack by D. Shorthouse to pop menu up if necessary
                    if(setting.orientation!='v' && e.pageY + $targetul.height() > $(window).height() + $(window).scrollTop()) {
                      $targetul.css({top:-$targetul.height()+"px"});
                    }

                }, ddsmoothmenu.showhidedelay.showdelay);
            },
            function(e){
                var $targetul=$subul;
                var header=$curobj.get(0);
                clearTimeout($targetul.data('timers').showtimer);
                $targetul.data('timers').hidetimer=setTimeout(function(){
                    $targetul.animate({height:'hide', opacity:'hide'}, ddsmoothmenu.transition.outtime);
                    if (smoothmenu.shadow.enable && !smoothmenu.css3support){
                        if (ddsmoothmenu.detectwebkit){ //in WebKit browsers, set first child shadow's opacity to 0, as "overflow:hidden" doesn't work in them
                            header.$shadow.children('div:eq(0)').css({opacity:0});
                        }
                        header.$shadow.css({overflow:'hidden'}).animate({height:0}, ddsmoothmenu.transition.outtime);
                    }

                    // Hack by D. Shorthouse to put menu back into place
                    if(setting.orientation!='v') {
                      $targetul.css({top:self._dimensions.h+"px"});
                    }

                }, ddsmoothmenu.showhidedelay.hidedelay);
            }
        ); //end hover
    }); //end $headers.each()
    if (smoothmenu.shadow.enable && smoothmenu.css3support){ //if shadows enabled and browser supports CSS3 shadows
        var $toplevelul=$('#'+setting.mainmenuid+' ul li ul');
        var css3shadow=parseInt(smoothmenu.shadow.offsetx)+"px "+parseInt(smoothmenu.shadow.offsety)+"px 5px #aaa"; //construct CSS3 box-shadow value
        var shadowprop=["boxShadow", "MozBoxShadow", "WebkitBoxShadow", "MsBoxShadow"]; //possible vendor specific CSS3 shadow properties
        for (var i=0; i<shadowprop.length; i++){
            $toplevelul.css(shadowprop[i], css3shadow);
        }
    }
    $mainmenu.find("ul").css({display:'none'});
},

init:function(setting){
    if (typeof setting.customtheme=="object" && setting.customtheme.length==2){ //override default menu colors (default/hover) with custom set?
        var mainmenuid='#'+setting.mainmenuid;
        var mainselector=(setting.orientation=="v")? mainmenuid : mainmenuid+', '+mainmenuid;
        document.write('');
    }
    this.shadow.enable=(document.all && !window.XMLHttpRequest)? false : this.shadow.enable; //in IE6, always disable shadow
    jQuery(document).ready(function($){ //ajax menu?
        if (typeof setting.contentsource=="object") { //if external ajax menu
            ddsmoothmenu.getajaxmenu($, setting);
        }
        else { //else if markup menu
            ddsmoothmenu.buildmenu($, setting);
        }
    });
}

}; //end ddsmoothmenu variable
<commit_msg>Adjustment to pop-up positioning<commit_after>//** Smooth Navigational Menu- By Dynamic Drive DHTML code library: http://www.dynamicdrive.com
//** Script Download/ instructions page: http://www.dynamicdrive.com/dynamicindex1/ddlevelsmenu/
//** Menu created: Nov 12, 2008

//** Dec 12th, 08" (v1.01): Fixed Shadow issue when multiple LIs within the same UL (level) contain sub menus: http://www.dynamicdrive.com/forums/showthread.php?t=39177&highlight=smooth

//** Feb 11th, 09" (v1.02): The currently active main menu item (LI A) now gets a CSS class of ".selected", including sub menu items.

//** May 1st, 09" (v1.3):
//** 1) Now supports vertical (side bar) menu mode- set "orientation" to 'v'
//** 2) In IE6, shadows are now always disabled

//** July 27th, 09" (v1.31): Fixed bug so shadows can be disabled if desired.
//** Feb 2nd, 10" (v1.4): Adds ability to specify delay before sub menus appear and disappear, respectively. See showhidedelay variable below

//** Dec 17th, 10" (v1.5): Updated menu shadow to use CSS3 box shadows when the browser is FF3.5+, IE9+, Opera9.5+, or Safari3+/Chrome. Only .js file changed.

var ddsmoothmenu = {

  //Specify full URL to down and right arrow images (23 is padding-right added to top level LIs with drop downs):
  arrowimages: {
    down:['downarrowclass', '../images/down.gif', 23],
    right:['rightarrowclass', '../images/right.gif']
  },
  transition: {
    overtime:0,
    outtime:0
  }, //duration of slide in/ out animation, in milliseconds
  shadow: {
    enable:true,
    offsetx:5,
    offsety:5
  }, //enable shadow?
  showhidedelay: {
    showdelay: 0, hidedelay: 0
  }, //set delay in milliseconds before sub menus appear and disappear, respectively

///////Stop configuring beyond here///////////////////////////

  detectwebkit: navigator.userAgent.toLowerCase().indexOf("applewebkit")!=-1, //detect WebKit browsers (Safari, Chrome etc)
  detectie6: document.all && !window.XMLHttpRequest,
  css3support: window.msPerformance || (!document.all && document.querySelector), //detect browsers that support CSS3 box shadows (ie9+ or FF3.5+, Safari3+, Chrome etc)

getajaxmenu:function($, setting){ //function to fetch external page containing the panel DIVs
    var $menucontainer=$('#'+setting.contentsource[0]); //reference empty div on page that will hold menu
    $menucontainer.html("Loading Menu...");
    $.ajax({
        url: setting.contentsource[1], //path to external menu file
        async: true,
        error:function(ajaxrequest){
            $menucontainer.html('Error fetching content. Server Response: '+ajaxrequest.responseText)
        },
        success:function(content){
            $menucontainer.html(content)
            ddsmoothmenu.buildmenu($, setting)
        }
    });
},

buildmenu:function($, setting) {
    var smoothmenu = ddsmoothmenu;
    var $mainmenu = $("#"+setting.mainmenuid+">ul"); //reference main menu UL
    var $headers = $mainmenu.find("ul").parent();
    $headers.hover(
        function(e) {
            $(this).children('a:eq(0)').addClass('selected');
        },
        function(e) {
            $(this).children('a:eq(0)').removeClass('selected');
        }
    );
    $headers.each(function(i){ //loop through each LI header
        var $curobj=$(this); //reference current LI header
        var $subul=$(this).find('ul:eq(0)').css({display:'block'});
        var self = this;
        $subul.data('timers', {});
        this._dimensions={w:this.offsetWidth, h:this.offsetHeight, subulw:$subul.outerWidth, subulh:$subul.outerHeight};
        this.istopheader=$curobj.parents("ul").length==1? true : false; //is top level header?
        $subul.css({top:this.istopheader && setting.orientation!='v'? this._dimensions.h+"px" : 0}); //this is where height of $subul determined
        if (smoothmenu.shadow.enable && !smoothmenu.css3support){ //if shadows enabled and browser doesn't support CSS3 box shadows
            this._shadowoffset={x:(this.istopheader?$subul.offset().left+smoothmenu.shadow.offsetx : this._dimensions.w), y:(this.istopheader? $subul.offset().top+smoothmenu.shadow.offsety : $curobj.position().top)}; //store this shadow's offsets
            if (this.istopheader)
                $parentshadow=$(document.body);
            else{
                var $parentLi=$curobj.parents("li:eq(0)");
                $parentshadow=$parentLi.get(0).$shadow;
            }
            this.$shadow=$('

').prependTo($parentshadow).css({left:this._shadowoffset.x+'px', top:this._shadowoffset.y+'px'});  //insert shadow DIV and set it to parent node for the next shadow div
        }

        $curobj.hover(
            function(e){
                var $targetul=$subul; //reference UL to reveal
                var header=$curobj.get(0); //reference header LI as DOM object
                clearTimeout($targetul.data('timers').hidetimer);
                $targetul.data('timers').showtimer=setTimeout(function(){
                    header._offsets={left:$curobj.offset().left, top:$curobj.offset().top};
                    var menuleft=header.istopheader && setting.orientation!='v'? 0 : header._dimensions.w;
                    menuleft=(header._offsets.left+menuleft+header._dimensions.subulw>$(window).width())? (header.istopheader && setting.orientation!='v'? -header._dimensions.subulw+header._dimensions.w : -header._dimensions.w) : menuleft; //calculate this sub menu's offsets from its parent
                    if ($targetul.queue().length<=1){ //if 1 or less queued animations
                        $targetul.css({left:menuleft+"px", width:header._dimensions.subulw+'px'}).animate({height:'show',opacity:'show'}, ddsmoothmenu.transition.overtime);
                        if (smoothmenu.shadow.enable && !smoothmenu.css3support){
                            var shadowleft=header.istopheader? $targetul.offset().left+ddsmoothmenu.shadow.offsetx : menuleft;
                            var shadowtop=header.istopheader?$targetul.offset().top+smoothmenu.shadow.offsety : header._shadowoffset.y;
                            if (!header.istopheader && ddsmoothmenu.detectwebkit){ //in WebKit browsers, restore shadow's opacity to full
                                header.$shadow.css({opacity:1});
                            }
                            header.$shadow.css({overflow:'', width:header._dimensions.subulw+'px', left:shadowleft+'px', top:shadowtop+'px'}).animate({height:header._dimensions.subulh+'px'}, ddsmoothmenu.transition.overtime);
                        }
                    }

                    // Hack by D. Shorthouse to pop menu up if necessary
                    if(setting.orientation!='v' && e.pageY + $targetul.height() + 15 > $(window).height() + $(window).scrollTop()) {
                      $targetul.css({top:-$targetul.height()+"px"});
                    }

                }, ddsmoothmenu.showhidedelay.showdelay);
            },
            function(e){
                var $targetul=$subul;
                var header=$curobj.get(0);
                clearTimeout($targetul.data('timers').showtimer);
                $targetul.data('timers').hidetimer=setTimeout(function(){
                    $targetul.animate({height:'hide', opacity:'hide'}, ddsmoothmenu.transition.outtime);
                    if (smoothmenu.shadow.enable && !smoothmenu.css3support){
                        if (ddsmoothmenu.detectwebkit){ //in WebKit browsers, set first child shadow's opacity to 0, as "overflow:hidden" doesn't work in them
                            header.$shadow.children('div:eq(0)').css({opacity:0});
                        }
                        header.$shadow.css({overflow:'hidden'}).animate({height:0}, ddsmoothmenu.transition.outtime);
                    }

                    // Hack by D. Shorthouse to put menu back into place
                    if(setting.orientation!='v') {
                      $targetul.css({top:self._dimensions.h+"px"});
                    }

                }, ddsmoothmenu.showhidedelay.hidedelay);
            }
        ); //end hover
    }); //end $headers.each()
    if (smoothmenu.shadow.enable && smoothmenu.css3support){ //if shadows enabled and browser supports CSS3 shadows
        var $toplevelul=$('#'+setting.mainmenuid+' ul li ul');
        var css3shadow=parseInt(smoothmenu.shadow.offsetx)+"px "+parseInt(smoothmenu.shadow.offsety)+"px 5px #aaa"; //construct CSS3 box-shadow value
        var shadowprop=["boxShadow", "MozBoxShadow", "WebkitBoxShadow", "MsBoxShadow"]; //possible vendor specific CSS3 shadow properties
        for (var i=0; i<shadowprop.length; i++){
            $toplevelul.css(shadowprop[i], css3shadow);
        }
    }
    $mainmenu.find("ul").css({display:'none'});
},

init:function(setting){
    if (typeof setting.customtheme=="object" && setting.customtheme.length==2){ //override default menu colors (default/hover) with custom set?
        var mainmenuid='#'+setting.mainmenuid;
        var mainselector=(setting.orientation=="v")? mainmenuid : mainmenuid+', '+mainmenuid;
        document.write('');
    }
    this.shadow.enable=(document.all && !window.XMLHttpRequest)? false : this.shadow.enable; //in IE6, always disable shadow
    jQuery(document).ready(function($){ //ajax menu?
        if (typeof setting.contentsource=="object") { //if external ajax menu
            ddsmoothmenu.getajaxmenu($, setting);
        }
        else { //else if markup menu
            ddsmoothmenu.buildmenu($, setting);
        }
    });
}

}; //end ddsmoothmenu variable
<|endoftext|>


<commit_before>
/*

//nominatim.openstreetmap.org/reverse/?lat=33.49351305030696&lon=-111.95955634117126&zoom=18&addressdetails=1&format=json

*/

(function() {
    "use strict";

    console.log('GeoCoder setup');
    define([
    ],

        function GeoCoder() {

			var options = {};
            var http = null;
            options.serviceUrl = '//nominatim.openstreetmap.org/';

            // Return public API.
            return({
                start: init,
                reverse: reverse
            });

            function handleSuccess( response ) {

                return(response.data);

            };

            // I transform the error response, unwrapping the application dta from
            // the API response payload.
            function handleError( response ) {

                // The API response from the server should be returned in a
                // nomralized format. However, if the request was not handled by the
                // server (or what not handles properly - ex. server error), then we
                // may have to normalize it on our end, as best we can.
                if (
                    ! angular.isObject( response.data ) ||
                    ! response.data.message
                    ) {

                    return( $q.reject( "An unknown error occurred." ) );

                }

                // Otherwise, use expected error message.
                return( $q.reject( response.data.message ) );

            };
    //nominatim.openstreetmap.org/reverse/?lat=33.49351305030696&lon=-111.95955634117126&zoom=18&addressdetails=1&format=json

            function reverse(location, scale) {
                var zm = 18; //Math.round(Math.log(scale / 256) / Math.log(2));
                var qstr = options.serviceUrl + 'reverse/?lat=' + location.lat + '&lon=' + location.lng + '&zoom='+ zm +
                    '&addressdetails=1&format=json';
                 console.log(qstr);

                var request = http({
                    method: "get",
                    url: qstr,
                    params: {
                        action: "get"
                    }
                });

                return( request.then( handleSuccess, handleError ) );
            };

        function init(App, hhttttpp) {
            http = hhttttpp;
            console.log('GeoCoder init');
            App.service('GeoCoder', GeoCoder);
            return GeoCoder;
        };

    });

}).call(this);<commit_msg>Linted Leaflet GeoCoder<commit_after>/*global define */

/*

//nominatim.openstreetmap.org/reverse/?lat=33.49351305030696&lon=-111.95955634117126&zoom=18&addressdetails=1&format=json

*/

(function () {
    "use strict";

    console.log('GeoCoder setup');
    define([
    ],

        function GeoCoder() {

            var options = {},
                http = null;
            options.serviceUrl = '//nominatim.openstreetmap.org/';

            function init(App, hhttttpp) {
                http = hhttttpp;
                console.log('GeoCoder init');
                App.service('GeoCoder', GeoCoder);
                return GeoCoder;
            }

            function handleSuccess(response) {

                return (response.data);

            }

            // I transform the error response, unwrapping the application dta from
            // the API response payload.
            function handleError(response) {

                // The API response from the server should be returned in a
                // nomralized format. However, if the request was not handled by the
                // server (or what not handles properly - ex. server error), then we
                // may have to normalize it on our end, as best we can.
                if (!angular.isObject(response.data) || !response.data.message) {
                    return ($q.reject("An unknown error occurred."));
                }

                // Otherwise, use expected error message.
                return ($q.reject(response.data.message));

            }

            function reverse(location, scale) {
                var zm = 18, //Math.round(Math.log(scale / 256) / Math.log(2)),
                    qstr = options.serviceUrl + 'reverse/?lat=' + location.lat + '&lon=' + location.lng + '&zoom=' + zm +
                        '&addressdetails=1&format=json',
                    request;
                console.log(qstr);

                request = http({
                    method: "get",
                    url: qstr,
                    params: {
                        action: "get"
                    }
                });

                return (request.then(handleSuccess, handleError));
            }

            // Return public API.
            return ({
                start: init,
                reverse: reverse
            });

    //nominatim.openstreetmap.org/reverse/?lat=33.49351305030696&lon=-111.95955634117126&zoom=18&addressdetails=1&format=json

        });

}());
<|endoftext|>


<commit_before>DOMBuilder.apply(window);

Presentation = function() {
	var pub = {};
	var transition = {
		show: {
			effect: "slide",
			options: {},
			speed: "normal"
		},
		hide: {
			effect: "slide",
			options: {},
			speed: "normal"
		}
	}
	var _imageIndex = 0;
	var _images = [];
	var _slideIndex = null;
	var _pollLocationHash = function() {
		var index = pub.getSlideIndex();
		if (_slideIndex != index) {
			if (_slideIndex == null) {
				showSlide(index);
			} else {
				doTransition(_slideIndex, index);
			}
			//console.log("switching from slide #" + _slideIndex + " to #" + index);
			_slideIndex = index;
		}
	}
	function showSlide(index) {
		$(".slide[id='" + index + "']").fadeIn("normal");
		Slide.layout();
		$(".slide[id='" + index + "'] a.zoom").each(function(e){
			console.log(this);
			_images.push(this);
		});
		_imageIndex = 0;
	}
	function doTransition(from, to) {
		$(".slide[id='" + from + "']").fadeOut("normal", function() {showSlide(to)});
	}
	pub.getSlideIndex = function() {
		return parseInt(location.hash.substring(1)) || 1;
	}
	pub.init = function() {
		$(".slide").hide();
		setInterval(_pollLocationHash, 200);
	}
	pub.showSlide = function(index) {
		location.hash = "#" + index;
	}
	pub.nextSlide = function() {
		pub.showSlide(_slideIndex + 1);
	}
	pub.previousSlide = function() {
		pub.showSlide(_slideIndex - 1)
	}
	pub.nextImage = function() {
		$(_images[_imageIndex]).trigger("click");
		_imageIndex++
	}
	pub.previousImage =  function() {
		$(_images[_imageIndex]).trigger("click")
		_imageIndex--
	}
	return pub;
}();

Slide = function() {
	var pub = {};
	pub.width = function() {
		//Try using slide-div-dimensions
		return $(window).width();
	}
	pub.height = function() {
		return $(window).height();
	}
	pub.layout = function() {
		//console.log("layout");
		var size = Slide.height() / 32;
	    $("body").css("font-size", size + 'px');
	    $(".slide").css("width", Slide.width() + 'px');
	    $(".slide").css("height", Slide.height() + 'px');
		$("#" + Presentation.getSlideIndex() + " .fit").each(function() {
			if (!$(this).data('dimensions')) {
				$(this).data('dimensions', {
					width: $(this).width(),
					height: $(this).height(),
					parent: $(this).offsetParent()
				});
			}
			var width = $(this).data('dimensions').width;
			var height = $(this).data('dimensions').height;

			var ratio = width/height;
			var parent = $(this).data('dimensions').parent;
			var new_width = 0;
			var new_height = 0;

			if (ratio < (parent.width() / parent.height())) {
				new_height = parent.height();
				new_width = new_height * ratio;
			} else {
				new_width = parent.width();
				new_height = new_width / ratio;
			}
			$(this).width(new_width);
			$(this).height(new_height);
		});

		//Align centered elements
		$(".center").each(function() {
			Slot.center($(this));
		});
		$(".center_v").each(function() {
			Slot.centerVertically($(this));
		});
		$(".center_h").each(function() {
			Slot.centerHorizontally($(this));
		});

	}
	return pub;
}();

var Slot = {
	init: function(element) {
		if (!element.data('dimensions')) {
			element.data('dimensions', {
				width: element.width(),
				height: element.height(),
				parent: element.offsetParent()
			});
		}
	},
	centerVertically: function(element) {
		var top = (element.offsetParent().height() - element.height()) / 2;
		element.css("position","absolute");
		element.css("top", top + "px");
	},
	centerHorizontally: function(element) {
		var left = (element.offsetParent().width() - element.width()) / 2;
		element.css("position","absolute");
		element.css("left", left + "px");

	},
	center: function(element) {
		Slot.centerHorizontally(element);
		Slot.centerVertically(element);
	},
	alignLeftIndented: function(element) {
		//Slot.
	}
}
Selector = function() {
	var pub = {};

	var _original_dim = {
		"position": "absolute",
		"overflow": "hidden",
		"bottom": "0px",
		"right": "0px",
		"opacity": 0,
		"width": "0px",
		"height": "0px"
	}
	var _selector = $(DIV({"id": "selector"})).css(_original_dim);
	var _items = [];
	var _list = $(TABLE()).css({
		"position": "absolute"
	});
	_list.hide();
	var _index = 0;
	function selectSlide(i) {
		$(_items[_index]).removeClass("selected");
		_index = i;
		$(_items[_index]).addClass("selected");

		var pos = (_list.height() / _items.length) * -(_index + 1) + _selector.outerHeight() / 2;
		_list.css("top", pos);

	}
	pub.init = function() {
		$(".slide").each(function(i, e){
			var row = TR(TD({"class": "position"}, i + 1), TD($(e).attr("alt")));
			_list.append(row);
			_items.push(row);
		});
		_selector.append(_list);
		_selector.hide();
		$("body").append(_selector);
	}
	pub.show = function() {
		if (!pub.isVisible()) {
			var bottom = Slide.height() / 2 - Slide.height() / 4;
			var right = Slide.width() / 2 -  Slide.width() / 4;
			var width = Slide.width() / 2;
			console.log(width);
			var height = Slide.height() / 2;
			_list.find(".active").removeClass("active");
			$(_items[Presentation.getSlideIndex() - 1]).addClass("active");
			_selector.animate(
				{"bottom": bottom,
				"right": right,
				"opacity": 0.98,
				"width": width,
				"height": height}, 200, "swing", function() {
					selectSlide(Presentation.getSlideIndex() - 1);
					_list.show();
				});
			return true;
		}
		return false;
	}
	pub.hide = function() {
		_selector.animate(_original_dim, 200, "swing", function() {
			_list.hide();
			_selector.hide();
		});
	}
	pub.isVisible = function() {
		return _selector.is(":visible");
	}
	pub.previous = function() {
		pub.show();
		if (_index == 0) return;
		selectSlide(_index - 1);
	}
	pub.next = function() {
		pub.show();
		if (_index == _items.length - 1) return;
		selectSlide(_index + 1);
	}
	pub.confirm = function() {
		pub.hide();
		Presentation.showSlide(_index + 1);
	}
	return pub;
}();

$(function(){
	Presentation.init();
	Selector.init();
	$(window).keydown(function(event){
		switch(event.keyCode) {
		case 37: //Left
    case 33: //PgUp
			if (!Selector.isVisible()) Presentation.previousSlide();
			break;
		case 39: //Right
		case 32: //Space
    case 34: //PgDown
			if (!Selector.isVisible()) Presentation.nextSlide();
			break;
		case 38: //Up
			Selector.previous();
			break;
		case 40: //Down
			Selector.next();
			break;
		case 27: //ESC
			Selector.hide();
			break;
		case 13: //Enter
			if (Selector.isVisible()) Selector.confirm();
			break;
		case 49: //1
			Presentation.previousImage();
			break;
		case 50: //2
			Presentation.nextImage();
			break;
		}
		console.log(event.keyCode);
	});

	$(window).resize(function(event){
		Slide.layout();
		Selector.hide();
	});

	//Fancy Image Zooming
	$.fn.fancyzoom.defaultsOptions.imgDir='/images/fancyzoom/';
	$.fn.fancyzoom.defaultsOptions.showoverlay=true;
	$('a.zoom').fancyzoom();
});

<commit_msg>Don't let the user go to slides that don't exist e.g. 0 or n+1 (with n slides)<commit_after>DOMBuilder.apply(window);

Presentation = function() {
	var pub = {};
	var transition = {
		show: {
			effect: "slide",
			options: {},
			speed: "normal"
		},
		hide: {
			effect: "slide",
			options: {},
			speed: "normal"
		}
	}
	var _imageIndex = 0;
	var _images = [];
  var _items = [];
	var _slideIndex = null;
	var _pollLocationHash = function() {
		var index = pub.getSlideIndex();
		if (_slideIndex != index) {
			if (_slideIndex == null) {
				showSlide(index);
			} else {
				doTransition(_slideIndex, index);
			}
			//console.log("switching from slide #" + _slideIndex + " to #" + index);
			_slideIndex = index;
		}
	}
	function showSlide(index) {
		$(".slide[id='" + index + "']").fadeIn("normal");
		Slide.layout();
		$(".slide[id='" + index + "'] a.zoom").each(function(e){
			console.log(this);
			_images.push(this);
		});
		_imageIndex = 0;
	}
	function doTransition(from, to) {
		$(".slide[id='" + from + "']").fadeOut("normal", function() {showSlide(to)});
	}
	pub.getSlideIndex = function() {
		return parseInt(location.hash.substring(1)) || 1;
	}
	pub.init = function() {
		$(".slide").hide();
		$(".slide").each(function(i, e){
			var row = TR(TD({"class": "position"}, i + 1), TD($(e).attr("alt")));
			_items.push(row);
		});
		setInterval(_pollLocationHash, 200);
	}
	pub.showSlide = function(index) {
		location.hash = "#" + index;
	}
	pub.nextSlide = function() {
    if (_slideIndex == _items.length) return;
		pub.showSlide(_slideIndex + 1);
	}
	pub.previousSlide = function() {
    if (_slideIndex == 1) return;
		pub.showSlide(_slideIndex - 1)
	}
	pub.nextImage = function() {
		$(_images[_imageIndex]).trigger("click");
		_imageIndex++
	}
	pub.previousImage =  function() {
		$(_images[_imageIndex]).trigger("click")
		_imageIndex--
	}
	return pub;
}();

Slide = function() {
	var pub = {};
	pub.width = function() {
		//Try using slide-div-dimensions
		return $(window).width();
	}
	pub.height = function() {
		return $(window).height();
	}
	pub.layout = function() {
		//console.log("layout");
		var size = Slide.height() / 32;
	    $("body").css("font-size", size + 'px');
	    $(".slide").css("width", Slide.width() + 'px');
	    $(".slide").css("height", Slide.height() + 'px');
		$("#" + Presentation.getSlideIndex() + " .fit").each(function() {
			if (!$(this).data('dimensions')) {
				$(this).data('dimensions', {
					width: $(this).width(),
					height: $(this).height(),
					parent: $(this).offsetParent()
				});
			}
			var width = $(this).data('dimensions').width;
			var height = $(this).data('dimensions').height;

			var ratio = width/height;
			var parent = $(this).data('dimensions').parent;
			var new_width = 0;
			var new_height = 0;

			if (ratio < (parent.width() / parent.height())) {
				new_height = parent.height();
				new_width = new_height * ratio;
			} else {
				new_width = parent.width();
				new_height = new_width / ratio;
			}
			$(this).width(new_width);
			$(this).height(new_height);
		});

		//Align centered elements
		$(".center").each(function() {
			Slot.center($(this));
		});
		$(".center_v").each(function() {
			Slot.centerVertically($(this));
		});
		$(".center_h").each(function() {
			Slot.centerHorizontally($(this));
		});

	}
	return pub;
}();

var Slot = {
	init: function(element) {
		if (!element.data('dimensions')) {
			element.data('dimensions', {
				width: element.width(),
				height: element.height(),
				parent: element.offsetParent()
			});
		}
	},
	centerVertically: function(element) {
		var top = (element.offsetParent().height() - element.height()) / 2;
		element.css("position","absolute");
		element.css("top", top + "px");
	},
	centerHorizontally: function(element) {
		var left = (element.offsetParent().width() - element.width()) / 2;
		element.css("position","absolute");
		element.css("left", left + "px");

	},
	center: function(element) {
		Slot.centerHorizontally(element);
		Slot.centerVertically(element);
	},
	alignLeftIndented: function(element) {
		//Slot.
	}
}
Selector = function() {
	var pub = {};

	var _original_dim = {
		"position": "absolute",
		"overflow": "hidden",
		"bottom": "0px",
		"right": "0px",
		"opacity": 0,
		"width": "0px",
		"height": "0px"
	}
	var _selector = $(DIV({"id": "selector"})).css(_original_dim);
	var _items = [];
	var _list = $(TABLE()).css({
		"position": "absolute"
	});
	_list.hide();
	var _index = 0;
	function selectSlide(i) {
		$(_items[_index]).removeClass("selected");
		_index = i;
		$(_items[_index]).addClass("selected");

		var pos = (_list.height() / _items.length) * -(_index + 1) + _selector.outerHeight() / 2;
		_list.css("top", pos);

	}
	pub.init = function() {
		$(".slide").each(function(i, e){
			var row = TR(TD({"class": "position"}, i + 1), TD($(e).attr("alt")));
			_list.append(row);
			_items.push(row);
		});
		_selector.append(_list);
		_selector.hide();
		$("body").append(_selector);
	}
	pub.show = function() {
		if (!pub.isVisible()) {
			var bottom = Slide.height() / 2 - Slide.height() / 4;
			var right = Slide.width() / 2 -  Slide.width() / 4;
			var width = Slide.width() / 2;
			console.log(width);
			var height = Slide.height() / 2;
			_list.find(".active").removeClass("active");
			$(_items[Presentation.getSlideIndex() - 1]).addClass("active");
			_selector.animate(
				{"bottom": bottom,
				"right": right,
				"opacity": 0.98,
				"width": width,
				"height": height}, 200, "swing", function() {
					selectSlide(Presentation.getSlideIndex() - 1);
					_list.show();
				});
			return true;
		}
		return false;
	}
	pub.hide = function() {
		_selector.animate(_original_dim, 200, "swing", function() {
			_list.hide();
			_selector.hide();
		});
	}
	pub.isVisible = function() {
		return _selector.is(":visible");
	}
	pub.previous = function() {
		pub.show();
		if (_index == 0) return;
		selectSlide(_index - 1);
	}
	pub.next = function() {
		pub.show();
		if (_index == _items.length - 1) return;
		selectSlide(_index + 1);
	}
	pub.confirm = function() {
		pub.hide();
		Presentation.showSlide(_index + 1);
	}
	return pub;
}();

$(function(){
	Presentation.init();
	Selector.init();
	$(window).keydown(function(event){
		switch(event.keyCode) {
		case 37: //Left
    case 33: //PgUp
			if (!Selector.isVisible()) Presentation.previousSlide();
			break;
		case 39: //Right
		case 32: //Space
    case 34: //PgDown
			if (!Selector.isVisible()) Presentation.nextSlide();
			break;
		case 38: //Up
			Selector.previous();
			break;
		case 40: //Down
			Selector.next();
			break;
		case 27: //ESC
			Selector.hide();
			break;
		case 13: //Enter
			if (Selector.isVisible()) Selector.confirm();
			break;
		case 49: //1
			Presentation.previousImage();
			break;
		case 50: //2
			Presentation.nextImage();
			break;
		}
		console.log(event.keyCode);
	});

	$(window).resize(function(event){
		Slide.layout();
		Selector.hide();
	});

	//Fancy Image Zooming
	$.fn.fancyzoom.defaultsOptions.imgDir='/images/fancyzoom/';
	$.fn.fancyzoom.defaultsOptions.showoverlay=true;
	$('a.zoom').fancyzoom();
});

<|endoftext|>