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

  function Even(config) {
    this.config = config;
  }

  Even.prototype.setup = function() {
    var leancloud = this.config.leancloud;

    this.navbar();
    this.responsiveTable();

    if (this.config.toc) {
      this.scrollToc();
      this.tocFollow();
    }
    if (this.config.fancybox) {
      this.fancybox();
    }
    if (leancloud.app_id && leancloud.app_key) {
      this.recordReadings();
    }
    if(this.config.latex) {
      this.renderLaTeX();
    }
    this.backToTop();
  };

  Even.prototype.navbar = function () {
    var $nav = $('#mobile-navbar');
    var $navIcon = $('.mobile-navbar-icon');

    var slideout = new Slideout({
      'panel': document.getElementById('mobile-panel'),
      'menu': document.getElementById('mobile-menu'),
      'padding': 180,
      'tolerance': 70
    });
    slideout.disableTouch();

    $navIcon.click(function () {
      slideout.toggle();
    });

    slideout.on('beforeopen', function () {
      $nav.addClass('fixed-open');
      $navIcon.addClass('icon-click').removeClass('icon-out');
    });

    slideout.on('beforeclose', function () {
      $nav.removeClass('fixed-open');
      $navIcon.addClass('icon-out').removeClass('icon-click');
    });

    $('#mobile-panel').on('touchend', function () {
      slideout.isOpen() && $navIcon.click();
    });
  };

  Even.prototype.responsiveTable = function () {
    var tables = $('.post-content > table')
    tables.wrap('
')
  };

  Even.prototype.scrollToc = function () {
    var SPACING = 20;
    var $toc = $('.post-toc');
    var $footer = $('.post-footer');

    if ($toc.length) {
      var minScrollTop = $toc.offset().top - SPACING;
      $(window).scroll(function () {
        var tocState = {
          start: {
            'position': 'absolute',
            'top': minScrollTop
          },
          process: {
            'position': 'fixed',
            'top': SPACING
          }
        }
        var scrollTop = $(window).scrollTop();
        if (scrollTop < minScrollTop) {
          $toc.css(tocState.start);
        } else {
          $toc.css(tocState.process);

          if($('.toc-link.active').offset() != undefined && $('.toc-link.active').offset().top - document.documentElement.scrollTop > window.innerHeight*1/2){
            $('.post-toc').offset({top:Math.min($footer.offset().top - $toc.height()- SPACING,window.innerHeight*1/2 + document.documentElement.scrollTop - ($('.toc-link.active').offset().top - $('.post-toc').offset().top))});
          }
          if($footer.offset().top <$('.post-toc').offset().top + $toc.height() + SPACING){
            $('.post-toc').offset({top:$footer.offset().top- $toc.height()-SPACING});
          }
          //   $('.toc').offset({top:window.innerHeight/2 + document.documentElement.scrollTop - ($('.toc-link.active').offset().top - $('.toc').offset().top)});
        }
      })
    }
  };

  Even.prototype.tocFollow = function () {
    var HEADERFIX = 30;
    var $toclink = $('.toc-link'),
      $headerlink = $('.headerlink');

    $(window).scroll(function () {
      var headerlinkTop = $.map($headerlink, function (link) {
        return $(link).offset().top;
      });
      var scrollTop = $(window).scrollTop();

      for (var i = 0; i < $toclink.length; i++) {
        var isLastOne = i + 1 === $toclink.length,
          currentTop = headerlinkTop[i] - HEADERFIX,
          nextTop = isLastOne ? Infinity : headerlinkTop[i + 1] - HEADERFIX;

        if (currentTop < scrollTop && scrollTop <= nextTop) {
          $($toclink[i]).addClass('active');
        } else {
          $($toclink[i]).removeClass('active');
        }
      }
    });
  };

  Even.prototype.fancybox = function () {
    if ($.fancybox) {
      $('.post').each(function () {
        $(this).find('img').each(function () {
          var href = 'href="' + this.src + '"';
          var title = 'title="' + this.alt + '"';
          $(this).wrap('');
        });
      });

      $('.fancybox').fancybox({
        openEffect: 'elastic',
        closeEffect: 'elastic'
      });
    }
  };

  Even.prototype.recordReadings = function () {
    if (typeof AV !== 'object') return;

    var $visits = $('.post-visits');
    var Counter = AV.Object.extend('Counter');
    if ($visits.length === 1) {
      addCounter(Counter);
    } else {
      showTime(Counter);
    }

    function updateVisits(dom, time) {
      var readText = dom.text().replace(/(\d+)/i, time)
      dom.text(readText);
    }

    function addCounter(Counter) {
      var query = new AV.Query(Counter);

      var url = $visits.data('url').trim();
      var title = $visits.data('title').trim();

      query.equalTo('url', url);
      query.find().then(function (results) {
        if (results.length > 0) {
          var counter = results[0];
          counter.save(null, {
            fetchWhenSave: true
          }).then(function (counter) {
            counter.increment('time', 1);
            return counter.save();
          }).then(function (counter) {
            updateVisits($visits, counter.get('time'));
          });
        } else {
          var newcounter = new Counter();
          newcounter.set('title', title);
          newcounter.set('url', url);
          newcounter.set('time', 1);

          var acl = new AV.ACL();
          acl.setWriteAccess('*', true)
          acl.setReadAccess('*', true)
          newcounter.setACL(acl)

          newcounter.save().then(function () {
            updateVisits($visits, newcounter.get('time'));
          });
        }
      }, function (error) {
        // eslint-disable-next-line
        console.log('Error:' + error.code + ' ' + error.message);
      });
    }

    function showTime(Counter) {
      let index = 0;
      $visits.each(function () {
        var $this = $(this);
        setTimeout(
          function() {
            var query = new AV.Query(Counter);
            var url = $this.data('url').trim();

            query.equalTo('url', url);
            query.find().then(function (results) {
              if (results.length === 0) {
                updateVisits($this, 0);
              } else {
                var counter = results[0];
                updateVisits($this, counter.get('time'));
              }
            }, function (error) {
              // eslint-disable-next-line
              console.log('Error:' + error.code + ' ' + error.message);
            });
          }, 100*(index++));
      })
    }
  };

  Even.prototype.backToTop = function () {
    var $backToTop = $('#back-to-top');

    $(window).scroll(function () {
      if ($(window).scrollTop() > 100) {
        $backToTop.fadeIn(1000);
      } else {
        $backToTop.fadeOut(1000);
      }
    });

    $backToTop.click(function () {
      $('body,html').animate({ scrollTop: 0 });
    });
  };

  Even.prototype.renderLaTeX = function () {
    var loopID = setInterval(function () {
      if(window.MathJax) {
        var jax = window.MathJax;
        jax.Hub.Config({ tex2jax: { inlineMath: [['$', '$'], ['\\(', '\\)']] }});
        jax.Hub.Queue(['Typeset', jax.Hub, $(document.body)[0]]);
        clearInterval(loopID);
      }
    }, 500);
  }

  var config = window.config;
  var even = new Even(config);
  even.setup();
}(window))
<commit_msg>Update even.js<commit_after>(function (window) {
  'use strict';

  function Even(config) {
    this.config = config;
  }

  Even.prototype.setup = function() {
    var leancloud = this.config.leancloud;

    this.navbar();
    this.responsiveTable();

    if (this.config.toc) {
      this.scrollToc();
      this.tocFollow();
    }
    if (this.config.fancybox) {
      this.fancybox();
    }
    if (leancloud.app_id && leancloud.app_key) {
      this.recordReadings();
    }
    if(this.config.latex) {
      this.renderLaTeX();
    }
    this.backToTop();
  };

  Even.prototype.navbar = function () {
    var $nav = $('#mobile-navbar');
    var $navIcon = $('.mobile-navbar-icon');

    var slideout = new Slideout({
      'panel': document.getElementById('mobile-panel'),
      'menu': document.getElementById('mobile-menu'),
      'padding': 180,
      'tolerance': 70
    });
    slideout.disableTouch();

    $navIcon.click(function () {
      slideout.toggle();
    });

    slideout.on('beforeopen', function () {
      $nav.addClass('fixed-open');
      $navIcon.addClass('icon-click').removeClass('icon-out');
    });

    slideout.on('beforeclose', function () {
      $nav.removeClass('fixed-open');
      $navIcon.addClass('icon-out').removeClass('icon-click');
    });

    $('#mobile-panel').on('touchend', function () {
      slideout.isOpen() && $navIcon.click();
    });
  };

  Even.prototype.responsiveTable = function () {
    var tables = $('.post-content > table')
    tables.wrap('
')
  };

  Even.prototype.scrollToc = function () {
    var SPACING = 20;
    var $toc = $('.post-toc');
    var $footer = $('.post-footer');

    if ($toc.length) {
      var minScrollTop = $toc.offset().top - SPACING;
      $(window).scroll(function () {
        var tocState = {
          start: {
            'position': 'absolute',
            'top': minScrollTop
          },
          process: {
            'position': 'fixed',
            'top': SPACING
          }
        }
        var scrollTop = $(window).scrollTop();
        if (scrollTop < minScrollTop) {
          $toc.css(tocState.start);
        } else {
          $toc.css(tocState.process);

          var maxTocTop = $footer.offset().top - $toc.height() - SPACING;
          var tocCenterThreshold = document.documentElement.scrollTop + window.innerHeight / 2;
          if ($(".toc-link.active").offset() != undefined && $(".toc-link.active").offset().top > tocCenterThreshold) {
            var distanceBetween = $(".post-toc").offset().top - $(".toc-link.active").offset().top;
            $(".post-toc").offset({
                top: Math.min(maxTocTop, tocCenterThreshold + distanceBetween),
            });
          }
          if (maxTocTop < $(".post-toc").offset().top) {
            $(".post-toc").offset({ top: maxTocTop });
          }
        }
      })
    }
  };

  Even.prototype.tocFollow = function () {
    var HEADERFIX = 30;
    var $toclink = $('.toc-link'),
      $headerlink = $('.headerlink');

    $(window).scroll(function () {
      var headerlinkTop = $.map($headerlink, function (link) {
        return $(link).offset().top;
      });
      var scrollTop = $(window).scrollTop();

      for (var i = 0; i < $toclink.length; i++) {
        var isLastOne = i + 1 === $toclink.length,
          currentTop = headerlinkTop[i] - HEADERFIX,
          nextTop = isLastOne ? Infinity : headerlinkTop[i + 1] - HEADERFIX;

        if (currentTop < scrollTop && scrollTop <= nextTop) {
          $($toclink[i]).addClass('active');
        } else {
          $($toclink[i]).removeClass('active');
        }
      }
    });
  };

  Even.prototype.fancybox = function () {
    if ($.fancybox) {
      $('.post').each(function () {
        $(this).find('img').each(function () {
          var href = 'href="' + this.src + '"';
          var title = 'title="' + this.alt + '"';
          $(this).wrap('');
        });
      });

      $('.fancybox').fancybox({
        openEffect: 'elastic',
        closeEffect: 'elastic'
      });
    }
  };

  Even.prototype.recordReadings = function () {
    if (typeof AV !== 'object') return;

    var $visits = $('.post-visits');
    var Counter = AV.Object.extend('Counter');
    if ($visits.length === 1) {
      addCounter(Counter);
    } else {
      showTime(Counter);
    }

    function updateVisits(dom, time) {
      var readText = dom.text().replace(/(\d+)/i, time)
      dom.text(readText);
    }

    function addCounter(Counter) {
      var query = new AV.Query(Counter);

      var url = $visits.data('url').trim();
      var title = $visits.data('title').trim();

      query.equalTo('url', url);
      query.find().then(function (results) {
        if (results.length > 0) {
          var counter = results[0];
          counter.save(null, {
            fetchWhenSave: true
          }).then(function (counter) {
            counter.increment('time', 1);
            return counter.save();
          }).then(function (counter) {
            updateVisits($visits, counter.get('time'));
          });
        } else {
          var newcounter = new Counter();
          newcounter.set('title', title);
          newcounter.set('url', url);
          newcounter.set('time', 1);

          var acl = new AV.ACL();
          acl.setWriteAccess('*', true)
          acl.setReadAccess('*', true)
          newcounter.setACL(acl)

          newcounter.save().then(function () {
            updateVisits($visits, newcounter.get('time'));
          });
        }
      }, function (error) {
        // eslint-disable-next-line
        console.log('Error:' + error.code + ' ' + error.message);
      });
    }

    function showTime(Counter) {
      let index = 0;
      $visits.each(function () {
        var $this = $(this);
        setTimeout(
          function() {
            var query = new AV.Query(Counter);
            var url = $this.data('url').trim();

            query.equalTo('url', url);
            query.find().then(function (results) {
              if (results.length === 0) {
                updateVisits($this, 0);
              } else {
                var counter = results[0];
                updateVisits($this, counter.get('time'));
              }
            }, function (error) {
              // eslint-disable-next-line
              console.log('Error:' + error.code + ' ' + error.message);
            });
          }, 100*(index++));
      })
    }
  };

  Even.prototype.backToTop = function () {
    var $backToTop = $('#back-to-top');

    $(window).scroll(function () {
      if ($(window).scrollTop() > 100) {
        $backToTop.fadeIn(1000);
      } else {
        $backToTop.fadeOut(1000);
      }
    });

    $backToTop.click(function () {
      $('body,html').animate({ scrollTop: 0 });
    });
  };

  Even.prototype.renderLaTeX = function () {
    var loopID = setInterval(function () {
      if(window.MathJax) {
        var jax = window.MathJax;
        jax.Hub.Config({ tex2jax: { inlineMath: [['$', '$'], ['\\(', '\\)']] }});
        jax.Hub.Queue(['Typeset', jax.Hub, $(document.body)[0]]);
        clearInterval(loopID);
      }
    }, 500);
  }

  var config = window.config;
  var even = new Even(config);
  even.setup();
}(window))
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * Owner: mark@famo.us
 * @license MPL 2.0
 * @copyright Famous Industries, Inc. 2014
 */

define(function(require, exports, module) {
    var Surface = require('famous/core/Surface');

    /**
     * A Famo.us surface in the form of an HTML input element.
     *   This extends the Surface class.
     *
     * @class InputSurface
     * @extends Surface
     * @constructor
     * @param {Object} [options] overrides of default options
     * @param {string} [options.placeholder] placeholder text hint that describes the expected value of an <input> element
     * @param {string} [options.type] specifies the type of element to display (e.g. 'datetime', 'text', 'button', etc.)
     * @param {string} [options.value] value of text
     */
    function InputSurface(options) {
        this._placeholder = options.placeholder || '';
        this._value       = options.value || '';
        this._type        = options.type || 'text';
        this._name        = options.name || '';

        Surface.apply(this, arguments);
        this.on('click', this.focus.bind(this));
    }
    InputSurface.prototype = Object.create(Surface.prototype);
    InputSurface.prototype.constructor = InputSurface;

    InputSurface.prototype.elementType = 'input';
    InputSurface.prototype.elementClass = 'famous-surface';

    /**
     * Set placeholder text.  Note: Triggers a repaint.
     *
     * @method setPlaceholder
     * @param {string} str Value to set the placeholder to.
     * @return {InputSurface} this, allowing method chaining.
     */
    InputSurface.prototype.setPlaceholder = function setPlaceholder(str) {
        this._placeholder = str;
        this._contentDirty = true;
        return this;
    };

    /**
     * Focus on the current input, pulling up the keyboard on mobile.
     *
     * @method focus
     * @return {InputSurface} this, allowing method chaining.
     */
    InputSurface.prototype.focus = function focus() {
        if (this._currTarget) this._currTarget.focus();
        return this;
    };

    /**
     * Blur the current input, hiding the keyboard on mobile.
     *
     * @method blur
     * @return {InputSurface} this, allowing method chaining.
     */
    InputSurface.prototype.blur = function blur() {
        if (this._currTarget) this._currTarget.blur();
        return this;
    };

    /**
     * Set the placeholder conent.
     *   Note: Triggers a repaint next tick.
     *
     * @method setValue
     * @param {string} str Value to set the main input value to.
     * @return {InputSurface} this, allowing method chaining.
     */
    InputSurface.prototype.setValue = function setValue(str) {
        this._value = str;
        this._contentDirty = true;
        return this;
    };

    /**
     * Set the type of element to display conent.
     *   Note: Triggers a repaint next tick.
     *
     * @method setType
     * @param {string} str type of the input surface (e.g. 'button', 'text')
     * @return {InputSurface} this, allowing method chaining.
     */
    InputSurface.prototype.setType = function setType(str) {
        this._type = str;
        this._contentDirty = true;
        return this;
    };

    /**
     * Get the value of the inner content of the element (e.g. the entered text)
     *
     * @method getValue
     * @return {string} value of element
     */
    InputSurface.prototype.getValue = function getValue() {
        if (this._currTarget) {
            return this._currTarget.value;
        }
        else {
            return this._value;
        }
    };

    /**
     * Set the name attribute of the element.
     *   Note: Triggers a repaint next tick.
     *
     * @method setName
     * @param {string} str element name
     * @return {InputSurface} this, allowing method chaining.
     */
    InputSurface.prototype.setName = function setName(str) {
        this._name = str;
        this._contentDirty = true;
        return this;
    };

    /**
     * Get the name attribute of the element.
     *
     * @method getName
     * @return {string} name of element
     */
    InputSurface.prototype.getName = function getName() {
        return this._name;
    };

    /**
     * Place the document element this component manages into the document.
     *
     * @private
     * @method deploy
     * @param {Node} target document parent of this container
     */
    InputSurface.prototype.deploy = function deploy(target) {
        if (this._placeholder !== '') target.placeholder = this._placeholder;
        target.value = this._value;
        target.type = this._type;
        target.name = this._name;
    };

    module.exports = InputSurface;
});
<commit_msg>Fix InputSurface blur event firing<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * Owner: mark@famo.us
 * @license MPL 2.0
 * @copyright Famous Industries, Inc. 2014
 */

define(function(require, exports, module) {
    var Surface = require('famous/core/Surface');

    /**
     * A Famo.us surface in the form of an HTML input element.
     *   This extends the Surface class.
     *
     * @class InputSurface
     * @extends Surface
     * @constructor
     * @param {Object} [options] overrides of default options
     * @param {string} [options.placeholder] placeholder text hint that describes the expected value of an <input> element
     * @param {string} [options.type] specifies the type of element to display (e.g. 'datetime', 'text', 'button', etc.)
     * @param {string} [options.value] value of text
     */
    function InputSurface(options) {
        this._placeholder = options.placeholder || '';
        this._value       = options.value || '';
        this._type        = options.type || 'text';
        this._name        = options.name || '';

        Surface.apply(this, arguments);

        this.on('click', this.focus.bind(this));
        window.addEventListener('click', function(event){
            if (event.target !== this._currTarget) this.blur();
        }.bind(this));
    }
    InputSurface.prototype = Object.create(Surface.prototype);
    InputSurface.prototype.constructor = InputSurface;

    InputSurface.prototype.elementType = 'input';
    InputSurface.prototype.elementClass = 'famous-surface';

    /**
     * Set placeholder text.  Note: Triggers a repaint.
     *
     * @method setPlaceholder
     * @param {string} str Value to set the placeholder to.
     * @return {InputSurface} this, allowing method chaining.
     */
    InputSurface.prototype.setPlaceholder = function setPlaceholder(str) {
        this._placeholder = str;
        this._contentDirty = true;
        return this;
    };

    /**
     * Focus on the current input, pulling up the keyboard on mobile.
     *
     * @method focus
     * @return {InputSurface} this, allowing method chaining.
     */
    InputSurface.prototype.focus = function focus() {
        if (this._currTarget) this._currTarget.focus();
        return this;
    };

    /**
     * Blur the current input, hiding the keyboard on mobile.
     *
     * @method blur
     * @return {InputSurface} this, allowing method chaining.
     */
    InputSurface.prototype.blur = function blur() {
        if (this._currTarget) this._currTarget.blur();
        return this;
    };

    /**
     * Set the placeholder conent.
     *   Note: Triggers a repaint next tick.
     *
     * @method setValue
     * @param {string} str Value to set the main input value to.
     * @return {InputSurface} this, allowing method chaining.
     */
    InputSurface.prototype.setValue = function setValue(str) {
        this._value = str;
        this._contentDirty = true;
        return this;
    };

    /**
     * Set the type of element to display conent.
     *   Note: Triggers a repaint next tick.
     *
     * @method setType
     * @param {string} str type of the input surface (e.g. 'button', 'text')
     * @return {InputSurface} this, allowing method chaining.
     */
    InputSurface.prototype.setType = function setType(str) {
        this._type = str;
        this._contentDirty = true;
        return this;
    };

    /**
     * Get the value of the inner content of the element (e.g. the entered text)
     *
     * @method getValue
     * @return {string} value of element
     */
    InputSurface.prototype.getValue = function getValue() {
        if (this._currTarget) {
            return this._currTarget.value;
        }
        else {
            return this._value;
        }
    };

    /**
     * Set the name attribute of the element.
     *   Note: Triggers a repaint next tick.
     *
     * @method setName
     * @param {string} str element name
     * @return {InputSurface} this, allowing method chaining.
     */
    InputSurface.prototype.setName = function setName(str) {
        this._name = str;
        this._contentDirty = true;
        return this;
    };

    /**
     * Get the name attribute of the element.
     *
     * @method getName
     * @return {string} name of element
     */
    InputSurface.prototype.getName = function getName() {
        return this._name;
    };

    /**
     * Place the document element this component manages into the document.
     *
     * @private
     * @method deploy
     * @param {Node} target document parent of this container
     */
    InputSurface.prototype.deploy = function deploy(target) {
        if (this._placeholder !== '') target.placeholder = this._placeholder;
        target.value = this._value;
        target.type = this._type;
        target.name = this._name;
    };

    module.exports = InputSurface;
});
<|endoftext|>


<commit_before>// @flow

import type { Children } from 'react';
import type { Animation } from 'yubaba-core';

import React from 'react';
import { orchestrator, removeFromStore, addListener } from 'yubaba-core';

export default class Animate extends React.Component {
  _node: HTMLElement;
  _detatch: Function;

  props: {
    pair: string,
    children?: Children,
    animations: Array<Animation>,
    style?: {
      [string]: any,
    },
  };

  state = {
    visible: false,
  };

  componentDidMount () {
    this._detatch = addListener(this.props.pair, this.setVisibility);
    this.initialise();
  }

  componentWillUnmount () {
    this._detatch();
    this.initialise();

    if (this._node.firstElementChild) {
      removeFromStore(this.props.pair, this._node.firstElementChild, true);
    }
  }

  setVisibility = (visible: boolean) => {
    this.setState({
      visible,
    });
  };

  setDOMNode (node: HTMLElement) {
    this._node = node;
  }

  initialise () {
    if (!this._node.firstElementChild) {
      return;
    }

    orchestrator(this.props.pair, {
      node: this._node.firstElementChild,
      animations: this.props.animations,
      shouldShow: this.setVisibility,
    });
  }

  render () {
    const { pair, animations, style, ...props } = this.props;

    return (
      <div
        {...props}
        ref={this.setDOMNode}
        style={{ ...style, opacity: this.state.visible ? 1 : 0 }}
      >
        {this.props.children}
      </div>
    );
  }
}
<commit_msg>chore(bind): fixes method bind<commit_after>// @flow

import type { Children } from 'react';
import type { Animation } from 'yubaba-core';

import React from 'react';
import { orchestrator, removeFromStore, addListener } from 'yubaba-core';

export default class Animate extends React.Component {
  _node: HTMLElement;
  _detatch: Function;

  props: {
    pair: string,
    children?: Children,
    animations: Array<Animation>,
    style?: {
      [string]: any,
    },
  };

  state = {
    visible: false,
  };

  componentDidMount () {
    this._detatch = addListener(this.props.pair, this.setVisibility);
    this.initialise();
  }

  componentWillUnmount () {
    this._detatch();
    this.initialise();

    if (this._node.firstElementChild) {
      removeFromStore(this.props.pair, this._node.firstElementChild, true);
    }
  }

  setVisibility = (visible: boolean) => {
    this.setState({
      visible,
    });
  };

  setDOMNode = (node: HTMLElement) => {
    this._node = node;
  };

  initialise () {
    if (!this._node.firstElementChild) {
      return;
    }

    orchestrator(this.props.pair, {
      node: this._node.firstElementChild,
      animations: this.props.animations,
      shouldShow: this.setVisibility,
    });
  }

  render () {
    const { pair, animations, style, ...props } = this.props;

    return (
      <div
        {...props}
        ref={this.setDOMNode}
        style={{ ...style, opacity: this.state.visible ? 1 : 0 }}
      >
        {this.props.children}
      </div>
    );
  }
}
<|endoftext|>


<commit_before>var nodeio = require('node.io')
var Job = {}

Job.name = "Google Nexus 4 Availability"
Job.msg = 'fetching from Play Store ...'
Job.enabled = true
Job.status = 'building'
Job.interval = 1000*60*5
Job.timestamp = ''
Job.func = function( callback ) {
	var job  = new nodeio.Job({
		input:	false,
		run:	function(){
			this.getHtml(
				'https://play.google.com/store/devices/details?id=nexus_4_16gb',
				function( err, $ ) {
					if(err) {
						callback(err, null)
					} else {
						var t = $('span.hardware-price-description').fulltext
						callback( null, {
							msg: t,
							status: 'success',
							timestamp: new Date()
						})
					}
				}
			)
		}
	})

	nodeio.start( job, { silent: true })
}
module.exports = Job

<commit_msg>Add comments<commit_after>var nodeio = require('node.io')
var Job = {}

Job.name = "Google Nexus 4 Availability"
Job.msg = 'fetching from Play Store ...'
Job.enabled = true
Job.status = 'building'
Job.interval = 1000*60*5
Job.timestamp = ''
Job.func = function( callback ) {
	var job  = new nodeio.Job({
		input:	false,
		run:	function(){
			this.getHtml(
				'https://play.google.com/store/devices/details?id=nexus_4_16gb',
				function( err, $ ) {
					if(err) {
						callback(err, null)
					} else {
						// this is fragile, because when it is available, this span doesn't exist!
						var t = $('span.hardware-price-description').fulltext
						callback( null, {
							msg: t,
							status: 'success',
							timestamp: new Date()
						})
					}
				}
			)
		}
	})

	nodeio.start( job, { silent: true })
}
module.exports = Job

<|endoftext|>


<commit_before>/*!
 * jQuery ajaxProgress Plugin v0.5.0
 * Requires jQuery v1.5.0 or later
 *
 * http://www.kpozin.net/ajaxprogress
 *
 * (c) 2011, Konstantin Pozin
 * Licensed under MIT license.
 */
(function($) {

    // Test whether onprogress is supported
    var support = $.support.ajaxProgress = ("onprogress" in (new $.ajaxSettings.xhr()));

    // If it's not supported, we can't do anything
    if (!support) {
        return;
    }

    var NAMESPACE = ".ajaxprogress";

    // Create global "ajaxProgress" event
    $.fn.ajaxProgress = function (f) {
        return this.bind("ajaxProgress", f);
    };

    // Hold on to a reference to the jqXHR object so that we can pass it to the progress callback.
    // Namespacing the handler with ".ajaxprogress"
    $("html").bind("ajaxSend" + NAMESPACE, function(event, jqXHR, ajaxOptions) {
        ajaxOptions.__jqXHR = jqXHR;
    });

    /**
     * @param {XMLHttpRequestProgressEvent} evt
     * @param {Object} options jQuery AJAX options
     */
    function handleOnProgress(evt, options) {

        // Trigger the global event.
        // function handler(jqEvent, progressEvent, jqXHR) {}
        if (options.global) {
            $.event.trigger("ajaxProgress", [evt, options.__jqXHR]);
        }

        // Trigger the local event.
        // function handler(jqXHR, progressEvent)
        if (typeof options.progress === "function") {
            options.progress(options.__jqXHR, evt);
        }
    }

    // We'll work with the original factory method just in case
    var makeOriginalXhr = $.ajaxSettings.xhr.bind($.ajaxSettings);

    // Options to be passed into $.ajaxSetup;
    var newOptions = {};

    // Wrap the XMLHttpRequest factory method
    newOptions.xhr = function () {

        // Reference to the extended options object
        var s = this;

        var newXhr = makeOriginalXhr();
        if (newXhr) {
            newXhr.addEventListener("progress", function(evt) {
                handleOnProgress(evt, s);
            });
        }
        return newXhr;
    };

    $.ajaxSetup(newOptions);

})(jQuery);<commit_msg>Removed redundant "new".<commit_after>/*!
 * jQuery ajaxProgress Plugin v0.5.0
 * Requires jQuery v1.5.0 or later
 *
 * http://www.kpozin.net/ajaxprogress
 *
 * (c) 2011, Konstantin Pozin
 * Licensed under MIT license.
 */
(function($) {

    // Test whether onprogress is supported
    var support = $.support.ajaxProgress = ("onprogress" in $.ajaxSettings.xhr());

    // If it's not supported, we can't do anything
    if (!support) {
        return;
    }

    var NAMESPACE = ".ajaxprogress";

    // Create global "ajaxProgress" event
    $.fn.ajaxProgress = function (f) {
        return this.bind("ajaxProgress", f);
    };

    // Hold on to a reference to the jqXHR object so that we can pass it to the progress callback.
    // Namespacing the handler with ".ajaxprogress"
    $("html").bind("ajaxSend" + NAMESPACE, function(event, jqXHR, ajaxOptions) {
        ajaxOptions.__jqXHR = jqXHR;
    });

    /**
     * @param {XMLHttpRequestProgressEvent} evt
     * @param {Object} options jQuery AJAX options
     */
    function handleOnProgress(evt, options) {

        // Trigger the global event.
        // function handler(jqEvent, progressEvent, jqXHR) {}
        if (options.global) {
            $.event.trigger("ajaxProgress", [evt, options.__jqXHR]);
        }

        // Trigger the local event.
        // function handler(jqXHR, progressEvent)
        if (typeof options.progress === "function") {
            options.progress(options.__jqXHR, evt);
        }
    }

    // We'll work with the original factory method just in case
    var makeOriginalXhr = $.ajaxSettings.xhr.bind($.ajaxSettings);

    // Options to be passed into $.ajaxSetup;
    var newOptions = {};

    // Wrap the XMLHttpRequest factory method
    newOptions.xhr = function () {

        // Reference to the extended options object
        var s = this;

        var newXhr = makeOriginalXhr();
        if (newXhr) {
            newXhr.addEventListener("progress", function(evt) {
                handleOnProgress(evt, s);
            });
        }
        return newXhr;
    };

    $.ajaxSetup(newOptions);

})(jQuery);<|endoftext|>


<commit_before>/**
 *  Autocomplete for jQuery, version 1.10.X
 *  (c) 2013 Lloyd Watkin
 *
 * Heavily modified from http://www.devbridge.com/projects/autocomplete/jquery/
 */
(function($) {

  function Autocomplete(el, options) {
    this.regEx = new RegExp(
      '(\\' + ['/', '.', '*', '+', '?', '|', '(', ')', '[', ']', '{', '}', '\\']
          .join('|\\') + ')',
      'g'
  )
    this.el = $(el)
    this.el.attr('autocomplete', 'off')
    this.suggestions = []
    this.data = []
    this.badQueries = []
    this.selectedIndex = -1
    this.currentValue = this.isFormField() ? this.el.val() : this.el.html()
    this.intervalId = 0
    this.cachedResponse = []
    this.onChangeInterval = null
    this.ignoreValueChange = false
    this.serviceUrl = options.serviceUrl
    this.isLocal = false
    this.options = {
      autoSubmit: false,
      minChars: 1,
      maxHeight: 300,
      deferRequestBy: 0,
      width: 300,
      highlight: true,
      params: {},
      dataKey: null,
      formatResult: this.formatResult,
      delimiter: ' ',
      zIndex: 9999,
      searchPrefix: '',
      searchEverywhere: false,
      appendChars: ' ',
      insertDomContent: this.insertDomContent
    }
    this.initialize()
    this.setOptions(options)
    return this
  }

  $.fn.autocomplete = function(options) {
    return new Autocomplete(this.get(0) || $('<input />'), options)
  }

  Autocomplete.prototype = {

    killerFn: null,

    initialize: function() {

      var self = this
      var uid = Math.floor(Math.random() * 0x100000).toString(16)
      var autocompleteElementId = 'Autocomplete_' + uid

      this.killerFn = function(e) {
        if (0 === $(e.target).parents('.autocomplete').size()) {
          self.killSuggestions()
          self.disableKillerFn()
        }
      }

      if (!this.options.width) this.options.width = this.el.width()
      this.mainContainerId = 'AutocompleteContainer_' + uid

      $('
' +
        '

')
        .appendTo('body')

      this.container = $('#' + autocompleteElementId)
      this.fixPosition()
      if (window.opera)
        this.el.keypress(function(e) { self.onKeyPress(e) })
      else
        this.el.keydown(function(e) { self.onKeyPress(e) })

      this.el.keyup(function(e) { self.onKeyUp(e) })
      this.el.blur(function() { self.enableKillerFn() })
      this.el.focus(function() { self.fixPosition() })
    },

    template: function(suggestion, data) {
      return this.options.formatResult(suggestion, data, this)
    },

    setOptions: function(options) {
      var o = this.options
      $.extend(o, options)

      if (o.lookup) this.setLookup(o.lookup)
      $('#' + this.mainContainerId).css({ zIndex: o.zIndex })
      this.container.css({ maxHeight: o.maxHeight + 'px', width: o.width })
    },

    setLookup: function(lookup) {
        this.isLocal = true
        if ($.isArray(lookup) || $.isObject(lookup))
            this.options.lookup = { suggestions: lookup, data: [] }
    },

    clearCache: function() {
      this.cachedResponse = []
      this.badQueries = []
    },

    disable: function() {
      this.disabled = true
    },

    enable: function() {
      this.disabled = false
    },

    fixPosition: function() {
      var offset = this.el.offset()
      $('#' + this.mainContainerId).css({
          top: (offset.top + this.el.innerHeight()) + 'px',
          left: offset.left + 'px'
      })
    },

    enableKillerFn: function() {
      var self = this
      $(document).bind('click', self.killerFn)
    },

    disableKillerFn: function() {
      var self = this
      $(document).unbind('click', self.killerFn)
    },

    killSuggestions: function() {
      var self = this
      this.stopKillSuggestions()
      this.intervalId = window.setInterval(function() {
          self.hide()
          self.stopKillSuggestions()
      }, 300)
    },

    stopKillSuggestions: function() {
      window.clearInterval(this.intervalId)
    },

    onKeyPress: function(e) {
      if (this.disabled || !this.enabled) return

      switch (e.keyCode) {
        case 27: // ESC:
          this.el.val(this.currentValue)
          this.hide()
          break
        case 9:  // TAB
        case 13: // RETURN:
          if (-1 === this.selectedIndex)
            return this.hide()
          this.select(this.selectedIndex)
          if (9 === e.keyCode) return
          break
        case 38: // UP:
          this.moveUp()
          break
        case 40: // DOWN:
          this.moveDown()
          break
        default:
          return
      }
      e.stopImmediatePropagation()
      e.preventDefault()
    },

    onKeyUp: function(e) {
      if (this.disabled) return
      switch (e.keyCode) {
        case 38: // UP:
        case 40: // DOWN:
          return
      }
      clearInterval(this.onChangeInterval)
      var self = this
      var value = this.isFormField() ? this.el.val() : this.el.html()
      if (this.currentValue !== value) {
        if (this.options.deferRequestBy > 0)
          this.onChangeInterval = setInterval(
              function() { self.onValueChange() },
              this.options.deferRequestBy
          )
        else
          this.onValueChange()
      }
    },

    onValueChange: function() {
      clearInterval(this.onChangeInterval)
      this.currentValue = this.isFormField() ? this.el.val() : this.el.html()
      var q = this.getQuery(this.currentValue)
      this.selectedIndex = -1
      if (this.ignoreValueChange) {
        this.ignoreValueChange = false
        return
      }
      if (('' === q) || (q.length < this.options.minChars))
        this.hide()
      else
        this.getSuggestions(q)
    },

    getQuery: function(val) {
      var prefixLength = this.options.searchPrefix.length
      var d = this.options.delimiter
      if (!d) { return $.trim(val) }
      var arr = val.split(d)
      var query = $.trim(arr[arr.length - 1])
      if (query.substring(0, prefixLength) == this.options.searchPrefix)
         return query.substring(this.options.searchPrefix.length)
      return ''
    },

    getSuggestionsLocal: function(q) {
      var arr = this.options.lookup.suggestions
      var ret = { suggestions: [], data: [] }
      q       = q.toLowerCase()

      for (var index in arr) {
        var val = arr[index]
        if ('object' === typeof(val))
          val = val[this.options.searchKey]
        var indexPosition = (val  + ' ' + arr[index][this.options.dataKey])
            .toLowerCase().indexOf(q)
        var addData = false
        if ((true === this.options.searchEverywhere) && (indexPosition > -1))
          addData = true
        else if (0 === indexPosition)
          addData = true
        if (true === addData) {
          ret.suggestions.push(val)
          ret.data.push(arr[index])
        }
      }
      return ret
    },

    getSuggestions: function(q) {
      var self = this
      var cached = this.isLocal ? this.getSuggestionsLocal(q) : this.cachedResponse[q]
      if (cached && ($.isArray(cached.suggestions) || $.isObject(cached.suggestions))) {
        this.suggestions = cached.suggestions
        this.data = cached.data
        this.suggest()
      } else if (!this.isBadQuery(q)) {
        this.options.params.query = q
        $.get(this.serviceUrl, this.options.params, function(txt) {
            self.processResponse(txt)
        }, 'text')
      }
    },

    isBadQuery: function(q) {
      var i = this.badQueries.length
      while (i--) {
        if (0 === q.indexOf(this.badQueries[i])) return true
      }
      return false
    },

    hide: function() {
      this.enabled = false
      this.selectedIndex = -1
      this.container.hide()
    },

    suggest: function() {
      if (0 === this.suggestions.length)
        return this.hide()
      this.fixPosition()
      var div, s
      var self = this
      var len = this.suggestions.length
      var v = this.getQuery(this.currentValue)
      var mOver = function(xi) { return function() { self.activate(xi) } }
      var mClick = function(xi) { return function() { self.select(xi) } }
      this.container.hide().empty()
      for (var i = 0; i < len; i++) {
        s = this.suggestions[i]
        if ((typeof(entry) === 'object') &&
            (typeof(this.options.dataKey) !== 'undefined'))
            s = this.data[i][this.options.dataKey]
        div = $((self.selectedIndex === i ?
            '<div class="selected"' : '
' +
            this.template(v, this.data[i]) + '
'
        )
        div.mouseover(mOver(i))
        div.click(mClick(i))
        this.container.append(div)
      }
      this.enabled = true
      this.container.show()
    },

    processResponse: function(text) {
      var response
      try {
        response = JSON.parse(text)
      } catch (err) {
        return
      }
      if (!$.isArray(response.data)) response.data = []
      if (!this.options.noCache) {
        this.cachedResponse[response.query] = response
        if (0 === response.suggestions.length)
            this.badQueries.push(response.query)
      }
      if (response.query === this.getQuery(this.currentValue)) {
        this.suggestions = response.suggestions
        this.data = response.data
        this.suggest()
      }
    },

    activate: function(index) {
      var divs = this.container.children()
      // Clear previous selection:
      if ((-1 !== this.selectedIndex) && (divs.length > this.selectedIndex))
        $(divs.get(this.selectedIndex)).removeClass()

      this.selectedIndex = index
      var activeItem
      if ((-1 !== this.selectedIndex) && (divs.length > this.selectedIndex)) {
        activeItem = divs.get(this.selectedIndex)
        $(activeItem).addClass('selected')
      }
      return activeItem
    },

    deactivate: function(div, index) {
      div.className = ''
      if (this.selectedIndex === index) { this.selectedIndex = -1 }
    },

    select: function(i) {
      var selectedValue = this.suggestions[i]
      if (!selectedValue) return
      this.el.val(selectedValue)
      if (this.options.autoSubmit) {
        var f = this.el.parents('form')
        if (f.length > 0) { f.get(0).submit() }
      }
      this.ignoreValueChange = true
      this.hide()
      this.onSelect(i)
    },

    moveUp: function() {
      if (-1 === this.selectedIndex) return
      if (0 === this.selectedIndex) {
        this.container.children().get(0).className = ''
        this.selectedIndex = -1
        this.el.val(this.currentValue)
        return
      }
      this.adjustScroll(this.selectedIndex - 1)
    },

    moveDown: function() {
      if (this.selectedIndex === (this.suggestions.length - 1)) return
      this.adjustScroll(this.selectedIndex + 1)
    },

    adjustScroll: function(i) {
      var activeItem = this.activate(i)
      var offsetTop = activeItem.offsetTop
      var upperBound = this.container.scrollTop()
      var lowerBound = upperBound + this.options.maxHeight - 25
      if (offsetTop < upperBound)
        this.container.scrollTop(offsetTop)
      else if (offsetTop > lowerBound)
        this.container.scrollTop(offsetTop - this.options.maxHeight + 25)
      this.el.val(this.getValue(this.options.searchPrefix + this.suggestions[i]))
    },

    onSelect: function(i) {
      var self = this
      var fn   = this.options.onSelect
      var s    = this.suggestions[i]
      var d    = this.data[i]
      var val  = this.options.insertDomContent(d, s, this)
      if (this.isFormField())
          this.el.val(val)
      else
          this.el.html(val)

      if ($.isFunction(fn)) { fn(s, d, self.el) }
    },

    insertDomContent: function(data, suggestion, context) {
      var val = context.getValue(suggestion)
      if ('object' === typeof(data))
        val = context.getValue(data[context.options.dataKey])
      if (context.options.appendChars) val = val + context.options.appendChars
      return val
    },

    isFormField: function() {
        return this.el.is('input') || this.el.is('textarea')
    },

    getValue: function(value) {
        var del = this.options.delimiter
        if (!del) return value
        var currVal = this.currentValue
        var arr = currVal.split(del)
        if (1 === arr.length) return value
        var response = currVal.substr(0, currVal.length - arr[arr.length - 1].length)
        return response + value
    },

    /**
     * value: Data entered to autocomplete
     * data: Matching data
     */
    formatResult: function(value, data) {
      if (this.dataKey) data = data[this.dataKey]
      var pattern = '(' + value.replace(this.regEx, '\\$1') + ')'
      return data.replace(new RegExp(pattern, 'gi'), '$1<\/strong>')
    },

    remove: function() {
        $('#' + this.mainContainerId).remove()
    },
  }

})(jQuery)
<commit_msg>Refocus the textarea after selecting value<commit_after>/**
 *  Autocomplete for jQuery, version 1.10.X
 *  (c) 2013 Lloyd Watkin
 *
 * Heavily modified from http://www.devbridge.com/projects/autocomplete/jquery/
 */
(function($) {

  function Autocomplete(el, options) {
    this.regEx = new RegExp(
      '(\\' + ['/', '.', '*', '+', '?', '|', '(', ')', '[', ']', '{', '}', '\\']
          .join('|\\') + ')',
      'g'
  )
    this.el = $(el)
    this.el.attr('autocomplete', 'off')
    this.suggestions = []
    this.data = []
    this.badQueries = []
    this.selectedIndex = -1
    this.currentValue = this.isFormField() ? this.el.val() : this.el.html()
    this.intervalId = 0
    this.cachedResponse = []
    this.onChangeInterval = null
    this.ignoreValueChange = false
    this.serviceUrl = options.serviceUrl
    this.isLocal = false
    this.options = {
      autoSubmit: false,
      minChars: 1,
      maxHeight: 300,
      deferRequestBy: 0,
      width: 300,
      highlight: true,
      params: {},
      dataKey: null,
      formatResult: this.formatResult,
      delimiter: ' ',
      zIndex: 9999,
      searchPrefix: '',
      searchEverywhere: false,
      appendChars: ' ',
      insertDomContent: this.insertDomContent
    }
    this.initialize()
    this.setOptions(options)
    return this
  }

  $.fn.autocomplete = function(options) {
    return new Autocomplete(this.get(0) || $('<input />'), options)
  }

  Autocomplete.prototype = {

    killerFn: null,

    initialize: function() {

      var self = this
      var uid = Math.floor(Math.random() * 0x100000).toString(16)
      var autocompleteElementId = 'Autocomplete_' + uid

      this.killerFn = function(e) {
        if (0 === $(e.target).parents('.autocomplete').size()) {
          self.killSuggestions()
          self.disableKillerFn()
        }
      }

      if (!this.options.width) this.options.width = this.el.width()
      this.mainContainerId = 'AutocompleteContainer_' + uid

      $('
' +
        '

')
        .appendTo('body')

      this.container = $('#' + autocompleteElementId)
      this.fixPosition()
      if (window.opera)
        this.el.keypress(function(e) { self.onKeyPress(e) })
      else
        this.el.keydown(function(e) { self.onKeyPress(e) })

      this.el.keyup(function(e) { self.onKeyUp(e) })
      this.el.blur(function() { self.enableKillerFn() })
      this.el.focus(function() { self.fixPosition() })
    },

    template: function(suggestion, data) {
      return this.options.formatResult(suggestion, data, this)
    },

    setOptions: function(options) {
      var o = this.options
      $.extend(o, options)

      if (o.lookup) this.setLookup(o.lookup)
      $('#' + this.mainContainerId).css({ zIndex: o.zIndex })
      this.container.css({ maxHeight: o.maxHeight + 'px', width: o.width })
    },

    setLookup: function(lookup) {
        this.isLocal = true
        if ($.isArray(lookup) || $.isObject(lookup))
            this.options.lookup = { suggestions: lookup, data: [] }
    },

    clearCache: function() {
      this.cachedResponse = []
      this.badQueries = []
    },

    disable: function() {
      this.disabled = true
    },

    enable: function() {
      this.disabled = false
    },

    fixPosition: function() {
      var offset = this.el.offset()
      $('#' + this.mainContainerId).css({
          top: (offset.top + this.el.innerHeight()) + 'px',
          left: offset.left + 'px'
      })
    },

    enableKillerFn: function() {
      var self = this
      $(document).bind('click', self.killerFn)
    },

    disableKillerFn: function() {
      var self = this
      $(document).unbind('click', self.killerFn)
    },

    killSuggestions: function() {
      var self = this
      this.stopKillSuggestions()
      this.intervalId = window.setInterval(function() {
          self.hide()
          self.stopKillSuggestions()
      }, 300)
    },

    stopKillSuggestions: function() {
      window.clearInterval(this.intervalId)
    },

    onKeyPress: function(e) {
      if (this.disabled || !this.enabled) return

      switch (e.keyCode) {
        case 27: // ESC:
          this.el.val(this.currentValue)
          this.hide()
          break
        case 9:  // TAB
        case 13: // RETURN:
          if (-1 === this.selectedIndex)
            return this.hide()
          this.select(this.selectedIndex)
          if (9 === e.keyCode) return
          break
        case 38: // UP:
          this.moveUp()
          break
        case 40: // DOWN:
          this.moveDown()
          break
        default:
          return
      }
      e.stopImmediatePropagation()
      e.preventDefault()
    },

    onKeyUp: function(e) {
      if (this.disabled) return
      switch (e.keyCode) {
        case 38: // UP:
        case 40: // DOWN:
          return
      }
      clearInterval(this.onChangeInterval)
      var self = this
      var value = this.isFormField() ? this.el.val() : this.el.html()
      if (this.currentValue !== value) {
        if (this.options.deferRequestBy > 0)
          this.onChangeInterval = setInterval(
              function() { self.onValueChange() },
              this.options.deferRequestBy
          )
        else
          this.onValueChange()
      }
    },

    onValueChange: function() {
      clearInterval(this.onChangeInterval)
      this.currentValue = this.isFormField() ? this.el.val() : this.el.html()
      var q = this.getQuery(this.currentValue)
      this.selectedIndex = -1
      if (this.ignoreValueChange) {
        this.ignoreValueChange = false
        return
      }
      if (('' === q) || (q.length < this.options.minChars))
        this.hide()
      else
        this.getSuggestions(q)
    },

    getQuery: function(val) {
      var prefixLength = this.options.searchPrefix.length
      var d = this.options.delimiter
      if (!d) { return $.trim(val) }
      var arr = val.split(d)
      var query = $.trim(arr[arr.length - 1])
      if (query.substring(0, prefixLength) == this.options.searchPrefix)
         return query.substring(this.options.searchPrefix.length)
      return ''
    },

    getSuggestionsLocal: function(q) {
      var arr = this.options.lookup.suggestions
      var ret = { suggestions: [], data: [] }
      q       = q.toLowerCase()

      for (var index in arr) {
        var val = arr[index]
        if ('object' === typeof(val))
          val = val[this.options.searchKey]
        var indexPosition = (val  + ' ' + arr[index][this.options.dataKey])
            .toLowerCase().indexOf(q)
        var addData = false
        if ((true === this.options.searchEverywhere) && (indexPosition > -1))
          addData = true
        else if (0 === indexPosition)
          addData = true
        if (true === addData) {
          ret.suggestions.push(val)
          ret.data.push(arr[index])
        }
      }
      return ret
    },

    getSuggestions: function(q) {
      var self = this
      var cached = this.isLocal ? this.getSuggestionsLocal(q) : this.cachedResponse[q]
      if (cached && ($.isArray(cached.suggestions) || $.isObject(cached.suggestions))) {
        this.suggestions = cached.suggestions
        this.data = cached.data
        this.suggest()
      } else if (!this.isBadQuery(q)) {
        this.options.params.query = q
        $.get(this.serviceUrl, this.options.params, function(txt) {
            self.processResponse(txt)
        }, 'text')
      }
    },

    isBadQuery: function(q) {
      var i = this.badQueries.length
      while (i--) {
        if (0 === q.indexOf(this.badQueries[i])) return true
      }
      return false
    },

    hide: function() {
      this.enabled = false
      this.selectedIndex = -1
      this.container.hide()
    },

    suggest: function() {
      if (0 === this.suggestions.length)
        return this.hide()
      this.fixPosition()
      var div, s
      var self = this
      var len = this.suggestions.length
      var v = this.getQuery(this.currentValue)
      var mOver = function(xi) { return function() { self.activate(xi) } }
      var mClick = function(xi) { return function() { self.select(xi) } }
      this.container.hide().empty()
      for (var i = 0; i < len; i++) {
        s = this.suggestions[i]
        if ((typeof(entry) === 'object') &&
            (typeof(this.options.dataKey) !== 'undefined'))
            s = this.data[i][this.options.dataKey]
        div = $((self.selectedIndex === i ?
            '<div class="selected"' : '
' +
            this.template(v, this.data[i]) + '
'
        )
        div.mouseover(mOver(i))
        div.click(mClick(i))
        this.container.append(div)
      }
      this.enabled = true
      this.container.show()
    },

    processResponse: function(text) {
      var response
      try {
        response = JSON.parse(text)
      } catch (err) {
        return
      }
      if (!$.isArray(response.data)) response.data = []
      if (!this.options.noCache) {
        this.cachedResponse[response.query] = response
        if (0 === response.suggestions.length)
            this.badQueries.push(response.query)
      }
      if (response.query === this.getQuery(this.currentValue)) {
        this.suggestions = response.suggestions
        this.data = response.data
        this.suggest()
      }
    },

    activate: function(index) {
      var divs = this.container.children()
      // Clear previous selection:
      if ((-1 !== this.selectedIndex) && (divs.length > this.selectedIndex))
        $(divs.get(this.selectedIndex)).removeClass()

      this.selectedIndex = index
      var activeItem
      if ((-1 !== this.selectedIndex) && (divs.length > this.selectedIndex)) {
        activeItem = divs.get(this.selectedIndex)
        $(activeItem).addClass('selected')
      }
      return activeItem
    },

    deactivate: function(div, index) {
      div.className = ''
      if (this.selectedIndex === index) { this.selectedIndex = -1 }
    },

    select: function(i) {
      var selectedValue = this.suggestions[i]
      if (!selectedValue) return
      this.el.val(selectedValue)
      if (this.options.autoSubmit) {
        var f = this.el.parents('form')
        if (f.length > 0) { f.get(0).submit() }
      }
      this.ignoreValueChange = true
      this.hide()
      this.onSelect(i)
    },

    moveUp: function() {
      if (-1 === this.selectedIndex) return
      if (0 === this.selectedIndex) {
        this.container.children().get(0).className = ''
        this.selectedIndex = -1
        this.el.val(this.currentValue)
        return
      }
      this.adjustScroll(this.selectedIndex - 1)
    },

    moveDown: function() {
      if (this.selectedIndex === (this.suggestions.length - 1)) return
      this.adjustScroll(this.selectedIndex + 1)
    },

    adjustScroll: function(i) {
      var activeItem = this.activate(i)
      var offsetTop = activeItem.offsetTop
      var upperBound = this.container.scrollTop()
      var lowerBound = upperBound + this.options.maxHeight - 25
      if (offsetTop < upperBound)
        this.container.scrollTop(offsetTop)
      else if (offsetTop > lowerBound)
        this.container.scrollTop(offsetTop - this.options.maxHeight + 25)
      this.el.val(this.getValue(this.options.searchPrefix + this.suggestions[i]))
    },

    onSelect: function(i) {
      var self = this
      var fn   = this.options.onSelect
      var s    = this.suggestions[i]
      var d    = this.data[i]
      var val  = this.options.insertDomContent(d, s, this)
      if (this.isFormField()) {
          this.el.val(val)
      } else {
          this.el.html(val)
      }
      this.el.focus()
      if ($.isFunction(fn)) { fn(s, d, self.el) }
    },

    insertDomContent: function(data, suggestion, context) {
      var val = context.getValue(suggestion)
      if ('object' === typeof(data))
        val = context.getValue(data[context.options.dataKey])
      if (context.options.appendChars) val = val + context.options.appendChars
      return val
    },

    isFormField: function() {
        return this.el.is('input') || this.el.is('textarea')
    },

    getValue: function(value) {
        var del = this.options.delimiter
        if (!del) return value
        var currVal = this.currentValue
        var arr = currVal.split(del)
        if (1 === arr.length) return value
        var response = currVal.substr(0, currVal.length - arr[arr.length - 1].length)
        return response + value
    },

    /**
     * value: Data entered to autocomplete
     * data: Matching data
     */
    formatResult: function(value, data) {
      if (this.dataKey) data = data[this.dataKey]
      var pattern = '(' + value.replace(this.regEx, '\\$1') + ')'
      return data.replace(new RegExp(pattern, 'gi'), '$1<\/strong>')
    },

    remove: function() {
        $('#' + this.mainContainerId).remove()
    },
  }

})(jQuery)
<|endoftext|>


<commit_before>/*!
 * Drop-it v1.0.0
 * Licensed under http://www.apache.org/licenses/LICENSE-2.0
 *
 * Developed by HellCoderz | www.makefbcoverscom
 */

(function($){
    if(!$.bhs){
        $.bhs = new Object();
    };

    $.bhs.uploader = function(el,options){

        var base = this;
		var files, target, maxfile, errorResp, fileReader;
		var resp = new Array();
		var fileArr = new Array();
		var errorArr = new Array();
		var uploadedArr = new Array();
        var Progressor= [];
		var busyFlag = false;

        base.$el = target = $(el);
        base.el = el;
        base.$el.data("bhs.uploader", base);

        base.init = function(){
            base.options = $.extend({},$.bhs.uploader.defaultOptions, options);
			//Initializations
			dataArray = [];
			maxfile = base.options.maxfile;
			$.event.props.push('dataTransfer');

        };
		ondragover =  function(callback){
			target.bind('dragover', function(e) {
				e.preventDefault();
				e.stopPropagation();
				if(typeof callback == 'function')
					callback.call(this);
				return false;
			});
		};

		base.init();
		ondragover();

		if(base.options.fileUpload){
			$(base.options.fileUpload).bind("change", function () {
				traverseFiles(this.files);
			});
		}

		if(typeof base.options.onDragEnter == 'function'){
			target.bind('dragenter', function(e) {
				e.preventDefault();
				e.stopPropagation();
				base.options.onDragEnter.call(this);
				return false;
			});
		}

		if(typeof base.options.onDragOver == 'function'){
			ondragover(base.options.onDragOver);
		}

		if(typeof base.options.onDragLeave == 'function'){
			target.bind('dragleave', function(e) {
				e.preventDefault();
				e.stopPropagation();
				base.options.onDragLeave.call(this);
				return false;
			});
		}

		target.bind('drop', function(e) {
			e.preventDefault();
			e.stopPropagation();
			var files = e.dataTransfer.files;
			traverseFiles(files);
			return false;
		});

		/***--------- Private Methods ----------***/

		uniqueData =  function(){
			var text = "";
			var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";

			for( var i=0; i < 5; i++ )
				text += possible.charAt(Math.floor(Math.random() * possible.length));

			return text;
		}

		traverseFiles = function(files){
			if(files.length <= maxfile){
				var len = 0;
				$.each(files, function(index, file) {

					if(base.isImage(file)){
						len++;
						var uniq = uniqueData();
						file.handle = uniq;
						fileReader = new FileReader();
						fileReader.onload = (function(file) {
							return function(e) {
								file.src = this.result;
							};
						})(files[index]);
						fileReader.readAsDataURL(file);
						fileArr.push(file);
					}else{
						errorResp = 'file '+file.name+' id('+index+') is not a valid image file';
						parseError(base.options.error, errorResp);
					}
				});
				resp = { fileinfo: fileArr, error: errorArr};
				resp.count = resp.fileinfo.length;
				parsePreview(base.options.preview, resp);
				if(typeof base.options.error == 'function')
					base.error();
				}
			else{
				errorResp = "Maximum "+maxfile+" files are allowed";
				parseError(base.options.error, errorResp);
				return false;
			}
		}

		parsePreview = function(MethodOpt, Args){
			if(typeof MethodOpt == 'function'){
				if(Args){
					if(MethodOpt == base.options.error){
						errorArr.push(Args);
					}
					MethodOpt.call(target,Args);
				}				else

					MethodOpt.call(target);
			}
			return false;
		}

		parseError = function(MethodOpt, Args){
			errorArr.push(Args);
			if(typeof MethodOpt == 'function'){
				MethodOpt.call(target,Args);
			}
			return false;
		}

		parseFunc = function(arg){
			arg.call(target);
		}

		clearArr = function(arr){
			if(arr && arr.length > 0){
				$.grep(arr, function(e,i){
					arr.splice(i,arr.length);
				});
			}
			return arr;
		}

		doAjax = function(postFile, array, xhr, callback){

			var file = $(array.shift());
			var fileName = file[0].name;
			var fileSize = file[0].size;
			var fileType = file[0].type;
			var fileSrc = file[0].src;
			var fileHandle = file[0].handle;
			busyFlag = true;
			$.userdata = file;
			provider = function () { return xhr; };
			data = fileSrc.substr(fileSrc.indexOf('base64') + 7);
			$.ajax({
					type: 'POST',
					url: postFile,
					xhr: provider,
					cache: false,
					data: {
						name: fileName,
						size: fileSize,
						type: fileType,
						data: data,
					},
					success: function (data) {
						$.userdata[0].filename =  data;
						console.log(resp.fileinfo);
						$.grep(resp.fileinfo, function(e,i){
							if(e.handle == fileHandle)
							{
								resp.fileinfo.splice(i,1);
							}
						});
						callback($.userdata);
						busyFlag = false;
					},
					error: function (data,e1,e2) {
						$(array.unshift(file[0]));
						busyFlag = false;
						console.log(data.statusText);
						resp.count = resp.fileinfo.length;
						errorResp = 'The image could not be saved on server';
						parseError(base.options.error, errorResp);
					}
			}).done(function(){
				if(array.length === 0){
					return false;
				}
				doAjax(postFile,array, xhr,callback);
			});
			resp.count = resp.fileinfo.length;
		}

		/***--------- Public Methods ----------***/

		base.isImage =  function(file){
			if (file.type.match('image.*')) {
				return true;
			}
			return false;
		}

		base.preview = function(arg){
			if(typeof arg === 'undefined')
				return resp;
			else{
				var index = arg;
				try
				{
					if(arg < 1) return false;
					return resp.fileinfo[arg-1];
				}
				catch(exception){
					return false;
				}
			}
		}

		base.uploaded = function(){
			return uploadedArr;
		}

		base.error = function(){
			return (typeof resp == 'object' && resp.error)?resp.error:false;
		}

		base.dropped = function(){
			var x = resp.fileinfo;
			var chk = (x)?x:[];
			var dropped = $.merge( $.merge( [], chk ),  uploadedArr );
			return dropped;
		}

		base.removeAll =  function(arg){
			if(busyFlag == true){
				console.log('File currently under upload. Could not remove the file now');
				return false;
			}
			else{
				if(typeof arg == 'function')
					parseFunc(arg);
				resp.fileinfo = clearArr(resp.fileinfo);
				resp.error = clearArr(resp.error);
				resp.count = 0;
				return resp;
			}
		}

		base.upload = function(arg){
			if(typeof resp != 'undefined' && resp.count)
			{
				var xhr, provider;
				xhr = $.ajaxSettings.xhr();
				if(typeof arg === 'undefined' || arg == ''){
					errorResp = 'Please provide the argument for uploading image';
					parseError(base.options.error, errorResp);
					return false;
				}
				if(typeof arg == 'object' && !arg.file){
					errorResp = 'Please mention a PHP file before uploading';
					parseError(base.options.error, errorResp);
					return false;
				}
				if(typeof(arg.progress) == 'function')
				{
					if (xhr.upload) {
						xhr.upload.addEventListener('progress', function (evt) {
							if (evt.lengthComputable) {
								var percentage = Math.round((evt.loaded / evt.total) * 100);
								$.userdata.progress = percentage;
								arg.progress.call(target,$.userdata);
							}
						}, false);
					}
				}

				var file = (typeof arg == 'object')?arg.file:arg;
				doAjax(file, resp.fileinfo, xhr, function(data){
					$.grep(data, function(e,i){
						uploadedArr.push(data[i]);
					});
					if(typeof(arg.done) == 'function'){
						arg.done.call(target,data);
					}
				});

			}else{
				errorResp = 'No Valid files to upload';
				parseError(base.options.error, errorResp);
				return false;
			}
		}

    };

    $.bhs.uploader.defaultOptions = {
		maxfile: 5
    };

    $.fn.bhs_uploader = function(options){
		var args = Array.prototype.slice.call(arguments, 1);
        return this.each(function(){
				var item = $(this), instance = item.data('bhs_uploader');
				if(!instance) {
					item.data('bhs_uploader', new $.bhs.uploader(this, options));
				} else {
					if(typeof options === 'string') {
						return instance[options].apply(instance, args);
					}
				}
        });
    };

})(jQuery);
<commit_msg>Fixed backend response<commit_after>/*!
 * Drop-it v1.0.0
 * Licensed under http://www.apache.org/licenses/LICENSE-2.0
 *
 * Developed by HellCoderz | www.makefbcoverscom
 */

(function($){
    if(!$.bhs){
        $.bhs = new Object();
    };

    $.bhs.uploader = function(el,options){

        var base = this;
		var files, target, maxfile, errorResp, fileReader;
		var resp = new Array();
		var fileArr = new Array();
		var errorArr = new Array();
		var uploadedArr = new Array();
        var Progressor= [];
		var busyFlag = false;

        base.$el = target = $(el);
        base.el = el;
        base.$el.data("bhs.uploader", base);

        base.init = function(){
            base.options = $.extend({},$.bhs.uploader.defaultOptions, options);
			//Initializations
			dataArray = [];
			maxfile = base.options.maxfile;
			$.event.props.push('dataTransfer');

        };
		ondragover =  function(callback){
			target.bind('dragover', function(e) {
				e.preventDefault();
				e.stopPropagation();
				if(typeof callback == 'function')
					callback.call(this);
				return false;
			});
		};

		base.init();
		ondragover();

		if(base.options.fileUpload){
			$(base.options.fileUpload).bind("change", function () {
				traverseFiles(this.files);
			});
		}

		if(typeof base.options.onDragEnter == 'function'){
			target.bind('dragenter', function(e) {
				e.preventDefault();
				e.stopPropagation();
				base.options.onDragEnter.call(this);
				return false;
			});
		}

		if(typeof base.options.onDragOver == 'function'){
			ondragover(base.options.onDragOver);
		}

		if(typeof base.options.onDragLeave == 'function'){
			target.bind('dragleave', function(e) {
				e.preventDefault();
				e.stopPropagation();
				base.options.onDragLeave.call(this);
				return false;
			});
		}

		target.bind('drop', function(e) {
			e.preventDefault();
			e.stopPropagation();
			var files = e.dataTransfer.files;
			traverseFiles(files);
			return false;
		});

		/***--------- Private Methods ----------***/

		uniqueData =  function(){
			var text = "";
			var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";

			for( var i=0; i < 5; i++ )
				text += possible.charAt(Math.floor(Math.random() * possible.length));

			return text;
		}

		traverseFiles = function(files){
			if(files.length <= maxfile){
				var len = 0;
				$.each(files, function(index, file) {

					if(base.isImage(file)){
						len++;
						var uniq = uniqueData();
						file.handle = uniq;
						fileReader = new FileReader();
						fileReader.onload = (function(file) {
							return function(e) {
								file.src = this.result;
							};
						})(files[index]);
						fileReader.readAsDataURL(file);
						fileArr.push(file);
					}else{
						errorResp = 'file '+file.name+' id('+index+') is not a valid image file';
						parseError(base.options.error, errorResp);
					}
				});
				resp = { fileinfo: fileArr, error: errorArr};
				resp.count = resp.fileinfo.length;
				parsePreview(base.options.preview, resp);
				if(typeof base.options.error == 'function')
					base.error();
				}
			else{
				errorResp = "Maximum "+maxfile+" files are allowed";
				parseError(base.options.error, errorResp);
				return false;
			}
		}

		parsePreview = function(MethodOpt, Args){
			if(typeof MethodOpt == 'function'){
				if(Args){
					if(MethodOpt == base.options.error){
						errorArr.push(Args);
					}
					MethodOpt.call(target,Args);
				}				else

					MethodOpt.call(target);
			}
			return false;
		}

		parseError = function(MethodOpt, Args){
			errorArr.push(Args);
			if(typeof MethodOpt == 'function'){
				MethodOpt.call(target,Args);
			}
			return false;
		}

		parseFunc = function(arg){
			arg.call(target);
		}

		clearArr = function(arr){
			if(arr && arr.length > 0){
				$.grep(arr, function(e,i){
					arr.splice(i,arr.length);
				});
			}
			return arr;
		}

		doAjax = function(postFile, array, xhr, callback){

			var file = $(array.shift());
			var fileName = file[0].name;
			var fileSize = file[0].size;
			var fileType = file[0].type;
			var fileSrc = file[0].src;
			var fileHandle = file[0].handle;
			busyFlag = true;
			$.userdata = file;
			provider = function () { return xhr; };
			data = fileSrc.substr(fileSrc.indexOf('base64') + 7);
			$.ajax({
					type: 'POST',
					url: postFile,
					xhr: provider,
					cache: false,
					data: {
						name: fileName,
						size: fileSize,
						type: fileType,
						data: data,
					},
					success: function (data) {
						$.userdata[0].response =  data;
						console.log(resp.fileinfo);
						$.grep(resp.fileinfo, function(e,i){
							if(e.handle == fileHandle)
							{
								resp.fileinfo.splice(i,1);
							}
						});
						callback($.userdata);
						busyFlag = false;
					},
					error: function (data,e1,e2) {
						$(array.unshift(file[0]));
						busyFlag = false;
						console.log(data.statusText);
						resp.count = resp.fileinfo.length;
						errorResp = 'The image could not be saved on server';
						parseError(base.options.error, errorResp);
					}
			}).done(function(){
				if(array.length === 0){
					return false;
				}
				doAjax(postFile,array, xhr,callback);
			});
			resp.count = resp.fileinfo.length;
		}

		/***--------- Public Methods ----------***/

		base.isImage =  function(file){
			if (file.type.match('image.*')) {
				return true;
			}
			return false;
		}

		base.preview = function(arg){
			if(typeof arg === 'undefined')
				return resp;
			else{
				var index = arg;
				try
				{
					if(arg < 1) return false;
					return resp.fileinfo[arg-1];
				}
				catch(exception){
					return false;
				}
			}
		}

		base.uploaded = function(){
			return uploadedArr;
		}

		base.error = function(){
			return (typeof resp == 'object' && resp.error)?resp.error:false;
		}

		base.dropped = function(){
			var x = resp.fileinfo;
			var chk = (x)?x:[];
			var dropped = $.merge( $.merge( [], chk ),  uploadedArr );
			return dropped;
		}

		base.removeAll =  function(arg){
			if(busyFlag == true){
				console.log('File currently under upload. Could not remove the file now');
				return false;
			}
			else{
				if(typeof arg == 'function')
					parseFunc(arg);
				resp.fileinfo = clearArr(resp.fileinfo);
				resp.error = clearArr(resp.error);
				resp.count = 0;
				return resp;
			}
		}

		base.upload = function(arg){
			if(typeof resp != 'undefined' && resp.count)
			{
				var xhr, provider;
				xhr = $.ajaxSettings.xhr();
				if(typeof arg === 'undefined' || arg == ''){
					errorResp = 'Please provide the argument for uploading image';
					parseError(base.options.error, errorResp);
					return false;
				}
				if(typeof arg == 'object' && !arg.file){
					errorResp = 'Please mention a PHP file before uploading';
					parseError(base.options.error, errorResp);
					return false;
				}
				if(typeof(arg.progress) == 'function')
				{
					if (xhr.upload) {
						xhr.upload.addEventListener('progress', function (evt) {
							if (evt.lengthComputable) {
								var percentage = Math.round((evt.loaded / evt.total) * 100);
								$.userdata.progress = percentage;
								arg.progress.call(target,$.userdata);
							}
						}, false);
					}
				}

				var file = (typeof arg == 'object')?arg.file:arg;
				doAjax(file, resp.fileinfo, xhr, function(data){
					$.grep(data, function(e,i){
						uploadedArr.push(data[i]);
					});
					if(typeof(arg.done) == 'function'){
						arg.done.call(target,data);
					}
				});

			}else{
				errorResp = 'No Valid files to upload';
				parseError(base.options.error, errorResp);
				return false;
			}
		}

    };

    $.bhs.uploader.defaultOptions = {
		maxfile: 5
    };

    $.fn.bhs_uploader = function(options){
		var args = Array.prototype.slice.call(arguments, 1);
        return this.each(function(){
				var item = $(this), instance = item.data('bhs_uploader');
				if(!instance) {
					item.data('bhs_uploader', new $.bhs.uploader(this, options));
				} else {
					if(typeof options === 'string') {
						return instance[options].apply(instance, args);
					}
				}
        });
    };

})(jQuery);
<|endoftext|>