<commit_before>(function(){
	customTag_get = function(name, ctr) {
		var Ctor = custom_Tags[name];
		if (Ctor == null) {
			return null;
		}
		if (Ctor !== Resolver) {
			return Ctor;
		}

		var ctr_ = ctr;
		while(ctr_ != null) {
			if (is_Function(ctr_.getHandler)) {
				Ctor = ctr_.getHandler(name);
				if (Ctor != null) {
					return Ctor;
				}
			}
			ctr_ = ctr_.parent;
		}
		return null;
	};
	customTag_getAll = function(ctr) {
		var obj = {},
			ctr_ = ctr, x;
		while (ctr_ != null) {
			x = null;
			if (is_Function(ctr_.getHandlers)) {
				x = ctr_.getHandlers();
			} else {
				x = ctr_.__handlers__;
			}
			if (x != null) {
				obj = obj_extendDefaults(obj, x);
			}
			ctr_ = ctr_.parent;
		}
		for (var key in custom_Tags) {
			x = custom_Tags[key];
			if (x == null || x === Resolver) {
				continue;
			}
			if (obj[key] == null) {
				obj[key] = x;
			}
		}
		return obj;
	};

	customTag_register = function(mix, Handler){
		if (is_Object(Handler)) {
			//> static
			Handler.__Ctor = wrapStatic(Handler);
		}
		if (typeof mix !== 'string' && arguments.length === 3) {
			customTag_registerScoped.apply(this, arguments);
			return;
		}

		custom_Tags[name] = Handler;
		//> make fast properties
		obj_toFastProps(custom_Tags);
	};

	customTag_registerScoped = function(Mix, name, Handler) {
		customTag_registerResolver(name);
		var obj = is_Function(Mix) ? Mix.prototype : Mix;
		var map = obj.__handlers__;
		if (map == null) {
			map = obj.__handlers__ = {};
		}
		map[name] = Handler;

		if (obj.getHandler == null) {
			obj.getHandler = compo_getHandlerDelegate;
		}
	};

	customTag_registerResolver = function(name){
		var Ctor = custom_Tags[name];
		if (Ctor === Resolver)
			return;

		if (Ctor != null)
			custom_Tags_global[name] = Ctor;

		custom_Tags[name] = Resolver;

		//> make fast properties
		obj_toFastProps(custom_Tags);
	};

	customTag_Base = {
		async: false,
		attr: null,
		await: null,
		compoName: null,
		components: null,
		expression: null,
		ID: null,
		meta: null,
		model: null,
		nodes: null,
		parent: null,
		render: null,
		renderEnd: null,
		renderStart: null,
		tagName: null,
		type: null,
	};

	var Resolver;
	(function(){
		Resolver = function (node, model, ctx, container, ctr) {
			var Mix = customTag_get(node.tagName, ctr);
			if (Mix != null) {
				if (is_Function(Mix) === false)	{
					return obj_create(Mix);
				}
				return new Mix(node, model, ctx, container, ctr);
			}

			log_error('Component not found:', node.tagName);
			return null;
		};
	}());

	function wrapStatic(proto) {
		function Ctor(node, parent) {
			this.ID = null;
			this.tagName = node.tagName;
			this.attr = obj_create(node.attr);
			this.expression = node.expression;
			this.nodes = node.nodes;
			this.nextSibling = node.nextSibling;
			this.parent = parent;
			this.components = null;
		}
		Ctor.prototype = proto;
		return Ctor;
	}

	function compo_getHandlerDelegate(name) {
		var map = this.__handlers__;
		return map == null ? null : map[name];
	}

}());<commit_msg>fix (RegisterHandler) scope vs global<commit_after>(function(){
	customTag_get = function(name, ctr) {
		var Ctor = custom_Tags[name];
		if (Ctor == null) {
			return null;
		}
		if (Ctor !== Resolver) {
			return Ctor;
		}

		var ctr_ = ctr;
		while(ctr_ != null) {
			if (is_Function(ctr_.getHandler)) {
				Ctor = ctr_.getHandler(name);
				if (Ctor != null) {
					return Ctor;
				}
			}
			ctr_ = ctr_.parent;
		}
		return null;
	};
	customTag_getAll = function(ctr) {
		var obj = {},
			ctr_ = ctr, x;
		while (ctr_ != null) {
			x = null;
			if (is_Function(ctr_.getHandlers)) {
				x = ctr_.getHandlers();
			} else {
				x = ctr_.__handlers__;
			}
			if (x != null) {
				obj = obj_extendDefaults(obj, x);
			}
			ctr_ = ctr_.parent;
		}
		for (var key in custom_Tags) {
			x = custom_Tags[key];
			if (x == null || x === Resolver) {
				continue;
			}
			if (obj[key] == null) {
				obj[key] = x;
			}
		}
		return obj;
	};

	customTag_register = function(mix, Handler){
		if (typeof mix !== 'string' && arguments.length === 3) {
			debugger;
			customTag_registerScoped.apply(this, arguments);
			return;
		}

		custom_Tags[mix] = compo_ensureCtor(Handler);
		//> make fast properties
		obj_toFastProps(custom_Tags);
	};

	customTag_registerScoped = function(Ctx, name, Handler) {
		customTag_registerResolver(name);
		var obj = is_Function(Ctx) ? Ctx.prototype : Ctx;
		var map = obj.__handlers__;
		if (map == null) {
			map = obj.__handlers__ = {};
		}
		map[name] = compo_ensureCtor(Handler);

		if (obj.getHandler == null) {
			obj.getHandler = compo_getHandlerDelegate;
		}
	};

	customTag_registerResolver = function(name){
		var Ctor = custom_Tags[name];
		if (Ctor === Resolver)
			return;

		if (Ctor != null)
			custom_Tags_global[name] = Ctor;

		custom_Tags[name] = Resolver;

		//> make fast properties
		obj_toFastProps(custom_Tags);
	};

	customTag_Base = {
		async: false,
		attr: null,
		await: null,
		compoName: null,
		components: null,
		expression: null,
		ID: null,
		meta: null,
		model: null,
		nodes: null,
		parent: null,
		render: null,
		renderEnd: null,
		renderStart: null,
		tagName: null,
		type: null,
	};

	var Resolver;
	(function(){
		Resolver = function (node, model, ctx, container, ctr) {
			var Mix = customTag_get(node.tagName, ctr);
			if (Mix != null) {
				if (is_Function(Mix) === false)	{
					return obj_create(Mix);
				}
				return new Mix(node, model, ctx, container, ctr);
			}

			log_error('Component not found:', node.tagName);
			return null;
		};
	}());

	function wrapStatic(proto) {
		function Ctor(node, parent) {
			this.ID = null;
			this.tagName = node.tagName;
			this.attr = obj_create(node.attr);
			this.expression = node.expression;
			this.nodes = node.nodes;
			this.nextSibling = node.nextSibling;
			this.parent = parent;
			this.components = null;
		}
		Ctor.prototype = proto;
		return Ctor;
	}

	function compo_getHandlerDelegate(name) {
		var map = this.__handlers__;
		return map == null ? null : map[name];
	}

	function compo_ensureCtor(Handler) {
		if (is_Object(Handler)) {
			//> static
			Handler.__Ctor = wrapStatic(Handler);
		}
		return Handler;
	}

}());<|endoftext|>


<commit_before>if (document.head.dataset.piwikHost) {
  var _paq = _paq || [];
  /* tracker methods like "setCustomDimension" should be called before "trackPageView" */
  _paq.push(['trackPageView']);
  _paq.push(['enableLinkTracking']);
  (function() {
    var u=document.head.dataset.piwikHost;
    _paq.push(['setTrackerUrl', u+'piwik.php']);
    _paq.push(['setSiteId', '6']);
    var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
    g.type='text/javascript'; g.async=true; g.defer=true; g.src=u+'piwik.js'; s.parentNode.insertBefore(g,s);
  })();

  document.addEventListener('click', function (e) {
    e = e || window.event;
    var target = e.target || e.srcElement;

    if (target.dataset.piwikAction) {
      _paq.push(['trackEvent', target.dataset.piwikAction, target.dataset.piwikName, target.dataset.piwikValue]);
    }
  }, false);
}
<commit_msg>Fix piwik by using window._paq<commit_after>if (document.head.dataset.piwikHost) {
  window._paq = window._paq || [];
  /* tracker methods like "setCustomDimension" should be called before "trackPageView" */
  window._paq.push(['trackPageView']);
  window._paq.push(['enableLinkTracking']);
  (function() {
    var u=document.head.dataset.piwikHost;
    window._paq.push(['setTrackerUrl', u+'piwik.php']);
    window._paq.push(['setSiteId', '6']);
    var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
    g.type='text/javascript'; g.async=true; g.defer=true; g.src=u+'piwik.js'; s.parentNode.insertBefore(g,s);
  })();

  document.addEventListener('click', function (e) {
    e = e || window.event;
    var target = e.target || e.srcElement;

    if (target.dataset.piwikAction) {
      window._paq.push(['trackEvent', target.dataset.piwikAction, target.dataset.piwikName, target.dataset.piwikValue]);
    }
  }, false);
}
<|endoftext|>


<commit_before>'use strict'

/* globals chrome */

var util = require('util')
var _ = require('lodash')
var zepto = require('zepto-browserify')
var keycode = require('keycode')
var deepEqual = require('deep-equal')
var eventUtils = require('./event-utils')
var Controller = require('./controller')
var Query = require('./Query')
var Entry = require('./Entry')

var $ = zepto.$

module.exports = exports = EntriesController

function EntriesController () {
  Controller.apply(this, arguments)
  this.entryViewList = []
  this.active = false

  this.boundOnKeydown = this.onKeydown.bind(this)
  this.boundOnDeadEntryView = this.onDeadEntryView.bind(this)

  this.selectedEntryView = null
  this.cachedSelectionIndex = -1

  this.undoStack = []

  this.renderList() // to center the input
  var self = this
  window.addEventListener('resize', function () {
    if (self.active) {
      // recenter the view
      self.renderList()
    }
  })
  document.addEventListener('mousewheel', function (evt) {
    // We want the selection to change when manually scrolling. By resetting
    // the last MouseEvent we make sure the next one is not ignored.
    eventUtils.setLastMouseEventAfterEventQueue(undefined)
  })
  document.addEventListener('mousemove', function (evt) {
    eventUtils.setLastMouseEventAfterEventQueue(evt)
  })
  chrome.storage.sync.get(null, function (items) {
    var backup = ''
    var Model = self.model
    Model.items = items
    for (var id in items) {
      var item = items[id]
      var model = Model.fromObject(item)
      if (model instanceof Model) {
        backup += model.title + '\n'
        self.addEntry(model)
      } else {
        chrome.storage.sync.remove(id)
      }
    }
    self.renderList()
    console.log('animus backup:')
    console.log('(you probably want to save this if your entries are missing)')
    console.log(backup)
  })
  chrome.storage.onChanged.addListener(function (changes, area) {
    // TODO: refactor
    if (area !== 'sync') return
    _.forEach(changes, function (change, id) {
      // failure to perform a change probably means that this instance was the
      // one that performed the sync / modified data
      var sucess = self.performChange(change, id)

      if (sucess && deepEqual(change, self.getNextUndo(), {strict: true})) {
        /**
         * another animus instance used undo, so we pop our undo stack
         *
         * edge-case: the other animus instance was older, and had some changes
         * in its undo stack, and it's popping changes this instance doesn't have
         */
        console.log('an animus instance used undo')
        self.undoStack.pop()
      } else {
        // add change to undostack, leave it ready for performChange
        console.log('added change to undo')
        var undoChange = {}
        if (change.newValue) undoChange.oldValue = change.newValue
        if (change.oldValue) undoChange.newValue = change.oldValue
        self.undoStack.push(undoChange)
      }
    })
    self.renderList()
  })
}
util.inherits(EntriesController, Controller)
_.mixin(EntriesController, Controller)

EntriesController.prototype.attach = function (el) {
  Controller.prototype.attach.call(this, el)
  this.input = this.$el.find('input')
  this.input.on('input', this.onInputChange.bind(this))
  this.input.on('focus', this.onFocusInput.bind(this))
}

EntriesController.prototype.setActive = function (flag) {
  flag = !!flag
  if (!this.active && flag) {
    this.attachKeyListener()
    this.focusInput()
    // recenter the view in case there was a resize whilst unactive
    this.renderList()
  } else if (this.active && !flag) {
    this.detachKeyListener()
  }
  this.active = flag
}

EntriesController.prototype.attachKeyListener = function () {
  document.addEventListener('keydown', this.boundOnKeydown, true)
}

EntriesController.prototype.detachKeyListener = function () {
  document.removeEventListener('keydown', this.boundOnKeydown, true)
}

EntriesController.prototype.onKeydown = function (evt) {
  // Prevent animus from blocking command usage, e.g. Cmd+Shift+F for fullscreen
  if (evt.altKey || evt.ctrlKey || evt.metaKey) {
    return
  }

  // Prevent websites to do stuff while we interact with animus
  // e.g. Wired automatically starts searching when a key is pressed
  evt.stopPropagation()

  if (evt.keyCode === keycode('esc')) {
    this.emit('toggle')
    return
  }

  if (this.inputIsFocused()) {
    switch (evt.keyCode) {

      case keycode('tab'):
        this.focusFirstEntry()
        evt.preventDefault()
        break

      case keycode('enter'):
        evt.preventDefault()
        // TODO: Refactor this into a function
        var val = this.input.val()
        if (!val) return
        var Model = this.model
        var entry = new Model({
          title: val
        })
        entry.save()
        this.addEntry(entry)
        this.input.val('')
        // TODO: Why doesn't this fire automatticaly? trigger?
        this.onInputChange({srcElement: this.input[0]})

        // save entry and close animus if shift+enter
        if (evt.shiftKey) {
          this.emit('toggle')
        }
        break

    }
  } else {
    var index
    switch (evt.keyCode) {

      case keycode('a'):
      case keycode('tab'):
        this.focusInput()
        evt.preventDefault()
        break

      case keycode('e'):
        var title = this.selectedEntryView.model.title
        this.deleteSelectedEntry()
        this.focusInput()
        this.input.val(title)
        evt.preventDefault()
        break

      case keycode('u'):
        this.undo()
        // since we might end up focusing the input when no entries are left
        evt.preventDefault()
        break

      case keycode('d'):
        this.deleteSelectedEntry()
        // since we might end up focusing the input when no entries are left
        evt.preventDefault()
        break

      case keycode('f'):
        if (this.selectedEntryView) {
          var link = this.selectedEntryView.model.getLink()
          if (link) {
            window.open(link, '_blank')
          }
        }
        break

      case keycode('j'):
        index = this.getSelectionIndex()
        index = Math.min(this.entryViewList.length - 1, index + 1)
        this.selectEntryViewAtIndex(index, true)
        break

      case keycode('k'):
        index = this.getSelectionIndex()
        index = Math.max(0, index - 1)
        this.selectEntryViewAtIndex(index, true)
        break

    }
  }
}

EntriesController.prototype.addEntry = function (entry) {
  var ModelView = this.modelView
  var entryView = new ModelView(entry)
  entryView.on('click:tag', this.addTagToQuery.bind(this))
  entryView.on('hover', this.hoveredEntryView.bind(this))
  entryView.on('destroy', this.boundOnDeadEntryView)
  var list = this.$el.find('.animus-entry-list')
  list.prepend(entryView.$el)
  this.entryViewList.unshift(entryView)
}

/**
 * If the tag is not already part of the query, add it.
 *
 * @param {String} tag
 */
EntriesController.prototype.addTagToQuery = function (tag) {
  var val = this.input.val()
  var query = new Query(val)
  if (!query.hasTag(tag)) {
    // Add tag to query
    this.input.val(val + tag)
  } else {
    // Tags only have [#a-zA-Z], so don't worry about escaping regex
    var replacingTagRe = new RegExp(tag, 'g')
    var newVal = val.replace(replacingTagRe, '')
    this.input.val(newVal)
  }
  this.focusInput()
  // TODO: Why doesn't this fire automatticaly? trigger?
  this.onInputChange({srcElement: this.input[0]})
}

/**
 * Callback for the InputChange Event.
 *
 * @param {Event} evt
 */
EntriesController.prototype.onInputChange = function (evt) {
  var input = this.input[0]
  var query = new Query(input.value)
  for (var i = 0; i < this.entryViewList.length; ++i) {
    var entryView = this.entryViewList[i]
    entryView.applyQuery(query)
  }
  this.entryViewList = _.sortByOrder(this.entryViewList, ['matchScore'], [false])
  this.renderList()
  $(input)[query.title ? 'addClass' : 'removeClass']('has-content')
}

/**
 * Relocates EntryViews
 */
EntriesController.prototype.renderList = function (startIndex) {
  var entryView
  startIndex = Math.max(startIndex || 0, 0)
  for (var i = startIndex; i < this.entryViewList.length; ++i) {
    entryView = this.entryViewList[i]
    entryView.offsetY = i * 63
    entryView.$el.css('transform', 'translateY(' + entryView.offsetY + 'px)')
  }

  // We find out the list element with the largest width so that
  // we can make the input's width match it
  var maxWidth = 0
  for (var j = startIndex; j < this.entryViewList.length; ++j) {
    entryView = this.entryViewList[j]
    var domEl = entryView.$el[0]
    maxWidth = Math.max(maxWidth, domEl.offsetWidth)
  }
  this.$('.animus-new-entry-input').css('width', maxWidth)

  // We fake the list's height since all the list elements have top,left: 0px
  var listHeight = this.entryViewList.length * 63
  this.$('.animus-entry-list').css('height', listHeight + 'px')
  var inputHeight = 52
  if (listHeight) listHeight += 30
  var animusHeight = 100 + inputHeight + listHeight + 100
  this.offsetY = (window.innerHeight - animusHeight) / 2
  this.offsetY = Math.max(this.offsetY, 0)
  this.$el.css('transform', 'translateY(' + this.offsetY + 'px)')
}

/**
 * Callback for when an EntryView is hovered.
 * @param {EntryView} entryView
 */
EntriesController.prototype.hoveredEntryView = function (entryView) {
  clearTimeout(this.focusTimeout)
  if (entryView) {
    this.selectEntryViewAtIndex(this.entryViewList.indexOf(entryView))
    this.input.blur()
  } else {
    /**
     * mouseout is called when changing hover between elements, and focusing
     * the input scrolls, even just during the entry switch, scrolls the view
     * to the input. not desired.
     */
    this.focusTimeout = setTimeout(function () {
      if ($('#animus')[0].scrollTop === 0) {
        this.focusInput()
      }
    }.bind(this), 1)
  }
}

/**
 * Get index of selected EntryView. We store a cache of the index, but since
 * the entry list can be modified due to sync events, we must ensure the cached
 * index is still correct.
 *
 * @return {Number} selectionIndex
 */
EntriesController.prototype.getSelectionIndex = function () {
  if (!this.selectedEntryView) {
    return -1
  }
  var cachedEntryView = this.entryViewList[this.cachedSelectionIndex]
  if (cachedEntryView === this.selectedEntryView) {
    return this.cachedSelectionIndex
  }
  this.cachedSelectionIndex = this.entryViewList.indexOf(this.selectedEntryView)
  return this.cachedSelectionIndex
}

/**
 * Select the EntryView at the given index
 *
 * @param {Number} index
 */
EntriesController.prototype.selectEntryViewAtIndex = function (index, shortcut) {
  if (this.selectedEntryView) {
    this.selectedEntryView.setSelected(false)
  }
  var entryView = null
  if (index > -1) {
    entryView = this.entryViewList[index]
    entryView.setSelected(true)
  } else {
    index = -1
  }
  if (entryView && shortcut) {
    var entryViewTop = this.offsetY + 182 + entryView.offsetY
    var entryViewBottom = entryViewTop + 63
    var animus = $('#animus')[0]
    var windowTop = animus.scrollTop
    var windowHeight = window.innerHeight
    var windowBottom = windowTop + windowHeight
    var margin = 182
    if (windowTop + margin > entryViewTop) {
      animus.scrollTop = entryViewTop - margin
    } else if (windowBottom - margin < entryViewBottom) {
      animus.scrollTop = entryViewBottom + margin - windowHeight
    }
  }
  this.selectedEntryView = entryView
  this.cachedSelectionIndex = index
}

/**
 * Removes from the list and deletes data of the selected entry.
 *
 * A double-linked list would allow faster delete. Even though we have to
 * support random access entry selecting due to being able to hover entries, it
 * could be solved by referencing the list item from the EntryView.
 * (yay circular references)
 */
EntriesController.prototype.deleteSelectedEntry = function () {
  var index = this.getSelectionIndex()
  var entryView = this.entryViewList[index]
  if (!entryView) return
  entryView.deleteEntry(index)
}

/**
 * Dead entry view callback. It may give a `hint` about it's index in
 * entryViewList.
 *
 * @param {EntryView} entryView
 * @param {Number} hint
 */
EntriesController.prototype.onDeadEntryView = function (entryView, hint) {
  var index = hint
  if (index === -1) {
    // TODO: improve this, hashing
    if (this.selectedEntryView === entryView) {
      // happy coincidence
      index = this.getSelectionIndex()
    } else {
      index = this.entryViewList.indexOf(entryView)
    }
  }
  if (index === -1) return
  this.entryViewList.splice(index, 1)
  this.renderList(index)
  if (this.selectedEntryView === entryView) {
    this.selectedEntryView = null
    while (index >= this.entryViewList.length) --index
    this.selectEntryViewAtIndex(index)
    if (!this.selectedEntryView) {
      // no entries left
      this.focusInput()
    }
  }
}

/**
 * Undo the last action.
 */
EntriesController.prototype.undo = function () {
  var changedList = this.performChange(this.undoStack.pop())
  if (changedList) {
    this.renderList()
  }
}

EntriesController.prototype.getNextUndo = function () {
  return this.undoStack[this.undoStack.length - 1]
}

/**
 * Performs a change on the data, given by an oldValue and a newValue.
 *
 * @param {Object} change
 * @return {Boolean} success
 */

EntriesController.prototype.performChange = function (change) {
  var id = (change.newValue || change.oldValue).id
  var entry
  if (!change.newValue) {
    // deleted entry
    entry = Entry.items[id]
    if (!entry) return false
    if (entry instanceof Entry) entry.destroy()
    else Entry.items = undefined
  } else if (!change.oldValue) {
    // added entry
    if (Entry.items[id]) return false
    entry = Entry.fromObject(change.newValue)
    if (!(entry instanceof Entry)) return false
    this.addEntry(entry)
  } else {
    // updated entry
    // lol, we don't perform updates right now, we delete / re-create entries
    entry = Entry.items[id]
    entry.update(change.newValue)
  }
  return true
}

EntriesController.prototype.inputIsFocused = function () {
  return document.activeElement === this.input[0]
}

EntriesController.prototype.focusInput = function () {
  $('#animus')[0].scrollTop = 0
  this.input.focus()
}

EntriesController.prototype.onFocusInput = function (evt) {
  this.selectEntryViewAtIndex(-1)
}

EntriesController.prototype.focusFirstEntry = function () {
  if (this.entryViewList.length > 0) {
    this.selectEntryViewAtIndex(0)
  }
  this.input.blur()
}
<commit_msg>animus always closes on shift+enter<commit_after>'use strict'

/* globals chrome */

var util = require('util')
var _ = require('lodash')
var zepto = require('zepto-browserify')
var keycode = require('keycode')
var deepEqual = require('deep-equal')
var eventUtils = require('./event-utils')
var Controller = require('./controller')
var Query = require('./Query')
var Entry = require('./Entry')

var $ = zepto.$

module.exports = exports = EntriesController

function EntriesController () {
  Controller.apply(this, arguments)
  this.entryViewList = []
  this.active = false

  this.boundOnKeydown = this.onKeydown.bind(this)
  this.boundOnDeadEntryView = this.onDeadEntryView.bind(this)

  this.selectedEntryView = null
  this.cachedSelectionIndex = -1

  this.undoStack = []

  this.renderList() // to center the input
  var self = this
  window.addEventListener('resize', function () {
    if (self.active) {
      // recenter the view
      self.renderList()
    }
  })
  document.addEventListener('mousewheel', function (evt) {
    // We want the selection to change when manually scrolling. By resetting
    // the last MouseEvent we make sure the next one is not ignored.
    eventUtils.setLastMouseEventAfterEventQueue(undefined)
  })
  document.addEventListener('mousemove', function (evt) {
    eventUtils.setLastMouseEventAfterEventQueue(evt)
  })
  chrome.storage.sync.get(null, function (items) {
    var backup = ''
    var Model = self.model
    Model.items = items
    for (var id in items) {
      var item = items[id]
      var model = Model.fromObject(item)
      if (model instanceof Model) {
        backup += model.title + '\n'
        self.addEntry(model)
      } else {
        chrome.storage.sync.remove(id)
      }
    }
    self.renderList()
    console.log('animus backup:')
    console.log('(you probably want to save this if your entries are missing)')
    console.log(backup)
  })
  chrome.storage.onChanged.addListener(function (changes, area) {
    // TODO: refactor
    if (area !== 'sync') return
    _.forEach(changes, function (change, id) {
      // failure to perform a change probably means that this instance was the
      // one that performed the sync / modified data
      var sucess = self.performChange(change, id)

      if (sucess && deepEqual(change, self.getNextUndo(), {strict: true})) {
        /**
         * another animus instance used undo, so we pop our undo stack
         *
         * edge-case: the other animus instance was older, and had some changes
         * in its undo stack, and it's popping changes this instance doesn't have
         */
        console.log('an animus instance used undo')
        self.undoStack.pop()
      } else {
        // add change to undostack, leave it ready for performChange
        console.log('added change to undo')
        var undoChange = {}
        if (change.newValue) undoChange.oldValue = change.newValue
        if (change.oldValue) undoChange.newValue = change.oldValue
        self.undoStack.push(undoChange)
      }
    })
    self.renderList()
  })
}
util.inherits(EntriesController, Controller)
_.mixin(EntriesController, Controller)

EntriesController.prototype.attach = function (el) {
  Controller.prototype.attach.call(this, el)
  this.input = this.$el.find('input')
  this.input.on('input', this.onInputChange.bind(this))
  this.input.on('focus', this.onFocusInput.bind(this))
}

EntriesController.prototype.setActive = function (flag) {
  flag = !!flag
  if (!this.active && flag) {
    this.attachKeyListener()
    this.focusInput()
    // recenter the view in case there was a resize whilst unactive
    this.renderList()
  } else if (this.active && !flag) {
    this.detachKeyListener()
  }
  this.active = flag
}

EntriesController.prototype.attachKeyListener = function () {
  document.addEventListener('keydown', this.boundOnKeydown, true)
}

EntriesController.prototype.detachKeyListener = function () {
  document.removeEventListener('keydown', this.boundOnKeydown, true)
}

EntriesController.prototype.onKeydown = function (evt) {
  // Prevent animus from blocking command usage, e.g. Cmd+Shift+F for fullscreen
  if (evt.altKey || evt.ctrlKey || evt.metaKey) {
    return
  }

  // Prevent websites to do stuff while we interact with animus
  // e.g. Wired automatically starts searching when a key is pressed
  evt.stopPropagation()

  if (evt.keyCode === keycode('esc')) {
    this.emit('toggle')
    return
  }

  if (this.inputIsFocused()) {
    switch (evt.keyCode) {

      case keycode('tab'):
        this.focusFirstEntry()
        evt.preventDefault()
        break

      case keycode('enter'):
        evt.preventDefault()
        // TODO: Refactor this into a function
        var val = this.input.val()
        if (val) {
          var Model = this.model
          var entry = new Model({
            title: val
          })
          entry.save()
          this.addEntry(entry)
          this.input.val('')
          // TODO: Why doesn't this fire automatticaly? trigger?
          this.onInputChange({srcElement: this.input[0]})
        }
        break

    }
  } else {
    var index
    switch (evt.keyCode) {

      case keycode('a'):
      case keycode('tab'):
        this.focusInput()
        evt.preventDefault()
        break

      case keycode('e'):
        var title = this.selectedEntryView.model.title
        this.deleteSelectedEntry()
        this.focusInput()
        this.input.val(title)
        evt.preventDefault()
        break

      case keycode('u'):
        this.undo()
        // since we might end up focusing the input when no entries are left
        evt.preventDefault()
        break

      case keycode('d'):
        this.deleteSelectedEntry()
        // since we might end up focusing the input when no entries are left
        evt.preventDefault()
        break

      case keycode('f'):
        if (this.selectedEntryView) {
          var link = this.selectedEntryView.model.getLink()
          if (link) {
            window.open(link, '_blank')
          }
        }
        break

      case keycode('j'):
        index = this.getSelectionIndex()
        index = Math.min(this.entryViewList.length - 1, index + 1)
        this.selectEntryViewAtIndex(index, true)
        break

      case keycode('k'):
        index = this.getSelectionIndex()
        index = Math.max(0, index - 1)
        this.selectEntryViewAtIndex(index, true)
        break

    }
  }

  if (evt.keyCode === keycode('enter') && evt.shiftKey) {
    evt.preventDefault()
    // close animus if shift+enter
    this.emit('toggle')
  }
}

EntriesController.prototype.addEntry = function (entry) {
  var ModelView = this.modelView
  var entryView = new ModelView(entry)
  entryView.on('click:tag', this.addTagToQuery.bind(this))
  entryView.on('hover', this.hoveredEntryView.bind(this))
  entryView.on('destroy', this.boundOnDeadEntryView)
  var list = this.$el.find('.animus-entry-list')
  list.prepend(entryView.$el)
  this.entryViewList.unshift(entryView)
}

/**
 * If the tag is not already part of the query, add it.
 *
 * @param {String} tag
 */
EntriesController.prototype.addTagToQuery = function (tag) {
  var val = this.input.val()
  var query = new Query(val)
  if (!query.hasTag(tag)) {
    // Add tag to query
    this.input.val(val + tag)
  } else {
    // Tags only have [#a-zA-Z], so don't worry about escaping regex
    var replacingTagRe = new RegExp(tag, 'g')
    var newVal = val.replace(replacingTagRe, '')
    this.input.val(newVal)
  }
  this.focusInput()
  // TODO: Why doesn't this fire automatticaly? trigger?
  this.onInputChange({srcElement: this.input[0]})
}

/**
 * Callback for the InputChange Event.
 *
 * @param {Event} evt
 */
EntriesController.prototype.onInputChange = function (evt) {
  var input = this.input[0]
  var query = new Query(input.value)
  for (var i = 0; i < this.entryViewList.length; ++i) {
    var entryView = this.entryViewList[i]
    entryView.applyQuery(query)
  }
  this.entryViewList = _.sortByOrder(this.entryViewList, ['matchScore'], [false])
  this.renderList()
  $(input)[query.title ? 'addClass' : 'removeClass']('has-content')
}

/**
 * Relocates EntryViews
 */
EntriesController.prototype.renderList = function (startIndex) {
  var entryView
  startIndex = Math.max(startIndex || 0, 0)
  for (var i = startIndex; i < this.entryViewList.length; ++i) {
    entryView = this.entryViewList[i]
    entryView.offsetY = i * 63
    entryView.$el.css('transform', 'translateY(' + entryView.offsetY + 'px)')
  }

  // We find out the list element with the largest width so that
  // we can make the input's width match it
  var maxWidth = 0
  for (var j = startIndex; j < this.entryViewList.length; ++j) {
    entryView = this.entryViewList[j]
    var domEl = entryView.$el[0]
    maxWidth = Math.max(maxWidth, domEl.offsetWidth)
  }
  this.$('.animus-new-entry-input').css('width', maxWidth)

  // We fake the list's height since all the list elements have top,left: 0px
  var listHeight = this.entryViewList.length * 63
  this.$('.animus-entry-list').css('height', listHeight + 'px')
  var inputHeight = 52
  if (listHeight) listHeight += 30
  var animusHeight = 100 + inputHeight + listHeight + 100
  this.offsetY = (window.innerHeight - animusHeight) / 2
  this.offsetY = Math.max(this.offsetY, 0)
  this.$el.css('transform', 'translateY(' + this.offsetY + 'px)')
}

/**
 * Callback for when an EntryView is hovered.
 * @param {EntryView} entryView
 */
EntriesController.prototype.hoveredEntryView = function (entryView) {
  clearTimeout(this.focusTimeout)
  if (entryView) {
    this.selectEntryViewAtIndex(this.entryViewList.indexOf(entryView))
    this.input.blur()
  } else {
    /**
     * mouseout is called when changing hover between elements, and focusing
     * the input scrolls, even just during the entry switch, scrolls the view
     * to the input. not desired.
     */
    this.focusTimeout = setTimeout(function () {
      if ($('#animus')[0].scrollTop === 0) {
        this.focusInput()
      }
    }.bind(this), 1)
  }
}

/**
 * Get index of selected EntryView. We store a cache of the index, but since
 * the entry list can be modified due to sync events, we must ensure the cached
 * index is still correct.
 *
 * @return {Number} selectionIndex
 */
EntriesController.prototype.getSelectionIndex = function () {
  if (!this.selectedEntryView) {
    return -1
  }
  var cachedEntryView = this.entryViewList[this.cachedSelectionIndex]
  if (cachedEntryView === this.selectedEntryView) {
    return this.cachedSelectionIndex
  }
  this.cachedSelectionIndex = this.entryViewList.indexOf(this.selectedEntryView)
  return this.cachedSelectionIndex
}

/**
 * Select the EntryView at the given index
 *
 * @param {Number} index
 */
EntriesController.prototype.selectEntryViewAtIndex = function (index, shortcut) {
  if (this.selectedEntryView) {
    this.selectedEntryView.setSelected(false)
  }
  var entryView = null
  if (index > -1) {
    entryView = this.entryViewList[index]
    entryView.setSelected(true)
  } else {
    index = -1
  }
  if (entryView && shortcut) {
    var entryViewTop = this.offsetY + 182 + entryView.offsetY
    var entryViewBottom = entryViewTop + 63
    var animus = $('#animus')[0]
    var windowTop = animus.scrollTop
    var windowHeight = window.innerHeight
    var windowBottom = windowTop + windowHeight
    var margin = 182
    if (windowTop + margin > entryViewTop) {
      animus.scrollTop = entryViewTop - margin
    } else if (windowBottom - margin < entryViewBottom) {
      animus.scrollTop = entryViewBottom + margin - windowHeight
    }
  }
  this.selectedEntryView = entryView
  this.cachedSelectionIndex = index
}

/**
 * Removes from the list and deletes data of the selected entry.
 *
 * A double-linked list would allow faster delete. Even though we have to
 * support random access entry selecting due to being able to hover entries, it
 * could be solved by referencing the list item from the EntryView.
 * (yay circular references)
 */
EntriesController.prototype.deleteSelectedEntry = function () {
  var index = this.getSelectionIndex()
  var entryView = this.entryViewList[index]
  if (!entryView) return
  entryView.deleteEntry(index)
}

/**
 * Dead entry view callback. It may give a `hint` about it's index in
 * entryViewList.
 *
 * @param {EntryView} entryView
 * @param {Number} hint
 */
EntriesController.prototype.onDeadEntryView = function (entryView, hint) {
  var index = hint
  if (index === -1) {
    // TODO: improve this, hashing
    if (this.selectedEntryView === entryView) {
      // happy coincidence
      index = this.getSelectionIndex()
    } else {
      index = this.entryViewList.indexOf(entryView)
    }
  }
  if (index === -1) return
  this.entryViewList.splice(index, 1)
  this.renderList(index)
  if (this.selectedEntryView === entryView) {
    this.selectedEntryView = null
    while (index >= this.entryViewList.length) --index
    this.selectEntryViewAtIndex(index)
    if (!this.selectedEntryView) {
      // no entries left
      this.focusInput()
    }
  }
}

/**
 * Undo the last action.
 */
EntriesController.prototype.undo = function () {
  var changedList = this.performChange(this.undoStack.pop())
  if (changedList) {
    this.renderList()
  }
}

EntriesController.prototype.getNextUndo = function () {
  return this.undoStack[this.undoStack.length - 1]
}

/**
 * Performs a change on the data, given by an oldValue and a newValue.
 *
 * @param {Object} change
 * @return {Boolean} success
 */

EntriesController.prototype.performChange = function (change) {
  var id = (change.newValue || change.oldValue).id
  var entry
  if (!change.newValue) {
    // deleted entry
    entry = Entry.items[id]
    if (!entry) return false
    if (entry instanceof Entry) entry.destroy()
    else Entry.items = undefined
  } else if (!change.oldValue) {
    // added entry
    if (Entry.items[id]) return false
    entry = Entry.fromObject(change.newValue)
    if (!(entry instanceof Entry)) return false
    this.addEntry(entry)
  } else {
    // updated entry
    // lol, we don't perform updates right now, we delete / re-create entries
    entry = Entry.items[id]
    entry.update(change.newValue)
  }
  return true
}

EntriesController.prototype.inputIsFocused = function () {
  return document.activeElement === this.input[0]
}

EntriesController.prototype.focusInput = function () {
  $('#animus')[0].scrollTop = 0
  this.input.focus()
}

EntriesController.prototype.onFocusInput = function (evt) {
  this.selectEntryViewAtIndex(-1)
}

EntriesController.prototype.focusFirstEntry = function () {
  if (this.entryViewList.length > 0) {
    this.selectEntryViewAtIndex(0)
  }
  this.input.blur()
}
<|endoftext|>


<commit_before>'use strict';
/**
 * CSS Controller
 */
module.exports = function ( ) {
	console.log("CssController");
	var self = this;
	self.blue = false;

	/**
	 * Check if blue css styling needs to be applied
	 * @return {Boolean} isBlue
	 */
	self.isBlue = function (){
		console.log(self.blue);
		return self.blue;
	}
};<commit_msg>remove logs<commit_after>'use strict';
/**
 * CSS Controller
 */
module.exports = function ( ) {

	var self = this;
	self.blue = false;

	/**
	 * Check if blue css styling needs to be applied
	 * @return {Boolean} isBlue
	 */
	self.isBlue = function (){
		return self.blue;
	}
};<|endoftext|>


<commit_before>
define([
  'jquery',
  'underscore',
  'backbone',
  'models/entry'
], function ($, _, Backbone, EksiEntry) {

  var Topic = Backbone.Collection.extend ({

    // 0 ASC
    // 1 DESC
    // 2 TODAY_ASC
    // 3 SUKELA
    order: 2,

    title: '',
    external_url: '',

    page: 1,
    pageCount: -1,

    url: function  () {
      var url = 'https://eksisozluk.com/' + this.external_url;

      url += this.external_url.match (/\?/) ? '&' : '?';
      url += 'p=' + (this.page <= 0 ? 1 : this.page);

      if (this.order == 2) {
        url += '&a=popular';
      } else if (this.order == 3) {
        url += '&a=nice';
      }

      return url;
    },

    parse: function (resp) {

      var entries = [];
      var htmlDoc = $.parseHTML (resp);

      this.title = $(htmlDoc).find ('#title a').text ();
      this.pageCount = $(htmlDoc).find ('div.pager').attr ('data-pagecount');

      $(htmlDoc).find ('article').each (function () {
        var entry = new EksiEntry ({ htmlDoc: this });
        entries.push (entry);
      });

      return entries;

    },

    // TODO: add DESC order
    firstPage: function () {

      this.page = 1;

    },

    nextPage: function () {

      this.page++;

    },

    lastPage: function () {

      return this.page >= this.pageCount;

    },

    fetch: function (options) {
      options = options || {};
      options.dataType = 'html';
      return Backbone.Collection.prototype.fetch.call (this, options);
    }

  });

  return Topic;
});
<commit_msg>check pageCount in lastPage ()<commit_after>
define([
  'jquery',
  'underscore',
  'backbone',
  'models/entry'
], function ($, _, Backbone, EksiEntry) {

  var Topic = Backbone.Collection.extend ({

    // 0 ASC
    // 1 DESC
    // 2 TODAY_ASC
    // 3 SUKELA
    order: 2,

    title: '',
    external_url: '',

    page: 1,
    pageCount: -1,

    url: function  () {
      var url = 'https://eksisozluk.com/' + this.external_url;

      url += this.external_url.match (/\?/) ? '&' : '?';
      url += 'p=' + (this.page <= 0 ? 1 : this.page);

      if (this.order == 2) {
        url += '&a=popular';
      } else if (this.order == 3) {
        url += '&a=nice';
      }

      return url;
    },

    parse: function (resp) {

      var entries = [];
      var htmlDoc = $.parseHTML (resp);

      this.title = $(htmlDoc).find ('#title a').text ();
      this.pageCount = $(htmlDoc).find ('div.pager').attr ('data-pagecount');

      $(htmlDoc).find ('article').each (function () {
        var entry = new EksiEntry ({ htmlDoc: this });
        entries.push (entry);
      });

      return entries;

    },

    // TODO: add DESC order
    firstPage: function () {

      this.page = 1;

    },

    nextPage: function () {

      this.page++;

    },

    lastPage: function () {

      // if pageCount is not defined, there's only one page
      // and it's our last page
      if (!this.pageCount)
        return true;

      return this.page >= this.pageCount;

    },

    fetch: function (options) {
      options = options || {};
      options.dataType = 'html';
      return Backbone.Collection.prototype.fetch.call (this, options);
    }

  });

  return Topic;
});
<|endoftext|>


<commit_before>/**
 * @file: PoliceDog web performance script for client side
 * @author: zhangxiang
 * @updated: 2017.05.29 14:29
 */

(function(){
    var win = window;

    function addHandler(type, callback) {

        if(win.addEventListener) {

            win.addEventListener(type, callback);

        } else if(win.attachEvent) {

            win.addEventListener('on' + type, callback);
        } else {

            win['on' + type] = callback;
        }
    }

    addHandler('load', function(){
            var perf = (function(){
            var perf = null;

            perf = win.performance ? win.performance : (win.wekitPerformance ? win.webkitPerformance : win.msPerformance);

            return perf;
        })();

        var sourceInfo = (function() {
            // Unfortunately Safari does not support ResourceTiming yet, so we'll just need to wait for them to support it.
            if(!perf || !perf.getEntries) {
                return null;
            }

            var entries = perf.getEntries();
            var javascriptNum = 0, cssNum = 0, imgNum = 0, javascriptTime = 0, cssTime = 0, imgTime = 0, QueryArr = [];

            entries.forEach(function(data, i){
                var name            = data.name;
                var initiatorType   = data.initiatorType;
                var DNSQuery        = data.domainLookupEnd - data.domainLookupStart;
                var connectTime     = data.connectEnd - data.connectStart;
                var duration        = data.duration;

                QueryArr.push({
                    name: name,
                    type: initiatorType,
                    DNSQuery: DNSQuery,
                    duration: duration,
                    connectTime: connectTime
                });
            });

            return QueryArr;
        })();

        var loadInfo = (function(){
            if(!perf) {
                return null;
            }

            var report = {}, resource = perf.timing;
            /**
             * to count the DNS Query time
             */
            var DNSquery = resource.domainLookupEnd - resource.domainLookupStart;
            report['DNSQuery'] = DNSquery;

            /**
             *to count the TCP connect time
             */
            var TCPconnect = resource.connectEnd - resource.connectStart;
            report['TCPConnect'] = TCPconnect;

            /**
             * to count the TTFB time
             */
            var TTFB = resource.responseStart - resource.navigationStart;
            report['TTFB'] = TTFB;

            /**
             * to count the response time
             */
            var responseTime = resource.responseEnd - resource.responseStart;
            report['RequestTime'] = responseTime;

            /**
             * to count white screen time
             */
            var whiteTime = resource.responseStart - resource.navigationStart;
            report['WhiteScreenTime'] = whiteTime;

            /**
             * to count analysis DOM time
             */
            var DOMAnalysis = resource.domContentLoadedEventEnd - resource.navigationStart;
            report['DOMAnalysis'] = DOMAnalysis;

            /**
             * to count load time
             */
            var loadTime = resource.loadEventEnd - resource.navigationStart;
            report['LoadTime'] = loadTime;

            return report;
        })();

        win.webPerf = {
            perf: perf,
            sourceInfo: sourceInfo,
            loadInfo: loadInfo,
            minimize: function(){

                var sourceInfo = this.sourceInfo, loadInfo = this.loadInfo, data = null;

                Object.keys(loadInfo).map(function(key, val){

                    if(val === 0) {
                        delete this[key];
                    }
                });

                data = {
                    userAgent: navigator.userAgent,
                    sourceInfo: sourceInfo,
                    loadInfo: loadInfo
                }

                return data;
            }
        };

        //兼容 forEach
        if(typeof Array.prototype.forEach !== 'function') {
            Array.prototype.forEach = function(fn, context){
                for(var k = 0, length = this.length; k < length; k++) {
                    if(typeof fn === 'function' && Object.prototype.hasOwnProperty.call(this.k)) {
                        fn.call(context, this[k], k, this);
                    }
                }
            }
        }
        /**
         * send data
         */
        var jsLoad = 0,
            jsDNSQuery = 0,
            jsAmount = 0;
            stylesheetLoad = 0,
            stylesheetDNSQuery = 0,
            stylesheetAmount = 0,
            imgLoad = 0,
            imgDNSQuery = 0,
            imgAmount = 0.
            xhrDNSQuery = 0,
            xhrload = 0,
            xhrAmount = 0;

        sourceInfo && sourceInfo.forEach(function(data, i){
            switch (data.type){
                case 'script':
                    jsLoad += data.duration;
                    jsDNSQuery += data.DNSQuery;
                    jsAmount ++;
                    break;
                case 'link':
                    stylesheetLoad += data.duration;
                    stylesheetDNSQuery += data.DNSQuery;
                    stylesheetAmount ++;
                    break;
                case 'img':
                    imgLoad += data.duration;
                    imgDNSQuery += data.DNSQuery;
                    imgAmount++;
                    break;
                case 'xmlhttprequest':
                    xhrDNSQuery += data.DNSQuery;
                    xhrload += data.duration;
                    xhrAmount++;
                    break;
            }
        });
        var sourceTime = {
            jsLoad: jsLoad,
            jsDNSQuery: jsDNSQuery,
            jsAmount: jsAmount,
            stylesheetLoad: stylesheetLoad,
            stylesheetDNSQuery: stylesheetDNSQuery,
            stylesheetAmount: stylesheetAmount,
            imgLoad: imgLoad,
            imgDNSQuery: imgDNSQuery,
            imgAmount: imgAmount,
            xhrload: xhrload,
            xhrDNSQuery: xhrDNSQuery,
            xhrAmount: xhrAmount
        }

        //页面加载信息，分为三个字段上报：页面整体加载时间，DNS 查询时间，TTFB
        ga('send', 'timing', 'pageload', 'load', loadInfo.LoadTime);
        ga('send', 'timing', 'pageload', 'DNSQuery', loadInfo.DNSQuery);
        ga('send', 'timing', 'pageload', 'TTFB', loadInfo.TTFB);
        //静态资源上报: Js 加载时间，DNS 查询时间，TTFB 时间以及 js 文件个数
        // 样式表 加载时间， DNS 查询时间， TTFB， stylesheel 文件个数
        // 图片 加载时间， DNS 查询时间， 图片个数
        if(sourceInfo) {
            ga('send', 'timing', 'entries', 'js loadtime', sourceTime.jsLoad);
            ga('send', 'timing', 'entries', 'js DNSQuery', sourceTime.jsDNSQuery);
            ga('send', 'timing', 'entries', 'js Amount', sourceTime.jsAmount);
            ga('send', 'timing', 'entries', 'css loadtime', sourceTime.stylesheetLoad);
            ga('send', 'timing', 'entries', 'css DNSQuery', sourceTime.stylesheetDNSQuery);
            ga('send', 'timing', 'entries', 'css Amount', sourceTime.stylesheetAmount);
            ga('send', 'timing', 'entries', 'img loadtime', sourceTime.imgLoad);
            ga('send', 'timing', 'entries', 'img DNSQuery', sourceTime.imgDNSQuery);
            ga('send', 'timing', 'entries', 'img Amount', sourceTime.imgAmount);
            ga('send', 'timing', 'entries', 'xhr load', sourceTime.xhrload);
            ga('send', 'timing', 'entries', 'xhr DNSQuery', sourceTime.xhrDNSQuery);
            ga('send', 'timing', 'entries', 'xhr Amount', sourceTime.xhrAmount);
        }
    });

})();
<commit_msg>换成 loadEventStart<commit_after>/**
 * @file: PoliceDog web performance script for client side
 * @author: zhangxiang
 * @updated: 2017.05.29 14:29
 */

(function(){
    var win = window;

    function addHandler(type, callback) {

        if(win.addEventListener) {

            win.addEventListener(type, callback);

        } else if(win.attachEvent) {

            win.addEventListener('on' + type, callback);
        } else {

            win['on' + type] = callback;
        }
    }

    addHandler('load', function(){
            var perf = (function(){
                var perf = null;

                perf = win.performance ? win.performance : (win.wekitPerformance ? win.webkitPerformance : win.msPerformance);

                return perf;
            })();

            var sourceInfo = (function() {
                // Unfortunately Safari does not support ResourceTiming yet, so we'll just need to wait for them to support it.
                if(!perf || !perf.getEntries) {
                    return null;
                }

                var entries = perf.getEntries();
                var javascriptNum = 0, cssNum = 0, imgNum = 0, javascriptTime = 0, cssTime = 0, imgTime = 0, QueryArr = [];

                entries.forEach(function(data, i){
                    var name            = data.name;
                    var initiatorType   = data.initiatorType;
                    var DNSQuery        = data.domainLookupEnd - data.domainLookupStart;
                    var connectTime     = data.connectEnd - data.connectStart;
                    var duration        = data.duration;

                    QueryArr.push({
                        name: name,
                        type: initiatorType,
                        DNSQuery: DNSQuery,
                        duration: duration,
                        connectTime: connectTime
                    });
                });

                return QueryArr;
            })();

            var loadInfo = (function(){
                if(!perf) {
                    return null;
                }

                var report = {}, resource = perf.timing;
                /**
                 * to count the DNS Query time
                 */
                var DNSquery = resource.domainLookupEnd - resource.domainLookupStart;
                report['DNSQuery'] = DNSquery;

                /**
                 *to count the TCP connect time
                 */
                var TCPconnect = resource.connectEnd - resource.connectStart;
                report['TCPConnect'] = TCPconnect;

                /**
                 * to count the TTFB time
                 */
                var TTFB = resource.responseStart - resource.navigationStart;
                report['TTFB'] = TTFB;

                /**
                 * to count the response time
                 */
                var responseTime = resource.responseEnd - resource.responseStart;
                report['RequestTime'] = responseTime;

                /**
                 * to count white screen time
                 */
                var whiteTime = resource.responseStart - resource.navigationStart;
                report['WhiteScreenTime'] = whiteTime;

                /**
                 * to count analysis DOM time
                 */
                var DOMAnalysis = resource.domContentLoadedEventEnd - resource.navigationStart;
                report['DOMAnalysis'] = DOMAnalysis;

                /**
                 * to count load time
                 */
                var loadTime = resource.loadEventStart - resource.navigationStart;
                report['LoadTime'] = loadTime;

                return report;
            })();

            win.webPerf = {
                perf: perf,
                sourceInfo: sourceInfo,
                loadInfo: loadInfo,
                minimize: function(){

                    var sourceInfo = this.sourceInfo, loadInfo = this.loadInfo, data = null;

                    Object.keys(loadInfo).map(function(key, val){

                        if(val === 0) {
                            delete this[key];
                        }
                    });

                    data = {
                        userAgent: navigator.userAgent,
                        sourceInfo: sourceInfo,
                        loadInfo: loadInfo
                    }

                    return data;
                }
            };

            //兼容 forEach
            if(typeof Array.prototype.forEach !== 'function') {
                Array.prototype.forEach = function(fn, context){
                    for(var k = 0, length = this.length; k < length; k++) {
                        if(typeof fn === 'function' && Object.prototype.hasOwnProperty.call(this.k)) {
                            fn.call(context, this[k], k, this);
                        }
                    }
                }
            }
            /**
             * send data
             */
            var jsLoad = 0,
                jsDNSQuery = 0,
                jsAmount = 0;
                stylesheetLoad = 0,
                stylesheetDNSQuery = 0,
                stylesheetAmount = 0,
                imgLoad = 0,
                imgDNSQuery = 0,
                imgAmount = 0.
                xhrDNSQuery = 0,
                xhrload = 0,
                xhrAmount = 0;

            sourceInfo && sourceInfo.forEach(function(data, i){
                switch (data.type){
                    case 'script':
                        jsLoad += data.duration;
                        jsDNSQuery += data.DNSQuery;
                        jsAmount ++;
                        break;
                    case 'link':
                        stylesheetLoad += data.duration;
                        stylesheetDNSQuery += data.DNSQuery;
                        stylesheetAmount ++;
                        break;
                    case 'img':
                        imgLoad += data.duration;
                        imgDNSQuery += data.DNSQuery;
                        imgAmount++;
                        break;
                    case 'xmlhttprequest':
                        xhrDNSQuery += data.DNSQuery;
                        xhrload += data.duration;
                        xhrAmount++;
                        break;
                }
            });
            var sourceTime = {
                jsLoad: jsLoad,
                jsDNSQuery: jsDNSQuery,
                jsAmount: jsAmount,
                stylesheetLoad: stylesheetLoad,
                stylesheetDNSQuery: stylesheetDNSQuery,
                stylesheetAmount: stylesheetAmount,
                imgLoad: imgLoad,
                imgDNSQuery: imgDNSQuery,
                imgAmount: imgAmount,
                xhrload: xhrload,
                xhrDNSQuery: xhrDNSQuery,
                xhrAmount: xhrAmount
            }

            //页面加载信息，分为三个字段上报：页面整体加载时间，DNS 查询时间，TTFB
            ga('send', 'timing', 'pageload', 'load', loadInfo.LoadTime);
            ga('send', 'timing', 'pageload', 'DNSQuery', loadInfo.DNSQuery);
            ga('send', 'timing', 'pageload', 'TTFB', loadInfo.TTFB);
            //静态资源上报: Js 加载时间，DNS 查询时间，TTFB 时间以及 js 文件个数
            // 样式表 加载时间， DNS 查询时间， TTFB， stylesheel 文件个数
            // 图片 加载时间， DNS 查询时间， 图片个数
            if(sourceInfo) {
                ga('send', 'timing', 'entries', 'js loadtime', sourceTime.jsLoad);
                ga('send', 'timing', 'entries', 'js DNSQuery', sourceTime.jsDNSQuery);
                ga('send', 'timing', 'entries', 'js Amount', sourceTime.jsAmount);
                ga('send', 'timing', 'entries', 'css loadtime', sourceTime.stylesheetLoad);
                ga('send', 'timing', 'entries', 'css DNSQuery', sourceTime.stylesheetDNSQuery);
                ga('send', 'timing', 'entries', 'css Amount', sourceTime.stylesheetAmount);
                ga('send', 'timing', 'entries', 'img loadtime', sourceTime.imgLoad);
                ga('send', 'timing', 'entries', 'img DNSQuery', sourceTime.imgDNSQuery);
                ga('send', 'timing', 'entries', 'img Amount', sourceTime.imgAmount);
                ga('send', 'timing', 'entries', 'xhr load', sourceTime.xhrload);
                ga('send', 'timing', 'entries', 'xhr DNSQuery', sourceTime.xhrDNSQuery);
                ga('send', 'timing', 'entries', 'xhr Amount', sourceTime.xhrAmount);
            }
    });

})();
<|endoftext|>


<commit_before>
define([
  'jquery',
  'underscore',
  'backbone',
  'models/entry',
  'helpers/app'
], function ($, _, Backbone, EksiEntry, AppHelper) {

  var Topic = Backbone.Collection.extend ({

    // 0 ASC
    // 1 DESC
    // 2 TODAY_ASC
    // 3 SUKELA
    order: 2,

    title: '',
    external_url: '',

    page: -1,
    pageCount: -1,

    url: function  () {
      var url = AppHelper.urlPrefix + this.external_url;

      url += this.external_url.match (/\?/) ? '&' : '?';
      url += 'p=' + (this.page <= 0 ? 1 : this.page);

      if (this.order == 2) {
        url += '&a=popular';
      } else if (this.order == 3) {
        url += '&a=nice';
      } else if (this.order > 3) {
        url += '&a=tracked&snapshot=' + this.order;
      }

      return url;
    },

    parse: function (resp) {

      var that = this;

      var entries = [];
      var htmlDoc = $.parseHTML (resp);

      this.title = $(htmlDoc).find ('#title a').text ();
      this.pageCount = $(htmlDoc).find ('div.pager').attr ('data-pagecount');

      this.external_url = $(htmlDoc).find ('#topic a')
                                    .attr ('href')
                                    .replace (/^\/*/, '');

      $(htmlDoc).find ('#entry-list li').each (function () {
        var entry = new EksiEntry ({ htmlDoc: this });

        // add entry to end of array if order is desc
        if (that.order == 1) {
          entries.unshift (entry);
        } else {
          entries.push (entry);
        }
      });

      return entries;

    },

    firstPage: function () {

      if (this.order == 1) {
        this.page = this.pageCount;
      } else {
        this.page = 1;
      }

    },

    nextPage: function () {

      if (this.order == 1) {
        this.page--;
      } else {
        this.page++;
      }

    },

    lastPage: function () {

      // if pageCount is not defined, there's only one page
      // and it's our last page
      if (!this.pageCount)
        return true;

      if (this.order == 1) {
        return this.page <= 1;
      } else {
        return this.page >= this.pageCount;
      }

    },

    fetch: function (options) {
      options = options || {};
      options.dataType = 'html';

      // if order is DESC, getting last page number
      // we will use last page number as first page in this collection
      if (this.order == 1 && this.page == -1) {
        var response = $.ajax ({
          type: 'GET',
          async: false,
          url: this.url ()
        }).responseText;
        var pageCount = $($.parseHTML (response)).find ('div.pager')
                                                 .attr ('data-pagecount');
        this.page = pageCount;
      }

      // if order is not DESC
      // first page is 1
      else if (this.page == -1) {
        this.page = 1;
      }

      return Backbone.Collection.prototype.fetch.call (this, options);
    }

  });

  return Topic;
});
<commit_msg>Add comment about snapshot order<commit_after>
define([
  'jquery',
  'underscore',
  'backbone',
  'models/entry',
  'helpers/app'
], function ($, _, Backbone, EksiEntry, AppHelper) {

  var Topic = Backbone.Collection.extend ({

    // 0 ASC
    // 1 DESC
    // 2 TODAY_ASC
    // 3 SUKELA
    // 3+ SNAPSHOT for followed topics
    order: 2,

    title: '',
    external_url: '',

    page: -1,
    pageCount: -1,

    url: function  () {
      var url = AppHelper.urlPrefix + this.external_url;

      url += this.external_url.match (/\?/) ? '&' : '?';
      url += 'p=' + (this.page <= 0 ? 1 : this.page);

      if (this.order == 2) {
        url += '&a=popular';
      } else if (this.order == 3) {
        url += '&a=nice';
      } else if (this.order > 3) {
        url += '&a=tracked&snapshot=' + this.order;
      }

      return url;
    },

    parse: function (resp) {

      var that = this;

      var entries = [];
      var htmlDoc = $.parseHTML (resp);

      this.title = $(htmlDoc).find ('#title a').text ();
      this.pageCount = $(htmlDoc).find ('div.pager').attr ('data-pagecount');

      this.external_url = $(htmlDoc).find ('#topic a')
                                    .attr ('href')
                                    .replace (/^\/*/, '');

      $(htmlDoc).find ('#entry-list li').each (function () {
        var entry = new EksiEntry ({ htmlDoc: this });

        // add entry to end of array if order is desc
        if (that.order == 1) {
          entries.unshift (entry);
        } else {
          entries.push (entry);
        }
      });

      return entries;

    },

    firstPage: function () {

      if (this.order == 1) {
        this.page = this.pageCount;
      } else {
        this.page = 1;
      }

    },

    nextPage: function () {

      if (this.order == 1) {
        this.page--;
      } else {
        this.page++;
      }

    },

    lastPage: function () {

      // if pageCount is not defined, there's only one page
      // and it's our last page
      if (!this.pageCount)
        return true;

      if (this.order == 1) {
        return this.page <= 1;
      } else {
        return this.page >= this.pageCount;
      }

    },

    fetch: function (options) {
      options = options || {};
      options.dataType = 'html';

      // if order is DESC, getting last page number
      // we will use last page number as first page in this collection
      if (this.order == 1 && this.page == -1) {
        var response = $.ajax ({
          type: 'GET',
          async: false,
          url: this.url ()
        }).responseText;
        var pageCount = $($.parseHTML (response)).find ('div.pager')
                                                 .attr ('data-pagecount');
        this.page = pageCount;
      }

      // if order is not DESC
      // first page is 1
      else if (this.page == -1) {
        this.page = 1;
      }

      return Backbone.Collection.prototype.fetch.call (this, options);
    }

  });

  return Topic;
});
<|endoftext|>


<commit_before>////////////////////////////////////////////////
/*   Provided Code - Please Don't Edit   */
////////////////////////////////////////////////
'use strict';

function getInput() {
    console.log("Please choose either 'rock', 'paper', or 'scissors'.")
    return prompt();
}
function randomPlay() {
    var randomNumber = Math.random();
    if (randomNumber < 0.33) {
        return "rock";
    } else if (randomNumber < 0.66) {
        return "paper";
    } else {
        return "scissors";
    }
}
////////////////////////////////////////////////
/*           Write Your Code Below            */
////////////////////////////////////////////////

function getPlayerMove(move) {
    // Write an expression that operates on a variable called `move`
    var move;
    // If a `move` has a value, your expression should evaluate to that value.
    if (move != null){
    	var userMove = move;
    } else {
    	var userMove = getInput();
    }
    // However, if `move` is not specified / is null, your expression should equal `getInput()`.
    return userMove;
}

function getComputerMove(move) {
    // Write an expression that operates on a variable called `move`
    var move;
    // If a `move` has a value, your expression should evaluate to that value.
    if (move != null){
    	var compsMove = move;
    } else {
    	var compsMove = randomPlay();
    }
    // However, if `move` is not specified / is null, your expression should equal `randomPlay()`.
    return compsMove;
}

function getWinner(playerMove,computerMove) {
    var winner;
    // Write code that will set winner to either 'player', 'computer', or 'tie' based on the values of playerMove and computerMove.
    // Assume that the only values playerMove and computerMove can have are 'rock', 'paper', and 'scissors'.
    // The rules of the game are that 'rock' beats 'scissors', 'scissors' beats 'paper', and 'paper' beats 'rock'.
    /* YOUR CODE HERE */
    return winner;
}

function playToFive() {
    console.log("Let's play Rock, Paper, Scissors");
    var playerWins = 0;
    var computerWins = 0;
    // Write code that plays 'Rock, Paper, Scissors' until either the player or the computer has won five times.
    /* YOUR CODE HERE */
    return [playerWins, computerWins];
}

<commit_msg>assignment 4 function getwinner with if else statement<commit_after>////////////////////////////////////////////////
/*   Provided Code - Please Don't Edit   */
////////////////////////////////////////////////
'use strict';

function getInput() {
    console.log("Please choose either 'rock', 'paper', or 'scissors'.")
    return prompt();
}
function randomPlay() {
    var randomNumber = Math.random();
    if (randomNumber < 0.33) {
        return "rock";
    } else if (randomNumber < 0.66) {
        return "paper";
    } else {
        return "scissors";
    }
}
////////////////////////////////////////////////
/*           Write Your Code Below            */
////////////////////////////////////////////////

function getPlayerMove(move) {
    // Write an expression that operates on a variable called `move`
    var move = null;
    var userMove;
    // If a `move` has a value, your expression should evaluate to that value.
    (move !== null)? userMove = move : userMove = getInput();
    // However, if `move` is not specified / is null, your expression should equal `getInput()`.
    return userMove;
}

function getComputerMove(move) {
    // Write an expression that operates on a variable called `move`
    var move = null;
    var compsMove;
    // If a `move` has a value, your expression should evaluate to that value.
	(move !== null)? compsMove = move : compsMove = getInput();
    // However, if `move` is not specified / is null, your expression should equal `randomPlay()`.
    return compsMove;
}

function getWinner(playerMove,computerMove) {
    var winner;
    // Write code that will set winner to either 'player', 'computer', or 'tie' based on the values of playerMove and computerMove.
    if (userMove == "rock" && compsMove == "paper"){
    	winner = "computer";
    }else if (userMove == "rock" && compsMove == "scissors"){
    	winner = "player";
    }else if (userMove == compsMove){
    	winner = "tie";
    }else if (userMove == "paper" && compsMove == "scissors"){
    	winner = "computer";
    }else if (userMove == "paper" && compsMove == "rock"){
    	winner = "player";
    }else if (userMove == "scissors" && compsMove == "rock"){
    	winner = "computer";
    }else if (userMove == "scissors" && compsMove == "paper"){
    	winner = "player";
    }
    return winner;
}

function playToFive() {
    console.log("Let's play Rock, Paper, Scissors");
    var playerWins = 0;
    var computerWins = 0;
    // Write code that plays 'Rock, Paper, Scissors' until either the player or the computer has won five times.
    /* YOUR CODE HERE */
    return [playerWins, computerWins];
}

<|endoftext|>


<commit_before>////////////////////////////////////////////////
/*   Provided Code - Please Don't Edit   */
////////////////////////////////////////////////
'use strict';

function getInput() {
    console.log("Please choose either 'rock', 'paper', or 'scissors'.")
    return prompt();
}
function randomPlay() {
    var randomNumber = Math.random();
    if (randomNumber < 0.33) {
        return "rock";
    } else if (randomNumber < 0.66) {
        return "paper";
    } else {
        return "scissors";
    }
}
////////////////////////////////////////////////
/*           Write Your Code Below            */
////////////////////////////////////////////////

function getPlayerMove(move) {
    // Write an expression that operates on a variable called `move`
    // If a `move` has a value, your expression should evaluate to that value.
    // However, if `move` is not specified / is null, your expression should equal `getInput()`.
    return var move = move || getInput();
}

function getComputerMove(move) {
    return var move = move || randomPlay();
}

function getWinner(playerMove,computerMove) {
    var winner;
    // Write code that will set winner to either 'player', 'computer', or 'tie' based on the values of playerMove and computerMove.
    // Assume that the only values playerMove and computerMove can have are 'rock', 'paper', and 'scissors'.
    // The rules of the game are that 'rock' beats 'scissors', 'scissors' beats 'paper', and 'paper' beats 'rock'.
    if (playerMove === 'rock' && computerMove === 'scissors'){
      winner = 'player';
    } else if (playerMove === 'scissors' && computerMove === 'paper'){
      winner = 'player';
    } else if (playerMove === 'paper' && computerMove === 'rock'){
      winner = 'player';
    } else if (playerMove === 'scissors' && computerMove === 'rock'){
      winner = 'computer';
    } else if (playerMove === 'paper' && computerMove === 'scissors'){
      winner = 'computer';
    } else if (playerMove === 'rock' && computerMove === 'paper'){
      winner = 'computer';
    } else {
        winner = 'tie';
    }
    return winner;
}

function playToFive() {
    console.log("Let's play Rock, Paper, Scissors");
    var playerWins = 0;
    var computerWins = 0;
    // Write code that plays 'Rock, Paper, Scissors' until either the player or the computer has won five times.
    /* YOUR CODE HERE */
    return [playerWins, computerWins];
}

<commit_msg>Final fundamentals homework<commit_after>////////////////////////////////////////////////
/*   Provided Code - Please Don't Edit   */
////////////////////////////////////////////////
'use strict';

function getInput() {
    console.log("Please choose either 'rock', 'paper', or 'scissors'.")
    return prompt();
}
function randomPlay() {
    var randomNumber = Math.random();
    if (randomNumber < 0.33) {
        return "rock";
    } else if (randomNumber < 0.66) {
        return "paper";
    } else {
        return "scissors";
    }
}
////////////////////////////////////////////////
/*           Write Your Code Below            */
////////////////////////////////////////////////

function getPlayerMove(move) {
    // Write an expression that operates on a variable called `move`
    // If a `move` has a value, your expression should evaluate to that value.
    // However, if `move` is not specified / is null, your expression should equal `getInput()`.
    var move = move || getInput();
    return move;
}

function getComputerMove(move) {
    // Write an expression that operates on a variable called `move`
    // If a `move` has a value, your expression should evaluate to that value.
    // However, if `move` is not specified / is null, your expression should equal `randomPlay()`.
    var move = move || randomPlay();
    return move;
}

function getWinner(playerMove,computerMove) {
    var winner;
    if (playerMove === 'rock') {
        if (computerMove === 'scissors') {
            return winner = 'player';
        }
        else if (computerMove === 'paper') {
            return winner = 'computer';
        }
    }
    else if (playerMove === 'paper') {
        if (computerMove === 'rock') {
            return winner = 'player';
        }
        else if (computerMove === 'scissors'){
            return winner = 'computer';
        }
    }
    else if (playerMove === 'scissors') {
        if (computerMove === 'paper') {
            return winner = 'player';
        }
        else if (computerMove === 'rock') {
            return winner = 'computer';
        }
    }
    else return winner = 'tie';
}

function playToFive() {
    console.log("Let's play Rock, Paper, Scissors");
    var playerWins = 0;
    var computerWins = 0;
    while ((playerWins < 5) && (computerWins < 5)) {
        console.log("the score is currently " + playerWins + " to " + computerWins);
        var playerMove = getPlayerMove(getInput());
        var computerMove = getComputerMove(randomPlay());
        var winner = getWinner(playerMove,computerMove);
        console.log("player chose " + playerMove + " while computer chose " + computerMove);
        if (winner = 'player') {
            playerWins += 1;
            console.log("player wins this round!");
        }
        else if (winner = 'computer') {
            computerWins += 1;
            console.log("computer wins this round!");
        }
        else console.log("round tied.");
    }
    console.log("GAME OVER");
    return [playerWins, computerWins];
}

playToFive()<|endoftext|>


<commit_before>////////////////////////////////////////////////
/*   Provided Code - Please Don't Edit   */
////////////////////////////////////////////////
'use strict';

function getInput() {
    console.log("Please choose either 'rock', 'paper', or 'scissors'.")
    return prompt();
}
function randomPlay() {
    var randomNumber = Math.random();
    if (randomNumber < 0.33) {
        return "rock";
    } else if (randomNumber < 0.66) {
        return "paper";
    } else {
        return "scissors";
    }
}
////////////////////////////////////////////////
/*           Write Your Code Below            */
////////////////////////////////////////////////

function getPlayerMove(move) {
    // Write an expression that operates on a variable called `move`
    // If a `move` has a value, your expression should evaluate to that value.
    // However, if `move` is not specified / is null, your expression should equal `getInput()`.
    return /* Your Expression */;
}

function getComputerMove(move) {
    // Write an expression that operates on a variable called `move`
    // If a `move` has a value, your expression should evaluate to that value.
    // However, if `move` is not specified / is null, your expression should equal `randomPlay()`.
    return /* Your Expression */;
}

function getWinner(playerMove,computerMove) {
    var winner;
    // Write code that will set winner to either 'player', 'computer', or 'tie' based on the values of playerMove and computerMove.
    // Assume that the only values playerMove and computerMove can have are 'rock', 'paper', and 'scissors'.
    // The rules of the game are that 'rock' beats 'scissors', 'scissors' beats 'paper', and 'paper' beats 'rock'.
    /* YOUR CODE HERE */
    return winner;
}

function playToFive() {
    console.log("Let's play Rock, Paper, Scissors");
    var playerWins = 0;
    var computerWins = 0;
    // Write code that plays 'Rock, Paper, Scissors' until either the player or the computer has won five times.
    /* YOUR CODE HERE */
    return [playerWins, computerWins];
}

<commit_msg>Homework 3.6 added playerMove and computerMove<commit_after>////////////////////////////////////////////////
/*   Provided Code - Please Don't Edit   */
////////////////////////////////////////////////
'use strict';

function getInput() {
    console.log("Please choose either 'rock', 'paper', or 'scissors'.")
    return prompt();
}
function randomPlay() {
    var randomNumber = Math.random();
    if (randomNumber < 0.33) {
        return "rock";
    } else if (randomNumber < 0.66) {
        return "paper";
    } else {
        return "scissors";
    }
}
////////////////////////////////////////////////
/*           Write Your Code Below            */
////////////////////////////////////////////////

function getPlayerMove(move) {
    var playerMove = move || getInput();
    return(playerMove);
}

function getComputerMove(move) {
   var computerMove = move || randomPlay();
   return (computerMove);
}

function getWinner(playerMove,computerMove) {
    var winner;
    // Write code that will set winner to either 'player', 'computer', or 'tie' based on the values of playerMove and computerMove.
    // Assume that the only values playerMove and computerMove can have are 'rock', 'paper', and 'scissors'.
    // The rules of the game are that 'rock' beats 'scissors', 'scissors' beats 'paper', and 'paper' beats 'rock'.
    /* YOUR CODE HERE */
    return winner;
}

function playToFive() {
    console.log("Let's play Rock, Paper, Scissors");
    var playerWins = 0;
    var computerWins = 0;
    // Write code that plays 'Rock, Paper, Scissors' until either the player or the computer has won five times.
    /* YOUR CODE HERE */
    return [playerWins, computerWins];
}

<|endoftext|>


<commit_before><commit_msg>updated correct verison<commit_after><|endoftext|>


<commit_before>
////////////////////////////////////////////////
/*   Provided Code - Please Don't Edit   */
////////////////////////////////////////////////
'use strict';

function getInput() {
    console.log("Please choose either 'rock', 'paper', or 'scissors'.");
    return prompt();
}
function randomPlay() {
    var randomNumber = Math.random();
    if (randomNumber < 0.33) {
        return "rock";
    } else if (randomNumber < 0.66) {
        return "paper";
    } else {
        return "scissors";
    }
}
////////////////////////////////////////////////
/*           Write Your Code Below            */
////////////////////////////////////////////////

function getPlayerMove(move) {
    // If a `move` has a value, your expression should evaluate to that value.
    // However, if `move` is not specified / is null, your expression should equal `getInput()`.
    return (move = move || getInput());
}

function getComputerMove(move) {
    // Write an expression that operates on a variable called `move`
    // If a `move` has a value, your expression should evaluate to that value.
    // However, if `move` is not specified / is null, your expression should equal `randomPlay()`.
    return (move = move || randomPlay());
}

function getWinner(playerMove,computerMove) {
    var winner;
    // Write code that will set winner to either 'player', 'computer', or 'tie' based on the values of playerMove and computerMove.
    // Assume that the only values playerMove and computerMove can have are 'rock', 'paper', and 'scissors'.
    // The rules of the game are that 'rock' beats 'scissors', 'scissors' beats 'paper', and 'paper' beats 'rock'.
    if ((playerMove = 'rock') && (computerMove = 'rock')) {
        winner = 'tie';
    } else if ((playerMove = 'rock') && (computerMove = "paper")){
        winner = 'computer';
    } else if ((playerMove = 'rock') && (computerMove = 'scissors')) {
        winner = 'player';
    }
    return winner;
}

function playToFive() {
    console.log("Let's play Rock, Paper, Scissors");
    var playerWins = 0;
    var computerWins = 0;
    getInput();
    while (playerWins < 5 || computerWins <5) {
        var player = getPlayerMove();
        var computer = getComputerMove();
        var winner = getWinner();
    if (winner === player) {
        playerWins = (playerWins + 1);
        console.log("You win this time! Try again:");
        playToFive();
    } else if (winner === computer) {
        computerWins = (computerWins + 1);
        console.log("Sorry, you lose. Try again:");
        playToFive();
    }
     if (playerWins === 5) {
        console.log("You won against your opponent's" + " " + computerWins + " " + "games! Way to go!");
    } else if (computerWins === 5) {
        console.log("Sorry, you lost" + " " + computerWins + " " + "games.");
    }break;
    }

}
playToFive();
    <commit_msg>Tried and failed at rock paper scissors.<commit_after>
////////////////////////////////////////////////
/*   Provided Code - Please Don't Edit   */
////////////////////////////////////////////////
'use strict';

function getInput() {
    console.log("Please choose either 'rock', 'paper', or 'scissors'.");
    return prompt();
}
function randomPlay() {
    var randomNumber = Math.random();
    if (randomNumber < 0.33) {
        return "rock";
    } else if (randomNumber < 0.66) {
        return "paper";
    } else {
        return "scissors";
    }
}
////////////////////////////////////////////////
/*           Write Your Code Below            */
////////////////////////////////////////////////

function getPlayerMove(move) {
    // If a `move` has a value, your expression should evaluate to that value.
    // However, if `move` is not specified / is null, your expression should equal `getInput()`.
    return (move = move || getInput());
}

function getComputerMove(move) {
    // Write an expression that operates on a variable called `move`
    // If a `move` has a value, your expression should evaluate to that value.
    // However, if `move` is not specified / is null, your expression should equal `randomPlay()`.
    return (move = move || randomPlay());
}

function getWinner(playerMove,computerMove) {
    var winner;
    // Write code that will set winner to either 'player', 'computer', or 'tie' based on the values of playerMove and computerMove.
    // Assume that the only values playerMove and computerMove can have are 'rock', 'paper', and 'scissors'.
    // The rules of the game are that 'rock' beats 'scissors', 'scissors' beats 'paper', and 'paper' beats 'rock'.
    if ((playerMove = 'rock') && (computerMove = 'rock')) {
        winner = 'tie';
    } else if ((playerMove = 'rock') && (computerMove = "paper")){
        winner = 'computer';
    } else if ((playerMove = 'rock') && (computerMove = 'scissors')) {
        winner = 'player';
    }
    return winner;
}

function playToFive() {
    console.log("Let's play Rock, Paper, Scissors");
    var playerWins = 0;
    var computerWins = 0;
    getInput();
    while (playerWins < 5 || computerWins < 5) {
        var player = getPlayerMove();
        var computer = getComputerMove();
        var winner = getWinner();
    if (winner === player) {
        playerWins = (playerWins + 1);
        console.log("You win this time! Try again:");
        playToFive();
    } else if (winner === computer) {
        computerWins = (computerWins + 1);
        console.log("Sorry, you lose. Try again:");
        playToFive();
    }
     if (playerWins === 5) {
        console.log("You won against your opponent's" + " " + computerWins + " " + "games! Way to go!");
    } else if (computerWins === 5) {
        console.log("Sorry, you lost" + " " + computerWins + " " + "games.");
    }break;
    }

}
playToFive();
    <|endoftext|>


<commit_before>////////////////////////////////////////////////
/*   Provided Code - Please Don't Edit   */
////////////////////////////////////////////////
'use strict';

function getInput() {
    console.log("Please choose either 'rock', 'paper', or 'scissors'.")
    return prompt();
}
function randomPlay() {
    var randomNumber = Math.random();
    if (randomNumber < 0.33) {
        return "rock";
    } else if (randomNumber < 0.66) {
        return "paper";
    } else {
        return "scissors";
    }
}
////////////////////////////////////////////////
/*           Write Your Code Below            */
////////////////////////////////////////////////

function getPlayerMove(move) {
    // var  Write an expression that operates on a variable called `move`
    // If a `move` has a value, your expression should evaluate to that value.
    // However, if `move` is not specified / is null, your expression should equal `getInput()`.
    return move || getInput();
}

function getComputerMove(move) {
    // Write an expression that operates on a variable called `move`
    // If a `move` has a value, your expression should evaluate to that value.
    // However, if `move` is not specified / is null, your expression should equal `randomPlay()`.
    return move || getInput();
}

function getWinner(playerMove,computerMove) {
    var winner;
    // Write code that will set winner to either 'player', 'computer', or 'tie' based on the values of playerMove and computerMove.
    // Assume that the only values playerMove and computerMove can have are 'rock', 'paper', and 'scissors'.
    // The rules of the game are that 'rock' beats 'scissors', 'scissors' beats 'paper', and 'paper' beats 'rock'.
    /* YOUR CODE HERE */
    return winner;
}

function playToFive() {
    console.log("Let's play Rock, Paper, Scissors");
    var playerWins = 0;
    var computerWins = 0;
    // Write code that plays 'Rock, Paper, Scissors' until either the player or the computer has won five times.
    /* YOUR CODE HERE */
    return [playerWins, computerWins];
}
<commit_msg>fixed return move function getComputerMove and added code for function getWinner<commit_after>////////////////////////////////////////////////
/*   Provided Code - Please Don't Edit   */
////////////////////////////////////////////////
'use strict';

function getInput() {
    console.log("Please choose either 'rock', 'paper', or 'scissors'.")
    return prompt();
}
function randomPlay() {
    var randomNumber = Math.random();
    if (randomNumber < 0.33) {
        return "rock";
    } else if (randomNumber < 0.66) {
        return "paper";
    } else {
        return "scissors";
    }
}
////////////////////////////////////////////////
/*           Write Your Code Below            */
////////////////////////////////////////////////

function getPlayerMove(move) {
    // var  Write an expression that operates on a variable called `move`
    // If a `move` has a value, your expression should evaluate to that value.
    // However, if `move` is not specified / is null, your expression should equal `getInput()`.
    return move || getInput();
}

function getComputerMove(move) {
    // Write an expression that operates on a variable called `move`
    // If a `move` has a value, your expression should evaluate to that value.
    // However, if `move` is not specified / is null, your expression should equal `randomPlay()`.
    return move || randomPlay();
}

function getWinner(playerMove,computerMove) {
    var winner;
    // Write code that will set winner to either 'player', 'computer', or 'tie' based on the values of playerMove and computerMove.
    // Assume that the only values playerMove and computerMove can have are 'rock', 'paper', and 'scissors'.
    // The rules of the game are that 'rock' beats 'scissors', 'scissors' beats 'paper', and 'paper' beats 'rock'.
    if playerMove === "rock"{
      if computerMove === "rock"{
      winner = "tie";
      }
      else if computerMove === "paper" {
      winner = "computer";
      }
      else {
      winner = "player":
      }
    }

    if playerMove === "paper"{
      if computerMove === "paper"{
        winner = "tie";
      }
      else if computerMove === "scissors"{
        winner = "computer";
      }
      else {
        winner = "player"
      }
    }

    if playerMove === "scissors"{
      if computerMove === "scissors"{
        winner = "tie";
      }
      else if computerMove === "rock"{
        winner = "computer";
      }
      else {
        winner = "player";
      }
    }

    }
    return winner;
}

function playToFive() {
    console.log("Let's play Rock, Paper, Scissors");
    var playerWins = 0;
    var computerWins = 0;
    // Write code that plays 'Rock, Paper, Scissors' until either the player or the computer has won five times.
    /* YOUR CODE HERE */
    return [playerWins, computerWins];
}
<|endoftext|>


<commit_before>'use strict';

import Reflux       from 'reflux';
import TweetActions from '../actions/TweetActions';

var key             =  require('../config/keys.json');

var TweetStore = Reflux.createStore({

    init() {
        this.listenTo(TweetActions.postTweetUser, this.postTweetUser);
        this.listenTo(TweetActions.tweetPostSuccess, this.tweetPostSuccess);
        this.listenTo(TweetActions.tweetPostFail, this.tweetPostFail);
    },

    postTweetUser(tweet){
        var data = {};
            data.tweet = tweet;
            data.usersId = localStorage.getItem('key');

        $.ajax({
            dataType: 'json',
            contentType: "application/json",
            type: 'POST',
            url: 'https://api.parse.com/1/classes/post',
            data: JSON.stringify(data),
            headers: { 'X-Parse-Application-Id': key.applicationid, 'X-Parse-REST-API-Key': key.restapi }
        })
        .done((data) => {
            return this.tweetPostSuccess(data.objectId, data.createdAt);
        })
        .fail((jqXhr) => {
            this.tweetPostFail(jqXhr.responseJSON.message);
        });
    },

    tweetPostSuccess(objectId, createdAt){
        toastr.success('code user: ' + objectId + ', created ' + createdAt, 'User Register');
        return true;
    },

    tweetPostFail(msj){
        toastr.success(msj, 'Error');
    },

});

export default TweetStore;
<commit_msg>msg post tweet<commit_after>'use strict';

import Reflux       from 'reflux';
import TweetActions from '../actions/TweetActions';

var key             =  require('../config/keys.json');

var TweetStore = Reflux.createStore({

    init() {
        this.listenTo(TweetActions.postTweetUser, this.postTweetUser);
        this.listenTo(TweetActions.tweetPostSuccess, this.tweetPostSuccess);
        this.listenTo(TweetActions.tweetPostFail, this.tweetPostFail);
    },

    postTweetUser(tweet){
        var data = {};
            data.tweet = tweet;
            data.usersId = localStorage.getItem('key');

        $.ajax({
            dataType: 'json',
            contentType: "application/json",
            type: 'POST',
            url: 'https://api.parse.com/1/classes/post',
            data: JSON.stringify(data),
            headers: { 'X-Parse-Application-Id': key.applicationid, 'X-Parse-REST-API-Key': key.restapi }
        })
        .done((data) => {
            return this.tweetPostSuccess(data.objectId, data.createdAt);
        })
        .fail((jqXhr) => {
            this.tweetPostFail(jqXhr.responseJSON.message);
        });
    },

    tweetPostSuccess(objectId, createdAt){
        toastr.success('Tweet Send');
        return true;
    },

    tweetPostFail(msj){
        toastr.success(msj, 'Error');
    },

});

export default TweetStore;
<|endoftext|>


<commit_before>const ListenerInfo = require('./listener-info')

const registerListenerInfo = (method, event, selector) => {
  method.__events__ = method.__events__ || []

  method.__events__.push(new ListenerInfo(event, selector, method))
}

/**
 * The decorator for registering event listener info to the method.
 * @deprecated in favour of `@on`
 * @param {string} event The event name
 * @param {string} selector The selector for listening. When null is passed, the listener listens on the root element of the component.
 */
const event = (event, selector) => (target, key, descriptor) => {
  registerListenerInfo(descriptor.value, event, selector)
}

/**
 * The decorator for registering event listener info to the method.
 * @param {string} event The event name
 */
const on = (event) => {
  const onDecorator = (target, key, descriptor) => {
    registerListenerInfo(descriptor.value, event)
  }

  /**
   * The decorator for registering event listener info to the method.
   * @param {string} event The event name
   * @param {string} selector The selector for listening.
   */
  onDecorator.at = (selector) => (target, key, descriptor) => {
    registerListenerInfo(descriptor.value, event, selector)
  }

  return onDecorator
}

/**
 * The decorator to prepend and append event trigger.
 * @deprecated in favour of `@emit`
 * @param {string} start The event name when the method started
 * @param {string} end The event name when the method finished
 * @param {string} error the event name when the method errored
 */
const trigger = (start, end, error) => (target, key, descriptor) => {
  const method = descriptor.value

  const decorated = function () {
    if (start != null) {
      this.elem.trigger(start)
    }

    const result = method.apply(this, arguments)

    const promise = Promise.resolve(result)

    if (end != null) {
      promise.then(() => this.elem.trigger(end))
    }

    if (error != null) {
      promise.catch(() => this.elem.trigger(error))
    }

    return result
  }

  descriptor.value = decorated
}

/**
 * `@emit(event)` decorator.
 * This decorator adds the event emission at the beginning of the method.
 * @param {string} event The event name
 */
const emit = (event) => {
  const emitDecorator = (target, key, descriptor) => {
    const method = descriptor.value

    descriptor.value = function () {
      this.elem.trigger(event)

      method.apply(this, arguments)
    }
  }

  /**
   * `@emit(event).first` decorator. This is the same as emit()
   * @param {string} event The event name
   */
  emitDecorator.first = emitDecorator

  /**
   * `@emit(event).last` decorator.
   * This adds the emission of the event at the end of the method.
   * @param {string} event The event name
   */
  emitDecorator.last = (target, key, descriptor) => {
    const method = descriptor.value

    descriptor.value = function () {
      const result = method.apply(this, arguments)

      if (typeof result.then === 'function') {
        Promise.resolve(result).then(x => this.elem.trigger(event, x))
      } else {
        this.elem.trigger(event, result)
      }

      return result
    }
  }

  /**
   * `@emit(event).on.error` decorator.
   * This add the emission of the event when the method errored.
   * @param {string} event The event name
   */
  const error = (target, key, descriptor) => {
    const method = descriptor.value

    descriptor.value = function () {
      let result
      try {
        result = method.apply(this, arguments)
      } catch (e) {
        this.elem.trigger(event, e)

        throw e
      }

      Promise.resolve(result).catch(err => {
        this.elem.trigger(event, e)
      })

      return result
    }
  }

  emitDecorator.on = {error}

  return emitDecorator
}

exports.on = on
exports.event = event
exports.trigger = trigger
exports.emit = emit
<commit_msg>fix(decorator): add null check of the result value<commit_after>const ListenerInfo = require('./listener-info')

const registerListenerInfo = (method, event, selector) => {
  method.__events__ = method.__events__ || []

  method.__events__.push(new ListenerInfo(event, selector, method))
}

/**
 * The decorator for registering event listener info to the method.
 * @deprecated in favour of `@on`
 * @param {string} event The event name
 * @param {string} selector The selector for listening. When null is passed, the listener listens on the root element of the component.
 */
const event = (event, selector) => (target, key, descriptor) => {
  registerListenerInfo(descriptor.value, event, selector)
}

/**
 * The decorator for registering event listener info to the method.
 * @param {string} event The event name
 */
const on = (event) => {
  const onDecorator = (target, key, descriptor) => {
    registerListenerInfo(descriptor.value, event)
  }

  /**
   * The decorator for registering event listener info to the method.
   * @param {string} event The event name
   * @param {string} selector The selector for listening.
   */
  onDecorator.at = (selector) => (target, key, descriptor) => {
    registerListenerInfo(descriptor.value, event, selector)
  }

  return onDecorator
}

/**
 * The decorator to prepend and append event trigger.
 * @deprecated in favour of `@emit`
 * @param {string} start The event name when the method started
 * @param {string} end The event name when the method finished
 * @param {string} error the event name when the method errored
 */
const trigger = (start, end, error) => (target, key, descriptor) => {
  const method = descriptor.value

  const decorated = function () {
    if (start != null) {
      this.elem.trigger(start)
    }

    const result = method.apply(this, arguments)

    const promise = Promise.resolve(result)

    if (end != null) {
      promise.then(() => this.elem.trigger(end))
    }

    if (error != null) {
      promise.catch(() => this.elem.trigger(error))
    }

    return result
  }

  descriptor.value = decorated
}

/**
 * `@emit(event)` decorator.
 * This decorator adds the event emission at the beginning of the method.
 * @param {string} event The event name
 */
const emit = (event) => {
  const emitDecorator = (target, key, descriptor) => {
    const method = descriptor.value

    descriptor.value = function () {
      this.elem.trigger(event)

      method.apply(this, arguments)
    }
  }

  /**
   * `@emit(event).first` decorator. This is the same as emit()
   * @param {string} event The event name
   */
  emitDecorator.first = emitDecorator

  /**
   * `@emit(event).last` decorator.
   * This adds the emission of the event at the end of the method.
   * @param {string} event The event name
   */
  emitDecorator.last = (target, key, descriptor) => {
    const method = descriptor.value

    descriptor.value = function () {
      const result = method.apply(this, arguments)

      if (result != null && typeof result.then === 'function') {
        Promise.resolve(result).then(x => this.elem.trigger(event, x))
      } else {
        this.elem.trigger(event, result)
      }

      return result
    }
  }

  /**
   * `@emit(event).on.error` decorator.
   * This add the emission of the event when the method errored.
   * @param {string} event The event name
   */
  const error = (target, key, descriptor) => {
    const method = descriptor.value

    descriptor.value = function () {
      let result
      try {
        result = method.apply(this, arguments)
      } catch (e) {
        this.elem.trigger(event, e)

        throw e
      }

      Promise.resolve(result).catch(err => {
        this.elem.trigger(event, e)
      })

      return result
    }
  }

  emitDecorator.on = {error}

  return emitDecorator
}

exports.on = on
exports.event = event
exports.trigger = trigger
exports.emit = emit
<|endoftext|>