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

+ function ($) {
    'use strict';

    // VALIDATOR CLASS DEFINITION
    // ==========================

    function getValue($el) {
        return $el.is('[type="checkbox"]') ? $el.prop('checked') :
            $el.is('[type="radio"]') ? !!$('[name="' + $el.attr('name') + '"]:checked').length :
            $.trim($el.val())
    }

    var Validator = function (element, options) {
        this.options = options
        this.$element = $(element)
        this.$inputs = this.$element.find(Validator.INPUT_SELECTOR)
        this.$btn = $('button[type="submit"], input[type="submit"]')
            .filter('[form="' + this.$element.attr('id') + '"]')
            .add(this.$element.find('input[type="submit"], button[type="submit"]'))

        options.errors = $.extend({}, Validator.DEFAULTS.errors, options.errors)

        for (var custom in options.custom) {
            if (!options.errors[custom]) throw new Error('Missing default error message for custom validator: ' + custom)
        }

        $.extend(Validator.VALIDATORS, options.custom)

        this.$element.attr('novalidate', true) // disable automatic native validation
        this.toggleSubmit()

        this.$element.on('input.bs.validator change.bs.validator focusout.bs.validator', Validator.INPUT_SELECTOR, $.proxy(this.onInput, this))
        this.$element.on('submit.bs.validator', $.proxy(this.onSubmit, this))

        this.$element.find('[data-match]').each(function () {
            var $this = $(this)
            var target = $this.data('match')

            $(target).on('input.bs.validator', function (e) {
                getValue($this) && $this.trigger('input.bs.validator')
            })
        })
    }

    Validator.INPUT_SELECTOR = ':input:not([type="submit"], button):enabled:visible'

    Validator.FOCUS_OFFSET = 20

    Validator.DEFAULTS = {
        delay: 500,
        html: false,
        disable: true,
        focus: true,
        custom: {},
        errors: {
            match: 'Does not match',
            minlength: 'Not long enough'
        },
        feedback: {
            success: 'glyphicon-ok',
            error: 'glyphicon-remove'
        }
    }

    Validator.VALIDATORS = {
        'native': function ($el) {
            var el = $el[0]
            return el.checkValidity ? el.checkValidity() : true
        },
        'match': function ($el) {
            var target = $el.data('match')
            return !$el.val() || $el.val() === $(target).val()
        },
        'minlength': function ($el) {
            var minlength = $el.data('minlength')
            return !$el.val() || $el.val().length >= minlength
        }
    }

    Validator.prototype.onInput = function (e) {
        var self = this
        var $el = $(e.target)
        var deferErrors = e.type !== 'focusout'
        this.validateInput($el, deferErrors).done(function () {
            self.toggleSubmit()
        })
    }

    Validator.prototype.validateInput = function ($el, deferErrors) {
        var value = getValue($el)
        var prevValue = $el.data('bs.validator.previous')
        var prevErrors = $el.data('bs.validator.errors')
        var errors

        if (prevValue === value) return $.Deferred().resolve()
        else $el.data('bs.validator.previous', value)

        if ($el.is('[type="radio"]')) $el = this.$element.find('input[name="' + $el.attr('name') + '"]')

        var e = $.Event('validate.bs.validator', {
            relatedTarget: $el[0]
        })
        this.$element.trigger(e)
        if (e.isDefaultPrevented()) return

        var self = this

        return this.runValidators($el).done(function (errors) {
            $el.data('bs.validator.errors', errors)

            errors.length ? deferErrors ? self.defer($el, self.showErrors) : self.showErrors($el) : self.clearErrors($el)

            if (!prevErrors || errors.toString() !== prevErrors.toString()) {
                e = errors.length ? $.Event('invalid.bs.validator', {
                    relatedTarget: $el[0],
                    detail: errors
                }) : $.Event('valid.bs.validator', {
                    relatedTarget: $el[0],
                    detail: prevErrors
                })

                self.$element.trigger(e)
            }

            self.toggleSubmit()

            self.$element.trigger($.Event('validated.bs.validator', {
                relatedTarget: $el[0]
            }))
        })
    }

    Validator.prototype.runValidators = function ($el) {
        var errors = []
        var deferred = $.Deferred()
        var options = this.options

        $el.data('bs.validator.deferred') && $el.data('bs.validator.deferred').reject()
        $el.data('bs.validator.deferred', deferred)

        function getErrorMessage(key) {
            return $el.data(key + '-error') || $el.data('error') || key == 'native' && $el[0].validationMessage || options.errors[key]
        }

        $.each(Validator.VALIDATORS, $.proxy(function (key, validator) {
            if ((getValue($el) || $el.attr('required')) &&
                ($el.data(key) || key == 'native') &&
                !validator.call(this, $el)) {
                var error = getErrorMessage(key) !~errors.indexOf(error) && errors.push(error)
            }
        }, this))

        if (!errors.length && getValue($el) && $el.data('remote')) {
            this.defer($el, function () {
                var data = {}
                data[$el.attr('name')] = getValue($el)
                $.get($el.data('remote'), data)
                    .fail(function (jqXHR, textStatus, error) {
                        errors.push(getErrorMessage('remote') || error)
                    })
                    .always(function () {
                        deferred.resolve(errors)
                    })
            })
        } else deferred.resolve(errors)

        return deferred.promise()
    }

    Validator.prototype.validate = function () {
        var self = this

        $.when(this.$inputs.map(function (el) {
            return self.validateInput($(this), false)
        })).then(function () {
            self.toggleSubmit()
            self.focusError()
        })

        return this
    }

    Validator.prototype.focusError = function () {
        if (!this.options.focus) return

        var $input = $(".has-error:first :input")
        if ($input.length === 0) return

        $(document.body).animate({
            scrollTop: $input.offset().top - Validator.FOCUS_OFFSET
        }, 250)
        $input.focus()
    }

    Validator.prototype.showErrors = function ($el) {
        var method = this.options.html ? 'html' : 'text'
        var errors = $el.data('bs.validator.errors')
        var $group = $el.closest('.form-group')
        var $block = $group.find('.help-block.with-errors')
        var $feedback = $group.find('.form-control-feedback')

        if (!errors.length) return

        errors = $('<ul/>')
            .addClass('list-unstyled')
            .append($.map(errors, function (error) {
                return $('<li/>')[method](error)
            }))

        $block.data('bs.validator.originalContent') === undefined && $block.data('bs.validator.originalContent', $block.html())
        $block.empty().append(errors)
        $group.addClass('has-error has-danger')

        $group.hasClass('has-feedback') && $feedback.removeClass(this.options.feedback.success) && $feedback.addClass(this.options.feedback.error) && $group.removeClass('has-success')
    }

    Validator.prototype.clearErrors = function ($el) {
        var $group = $el.closest('.form-group')
        var $block = $group.find('.help-block.with-errors')
        var $feedback = $group.find('.form-control-feedback')

        $block.html($block.data('bs.validator.originalContent'))
        $group.removeClass('has-error has-danger')

        $group.hasClass('has-feedback') && $feedback.removeClass(this.options.feedback.error) && getValue($el) && $feedback.addClass(this.options.feedback.success) && $group.addClass('has-success')
    }

    Validator.prototype.hasErrors = function () {
        function fieldErrors() {
            return !!($(this).data('bs.validator.errors') || []).length
        }

        return !!this.$inputs.filter(fieldErrors).length
    }

    Validator.prototype.isIncomplete = function () {
        function fieldIncomplete() {
            return !getValue($(this))
        }

        return !!this.$inputs.filter('[required]').filter(fieldIncomplete).length
    }

    Validator.prototype.onSubmit = function (e) {
        this.validate()
        if (this.isIncomplete() || this.hasErrors()) e.preventDefault()
    }

    Validator.prototype.toggleSubmit = function () {
        if (!this.options.disable) return
        this.$btn.toggleClass('disabled', this.isIncomplete() || this.hasErrors())
    }

    Validator.prototype.defer = function ($el, callback) {
        callback = $.proxy(callback, this, $el)
        if (!this.options.delay) return callback()
        window.clearTimeout($el.data('bs.validator.timeout'))
        $el.data('bs.validator.timeout', window.setTimeout(callback, this.options.delay))
    }

    Validator.prototype.destroy = function () {
        this.$element
            .removeAttr('novalidate')
            .removeData('bs.validator')
            .off('.bs.validator')
            .find('.form-control-feedback')
            .removeClass([this.options.feedback.error, this.options.feedback.success].join(' '))

        this.$inputs
            .off('.bs.validator')
            .removeData(['bs.validator.errors', 'bs.validator.deferred', 'bs.validator.previous'])
            .each(function () {
                var $this = $(this)
                var timeout = $this.data('bs.validator.timeout')
                window.clearTimeout(timeout) && $this.removeData('bs.validator.timeout')
            })

        this.$element.find('.help-block.with-errors').each(function () {
            var $this = $(this)
            var originalContent = $this.data('bs.validator.originalContent')

            $this
                .removeData('bs.validator.originalContent')
                .html(originalContent)
        })

        this.$element.find('input[type="submit"], button[type="submit"]').removeClass('disabled')

        this.$element.find('.has-error, .has-danger').removeClass('has-error has-danger')

        return this
    }

    // VALIDATOR PLUGIN DEFINITION
    // ===========================

    function Plugin(option) {
        return this.each(function () {
            var $this = $(this)
            var options = $.extend({}, Validator.DEFAULTS, $this.data(), typeof option == 'object' && option)
            var data = $this.data('bs.validator')

            if (!data && option == 'destroy') return
            if (!data) $this.data('bs.validator', (data = new Validator(this, options)))
            if (typeof option == 'string') data[option]()
        })
    }

    var old = $.fn.validator

    $.fn.validator = Plugin
    $.fn.validator.Constructor = Validator

    // VALIDATOR NO CONFLICT
    // =====================

    $.fn.validator.noConflict = function () {
        $.fn.validator = old
        return this
    }

    // VALIDATOR DATA-API
    // ==================

    $(window).on('load', function () {
        $('form[data-toggle="validator"]').each(function () {
            var $form = $(this)
            Plugin.call($form, $form.data())
        })
    })

}(jQuery);
<commit_msg>Minor contact form changes.<commit_after>/* ========================================================================
 * Bootstrap (plugin): validator.js v0.10.2
 * ========================================================================
 * The MIT License (MIT)
 *
 * Copyright (c) 2015 Cina Saffary.
 * Made by @1000hz in the style of Bootstrap 3 era @fat
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 * ======================================================================== */

+function ($) {
  'use strict';

  // VALIDATOR CLASS DEFINITION
  // ==========================

  function getValue($el) {
    return $el.is('[type="checkbox"]') ? $el.prop('checked')                                     :
           $el.is('[type="radio"]')    ? !!$('[name="' + $el.attr('name') + '"]:checked').length :
                                         $.trim($el.val())
  }

  var Validator = function (element, options) {
    this.options  = options
    this.$element = $(element)
    this.$inputs  = this.$element.find(Validator.INPUT_SELECTOR)
    this.$btn     = $('button[type="submit"], input[type="submit"]')
                      .filter('[form="' + this.$element.attr('id') + '"]')
                      .add(this.$element.find('input[type="submit"], button[type="submit"]'))

    options.errors = $.extend({}, Validator.DEFAULTS.errors, options.errors)

    for (var custom in options.custom) {
      if (!options.errors[custom]) throw new Error('Missing default error message for custom validator: ' + custom)
    }

    $.extend(Validator.VALIDATORS, options.custom)

    this.$element.attr('novalidate', true) // disable automatic native validation
    this.toggleSubmit()

    this.$element.on('input.bs.validator change.bs.validator focusout.bs.validator', Validator.INPUT_SELECTOR, $.proxy(this.onInput, this))
    this.$element.on('submit.bs.validator', $.proxy(this.onSubmit, this))

    this.$element.find('[data-match]').each(function () {
      var $this  = $(this)
      var target = $this.data('match')

      $(target).on('input.bs.validator', function (e) {
        getValue($this) && $this.trigger('input.bs.validator')
      })
    })
  }

  Validator.INPUT_SELECTOR = ':input:not([type="submit"], button):enabled:visible'

  Validator.FOCUS_OFFSET = 20

  Validator.DEFAULTS = {
    delay: 500,
    html: false,
    disable: true,
    focus: true,
    custom: {},
    errors: {
      match: 'Does not match',
      minlength: 'Not long enough'
    },
    feedback: {
      success: 'glyphicon-ok',
      error: 'glyphicon-remove'
    }
  }

  Validator.VALIDATORS = {
    'native': function ($el) {
      var el = $el[0]
      return el.checkValidity ? el.checkValidity() : true
    },
    'match': function ($el) {
      var target = $el.data('match')
      return !$el.val() || $el.val() === $(target).val()
    },
    'minlength': function ($el) {
      var minlength = $el.data('minlength')
      return !$el.val() || $el.val().length >= minlength
    }
  }

  Validator.prototype.onInput = function (e) {
    var self        = this
    var $el         = $(e.target)
    var deferErrors = e.type !== 'focusout'
    this.validateInput($el, deferErrors).done(function () {
      self.toggleSubmit()
    })
  }

  Validator.prototype.validateInput = function ($el, deferErrors) {
    var value      = getValue($el)
    var prevValue  = $el.data('bs.validator.previous')
    var prevErrors = $el.data('bs.validator.errors')
    var errors

    if (prevValue === value) return $.Deferred().resolve()
    else $el.data('bs.validator.previous', value)

    if ($el.is('[type="radio"]')) $el = this.$element.find('input[name="' + $el.attr('name') + '"]')

    var e = $.Event('validate.bs.validator', {relatedTarget: $el[0]})
    this.$element.trigger(e)
    if (e.isDefaultPrevented()) return

    var self = this

    return this.runValidators($el).done(function (errors) {
      $el.data('bs.validator.errors', errors)

      errors.length
        ? deferErrors ? self.defer($el, self.showErrors) : self.showErrors($el)
        : self.clearErrors($el)

      if (!prevErrors || errors.toString() !== prevErrors.toString()) {
        e = errors.length
          ? $.Event('invalid.bs.validator', {relatedTarget: $el[0], detail: errors})
          : $.Event('valid.bs.validator', {relatedTarget: $el[0], detail: prevErrors})

        self.$element.trigger(e)
      }

      self.toggleSubmit()

      self.$element.trigger($.Event('validated.bs.validator', {relatedTarget: $el[0]}))
    })
  }

  Validator.prototype.runValidators = function ($el) {
    var errors   = []
    var deferred = $.Deferred()
    var options  = this.options

    $el.data('bs.validator.deferred') && $el.data('bs.validator.deferred').reject()
    $el.data('bs.validator.deferred', deferred)

    function getErrorMessage(key) {
      return $el.data(key + '-error')
        || $el.data('error')
        || key == 'native' && $el[0].validationMessage
        || options.errors[key]
    }

    $.each(Validator.VALIDATORS, $.proxy(function (key, validator) {
      if ((getValue($el) || $el.attr('required')) &&
          ($el.data(key) || key == 'native') &&
          !validator.call(this, $el)) {
        var error = getErrorMessage(key)
        !~errors.indexOf(error) && errors.push(error)
      }
    }, this))

    if (!errors.length && getValue($el) && $el.data('remote')) {
      this.defer($el, function () {
        var data = {}
        data[$el.attr('name')] = getValue($el)
        $.get($el.data('remote'), data)
          .fail(function (jqXHR, textStatus, error) { errors.push(getErrorMessage('remote') || error) })
          .always(function () { deferred.resolve(errors)})
      })
    } else deferred.resolve(errors)

    return deferred.promise()
  }

  Validator.prototype.validate = function () {
    var self = this

    $.when(this.$inputs.map(function (el) {
      return self.validateInput($(this), false)
    })).then(function () {
      self.toggleSubmit()
      self.focusError()
    })

    return this
  }

  Validator.prototype.focusError = function () {
    if (!this.options.focus) return

    var $input = $(".has-error:first :input")
    if ($input.length === 0) return

    $(document.body).animate({scrollTop: $input.offset().top - Validator.FOCUS_OFFSET}, 250)
    $input.focus()
  }

  Validator.prototype.showErrors = function ($el) {
    var method = this.options.html ? 'html' : 'text'
    var errors = $el.data('bs.validator.errors')
    var $group = $el.closest('.form-group')
    var $block = $group.find('.help-block.with-errors')
    var $feedback = $group.find('.form-control-feedback')

    if (!errors.length) return

    errors = $('<ul/>')
      .addClass('list-unstyled')
      .append($.map(errors, function (error) { return $('<li/>')[method](error) }))

    $block.data('bs.validator.originalContent') === undefined && $block.data('bs.validator.originalContent', $block.html())
    $block.empty().append(errors)
    $group.addClass('has-error has-danger')

    $group.hasClass('has-feedback')
      && $feedback.removeClass(this.options.feedback.success)
      && $feedback.addClass(this.options.feedback.error)
      && $group.removeClass('has-success')
  }

  Validator.prototype.clearErrors = function ($el) {
    var $group = $el.closest('.form-group')
    var $block = $group.find('.help-block.with-errors')
    var $feedback = $group.find('.form-control-feedback')

    $block.html($block.data('bs.validator.originalContent'))
    $group.removeClass('has-error has-danger')

    $group.hasClass('has-feedback')
      && $feedback.removeClass(this.options.feedback.error)
      && getValue($el)
      && $feedback.addClass(this.options.feedback.success)
      && $group.addClass('has-success')
  }

  Validator.prototype.hasErrors = function () {
    function fieldErrors() {
      return !!($(this).data('bs.validator.errors') || []).length
    }

    return !!this.$inputs.filter(fieldErrors).length
  }

  Validator.prototype.isIncomplete = function () {
    function fieldIncomplete() {
      return !getValue($(this))
    }

    return !!this.$inputs.filter('[required]').filter(fieldIncomplete).length
  }

  Validator.prototype.onSubmit = function (e) {
    this.validate()
    if (this.isIncomplete() || this.hasErrors()) e.preventDefault()
  }

  Validator.prototype.toggleSubmit = function () {
    if (!this.options.disable) return
    this.$btn.toggleClass('disabled', this.isIncomplete() || this.hasErrors())
  }

  Validator.prototype.defer = function ($el, callback) {
    callback = $.proxy(callback, this, $el)
    if (!this.options.delay) return callback()
    window.clearTimeout($el.data('bs.validator.timeout'))
    $el.data('bs.validator.timeout', window.setTimeout(callback, this.options.delay))
  }

  Validator.prototype.destroy = function () {
    this.$element
      .removeAttr('novalidate')
      .removeData('bs.validator')
      .off('.bs.validator')
      .find('.form-control-feedback')
        .removeClass([this.options.feedback.error, this.options.feedback.success].join(' '))

    this.$inputs
      .off('.bs.validator')
      .removeData(['bs.validator.errors', 'bs.validator.deferred', 'bs.validator.previous'])
      .each(function () {
        var $this = $(this)
        var timeout = $this.data('bs.validator.timeout')
        window.clearTimeout(timeout) && $this.removeData('bs.validator.timeout')
      })

    this.$element.find('.help-block.with-errors').each(function () {
      var $this = $(this)
      var originalContent = $this.data('bs.validator.originalContent')

      $this
        .removeData('bs.validator.originalContent')
        .html(originalContent)
    })

    this.$element.find('input[type="submit"], button[type="submit"]').removeClass('disabled')

    this.$element.find('.has-error, .has-danger').removeClass('has-error has-danger')

    return this
  }

  // VALIDATOR PLUGIN DEFINITION
  // ===========================

  function Plugin(option) {
    return this.each(function () {
      var $this   = $(this)
      var options = $.extend({}, Validator.DEFAULTS, $this.data(), typeof option == 'object' && option)
      var data    = $this.data('bs.validator')

      if (!data && option == 'destroy') return
      if (!data) $this.data('bs.validator', (data = new Validator(this, options)))
      if (typeof option == 'string') data[option]()
    })
  }

  var old = $.fn.validator

  $.fn.validator             = Plugin
  $.fn.validator.Constructor = Validator

  // VALIDATOR NO CONFLICT
  // =====================

  $.fn.validator.noConflict = function () {
    $.fn.validator = old
    return this
  }

  // VALIDATOR DATA-API
  // ==================

  $(window).on('load', function () {
    $('form[data-toggle="validator"]').each(function () {
      var $form = $(this)
      Plugin.call($form, $form.data())
    })
  })

}(jQuery);
<|endoftext|>


<commit_before>/* jshint asi:true */
//先等图片都加载完成
//再执行布局函数

/**
 * 执行主函数
 * @param  {[type]} function( [description]
 * @return {[type]}           [description]
 */
(function() {

  /**
     * 内容JSON
     */
  var demoContent = [
	{
      demo_link: 'https://github.com/joeyos/QQ_Manager',
      img_link: '/images/demo/QQManager.jpg',
      code_link: 'https://github.com/joeyos/QQ_Manager',
      title: '腾讯电脑管家',
      core_tech: 'Qt & C++',
      description: '利用Qt制作的腾讯电脑管家界面'
    }, {
      demo_link: 'http://v.youku.com/v_show/id_XMjgyNDEwMjU0OA==.html?spm=a2h0k.8191407.0.0&from=s1.8-1-1.2',
      img_link: '/images/demo/Graduate.jpg',
      code_link: 'http://v.youku.com/v_show/id_XMjgyNDEwMjU0OA==.html?spm=a2h0k.8191407.0.0&from=s1.8-1-1.2',
      title: '毕业电子相册',
      core_tech: 'Ae & Edius',
      description: '献给悄悄流逝的大学四年时光'
    }, {
      demo_link: 'https://github.com/joeyos/LicensePlateRecognition',
      img_link: '/images/demo/LicensePlateRecognition.jpg',
      code_link: 'https://github.com/joeyos/LicensePlateRecognition',
      title: 'Matlab车牌识别',
      core_tech: 'Matlab',
      description: '用模板匹配法实现的车牌识别'
    }, {
      demo_link: 'https://github.com/joeyos/QQbyQt',
      img_link: '/images/demo/QQbyQt.jpg',
      code_link: 'https://github.com/joeyos/QQbyQt',
      title: 'QQ局域网聊天',
      core_tech: 'Qt & C++',
      description: '基于Qt实现的局域网聊天系统'
    }, {
      demo_link: 'https://github.com/joeyos/SAR-imaging',
      img_link: '/images/demo/SAR.jpg',
      code_link: 'https://github.com/joeyos/SAR-imaging',
      title: '合成孔径雷达成像',
      core_tech: 'Matlab',
      description: '几种传统雷达成像算法'
    }, {
      demo_link: 'https://joeyos.github.io/AdaptiveScreen',
      img_link: '/images/demo/AdaptiveScreen.jpg',
      code_link: 'https://github.com/joeyos/AdaptiveScreen',
      title: '网页自适应屏幕',
      core_tech: 'CSS3',
      description: '网页根据长宽比自适应屏幕尺寸'
    }, {
      demo_link: 'https://joeyos.github.io/ImgChange',
      img_link: '/images/demo/ImgChange.jpg',
      code_link: 'https://github.com/joeyos/ImgChange',
      title: '网页图片切换',
      core_tech: 'JavaScript',
      description: '图片自动切换或点击按钮切换'
    }, {
      demo_link: 'https://joeyos.github.io/3DPhoto',
      img_link: '/images/demo/3DPhoto.jpg',
      code_link: 'https://github.com/joeyos/3DPhoto',
      title: '网页三维图片切换',
      core_tech: 'CSS3',
      description: '百度前端学院三维图片切换'
    }, {
      demo_link: 'https://joeyos.github.io/AboutPage/',
      img_link: '/images/demo/AboutPage.jpg',
      code_link: 'https://github.com/joeyos/AboutPage',
      title: '网页圆角边框和阴影',
      core_tech: 'CSS3',
      description: '网页文本框设置圆角和阴影'
    }
  ];

  contentInit(demoContent) //内容初始化
  waitImgsLoad() //等待图片加载，并执行布局初始化
}());

/**
 * 内容初始化
 * @return {[type]} [description]
 */
function contentInit(content) {
  // var htmlArr = [];
  // for (var i = 0; i < content.length; i++) {
  //     htmlArr.push('
')
  //     htmlArr.push('')
  //     htmlArr.push('')
  //     htmlArr.push('')
  //     htmlArr.push('
')
  //     htmlArr.push(''+content[i].title+'')
  //     htmlArr.push('
')
  //     htmlArr.push('
Skills：'+content[i].core_tech+'
')
  //     htmlArr.push('
'+content[i].description)
  //     htmlArr.push('Code ')
  //     htmlArr.push('
')
  //     htmlArr.push('
')
  // }
  // var htmlStr = htmlArr.join('')
  var htmlStr = ''
  for (var i = 0; i < content.length; i++) {
    htmlStr += '
' + '   ' + '       ' + '   ' + '
' + '       ' + content[i].title + '' + '
' + '
Skills：' + content[i].core_tech + '
' + '
' + content[i].description + '
' + '
'
  }
  var grid = document.querySelector('.grid')
  grid.insertAdjacentHTML('afterbegin', htmlStr)
}

/**
 * 等待图片加载
 * @return {[type]} [description]
 */
function waitImgsLoad() {
  var imgs = document.querySelectorAll('.grid img')
  var totalImgs = imgs.length
  var count = 0
  //console.log(imgs)
  for (var i = 0; i < totalImgs; i++) {
    if (imgs[i].complete) {
      //console.log('complete');
      count++
    } else {
      imgs[i].onload = function() {
        // alert('onload')
        count++
        //console.log('onload' + count)
        if (count == totalImgs) {
          //console.log('onload---bbbbbbbb')
          initGrid()
        }
      }
    }
  }
  if (count == totalImgs) {
    //console.log('---bbbbbbbb')
    initGrid()
  }
}

/**
 * 初始化栅格布局
 * @return {[type]} [description]
 */
function initGrid() {
  var msnry = new Masonry('.grid', {
    // options
    itemSelector: '.grid-item',
    columnWidth: 250,
    isFitWidth: true,
    gutter: 20
  })
}
<commit_msg>modify<commit_after>/* jshint asi:true */
//先等图片都加载完成
//再执行布局函数

/**
 * 执行主函数
 * @param  {[type]} function( [description]
 * @return {[type]}           [description]
 */
(function() {

  /**
     * 内容JSON
     */
  var demoContent = [
	{
      demo_link: 'https://github.com/joeyos/QQ_Manager',
      img_link: '/images/demo/QQManager.jpg',
      code_link: 'https://github.com/joeyos/QQ_Manager',
      title: '腾讯电脑管家',
      core_tech: 'Qt & C++',
      description: '利用Qt制作的腾讯电脑管家界面'
    }, {
      demo_link: 'http://v.youku.com/v_show/id_XMjgyNDEwMjU0OA==.html?spm=a2h0k.8191407.0.0&from=s1.8-1-1.2',
      img_link: '/images/demo/Graduate.jpg',
      code_link: 'http://v.youku.com/v_show/id_XMjgyNDEwMjU0OA==.html?spm=a2h0k.8191407.0.0&from=s1.8-1-1.2',
      title: '毕业电子相册',
      core_tech: 'Ae & Edius',
      description: '献给悄悄流逝的大学四年时光'
    }, {
      demo_link: 'https://github.com/joeyos/LicensePlateRecognition',
      img_link: '/images/demo/LicensePlateRecognition.jpg',
      code_link: 'https://github.com/joeyos/LicensePlateRecognition',
      title: 'Matlab车牌识别',
      core_tech: 'Matlab',
      description: '用模板匹配法实现的车牌识别'
    }, {
      demo_link: 'https://github.com/joeyos/QQbyQt',
      img_link: '/images/demo/QQbyQt.jpg',
      code_link: 'https://github.com/joeyos/QQbyQt',
      title: 'QQ局域网聊天',
      core_tech: 'Qt & C++',
      description: '基于Qt实现的局域网聊天系统'
    }, {
      demo_link: 'https://github.com/joeyos/SAR-imaging',
      img_link: '/images/demo/SAR.jpg',
      code_link: 'https://github.com/joeyos/SAR-imaging',
      title: '合成孔径雷达成像',
      core_tech: 'Matlab',
      description: '几种传统雷达成像算法'
    }, {
      demo_link: 'https://joeyos.github.io/AdaptiveScreen',
      img_link: '/images/demo/AdaptiveScreen.jpg',
      code_link: 'https://github.com/joeyos/AdaptiveScreen',
      title: '网页自适应屏幕',
      core_tech: 'CSS3',
      description: '网页根据长宽比自适应屏幕尺寸'
    }, {
      demo_link: 'https://joeyos.github.io/ImgChange',
      img_link: '/images/demo/ImgChange.jpg',
      code_link: 'https://github.com/joeyos/ImgChange',
      title: '网页图片切换',
      core_tech: 'JavaScript',
      description: '图片自动切换或点击按钮切换'
    }, {
      demo_link: 'https://joeyos.github.io/3DPhoto',
      img_link: '/images/demo/3DPhoto.jpg',
      code_link: 'https://github.com/joeyos/3DPhoto',
      title: '网页三维图片切换',
      core_tech: 'CSS3',
      description: '百度前端学院三维图片切换'
    }, {
      demo_link: 'https://joeyos.github.io/AboutPage/',
      img_link: '/images/demo/AboutPage.jpg',
      code_link: 'https://github.com/joeyos/AboutPage',
      title: '网页圆角边框和阴影',
      core_tech: 'CSS3',
      description: '网页文本框设置圆角和阴影'
    }
  ];

  contentInit(demoContent) //内容初始化
  waitImgsLoad() //等待图片加载，并执行布局初始化
}());

/**
 * 内容初始化
 * @return {[type]} [description]
 */
function contentInit(content) {
  // var htmlArr = [];
  // for (var i = 0; i < content.length; i++) {
  //     htmlArr.push('
')
  //     htmlArr.push('')
  //     htmlArr.push('')
  //     htmlArr.push('')
  //     htmlArr.push('
')
  //     htmlArr.push(''+content[i].title+'')
  //     htmlArr.push('
')
  //     htmlArr.push('
Skills：'+content[i].core_tech+'
')
  //     htmlArr.push('
'+content[i].description)
  //     htmlArr.push('Code ')
  //     htmlArr.push('
')
  //     htmlArr.push('
')
  // }
  // var htmlStr = htmlArr.join('')
  var htmlStr = ''
  for (var i = 0; i < content.length; i++) {
    htmlStr += '
' + '   ' + '       ' + '   ' + '
' + '       ' + content[i].title + '' + '
' + '
Skills：' + content[i].core_tech + '
' + '
' + content[i].description + '
' + '
'
  }
  var grid = document.querySelector('.grid')
  grid.insertAdjacentHTML('afterbegin', htmlStr)
}

/**
 * 等待图片加载
 * @return {[type]} [description]
 */
function waitImgsLoad() {
  var imgs = document.querySelectorAll('.grid img')
  var totalImgs = imgs.length
  var count = 0
  //console.log(imgs)
  for (var i = 0; i < totalImgs; i++) {
    if (imgs[i].complete) {
      //console.log('complete');
      count++
    } else {
      imgs[i].onload = function() {
        // alert('onload')
        count++
        //console.log('onload' + count)
        if (count == totalImgs) {
          //console.log('onload---bbbbbbbb')
          initGrid()
        }
      }
    }
  }
  if (count == totalImgs) {
    //console.log('---bbbbbbbb')
    initGrid()
  }
}

/**
 * 初始化栅格布局
 * @return {[type]} [description]
 */
function initGrid() {
  var msnry = new Masonry('.grid', {
    // options
    itemSelector: '.grid-item',
    columnWidth: 250,
    isFitWidth: true,
    gutter: 20
  })
}
<|endoftext|>


<commit_before>(function() {

    var repoConfig = require('../custom_configFile.json');

    var getPosition = function(str, m, i) {
           return str.split(m, i).join(m).length;
    };

    var appDomain = (function() {
      var domain = repoConfig.domain;
      if (domain.match(/:/g).length > 1) {
         var indexOfPort = getPosition(domain, ":", 2);
         domain = domain.substr(0, indexOfPort);
      }

      return domain;
    })();

    var config = {

        DEBUG: false,
        RICH_LOG_ENABLED: false,

        // For embeds that require render, baseAppUrl will be used as the host.
        baseAppUrl: appDomain,
        relativeStaticUrl: "/r",

        SKIP_OEMBED_RE_LIST: [
            // /^https?:\/\/yourdomain\.com\//,
        ],

        port: repoConfig.linkDebuggingServicePort,

        // Optional SSL cert, if you serve under HTTPS.
        /*
        ssl: {
            key: require('fs').readFileSync(__dirname + '/key.pem'),
            cert: require('fs').readFileSync(__dirname + '/cert.pem'),
            port: 443
        },
        */

        /*
        Supported cache engines:
        - no-cache - no caching will be used.
        - node-cache - good for debug, node memory will be used (https://github.com/tcs-de/nodecache).
        - redis - https://github.com/mranney/node_redis.
        - memcached - https://github.com/3rd-Eden/node-memcached
        */
        CACHE_ENGINE: 'node-cache',
        CACHE_TTL: 0, // In milliseconds. 0 for 'never expire' to let cache engine decide itself when to evict the record

        /*
        // Redis cache options.
        REDIS_OPTIONS: {
            host: '127.0.0.1',
            port: 6379
        },
        */

        /*
        // Memcached options. See https://github.com/3rd-Eden/node-memcached#server-locations
        MEMCACHED_OPTIONS: {
            locations: "127.0.0.1:11211"
        }
        */

        // Access-Control-Allow-Origin list.
        allowedOrigins: [
            appDomain,
            appDomain + ':' + repoConfig.gulpDevExpressPort
        ],

        /*
        // Uncomment to enable plugin testing framework.
        tests: {
            mongodb: 'mongodb://localhost:27017/iframely-tests',
            single_test_timeout: 10 * 1000,
            plugin_test_period: 2 * 60 * 60 * 1000,
            relaunch_script_period: 5 * 60 * 1000
        },
        */

        // If there's no response from remote server, the timeout will occur after
        RESPONSE_TIMEOUT: 5 * 1000, //ms

        // Customize API calls to 3rd parties. At the very least - configure required keys.
        providerOptions: {
            "twitter.status": {
                "max-width": 550,
                "min-width": 250,
                consumer_key: 'INSERT YOUR VALUE',
                consumer_secret: 'INSERT YOUR VALUE',
                access_token: 'INSERT YOUR VALUE',
                access_token_secret: 'INSERT YOUR VALUE',
                hide_media: false,
                hide_thread: false,
                omit_script: false
            },
            flickr: {
                apiKey: 'INSERT YOUR VALUE'
            },
            "google.maps": {
            //  apiKey: 'INSERT YOUR VALUE' // not required, but recommended
            },
            readability: {
                enabled: false
            },
            images: {
                loadSize: false, // if true, will try an load first bytes of all images to get/confirm the sizes
                checkFavicon: false // if true, will verify all favicons
            },
            tumblr: {
                consumer_key: "INSERT YOUR VALUE"
            },
            google: {
                // https://developers.google.com/maps/documentation/embed/guide#api_key
                // yes, there is already "apiKey" option above, but I am not sure if old keys are the same as the news ones.
                maps_key: "INSERT YOUR VALUE"
            },

            /*
            // Optional Camo Proxy to wrap all images: https://github.com/atmos/camo
            camoProxy: {
                camo_proxy_key: "INSERT YOUR VALUE",
                camo_proxy_host: "INSERT YOUR VALUE"
            },
            */

            // List of query parameters to add to YouTube and Vimeo frames
            // Start it with leading "?". Or omit alltogether for default values
            // API key is optional, youtube will work without it too.
            // It is probably the same API key you use for Google Maps.
            youtube: {
                // api_key: "INSERT YOUR VALUE",
                get_params: "?rel=0&showinfo=1"     // https://developers.google.com/youtube/player_parameters
            },
            vimeo: {
                get_params: "?byline=0&badge=0"     // http://developer.vimeo.com/player/embedding
            }
        },

        // WHITELIST_WILDCARD, if present, will be added to whitelist as record for top level domain: "*"
        // with it, you can define what parsers do when they run accross unknown publisher.
        // If absent or empty, all generic media parsers will be disabled except for known domains
        // More about format: https://iframely.com/docs/qa-format

        /*
        WHITELIST_WILDCARD: {
              "twitter": {
                "player": "allow",
                "photo": "deny"
              },
              "oembed": {
                "video": "allow",
                "photo": "allow",
                "rich": "deny",
                "link": "deny"
              },
              "og": {
                "video": ["allow", "ssl", "responsive"]
              },
              "iframely": {
                "survey": "allow",
                "reader": "allow",
                "player": "allow",
                "image": "allow"
              },
              "html-meta": {
                "video": ["allow", "responsive"]
              }
        }
        */
    };

    module.exports = config;
})();
<commit_msg>Add CORS to allow port 3000 for gulp browsersync task<commit_after>(function() {

    var repoConfig = require('../custom_configFile.json');

    var getPosition = function(str, m, i) {
           return str.split(m, i).join(m).length;
    };

    var appDomain = (function() {
      var domain = repoConfig.domain;
      if (domain.match(/:/g).length > 1) {
         var indexOfPort = getPosition(domain, ":", 2);
         domain = domain.substr(0, indexOfPort);
      }

      return domain;
    })();

    var config = {

        DEBUG: false,
        RICH_LOG_ENABLED: false,

        // For embeds that require render, baseAppUrl will be used as the host.
        baseAppUrl: appDomain,
        relativeStaticUrl: "/r",

        SKIP_OEMBED_RE_LIST: [
            // /^https?:\/\/yourdomain\.com\//,
        ],

        port: repoConfig.linkDebuggingServicePort,

        // Optional SSL cert, if you serve under HTTPS.
        /*
        ssl: {
            key: require('fs').readFileSync(__dirname + '/key.pem'),
            cert: require('fs').readFileSync(__dirname + '/cert.pem'),
            port: 443
        },
        */

        /*
        Supported cache engines:
        - no-cache - no caching will be used.
        - node-cache - good for debug, node memory will be used (https://github.com/tcs-de/nodecache).
        - redis - https://github.com/mranney/node_redis.
        - memcached - https://github.com/3rd-Eden/node-memcached
        */
        CACHE_ENGINE: 'node-cache',
        CACHE_TTL: 0, // In milliseconds. 0 for 'never expire' to let cache engine decide itself when to evict the record

        /*
        // Redis cache options.
        REDIS_OPTIONS: {
            host: '127.0.0.1',
            port: 6379
        },
        */

        /*
        // Memcached options. See https://github.com/3rd-Eden/node-memcached#server-locations
        MEMCACHED_OPTIONS: {
            locations: "127.0.0.1:11211"
        }
        */

        // Access-Control-Allow-Origin list.
        allowedOrigins: [
            appDomain,
            appDomain + ':' + repoConfig.gulpDevExpressPort,
	    appDomain + ':3000'
        ],

        /*
        // Uncomment to enable plugin testing framework.
        tests: {
            mongodb: 'mongodb://localhost:27017/iframely-tests',
            single_test_timeout: 10 * 1000,
            plugin_test_period: 2 * 60 * 60 * 1000,
            relaunch_script_period: 5 * 60 * 1000
        },
        */

        // If there's no response from remote server, the timeout will occur after
        RESPONSE_TIMEOUT: 5 * 1000, //ms

        // Customize API calls to 3rd parties. At the very least - configure required keys.
        providerOptions: {
            "twitter.status": {
                "max-width": 550,
                "min-width": 250,
                consumer_key: 'INSERT YOUR VALUE',
                consumer_secret: 'INSERT YOUR VALUE',
                access_token: 'INSERT YOUR VALUE',
                access_token_secret: 'INSERT YOUR VALUE',
                hide_media: false,
                hide_thread: false,
                omit_script: false
            },
            flickr: {
                apiKey: 'INSERT YOUR VALUE'
            },
            "google.maps": {
            //  apiKey: 'INSERT YOUR VALUE' // not required, but recommended
            },
            readability: {
                enabled: false
            },
            images: {
                loadSize: false, // if true, will try an load first bytes of all images to get/confirm the sizes
                checkFavicon: false // if true, will verify all favicons
            },
            tumblr: {
                consumer_key: "INSERT YOUR VALUE"
            },
            google: {
                // https://developers.google.com/maps/documentation/embed/guide#api_key
                // yes, there is already "apiKey" option above, but I am not sure if old keys are the same as the news ones.
                maps_key: "INSERT YOUR VALUE"
            },

            /*
            // Optional Camo Proxy to wrap all images: https://github.com/atmos/camo
            camoProxy: {
                camo_proxy_key: "INSERT YOUR VALUE",
                camo_proxy_host: "INSERT YOUR VALUE"
            },
            */

            // List of query parameters to add to YouTube and Vimeo frames
            // Start it with leading "?". Or omit alltogether for default values
            // API key is optional, youtube will work without it too.
            // It is probably the same API key you use for Google Maps.
            youtube: {
                // api_key: "INSERT YOUR VALUE",
                get_params: "?rel=0&showinfo=1"     // https://developers.google.com/youtube/player_parameters
            },
            vimeo: {
                get_params: "?byline=0&badge=0"     // http://developer.vimeo.com/player/embedding
            }
        },

        // WHITELIST_WILDCARD, if present, will be added to whitelist as record for top level domain: "*"
        // with it, you can define what parsers do when they run accross unknown publisher.
        // If absent or empty, all generic media parsers will be disabled except for known domains
        // More about format: https://iframely.com/docs/qa-format

        /*
        WHITELIST_WILDCARD: {
              "twitter": {
                "player": "allow",
                "photo": "deny"
              },
              "oembed": {
                "video": "allow",
                "photo": "allow",
                "rich": "deny",
                "link": "deny"
              },
              "og": {
                "video": ["allow", "ssl", "responsive"]
              },
              "iframely": {
                "survey": "allow",
                "reader": "allow",
                "player": "allow",
                "image": "allow"
              },
              "html-meta": {
                "video": ["allow", "responsive"]
              }
        }
        */
    };

    module.exports = config;
})();
<|endoftext|>


<commit_before>$( document ).ready(function() {
    /* slide transitions */
    var pauseTime = 4000;
    var transitionTime = 3000;
    var initialTimeout = window.setTimeout(fadeOutSlide1, pauseTime);
    var slideCompleted = new Array();
    var lightningTravelTime = 3000;
    var lightningWaitTime = 1000;
    var thisLightning;
    var thisLightningWidth;
    var lightningCounter = 1;

    function fadeOutSlide1(){
    	fadeOut($("#slide-1"));
    	reveal($("#slide-2"));
    	var afterSlide1Timeout = window.setTimeout(revealSlide3, pauseTime);
    }

    function revealSlide3(){
    	reveal($("#slide-3"));
        var afterSlide3Timeout = window.setTimeout(revealBubble, pauseTime*2);
    }

    function revealBubble(){
        reveal($("#bubble"));
    }

    function fadeOut(target){
    	target.fadeTo(transitionTime,0,'swing',
    		function(){
    			target.addClass('hidden');
    		}
    	);
    }

    function reveal(target){
    	//target.removeClass('hidden');
    	target.fadeTo(transitionTime,1,'swing', function(){

            //add this slide id to the array listing completed slide names
            slideCompleted.push(target[0].id);
        });
    }

    /*lightning*/
    var lightning = new Array();

    	/*prototype lightning definition*/
	lightning.push($(".lightning"));
    var w0 = parseInt(lightning[0].css("width"), 10);
    var h0 = parseInt(lightning[0].css("height"), 10);
    var minWidth = w0 / 4;
    /* initial left position of prototype lightning*/
    var l0 = parseInt(lightning[0].css("left"));

    /*spawning and moving next lightning*/
    function newLightning(){
        thisLightning = lightning[0].clone();
        lightning.push(thisLightning);

        thisLightningWidth = getRandomInt(minWidth, w0);

        thisLightning.css("width", thisLightningWidth);
        thisLightning.css("height", thisLightningWidth / (w0/h0));
        thisLightning.css("top", getRandomInt(0, windowHeight)*1.5);
        thisLightning.attr('id', 'lightning-'+lightningCounter);

        thisLightning.appendTo(lightning[0].parent());

        //moving it after creating it
        thisLightning.animate({left: windowWidth}, lightningTravelTime*(thisLightningWidth/w0), 'swing', function(){
            //remove this lightning from DOM
            this.remove();
            //remove this lightning from array
            lightning.splice($.inArray(thisLightning, lightning),1);
        });

        lightningCounter ++;

        //run again after random time
        window.setTimeout(newLightning, getRandomInt(0,lightningWaitTime));
    }

    //make the next lightning

    //remove if no longer needed
    function moveLightning(){
        $.each(lightning, function(key, value){
            //skip the first one, as it will remain as the prototype
            if(key > 0){
                this.animate({left: windowWidth}, lightningTravelTime*(this[0].width/w0), 'swing');
            }
        });
    }

    // run this function only once. Start the lightning moving and get rid of the functions to reposition the speech bubble
    $('#kepler a').one( 'click', function(){
        //$window.off('resize');
        $window.off('scroll');
        fadeOut($('#bubble'));
        //moveLightning();
        newLightning();
        //newLightning();
        $('#keplerImg').unwrap();

        //track google analytics event
        ga('send', 'event', 'Kepler', 'click', 'Easter Eggs');

        //don't follow the link
        return false;
    });

    	/*reusable generic functions*/
    function getRandomInt (min, max) {
	    return Math.floor(Math.random()*(max-min+1)+min);
	}

    /*positioning bubble*/
    var $window = $(window),
        $bubble = $('#bubble'),
        windowHeight,
        windowWidth,
        bubbleTop;

    function recalculateWindow(){
        windowHeight = $window.height();
        windowWidth = $window.width();
        bubbleTop = $bubble.offset().top;
        console.log('recalculate ran');
    }

    function toggleOffscreen(){
        $bubble.toggleClass('offscreen', ($window.scrollTop() + windowHeight) < bubbleTop);
        console.log('scroll ran');
    }

    // run recalculate once on start
    recalculateWindow();
    //run recalculate again on each window resize
    $window.on('resize', recalculateWindow);

    //run toggleOffscreen on each scroll event
    $window.on('scroll', toggleOffscreen);

});
<commit_msg>removing console logs<commit_after>$( document ).ready(function() {
    /* slide transitions */
    var pauseTime = 4000;
    var transitionTime = 3000;
    var initialTimeout = window.setTimeout(fadeOutSlide1, pauseTime);
    var slideCompleted = new Array();
    var lightningTravelTime = 3000;
    var lightningWaitTime = 1000;
    var thisLightning;
    var thisLightningWidth;
    var lightningCounter = 1;

    function fadeOutSlide1(){
    	fadeOut($("#slide-1"));
    	reveal($("#slide-2"));
    	var afterSlide1Timeout = window.setTimeout(revealSlide3, pauseTime);
    }

    function revealSlide3(){
    	reveal($("#slide-3"));
        var afterSlide3Timeout = window.setTimeout(revealBubble, pauseTime*2);
    }

    function revealBubble(){
        reveal($("#bubble"));
    }

    function fadeOut(target){
    	target.fadeTo(transitionTime,0,'swing',
    		function(){
    			target.addClass('hidden');
    		}
    	);
    }

    function reveal(target){
    	//target.removeClass('hidden');
    	target.fadeTo(transitionTime,1,'swing', function(){

            //add this slide id to the array listing completed slide names
            slideCompleted.push(target[0].id);
        });
    }

    /*lightning*/
    var lightning = new Array();

    	/*prototype lightning definition*/
	lightning.push($(".lightning"));
    var w0 = parseInt(lightning[0].css("width"), 10);
    var h0 = parseInt(lightning[0].css("height"), 10);
    var minWidth = w0 / 4;
    /* initial left position of prototype lightning*/
    var l0 = parseInt(lightning[0].css("left"));

    /*spawning and moving next lightning*/
    function newLightning(){
        thisLightning = lightning[0].clone();
        lightning.push(thisLightning);

        thisLightningWidth = getRandomInt(minWidth, w0);

        thisLightning.css("width", thisLightningWidth);
        thisLightning.css("height", thisLightningWidth / (w0/h0));
        thisLightning.css("top", getRandomInt(0, windowHeight)*1.5);
        thisLightning.attr('id', 'lightning-'+lightningCounter);

        thisLightning.appendTo(lightning[0].parent());

        //moving it after creating it
        thisLightning.animate({left: windowWidth}, lightningTravelTime*(thisLightningWidth/w0), 'swing', function(){
            //remove this lightning from DOM
            this.remove();
            //remove this lightning from array
            lightning.splice($.inArray(thisLightning, lightning),1);
        });

        lightningCounter ++;

        //run again after random time
        window.setTimeout(newLightning, getRandomInt(0,lightningWaitTime));
    }

    //make the next lightning

    //remove if no longer needed
    function moveLightning(){
        $.each(lightning, function(key, value){
            //skip the first one, as it will remain as the prototype
            if(key > 0){
                this.animate({left: windowWidth}, lightningTravelTime*(this[0].width/w0), 'swing');
            }
        });
    }

    // run this function only once. Start the lightning moving and get rid of the functions to reposition the speech bubble
    $('#kepler a').one( 'click', function(){
        //$window.off('resize');
        $window.off('scroll');
        fadeOut($('#bubble'));
        //moveLightning();
        newLightning();
        //newLightning();
        $('#keplerImg').unwrap();

        //track google analytics event
        ga('send', 'event', 'Kepler', 'click', 'Easter Eggs');

        //don't follow the link
        return false;
    });

    	/*reusable generic functions*/
    function getRandomInt (min, max) {
	    return Math.floor(Math.random()*(max-min+1)+min);
	}

    /*positioning bubble*/
    var $window = $(window),
        $bubble = $('#bubble'),
        windowHeight,
        windowWidth,
        bubbleTop;

    function recalculateWindow(){
        windowHeight = $window.height();
        windowWidth = $window.width();
        bubbleTop = $bubble.offset().top;
        //console.log('recalculate ran');
    }

    function toggleOffscreen(){
        $bubble.toggleClass('offscreen', ($window.scrollTop() + windowHeight) < bubbleTop);
        //console.log('scroll ran');
    }

    // run recalculate once on start
    recalculateWindow();
    //run recalculate again on each window resize
    $window.on('resize', recalculateWindow);

    //run toggleOffscreen on each scroll event
    $window.on('scroll', toggleOffscreen);

});
<|endoftext|>


<commit_before>let perso = {
        name: "",
        items: [],
        money: 0,
        hp: 100,
        mp: 5,
    }
    //FORM
document.body.querySelector("form").addEventListener("submit", function(e) {
    e.preventDefault();
    perso.name = document.body.querySelector("#name").value
    document.body.querySelector("#head").style.opacity = 0;
    setTimeout(function() {
        document.body.querySelector("header").remove();
    }, 1000);
    //Load main
    setTimeout(function() {
        console.log("faded");
        console.log("Loading...")
            //000000000000000000000000000000000000
        Crafty.init();

        Crafty.sprite(128, "http://craftyjs.com/demos/isometric/images/sprite.png", {
            grass: [0, 0, 1, 1],
            stone: [1, 0, 1, 1]
        });

        iso = Crafty.isometric.size(128);
        var z = 0;
        for (var i = 20; i >= 0; i--) {
            for (var y = 0; y < 20; y++) {
                var which = Crafty.math.randomInt(0, 1);
                var tile = Crafty.e("2D, Canvas, " + (!which ? "grass" : "stone") + ", Mouse")
                    .attr('z', i + 1 * y + 1)
                    .areaMap([64, 0], [128, 32], [128, 96], [64, 128], [0, 96], [0, 32])
                    .bind("Click", function(e) {
                        //destroy on right click
                        //right click seems not work in Mac OS
                        //delete it
                        console.log(e.button);
                        /*if(e.button === 2)*/
                        this.destroy();
                    })
                    .bind("MouseOver", function() {
                        if (this.has("grass")) {
                            this.sprite(0, 1, 1, 1);
                        } else {
                            this.sprite(1, 1, 1, 1);
                        }
                    }).bind("MouseOut", function() {
                        if (this.has("grass")) {
                            this.sprite(0, 0, 1, 1);
                        } else {
                            this.sprite(1, 0, 1, 1);
                        }
                    });

                iso.place(i, y, 0, tile);
            }
        }

        Crafty.addEvent(this, Crafty.stage.elem, "mousedown", function(e) {
            if (e.button > 1) return;
            var base = { x: e.clientX, y: e.clientY };

            function scroll(e) {
                var dx = base.x - e.clientX,
                    dy = base.y - e.clientY;
                base = { x: e.clientX, y: e.clientY };
                Crafty.viewport.x -= dx;
                Crafty.viewport.y -= dy;
            };

            Crafty.addEvent(this, Crafty.stage.elem, "mousemove", scroll);
            Crafty.addEvent(this, Crafty.stage.elem, "mouseup", function() {
                Crafty.removeEvent(this, Crafty.stage.elem, "mousemove", scroll);
            });
        });
        //000000000000000000000000000000000000
    }, 1000);

});
//FORM END
//CANVAS
function init() {
    /*
    let canvas = document.body.querySelector("canvas");
    let c = canvas.getContext("2d");
    c.fillStyle = "white";
    c.fillRect(0, 0, canvas.width, canvas.height);
    c.fillStyle = "black";
    c.font = "30px Oswald"
    c.fillText("Hello" + perso.name, 100, 100)
    */
    Crafty.init();
    // A blue block, controlled by arrow keys
    var player = Crafty.e("2D, Canvas, Color, Fourway")
        .attr({ x: 100, y: 100, w: 50, h: 50 })
        .color("blue")
        .fourway(2);
    console.log("loaded")
}
//CANVAS END
//http://craftyjs.com/#install
//http://craftyjs.com/demos/isometric/
//http://craftyjs.com/api/Crafty-isometric.html<commit_msg>garbage<commit_after>let perso = {
        name: "",
        items: [],
        money: 0,
        hp: 100,
        mp: 5,
    }
    //FORM
document.body.querySelector("form").addEventListener("submit", function(e) {
    e.preventDefault();
    perso.name = document.body.querySelector("#name").value
    document.body.querySelector("#head").style.opacity = 0;
    setTimeout(function() {
        document.body.querySelector("header").remove();
    }, 1000);
    //Load main
    setTimeout(function() {
        console.log("faded");
        console.log("Loading...")
            //0000000000000000000000000000000000001
        Crafty.init();

        Crafty.sprite(128, "http://craftyjs.com/demos/isometric/images/sprite.png", {
            grass: [0, 0, 1, 1],
            stone: [1, 0, 1, 1]
        });

        iso = Crafty.isometric.size(128);
        var z = 0;
        for (var i = 20; i >= 0; i--) {
            for (var y = 0; y < 20; y++) {
                var which = Crafty.math.randomInt(0, 1);
                var tile = Crafty.e("2D, Canvas, " + (!which ? "grass" : "stone") + ", Mouse")
                    .attr('z', i + 1 * y + 1)
                    .areaMap([64, 0], [128, 32], [128, 96], [64, 128], [0, 96], [0, 32])
                    .bind("Click", function(e) {
                        //destroy on right click
                        //right click seems not work in Mac OS
                        //delete it
                        console.log(e.button);
                        /*if(e.button === 2)*/
                        this.destroy();
                    })
                    .bind("MouseOver", function() {
                        if (this.has("grass")) {
                            this.sprite(0, 1, 1, 1);
                        } else {
                            this.sprite(1, 1, 1, 1);
                        }
                    }).bind("MouseOut", function() {
                        if (this.has("grass")) {
                            this.sprite(0, 0, 1, 1);
                        } else {
                            this.sprite(1, 0, 1, 1);
                        }
                    });

                iso.place(i, y, 0, tile);
            }
        }

        Crafty.addEvent(this, Crafty.stage.elem, "mousedown", function(e) {
            if (e.button > 1) return;
            var base = { x: e.clientX, y: e.clientY };

            function scroll(e) {
                var dx = base.x - e.clientX,
                    dy = base.y - e.clientY;
                base = { x: e.clientX, y: e.clientY };
                Crafty.viewport.x -= dx;
                Crafty.viewport.y -= dy;
            };

            Crafty.addEvent(this, Crafty.stage.elem, "mousemove", scroll);
            Crafty.addEvent(this, Crafty.stage.elem, "mouseup", function() {
                Crafty.removeEvent(this, Crafty.stage.elem, "mousemove", scroll);
            });
        });
        //000000000000000000000000000000000000
    }, 1000);

});
//FORM END
//CANVAS
function init() {
    /*
    let canvas = document.body.querySelector("canvas");
    let c = canvas.getContext("2d");
    c.fillStyle = "white";
    c.fillRect(0, 0, canvas.width, canvas.height);
    c.fillStyle = "black";
    c.font = "30px Oswald"
    c.fillText("Hello" + perso.name, 100, 100)
    */
    Crafty.init();
    // A blue block, controlled by arrow keys
    var player = Crafty.e("2D, Canvas, Color, Fourway")
        .attr({ x: 100, y: 100, w: 50, h: 50 })
        .color("blue")
        .fourway(2);
    console.log("loaded")
}
//CANVAS END
//http://craftyjs.com/#install
//http://craftyjs.com/demos/isometric/
//http://craftyjs.com/api/Crafty-isometric.html<|endoftext|>


<commit_before>$(document).ready(function () {
  var $up = $('.plus'),
    $down = $('.minus'),
    $minutes = $('.clock-wrapper .clock .minutes'),
    $seconds = $('.clock-wrapper .clock .seconds'),
    $reset = $('.controls .reset'),
    $play = $('.controls .play'),
    $pause = $('.controls .pause'),
    seconds = 60,
    minutes = 25,
    $checks = $('.tasks .glyphicon'),
    clockID;

  function init() {
    $minutes.text(minutes);
    $seconds.text("00");
  }
  init();

  function completed() {
    $(this).toggleClass('glyphicon-remove');
    $(this).toggleClass('glyphicon-ok');

  }

  function changeTimer() {
    seconds--;
    $seconds.text(seconds);
    if (minutes === 0 && seconds <= 0) {
      // or run break when ready.
      resetTimer();
    } else if (seconds <= 0 && minutes > 0) {
      seconds = 60;
      minutes--;
      $minutes.text(minutes);
    }
  }

  function startTimer() {
    // disable other buttons
    $('.timer .btn').attr("disabled", true);
    minutes--;
    $minutes.text(minutes);
    changeTimer();
    clockID = setInterval(changeTimer, 1000);

  }

  function pauseTimer() {
    $('.timer .btn').attr("disabled", false);
    clearInterval(clockID);
    minutes++;
  }

  function increaseTimer() {
    minutes++;
    $minutes.text(minutes);
    $seconds.text("00");
  }

  function decreaseTimer() {
    minutes--;
    $minutes.text(minutes);
    $seconds.text("00");
  }

  function resetTimer() {
    clearInterval(clockID);
    $('.timer .btn').attr("disabled", false);
    minutes = 25;
    seconds = 60;
    $minutes.text(minutes);
    $seconds.text("00");

  }

  $play.click(startTimer);
  $pause.click(pauseTimer);
  $reset.click(resetTimer);
  $up.click(increaseTimer);
  $down.click(decreaseTimer);
  $checks.click(completed);

});<commit_msg>Have the app working. Have to change when the plus and minus are hit to reset the seconds variable.<commit_after>$(document).ready(function () {
  var $up = $('.plus'),
    $down = $('.minus'),
    $minutes = $('.clock-wrapper .clock .minutes'),
    $seconds = $('.clock-wrapper .clock .seconds'),
    $reset = $('.controls .reset'),
    $play = $('.controls .play'),
    $pause = $('.controls .pause'),
    seconds = 60,
    minutes = 25,
    $checks = $('.tasks .glyphicon'),
    clockID;

  function init() {
    $minutes.text(minutes);
    $seconds.text("00");
  }
  init();

  function completed() {
    $(this).toggleClass('glyphicon-remove');
    $(this).toggleClass('glyphicon-ok');

  }

  function changeTimer() {
    seconds--;
    $seconds.text(seconds);
    if (minutes === 0 && seconds <= 0) {
      // or run break when ready.
      resetTimer();
    } else if (seconds <= 0 && minutes > 0) {
      seconds = 60;
      minutes--;
      $minutes.text(minutes);
    }
  }

  function startTimer() {
    // disable other buttons
    $('.timer .btn').attr("disabled", true);
    $minutes.text(minutes - 1);
    changeTimer();
    clockID = setInterval(changeTimer, 1000);

  }

  function pauseTimer() {
    $('.timer .btn').attr("disabled", false);
    clearInterval(clockID);
  }

  function increaseTimer() {
    minutes++;
    $minutes.text(minutes);
    $seconds.text("00");
  }

  function decreaseTimer() {
    minutes--;
    $minutes.text(minutes);
    $seconds.text("00");
  }

  function resetTimer() {
    clearInterval(clockID);
    $('.timer .btn').attr("disabled", false);
    minutes = 25;
    seconds = 60;
    $minutes.text(minutes);
    $seconds.text("00");

  }

  $play.click(startTimer);
  $pause.click(pauseTimer);
  $reset.click(resetTimer);
  $up.click(increaseTimer);
  $down.click(decreaseTimer);
  $checks.click(completed);

});<|endoftext|>


<commit_before>
/*! GetDevicePixelRatio | Author: Tyson Matanich, 2012 | License: MIT */ (function(n){n.getDevicePixelRatio=function(){var t=1;return n.screen.systemXDPI!==undefined&&n.screen.logicalXDPI!==undefined&&n.screen.systemXDPI>n.screen.logicalXDPI?t=n.screen.systemXDPI/n.screen.logicalXDPI:n.devicePixelRatio!==undefined&&(t=n.devicePixelRatio),t}})(this);
var IOS = /(iPad|iPhone|iPod)/g.test(navigator.userAgent);
var ANDROID = /android/gi.test(navigator.userAgent);

var SLIDES = {
	home: 1,
	chat: 2,
	achievments: 3,
	progress: 4,
	world: 5
}
var PREVENT_MOVE = false;

// Slider de los screenshots
function sliderScreenshots(elems){
	var self = this;
	var delay = 3000;

	this.position = elems.length * 200;
	this.elems = elems;
	this.timeout = null;

	this.next = function(n){
		var n = n ? n : 1;
		this.position += n;
		var p = this.position % this.elems.length;
		var ps = (this.position - 2) % this.elems.length;

		this.elems
			.removeClass("active")
			.eq(p)
			.addClass("active");

		if(p == 4){
			var i = -1;
			while(++i != 3)
				this.elems
					.parent()
					.append(this.elems.eq(i));
		}else if([0,1].indexOf(p) != -1){
			this.elems
				.parent()
				.append(this.elems.eq(ps));
		}

		this.nextTimeout();
	}
	this.prev = function(){
		this.next(-1);
	}

	this.nextTimeout = function(){
		clearTimeout(this.timeout);
		this.timeout = setTimeout(function(){
			self.next();
		}, delay);
	}

	$('.arrowL').click(function(){self.prev()});
	$('.arrowR').click(function(){self.next()});
	this.nextTimeout();
}

// Animar el chat a la entrada
function animateChat(){
	if($("#chatting li.noAnimate").length)
		return;
	$("#chatting li").eq(0)
		.addClass("firstAnimate")
		.addClass("noAnimate");
	setTimeout(function(){
		$("#chatting li").eq(0).removeClass("firstAnimate");
	}, 2200);
}

// Slider de logros
function initAchievements(elems, delay){
	var self = this;

	this.actual = 0;
	this.elems = elems;
	this.n = elems.length;
	this.nextTime;
	this.delay = delay;

	this.next = function(){
		clearTimeout(this.nextTime);
		this.elems
			.removeClass('visible')
			.eq(++this.actual % this.n)
			.addClass('visible');
		this.sleep();
	}
	this.sleep = function(){
		this.nextTime = setTimeout(function(){
			self.next();
		}, this.delay);
	}
	this.click = function(){
		if(480 > Math.min($(document).width(), $(document).height()))
			this.next();
	}

	this.elems.eq(0).parent()
		.click(function(){
			self.click();
		});
	this.sleep();
}

//Barra de progreso
function progressBar(initial){
	this.initial = initial;
	this.initialized = false;

	this.init = function(){
		if(this.initialized)
			return;
		this.initialized = true;
		var be = BezierEasing(0.4, 0.4, 0, 0.9);
		var fps = 30;
		var time = 6; // seconds
		var actualFrame = (time * this.initial / 100) * fps;
		var totalFrames = fps * time;

		$('#circle .number').text(this.initial);

		var nextFrame = function(){
			actualFrame++;

			var progress = ~~(100 * be(actualFrame / totalFrames));

			$('#circle').circleProgress({
				value: be(actualFrame / totalFrames)
			});

			$('#circle .number').text(progress);

			if(progress == 100){
				clearInterval(interval);
				$('.circleProgress').addClass("complete");
				$(document.body).addClass("progressComplete");
				$('#circle').circleProgress({
					value: 1
				});
			}
		};

		var interval = setInterval(nextFrame, 1000 / fps);
	}
}

// Control del tamaño de los puntos del mapa y la animación de las banderas
function worldControl(){
	var self = this;
	this.worldPattern = $('#worldPattern');
	this.flags = $('.worldFlags .flag');

	this.setPatternSize = function(){
		var ww = $(document.body).width();
		var wh = $(document.body).height();
		var size = Math.round((15 - (ww / 100)) * (ww > 800 ? 1 : 0.5));
		if(size < 4)
			size = 4;
		if(wh <= 440 || ww <=440)
			size = 8;
		this.worldPattern
			.attr("width", size)
			.attr("height", size);
	}
	this.showFlag = function(){
		var flags = $('.worldFlags .flag.hidden')
		var n = Math.floor(flags.length * Math.random());
		flags
			.eq(n)
			.removeClass("hidden");
		if(!flags.length){
			this.flags
				.removeClass("fadeIn");
			this.moveRandomFlag();
			return;
		}
		setTimeout(function(){
			self.showFlag();
		}, 500);
	}
	this.moveRandomFlag = function(){
		var flags = $('.worldFlags .flag')
		var n = Math.floor(flags.length * Math.random());
		flags
			.eq(n)
			.addClass("flagSwift");
		setTimeout(function(){
			$(".flagSwift")
				.removeClass("flagSwift");
		}, 1000);
		setTimeout(function(){
			self.moveRandomFlag();
		}, 1000 + (Math.random() * 4000));
	}

	this.init = function(){
		setTimeout(function(){
			self.showFlag();
		}, 500);
	}

	this.setPatternSize();
	$(window).resize(function() {
		self.setPatternSize();
	});
}

$(document).ready(function() {
	var inicialCircleValue = 12;
	var achievementsDelay = 4000;

	var progressBarObj = null;
	var worldControlObj = null;

	$('#fullpage').fullpage({
		anchors: ['QuitNow', 'Chat', 'Achievements', 'Health', 'Downloads'],
		sectionsColor: ['#3d91e6', '#eac850', '#6aad5d', '#d55c3f', '#3a5269', '#EAE1C0'],
		slidesNavigation: true,
		navigation: true,
		navigationPosition: 'right',
        scrollOverflow: false,
        css3: true,
		//navigationTooltips: ['First', 'Second', 'Third'],
		afterLoad: function(anchorLink, index){
			switch(index){
				case SLIDES.home: $('.home').removeClass('hideScreenshots'); break;
			}
		},
		onLeave: function(index, nextIndex, direction){
			$("#section4").scrollTop(0);
			switch(nextIndex){
				case SLIDES.chat: animateChat(); break;
				case SLIDES.progress: progressBarObj.init(); break;
				case SLIDES.world: worldControlObj.init(); break;
			}
		}
	});

	var pixelRatio = window.getDevicePixelRatio();

	$('#circle').circleProgress({
		value: inicialCircleValue / 100,
		startAngle: -Math.PI / 2,
		size: 320 * pixelRatio,
		emptyFill: "#792f1d",
		thickness: 20 * pixelRatio,
		animation: false,
		fill: {
			color: "#fff"
		}
	});

	if(IOS)
		$(document.body).addClass("appleDevice");

	$(".screen")
		.parent().hide();
	if(IOS){
		new sliderScreenshots($(".screen.apple"));
		$(".screen.apple")
			.parent().show();
	}else if(ANDROID){
		new sliderScreenshots($(".screen.android"));
		$(".screen.android")
			.parent().show();
	}else{
		new sliderScreenshots($(".screen.desktop"));
		$(".screen.desktop")
			.parent().show();
	}

	progressBarObj = new progressBar(inicialCircleValue);
	worldControlObj =  new worldControl();
	new initAchievements($("#achiev div"), achievementsDelay);
	new ElastiStack( $("#chatting").get(0), {
		distDragBack : 100,
		distDragMax : 200
	});
});

(function () {
	window.addEventListener('DOMContentLoaded', function (e) {
		var termsShow = document.getElementById('TermsShow');
		termsShow.addEventListener('click', function (e) {
			e.preventDefault();
			$('.js-Terms .wrapper').load('./terms-of-service/index.html .content');
			$('.js-Terms').addClass('show');
		});
		var termsHide = document.getElementById('TermsHide');
		termsHide.addEventListener('click', function (e) {
			e.preventDefault();
			$('.js-Terms .wrapper').html('');
			$('.js-Terms').removeClass('show');
		});
	});
})()
<commit_msg>Added keyup esc for close terms of service 😎<commit_after>
/*! GetDevicePixelRatio | Author: Tyson Matanich, 2012 | License: MIT */ (function(n){n.getDevicePixelRatio=function(){var t=1;return n.screen.systemXDPI!==undefined&&n.screen.logicalXDPI!==undefined&&n.screen.systemXDPI>n.screen.logicalXDPI?t=n.screen.systemXDPI/n.screen.logicalXDPI:n.devicePixelRatio!==undefined&&(t=n.devicePixelRatio),t}})(this);
var IOS = /(iPad|iPhone|iPod)/g.test(navigator.userAgent);
var ANDROID = /android/gi.test(navigator.userAgent);

var SLIDES = {
	home: 1,
	chat: 2,
	achievments: 3,
	progress: 4,
	world: 5
}
var PREVENT_MOVE = false;

// Slider de los screenshots
function sliderScreenshots(elems){
	var self = this;
	var delay = 3000;

	this.position = elems.length * 200;
	this.elems = elems;
	this.timeout = null;

	this.next = function(n){
		var n = n ? n : 1;
		this.position += n;
		var p = this.position % this.elems.length;
		var ps = (this.position - 2) % this.elems.length;

		this.elems
			.removeClass("active")
			.eq(p)
			.addClass("active");

		if(p == 4){
			var i = -1;
			while(++i != 3)
				this.elems
					.parent()
					.append(this.elems.eq(i));
		}else if([0,1].indexOf(p) != -1){
			this.elems
				.parent()
				.append(this.elems.eq(ps));
		}

		this.nextTimeout();
	}
	this.prev = function(){
		this.next(-1);
	}

	this.nextTimeout = function(){
		clearTimeout(this.timeout);
		this.timeout = setTimeout(function(){
			self.next();
		}, delay);
	}

	$('.arrowL').click(function(){self.prev()});
	$('.arrowR').click(function(){self.next()});
	this.nextTimeout();
}

// Animar el chat a la entrada
function animateChat(){
	if($("#chatting li.noAnimate").length)
		return;
	$("#chatting li").eq(0)
		.addClass("firstAnimate")
		.addClass("noAnimate");
	setTimeout(function(){
		$("#chatting li").eq(0).removeClass("firstAnimate");
	}, 2200);
}

// Slider de logros
function initAchievements(elems, delay){
	var self = this;

	this.actual = 0;
	this.elems = elems;
	this.n = elems.length;
	this.nextTime;
	this.delay = delay;

	this.next = function(){
		clearTimeout(this.nextTime);
		this.elems
			.removeClass('visible')
			.eq(++this.actual % this.n)
			.addClass('visible');
		this.sleep();
	}
	this.sleep = function(){
		this.nextTime = setTimeout(function(){
			self.next();
		}, this.delay);
	}
	this.click = function(){
		if(480 > Math.min($(document).width(), $(document).height()))
			this.next();
	}

	this.elems.eq(0).parent()
		.click(function(){
			self.click();
		});
	this.sleep();
}

//Barra de progreso
function progressBar(initial){
	this.initial = initial;
	this.initialized = false;

	this.init = function(){
		if(this.initialized)
			return;
		this.initialized = true;
		var be = BezierEasing(0.4, 0.4, 0, 0.9);
		var fps = 30;
		var time = 6; // seconds
		var actualFrame = (time * this.initial / 100) * fps;
		var totalFrames = fps * time;

		$('#circle .number').text(this.initial);

		var nextFrame = function(){
			actualFrame++;

			var progress = ~~(100 * be(actualFrame / totalFrames));

			$('#circle').circleProgress({
				value: be(actualFrame / totalFrames)
			});

			$('#circle .number').text(progress);

			if(progress == 100){
				clearInterval(interval);
				$('.circleProgress').addClass("complete");
				$(document.body).addClass("progressComplete");
				$('#circle').circleProgress({
					value: 1
				});
			}
		};

		var interval = setInterval(nextFrame, 1000 / fps);
	}
}

// Control del tamaño de los puntos del mapa y la animación de las banderas
function worldControl(){
	var self = this;
	this.worldPattern = $('#worldPattern');
	this.flags = $('.worldFlags .flag');

	this.setPatternSize = function(){
		var ww = $(document.body).width();
		var wh = $(document.body).height();
		var size = Math.round((15 - (ww / 100)) * (ww > 800 ? 1 : 0.5));
		if(size < 4)
			size = 4;
		if(wh <= 440 || ww <=440)
			size = 8;
		this.worldPattern
			.attr("width", size)
			.attr("height", size);
	}
	this.showFlag = function(){
		var flags = $('.worldFlags .flag.hidden')
		var n = Math.floor(flags.length * Math.random());
		flags
			.eq(n)
			.removeClass("hidden");
		if(!flags.length){
			this.flags
				.removeClass("fadeIn");
			this.moveRandomFlag();
			return;
		}
		setTimeout(function(){
			self.showFlag();
		}, 500);
	}
	this.moveRandomFlag = function(){
		var flags = $('.worldFlags .flag')
		var n = Math.floor(flags.length * Math.random());
		flags
			.eq(n)
			.addClass("flagSwift");
		setTimeout(function(){
			$(".flagSwift")
				.removeClass("flagSwift");
		}, 1000);
		setTimeout(function(){
			self.moveRandomFlag();
		}, 1000 + (Math.random() * 4000));
	}

	this.init = function(){
		setTimeout(function(){
			self.showFlag();
		}, 500);
	}

	this.setPatternSize();
	$(window).resize(function() {
		self.setPatternSize();
	});
}

$(document).ready(function() {
	var inicialCircleValue = 12;
	var achievementsDelay = 4000;

	var progressBarObj = null;
	var worldControlObj = null;

	$('#fullpage').fullpage({
		anchors: ['QuitNow', 'Chat', 'Achievements', 'Health', 'Downloads'],
		sectionsColor: ['#3d91e6', '#eac850', '#6aad5d', '#d55c3f', '#3a5269', '#EAE1C0'],
		slidesNavigation: true,
		navigation: true,
		navigationPosition: 'right',
        scrollOverflow: false,
        css3: true,
		//navigationTooltips: ['First', 'Second', 'Third'],
		afterLoad: function(anchorLink, index){
			switch(index){
				case SLIDES.home: $('.home').removeClass('hideScreenshots'); break;
			}
		},
		onLeave: function(index, nextIndex, direction){
			$("#section4").scrollTop(0);
			switch(nextIndex){
				case SLIDES.chat: animateChat(); break;
				case SLIDES.progress: progressBarObj.init(); break;
				case SLIDES.world: worldControlObj.init(); break;
			}
		}
	});

	var pixelRatio = window.getDevicePixelRatio();

	$('#circle').circleProgress({
		value: inicialCircleValue / 100,
		startAngle: -Math.PI / 2,
		size: 320 * pixelRatio,
		emptyFill: "#792f1d",
		thickness: 20 * pixelRatio,
		animation: false,
		fill: {
			color: "#fff"
		}
	});

	if(IOS)
		$(document.body).addClass("appleDevice");

	$(".screen")
		.parent().hide();
	if(IOS){
		new sliderScreenshots($(".screen.apple"));
		$(".screen.apple")
			.parent().show();
	}else if(ANDROID){
		new sliderScreenshots($(".screen.android"));
		$(".screen.android")
			.parent().show();
	}else{
		new sliderScreenshots($(".screen.desktop"));
		$(".screen.desktop")
			.parent().show();
	}

	progressBarObj = new progressBar(inicialCircleValue);
	worldControlObj =  new worldControl();
	new initAchievements($("#achiev div"), achievementsDelay);
	new ElastiStack( $("#chatting").get(0), {
		distDragBack : 100,
		distDragMax : 200
	});
});

(function () {
	window.addEventListener('DOMContentLoaded', function (e) {
		var termsShow = document.getElementById('TermsShow');
		termsShow.addEventListener('click', function (e) {
			e.preventDefault();
			$('.js-Terms .wrapper').load('./terms-of-service/index.html .content');
			$('.js-Terms').addClass('show');
		});

		var termsHide = document.getElementById('TermsHide');
		termsHide.addEventListener('click', function (e) {
			e.preventDefault();
			hideTerms();
		});

		document.addEventListener('keyup', function(e) {
	    if (e.keyCode == 27) {
	      hideTerms();
	    }
	  });

		function hideTerms() {
			$('.js-Terms .wrapper').html('');
			$('.js-Terms').removeClass('show');
		}
	});
})()
<|endoftext|>


<commit_before>(function($, _){
  function Sudoku(board) {

    this.__init__ = function() {
      this.board = _.map(board, function(row){
        return _.map(row, function(num){
          return {
            num: num,
            original: true
          }
        })
      })
    };
    this.__init__();

    this.getSuccessors = function() {
      var empty = this._getFirstEmpty();
      var possibleVals = this._getPossibleVals(empty);

      var successors = [];
      for (var i = 0; i < possibleVals.length; i += 1) {
        var val = possibleVals[i];
        var successor = this._getSuccessor(empty, val);
        successors.push(successor);
      }
      return successors.reverse();
    }

    this._getFirstEmpty = function() {
      for (var row = 0; row < 9; row += 1){
        for (var col = 0; col < 9; col += 1) {
          if (this.board[row][col].num === null)
            return {row: row, col: col};
        }
      }
      return null;
    }

    this._getRowNums = function(empty) {
      var x = empty.row;
      return _.map(this.board[x], function(el) { return el.num; });
    }

    this._getColNums = function(empty) {
      var y = empty.col;
      return _.map(this.board, function(row){ return row[y].num; });
    }

    this._getBoxNums = function(empty) {
      var rowMin = Math.floor(empty.row / 3) * 3,
          rowMax = rowMin + 3,
          colMin = Math.floor(empty.col / 3) * 3,
          colMax = colMin + 3;

      var box = [];
      for (var x = rowMin; x < rowMax; x += 1) {
        for (var y = colMin; y < colMax; y += 1) {
          box.push(this.board[x][y].num);
        }
      }
      return box;
    }

    this._getPossibleVals = function(empty) {
      var values = _.range(1,10),
          row = this._getRowNums(empty),
          col = this._getColNums(empty),
          box = this._getBoxNums(empty);
      _.remove(values, function(v){
        return _.indexOf(_.union(row, col, box), v) != -1;
      });
      return values;
    }

    this._getSuccessor = function(empty, val) {
      var successor = _.cloneDeep(this);
      successor.board[empty.row][empty.col] = {
        num: val,
        original: false
      };
      return successor
    }

    this.isFinalState = function() {
      return this._getFirstEmpty() === null;
    }
  }

  function DepthFirstSearchModule(startState) {

    this._exploreNode = function(){
      if (this.fringe.length){
        this.currentState = this.fringe.pop();
        this.nodesExplored += 1;
        if (this.currentState.isFinalState()){
          return "solved";
        }
        else {
          successors = this.currentState.getSuccessors();
          this.fringe = this.fringe.concat(successors);
        }
      }
      else return "failed";
    }

    this._exploreNodes = function(){
      var speed = parseInt( $('#speed-selector').val() );
      var numberOfNodes = speed * this.INTERVAL / 1000;
      for (var x = 0; x < numberOfNodes; x += 1) {

        var result = this._exploreNode();
        if (result === "solved" || result === "failed") {
          this._printState(this.currentState);
          clearInterval(this.id);
          return;
        }
      }
      this._printState(this.currentState);
    }

    this._printState = function(state) {
      var html = _.reduce(state.board, function(agg, row) {
        var rowString = _.reduce(row, function(agg, el) {
          var elString = el.num? '' + el.num : ' ';
          return agg + '
' + '
' + elString + '
' + '
';
        }, '');
        return agg + '
' + rowString + '
';
      }, '');

      html = _.template('<%= html %>
Nodes Explored: <%= nodesExplored %>
')({
        html: html,
        nodesExplored: this.nodesExplored
      });
      $('#sudoku-container').html(html);
    }

    this.search = function() {
      this.fringe = [startState];
      this.currentState = null;
      this.nodesExplored = 0;
      this.INTERVAL = 100;
      this.id = setInterval( this._exploreNodes.bind(this), this.INTERVAL );
    }
  }

  function initialize() {
    function updateSpeed(){
      var speed = $('#speed-selector').val();
      $('#speed').text(speed);
    };

    $('#speed-selector').on('input', updateSpeed );

    var startState = new Sudoku(
      [[null, null, null, null, null, 8, 9, null, 2],
       [6, null, 4, 3, null, null, null, null, null],
       [null, null, null, 5, 9, null, null, null, null],
       [null, null, 5, 7, null, 3, null, null, 9],
       [7, null, null, null, 4, null, null, null, null],
       [null, null, 9, null, null, null, 3, null, 5],
       [null, 8, null, null, null, 4, null, null, null],
       [null, 4, 1, null, null, null, null, 3, null],
       [2, null, null, 1, 5, null, null, null, null]]
    );
    var DFSModule = new DepthFirstSearchModule(startState);
    DFSModule.search();
  }

  initialize();

})(jQuery, _);
<commit_msg>bold original numbers<commit_after>(function($, _){
  function Sudoku(board) {

    this.__init__ = function() {
      this.board = _.map(board, function(row){
        return _.map(row, function(num){
          return {
            num: num,
            original: true
          }
        })
      })
    };
    this.__init__();

    this.getSuccessors = function() {
      var empty = this._getFirstEmpty();
      var possibleVals = this._getPossibleVals(empty);

      var successors = [];
      for (var i = 0; i < possibleVals.length; i += 1) {
        var val = possibleVals[i];
        var successor = this._getSuccessor(empty, val);
        successors.push(successor);
      }
      return successors.reverse();
    }

    this._getFirstEmpty = function() {
      for (var row = 0; row < 9; row += 1){
        for (var col = 0; col < 9; col += 1) {
          if (this.board[row][col].num === null)
            return {row: row, col: col};
        }
      }
      return null;
    }

    this._getRowNums = function(empty) {
      var x = empty.row;
      return _.map(this.board[x], function(el) { return el.num; });
    }

    this._getColNums = function(empty) {
      var y = empty.col;
      return _.map(this.board, function(row){ return row[y].num; });
    }

    this._getBoxNums = function(empty) {
      var rowMin = Math.floor(empty.row / 3) * 3,
          rowMax = rowMin + 3,
          colMin = Math.floor(empty.col / 3) * 3,
          colMax = colMin + 3;

      var box = [];
      for (var x = rowMin; x < rowMax; x += 1) {
        for (var y = colMin; y < colMax; y += 1) {
          box.push(this.board[x][y].num);
        }
      }
      return box;
    }

    this._getPossibleVals = function(empty) {
      var values = _.range(1,10),
          row = this._getRowNums(empty),
          col = this._getColNums(empty),
          box = this._getBoxNums(empty);
      _.remove(values, function(v){
        return _.indexOf(_.union(row, col, box), v) != -1;
      });
      return values;
    }

    this._getSuccessor = function(empty, val) {
      var successor = _.cloneDeep(this);
      successor.board[empty.row][empty.col] = {
        num: val,
        original: false
      };
      return successor
    }

    this.isFinalState = function() {
      return this._getFirstEmpty() === null;
    }
  }

  function DepthFirstSearchModule(startState) {

    this._exploreNode = function(){
      if (this.fringe.length){
        this.currentState = this.fringe.pop();
        this.nodesExplored += 1;
        if (this.currentState.isFinalState()){
          return "solved";
        }
        else {
          successors = this.currentState.getSuccessors();
          this.fringe = this.fringe.concat(successors);
        }
      }
      else return "failed";
    }

    this._exploreNodes = function(){
      var speed = parseInt( $('#speed-selector').val() );
      var numberOfNodes = speed * this.INTERVAL / 1000;
      for (var x = 0; x < numberOfNodes; x += 1) {

        var result = this._exploreNode();
        if (result === "solved" || result === "failed") {
          this._printState(this.currentState);
          clearInterval(this.id);
          return;
        }
      }
      this._printState(this.currentState);
    }

    this._printState = function(state) {
      var html = _.reduce(state.board, function(agg, row) {
        var rowString = _.reduce(row, function(agg, el) {
          var elString = el.num? '' + el.num : ' ';
          elString = el.original? '' + elString + '' : elString;
          return agg + '
' + '
' + elString + '
' + '
';
        }, '');
        return agg + '
' + rowString + '
';
      }, '');

      html = _.template('<%= html %>
Nodes Explored: <%= nodesExplored %>
')({
        html: html,
        nodesExplored: this.nodesExplored
      });
      $('#sudoku-container').html(html);
    }

    this.search = function() {
      this.fringe = [startState];
      this.currentState = null;
      this.nodesExplored = 0;
      this.INTERVAL = 100;
      this.id = setInterval( this._exploreNodes.bind(this), this.INTERVAL );
    }
  }

  function initialize() {
    function updateSpeed(){
      var speed = $('#speed-selector').val();
      $('#speed').text(speed);
    };

    $('#speed-selector').on('input', updateSpeed );

    var startState = new Sudoku(
      [[null, null, null, null, null, 8, 9, null, 2],
       [6, null, 4, 3, null, null, null, null, null],
       [null, null, null, 5, 9, null, null, null, null],
       [null, null, 5, 7, null, 3, null, null, 9],
       [7, null, null, null, 4, null, null, null, null],
       [null, null, 9, null, null, null, 3, null, 5],
       [null, 8, null, null, null, 4, null, null, null],
       [null, 4, 1, null, null, null, null, 3, null],
       [2, null, null, 1, 5, null, null, null, null]]
    );
    var DFSModule = new DepthFirstSearchModule(startState);
    DFSModule.search();
  }

  initialize();

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


<commit_before>// Karma configuration
// Generated on Thu Aug 03 2017 15:57:03 GMT-0300 (-03)

module.exports = function(config) {
  config.set({

    // base path that will be used to resolve all patterns (eg. files, exclude)
    basePath: '',

    // frameworks to use
    // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
    frameworks: ['jasmine'],

    // list of files / patterns to load in the browser
    files: [
      'server.js'
    ],

    // list of files to exclude
    exclude: [
    ],

    // preprocess matching files before serving them to the browser
    // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
    preprocessors: {
    },

    // test results reporter to use
    // possible values: 'dots', 'progress'
    // available reporters: https://npmjs.org/browse/keyword/karma-reporter
    reporters: ['progress'],

    // web server port
    port: 9876,

    // enable / disable colors in the output (reporters and logs)
    colors: true,

    // level of logging
    // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
    logLevel: config.LOG_INFO,

    // enable / disable watching file and executing tests whenever any file changes
    autoWatch: true,

    // start these browsers
    // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
    browsers: ['Firefox', 'Safari'],

    // Continuous Integration mode
    // if true, Karma captures browsers, runs the tests and exits
    singleRun: false,

    // Concurrency level
    // how many browser should be started simultaneous
    concurrency: Infinity
  })
}
<commit_msg>Nova config Karma<commit_after>// Karma configuration
// Generated on Fri Aug 04 2017 10:53:00 GMT-0300 (-03)

module.exports = function(config) {
  config.set({

    // base path that will be used to resolve all patterns (eg. files, exclude)
    basePath: '',

    // frameworks to use
    // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
    frameworks: [],

    // list of files / patterns to load in the browser
    files: [
      '*.js'
    ],

    // list of files to exclude
    exclude: [
    ],

    // preprocess matching files before serving them to the browser
    // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
    preprocessors: {
    },

    // test results reporter to use
    // possible values: 'dots', 'progress'
    // available reporters: https://npmjs.org/browse/keyword/karma-reporter
    reporters: ['progress'],

    // web server port
    port: 9876,

    // enable / disable colors in the output (reporters and logs)
    colors: true,

    // level of logging
    // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
    logLevel: config.LOG_INFO,

    // enable / disable watching file and executing tests whenever any file changes
    autoWatch: true,

    // start these browsers
    // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
    browsers: [],

    // Continuous Integration mode
    // if true, Karma captures browsers, runs the tests and exits
    singleRun: false,

    // Concurrency level
    // how many browser should be started simultaneous
    concurrency: Infinity
  })
}
<|endoftext|>