<commit_before>/*global
    ServerMarshal,
    $serverSide, createError, getOptionsData,
    normalizeHTMLAttributeOptions, viewHelperAttributeName
*/
var viewPlaceholderAttributeName = 'data-view-tmp',
    viewTemplateOverrides = {};

// Will be shared by HelperView and CollectionHelperView
var helperViewPrototype = {
  _ensureElement: function() {
    Thorax.View.prototype._ensureElement.apply(this, arguments);
    this.$el.attr(viewHelperAttributeName, this._helperName);
  },
  _getContext: function() {
    return this.parent._getContext.apply(this.parent, arguments);
  }
};

Thorax.HelperView = Thorax.View.extend(helperViewPrototype);

// Ensure nested inline helpers will always have this.parent
// set to the view containing the template
function getParent(parent) {
  // The `view` helper is a special case as it embeds
  // a view instead of creating a new one
  while (parent._helperName && parent._helperName !== 'view') {
    parent = parent.parent;
  }
  return parent;
}

function expandHash(context, hash) {
  if (hash['expand-tokens']) {
    delete hash['expand-tokens'];
    _.each(hash, function(value, key) {
      hash[key] = Thorax.Util.expandToken(value, context);
    });
    return true;
  }
}

Handlebars.registerViewHelper = function(name, ViewClass, callback) {
  if (arguments.length === 2) {
    if (ViewClass.factory) {
      callback = ViewClass.callback;
    } else {
      callback = ViewClass;
      ViewClass = Thorax.HelperView;
    }
  }

  var viewOptionWhiteList = ViewClass.attributeWhiteList;

  Handlebars.registerHelper(name, function() {
    var args = _.toArray(arguments),
        options = args.pop(),
        declaringView = getOptionsData(options).view;

    // Evaluate any nested parameters that we may have to content with
    var expandTokens = expandHash(this, options.hash);

    var viewOptions = createViewOptions(name, args, options, declaringView);
    setHelperTemplate(viewOptions, options, ViewClass);

    normalizeHTMLAttributeOptions(options.hash);
    var htmlAttributes = _.clone(options.hash);

    // Remap any view options per the whitelist and remove the source form the HTML
    _.each(viewOptionWhiteList, function(dest, source) {
      delete htmlAttributes[source];
      if (!_.isUndefined(options.hash[source])) {
        viewOptions[dest] = options.hash[source];
      }
    });
    if(htmlAttributes.tagName) {
      viewOptions.tagName = htmlAttributes.tagName;
    }

    viewOptions.attributes = function() {
      var attrs = (ViewClass.prototype && ViewClass.prototype.attributes) || {};
      if (_.isFunction(attrs)) {
        attrs = attrs.apply(this, arguments);
      }
      _.extend(attrs, _.omit(htmlAttributes, ['tagName']));
      // backbone wants "class"
      if (attrs.className) {
        attrs['class'] = attrs.className;
        delete attrs.className;
      }
      return attrs;
    };

    // Check to see if we have an existing instance that we can reuse
    var instance = _.find(declaringView._previousHelpers, function(child) {
      return child._cull && compareHelperOptions(viewOptions, child);
    });

    // Create the instance if we don't already have one
    if (!instance) {
      instance = getHelperInstance(args, viewOptions, ViewClass);
      if (!instance) {
        return '';
      }

      instance.$el.attr('data-view-helper-restore', name);

      if ($serverSide && instance.$el.attr('data-view-restore') !== 'false') {
        try {
          ServerMarshal.store(instance.$el, 'args', args, options.ids, options);
          ServerMarshal.store(instance.$el, 'attrs', options.hash, options.hashIds, options);
          if (options.fn && options.fn !== Handlebars.VM.noop) {
            ServerMarshal.store(instance.$el, 'fn', options.fn.program);
          }
          if (options.inverse && options.inverse !== Handlebars.VM.noop) {
            ServerMarshal.store(instance.$el, 'inverse', options.inverse.program);
          }
        } catch (err) {
          instance.$el.attr('data-view-restore', 'false');
        }
      }

      helperInit(args, instance, callback, viewOptions);
    } else {
      if (!instance.el) {
        throw new Error('insert-destroyed');
      }

      declaringView.children[instance.cid] = instance;
    }

    // Remove any possible entry in previous helpers in case this is a cached value returned from
    // slightly different data that does not qualify for the previous helpers direct reuse.
    // (i.e. when using an array that is modified between renders)
    instance._cull = false;

    // Register the append helper if not already done
    if (!declaringView._pendingAppend) {
      declaringView._pendingAppend = true;
      declaringView.once('append', helperAppend);
    }

    htmlAttributes[viewPlaceholderAttributeName] = instance.cid;
    if (ViewClass.modifyHTMLAttributes) {
      ViewClass.modifyHTMLAttributes(htmlAttributes, instance);
    }
    return new Handlebars.SafeString(Thorax.Util.tag(htmlAttributes, '', expandTokens ? this : null));
  });
  var helper = Handlebars.helpers[name];

  helper.restore = function(declaringView, el) {
    var context = declaringView.context(),
        args = ServerMarshal.load(el, 'args', declaringView, context) || [],
        attrs = ServerMarshal.load(el, 'attrs', declaringView, context) || {};

    var options = {
      hash: attrs,
      fn: ServerMarshal.load(el, 'fn'),
      inverse: ServerMarshal.load(el, 'inverse')
    };
    if (options.fn) {
      options.fn = declaringView.template.child(options.fn);
    }
    if (options.inverse) {
      options.inverse = declaringView.template.child(options.inverse);
    }

    var viewOptions = createViewOptions(name, args, options, declaringView);
    setHelperTemplate(viewOptions, options, ViewClass);

    if (viewOptionWhiteList) {
      _.each(viewOptionWhiteList, function(dest, source) {
        if (!_.isUndefined(attrs[source])) {
          viewOptions[dest] = attrs[source];
        }
      });
    }

    var instance = getHelperInstance(args, viewOptions, ViewClass);
    instance._assignCid(el.getAttribute('data-view-cid'));
    helperInit(args, instance, callback, viewOptions);

    instance.restore(el);

    return instance;
  };

  return helper;
};

Thorax.View.on('restore', function() {
  var parent = this,
      context;

  function filterAncestors(parent, callback) {
    return function() {
      if ($(this).parent().view({el: true, helper: true})[0] === parent.el) {
        return callback.call(this);
      }
    };
   }

  parent.$('[data-view-helper-restore]').each(filterAncestors(parent, function() {
    if (this.getAttribute('data-view-restore') === 'true') {
      var helper = Handlebars.helpers[this.getAttribute('data-view-helper-restore')],
          child = helper.restore(parent, this);
      parent._addChild(child);
    }
  }));
});

function createViewOptions(name, args, options, declaringView) {
  return {
    inverse: options.inverse,
    options: options.hash,
    declaringView: declaringView,
    parent: getParent(declaringView),
    _helperName: name,
    _helperOptions: {
      options: cloneHelperOptions(options),
      args: _.clone(args)
    }
  };
}

function setHelperTemplate(viewOptions, options, ViewClass) {
  if (options.fn) {
    // Only assign if present, allow helper view class to
    // declare template
    viewOptions.template = options.fn;
  } else if (ViewClass && ViewClass.prototype && !ViewClass.prototype.template) {
    // ViewClass may also be an instance or object with factory method
    // so need to do this check
    viewOptions.template = Handlebars.VM.noop;
  }
}

function getHelperInstance(args, viewOptions, ViewClass) {
  var instance;

  if (ViewClass.factory) {
    instance = ViewClass.factory(args, viewOptions);
    if (!instance) {
      return;
    }

    instance._helperName = viewOptions._helperName;
    instance._helperOptions = viewOptions._helperOptions;
  } else {
    instance = new ViewClass(viewOptions);
  }

  if (!instance.el) {
    // ViewClass.factory may return existing objects which may have been destroyed
    throw createError('insert-destroyed-factory');
  }
  return instance;
}
function helperInit(args, instance, callback, viewOptions) {
  var declaringView = viewOptions.declaringView,
      name = viewOptions._helperName;

  args.push(instance);
  declaringView._addChild(instance);
  declaringView.trigger.apply(declaringView, ['helper', name].concat(args));
  declaringView.trigger.apply(declaringView, ['helper:' + name].concat(args));

  callback && callback.apply(this, args);
}

function helperAppend(scope, callback) {
  this._pendingAppend = undefined;

  (scope || this.$el).find('[' + viewPlaceholderAttributeName + ']').forEach(function(el) {
    var $el = $(el),
        placeholderId = $el.attr(viewPlaceholderAttributeName),
        view = this.children[placeholderId];

    if (view) {
      //see if the view helper declared an override for the view
      //if not, ensure the view has been rendered at least once
      if (viewTemplateOverrides[placeholderId]) {
        view.render(viewTemplateOverrides[placeholderId]);
        delete viewTemplateOverrides[placeholderId];
      } else {
        view.ensureRendered();
      }
      $el.replaceWith(view.el);
      callback && callback(view.$el);
    }
  }, this);
}

/**
 * Clones the helper options, dropping items that are known to change
 * between rendering cycles as appropriate.
 */
function cloneHelperOptions(options) {
  var ret = _.pick(options, 'fn', 'inverse', 'hash', 'data');
  ret.data = _.omit(options.data, 'cid', 'view', 'yield', 'root', '_parent');

  // This is necessary to prevent failures when mixing restored and rendered data
  // as it forces the keys object to be complete.
  ret.fn = ret.fn || undefined;
  ret.inverse = ret.inverse || undefined;

  return ret;
}

/**
 * Checks for basic equality between two sets of parameters for a helper view.
 *
 * Checked fields include:
 *  - _helperName
 *  - All args
 *  - Hash
 *  - Data
 *  - Function and Invert (id based if possible)
 *
 * This method allows us to determine if the inputs to a given view are the same. If they
 * are then we make the assumption that the rendering will be the same (or the child view will
 * otherwise rerendering it by monitoring it's parameters as necessary) and reuse the view on
 * rerender of the parent view.
 */
function compareHelperOptions(a, b) {
  function compareValues(a, b) {
    return _.every(a, function(value, key) {
      return b[key] === value;
    });
  }

  if (a._helperName !== b._helperName) {
    return false;
  }

  a = a._helperOptions;
  b = b._helperOptions;

  // Implements a first level depth comparison
  return a.args.length === b.args.length
      && compareValues(a.args, b.args)
      && _.isEqual(_.keys(a.options).sort(), _.keys(b.options).sort())
      && _.every(a.options, function(value, key) {
          if (key === 'data' || key === 'hash') {
            return compareValues(a.options[key], b.options[key]);
          } else if (key === 'fn' || key === 'inverse') {
            if (b.options[key] === value) {
              return true;
            }

            var other = b.options[key] || {};
            return value && _.has(value, 'program') && !value.depth && other.program === value.program;
          }
          return b.options[key] === value;
        });
}
<commit_msg>Move helper conditional into selector<commit_after>/*global
    ServerMarshal,
    $serverSide, createError, getOptionsData,
    normalizeHTMLAttributeOptions, viewHelperAttributeName
*/
var viewPlaceholderAttributeName = 'data-view-tmp',
    viewTemplateOverrides = {};

// Will be shared by HelperView and CollectionHelperView
var helperViewPrototype = {
  _ensureElement: function() {
    Thorax.View.prototype._ensureElement.apply(this, arguments);
    this.$el.attr(viewHelperAttributeName, this._helperName);
  },
  _getContext: function() {
    return this.parent._getContext.apply(this.parent, arguments);
  }
};

Thorax.HelperView = Thorax.View.extend(helperViewPrototype);

// Ensure nested inline helpers will always have this.parent
// set to the view containing the template
function getParent(parent) {
  // The `view` helper is a special case as it embeds
  // a view instead of creating a new one
  while (parent._helperName && parent._helperName !== 'view') {
    parent = parent.parent;
  }
  return parent;
}

function expandHash(context, hash) {
  if (hash['expand-tokens']) {
    delete hash['expand-tokens'];
    _.each(hash, function(value, key) {
      hash[key] = Thorax.Util.expandToken(value, context);
    });
    return true;
  }
}

Handlebars.registerViewHelper = function(name, ViewClass, callback) {
  if (arguments.length === 2) {
    if (ViewClass.factory) {
      callback = ViewClass.callback;
    } else {
      callback = ViewClass;
      ViewClass = Thorax.HelperView;
    }
  }

  var viewOptionWhiteList = ViewClass.attributeWhiteList;

  Handlebars.registerHelper(name, function() {
    var args = _.toArray(arguments),
        options = args.pop(),
        declaringView = getOptionsData(options).view;

    // Evaluate any nested parameters that we may have to content with
    var expandTokens = expandHash(this, options.hash);

    var viewOptions = createViewOptions(name, args, options, declaringView);
    setHelperTemplate(viewOptions, options, ViewClass);

    normalizeHTMLAttributeOptions(options.hash);
    var htmlAttributes = _.clone(options.hash);

    // Remap any view options per the whitelist and remove the source form the HTML
    _.each(viewOptionWhiteList, function(dest, source) {
      delete htmlAttributes[source];
      if (!_.isUndefined(options.hash[source])) {
        viewOptions[dest] = options.hash[source];
      }
    });
    if(htmlAttributes.tagName) {
      viewOptions.tagName = htmlAttributes.tagName;
    }

    viewOptions.attributes = function() {
      var attrs = (ViewClass.prototype && ViewClass.prototype.attributes) || {};
      if (_.isFunction(attrs)) {
        attrs = attrs.apply(this, arguments);
      }
      _.extend(attrs, _.omit(htmlAttributes, ['tagName']));
      // backbone wants "class"
      if (attrs.className) {
        attrs['class'] = attrs.className;
        delete attrs.className;
      }
      return attrs;
    };

    // Check to see if we have an existing instance that we can reuse
    var instance = _.find(declaringView._previousHelpers, function(child) {
      return child._cull && compareHelperOptions(viewOptions, child);
    });

    // Create the instance if we don't already have one
    if (!instance) {
      instance = getHelperInstance(args, viewOptions, ViewClass);
      if (!instance) {
        return '';
      }

      instance.$el.attr('data-view-helper-restore', name);

      if ($serverSide && instance.$el.attr('data-view-restore') !== 'false') {
        try {
          ServerMarshal.store(instance.$el, 'args', args, options.ids, options);
          ServerMarshal.store(instance.$el, 'attrs', options.hash, options.hashIds, options);
          if (options.fn && options.fn !== Handlebars.VM.noop) {
            ServerMarshal.store(instance.$el, 'fn', options.fn.program);
          }
          if (options.inverse && options.inverse !== Handlebars.VM.noop) {
            ServerMarshal.store(instance.$el, 'inverse', options.inverse.program);
          }
        } catch (err) {
          instance.$el.attr('data-view-restore', 'false');
        }
      }

      helperInit(args, instance, callback, viewOptions);
    } else {
      if (!instance.el) {
        throw new Error('insert-destroyed');
      }

      declaringView.children[instance.cid] = instance;
    }

    // Remove any possible entry in previous helpers in case this is a cached value returned from
    // slightly different data that does not qualify for the previous helpers direct reuse.
    // (i.e. when using an array that is modified between renders)
    instance._cull = false;

    // Register the append helper if not already done
    if (!declaringView._pendingAppend) {
      declaringView._pendingAppend = true;
      declaringView.once('append', helperAppend);
    }

    htmlAttributes[viewPlaceholderAttributeName] = instance.cid;
    if (ViewClass.modifyHTMLAttributes) {
      ViewClass.modifyHTMLAttributes(htmlAttributes, instance);
    }
    return new Handlebars.SafeString(Thorax.Util.tag(htmlAttributes, '', expandTokens ? this : null));
  });
  var helper = Handlebars.helpers[name];

  helper.restore = function(declaringView, el) {
    var context = declaringView.context(),
        args = ServerMarshal.load(el, 'args', declaringView, context) || [],
        attrs = ServerMarshal.load(el, 'attrs', declaringView, context) || {};

    var options = {
      hash: attrs,
      fn: ServerMarshal.load(el, 'fn'),
      inverse: ServerMarshal.load(el, 'inverse')
    };
    if (options.fn) {
      options.fn = declaringView.template.child(options.fn);
    }
    if (options.inverse) {
      options.inverse = declaringView.template.child(options.inverse);
    }

    var viewOptions = createViewOptions(name, args, options, declaringView);
    setHelperTemplate(viewOptions, options, ViewClass);

    if (viewOptionWhiteList) {
      _.each(viewOptionWhiteList, function(dest, source) {
        if (!_.isUndefined(attrs[source])) {
          viewOptions[dest] = attrs[source];
        }
      });
    }

    var instance = getHelperInstance(args, viewOptions, ViewClass);
    instance._assignCid(el.getAttribute('data-view-cid'));
    helperInit(args, instance, callback, viewOptions);

    instance.restore(el);

    return instance;
  };

  return helper;
};

Thorax.View.on('restore', function() {
  var parent = this,
      context;

  function filterAncestors(parent, callback) {
    return function() {
      if ($(this).parent().view({el: true, helper: true})[0] === parent.el) {
        return callback.call(this);
      }
    };
   }

  parent.$('[data-view-helper-restore][data-view-restore=true]').each(filterAncestors(parent, function() {
    var helper = Handlebars.helpers[this.getAttribute('data-view-helper-restore')],
        child = helper.restore(parent, this);
    parent._addChild(child);
  }));
});

function createViewOptions(name, args, options, declaringView) {
  return {
    inverse: options.inverse,
    options: options.hash,
    declaringView: declaringView,
    parent: getParent(declaringView),
    _helperName: name,
    _helperOptions: {
      options: cloneHelperOptions(options),
      args: _.clone(args)
    }
  };
}

function setHelperTemplate(viewOptions, options, ViewClass) {
  if (options.fn) {
    // Only assign if present, allow helper view class to
    // declare template
    viewOptions.template = options.fn;
  } else if (ViewClass && ViewClass.prototype && !ViewClass.prototype.template) {
    // ViewClass may also be an instance or object with factory method
    // so need to do this check
    viewOptions.template = Handlebars.VM.noop;
  }
}

function getHelperInstance(args, viewOptions, ViewClass) {
  var instance;

  if (ViewClass.factory) {
    instance = ViewClass.factory(args, viewOptions);
    if (!instance) {
      return;
    }

    instance._helperName = viewOptions._helperName;
    instance._helperOptions = viewOptions._helperOptions;
  } else {
    instance = new ViewClass(viewOptions);
  }

  if (!instance.el) {
    // ViewClass.factory may return existing objects which may have been destroyed
    throw createError('insert-destroyed-factory');
  }
  return instance;
}
function helperInit(args, instance, callback, viewOptions) {
  var declaringView = viewOptions.declaringView,
      name = viewOptions._helperName;

  args.push(instance);
  declaringView._addChild(instance);
  declaringView.trigger.apply(declaringView, ['helper', name].concat(args));
  declaringView.trigger.apply(declaringView, ['helper:' + name].concat(args));

  callback && callback.apply(this, args);
}

function helperAppend(scope, callback) {
  this._pendingAppend = undefined;

  (scope || this.$el).find('[' + viewPlaceholderAttributeName + ']').forEach(function(el) {
    var $el = $(el),
        placeholderId = $el.attr(viewPlaceholderAttributeName),
        view = this.children[placeholderId];

    if (view) {
      //see if the view helper declared an override for the view
      //if not, ensure the view has been rendered at least once
      if (viewTemplateOverrides[placeholderId]) {
        view.render(viewTemplateOverrides[placeholderId]);
        delete viewTemplateOverrides[placeholderId];
      } else {
        view.ensureRendered();
      }
      $el.replaceWith(view.el);
      callback && callback(view.$el);
    }
  }, this);
}

/**
 * Clones the helper options, dropping items that are known to change
 * between rendering cycles as appropriate.
 */
function cloneHelperOptions(options) {
  var ret = _.pick(options, 'fn', 'inverse', 'hash', 'data');
  ret.data = _.omit(options.data, 'cid', 'view', 'yield', 'root', '_parent');

  // This is necessary to prevent failures when mixing restored and rendered data
  // as it forces the keys object to be complete.
  ret.fn = ret.fn || undefined;
  ret.inverse = ret.inverse || undefined;

  return ret;
}

/**
 * Checks for basic equality between two sets of parameters for a helper view.
 *
 * Checked fields include:
 *  - _helperName
 *  - All args
 *  - Hash
 *  - Data
 *  - Function and Invert (id based if possible)
 *
 * This method allows us to determine if the inputs to a given view are the same. If they
 * are then we make the assumption that the rendering will be the same (or the child view will
 * otherwise rerendering it by monitoring it's parameters as necessary) and reuse the view on
 * rerender of the parent view.
 */
function compareHelperOptions(a, b) {
  function compareValues(a, b) {
    return _.every(a, function(value, key) {
      return b[key] === value;
    });
  }

  if (a._helperName !== b._helperName) {
    return false;
  }

  a = a._helperOptions;
  b = b._helperOptions;

  // Implements a first level depth comparison
  return a.args.length === b.args.length
      && compareValues(a.args, b.args)
      && _.isEqual(_.keys(a.options).sort(), _.keys(b.options).sort())
      && _.every(a.options, function(value, key) {
          if (key === 'data' || key === 'hash') {
            return compareValues(a.options[key], b.options[key]);
          } else if (key === 'fn' || key === 'inverse') {
            if (b.options[key] === value) {
              return true;
            }

            var other = b.options[key] || {};
            return value && _.has(value, 'program') && !value.depth && other.program === value.program;
          }
          return b.options[key] === value;
        });
}
<|endoftext|>


<commit_before>// Hexdump.js 0.1.0
// (c) 2011 Dustin Willis Webber
// Hexdump is freely distributable under the MIT license.
// For all details and documentation:
// http://github.com/mephux/hexdump.js
var Hexdump;
Hexdump=function(){function f(c,b){var a=this;a.hexdump=[];a.hex=!1;a.options={container:b.container||"",width:b.width||16,byteGrouping:b.byteGrouping||0,ascii:b.ascii||!1,lineNumber:b.lineNumber,endian:b.endian||"big",html:b.html,base:b.base||"hexadecimal",nonPrintable:b.nonPrintable||".",style:{lineNumberLeft:b.style.lineNumberLeft||"",lineNumberRight:b.style.lineNumberRight||":",stringLeft:b.style.stringLeft||"|",stringRight:b.style.stringRight||"|",hexLeft:b.style.hexLeft||"",hexRight:b.style.hexRight||"",
hexNull:b.style.hexNull||".",stringNull:b.style.stringNull||" "}};if(a.options.base=="hex")a.hex=!0;else if(a.options.base=="hexadecimal")a.hex=!0;console.log(a.hex);var d=a.options.lineNumber;if(typeof d=="undefined"||d==null)a.options.lineNumber=!0;d=a.options.html;if(typeof d=="undefined"||d==null)a.options.html=!0;if(a.endian!="little")a.endian="big";if(a.options.byteGrouping>c.length)a.options.byteGrouping=c.length;a.options.byteGrouping--;if(a.options.width>c.length)a.options.width=c.length;
a.padding={hex:4,dec:5,bin:8};switch(a.options.base){case "hexadecimal":case "hex":case 16:a.setNullPadding(a.padding.hex);a.baseConvert=function(b){for(;0<b.length;)return a.addPadding(b[0].charCodeAt(0).toString(16),a.padding.hex)};break;case "decimal":case "dec":case 10:a.setNullPadding(a.padding.dec);a.baseConvert=function(b){for(;0<b.length;)return a.addPadding(b[0].charCodeAt(0),a.padding.dec)};break;case "binary":case "bin":case 2:a.setNullPadding(a.padding.bin);a.baseConvert=function(b){for(;0<
b.length;){b=b[0].charCodeAt(0);for(var c="",d=0;d<8;d++)c=b%2+c,b=Math.floor(b/2);return a.addPadding(c,a.padding.bin)}};break;default:a.options.base="hex",a.hex=!0,a.setNullPadding(a.padding.hex),a.baseConvert=function(b){for(;0<b.length;)return a.addPadding(b[0].charCodeAt(0).toString(16),a.padding.hex)}}a.data=c.match(RegExp(".{1,"+this.options.width+"}","g"));a.nullCount=a.options.width-a.data[a.data.length-1].length;a.hexCounter=0;for(d=a.stringCounter=0;d<a.data.length;d++){var e=a.process(a.data[d]);
a.hexdump.push({data:e.data,string:e.string,length:a.data[d].length,missing:a.options.width-a.data[d].length})}a.dump()}function g(c){var b=c.charCodeAt(0).toString(16);return b==9?".":b==127?".":c}f.prototype.dump=function(){this.output="";for(var c=0;c<this.hexdump.length;c++){if(this.options.lineNumber){var b="";b+=this.options.style.lineNumberLeft;for(var a=c*this.options.width,d=8-a.toString().length,e=0;e<d;e++)b+="0";b+=a;b+=this.options.style.lineNumberRight+" ";this.output+=this.options.html?
''+b+"":b}b=0;this.output+=this.options.style.hexLeft;for(a=0;a<this.hexdump[c].data.length;a++)b==this.options.byteGrouping?(this.output+=a==this.hexdump[c].data.length-1?this.hexdump[c].data[a]:this.hexdump[c].data[a]+" ",b=0):(this.output+=this.hexdump[c].data[a],b++);this.output+=this.options.style.hexRight;this.appendString(this.hexdump[c]);this.output+="\n"}document.getElementById(this.options.container).innerHTML=this.output};f.prototype.appendString=function(c){this.output+=
" "+this.options.style.stringLeft;this.output+=c.string;this.output+=this.options.style.stringRight};f.prototype.splitNulls=function(c){var b=[],a="";if(c&&c.length>2)for(var d=0;d<c.length;d++)(d+1)%2==0?(a+=c[d].toString(),b.push(a),a=""):a+=c[d].toString();return b};f.prototype.process=function(c){for(var b=[],a=[],d=0;d<c.length;d++){if(this.options.html){var e=this.baseConvert(c[d]);if(this.hex){e=this.splitNulls(e);for(var f=0;f<e.length;f++)a.push(''+
e[f]+"")}else a.push(''+e+"");b.push(''+g(c[d])+"")}else{e=this.baseConvert(c[d]);if(this.options.base=="hex"){e=this.splitNulls(e);for(f=0;f<e.length;f++)a.push(e[f])}else a.push(e);b.push(g(c[d]))}this.hexCounter++}d=this.hex?this.options.width*2:this.options.width;if(a.length<d){c=d-a.length;for(d=0;d<c;d++)e="",e=this.options.html?''+this.options.style.hexNull+"":
this.options.style.hexNull,a.push(e)}if(b.length<this.options.width){c=this.options.width-b.length;for(d=0;d<c;d++)e="",e=this.options.html?''+this.options.style.stringNull+"":this.options.style.stringNull,b.push(e)}return{data:a,string:b.join("")}};f.prototype.setNullPadding=function(c){var b=this.options.style.hexNull[0];this.options.style.hexNull="";this.hex&&(c/=2);for(var a=0;a<c;a++)this.options.style.hexNull+=b};f.prototype.addPadding=function(c,b){for(var a=
c.toString().length,d="",e=0;e<b-a;e++)d+="0";return this.options.endian=="big"?d+c:c+d};return f}();
<commit_msg>build assets<commit_after>// Hexdump.js 0.1.0
// (c) 2011 Dustin Willis Webber
// Hexdump is freely distributable under the MIT license.
// For all details and documentation:
// http://github.com/mephux/hexdump.js
var Hexdump;
Hexdump=function(){function f(c,b){var a=this;a.hexdump=[];a.hex=!1;a.options={container:b.container||"",width:b.width||16,byteGrouping:b.byteGrouping||0,ascii:b.ascii||!1,lineNumber:b.lineNumber,endian:b.endian||"big",html:b.html,base:b.base||"hexadecimal",nonPrintable:b.nonPrintable||".",style:{lineNumberLeft:b.style.lineNumberLeft||"",lineNumberRight:b.style.lineNumberRight||":",stringLeft:b.style.stringLeft||"|",stringRight:b.style.stringRight||"|",hexLeft:b.style.hexLeft||"",hexRight:b.style.hexRight||"",
hexNull:b.style.hexNull||".",stringNull:b.style.stringNull||" "}};if(a.options.base=="hex")a.hex=!0;else if(a.options.base=="hexadecimal")a.hex=!0;console.log(a.hex);var d=a.options.lineNumber;if(typeof d=="undefined"||d==null)a.options.lineNumber=!0;d=a.options.html;if(typeof d=="undefined"||d==null)a.options.html=!0;if(a.endian!="little")a.endian="big";if(a.options.byteGrouping>c.length)a.options.byteGrouping=c.length;a.options.byteGrouping--;if(a.options.width>c.length)a.options.width=c.length;
a.padding={hex:4,dec:5,bin:8};switch(a.options.base){case "hexadecimal":case "hex":case 16:a.setNullPadding(a.padding.hex);a.baseConvert=function(b){for(;0<b.length;)return a.addPadding(b[0].charCodeAt(0).toString(16),a.padding.hex)};break;case "decimal":case "dec":case 10:a.setNullPadding(a.padding.dec);a.baseConvert=function(b){for(;0<b.length;)return a.addPadding(b[0].charCodeAt(0),a.padding.dec)};break;case "binary":case "bin":case 2:a.setNullPadding(a.padding.bin);a.baseConvert=function(b){for(;0<
b.length;){b=b[0].charCodeAt(0);for(var c="",d=0;d<8;d++)c=b%2+c,b=Math.floor(b/2);return a.addPadding(c,a.padding.bin)}};break;default:a.options.base="hex",a.hex=!0,a.setNullPadding(a.padding.hex),a.baseConvert=function(b){for(;0<b.length;)return a.addPadding(b[0].charCodeAt(0).toString(16),a.padding.hex)}}a.data=c.match(RegExp(".{1,"+this.options.width+"}","g"));a.nullCount=a.options.width-a.data[a.data.length-1].length;a.hexCounter=0;for(d=a.stringCounter=0;d<a.data.length;d++){var e=a.process(a.data[d]);
a.hexdump.push({data:e.data,string:e.string,length:a.data[d].length,missing:a.options.width-a.data[d].length})}a.dump()}function g(c){var b=c.charCodeAt(0).toString(16);return b==9?".":b==127?".":c}f.prototype.dump=function(){this.output="";for(var c=0;c<this.hexdump.length;c++){if(this.options.lineNumber){var b="";b+=this.options.style.lineNumberLeft;for(var a=c*this.options.width,d=8-a.toString().length,e=0;e<d;e++)b+="0";b+=a;b+=this.options.style.lineNumberRight+" ";this.output+=this.options.html?
''+b+"":b}b=0;this.output+=this.options.style.hexLeft;for(a=0;a<this.hexdump[c].data.length;a++)b==this.options.byteGrouping?(this.output+=a==this.hexdump[c].data.length-1?this.hexdump[c].data[a]:this.hexdump[c].data[a]+" ",b=0):(this.output+=this.hexdump[c].data[a],b++);this.output+=this.options.style.hexRight;this.appendString(this.hexdump[c]);this.output+="\n"}document.getElementById(this.options.container).innerHTML=this.output};f.prototype.appendString=function(c){this.output+=
" "+this.options.style.stringLeft;this.output+=c.string;this.output+=this.options.style.stringRight};f.prototype.splitNulls=function(c){var b=[],a="";if(c&&c.length>2)for(var d=0;d<c.length;d++)(d+1)%2==0?(a+=c[d].toString(),b.push(a),a=""):a+=c[d].toString();return b};f.prototype.process=function(c){for(var b=[],a=[],d=0;d<c.length;d++){if(this.options.html){var e=this.baseConvert(c[d]);if(this.hex){e=this.splitNulls(e);for(var f=0;f<e.length;f++)a.push(''+
e[f]+"")}else a.push(''+e+"");b.push(''+g(c[d])+"")}else{e=this.baseConvert(c[d]);if(this.hex){e=this.splitNulls(e);for(f=0;f<e.length;f++)a.push(e[f])}else a.push(e);b.push(g(c[d]))}this.hexCounter++}d=this.hex?this.options.width*2:this.options.width;if(a.length<d){c=d-a.length;for(d=0;d<c;d++)e="",e=this.options.html?''+this.options.style.hexNull+"":this.options.style.hexNull,
a.push(e)}if(b.length<this.options.width){c=this.options.width-b.length;for(d=0;d<c;d++)e="",e=this.options.html?''+this.options.style.stringNull+"":this.options.style.stringNull,b.push(e)}return{data:a,string:b.join("")}};f.prototype.setNullPadding=function(c){var b=this.options.style.hexNull[0];this.options.style.hexNull="";this.hex&&(c/=2);for(var a=0;a<c;a++)this.options.style.hexNull+=b};f.prototype.addPadding=function(c,b){for(var a=c.toString().length,d=
"",e=0;e<b-a;e++)d+="0";return this.options.endian=="big"?d+c:c+d};return f}();
<|endoftext|>


<commit_before>;
/* main initialization routine */
$.fn.towelFoundation = function() {
    /* onReady */
    $(function() {
        var onReady = window.onReady || [];
        for (var i=0, l=onReady.length; i<l; i++) onReady[i].apply(null, [$]);
    });

    return this;
};

/* various plugins */
$.fn.flash = function() {
    return this.each(function() {
        var $this = $(this),
            opacity = $this.css('opacity');

        $this.css('opacity', 0.3).animate({opacity: opacity});
    });
};

$.fn.autogrow = function() {
    return this.not('.hasAutogrow').addClass('hasAutogrow').elastic();
};

/* gettext dummy
* if you need internationalizations, read here how to activate:
* https://docs.djangoproject.com/en/dev/topics/i18n/translation/#internationalization-in-javascript-code
* */
if (window.gettext === undefined) {
    window.gettext = function(msgid) {
        return msgid
    }
}

/* init forms */
(function($) {
    if (!window.onForm) window.onForm = [];

    var onForm = window.onForm,
        initForms = function(elem) {
            var elem = $(elem || document);
            for (var i=0, len=onForm.length; i<len; ++i)
                onForm[i].apply(null, [elem, $]);
        };

    onForm.push(function(elem, $) {
        if ($.fn.chosen)
            elem.find('select').not('.plain').chosen();
        if ($.fn.pickadate) {
            elem.find('.type-date').each(function() {
                var self = $(this),
                    input = self.find('input.dateinput');

                input.pickadate({
                    format: self.data('date-format')
                    , formatSubmit: self.data('date-format')
                    , selectYears: true
                    , selectMonths: true
                    , data: true
                });

                // https://github.com/amsul/pickadate.js/issues/128
                // uhm...
                var p = input.data('pickadate');
                if (p.get())
                    p.set('select', p.get(), {
                        format: self.data('date-format'), data: true});
            });
        }

        elem.find('textarea.autogrow, .autogrow textarea').autogrow();
    });

    onReady.push(function() { initForms(); });

    /* inject function into the global namespace */
    if (!window.initForms) window.initForms = initForms;

    $(document.body).on('updateLive', function(event, elem) {
        event.stopPropagation();
        elem.flash();
        initForms(elem);
    });
})(jQuery);

/* ajax modals */
(function($) {
    var initModal = function() {
            var modal = this,
                $elem = $(this);

            $elem.find('form').each(function() {
                var $form = $(this),
                    handleResponse = function(data) {
                        window.modalLoad.locked = false;

                        if (typeof(data) == 'string') {
                            $elem.html(data);
                            initModal.call($elem.get(0));
                        } else {
                            updateLive(data);
                            if (!('!keep' in data))
                                $elem.foundation('reveal', 'close');
                        }
                    }

                // set modal to locked: navigating away will be prevented
                // and also closing the modal will prompt the user
                $form.filter('[method="post"]').on('change', function(event) {
                    window.modalLoad.locked = true;
                });

                $form.on('submit', function() {
                    if (this.method.toLowerCase() == 'post') {
                        if ($.fn.ajaxSubmit) {
                            // jquery.form.js is available, XHR file uploads will
                            // work too
                            var $bar = $elem.find('.progress-bar');

                            $(this).ajaxSubmit({
                                uploadProgress: function(evt, pos, total, percComplete) {
                                    $bar.width(percComplete + '%');
                                },
                                beforeSubmit: function() {
                                    $bar.width('0%');
                                },
                                success: handleResponse
                            });
                        } else {
                            $.post(this.action, $form.serialize(), handleResponse);
                        }
                    } else {
                        $.get(this.action, $form.serialize(), handleResponse);
                    }
                    return false;
                });

                // focus the first form element
                (function(form) {
                    setTimeout(function() {
                        initForms(form);
                        $('input:visible, textarea', form).first().focus();
                    }, 150);
                })(this);
            });
        },
        modalLoad = function(url, cls) {
            var modal = $('div.reveal-modal');
            if (!modal.length) {
                /* create div for holding AJAX-loaded modals, once */
                modal = $('<div>').addClass('reveal-modal').appendTo('body');
                modal.on('close', function(event) {
                    if (event.target != this) {
                        // another element triggered the hide event. Ignore it.
                        return true;
                    }

                    // if the modal is locked (i.e. uploading/submission in progress)
                    if (window.modalLoad.locked) {
                        if (!confirm(gettext('You have unsaved changes. Do you really want to throw them away?'))) {
                            return false;
                        }
                    }

                    // unlock the modal
                    window.modalLoad.locked = false;
                    $('#logo').focus().blur();
                });
            }

            modal.removeClass().addClass('reveal-modal');
            if (cls)
                modal.addClass(cls);

            modal.empty().load(url, function() {
                var $m = $(this),
                    cls = $m.find('[data-reveal-class]').data('reveal-class');
                if (cls)
                    $m.addClass(cls);
                initModal.call(this);
                $m.foundation('reveal', 'open');
            });
        };

    $(document.body).on('click', 'a[data-toggle="ajaxmodal"]', function(e) {
        e.preventDefault();
        modalLoad(this.href, $(this).data('reveal-class'));
    });

    // prevent navigating away without saving:
    $(window).on('beforeunload', function() {
        if (window.modalLoad.locked) {
          return gettext('You have unsaved changes. Do you really want to throw them away?')
        };
    });

    /* inject function into the global namespace */
    if (!window.modalLoad) window.modalLoad = modalLoad;
})(jQuery);

/* jQuery / Django CSRF handling
Thanks, https://docs.djangoproject.com/en/dev/ref/contrib/csrf/#ajax */
jQuery(document).ajaxSend(function(event, xhr, settings) {
    function getCookie(name) {
        var cookieValue = null;
        if (document.cookie && document.cookie != '') {
            var cookies = document.cookie.split(';');
            for (var i = 0; i < cookies.length; i++) {
                var cookie = jQuery.trim(cookies[i]);
                // Does this cookie string begin with the name we want?
                if (cookie.substring(0, name.length + 1) == (name + '=')) {
                    cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                    break;
                }
            }
        }
        return cookieValue;
    }
    function sameOrigin(url) {
        // url could be relative or scheme relative or absolute
        var host = document.location.host; // host + port
        var protocol = document.location.protocol;
        var sr_origin = '//' + host;
        var origin = protocol + sr_origin;
        // Allow absolute or scheme relative URLs to same origin
        return (url == origin || url.slice(0, origin.length + 1) == origin + '/') ||
            (url == sr_origin || url.slice(0, sr_origin.length + 1) == sr_origin + '/') ||
            // or any other URL that isn't scheme relative or absolute i.e relative.
            !(/^(\/\/|http:|https:).*/.test(url));
    }
    function safeMethod(method) {
        return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
    }

    if (!safeMethod(settings.type) && sameOrigin(settings.url)) {
        xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
    }
});
<commit_msg>Fix pickadate hack<commit_after>;
/* main initialization routine */
$.fn.towelFoundation = function() {
    /* onReady */
    $(function() {
        var onReady = window.onReady || [];
        for (var i=0, l=onReady.length; i<l; i++) onReady[i].apply(null, [$]);
    });

    return this;
};

/* various plugins */
$.fn.flash = function() {
    return this.each(function() {
        var $this = $(this),
            opacity = $this.css('opacity');

        $this.css('opacity', 0.3).animate({opacity: opacity});
    });
};

$.fn.autogrow = function() {
    return this.not('.hasAutogrow').addClass('hasAutogrow').elastic();
};

/* gettext dummy
* if you need internationalizations, read here how to activate:
* https://docs.djangoproject.com/en/dev/topics/i18n/translation/#internationalization-in-javascript-code
* */
if (window.gettext === undefined) {
    window.gettext = function(msgid) {
        return msgid
    }
}

/* init forms */
(function($) {
    if (!window.onForm) window.onForm = [];

    var onForm = window.onForm,
        initForms = function(elem) {
            var elem = $(elem || document);
            for (var i=0, len=onForm.length; i<len; ++i)
                onForm[i].apply(null, [elem, $]);
        };

    onForm.push(function(elem, $) {
        if ($.fn.chosen)
            elem.find('select').not('.plain').chosen();
        if ($.fn.pickadate) {
            elem.find('.type-date').each(function() {
                var self = $(this),
                    input = self.find('input.dateinput');

                input.pickadate({
                    format: self.data('date-format')
                    , formatSubmit: self.data('date-format')
                    , selectYears: true
                    , selectMonths: true
                    , data: true
                });

                // https://github.com/amsul/pickadate.js/issues/128
                // uhm...
                var p = input.data('pickadate');
                if (p && p.get())
                    p.set('select', p.get(), {
                        format: self.data('date-format'), data: true});
            });
        }

        elem.find('textarea.autogrow, .autogrow textarea').autogrow();
    });

    onReady.push(function() { initForms(); });

    /* inject function into the global namespace */
    if (!window.initForms) window.initForms = initForms;

    $(document.body).on('updateLive', function(event, elem) {
        event.stopPropagation();
        elem.flash();
        initForms(elem);
    });
})(jQuery);

/* ajax modals */
(function($) {
    var initModal = function() {
            var modal = this,
                $elem = $(this);

            $elem.find('form').each(function() {
                var $form = $(this),
                    handleResponse = function(data) {
                        window.modalLoad.locked = false;

                        if (typeof(data) == 'string') {
                            $elem.html(data);
                            initModal.call($elem.get(0));
                        } else {
                            updateLive(data);
                            if (!('!keep' in data))
                                $elem.foundation('reveal', 'close');
                        }
                    }

                // set modal to locked: navigating away will be prevented
                // and also closing the modal will prompt the user
                $form.filter('[method="post"]').on('change', function(event) {
                    window.modalLoad.locked = true;
                });

                $form.on('submit', function() {
                    if (this.method.toLowerCase() == 'post') {
                        if ($.fn.ajaxSubmit) {
                            // jquery.form.js is available, XHR file uploads will
                            // work too
                            var $bar = $elem.find('.progress-bar');

                            $(this).ajaxSubmit({
                                uploadProgress: function(evt, pos, total, percComplete) {
                                    $bar.width(percComplete + '%');
                                },
                                beforeSubmit: function() {
                                    $bar.width('0%');
                                },
                                success: handleResponse
                            });
                        } else {
                            $.post(this.action, $form.serialize(), handleResponse);
                        }
                    } else {
                        $.get(this.action, $form.serialize(), handleResponse);
                    }
                    return false;
                });

                // focus the first form element
                (function(form) {
                    setTimeout(function() {
                        initForms(form);
                        $('input:visible, textarea', form).first().focus();
                    }, 150);
                })(this);
            });
        },
        modalLoad = function(url, cls) {
            var modal = $('div.reveal-modal');
            if (!modal.length) {
                /* create div for holding AJAX-loaded modals, once */
                modal = $('<div>').addClass('reveal-modal').appendTo('body');
                modal.on('close', function(event) {
                    if (event.target != this) {
                        // another element triggered the hide event. Ignore it.
                        return true;
                    }

                    // if the modal is locked (i.e. uploading/submission in progress)
                    if (window.modalLoad.locked) {
                        if (!confirm(gettext('You have unsaved changes. Do you really want to throw them away?'))) {
                            return false;
                        }
                    }

                    // unlock the modal
                    window.modalLoad.locked = false;
                    $('#logo').focus().blur();
                });
            }

            modal.removeClass().addClass('reveal-modal');
            if (cls)
                modal.addClass(cls);

            modal.empty().load(url, function() {
                var $m = $(this),
                    cls = $m.find('[data-reveal-class]').data('reveal-class');
                if (cls)
                    $m.addClass(cls);
                initModal.call(this);
                $m.foundation('reveal', 'open');
            });
        };

    $(document.body).on('click', 'a[data-toggle="ajaxmodal"]', function(e) {
        e.preventDefault();
        modalLoad(this.href, $(this).data('reveal-class'));
    });

    // prevent navigating away without saving:
    $(window).on('beforeunload', function() {
        if (window.modalLoad.locked) {
          return gettext('You have unsaved changes. Do you really want to throw them away?')
        };
    });

    /* inject function into the global namespace */
    if (!window.modalLoad) window.modalLoad = modalLoad;
})(jQuery);

/* jQuery / Django CSRF handling
Thanks, https://docs.djangoproject.com/en/dev/ref/contrib/csrf/#ajax */
jQuery(document).ajaxSend(function(event, xhr, settings) {
    function getCookie(name) {
        var cookieValue = null;
        if (document.cookie && document.cookie != '') {
            var cookies = document.cookie.split(';');
            for (var i = 0; i < cookies.length; i++) {
                var cookie = jQuery.trim(cookies[i]);
                // Does this cookie string begin with the name we want?
                if (cookie.substring(0, name.length + 1) == (name + '=')) {
                    cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                    break;
                }
            }
        }
        return cookieValue;
    }
    function sameOrigin(url) {
        // url could be relative or scheme relative or absolute
        var host = document.location.host; // host + port
        var protocol = document.location.protocol;
        var sr_origin = '//' + host;
        var origin = protocol + sr_origin;
        // Allow absolute or scheme relative URLs to same origin
        return (url == origin || url.slice(0, origin.length + 1) == origin + '/') ||
            (url == sr_origin || url.slice(0, sr_origin.length + 1) == sr_origin + '/') ||
            // or any other URL that isn't scheme relative or absolute i.e relative.
            !(/^(\/\/|http:|https:).*/.test(url));
    }
    function safeMethod(method) {
        return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
    }

    if (!safeMethod(settings.type) && sameOrigin(settings.url)) {
        xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
    }
});
<|endoftext|>


<commit_before>//
//   Copyright 2009-2015 Ilkka Oksanen <iao@iki.fi>
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing,
//   software distributed under the License is distributed on an "AS
//   IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
//   express or implied.  See the License for the specific language
//   governing permissions and limitations under the License.
//

import { autorun } from 'mobx';
import Component from '@ember/component';
import EmberObject from '@ember/object';

let previousEditedMessage = null;

export default Component.extend({
  classNames: ['message-list'],

  editing: false,
  editBody: null,

  init(args) {
    this._super(args);

    const message = this.message;

    this.disposers = [
      autorun(() => this.set('gid', message.gid)),
      autorun(() => this.set('body', message.body)),
      autorun(() => this.set('cat', message.cat)),
      autorun(() => this.set('ts', message.ts)),
      autorun(() => this.set('userId', message.userId)),
      autorun(() => this.set('status', message.status)),
      autorun(() => this.set('updatedTs', message.updatedTs)),
      autorun(() => this.set('hideImages', message.hideImages)),
      autorun(() => this.set('editing', message.editing)),
      autorun(() => this.set('ircMotd', message.ircMotd)),
      autorun(() => this.set('edited', message.edited)),
      autorun(() => this.set('editing', message.editing)),
      autorun(() => this.set('deleted', message.deleted)),
      autorun(() => this.set('updatedTime', message.updatedTime)),
      autorun(() => this.set('updatedDate', message.updatedDate)),
      autorun(() => this.set('updatedDateLong', message.updatedDateLong)),
      autorun(() => this.set('nick', message.nick)),
      autorun(() => this.set('avatarUrl', message.avatarUrl)),
      autorun(() => this.set('decoratedCat', message.decoratedCat)),
      autorun(() => this.set('decoratedTs', message.decoratedTs)),
      autorun(() => this.set('channelAction', message.channelAction)),
      autorun(() => this.set('myNotDeletedMessage', message.myNotDeletedMessage)),
      autorun(() => this.set('bodyParts', message.bodyParts)),
      autorun(() => this.set('text', message.text)),
      autorun(() => this.set('images', message.images.map(image => EmberObject.create(image)))),
      autorun(() => this.set('hasMedia', message.hasMedia)),
      autorun(() => this.set('hasImages', message.hasImages)),
      autorun(() => this.set('hasYoutubeVideo', message.hasYoutubeVideo)),
      autorun(() => this.set('videoId', message.videoId)),
      autorun(() => this.set('videoParams', message.videoParams))
    ];
  },

  didDestroyElement() {
    this.disposers.forEach(element => element());
  },

  actions: {
    toggleImages() {
      this.toggleProperty('hideImages');
    },

    edit() {
      this._endEdit();

      this.set('editBody', this.body);
      this.set('editing', true);

      previousEditedMessage = this;
    },

    change() {
      this.sendAction('editMessage', gid, this.editBody);
      this._endEdit();
    },

    cancel() {
      this._endEdit();
    },

    delete() {
      this.sendAction('deleteMessage', this.gid);
      this._endEdit();
    }
  },

  _endEdit() {
    if (previousEditedMessage) {
      previousEditedMessage.set('editing', false);
      previousEditedMessage = null;
    }
  }
});
<commit_msg>Fix message editing<commit_after>//
//   Copyright 2009-2015 Ilkka Oksanen <iao@iki.fi>
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing,
//   software distributed under the License is distributed on an "AS
//   IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
//   express or implied.  See the License for the specific language
//   governing permissions and limitations under the License.
//

import { autorun } from 'mobx';
import Component from '@ember/component';
import EmberObject from '@ember/object';

let previousEditedMessage = null;

export default Component.extend({
  classNames: ['message-list'],

  editing: false,
  editBody: null,

  init(args) {
    this._super(args);

    const message = this.message;

    this.disposers = [
      autorun(() => this.set('gid', message.gid)),
      autorun(() => this.set('body', message.body)),
      autorun(() => this.set('cat', message.cat)),
      autorun(() => this.set('ts', message.ts)),
      autorun(() => this.set('userId', message.userId)),
      autorun(() => this.set('status', message.status)),
      autorun(() => this.set('updatedTs', message.updatedTs)),
      autorun(() => this.set('hideImages', message.hideImages)),
      autorun(() => this.set('editing', message.editing)),
      autorun(() => this.set('ircMotd', message.ircMotd)),
      autorun(() => this.set('edited', message.edited)),
      autorun(() => this.set('editing', message.editing)),
      autorun(() => this.set('deleted', message.deleted)),
      autorun(() => this.set('updatedTime', message.updatedTime)),
      autorun(() => this.set('updatedDate', message.updatedDate)),
      autorun(() => this.set('updatedDateLong', message.updatedDateLong)),
      autorun(() => this.set('nick', message.nick)),
      autorun(() => this.set('avatarUrl', message.avatarUrl)),
      autorun(() => this.set('decoratedCat', message.decoratedCat)),
      autorun(() => this.set('decoratedTs', message.decoratedTs)),
      autorun(() => this.set('channelAction', message.channelAction)),
      autorun(() => this.set('myNotDeletedMessage', message.myNotDeletedMessage)),
      autorun(() => this.set('bodyParts', message.bodyParts)),
      autorun(() => this.set('text', message.text)),
      autorun(() => this.set('images', message.images.map(image => EmberObject.create(image)))),
      autorun(() => this.set('hasMedia', message.hasMedia)),
      autorun(() => this.set('hasImages', message.hasImages)),
      autorun(() => this.set('hasYoutubeVideo', message.hasYoutubeVideo)),
      autorun(() => this.set('videoId', message.videoId)),
      autorun(() => this.set('videoParams', message.videoParams))
    ];
  },

  didDestroyElement() {
    this.disposers.forEach(element => element());
  },

  actions: {
    toggleImages() {
      this.toggleProperty('hideImages');
    },

    edit() {
      this._endEdit();

      this.set('editBody', this.body);
      this.set('editing', true);

      previousEditedMessage = this;
    },

    change() {
      this.sendAction('editMessage', this.gid, this.editBody);
      this._endEdit();
    },

    cancel() {
      this._endEdit();
    },

    delete() {
      this.sendAction('deleteMessage', this.gid);
      this._endEdit();
    }
  },

  _endEdit() {
    if (previousEditedMessage) {
      previousEditedMessage.set('editing', false);
      previousEditedMessage = null;
    }
  }
});
<|endoftext|>


<commit_before>'use strict'

export function createInputElement (name, value) {
  const input = document.createElement('input')
  // using replace so I can use one string for the label and the ID
  input.setAttribute('id', name.replace(/\s/g, '') + 'Input')
  input.setAttribute('value', value)
  const label = document.createElement('label')
  label.innerHTML = name[0].toUpperCase() + name.substr(1) + ' Length'
  label.setAttribute('for', name.replace(/\s/g, '') + 'Input')
  label.appendChild(input)

  document.body.appendChild(label)
}

export function createSettingsView () {
  createInputElement('pomodoro', '25')
  createInputElement('short Break', '5')
  createInputElement('long Break', '15')
}

/* Placeholder variables for input from input elements */
export const userInputs = {
  pomodoroLength: 0.1,
  shortBreakLength: 0.2,
  longBreakLength: 0.3
}
/* end of placeholder variables */
<commit_msg>removed input placeholder variables as they are no longer needed (woohoo!)<commit_after>'use strict'

export function createInputElement (name, value) {
  const input = document.createElement('input')
  // using replace so I can use one string for the label and the ID
  input.setAttribute('id', name.replace(/\s/g, '') + 'Input')
  input.setAttribute('value', value)
  const label = document.createElement('label')
  label.innerHTML = name[0].toUpperCase() + name.substr(1) + ' Length'
  label.setAttribute('for', name.replace(/\s/g, '') + 'Input')
  label.appendChild(input)

  document.body.appendChild(label)
}

export function createSettingsView () {
  createInputElement('pomodoro', '25')
  createInputElement('short Break', '5')
  createInputElement('long Break', '15')
}
<|endoftext|>


<commit_before>import React, { Component, PropTypes } from 'react';

class Interpolate extends Component {

  constructor(props, context) {
    super(props, context);
    this.i18n = context.i18n;
    this.t = context.t;
  }

  render() {
    const parent = this.props.parent || 'span';
    const REGEXP = this.props.regexp || this.i18n.services.interpolator.regexp;

    let tOpts = {...{}, ...this.props.options, ...{interpolation: { prefix: '#$?', suffix: '?$#'}}}
    let format = this.t(this.props.i18nKey, tOpts);

    if (!format || typeof format !== 'string') return React.createElement('noscript', null);;

    let children = [];

    format.split(REGEXP).reduce((memo, match, index) => {
      var child;

      if (index % 2 === 0) {
        if (match.length === 0)  return memo;
        child = match;
      } else {
        child = this.props[match];
      }

      memo.push(child);
      return memo;
    }, children);

    return React.createElement.apply(this, [parent, this.props].concat(children));
  }
}

Interpolate.contextTypes = {
  i18n: PropTypes.object.isRequired,
  t: PropTypes.func.isRequired
};

export default Interpolate;
<commit_msg>Remove extra semicolon<commit_after>import React, { Component, PropTypes } from 'react';

class Interpolate extends Component {

  constructor(props, context) {
    super(props, context);
    this.i18n = context.i18n;
    this.t = context.t;
  }

  render() {
    const parent = this.props.parent || 'span';
    const REGEXP = this.props.regexp || this.i18n.services.interpolator.regexp;

    let tOpts = {...{}, ...this.props.options, ...{interpolation: { prefix: '#$?', suffix: '?$#'}}}
    let format = this.t(this.props.i18nKey, tOpts);

    if (!format || typeof format !== 'string') return React.createElement('noscript', null);

    let children = [];

    format.split(REGEXP).reduce((memo, match, index) => {
      var child;

      if (index % 2 === 0) {
        if (match.length === 0)  return memo;
        child = match;
      } else {
        child = this.props[match];
      }

      memo.push(child);
      return memo;
    }, children);

    return React.createElement.apply(this, [parent, this.props].concat(children));
  }
}

Interpolate.contextTypes = {
  i18n: PropTypes.object.isRequired,
  t: PropTypes.func.isRequired
};

export default Interpolate;
<|endoftext|>


<commit_before>function waitForTemplates() {
  if (typeof JST !== "undefined") {
    left = Object.keys(JST);

    while (left.length > 0) {
      left.forEach(function(key, idx) {
        try {
          JST[key]({}, function(out, err) {});
          left.splice(idx, 1);
        } catch (err) {
          console.log('failed', key, idx);
          left.splice(idx, 1);
        }
      });
    }

  } else {
    setTimeout(function() {
      waitForTemplates();
    }, 250);
  }
}

waitForTemplates();
<commit_msg>Remove unneccesary template loader<commit_after><|endoftext|>


<commit_before>//http://www.rgraph.net/blog/2013/february/an-example-of-the-html5-canvas-ispointinpath-function.html
// Begin jController Kernel
// create closure
(function($) {

	'use strict';

	// Defining request/cancel animation frame
	// shim layer with setTimeout fallback
	window.requestAnimFrame = (function () {
		return window.requestAnimationFrame ||
		window.webkitRequestAnimationFrame  ||
		window.mozRequestAnimationFrame     ||
		window.oRequestAnimationFrame       ||
		window.msRequestAnimationFrame      ||
		function (callback) {
			window.setTimeout(callback, 1000 / 60);
		};
	})();

	// jController object
	$.jController = {};

	// Private Canvas jQuery object
	var _$canvas;

	// Private Canvas
	var _canvas;

	// Private Canvas context
	var _context;

	// Default value of clearing canvas
	var _isClearCanvas = true;

	// Index of objets
	var _internal = {};

	// Private jController plugins list
	var _plugins = {};

	// Ephemeral plugins (nested plugin calls)
	var _ephemeral = {};

	// Private jController helpers list
	var _helpers = {};

	// Private jController listeners list
	var _listeners = {};

	// Plugins events list (triggerable)
	var _onEvent = {};

	// jController events
	var _kernelEvents = {};

	// jQuery jController function definition
	$.fn.jController = function (attr) {

		// Init jController canvas
		jController.init(this, attr);
		requestAnimFrame(animate);

		return this;
	}

	function animate() {
		if (_isClearCanvas)	{
			jController.clearCanvas();
		}

	    // Recusively render everything
	    jController.renderAll();
	    jController.cleanAll();

	    requestAnimFrame(animate);
	}

	// Create state "object" for plugin
	var state = function(attr, pluginName, index) {

		this.id = index;
		this.attr = attr;
		this.isRender = false;

		// Set internal values
		this.setInternal = function(data) {

			var _data = ($.isPlainObject(_internal[pluginName+index]))
				? _internal[pluginName+index]
				: {};

			_internal[pluginName+index] = $.extend(true, {}, _data, data);
		}

		// Retrieve internal value
		this.getInternal = function(key) {
			return ($.isPlainObject(_internal[pluginName+index]))
				? _internal[pluginName+index][key]
				: undefined;
		}

		// Retrieve internal values (all)
		this.getInternals = function() {
			return _internal[pluginName+index];
		}

		/* Idea:
		// Retrieve object path (useful for events detection)
		getPath : function() {
			return self.path; // = function(params)
		}
		*/

		// Render another plugin (plugin name, params)
		this.render = function(pluginName, attr) {
			if (! $.isPlainObject(_ephemeral[pluginName])) {
				_ephemeral[pluginName] = {
					instances : [],
				};
			}

			var index  = _ephemeral[pluginName].instances.length;
			var _state = new state(
				$.jController.getPlugin(pluginName).construct(attr),
				pluginName,
				index
			);

			_ephemeral[pluginName].instances.push(_state);

			return _state;
		}

		// Remove this instance
		this.remove = function () {

			_plugins[pluginName].instances[index] = undefined;

			if ($.isPlainObject(_onEvent[pluginName]))
			{
				// Remove all onEvent for this instance
				$.each(_onEvent[pluginName][index],function(listenerName, fn) {
					$.jController
						.getListener(listenerName)
						.off(_onEvent[pluginName][index][listenerName]);
				});

			}

		}

		// Trigger
		this.trigger = function (eventName, data) {

			var callback = state[eventName];

			if ($.jController.isEvent(pluginName, eventName) &&
				$.isFunction(callback)) {

				// Callback for event
				var callbackEvent = $.jController
					.getPlugin(pluginName)
					.events[eventName].fn;

				callbackEvent(this, callback, data);
			}
		}

		// Get parent (plugin "class")
		this.parent = function () {
			return _plugins[pluginName];
		}

	};

	// jController
	var jController = {
		// Creates canvas for jController
		init : function($obj, attr) {
			// Unique Canvas id
			var id = 'jController_' + $('canvas').length;

			// Canvas jQuery object
			_$canvas = $('<canvas>')
				.attr(attr.attr)
				.attr({id: id})
				.appendTo($obj);

			// Canvas
			_canvas = _$canvas[0];

			// Context of canvas
			_context = _canvas.getContext("2d");

			// Save kernel events
			$.each(attr.events,function(eventName,callback) {
				_kernelEvents[eventName] = callback;
			})

		},

		// Retrieve All events from instances and listen
		listenEvents : function(state, pluginName) {

			$.each(state.attr, function(key, value) {
				// Looking for events on state
				if ($.jController.isEvent(pluginName, key) &&
					$.isFunction(value)) {

					// Key is an EventName
					var eventName = key;
					// Value is a callback
					var evtCallback = value;

					// Listener Name
					var listenerName = $.jController
						.getPlugin(pluginName)
						.events[eventName].listener;

					// Callback for event
					var callbackEvent = $.jController
						.getPlugin(pluginName)
						.events[eventName].fn;

					if (listenerName != undefined) {

						if (!$.isPlainObject(_onEvent[pluginName])) {
							_onEvent[pluginName] = {};
						}

						if (!$.isPlainObject(_onEvent[pluginName][state.id])) {
							_onEvent[pluginName][state.id] = {};
						}

						// Don't change this, save the execute event function
						_onEvent[pluginName][state.id][listenerName] = function(e) {
							callbackEvent(state, evtCallback, e);
						};

						if ($.jController.isListener(listenerName)) {
							// Don't change this, start listening
							$.jController
								.getListener(listenerName)
								.on(_onEvent[pluginName][state.id][listenerName]);
						} else {
							throw "jController error: can't find <"+listenerName+"> listener";
						}

					}
				}
			});

		},

		// Set every plugins as to be rendered on next frame
		cleanAll : function() {

			// For each declared plugin
			_ephemeral = {};
		},

		// Clear canvas
		clearCanvas : function() {
			$.jController
				.getContext()
				.clearRect(0, 0,
					$.jController.getCanvas().width,
					$.jController.getCanvas().height);
		},

		// Render all plugins
		renderAll : function() {

			// For each declared plugin
			$.each(_plugins, function(pluginName, plugin) {

				// Construct and render each one
				$.each(plugin.instances, function(index, state) {

					if (state != undefined)
					{
						if (! state.isRender)
						{
							// Retrieve all events
							jController.listenEvents(state, pluginName);
							state.isRender = true;
						}

						// Render plugin
						plugin.render(state);
					}

				})
			})

			jController.renderEphemeral();
		},

		// Render Ephemeral plugins
		renderEphemeral : function () {

			var _exit = false;
			// For each declared plugin
			$.each(_ephemeral, function(pluginName, plugin) {

				_exit = true;
				// Construct and render each one
				$.each(plugin.instances, function(index, state) {

					if (state != undefined) {
						if (! state.isRender) {
							_exit = false;
							// Retrieve all events
							jController.listenEvents(state, pluginName);
							state.isRender = true;
						}

						// Render plugin
						$.jController.getPlugin(pluginName).render(state);
					}

				})
			})

			if (! _exit) {
				// Recursive call (for intricate plugins)
				jController.renderEphemeral();
			}
		}
	}

	// Import Js files
	$.jController.import =  function(links, callback) {
 		// Recursively import files and callback()
 		(function importRecursive(list, callback){
 			if (list.length == 0) {
 				callback();
 			} else {
	 			$.getScript(list[0], function() {
	 				importRecursive(list.slice(1), callback);
	 			}).fail(function(jqxhr, settings, exception){
	 				throw "jController error: on import, " + exception;
	 			})
 			}
 		}($.makeArray(links), callback));
	}

	$.jController.getCanvasObject = function() {
		return _$canvas;
	}

	$.jController.getCanvas = function() {
		return _canvas;
	}

	$.jController.getContext = function() {
		return _context;
	}

	$.jController.clearCanvas = function(flag) {
		_isClearCanvas = flag;
	}

	/* -- Trigger -- */

	$.jController.trigger = function(eventName,data) {

		var callback = _kernelEvents[eventName];

		if ($.isFunction(callback)) {
			// Execute callback using data
			callback(data);
		}
	}

	/* -- Listeners config -- */

	// Retrieve all listeners
	$.jController.getListeners = function() {
		return _listeners;
	}

	// Retrieve listener by name
	$.jController.getListener = function(name) {
		// return the listener if exists otherwise undefined
		return _listeners[name];
	}

	// Check wether a listener exists or nor
	$.jController.isListener = function(name) {
		return ($.isPlainObject(_listeners[name]) &&
				$.isFunction(_listeners[name].on) &&
				$.isFunction(_listeners[name].off));
	}

	// Register a listener
	$.jController.registerListener = function(listener) {
		// Check wether the name has been set
		if (listener.name) {
			// Register listener functions
			_listeners[listener.name] = {
				on  : listener.on,
				off : listener.off,
			}
		}
	}

	/* -- Helpers config -- */

	// Retrieve all helpers
	$.jController.getHelpers = function() {
		return _helpers;
	}

	// Retrieve helper by name
	$.jController.getHelper = function(name) {
		// return existing helper (undefined otherwise)
		return _helpers[name];
	}

	// Check wether a helper exists or nor
	$.jController.isHelper = function(name) {
		return ($.isFunction(_helpers[name]));
	}

	// Register a helper
	$.jController.registerHelper = function(helper) {
		// Check wether the name has been set
		if (helper.name) {
			// Register helper function
			_helpers[helper.name] = helper.fn;
		}
	}

	/* -- Events config -- */

	// Retrieve all events of PluginName
	$.jController.getEvents = function(pluginName) {
		return ($.jController.isPlugin(pluginName) &&
			$.isPlainObject($.jController.getPlugin(pluginName).events))
			? $.jController.getPlugin(pluginName).events
			: null;
	}

	// Retrieve a specific pluginName event
	$.jController.getEvent = function(pluginName, eventName) {
		// return existing event (null otherwise)
		return ($.jController.isEvent(pluginName, eventName))
			? _plugins[pluginName].events[eventName]
			: null;
	}

	// Check pluginName event existence
	$.jController.isEvent = function(pluginName, eventName) {
		return ($.jController.isPlugin(pluginName) &&
			$.isPlainObject(_plugins[pluginName].events) &&
			$.isPlainObject(_plugins[pluginName].events[eventName]) &&
			$.isFunction(_plugins[pluginName].events[eventName].fn))
	}

	/* -- Plugins config  -- */

	// Retrieve all plugins
	$.jController.getPlugins = function() {
		return _plugins;
	}

	// Retrieve plugin by name
	$.jController.getPlugin = function(name) {
		// return the plugin if exists otherwise undefined
		return _plugins[name];
	}

	// Check wether a Plugin exists or nor
	$.jController.isPlugin = function(name) {
		return ($.isPlainObject(_plugins[name]));
	}

	// Register Plugin
	$.jController.registerPlugin = function(plugin) {

		var pName = plugin.name;

		// Check wether the name has been set
		if (! pName) {
			throw "jController error: can't register plugin without name !";
		}

		var _config = {
			instances  : [],          			// With instances (list)
			getEvent : function(eventName) {
				// Get eventName
				return $.jController.getEvent(pName, eventName);
			},
			isEvent : function(eventName) {
				// Get eventName
				return $.jController.isEvent(pName, eventName);
			}

		}

		// Create new object of plugin
		_plugins[pName] = $.extend(true, {}, _config, plugin);

		// Add plugin function
		// Ex : $.jController.arc({[...]}) adds an arc into the controller
		$.jController[pName] = function(attr) {

			var index = _plugins[pName].instances.length;
			var _state = new state(plugin.construct(attr),pName,index);
			_plugins[pName].instances.push (_state);

			return _state;
		}

	}

})(jQuery); // jController Kernel end
<commit_msg>cosmetics<commit_after>//http://www.rgraph.net/blog/2013/february/an-example-of-the-html5-canvas-ispointinpath-function.html
// Begin jController Kernel
// create closure
(function($) {

	'use strict';

	// Defining request/cancel animation frame
	// shim layer with setTimeout fallback
	window.requestAnimFrame = (function () {
		return window.requestAnimationFrame ||
		window.webkitRequestAnimationFrame  ||
		window.mozRequestAnimationFrame     ||
		window.oRequestAnimationFrame       ||
		window.msRequestAnimationFrame      ||
		function (callback) {
			window.setTimeout(callback, 1000 / 60);
		};
	})();

	// jController object
	$.jController = {};

	// Private Canvas jQuery object
	var _$canvas;

	// Private Canvas
	var _canvas;

	// Private Canvas context
	var _context;

	// Default value of clearing canvas
	var _isClearCanvas = true;

	// Index of objets
	var _internal = {};

	// Private jController plugins list
	var _plugins = {};

	// Ephemeral plugins (nested plugin calls)
	var _ephemeral = {};

	// Private jController helpers list
	var _helpers = {};

	// Private jController listeners list
	var _listeners = {};

	// Plugins events list (triggerable)
	var _onEvent = {};

	// jController events
	var _kernelEvents = {};

	// jQuery jController function definition
	$.fn.jController = function (attr) {

		// Init jController canvas
		jController.init(this, attr);
		requestAnimFrame(animate);

		return this;
	}

	function animate() {
		if (_isClearCanvas)	{
			jController.clearCanvas();
		}

	    // Recusively render everything
	    jController.renderAll();
	    jController.cleanAll();

	    requestAnimFrame(animate);
	}

	// Create state "object" for plugin
	var state = function(attr, pluginName, index) {

		this.id = index;
		this.attr = attr;
		this.isRender = false;

		// Set internal values
		this.setInternal = function(data) {

			var _data = ($.isPlainObject(_internal[pluginName+index]))
				? _internal[pluginName+index]
				: {};

			_internal[pluginName+index] = $.extend(true, {}, _data, data);
		}

		// Retrieve internal value
		this.getInternal = function(key) {
			return ($.isPlainObject(_internal[pluginName+index]))
				? _internal[pluginName+index][key]
				: undefined;
		}

		// Retrieve internal values (all)
		this.getInternals = function() {
			return _internal[pluginName+index];
		}

		/* Idea:
		// Retrieve object path (useful for events detection)
		getPath : function() {
			return self.path; // = function(params)
		}
		*/

		// Render another plugin (plugin name, params)
		this.render = function(pluginName, attr) {
			if (! $.isPlainObject(_ephemeral[pluginName])) {
				_ephemeral[pluginName] = {
					instances : [],
				};
			}

			var index  = _ephemeral[pluginName].instances.length;
			var _state = new state(
				$.jController.getPlugin(pluginName).construct(attr),
				pluginName,
				index
			);

			_ephemeral[pluginName].instances.push(_state);

			return _state;
		}

		// Remove this instance
		this.remove = function () {

			_plugins[pluginName].instances[index] = undefined;

			if ($.isPlainObject(_onEvent[pluginName]))
			{
				// Remove all onEvent for this instance
				$.each(_onEvent[pluginName][index],function(listenerName, fn) {
					$.jController
						.getListener(listenerName)
						.off(_onEvent[pluginName][index][listenerName]);
				});

			}

		}

		// Trigger
		this.trigger = function (eventName, data) {

			var callback = state[eventName];

			if ($.jController.isEvent(pluginName, eventName) &&
				$.isFunction(callback)) {

				// Callback for event
				var callbackEvent = $.jController
					.getPlugin(pluginName)
					.events[eventName].fn;

				callbackEvent(this, callback, data);
			}
		}

		// Get parent (plugin "class")
		this.parent = function () {
			return _plugins[pluginName];
		}

	};

	// jController
	var jController = {
		// Creates canvas for jController
		init : function($obj, attr) {
			// Unique Canvas id
			var id = 'jController_' + $('canvas').length;

			// Canvas jQuery object
			_$canvas = $('<canvas>')
				.attr(attr.attr)
				.attr({id: id})
				.appendTo($obj);

			// Canvas
			_canvas = _$canvas[0];

			// Context of canvas
			_context = _canvas.getContext("2d");

			// Save kernel events
			$.each(attr.events, function(eventName, callback) {
				_kernelEvents[eventName] = callback;
			})

		},

		// Retrieve All events from instances and listen
		listenEvents : function(state, pluginName) {

			$.each(state.attr, function(key, value) {
				// Looking for events on state
				if ($.jController.isEvent(pluginName, key) &&
					$.isFunction(value)) {

					// Key is an EventName
					var eventName = key;
					// Value is a callback
					var evtCallback = value;

					// Listener Name
					var listenerName = $.jController
						.getPlugin(pluginName)
						.events[eventName].listener;

					// Callback for event
					var callbackEvent = $.jController
						.getPlugin(pluginName)
						.events[eventName].fn;

					if (listenerName != undefined) {

						if (!$.isPlainObject(_onEvent[pluginName])) {
							_onEvent[pluginName] = {};
						}

						if (!$.isPlainObject(_onEvent[pluginName][state.id])) {
							_onEvent[pluginName][state.id] = {};
						}

						// Don't change this, save the execute event function
						_onEvent[pluginName][state.id][listenerName] = function(e) {
							callbackEvent(state, evtCallback, e);
						};

						if ($.jController.isListener(listenerName)) {
							// Don't change this, start listening
							$.jController
								.getListener(listenerName)
								.on(_onEvent[pluginName][state.id][listenerName]);
						} else {
							throw "jController error: can't find <"+listenerName+"> listener";
						}

					}
				}
			});

		},

		// Set every plugins as to be rendered on next frame
		cleanAll : function() {

			// For each declared plugin
			_ephemeral = {};
		},

		// Clear canvas
		clearCanvas : function() {
			$.jController
				.getContext()
				.clearRect(0, 0,
					$.jController.getCanvas().width,
					$.jController.getCanvas().height);
		},

		// Render all plugins
		renderAll : function() {

			// For each declared plugin
			$.each(_plugins, function(pluginName, plugin) {

				// Construct and render each one
				$.each(plugin.instances, function(index, state) {

					if (state != undefined)
					{
						if (! state.isRender)
						{
							// Retrieve all events
							jController.listenEvents(state, pluginName);
							state.isRender = true;
						}

						// Render plugin
						plugin.render(state);
					}

				})
			})

			jController.renderEphemeral();
		},

		// Render Ephemeral plugins
		renderEphemeral : function () {

			var _exit = false;
			// For each declared plugin
			$.each(_ephemeral, function(pluginName, plugin) {

				_exit = true;
				// Construct and render each one
				$.each(plugin.instances, function(index, state) {

					if (state != undefined) {
						if (! state.isRender) {
							_exit = false;
							// Retrieve all events
							jController.listenEvents(state, pluginName);
							state.isRender = true;
						}

						// Render plugin
						$.jController.getPlugin(pluginName).render(state);
					}

				})
			})

			if (! _exit) {
				// Recursive call (for intricate plugins)
				jController.renderEphemeral();
			}
		}
	}

	// Import Js files
	$.jController.import =  function(links, callback) {
 		// Recursively import files and callback()
 		(function importRecursive(list, callback) {
 			if (list.length == 0) {
 				callback();
 			} else {
	 			$.getScript(list[0], function() {
	 				importRecursive(list.slice(1), callback);
	 			}).fail(function(jqxhr, settings, exception) {
	 				throw "jController error: on import, " + exception;
	 			})
 			}
 		}($.makeArray(links), callback));
	}

	$.jController.getCanvasObject = function() {
		return _$canvas;
	}

	$.jController.getCanvas = function() {
		return _canvas;
	}

	$.jController.getContext = function() {
		return _context;
	}

	$.jController.clearCanvas = function(flag) {
		_isClearCanvas = flag;
	}

	/* -- Trigger -- */

	$.jController.trigger = function(eventName, data) {

		var callback = _kernelEvents[eventName];

		if ($.isFunction(callback)) {
			// Execute callback using data
			callback(data);
		}
	}

	/* -- Listeners config -- */

	// Retrieve all listeners
	$.jController.getListeners = function() {
		return _listeners;
	}

	// Retrieve listener by name
	$.jController.getListener = function(name) {
		// return the listener if exists otherwise undefined
		return _listeners[name];
	}

	// Check wether a listener exists or nor
	$.jController.isListener = function(name) {
		return ($.isPlainObject(_listeners[name]) &&
				$.isFunction(_listeners[name].on) &&
				$.isFunction(_listeners[name].off));
	}

	// Register a listener
	$.jController.registerListener = function(listener) {
		// Check wether the name has been set
		if (listener.name) {
			// Register listener functions
			_listeners[listener.name] = {
				on  : listener.on,
				off : listener.off,
			}
		}
	}

	/* -- Helpers config -- */

	// Retrieve all helpers
	$.jController.getHelpers = function() {
		return _helpers;
	}

	// Retrieve helper by name
	$.jController.getHelper = function(name) {
		// return existing helper (undefined otherwise)
		return _helpers[name];
	}

	// Check wether a helper exists or nor
	$.jController.isHelper = function(name) {
		return ($.isFunction(_helpers[name]));
	}

	// Register a helper
	$.jController.registerHelper = function(helper) {
		// Check wether the name has been set
		if (helper.name) {
			// Register helper function
			_helpers[helper.name] = helper.fn;
		}
	}

	/* -- Events config -- */

	// Retrieve all events of PluginName
	$.jController.getEvents = function(pluginName) {
		return ($.jController.isPlugin(pluginName) &&
			$.isPlainObject($.jController.getPlugin(pluginName).events))
			? $.jController.getPlugin(pluginName).events
			: null;
	}

	// Retrieve a specific pluginName event
	$.jController.getEvent = function(pluginName, eventName) {
		// return existing event (null otherwise)
		return ($.jController.isEvent(pluginName, eventName))
			? _plugins[pluginName].events[eventName]
			: null;
	}

	// Check pluginName event existence
	$.jController.isEvent = function(pluginName, eventName) {
		return ($.jController.isPlugin(pluginName) &&
			$.isPlainObject(_plugins[pluginName].events) &&
			$.isPlainObject(_plugins[pluginName].events[eventName]) &&
			$.isFunction(_plugins[pluginName].events[eventName].fn))
	}

	/* -- Plugins config  -- */

	// Retrieve all plugins
	$.jController.getPlugins = function() {
		return _plugins;
	}

	// Retrieve plugin by name
	$.jController.getPlugin = function(name) {
		// return the plugin if exists otherwise undefined
		return _plugins[name];
	}

	// Check wether a Plugin exists or nor
	$.jController.isPlugin = function(name) {
		return ($.isPlainObject(_plugins[name]));
	}

	// Register Plugin
	$.jController.registerPlugin = function(plugin) {

		var pName = plugin.name;

		// Check wether the name has been set
		if (! pName) {
			throw "jController error: can't register plugin without name !";
		}

		var defaults = {
			// With instances (list)
			instances  : [],
			getEvent : function(eventName) {
				// Get eventName
				return $.jController.getEvent(pName, eventName);
			},
			isEvent : function(eventName) {
				// Get eventName
				return $.jController.isEvent(pName, eventName);
			}
		}

		// Create new object of plugin
		_plugins[pName] = $.extend(true, {}, defaults, plugin);

		// Add plugin function
		// Ex : $.jController.arc({[...]}) adds an arc into the controller
		$.jController[pName] = function(attr) {

			var index = _plugins[pName].instances.length;
			var _state = new state(plugin.construct(attr),pName, index);
			_plugins[pName].instances.push (_state);

			return _state;
		}

	}

})(jQuery); // jController Kernel end
<|endoftext|>


<commit_before>var fs = require('fs'),
    Parser = require('jison').Parser,
    fsJson = require('jsonfile'),
    grammars = fs.readFileSync(__dirname + '/grammars.jison', 'utf8'),
    jKifParser = new Parser(grammars);

jKifParser.parseFile = function(filePath, cb) {
  fs.readFile(filePath, 'utf8', function(err, kif) {
    err ? cb(err) : cb(null, jKifParser.parse(kif));
  });
};

jKifParser.writeParsedToFile = function(parsed, filePath, encoding) {
  if (encoding === 'json' || !encoding) {
    fsJson.writeFile(filePath, parsed, function(err) {
      return err ? false : true;
    });
  }
};

module.exports = jKifParser;
<commit_msg>Add support for non json encoding #writeParsedToFile<commit_after>var fs = require('fs'),
    Parser = require('jison').Parser,
    fsJson = require('jsonfile'),
    grammars = fs.readFileSync(__dirname + '/grammars.jison', 'utf8'),
    jKifParser = new Parser(grammars);

jKifParser.parseFile = function(filePath, cb) {
  fs.readFile(filePath, 'utf8', function(err, kif) {
    err ? cb(err) : cb(null, jKifParser.parse(kif));
  });
};

jKifParser.writeParsedToFile = function(parsed, filePath, encoding) {
  if (encoding === 'json' || !encoding) {
    fsJson.writeFile(filePath, parsed, function(err) {
      return err ? false : true;
    });
  } else {
    fs.writeFile(filePath, parsed, { encoding: encoding }, function(err) {
      return err ? false : true;
    });
  }
};

module.exports = jKifParser;
<|endoftext|>