<commit_before>//     Zepto.js
//     (c) 2010-2013 Thomas Fuchs
//     Zepto.js may be freely distributed under the MIT license.

;(function($){
  var $$ = $.zepto.qsa, _zid = 1, undefined,
      slice = Array.prototype.slice,
      isFunction = $.isFunction,
      isString = function(obj){ return typeof obj == 'string' },
      handlers = {},
      specialEvents={},
      focus = { focus: 'focusin', blur: 'focusout' },
      hover = { mouseenter: 'mouseover', mouseleave: 'mouseout' }

  specialEvents.click = specialEvents.mousedown = specialEvents.mouseup = specialEvents.mousemove = 'MouseEvents'

  function zid(element) {
    return element._zid || (element._zid = _zid++)
  }
  function findHandlers(element, event, fn, selector) {
    event = parse(event)
    if (event.ns) var matcher = matcherFor(event.ns)
    return (handlers[zid(element)] || []).filter(function(handler) {
      return handler
        && (!event.e  || handler.e == event.e)
        && (!event.ns || matcher.test(handler.ns))
        && (!fn       || zid(handler.fn) === zid(fn))
        && (!selector || handler.sel == selector)
    })
  }
  function parse(event) {
    var parts = ('' + event).split('.')
    return {e: parts[0], ns: parts.slice(1).sort().join(' ')}
  }
  function matcherFor(ns) {
    return new RegExp('(?:^| )' + ns.replace(' ', ' .* ?') + '(?: |$)')
  }

  function eventCapture(handler, captureSetting) {
    return handler.del &&
      !!captureSetting
  }

  function realEvent(type) {
    return hover[type] || focus[type] || type
  }

  function add(element, events, fn, data, selector, delegator, capture){
    var id = zid(element), set = (handlers[id] || (handlers[id] = []))
    events.split(/\s/).forEach(function(event){
      if (event == 'ready') return $(document).ready(fn)
      var handler   = parse(event)
      handler.fn    = fn
      handler.sel   = selector
      // emulate mouseenter, mouseleave
      if (handler.e in hover) fn = function(e){
        var related = e.relatedTarget
        if (!related || (related !== this && !$.contains(this, related)))
          return handler.fn.apply(this, arguments)
      }
      handler.del   = delegator
      var callback  = delegator || fn
      handler.proxy = function(e){
        e = compatible(e)
        if (e.isImmediatePropagationStopped()) return
        e.data = data
        var result = callback.apply(element, e._args == undefined ? [e] : [e].concat(e._args))
        if (result === false) e.preventDefault(), e.stopPropagation()
        return result
      }
      handler.i = set.length
      set.push(handler)
      if ('addEventListener' in element)
        element.addEventListener(realEvent(handler.e), handler.proxy, eventCapture(handler, capture))
    })
  }
  function remove(element, events, fn, selector, capture){
    var id = zid(element)
    ;(events || '').split(/\s/).forEach(function(event){
      findHandlers(element, event, fn, selector).forEach(function(handler){
        delete handlers[id][handler.i]
      if ('removeEventListener' in element)
        element.removeEventListener(realEvent(handler.e), handler.proxy, eventCapture(handler, capture))
      })
    })
  }

  $.event = { add: add, remove: remove }

  $.proxy = function(fn, context) {
    if (isFunction(fn)) {
      var proxyFn = function(){ return fn.apply(context, arguments) }
      proxyFn._zid = zid(fn)
      return proxyFn
    } else if (isString(context)) {
      return $.proxy(fn[context], fn)
    } else {
      throw new TypeError("expected function")
    }
  }

  $.fn.bind = function(event, data, callback){
    return this.on(event, data, callback)
  }
  $.fn.unbind = function(event, callback){
    return this.off(event, callback)
  }
  $.fn.one = function(event, selector, data, callback){
    return this.on(event, selector, data, callback, 1)
  }

  var returnTrue = function(){return true},
      returnFalse = function(){return false},
      ignoreProperties = /^([A-Z]|returnValue$|layer[XY]$)/,
      eventMethods = {
        preventDefault: 'isDefaultPrevented',
        stopImmediatePropagation: 'isImmediatePropagationStopped',
        stopPropagation: 'isPropagationStopped'
      }

  function compatible(event, source) {
    if (source || !event.isDefaultPrevented) {
      source || (source = event)

      $.each(eventMethods, function(name, predicate) {
        var sourceMethod = source[name]
        event[name] = function(){
          this[predicate] = returnTrue
          return sourceMethod && sourceMethod.apply(source, arguments)
        }
        event[predicate] = returnFalse
      })

      if (source.defaultPrevented !== undefined ? source.defaultPrevented :
          'returnValue' in source ? source.returnValue === false :
          source.getPreventDefault && source.getPreventDefault())
        event.isDefaultPrevented = returnTrue
    }
    return event
  }

  function createProxy(event) {
    var key, proxy = { originalEvent: event }
    for (key in event)
      if (!ignoreProperties.test(key) && event[key] !== undefined) proxy[key] = event[key]

    return compatible(proxy, event)
  }

  $.fn.delegate = function(selector, event, callback){
    return this.on(event, selector, callback)
  }
  $.fn.undelegate = function(selector, event, callback){
    return this.off(event, selector, callback)
  }

  $.fn.live = function(event, callback){
    $(document.body).delegate(this.selector, event, callback)
    return this
  }
  $.fn.die = function(event, callback){
    $(document.body).undelegate(this.selector, event, callback)
    return this
  }

  $.fn.on = function(event, selector, data, callback, one){
    var autoRemove, delegator, $this = this
    if (event && !isString(event)) {
      $.each(event, function(type, fn){
        $this.on(type, selector, data, fn, one)
      })
      return $this
    }

    if (!isString(selector) && !isFunction(callback) && callback !== false)
      callback = data, data = selector, selector = undefined
    if (isFunction(data) || data === false)
      callback = data, data = undefined

    if (callback === false) callback = returnFalse

    return $this.each(function(_, element){
      if (one) autoRemove = function(e){
        remove(element, e.type, callback)
        return callback.apply(this, arguments)
      }

      if (selector) delegator = function(e){
        var evt, match = $(e.target).closest(selector, element).get(0)
        if (match && match !== element) {
          evt = $.extend(createProxy(e), {currentTarget: match, liveFired: element})
          return (autoRemove || callback).apply(match, [evt].concat(slice.call(arguments, 1)))
        }
      }

      add(element, event, callback, data, selector, delegator || autoRemove)
    })
  }
  $.fn.off = function(event, selector, callback){
    var $this = this
    if (event && !isString(event)) {
      $.each(event, function(type, fn){
        $this.off(type, selector, fn)
      })
      return $this
    }

    if (!isString(selector) && !isFunction(callback) && callback !== false)
      callback = selector, selector = undefined

    if (callback === false) callback = returnFalse

    return $this.each(function(){
      remove(this, event, callback, selector)
    })
  }

  $.fn.trigger = function(event, args){
    event = (isString(event) || $.isPlainObject(event)) ? $.Event(event) : compatible(event)
    event._args = args
    return this.each(function(){
      // items in the collection might not be DOM elements
      if('dispatchEvent' in this) this.dispatchEvent(event)
      else $(this).triggerHandler(event, args)
    })
  }

  // triggers event handlers on current element just as if an event occurred,
  // doesn't trigger an actual event, doesn't bubble
  $.fn.triggerHandler = function(event, args){
    var e, result
    this.each(function(i, element){
      e = createProxy(isString(event) ? $.Event(event) : event)
      e._args = args
      e.target = element
      $.each(findHandlers(element, event.type || event), function(i, handler){
        result = handler.proxy(e)
        if (e.isImmediatePropagationStopped()) return false
      })
    })
    return result
  }

  // shortcut methods for `.bind(event, fn)` for each event type
  ;('focusin focusout load resize scroll unload click dblclick '+
  'mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave '+
  'change select keydown keypress keyup error').split(' ').forEach(function(event) {
    $.fn[event] = function(callback) {
      return callback ?
        this.bind(event, callback) :
        this.trigger(event)
    }
  })

  ;['focus', 'blur'].forEach(function(name) {
    $.fn[name] = function(callback) {
      if (callback) this.bind(name, callback)
      else this.each(function(){
        try { this[name]() }
        catch(e) {}
      })
      return this
    }
  })

  $.Event = function(type, props) {
    if (!isString(type)) props = type, type = props.type
    var event = document.createEvent(specialEvents[type] || 'Events'), bubbles = true
    if (props) for (var name in props) (name == 'bubbles') ? (bubbles = !!props[name]) : (event[name] = props[name])
    event.initEvent(type, bubbles, true)
    return compatible(event)
  }

})(Zepto)
<commit_msg>Fix focus/blur delegation in Firefox and Android<commit_after>//     Zepto.js
//     (c) 2010-2013 Thomas Fuchs
//     Zepto.js may be freely distributed under the MIT license.

;(function($){
  var $$ = $.zepto.qsa, _zid = 1, undefined,
      slice = Array.prototype.slice,
      isFunction = $.isFunction,
      isString = function(obj){ return typeof obj == 'string' },
      handlers = {},
      specialEvents={},
      focusinSupported = 'onfocusin' in window,
      focus = { focus: 'focusin', blur: 'focusout' },
      hover = { mouseenter: 'mouseover', mouseleave: 'mouseout' }

  specialEvents.click = specialEvents.mousedown = specialEvents.mouseup = specialEvents.mousemove = 'MouseEvents'

  function zid(element) {
    return element._zid || (element._zid = _zid++)
  }
  function findHandlers(element, event, fn, selector) {
    event = parse(event)
    if (event.ns) var matcher = matcherFor(event.ns)
    return (handlers[zid(element)] || []).filter(function(handler) {
      return handler
        && (!event.e  || handler.e == event.e)
        && (!event.ns || matcher.test(handler.ns))
        && (!fn       || zid(handler.fn) === zid(fn))
        && (!selector || handler.sel == selector)
    })
  }
  function parse(event) {
    var parts = ('' + event).split('.')
    return {e: parts[0], ns: parts.slice(1).sort().join(' ')}
  }
  function matcherFor(ns) {
    return new RegExp('(?:^| )' + ns.replace(' ', ' .* ?') + '(?: |$)')
  }

  function eventCapture(handler, captureSetting) {
    return handler.del &&
      (!focusinSupported && (handler.e in focus)) ||
      !!captureSetting
  }

  function realEvent(type) {
    return hover[type] || (focusinSupported && focus[type]) || type
  }

  function add(element, events, fn, data, selector, delegator, capture){
    var id = zid(element), set = (handlers[id] || (handlers[id] = []))
    events.split(/\s/).forEach(function(event){
      if (event == 'ready') return $(document).ready(fn)
      var handler   = parse(event)
      handler.fn    = fn
      handler.sel   = selector
      // emulate mouseenter, mouseleave
      if (handler.e in hover) fn = function(e){
        var related = e.relatedTarget
        if (!related || (related !== this && !$.contains(this, related)))
          return handler.fn.apply(this, arguments)
      }
      handler.del   = delegator
      var callback  = delegator || fn
      handler.proxy = function(e){
        e = compatible(e)
        if (e.isImmediatePropagationStopped()) return
        e.data = data
        var result = callback.apply(element, e._args == undefined ? [e] : [e].concat(e._args))
        if (result === false) e.preventDefault(), e.stopPropagation()
        return result
      }
      handler.i = set.length
      set.push(handler)
      if ('addEventListener' in element)
        element.addEventListener(realEvent(handler.e), handler.proxy, eventCapture(handler, capture))
    })
  }
  function remove(element, events, fn, selector, capture){
    var id = zid(element)
    ;(events || '').split(/\s/).forEach(function(event){
      findHandlers(element, event, fn, selector).forEach(function(handler){
        delete handlers[id][handler.i]
      if ('removeEventListener' in element)
        element.removeEventListener(realEvent(handler.e), handler.proxy, eventCapture(handler, capture))
      })
    })
  }

  $.event = { add: add, remove: remove }

  $.proxy = function(fn, context) {
    if (isFunction(fn)) {
      var proxyFn = function(){ return fn.apply(context, arguments) }
      proxyFn._zid = zid(fn)
      return proxyFn
    } else if (isString(context)) {
      return $.proxy(fn[context], fn)
    } else {
      throw new TypeError("expected function")
    }
  }

  $.fn.bind = function(event, data, callback){
    return this.on(event, data, callback)
  }
  $.fn.unbind = function(event, callback){
    return this.off(event, callback)
  }
  $.fn.one = function(event, selector, data, callback){
    return this.on(event, selector, data, callback, 1)
  }

  var returnTrue = function(){return true},
      returnFalse = function(){return false},
      ignoreProperties = /^([A-Z]|returnValue$|layer[XY]$)/,
      eventMethods = {
        preventDefault: 'isDefaultPrevented',
        stopImmediatePropagation: 'isImmediatePropagationStopped',
        stopPropagation: 'isPropagationStopped'
      }

  function compatible(event, source) {
    if (source || !event.isDefaultPrevented) {
      source || (source = event)

      $.each(eventMethods, function(name, predicate) {
        var sourceMethod = source[name]
        event[name] = function(){
          this[predicate] = returnTrue
          return sourceMethod && sourceMethod.apply(source, arguments)
        }
        event[predicate] = returnFalse
      })

      if (source.defaultPrevented !== undefined ? source.defaultPrevented :
          'returnValue' in source ? source.returnValue === false :
          source.getPreventDefault && source.getPreventDefault())
        event.isDefaultPrevented = returnTrue
    }
    return event
  }

  function createProxy(event) {
    var key, proxy = { originalEvent: event }
    for (key in event)
      if (!ignoreProperties.test(key) && event[key] !== undefined) proxy[key] = event[key]

    return compatible(proxy, event)
  }

  $.fn.delegate = function(selector, event, callback){
    return this.on(event, selector, callback)
  }
  $.fn.undelegate = function(selector, event, callback){
    return this.off(event, selector, callback)
  }

  $.fn.live = function(event, callback){
    $(document.body).delegate(this.selector, event, callback)
    return this
  }
  $.fn.die = function(event, callback){
    $(document.body).undelegate(this.selector, event, callback)
    return this
  }

  $.fn.on = function(event, selector, data, callback, one){
    var autoRemove, delegator, $this = this
    if (event && !isString(event)) {
      $.each(event, function(type, fn){
        $this.on(type, selector, data, fn, one)
      })
      return $this
    }

    if (!isString(selector) && !isFunction(callback) && callback !== false)
      callback = data, data = selector, selector = undefined
    if (isFunction(data) || data === false)
      callback = data, data = undefined

    if (callback === false) callback = returnFalse

    return $this.each(function(_, element){
      if (one) autoRemove = function(e){
        remove(element, e.type, callback)
        return callback.apply(this, arguments)
      }

      if (selector) delegator = function(e){
        var evt, match = $(e.target).closest(selector, element).get(0)
        if (match && match !== element) {
          evt = $.extend(createProxy(e), {currentTarget: match, liveFired: element})
          return (autoRemove || callback).apply(match, [evt].concat(slice.call(arguments, 1)))
        }
      }

      add(element, event, callback, data, selector, delegator || autoRemove)
    })
  }
  $.fn.off = function(event, selector, callback){
    var $this = this
    if (event && !isString(event)) {
      $.each(event, function(type, fn){
        $this.off(type, selector, fn)
      })
      return $this
    }

    if (!isString(selector) && !isFunction(callback) && callback !== false)
      callback = selector, selector = undefined

    if (callback === false) callback = returnFalse

    return $this.each(function(){
      remove(this, event, callback, selector)
    })
  }

  $.fn.trigger = function(event, args){
    event = (isString(event) || $.isPlainObject(event)) ? $.Event(event) : compatible(event)
    event._args = args
    return this.each(function(){
      // items in the collection might not be DOM elements
      if('dispatchEvent' in this) this.dispatchEvent(event)
      else $(this).triggerHandler(event, args)
    })
  }

  // triggers event handlers on current element just as if an event occurred,
  // doesn't trigger an actual event, doesn't bubble
  $.fn.triggerHandler = function(event, args){
    var e, result
    this.each(function(i, element){
      e = createProxy(isString(event) ? $.Event(event) : event)
      e._args = args
      e.target = element
      $.each(findHandlers(element, event.type || event), function(i, handler){
        result = handler.proxy(e)
        if (e.isImmediatePropagationStopped()) return false
      })
    })
    return result
  }

  // shortcut methods for `.bind(event, fn)` for each event type
  ;('focusin focusout load resize scroll unload click dblclick '+
  'mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave '+
  'change select keydown keypress keyup error').split(' ').forEach(function(event) {
    $.fn[event] = function(callback) {
      return callback ?
        this.bind(event, callback) :
        this.trigger(event)
    }
  })

  ;['focus', 'blur'].forEach(function(name) {
    $.fn[name] = function(callback) {
      if (callback) this.bind(name, callback)
      else this.each(function(){
        try { this[name]() }
        catch(e) {}
      })
      return this
    }
  })

  $.Event = function(type, props) {
    if (!isString(type)) props = type, type = props.type
    var event = document.createEvent(specialEvents[type] || 'Events'), bubbles = true
    if (props) for (var name in props) (name == 'bubbles') ? (bubbles = !!props[name]) : (event[name] = props[name])
    event.initEvent(type, bubbles, true)
    return compatible(event)
  }

})(Zepto)
<|endoftext|>


<commit_before>// Account Model

dc.model.Account = Backbone.Model.extend({

  ADMINISTRATOR      : 1,

  CONTRIBUTOR        : 2,

  REVIEWER           : 3,

  ROLE_NAMES         : ['', 'administrator', 'contributor', 'reviewer'],

  GRAVATAR_BASE      : location.protocol + (location.protocol == 'https:' ? '//secure.' : '//www.') + 'gravatar.com/avatar/',

  DEFAULT_AVATAR     : location.protocol + '//' + location.host + '/images/embed/icons/user_blue_32.png',

  BLANK_ACCOUNT      : {first_name : '', last_name : '', email : '', role : 2},

  constructor : function(attributes, options) {
    Backbone.Model.call(this, attributes || this.BLANK_ACCOUNT, options);
  },

  organization : function() {
    return Organizations.get(this.get('organization_id'));
  },

  openDocuments : function(options) {
    options || (options = {});
    var suffix = options.published ? ' filter: published' : '';
    dc.app.searcher.search('account: ' + this.get('slug') + suffix);
  },

  openOrganizationDocuments : function() {
    dc.app.searcher.search('group: ' + dc.account.organization.slug);
  },

  allowedToEdit: function(model) {
    return this.ownsOrOrganization(model) || this.collaborates(model);
  },

  ownsOrOrganization: function(model) {
    return (model.get('account_id') == this.id) ||
           (model.get('organization_id') == this.get('organization_id') &&
            this.isEditor() &&
            _.contains(['public', 'exclusive', 'organization'], model.get('access')));
  },

  collaborates: function(model) {
    var docId = model.get('document_id') || model.id;
    for (var i = 0, l = Projects.length; i < l; i++) {
      var project = Projects.models[i];
      if (_.include(project.get('document_ids'), docId) && !project.isReviewerProject()) {
        for (var j = 0, k = project.collaborators.length; j < k; j++) {
          var collab = project.collaborators.models[j];
          if (collab.ownsOrOrganization(model)) return true;
        }
      }
    }
    return false;
  },

  fullName : function(nonbreaking) {
    var name = this.get('first_name') + ' ' + this.get('last_name');
    return nonbreaking ? name.replace(/\s/g, ' ') : name;
  },

  documentsTitle : function() {
    return Inflector.possessivize(this.fullName()) + ' Documents';
  },

  isAdmin : function() {
    return this.attributes.role == this.ADMINISTRATOR;
  },

  isEditor : function() {
    var role = this.attributes.role;
    return role == this.ADMINISTRATOR || role == this.CONTRIBUTOR;
  },

  isPending : function() {
    return !!this.get('pending');
  },

  searchUrl : function() {
    return "/#search/" + encodeURIComponent("account: " + this.get('slug'));
  },

  gravatarUrl : function(size) {
    var hash = this.get('hashed_email');
    var fallback = encodeURIComponent(this.DEFAULT_AVATAR);
    return this.GRAVATAR_BASE + hash + '.jpg?s=' + size + '&d=' + fallback;
  },

  resendWelcomeEmail: function(options) {
    var url = '/accounts/' + this.id + '/resend_welcome';
    $.ajax(_.extend(options || {}, {type : 'POST', dataType : 'json', url : url}));
  }

});

dc.model.Account.COLLABORATOR_ROLES = [
  dc.model.Account.prototype.ADMINISTRATOR,
  dc.model.Account.prototype.CONTRIBUTOR
];

// Account Set
dc.model.AccountSet = Backbone.Collection.extend({

  model : dc.model.Account,
  url   : '/accounts',

  comparator : function(account) {
    return (account.get('last_name') || '').toLowerCase() + ' ' + (account.get('first_name') || '').toLowerCase();
  },

  getBySlug : function(slug) {
    return this.detect(function(account) {
      return account.get('slug') === slug;
    });
  },

  // Fetch the account of the logged-in journalist.
  current : function() {
    if (!dc.account) return null;
    return this.get(dc.account.id);
  },

  // All accounts other than yours.
  others : function() {
    return this.filter(function(account) {
      return account.id !== dc.account.id;
    });
  },

  // If the contributor has logged-out of the workspace in a different tab,
  // force the logout here.
  forceLogout : function() {
    dc.ui.Dialog.alert('You are no longer logged in to DocumentCloud.', {onClose : function() {
      window.location = '/logout';
    }});
  }

});

window.Accounts = new dc.model.AccountSet();
<commit_msg>Fixing access controls for collaboration on documents by using both NUMBERS and STRINGS for access control.<commit_after>// Account Model

dc.model.Account = Backbone.Model.extend({

  ADMINISTRATOR      : 1,

  CONTRIBUTOR        : 2,

  REVIEWER           : 3,

  ROLE_NAMES         : ['', 'administrator', 'contributor', 'reviewer'],

  GRAVATAR_BASE      : location.protocol + (location.protocol == 'https:' ? '//secure.' : '//www.') + 'gravatar.com/avatar/',

  DEFAULT_AVATAR     : location.protocol + '//' + location.host + '/images/embed/icons/user_blue_32.png',

  BLANK_ACCOUNT      : {first_name : '', last_name : '', email : '', role : 2},

  constructor : function(attributes, options) {
    Backbone.Model.call(this, attributes || this.BLANK_ACCOUNT, options);
  },

  organization : function() {
    return Organizations.get(this.get('organization_id'));
  },

  openDocuments : function(options) {
    options || (options = {});
    var suffix = options.published ? ' filter: published' : '';
    dc.app.searcher.search('account: ' + this.get('slug') + suffix);
  },

  openOrganizationDocuments : function() {
    dc.app.searcher.search('group: ' + dc.account.organization.slug);
  },

  allowedToEdit: function(model) {
    return this.ownsOrOrganization(model) || this.collaborates(model);
  },

  ownsOrOrganization: function(model) {
    return (model.get('account_id') == this.id) ||
           (model.get('organization_id') == this.get('organization_id') &&
            this.isEditor() &&
            _.contains([
              dc.access.PUBLIC, dc.access.EXCLUSIVE, dc.access.ORGANIZATION,
              'public', 'exclusive', 'organization'
            ], model.get('access')));
  },

  collaborates: function(model) {
    var docId = model.get('document_id') || model.id;
    for (var i = 0, l = Projects.length; i < l; i++) {
      var project = Projects.models[i];
      if (_.include(project.get('document_ids'), docId) && !project.isReviewerProject()) {
        for (var j = 0, k = project.collaborators.length; j < k; j++) {
          var collab = project.collaborators.models[j];
          if (collab.ownsOrOrganization(model)) return true;
        }
      }
    }
    return false;
  },

  fullName : function(nonbreaking) {
    var name = this.get('first_name') + ' ' + this.get('last_name');
    return nonbreaking ? name.replace(/\s/g, ' ') : name;
  },

  documentsTitle : function() {
    return Inflector.possessivize(this.fullName()) + ' Documents';
  },

  isAdmin : function() {
    return this.attributes.role == this.ADMINISTRATOR;
  },

  isEditor : function() {
    var role = this.attributes.role;
    return role == this.ADMINISTRATOR || role == this.CONTRIBUTOR;
  },

  isPending : function() {
    return !!this.get('pending');
  },

  searchUrl : function() {
    return "/#search/" + encodeURIComponent("account: " + this.get('slug'));
  },

  gravatarUrl : function(size) {
    var hash = this.get('hashed_email');
    var fallback = encodeURIComponent(this.DEFAULT_AVATAR);
    return this.GRAVATAR_BASE + hash + '.jpg?s=' + size + '&d=' + fallback;
  },

  resendWelcomeEmail: function(options) {
    var url = '/accounts/' + this.id + '/resend_welcome';
    $.ajax(_.extend(options || {}, {type : 'POST', dataType : 'json', url : url}));
  }

});

dc.model.Account.COLLABORATOR_ROLES = [
  dc.model.Account.prototype.ADMINISTRATOR,
  dc.model.Account.prototype.CONTRIBUTOR
];

// Account Set
dc.model.AccountSet = Backbone.Collection.extend({

  model : dc.model.Account,
  url   : '/accounts',

  comparator : function(account) {
    return (account.get('last_name') || '').toLowerCase() + ' ' + (account.get('first_name') || '').toLowerCase();
  },

  getBySlug : function(slug) {
    return this.detect(function(account) {
      return account.get('slug') === slug;
    });
  },

  // Fetch the account of the logged-in journalist.
  current : function() {
    if (!dc.account) return null;
    return this.get(dc.account.id);
  },

  // All accounts other than yours.
  others : function() {
    return this.filter(function(account) {
      return account.id !== dc.account.id;
    });
  },

  // If the contributor has logged-out of the workspace in a different tab,
  // force the logout here.
  forceLogout : function() {
    dc.ui.Dialog.alert('You are no longer logged in to DocumentCloud.', {onClose : function() {
      window.location = '/logout';
    }});
  }

});

window.Accounts = new dc.model.AccountSet();
<|endoftext|>


<commit_before>import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter, Route, Switch, Redirect } from 'react-router-dom';
import { Provider } from 'react-redux';
import store from './store';

import '../stylesheets/app.less';
// Components
import App from './components/app';
import RegistrationForm from './containers/registration';
// import EditAccountInfo from './components/edit_account';
import LandingPage from './components/landing_page';
import LogInForm from './components/login';
import AccountPage from './components/account';
import EditAccountInfo from './components/edit_account';

import { authTransition } from './actions/login';

const Root = props => {
  //isLogged in will go here, does not exist yet!
  //login redirect if logged in is true needs to redirect to the landing page
  const isLoggedIn = authTransition.bind(null, store);
  console.log(isLoggedIn)

  return (
    <Provider store={store}>
      <BrowserRouter>
        <App>
          <Switch>
            <Route path="/registration" render={() => !isLoggedIn() ? (<RegistrationForm />) : (<Redirect to="/" />)} />
            <Route path="/login" render={() => isLoggedIn() ? (<Redirect to="/account" />) : (<LogInForm />)} />
            <Route exact path="/account/:id/edit" render={() => isLoggedIn() ? (<EditAccountInfo />) : (<Redirect to="/login" />)} />
            <Route path="/account" render={() => isLoggedIn() ? (<AccountPage />) : (<Redirect to="/login" />)} />
            <Route path="/" render={() => isLoggedIn() ? (<LandingPage />) : (<Redirect to="/login" />)} />
          </Switch>
        </App>
      </BrowserRouter>
    </Provider>
  );
};

ReactDOM.render(<Root />, document.getElementById('root'));
<commit_msg>linted index.js<commit_after>import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter, Route, Switch, Redirect } from 'react-router-dom';
import { Provider } from 'react-redux';
import store from './store';

import '../stylesheets/app.less';
// Components
import App from './components/app';
import RegistrationForm from './containers/registration';
// import EditAccountInfo from './components/edit_account';
import LandingPage from './components/landing_page';
import LogInForm from './components/login';
import AccountPage from './components/account';
import EditAccountInfo from './components/edit_account';

import { authTransition } from './actions/login';

const Root = () => {
  // checks if user id !==null and if authToken exists iin localStorage;
  // will refactor to seperate concerns;
  const isLoggedIn = authTransition.bind(null, store);

  return (
    <Provider store={store}>
      <BrowserRouter>
        <App>
          <Switch>
            <Route
              path="/registration"
              render={
                () => !isLoggedIn() ? (<RegistrationForm />) : (<Redirect to="/" />)
              }
            />
            <Route
              path="/login"
              render={
                () => isLoggedIn() ? (<Redirect to="/account" />) : (<LogInForm />)
              }
            />
            <Route
              exact path="/account/:id/edit"
              render={
                () => isLoggedIn() ? (<EditAccountInfo />) : (<Redirect to="/login" />)
              }
            />
            <Route
              path="/account"
              render={
                () => isLoggedIn() ? (<AccountPage />) : (<Redirect to="/login" />)
              }
            />
            <Route
              path="/"
              render={
                () => isLoggedIn() ? (<LandingPage />) : (<Redirect to="/login" />)
              }
            />
          </Switch>
        </App>
      </BrowserRouter>
    </Provider>
  );
};

ReactDOM.render(<Root />, document.getElementById('root'));
<|endoftext|>


<commit_before>/**
 * Copyright (C) 2011 Instructure, Inc.
 *
 * This file is part of Canvas.
 *
 * Canvas is free software: you can redistribute it and/or modify it under
 * the terms of the GNU Affero General Public License as published by the Free
 * Software Foundation, version 3 of the License.
 *
 * Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
 * details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */

$(document).ready(function() {
  $(".add_bank_link").click(function(event) {
    event.preventDefault();
    var $bank = $("#question_bank_blank").clone(true).attr('id', 'question_bank_new');
    $("#questions").prepend($bank.show());
    $bank.find(".edit_bank_link").click();
  });
  $(".question_bank .delete_bank_link").click(function(event) {
    event.preventDefault();
    $(this).parents(".question_bank").confirmDelete({
      url: $(this).attr('href'),
      message: "Are you sure you want to delete this bank of questions?",
      success: function() {
        $(this).slideUp(function() {
          $(this).remove();
        });
      }
    });
  });
  $(".question_bank .bookmark_bank_link").click(function(event) {
    event.preventDefault();
    var $link = $(this);
    var $bank = $link.parents(".question_bank");
    $.ajaxJSON($(this).attr('href'), 'POST', {}, function(data) {
      $bank.find(".bookmark_bank_link").toggle();
    });
  });
  $(".question_bank .edit_bank_link").click(function(event) {
    event.preventDefault();
    var $bank = $(this).parents(".question_bank");
    var data = $bank.getTemplateData({textValues: ['title']});
    $bank.find(".header_content").hide();
    var $form = $("#edit_bank_form");
    $bank.find(".header").prepend($form.show());
    $form.attr('action', $(this).attr('href'));
    $form.attr('method', 'PUT');
    if($bank.attr('id') == 'question_bank_new') {
      $form.attr('action', $("#bank_urls .add_bank_url").attr('href'));
      $form.attr('method', 'POST');
    }
    $form.fillFormData(data, {object_name: 'assessment_question_bank'});
    $form.find(":text:visible:first").focus().select();
  });
  $("#edit_bank_form .bank_name_box").keycodes('return esc', function(event) {
    if(event.keyString == 'esc') {
      $(this).parents(".question_bank").addClass('dont_save')
      $(this).blur();
    } else if(event.keyString == 'return') {
      $("#edit_bank_form").submit();
    }
  });
  $("#edit_bank_form .bank_name_box").blur(function() {
    var $bank = $(this).parents(".question_bank");
    if(!$bank.hasClass('dont_save') && $bank.attr('id') != 'question_bank_new') {
      $("#edit_bank_form").submit();
      return;
    }
    $bank.removeClass('dont_save');
    $bank.find(".header_content").show();
    $("body").append($("#edit_bank_form").hide());
    if($bank.attr('id') == 'question_bank_new') {
      $bank.remove();
    }
  });
  $("#edit_bank_form").formSubmit({
    object_name: 'assessment_question_bank',
    beforeSubmit: function(data) {
      var $bank = $(this).parents(".question_bank");
      $bank.attr('id', 'question_bank_adding');
      try {
        $bank.addClass('dont_save');
        $bank.find(".bank_name_box").blur();
        $bank.removeClass('saving');
      } catch(e) { }
      $bank.fillTemplateData({
        data: data
      });
      $bank.loadingImage();
      return $bank;
    },
    success: function(data, $bank) {
      $bank.loadingImage('remove');
      var bank = data.assessment_question_bank;
      bank.last_updated_at = $.parseFromISO(bank.updated_at).datetime_formatted;
      $bank.fillTemplateData({
        data: bank,
        hrefValues: ['id']
      })
    },
    error: function(data, $bank) {
      $bank.loadingImage('remove');
      $bank.find(".edit_bank_link").click();
      $("#edit_bank_form").formErrors(data);
    }
  });
});
<commit_msg>don't create 2 question banks when hitting enter; fixes #4105<commit_after>/**
 * Copyright (C) 2011 Instructure, Inc.
 *
 * This file is part of Canvas.
 *
 * Canvas is free software: you can redistribute it and/or modify it under
 * the terms of the GNU Affero General Public License as published by the Free
 * Software Foundation, version 3 of the License.
 *
 * Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
 * details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */

$(document).ready(function() {
  $(".add_bank_link").click(function(event) {
    event.preventDefault();
    var $bank = $("#question_bank_blank").clone(true).attr('id', 'question_bank_new');
    $("#questions").prepend($bank.show());
    $bank.find(".edit_bank_link").click();
  });
  $(".question_bank .delete_bank_link").click(function(event) {
    event.preventDefault();
    $(this).parents(".question_bank").confirmDelete({
      url: $(this).attr('href'),
      message: "Are you sure you want to delete this bank of questions?",
      success: function() {
        $(this).slideUp(function() {
          $(this).remove();
        });
      }
    });
  });
  $(".question_bank .bookmark_bank_link").click(function(event) {
    event.preventDefault();
    var $link = $(this);
    var $bank = $link.parents(".question_bank");
    $.ajaxJSON($(this).attr('href'), 'POST', {}, function(data) {
      $bank.find(".bookmark_bank_link").toggle();
    });
  });
  $(".question_bank .edit_bank_link").click(function(event) {
    event.preventDefault();
    var $bank = $(this).parents(".question_bank");
    var data = $bank.getTemplateData({textValues: ['title']});
    $bank.find(".header_content").hide();
    var $form = $("#edit_bank_form");
    $bank.find(".header").prepend($form.show());
    $form.attr('action', $(this).attr('href'));
    $form.attr('method', 'PUT');
    if($bank.attr('id') == 'question_bank_new') {
      $form.attr('action', $("#bank_urls .add_bank_url").attr('href'));
      $form.attr('method', 'POST');
    }
    $form.fillFormData(data, {object_name: 'assessment_question_bank'});
    $form.find(":text:visible:first").focus().select();
  });
  $("#edit_bank_form .bank_name_box").keycodes('return esc', function(event) {
    if(event.keyString == 'esc') {
      $(this).parents(".question_bank").addClass('dont_save')
      $(this).blur();
    } else if(event.keyString == 'return') {
      $("#edit_bank_form").submit();
    }
  });
  $("#edit_bank_form .bank_name_box").blur(function() {
    var $bank = $(this).parents(".question_bank");
    if(!$bank.hasClass('dont_save') && !$bank.hasClass('save_in_progress') && $bank.attr('id') != 'question_bank_new') {
      $("#edit_bank_form").submit();
      return;
    }
    $bank.removeClass('dont_save');
    $bank.find(".header_content").show();
    $("body").append($("#edit_bank_form").hide());
    if($bank.attr('id') == 'question_bank_new') {
      $bank.remove();
    }
  });
  $("#edit_bank_form").formSubmit({
    object_name: 'assessment_question_bank',
    beforeSubmit: function(data) {
      var $bank = $(this).parents(".question_bank");
      $bank.attr('id', 'question_bank_adding');
      try {
        $bank.addClass('save_in_progress')
        $bank.find(".bank_name_box").blur();
      } catch(e) { }
      $bank.fillTemplateData({
        data: data
      });
      $bank.loadingImage();
      return $bank;
    },
    success: function(data, $bank) {
      $bank.loadingImage('remove');
      $bank.removeClass('save_in_progress')
      var bank = data.assessment_question_bank;
      bank.last_updated_at = $.parseFromISO(bank.updated_at).datetime_formatted;
      $bank.fillTemplateData({
        data: bank,
        hrefValues: ['id']
      })
    },
    error: function(data, $bank) {
      $bank.loadingImage('remove');
      $bank.removeClass('save_in_progress')
      $bank.find(".edit_bank_link").click();
      $("#edit_bank_form").formErrors(data);
    }
  });
});
<|endoftext|>


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

Elm.Debugger = null;
Elm.debuggerAttach = function(module, hotSwapState /* =undefined */) {
  return {
    make: function(runtime) {
      var wrappedModule = debugModule(module, runtime);
      Elm.Debugger = debuggerInit(wrappedModule, runtime, hotSwapState);
      dispatchElmDebuggerInit();
      return wrappedModule.moduleInstance;
    }
  };
};

function dispatchElmDebuggerInit() {
  if (parent.window) {
    var dispatch = function(_) {
      parent.window.postMessage("elmDebuggerInit", window.location.origin);
    };
    if (parent.window.document.readyState === "complete") {
      dispatch();
    }
    else {
      parent.window.addEventListener("load", dispatch);
    }
  }
}

function debugModule(module, runtime) {
  var programPaused = false;
  var recordedEvents = [];
  var asyncCallbacks = [];

  function wrapNotify(id, v) {
    var timestep = Date.now();

    if (programPaused) {
      // ignore async events generated while playing back
      // or user events while program is paused
      return false;
    }
    else {
      var changed = runtime.notify(id, v, timestep);
      recordEvent(id, v, timestep);
      if (parent.window) {
        parent.window.postMessage("elmNotify", window.location.origin);
      }
      return changed;
    }
  };

  function wrapRunDelayed(func, delayMs) {
    var cbObj = { func:func, delayMs:delayMs, timerId:0, executed:false };
    var timerId = setTimeout(function() {
        cbObj.executed = true;
        func();
      }, delayMs);
    cbObj.timerId = timerId;
    asyncCallbacks.push(cbObj);
    return timerId;
  }

  function recordEvent(id, v, timestep) {
    recordedEvents.push({ id:id, value:v, timestep:timestep });
  }

  function clearAsyncCallbacks() {
    asyncCallbacks.forEach(function(timer) {
      if (!timer.executed) {
        clearTimeout(timer.timerId);
      }
    });
  }

  function clearRecordedEvents() {
    recordedEvents = [];
  }

  function getRecordedEventsLength() {
    return recordedEvents.length;
  }

  function getRecordedEventAt(i) {
    return recordedEvents[i];
  }

  function copyRecordedEvents() {
    return recordedEvents.slice();
  }

  function loadRecordedEvents(events) {
    recordedEvents = events.slice();
  }

  function setPaused(v) {
    programPaused = v;
    if (programPaused) {
      clearAsyncCallbacks();
      tracePath.stopRecording();
    }
    else {
      // executeCallbacks should only be called when continuing, not when restarting.
      //executeCallbacks(asyncCallbacks, false);
      tracePath.startRecording();
    }
  }

  function getPaused() {
    return programPaused;
  }

  var wrappedRuntime = {
    notify: wrapNotify,
    runDelayed: wrapRunDelayed,
    node: runtime.node,
    display: runtime.display,
    id: runtime.id,
    addListener: runtime.addListener,
    inputs: runtime.inputs
  };

  var moduleInstance = module.make(wrappedRuntime);
  var moduleNodes = flattenNodes(wrappedRuntime.inputs);
  var tracePath = tracePathInit(runtime);

  return {
    moduleInstance: moduleInstance,
    moduleNodes: moduleNodes,
    initialNodeValues: saveNodeValues(moduleNodes),
    initialAsyncCallbacks: asyncCallbacks.slice(),
    // API functions
    clearAsyncCallbacks: clearAsyncCallbacks,
    clearRecordedEvents: clearRecordedEvents,
    getRecordedEventsLength: getRecordedEventsLength,
    getRecordedEventAt: getRecordedEventAt,
    copyRecordedEvents: copyRecordedEvents,
    loadRecordedEvents: loadRecordedEvents,
    getPaused: getPaused,
    setPaused: setPaused,
    tracePath: tracePath
  };
}

function debuggerInit(debugModule, runtime, hotSwapState /* =undefined */) {
  var Signal = Elm.Signal.make(runtime);

  var tracePathNode = A2(Signal.lift, debugModule.tracePath.graphicsUpdate, debugModule.moduleInstance.main);
  runtime.node.parentNode.appendChild(debugModule.tracePath.canvas);

  var eventCounter = 0;

  function resetProgram() {
    debugModule.clearAsyncCallbacks();
    restoreNodeValues(debugModule.moduleNodes, debugModule.initialNodeValues);
    redrawGraphics();
  }

  function restartProgram() {
    resetProgram();
    debugModule.tracePath.clearTraces();
    debugModule.clearRecordedEvents();
    debugModule.setPaused(false);
    executeCallbacks(debugModule.initialAsyncCallbacks, true);
  }

  function pauseProgram() {
    debugModule.setPaused(true);
    eventCounter = debugModule.getRecordedEventsLength();
  }

  function continueProgram() {
    if (debugModule.getPaused())
    {
      debugModule.setPaused(false);
    }
  }

  function stepTo(index) {
    if (!debugModule.getPaused()) {
      debugModule.setPaused(true);
      resetProgram();
    }

    if (index < 0 || index > getMaxSteps()) {
      throw "Index out of bounds: " + index;
    }

    if (index < eventCounter) {
      resetProgram();
      eventCounter = 0;
    }

    assert(index >= eventCounter, "index must be bad");
    while (eventCounter < index) {
      var nextEvent = debugModule.getRecordedEventAt(eventCounter);
      runtime.notify(nextEvent.id, nextEvent.value, nextEvent.timestep);

      eventCounter += 1;
    }
    assert(eventCounter == index, "while loop didn't work");
  }

  function getMaxSteps() {
    return debugModule.getRecordedEventsLength();
  }

  function doPlayback(eventList) {
    var x = eventList.shift();
    var time = x[2];
    runtime.notify(x[0], x[1], x[2]);

    if (eventList.length > 0) {
      var delta = eventList[0][2] - time;
      setTimeout(function() { doPlayback(eventList); }, delta);
    }
  }

  function redrawGraphics() {
    var graphicsNode = debugModule.moduleInstance.main.kids[0];
    graphicsNode.recv(Date.now(), true, debugModule.moduleInstance.main.id);
  }

  function getHotSwapState() {
    var counter = eventCounter;
    if (!debugModule.getPaused()) {
      counter = getMaxSteps();
    }
    return {
      recordedEvents: debugModule.copyRecordedEvents(),
      eventCounter: counter
    };
  }

  function dispose() {
    var parentNode = runtime.node.parentNode;
    parentNode.removeChild(debugModule.tracePath.canvas);
    parentNode.removeChild(runtime.node);
  }

  if (hotSwapState) {
    debugModule.setPaused(true);
    debugModule.loadRecordedEvents(hotSwapState.recordedEvents);

    // draw new trace path
    debugModule.tracePath.startRecording();
    stepTo(getMaxSteps());
    debugModule.tracePath.stopRecording();

    stepTo(hotSwapState.eventCounter);
  }

  var elmDebugger = {
      restart: restartProgram,
      pause: pauseProgram,
      kontinue: continueProgram,
      getMaxSteps: getMaxSteps,
      stepTo: stepTo,
      getPaused: debugModule.getPaused,
      getHotSwapState: getHotSwapState,
      dispose: dispose
  };

  return elmDebugger;
}

function Point(x, y) {
  this.x = x;
  this.y = y;

  this.translate = function(x, y) {
    return new Point(this.x + x, this.y + y);
  }

  this.equals = function(p) {
    return this.x == p.x && this.y == p.y;
  }
}

function tracePathInit(runtime) {
  var List = Elm.List.make(runtime);
  var tracePathCanvas = createCanvas();
  var tracePositions = {};
  var recordingTraces = true;

  function findPositions(currentScene) {
    var positions = {};
    function processElement(elem, offset) {
      if (elem.element.ctor == "Custom" && elem.element.type == "Collage")
      {
        List.map(F2(processForm)(offset))(elem.element.model.forms);
      }
      else if (elem.element.ctor == "Image" && elem.props.debugTracePathId)
      {
        positions[elem.props.debugTracePathId] = new Point(offset.x, offset.y);
      }
    }

    function processForm(offset, form) {
      if (form.form.ctor == "FElement")
      {
        processElement(form.form._0, offset.translate(form.x, -form.y));
      }
    }

    processElement(currentScene, new Point(0, 0));
    return positions;
  }

  function appendPositions(positions) {
    for (var id in positions) {
      var pos = positions[id];
      if (tracePositions.hasOwnProperty(id)) {
        var points = tracePositions[id];
        if (!pos.equals(points[points.length-1])) {
          points.push(pos);
        }
      }
      else {
        tracePositions[id] = [pos];
      }
    }
  }

  function graphicsUpdate(currentScene) {
    if (!recordingTraces) {
      return;
    }

    var ctx = tracePathCanvas.getContext('2d');
    ctx.clearRect(0, 0, tracePathCanvas.width, tracePathCanvas.height);

    ctx.save();
    ctx.translate(ctx.canvas.width/2, ctx.canvas.height/2);
    appendPositions(findPositions(currentScene));
    for (var id in tracePositions)
    {
      ctx.beginPath();
      var points = tracePositions[id];
      for (var i=0; i < points.length; i++)
      {
        var p = points[i];
        if (i == 0) {
          ctx.moveTo(p.x, p.y);
        }
        else {
          ctx.lineTo(p.x, p.y);
        }
      }
      ctx.lineWidth = 1;
      ctx.strokeStyle = "#888a85";
      ctx.stroke();

      for (var i=0; i < points.length; i++)
      {
        var p = points[i];
        ctx.beginPath();
        ctx.arc(p.x, p.y, 2, 0, Math.PI * 2);
        ctx.fillStyle = "#2e3436";
        ctx.fill();
      }
    }

    ctx.restore();
  }

  function clearTraces() {
    tracePositions = {};
  }

  function stopRecording() {
    recordingTraces = false;
  }

  function startRecording() {
    recordingTraces = true;
  }

  return {
    graphicsUpdate: graphicsUpdate,
    canvas: tracePathCanvas,
    clearTraces: clearTraces,
    stopRecording: stopRecording,
    startRecording: startRecording
  }
}

function executeCallbacks(callbacks, reexecute) {
  callbacks.forEach(function(timer) {
    if (reexecute || !timer.executed) {
      var func = timer.func;
      func();
    }
  });
}

function createCanvas() {
  var c = document.createElement('canvas');
  c.width = window.innerWidth;
  c.height = window.innerHeight;
  c.style.position = "absolute";
  c.style.top = "0";
  c.style.left = "0";
  return c;
}

function assert(bool, msg) {
  if (!bool) {
    throw "Assertion error: " + msg;
  }
}

function saveNodeValues(allNodes) {
  var nodeValues = [];

  allNodes.forEach(function(node) {
    nodeValues.push({ value: node.value, id: node.id });
  });

  return nodeValues;
};

function restoreNodeValues(allNodes, nodeStates) {
  assert(allNodes.length == nodeStates.length, "saved program state has wrong length");
  for (var i=0; i < allNodes.length; i++) {
    var node = allNodes[i];
    var state = nodeStates[i];
    assert(node.id == state.id, "the nodes moved position");

    node.value = state.value;
  }
}

function flattenNodes(nodes) {
  var treeReduce = function(prev, cur, i, arr) {
    var flatKids = cur.kids.reduce(treeReduce, []);
    flatKids.push(cur);
    return prev.concat(flatKids);
  }

  return nodes.reduce(treeReduce, []);
};

}());
<commit_msg>Debugger: fix flattenNodes() so it doesn't return duplicates.<commit_after>
(function() {
'use strict';

Elm.Debugger = null;
Elm.debuggerAttach = function(module, hotSwapState /* =undefined */) {
  return {
    make: function(runtime) {
      var wrappedModule = debugModule(module, runtime);
      Elm.Debugger = debuggerInit(wrappedModule, runtime, hotSwapState);
      dispatchElmDebuggerInit();
      return wrappedModule.moduleInstance;
    }
  };
};

function dispatchElmDebuggerInit() {
  if (parent.window) {
    var dispatch = function(_) {
      parent.window.postMessage("elmDebuggerInit", window.location.origin);
    };
    if (parent.window.document.readyState === "complete") {
      dispatch();
    }
    else {
      parent.window.addEventListener("load", dispatch);
    }
  }
}

function debugModule(module, runtime) {
  var programPaused = false;
  var recordedEvents = [];
  var asyncCallbacks = [];

  function wrapNotify(id, v) {
    var timestep = Date.now();

    if (programPaused) {
      // ignore async events generated while playing back
      // or user events while program is paused
      return false;
    }
    else {
      var changed = runtime.notify(id, v, timestep);
      recordEvent(id, v, timestep);
      if (parent.window) {
        parent.window.postMessage("elmNotify", window.location.origin);
      }
      return changed;
    }
  };

  function wrapRunDelayed(func, delayMs) {
    var cbObj = { func:func, delayMs:delayMs, timerId:0, executed:false };
    var timerId = setTimeout(function() {
        cbObj.executed = true;
        func();
      }, delayMs);
    cbObj.timerId = timerId;
    asyncCallbacks.push(cbObj);
    return timerId;
  }

  function recordEvent(id, v, timestep) {
    recordedEvents.push({ id:id, value:v, timestep:timestep });
  }

  function clearAsyncCallbacks() {
    asyncCallbacks.forEach(function(timer) {
      if (!timer.executed) {
        clearTimeout(timer.timerId);
      }
    });
  }

  function clearRecordedEvents() {
    recordedEvents = [];
  }

  function getRecordedEventsLength() {
    return recordedEvents.length;
  }

  function getRecordedEventAt(i) {
    return recordedEvents[i];
  }

  function copyRecordedEvents() {
    return recordedEvents.slice();
  }

  function loadRecordedEvents(events) {
    recordedEvents = events.slice();
  }

  function setPaused(v) {
    programPaused = v;
    if (programPaused) {
      clearAsyncCallbacks();
      tracePath.stopRecording();
    }
    else {
      // executeCallbacks should only be called when continuing, not when restarting.
      //executeCallbacks(asyncCallbacks, false);
      tracePath.startRecording();
    }
  }

  function getPaused() {
    return programPaused;
  }

  var wrappedRuntime = {
    notify: wrapNotify,
    runDelayed: wrapRunDelayed,
    node: runtime.node,
    display: runtime.display,
    id: runtime.id,
    addListener: runtime.addListener,
    inputs: runtime.inputs
  };

  var moduleInstance = module.make(wrappedRuntime);
  var moduleNodes = flattenNodes(wrappedRuntime.inputs);
  var tracePath = tracePathInit(runtime);

  return {
    moduleInstance: moduleInstance,
    moduleNodes: moduleNodes,
    initialNodeValues: saveNodeValues(moduleNodes),
    initialAsyncCallbacks: asyncCallbacks.slice(),
    // API functions
    clearAsyncCallbacks: clearAsyncCallbacks,
    clearRecordedEvents: clearRecordedEvents,
    getRecordedEventsLength: getRecordedEventsLength,
    getRecordedEventAt: getRecordedEventAt,
    copyRecordedEvents: copyRecordedEvents,
    loadRecordedEvents: loadRecordedEvents,
    getPaused: getPaused,
    setPaused: setPaused,
    tracePath: tracePath
  };
}

function debuggerInit(debugModule, runtime, hotSwapState /* =undefined */) {
  var Signal = Elm.Signal.make(runtime);

  var tracePathNode = A2(Signal.lift, debugModule.tracePath.graphicsUpdate, debugModule.moduleInstance.main);
  runtime.node.parentNode.appendChild(debugModule.tracePath.canvas);

  var eventCounter = 0;

  function resetProgram() {
    debugModule.clearAsyncCallbacks();
    restoreNodeValues(debugModule.moduleNodes, debugModule.initialNodeValues);
    redrawGraphics();
  }

  function restartProgram() {
    resetProgram();
    debugModule.tracePath.clearTraces();
    debugModule.clearRecordedEvents();
    debugModule.setPaused(false);
    executeCallbacks(debugModule.initialAsyncCallbacks, true);
  }

  function pauseProgram() {
    debugModule.setPaused(true);
    eventCounter = debugModule.getRecordedEventsLength();
  }

  function continueProgram() {
    if (debugModule.getPaused())
    {
      debugModule.setPaused(false);
    }
  }

  function stepTo(index) {
    if (!debugModule.getPaused()) {
      debugModule.setPaused(true);
      resetProgram();
    }

    if (index < 0 || index > getMaxSteps()) {
      throw "Index out of bounds: " + index;
    }

    if (index < eventCounter) {
      resetProgram();
      eventCounter = 0;
    }

    assert(index >= eventCounter, "index must be bad");
    while (eventCounter < index) {
      var nextEvent = debugModule.getRecordedEventAt(eventCounter);
      runtime.notify(nextEvent.id, nextEvent.value, nextEvent.timestep);

      eventCounter += 1;
    }
    assert(eventCounter == index, "while loop didn't work");
  }

  function getMaxSteps() {
    return debugModule.getRecordedEventsLength();
  }

  function doPlayback(eventList) {
    var x = eventList.shift();
    var time = x[2];
    runtime.notify(x[0], x[1], x[2]);

    if (eventList.length > 0) {
      var delta = eventList[0][2] - time;
      setTimeout(function() { doPlayback(eventList); }, delta);
    }
  }

  function redrawGraphics() {
    var graphicsNode = debugModule.moduleInstance.main.kids[0];
    graphicsNode.recv(Date.now(), true, debugModule.moduleInstance.main.id);
  }

  function getHotSwapState() {
    var counter = eventCounter;
    if (!debugModule.getPaused()) {
      counter = getMaxSteps();
    }
    return {
      recordedEvents: debugModule.copyRecordedEvents(),
      eventCounter: counter
    };
  }

  function dispose() {
    var parentNode = runtime.node.parentNode;
    parentNode.removeChild(debugModule.tracePath.canvas);
    parentNode.removeChild(runtime.node);
  }

  if (hotSwapState) {
    debugModule.setPaused(true);
    debugModule.loadRecordedEvents(hotSwapState.recordedEvents);

    // draw new trace path
    debugModule.tracePath.startRecording();
    stepTo(getMaxSteps());
    debugModule.tracePath.stopRecording();

    stepTo(hotSwapState.eventCounter);
  }

  var elmDebugger = {
      restart: restartProgram,
      pause: pauseProgram,
      kontinue: continueProgram,
      getMaxSteps: getMaxSteps,
      stepTo: stepTo,
      getPaused: debugModule.getPaused,
      getHotSwapState: getHotSwapState,
      dispose: dispose
  };

  return elmDebugger;
}

function Point(x, y) {
  this.x = x;
  this.y = y;

  this.translate = function(x, y) {
    return new Point(this.x + x, this.y + y);
  }

  this.equals = function(p) {
    return this.x == p.x && this.y == p.y;
  }
}

function tracePathInit(runtime) {
  var List = Elm.List.make(runtime);
  var tracePathCanvas = createCanvas();
  var tracePositions = {};
  var recordingTraces = true;

  function findPositions(currentScene) {
    var positions = {};
    function processElement(elem, offset) {
      if (elem.element.ctor == "Custom" && elem.element.type == "Collage")
      {
        List.map(F2(processForm)(offset))(elem.element.model.forms);
      }
      else if (elem.element.ctor == "Image" && elem.props.debugTracePathId)
      {
        positions[elem.props.debugTracePathId] = new Point(offset.x, offset.y);
      }
    }

    function processForm(offset, form) {
      if (form.form.ctor == "FElement")
      {
        processElement(form.form._0, offset.translate(form.x, -form.y));
      }
    }

    processElement(currentScene, new Point(0, 0));
    return positions;
  }

  function appendPositions(positions) {
    for (var id in positions) {
      var pos = positions[id];
      if (tracePositions.hasOwnProperty(id)) {
        var points = tracePositions[id];
        if (!pos.equals(points[points.length-1])) {
          points.push(pos);
        }
      }
      else {
        tracePositions[id] = [pos];
      }
    }
  }

  function graphicsUpdate(currentScene) {
    if (!recordingTraces) {
      return;
    }

    var ctx = tracePathCanvas.getContext('2d');
    ctx.clearRect(0, 0, tracePathCanvas.width, tracePathCanvas.height);

    ctx.save();
    ctx.translate(ctx.canvas.width/2, ctx.canvas.height/2);
    appendPositions(findPositions(currentScene));
    for (var id in tracePositions)
    {
      ctx.beginPath();
      var points = tracePositions[id];
      for (var i=0; i < points.length; i++)
      {
        var p = points[i];
        if (i == 0) {
          ctx.moveTo(p.x, p.y);
        }
        else {
          ctx.lineTo(p.x, p.y);
        }
      }
      ctx.lineWidth = 1;
      ctx.strokeStyle = "#888a85";
      ctx.stroke();

      for (var i=0; i < points.length; i++)
      {
        var p = points[i];
        ctx.beginPath();
        ctx.arc(p.x, p.y, 2, 0, Math.PI * 2);
        ctx.fillStyle = "#2e3436";
        ctx.fill();
      }
    }

    ctx.restore();
  }

  function clearTraces() {
    tracePositions = {};
  }

  function stopRecording() {
    recordingTraces = false;
  }

  function startRecording() {
    recordingTraces = true;
  }

  return {
    graphicsUpdate: graphicsUpdate,
    canvas: tracePathCanvas,
    clearTraces: clearTraces,
    stopRecording: stopRecording,
    startRecording: startRecording
  }
}

function executeCallbacks(callbacks, reexecute) {
  callbacks.forEach(function(timer) {
    if (reexecute || !timer.executed) {
      var func = timer.func;
      func();
    }
  });
}

function createCanvas() {
  var c = document.createElement('canvas');
  c.width = window.innerWidth;
  c.height = window.innerHeight;
  c.style.position = "absolute";
  c.style.top = "0";
  c.style.left = "0";
  return c;
}

function assert(bool, msg) {
  if (!bool) {
    throw "Assertion error: " + msg;
  }
}

function saveNodeValues(allNodes) {
  var nodeValues = [];

  allNodes.forEach(function(node) {
    nodeValues.push({ value: node.value, id: node.id });
  });

  return nodeValues;
};

function restoreNodeValues(allNodes, nodeStates) {
  assert(allNodes.length == nodeStates.length, "saved program state has wrong length");
  for (var i=0; i < allNodes.length; i++) {
    var node = allNodes[i];
    var state = nodeStates[i];
    assert(node.id == state.id, "the nodes moved position");

    node.value = state.value;
  }
}

function flattenNodes(nodes) {
  var nodesById = {};

  function addAllToDict(node) {
    nodesById[node.id] = node;
    node.kids.forEach(addAllToDict);
  }
  nodes.forEach(addAllToDict);

  var allNodes = Object.keys(nodesById).sort().map(function(key) {
    return nodesById[key];
  });
  return allNodes;
};

}());
<|endoftext|>


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

  // shamelessly taken from jQuery
  // https://github.com/jquery/jquery/blob/master/src/event.js

  $$.Event = function( src, props ) {
    // Allow instantiation without the 'new' keyword
    if ( !(this instanceof $$.Event) ) {
      return new $$.Event( src, props );
    }

    // Event object
    if ( src && src.type ) {
      this.originalEvent = src;
      this.type = src.type;

      // Events bubbling up the document may have been marked as prevented
      // by a handler lower down the tree; reflect the correct value.
      this.isDefaultPrevented = ( src.defaultPrevented ||
        src.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse;

    // Event type
    } else {
      this.type = src;
    }

    // Put explicitly provided properties onto the event object
    if ( props ) {
      // $$.util.extend( this, props );

      // more efficient to manually copy fields we use
      this.type = props.type !== undefined ? props.type : this.type;
      this.cy = props.cy;
      this.cyTarget = props.cyTarget;
      this.cyPosition = props.cyPosition;
      this.cyRenderedPosition = props.cyRenderedPosition;
      this.namespace = props.namespace;
      this.layout = props.layout;
      this.data = props.data;
    }

    // Create a timestamp if incoming event doesn't have one
    this.timeStamp = src && src.timeStamp || +new Date();
  };

  function returnFalse() {
    return false;
  }
  function returnTrue() {
    return true;
  }

  // jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
  // http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
  $$.Event.prototype = {
    preventDefault: function() {
      this.isDefaultPrevented = returnTrue;

      var e = this.originalEvent;
      if ( !e ) {
        return;
      }

      // if preventDefault exists run it on the original event
      if ( e.preventDefault ) {
        e.preventDefault();
      }
    },
    stopPropagation: function() {
      this.isPropagationStopped = returnTrue;

      var e = this.originalEvent;
      if ( !e ) {
        return;
      }
      // if stopPropagation exists run it on the original event
      if ( e.stopPropagation ) {
        e.stopPropagation();
      }
    },
    stopImmediatePropagation: function() {
      this.isImmediatePropagationStopped = returnTrue;
      this.stopPropagation();
    },
    isDefaultPrevented: returnFalse,
    isPropagationStopped: returnFalse,
    isImmediatePropagationStopped: returnFalse
  };

})( cytoscape );
<commit_msg> Remove deprecated getPreventDefault() from 726.Event #703<commit_after>;(function($$){ 'use strict';

  // shamelessly taken from jQuery
  // https://github.com/jquery/jquery/blob/master/src/event.js

  $$.Event = function( src, props ) {
    // Allow instantiation without the 'new' keyword
    if ( !(this instanceof $$.Event) ) {
      return new $$.Event( src, props );
    }

    // Event object
    if ( src && src.type ) {
      this.originalEvent = src;
      this.type = src.type;

      // Events bubbling up the document may have been marked as prevented
      // by a handler lower down the tree; reflect the correct value.
      this.isDefaultPrevented = ( src.defaultPrevented ) ? returnTrue : returnFalse;

    // Event type
    } else {
      this.type = src;
    }

    // Put explicitly provided properties onto the event object
    if ( props ) {
      // $$.util.extend( this, props );

      // more efficient to manually copy fields we use
      this.type = props.type !== undefined ? props.type : this.type;
      this.cy = props.cy;
      this.cyTarget = props.cyTarget;
      this.cyPosition = props.cyPosition;
      this.cyRenderedPosition = props.cyRenderedPosition;
      this.namespace = props.namespace;
      this.layout = props.layout;
      this.data = props.data;
    }

    // Create a timestamp if incoming event doesn't have one
    this.timeStamp = src && src.timeStamp || +new Date();
  };

  function returnFalse() {
    return false;
  }
  function returnTrue() {
    return true;
  }

  // jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
  // http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
  $$.Event.prototype = {
    preventDefault: function() {
      this.isDefaultPrevented = returnTrue;

      var e = this.originalEvent;
      if ( !e ) {
        return;
      }

      // if preventDefault exists run it on the original event
      if ( e.preventDefault ) {
        e.preventDefault();
      }
    },
    stopPropagation: function() {
      this.isPropagationStopped = returnTrue;

      var e = this.originalEvent;
      if ( !e ) {
        return;
      }
      // if stopPropagation exists run it on the original event
      if ( e.stopPropagation ) {
        e.stopPropagation();
      }
    },
    stopImmediatePropagation: function() {
      this.isImmediatePropagationStopped = returnTrue;
      this.stopPropagation();
    },
    isDefaultPrevented: returnFalse,
    isPropagationStopped: returnFalse,
    isImmediatePropagationStopped: returnFalse
  };

})( cytoscape );
<|endoftext|>


<commit_before>// ==========================================
// Copyright 2013 Dataminr
// Licensed under The MIT License
// http://opensource.org/licenses/MIT
// work derived from https://github.com/rhysbrettbowen/PlastronJS
// ==========================================

// V0.1.0

define('underscore.extras', [
  'underscore'
], function(_) {

  var id = 1;
  var toArray = _.toArray;

  _.mixin({

    // sum an array or values of an object
    sum: function(arr, asString) {
      var radix = _.isNumber(asString) ? asString : 10;
      var transform = function(val) {
        if (_.isString(val))
          return parseInt(val, radix);
        return val;
      };
      if (_.isFunction(asString)) {
        transform = asString;
        asString = arguments[2];
      }
      return _.reduce(arr, function(memo, num) {
        return memo + transform(num);
      }, asString === true ? '': 0);
    },

    // gets the element relative to another child in an array
    relative: function(arr, child, rel) {
      var ind = _.indexOf(arr, child);
      if (ind < 0)
        return;
      return arr[ind + rel];
    },

    // insert a child in to an array if it doesn't exist
    insert: function(arr, child) {
      if (!_.contains(arr, child))
        arr.push(child);
      return arr;
    },

    // remove the item at the given index
    removeAt: function(arr, ind) {
      return arr.splice(ind, 1);
    },

    // remove an item from an array
    remove: function(arr, child) {
      var i = _.indexOf(arr, child);
      if (i > 0)
        return _.removeAt(arr, i);
    },

    // remove an item that satisfies a function
    removeIf: function(arr, fn) {
      _.remove(arr, _.find(arr, fn));
    },

    // give an object a unique id if it doesn't have one and return it
    giveUid: function(obj) {
      if (!obj._underscore_uid_property)
        obj._underscore_uid_property = id++;
      return obj._underscore_uid_property;
    },

    // change the order of arguments in an array
    // pass the array then a list of the order arguments should be in
    // for instance to move the last argument to the front and the others along
    // one for a 3 argument function:
    // _.flip(threeArg, 2, 0, 1);
    // if no numbers given will flip the first two arguments
    flip: function(fn) {
      var flips = _.toArray(arguments, 1);
      if (!flips.length) {
        flips[0] = 1;
        flips[1] = 0;
      }
      return function() {
        var args = _.toArray(arguments);
        var temp = [];
        for (var i = 0; i < args.length || i < flips.length; i++) {
          temp.push(args[i < flips.length ? flips[i] : i]);
        }
        return fn.apply(this, temp);
      };
    },

    // a self currying function, will continually return a curried version
    // of the given function until the opt_minLength is reached or it is
    // called with no arguments. Passing in undefined will leave a 'gap' in the
    // arguments passed in that you can fill in later.
    curry: function(fn, opt_minLength) {
      var args = arguments.length > 2 ? _.toArray(arguments, 2) : [];
      var curried = function() {
        var newArgs = args.slice();
        if (!arguments.length)
          return fn.apply(this, args);
        var ind = 0;
        _.each(arguments, function(arg) {
          if (arg === undefined) {
            while (newArgs[ind++] !== undefined) {}
          } else {
            while (newArgs[ind] !== undefined)
              ind++;
            newArgs[ind] = arg;
          }
        });
        var newArgsLength = _.filter(newArgs, function(arg) {
          return arg !== undefined;
        }).length;
        if (opt_minLength <= newArgsLength) {
          return fn.apply(this, newArgs);
        }
        return _.curry.apply(this,
          [fn].concat(opt_minLength !== undefined ?
          opt_minLength - newArgsLength : undefined, newArgs));
      };
      return curried;
    },

    // push to an array in an object and create one if it doesn't exist
    push: function(obj, key, value) {
      if (value !== undefined) {
        if (!obj[key])
          obj[key] = [];
        obj[key].push(value);
      }
    },

    // put a key/value pair in an object if the value is defined
    put: function(obj, key, value) {
      if (obj[key] && value === undefined)
        delete obj[key];
      else if (value !== undefined)
        obj[key] = value;
    },

    // gets a value given a key and object
    get: function(key, obj, backup) {
      return _.exist(obj, key, backup);
    },

    // create a function that will run the initially given functions in order
    // with the called arguments and return the last result
    seq: function() {
      var functions = arguments;
      var length = functions.length;
      return function() {
        var result;
        for (var i = 0; i < length; i++) {
          result = functions[i].apply(this, arguments);
        }
        return result;
      };
    },

    // returns if an object is empty or doesn't exist
    isEmpty: function(obj) {
      return !!(obj === undefined || obj === null ||
        (_.isObject(obj) && !_.keys(obj).length) ||
        (_.isString(obj) && !obj.length)) ||
        !_.isNumber(obj);
    },

    // give a base object and string with dot delimited namespace. Will return
    // the backup or undefined if it doesn't exist else will return the value
    exist: function(obj, namespace, backup) {
      if (!obj) return;
      var names = namespace.split('.').reverse();
      while(names.length && (obj = obj[names.pop()]) !== undefined);
      return( obj === undefined ? backup : obj);
    },

    // call a function on an object and set the object to the result
    inPlace: function(obj, namespace, fn) {
      if (!obj) return;
      var names = namespace.split('.').reverse();
      while(names.length > 1 && (obj = obj[names.pop()]) !== undefined);
      if (!obj || !obj[names[0]])
        return;
      if (_.isString(fn)) {
        if (_.isFunction(obj[names[0]][fn])) {
          fn = obj[names[0]][fn];
        } else {
          return;
        }
      }
      return (obj[names[0]] = fn.apply(obj[names[0]], _.toArray(arguments, 3)));
    },

    // pass in the context as the first value to a function
    feedThis: function(fn) {
      return function() {
        return fn.apply(this, [this].concat(_.toArray(arguments)));
      };
    },

    // if an object exists pass it to a function
    canUse: function(obj, fn, ctx) {
      if (obj === undefined)
        return;
      return fn.call(ctx || this, obj);
    },

    // call a function from the context of an object
    invoke: function(fn, obj) {
      var args = _.toArray(arguments, 2);
      if (obj == null)
        return;
      if (_.isString(fn) && _.isFunction(obj[fn]))
        return obj[fn].apply(obj, args);
      if (_.isFunction(fn))
        return fn.apply(obj, args);
    },

    // return a function that will call the functions on an object
    makeCallable: function(fn, obj) {
      var args = _.toArray(arguments, 2);
      return function() {
        var args2 = args.concat(_.toArray(arguments));
        return _.invoke.apply(this, [fn, obj].concat(args2));
      };
    },

    // return the true or false value passed in given the condition, if any of
    // them are functions then run with the extra arguments given
    ifelse: function(cond, tr, fa) {
      var args = _.toArray(arguments, 3);
      var test = _.isFunction(cond) ? cond.apply(this, args) : cond;
      if (test) {
        return _.isFunction(tr) ? tr.apply(this, args) : tr;
      } else {
        return _.isFunction(fa) ? fa.apply(this, args): fa;
      }
    },

    // add on slice variables to the underscore toArray
    toArray: function(arr, start, end) {
      return toArray(arr).slice(start, end);
    },

    // only give the first x arguments to a function
    cutArgs: function(fn, num) {
      return function() {
        var args = _.toArray(arguments, 0, num);
        return fn.apply(this, args);
      };
    },

    // pythonesque string interpolation
    print: function(str) {
      var args = _.toArray(arguments, 1).reverse();
      return str.replace(/%s/g, function() {
        var arg = args.pop();
        return (arg == null ? '' : '' + arg);
      });
    },

    // just like delay but you can pass in the context
    wait: function(fn, time, ctx) {
      fn = _.bind(fn, ctx || this);
      return _.delay.apply(this, [fn, time].concat(_.toArray(arguments, 3)));
    },

    // enhanced map function can also map values of an object
    map: function (obj, iterator, context) {
      if (!obj)
        return [];
      var results = _.isArray(obj) ? [] : {};
      if (obj == null) return results;
      if (_.isFunction(obj.map)) return obj.map(iterator, context);
      _.each(obj, function(value, index, list) {
        results[index] = iterator.call(context, value, index, list);
      });
      return results;
    }

  });

});
<commit_msg>update _.isEmpty test<commit_after>// ==========================================
// Copyright 2013 Dataminr
// Licensed under The MIT License
// http://opensource.org/licenses/MIT
// work derived from https://github.com/rhysbrettbowen/PlastronJS
// ==========================================

// V0.1.0

define('underscore.extras', [
  'underscore'
], function(_) {

  var id = 1;
  var toArray = _.toArray;

  _.mixin({

    // sum an array or values of an object
    sum: function(arr, asString) {
      var radix = _.isNumber(asString) ? asString : 10;
      var transform = function(val) {
        if (_.isString(val))
          return parseInt(val, radix);
        return val;
      };
      if (_.isFunction(asString)) {
        transform = asString;
        asString = arguments[2];
      }
      return _.reduce(arr, function(memo, num) {
        return memo + transform(num);
      }, asString === true ? '': 0);
    },

    // gets the element relative to another child in an array
    relative: function(arr, child, rel) {
      var ind = _.indexOf(arr, child);
      if (ind < 0)
        return;
      return arr[ind + rel];
    },

    // insert a child in to an array if it doesn't exist
    insert: function(arr, child) {
      if (!_.contains(arr, child))
        arr.push(child);
      return arr;
    },

    // remove the item at the given index
    removeAt: function(arr, ind) {
      return arr.splice(ind, 1);
    },

    // remove an item from an array
    remove: function(arr, child) {
      var i = _.indexOf(arr, child);
      if (i > 0)
        return _.removeAt(arr, i);
    },

    // remove an item that satisfies a function
    removeIf: function(arr, fn) {
      _.remove(arr, _.find(arr, fn));
    },

    // give an object a unique id if it doesn't have one and return it
    giveUid: function(obj) {
      if (!obj._underscore_uid_property)
        obj._underscore_uid_property = id++;
      return obj._underscore_uid_property;
    },

    // change the order of arguments in an array
    // pass the array then a list of the order arguments should be in
    // for instance to move the last argument to the front and the others along
    // one for a 3 argument function:
    // _.flip(threeArg, 2, 0, 1);
    // if no numbers given will flip the first two arguments
    flip: function(fn) {
      var flips = _.toArray(arguments, 1);
      if (!flips.length) {
        flips[0] = 1;
        flips[1] = 0;
      }
      return function() {
        var args = _.toArray(arguments);
        var temp = [];
        for (var i = 0; i < args.length || i < flips.length; i++) {
          temp.push(args[i < flips.length ? flips[i] : i]);
        }
        return fn.apply(this, temp);
      };
    },

    // a self currying function, will continually return a curried version
    // of the given function until the opt_minLength is reached or it is
    // called with no arguments. Passing in undefined will leave a 'gap' in the
    // arguments passed in that you can fill in later.
    curry: function(fn, opt_minLength) {
      var args = arguments.length > 2 ? _.toArray(arguments, 2) : [];
      var curried = function() {
        var newArgs = args.slice();
        if (!arguments.length)
          return fn.apply(this, args);
        var ind = 0;
        _.each(arguments, function(arg) {
          if (arg === undefined) {
            while (newArgs[ind++] !== undefined) {}
          } else {
            while (newArgs[ind] !== undefined)
              ind++;
            newArgs[ind] = arg;
          }
        });
        var newArgsLength = _.filter(newArgs, function(arg) {
          return arg !== undefined;
        }).length;
        if (opt_minLength <= newArgsLength) {
          return fn.apply(this, newArgs);
        }
        return _.curry.apply(this,
          [fn].concat(opt_minLength !== undefined ?
          opt_minLength - newArgsLength : undefined, newArgs));
      };
      return curried;
    },

    // push to an array in an object and create one if it doesn't exist
    push: function(obj, key, value) {
      if (value !== undefined) {
        if (!obj[key])
          obj[key] = [];
        obj[key].push(value);
      }
    },

    // put a key/value pair in an object if the value is defined
    put: function(obj, key, value) {
      if (obj[key] && value === undefined)
        delete obj[key];
      else if (value !== undefined)
        obj[key] = value;
    },

    // gets a value given a key and object
    get: function(key, obj, backup) {
      return _.exist(obj, key, backup);
    },

    // create a function that will run the initially given functions in order
    // with the called arguments and return the last result
    seq: function() {
      var functions = arguments;
      var length = functions.length;
      return function() {
        var result;
        for (var i = 0; i < length; i++) {
          result = functions[i].apply(this, arguments);
        }
        return result;
      };
    },

    // returns if an object is empty or doesn't exist
    isEmpty: function(obj) {
      return !!(obj === undefined || obj === null ||
        (_.isObject(obj) && !_.keys(obj).length) ||
        (_.isString(obj) && !obj.length));
    },

    // give a base object and string with dot delimited namespace. Will return
    // the backup or undefined if it doesn't exist else will return the value
    exist: function(obj, namespace, backup) {
      if (!obj) return;
      var names = namespace.split('.').reverse();
      while(names.length && (obj = obj[names.pop()]) !== undefined);
      return( obj === undefined ? backup : obj);
    },

    // call a function on an object and set the object to the result
    inPlace: function(obj, namespace, fn) {
      if (!obj) return;
      var names = namespace.split('.').reverse();
      while(names.length > 1 && (obj = obj[names.pop()]) !== undefined);
      if (!obj || !obj[names[0]])
        return;
      if (_.isString(fn)) {
        if (_.isFunction(obj[names[0]][fn])) {
          fn = obj[names[0]][fn];
        } else {
          return;
        }
      }
      return (obj[names[0]] = fn.apply(obj[names[0]], _.toArray(arguments, 3)));
    },

    // pass in the context as the first value to a function
    feedThis: function(fn) {
      return function() {
        return fn.apply(this, [this].concat(_.toArray(arguments)));
      };
    },

    // if an object exists pass it to a function
    canUse: function(obj, fn, ctx) {
      if (obj === undefined)
        return;
      return fn.call(ctx || this, obj);
    },

    // call a function from the context of an object
    invoke: function(fn, obj) {
      var args = _.toArray(arguments, 2);
      if (obj == null)
        return;
      if (_.isString(fn) && _.isFunction(obj[fn]))
        return obj[fn].apply(obj, args);
      if (_.isFunction(fn))
        return fn.apply(obj, args);
    },

    // return a function that will call the functions on an object
    makeCallable: function(fn, obj) {
      var args = _.toArray(arguments, 2);
      return function() {
        var args2 = args.concat(_.toArray(arguments));
        return _.invoke.apply(this, [fn, obj].concat(args2));
      };
    },

    // return the true or false value passed in given the condition, if any of
    // them are functions then run with the extra arguments given
    ifelse: function(cond, tr, fa) {
      var args = _.toArray(arguments, 3);
      var test = _.isFunction(cond) ? cond.apply(this, args) : cond;
      if (test) {
        return _.isFunction(tr) ? tr.apply(this, args) : tr;
      } else {
        return _.isFunction(fa) ? fa.apply(this, args): fa;
      }
    },

    // add on slice variables to the underscore toArray
    toArray: function(arr, start, end) {
      return toArray(arr).slice(start, end);
    },

    // only give the first x arguments to a function
    cutArgs: function(fn, num) {
      return function() {
        var args = _.toArray(arguments, 0, num);
        return fn.apply(this, args);
      };
    },

    // pythonesque string interpolation
    print: function(str) {
      var args = _.toArray(arguments, 1).reverse();
      return str.replace(/%s/g, function() {
        var arg = args.pop();
        return (arg == null ? '' : '' + arg);
      });
    },

    // just like delay but you can pass in the context
    wait: function(fn, time, ctx) {
      fn = _.bind(fn, ctx || this);
      return _.delay.apply(this, [fn, time].concat(_.toArray(arguments, 3)));
    },

    // enhanced map function can also map values of an object
    map: function (obj, iterator, context) {
      if (!obj)
        return [];
      var results = _.isArray(obj) ? [] : {};
      if (obj == null) return results;
      if (_.isFunction(obj.map)) return obj.map(iterator, context);
      _.each(obj, function(value, index, list) {
        results[index] = iterator.call(context, value, index, list);
      });
      return results;
    }

  });

});
<|endoftext|>


<commit_before><commit_msg>aync promise sample WORKING \o/<commit_after><|endoftext|>


<commit_before>define(["Tone/core/Tone", "Tone/signal/SchedulableSignal", "Tone/core/Schedulable"], function (Tone) {

	Tone.Clock = function(){

		Tone.Schedulable.call(this, 0, 0);

		var options = this.optionsObject(arguments, ["callback", "frequency"], Tone.Clock.defaults);

		/**
		 *  The callback function to invoke on the loop
		 *  @type  {Function}
		 *  @private
		 */
		this._callback = options.callback;

		/**
		 *  The time which the clock will schedule events in advance
		 *  of the current time. Scheduling notes in advance improves
		 *  performance and decreases the chance for clicks caused
		 *  by scheduling events in the past. If set to "auto",
		 *  this value will be automatically computed based on the
		 *  rate of requestAnimationFrame (0.016 seconds). Larger values
		 *  will yeild better performance, but at the cost of latency.
		 *  Values less than 0.016 are not recommended.
		 *  @type {Number|String}
		 */
		this.lookAhead = "auto";

		/**
		 *  The lookahead value which was automatically
		 *  computed using a time-based averaging.
		 *  @type {Number}
		 *  @private
		 */
		this._computedLookAhead = 1/60;

		/**
		 *  The value afterwhich events are thrown out
		 *  @type {Number}
		 *  @private
		 */
		this._threshold = 0.5;

		/**
		 *  The time the next callback function is invoked
		 *  @type {Number}
		 *  @private
		 */
		this._nextTick = 0;

		/**
		 *  The last time the callback was invoked
		 *  @type  {Number}
		 */
		this._lastUpdate = 0;

		/**
		 *  The rate the callback function should be invoked.
		 *  @type  {BPM}
		 *  @signal
		 */
		this.frequency = new Tone.SchedulableSignal(options.frequency, Tone.Type.Frequency).noGC();

		/**
		 *  A pre-binded loop function to save a tiny bit of overhead
		 *  of rebinding the function on every frame.
		 *  @type  {Function}
		 *  @private
		 */
		this._boundLoop = this._loop.bind(this);

		//start the loop
		this._loop();

		//initially it's stopped
		this.stop(0);
	};

	Tone.extend(Tone.Clock, Tone.Schedulable);

	/**
	 *  The defaults
	 *  @const
	 *  @type  {Object}
	 */
	Tone.Clock.defaults = {
		"callback" : Tone.noOp,
		"frequency" : 1,
		"lookAhead" : "auto",
	};

	/**
	 *  Returns the playback state of the source, either "started" or "stopped".
	 *  @type {Tone.State}
	 *  @readOnly
	 *  @memberOf Tone.Clock#
	 *  @name state
	 */
	Object.defineProperty(Tone.Clock.prototype, "state", {
		get : function(){
			return this._getStateAtTime(this.now());
		}
	});

	Tone.Clock.prototype.start = function(time){
		time = this.toSeconds(time);
		if (this._getStateAtTime(time) !== Tone.State.Started){
			this._setStateAtTime(Tone.State.Started, time);
		}
		return this;
	};

	Tone.Clock.prototype.stop = function(time){
		time = this.toSeconds(time);
		if (this._getStateAtTime(time) !== Tone.State.Started || this.retrigger){
			this._setStateAtTime(Tone.State.Stopped, time);
		}
		return this;
	};

	Tone.Clock.prototype._loop = function(time){
		requestAnimationFrame(this._boundLoop);
		//compute the look ahead
		if (this.lookAhead === "auto"){
			if (!this.isUndef(time)){
				var diff = (time - this._lastUpdate) / 1000;
				this._lastUpdate = time;
				//throw away large differences
				if (diff < this._threshold){
					//averaging
					this._computedLookAhead = (9 * this._computedLookAhead + diff) / 10;
				}
			}
		} else {
			this._computedLookAhead = this.lookAhead;
		}
		//if it's started
		if (this.state === Tone.State.Started){
			//get the frequency value to compute the value of the next loop
			var now = this.now();
			while (now + this._computedLookAhead * 2 > this._nextTick){
				if (this._nextTick + this._threshold < now){
					this._nextTick = now;
				}
				this._callback(this._nextTick + this._computedLookAhead * 2);
				this._nextTick += 1 / this.frequency._getValueAtTime(this._nextTick);
			}
		}
	};

	return Tone.Clock;
});<commit_msg>clock counts its own ticks<commit_after>define(["Tone/core/Tone", "Tone/signal/TimelineSignal", "Tone/core/TimelineState"], function (Tone) {

	/**
	 *  @class  A sample accurate clock which provides a callback at the given rate.
	 *          While the callback is not sample-accurate (it is still susceptible to
	 *          loose JS timing), the time passed in as the argument to the callback
	 *          is precise. For most applications, it is better to use Tone.Transport
	 *          instead of the Clock by itself since you can synchronize multiple callbacks.
	 *
	 * 	@constructor
	 * 	@extends {Tone}
	 * 	@param {Frequency} frequency The rate of the callback
	 * 	@param {function} callback The callback to be invoked with the time of the audio event
	 * 	@example
	 * //the callback will be invoked approximately once a second
	 * //and will print the time exactly once a second apart.
	 * var clock = new Tone.Clock(function(time){
	 * 	console.log(time);
	 * }, 1);
	 */
	Tone.Clock = function(){

		var options = this.optionsObject(arguments, ["callback", "frequency"], Tone.Clock.defaults);

		/**
		 *  The callback function to invoke at the scheduled tick.
		 *  @type  {Function}
		 */
		this.callback = options.callback;

		/**
		 *  The time which the clock will schedule events in advance
		 *  of the current time. Scheduling notes in advance improves
		 *  performance and decreases the chance for clicks caused
		 *  by scheduling events in the past. If set to "auto",
		 *  this value will be automatically computed based on the
		 *  rate of requestAnimationFrame (0.016 seconds). Larger values
		 *  will yeild better performance, but at the cost of latency.
		 *  Values less than 0.016 are not recommended.
		 *  @type {Number|String}
		 */
		this._lookAhead = "auto";

		/**
		 *  The lookahead value which was automatically
		 *  computed using a time-based averaging.
		 *  @type {Number}
		 *  @private
		 */
		this._computedLookAhead = 1/60;

		/**
		 *  The value afterwhich events are thrown out
		 *  @type {Number}
		 *  @private
		 */
		this._threshold = 0.5;

		/**
		 *  The next time the callback is scheduled.
		 *  @type {Number}
		 *  @private
		 */
		this._nextTick = -1;

		/**
		 *  The last time the callback was invoked
		 *  @type  {Number}
		 *  @private
		 */
		this._lastUpdate = 0;

		/**
		 *  The id of the requestAnimationFrame
		 *  @type {Number}
		 *  @private
		 */
		this._loopID = -1;

		/**
		 *  The rate the callback function should be invoked.
		 *  @type  {BPM}
		 *  @signal
		 */
		this.frequency = new Tone.TimelineSignal(options.frequency, Tone.Type.Frequency);

		/**
		 *  If the oneneded callback was called.
		 *  @type {Boolean}
		 *  @private
		 */
		this._calledEnded = true;

		/**
		 * Callback is invoked when the clock is stopped.
		 * @type {function}
		 * @example
		 * clock.onended = function(){
		 * 	console.log("the clock is stopped");
		 * }
		 */
		this.onended = options.onended;

		/**
		 *  Keeps track of the number of times the callback was invoked
		 *  @type {Ticks}
		 */
		this.ticks = 0;

		/**
		 *  The state timeline
		 *  @type {Tone.TimelineState}
		 *  @private
		 */
		this._state = new Tone.TimelineState(Tone.State.Stopped);

		/**
		 *  A pre-binded loop function to save a tiny bit of overhead
		 *  of rebinding the function on every frame.
		 *  @type  {Function}
		 *  @private
		 */
		this._boundLoop = this._loop.bind(this);

		this._readOnly("frequency");
		//start the loop
		this._loop();
	};

	Tone.extend(Tone.Clock);

	/**
	 *  The defaults
	 *  @const
	 *  @type  {Object}
	 */
	Tone.Clock.defaults = {
		"callback" : Tone.noOp,
		"frequency" : 1,
		"lookAhead" : "auto",
		"onended" : Tone.noOp
	};

	/**
	 *  Returns the playback state of the source, either "started" or "stopped".
	 *  @type {Tone.State}
	 *  @readOnly
	 *  @memberOf Tone.Clock#
	 *  @name state
	 */
	Object.defineProperty(Tone.Clock.prototype, "state", {
		get : function(){
			return this._state.getStateAtTime(this.now());
		}
	});

	/**
	 *  The time which the clock will schedule events in advance
	 *  of the current time. Scheduling notes in advance improves
	 *  performance and decreases the chance for clicks caused
	 *  by scheduling events in the past. If set to "auto",
	 *  this value will be automatically computed based on the
	 *  rate of requestAnimationFrame (0.016 seconds). Larger values
	 *  will yeild better performance, but at the cost of latency.
	 *  Values less than 0.016 are not recommended.
	 *  @type {Number|String}
	 *  @memberOf Tone.Clock#
	 *  @name lookAhead
	 */
	Object.defineProperty(Tone.Clock.prototype, "lookAhead", {
		get : function(){
			return this._lookAhead;
		},
		set : function(val){
			if (val === "auto"){
				this._lookAhead = "auto";
			} else {
				this._lookAhead = this.toSeconds(val);
			}
		}
	});

	Tone.Clock.prototype.start = function(time, offset){
		time = this.toSeconds(time);
		if (this._state.getStateAtTime(time) !== Tone.State.Started){
			offset = this.defaultArg(offset, 0);
			this._state.addEvent({
				"state" : Tone.State.Started,
				"time" : time,
				"offset" : offset
			});
		}
		return this;
	};

	Tone.Clock.prototype.stop = function(time){
		time = this.toSeconds(time);
		if (this._state.getStateAtTime(time) !== Tone.State.Stopped){
			this._state.setStateAtTime(Tone.State.Stopped, time);
		}
		return this;
	};

	Tone.Clock.prototype.pause = function(time){
		time = this.toSeconds(time);
		if (this._state.getStateAtTime(time) === Tone.State.Started){
			this._state.setStateAtTime(Tone.State.Paused, time);
		}
		return this;
	};

	Tone.Clock.prototype._loop = function(time){
		this._loopID = requestAnimationFrame(this._boundLoop);
		//compute the look ahead
		if (this._lookAhead === "auto"){
			if (!this.isUndef(time)){
				var diff = (time - this._lastUpdate) / 1000;
				this._lastUpdate = time;
				//throw away large differences
				if (diff < this._threshold){
					//averaging
					this._computedLookAhead = (9 * this._computedLookAhead + diff) / 10;
				}
			}
		} else {
			this._computedLookAhead = this._lookAhead;
		}
		//get the frequency value to compute the value of the next loop
		var now = this.now();
		//if it's started
		var lookAhead = this._computedLookAhead * 2;
		var event = this._state.getEvent(now + lookAhead);
		var state = Tone.State.Stopped;
		if (event){
			state = event.state;
			//if it was stopped and now started
			if (this._nextTick === -1 && state === Tone.State.Started){
				this._nextTick = event.time;
				this.ticks = event.offset;
			}
		}
		if (state === Tone.State.Started){
			while (now + lookAhead > this._nextTick){
				//catch up
				if (now > this._nextTick + this._threshold){
					this._nextTick = now;
				}
				var tickTime = this._nextTick;
				this._nextTick += 1 / this.frequency.getValueAtTime(this._nextTick);
				this.callback(tickTime);
				this.ticks++;
			}
		} else if (state === Tone.State.Stopped){
			this._nextTick = -1;
			this.ticks = 0;
		}
	};

	/**
	 *  Returns the scheduled state scheduled before or at
	 *  the given time.
	 *  @param  {Time}  time  The time to query.
	 *  @return  {String}  The name of the state input in setStateAtTime.
	 */
	Tone.Clock.prototype.getStateAtTime = function(time){
		return this._state.getStateAtTime(time);
	};

	/**
	 *  Clean up
	 *  @returns {Tone.Clock} this
	 */
	Tone.Clock.prototype.dispose = function(){
		cancelAnimationFrame(this._loopID);
		Tone.TimelineState.prototype.dispose.call(this);
		this._writable("frequency");
		this.frequency.dispose();
		this.frequency = null;
		this._boundLoop = Tone.noOp;
		this._nextTick = Infinity;
		this.callback = null;
		this._state.dispose();
		this._state = null;
	};

	return Tone.Clock;
});<|endoftext|>