<commit_before>/**
 *
 * Backbone-DocumentModel v0.6.4
 *
 * Copyright (c) 2013 Michael Haselton & Aaron Herres, Loqwai LLC
 *
 * https://github.com/icereval/backbone-documentmodel
 * Licensed under the MIT License
 */
(function (factory) {
    if (typeof define === 'function' && define.amd) {
        // AMD
        define(['underscore', 'backbone'], factory);
    } else if (typeof exports !== 'undefined') {
        // CommonJS / Node.js
        module.exports = factory(require('underscore'), require('backbone'));
    } else {
        // globals
        factory(_, Backbone);
    }
}(function (_, Backbone) {
    // Can get overridden to determine the nested model class based on passed values.
    function documentModelGetNestedModel(nestedKey, value, options) {
        return new Backbone.DocumentModel(value, options);
    }

    // Can get overridden to determine the nested collection class based on passed values.
    function documentModelGetNestedCollection(nestedKey, value, options) {
        return new Backbone.DocumentCollection(value, options);
    }

    function documentCollectionGet(obj) {
        if (this.pseudoIdAttribute) {
            return this.findWhere({value: obj});
        }

        return Backbone.Collection.prototype.get.call(this, obj);
    }

    function documentModelGet(property) {
        if (!_.isString(property)) {
            return Backbone.Model.prototype.get.call(this, property);
        }

        var properties = _.isArray(property) ? property : property.split('.');
        var retVal = Backbone.Model.prototype.get.call(this, properties.shift());

        if (retVal === undefined) {
            return undefined;
        }

        _.each(properties, function (prop) {
            var parseIntProp;

            if (retVal !== undefined) {
                parseIntProp = parseInt(prop, 10);

                retVal = _.isFinite(parseIntProp) ? retVal.at(parseIntProp) : retVal.get(prop);

                // If the value is a 'pseudo' object go ahead and retrieve its 'value' attribute.
                if (retVal !== undefined && retVal.collection && retVal.collection.pseudoIdAttribute) {
                    retVal = retVal.get('value');
                }
            }
        }, this);

        return retVal;
    }

    function documentCollectionSet(models, options) {
        options || (options = {});

        // Model's within Collections do not store parent/name, this can be accessed
        // through the model's collection attribute.
        delete options.name;
        delete options.parent;

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

    function documentModelPrepare(attrs, options) {
        _.extend(options, _.pick(this.idAttribute ? this : _.isObject(attrs) ? attrs : this, ['idAttribute']));

        // If we are parsing an array or values we'll need to generate a pseudoIdAttribute.
        if (Object.prototype.toString.call(attrs) !== '[object Object]' || _.isArray(attrs)) {
            // #5 - Ensure we do not omit wrapped primitives.
            var value = attrs;

            this.pseudoIdAttribute = true;

            attrs = {};
            attrs[options.idAttribute] = _.uniqueId();
            attrs.value = value;
        }

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

    function documentModelSet(key, val, options) {
        var attrs,
            isBackboneObj,
            nestedAttrs = {},
            deepNamedAttrs = {};

        if (key == null) return this;

        // Handle both `"key", value` and `{key: value}` -style arguments.
        if (typeof key === 'object') {
            attrs = key;
            options = val;
        } else {
            (attrs = {})[key] = val;
        }

        options || (options = {});

        // If the object is already a Collection or Model assume its a Document object.
        isBackboneObj =  attrs instanceof Backbone.Collection || attrs instanceof Backbone.Model;

        if (!isBackboneObj) {
            _.each(_.keys(attrs), function (attrKey) {
                if (attrKey.indexOf('.') > 0) {
                    deepNamedAttrs[attrKey] = attrs[attrKey];
                    delete attrs[attrKey];
                } else if (Object.prototype.toString.call(attrs[attrKey]) === '[object Object]' || _.isArray(attrs[attrKey])) {
                    // #5 - Ensure we do not omit wrapped primitives.
                    nestedAttrs[attrKey] = attrs[attrKey];
                    delete attrs[attrKey];
                }
            });
        }

        if (!Backbone.Model.prototype.set.call(this, attrs, options)) return false;

        if (!isBackboneObj) {
            // Refactor Deep Named Attributes ( ex: { 'name.first': 'Joe' } ) into Objects/Arrays for nested attribute merge.
            _.each(_.keys(deepNamedAttrs), function (deepAttrKey) {
                var splitDeepAttrs = deepAttrKey.split('.'),
                    deepAttrName = splitDeepAttrs.pop(),
                    deepAttrHandled = false;

                var parentNestedAttr = nestedAttrs;

                for (var i = 0; i < splitDeepAttrs.length; i++) {
                    var splitDeepAttrKey = splitDeepAttrs[i],
                        childSplitDeepAttrKey = splitDeepAttrs[i + 1];

                    if (_.isFinite(childSplitDeepAttrKey)) {
                        var deepAttrParentName = _.reduce(splitDeepAttrs, function (memo, val) {
                                return memo + '.' + val;
                            }),
                            deepAttrParent = this.get.call(this, deepAttrParentName);

                        if (deepAttrParent) {
                            deepAttrParent.set(deepAttrName, deepNamedAttrs[deepAttrKey], options);
                        }

                        deepAttrHandled = true;

                        break;
                    } else {
                        if (!parentNestedAttr[splitDeepAttrKey]) {
                            parentNestedAttr[splitDeepAttrKey] = {};
                        }

                        parentNestedAttr = parentNestedAttr[splitDeepAttrKey];
                    }
                }

                if (!deepAttrHandled) {
                    parentNestedAttr[deepAttrName] = deepNamedAttrs[deepAttrKey];
                }
            }, this);

            // Handle Nested Attribute Creation - ex: { name: { first: 'Joe' } }
            _.each(_.keys(nestedAttrs), function (nestedAttrKey) {
                var nestedOptions;
                var nestedValue = nestedAttrs[nestedAttrKey];
                // If the attribute already exists, merge the objects.
                if (this.attributes[nestedAttrKey]) {
                    this.attributes[nestedAttrKey].set.call(this.attributes[nestedAttrKey], nestedValue, options);
                } else {
                    nestedOptions = { parent: this };
                    _.extend(nestedOptions, _.pick(this, ['idAttribute']));
                    nestedOptions.name = nestedAttrKey;

                    if (_.isArray(nestedValue)) {
                        // Collection
                        Backbone.Model.prototype.set.call(this, nestedAttrKey, this.getNestedCollection(nestedAttrKey, nestedValue, nestedOptions), options);
                    }  else {
                        // Model
                        if (this instanceof Backbone.DocumentModel) {
                            // Model -> Model
                            if (nestedValue instanceof Backbone.DocumentModel) {
                                if (!nestedValue.get(this.idAttribute)) {
                                    // If no id has was specified for the nested Model, use it's parent id.
                                    // This is required for patching updates and will be omitted on JSON build.
                                    nestedValue.set(this.idAttribute, this.get(this.idAttribute), {silent:true});
                                    nestedOptions.pseudoIdAttribute = true;
                                }
                                _.extend(nestedValue, nestedOptions);
                                Backbone.Model.prototype.set.call(this, nestedAttrKey, nestedValue, options);
                            } else if (!nestedValue[this.idAttribute]) {
                                // If no id has was specified for the nested Model, use it's parent id.
                                // This is required for patching updates and will be omitted on JSON build.
                                nestedValue[this.idAttribute] = this.get(this.idAttribute);
                                nestedOptions.pseudoIdAttribute = true;
                                Backbone.Model.prototype.set.call(this, nestedAttrKey, this.getNestedModel(nestedAttrKey, nestedValue, nestedOptions), options);
                            }
                        }
                    }
                }
            }, this);
        }

        return this;
    }

    function documentToJSON() {
        var omitList = [],
            response;

        if (this instanceof Backbone.Collection) {
            var models = this.models;
            response = [];

            _.each(_.keys(models), function (modelKey) {
                var modelValues = models[modelKey].toJSON();

                if (this.pseudoIdAttribute) {
                    modelValues = modelValues.value;
                }

                response.push(modelValues);
            }, this);
        } else if (this instanceof Backbone.Model && this.attributes) {
            var attributes = this.attributes;
            response = {};

            // #7 - Strange output on nested collection models toJSON()
            if (this.collection && this.collection.pseudoIdAttribute) {
                response = this.get('value');
            } else {
                _.each(_.keys(attributes), function (attrKey) {
                    if (attributes[attrKey] instanceof Backbone.Model || attributes[attrKey] instanceof Backbone.Collection) {
                        omitList.push(attrKey);
                    }
                });

                // clear pseudo parent id reference.
                if (this.pseudoIdAttribute) {
                    delete attributes[this.idAttribute];
                }

                response = _.omit(attributes, omitList);

                _.each(omitList, function (omitKey) {
                    response[omitKey] = attributes[omitKey].toJSON();
                });
            }
        }

        return response;
    }

    function documentEvents(eventName) {
        var eventSplit = eventName.split(':'),
            eventType = eventSplit[0],
            eventAttrs = eventSplit.length > 1 ? _.last(eventSplit, eventSplit.length - 1)[0].split('.') : [],
            args = Array.prototype.slice.call(arguments, 0);

        //console.log('DocumentEvent:event:this (' + this.name + ') [' + (this instanceof Backbone.Model ? 'M' : 'C') + ']:' + eventName);

        if (eventName === 'change') {
            return;
        }

        // Only trigger events on Models, Collections automatically replicate Child Model events.
        eventAttrs.unshift(this.name);

        var event = _.reduce(eventAttrs, function (memo, val) {
            return memo + '.' + val;
        });

        args[0] = eventType + ':' + event;

        //console.log('DocumentEvent:trigger:this (' + this.name + ') [' + (this instanceof Backbone.Model ? 'M' : 'C') + ']:parent (' + (this.parent.name || (this.parent.collection ? this.parent.collection.name : 'undefined')) + ') [' + (this.parent instanceof Backbone.Model ? 'M' : 'C') + ']:' + args[0]);
        this.parent.trigger.apply(this.parent, args);
    }

    function documentTrigger(name) {
        Backbone.Events.trigger.apply(this, arguments);

        if (this._events) {
            var eventMatches = _.filter(_.keys(this._events), function (eventKey) {
                var match = false;

                // Do not trigger on an exact match
                if (name !== eventKey) {
                    if (name.substring(0, 6) === 'change') {
                        if (name.indexOf('.') >= 0) {
                            match = true;
                        }
                    } else {
                        match = true;
                    }
                }

                return match && eventKey.indexOf(':') >= 0 && name.indexOf(':') >= 0 && name.match(eventKey);
            });

            if (eventMatches.length) {
                var args = Array.prototype.slice.call(arguments, 0);

                _.each(eventMatches, function (event) {
                    args[0] = event;
                    Backbone.Events.trigger.apply(this, args);
                }, this);
            }
        }
    }

    function documentSave(key, val, options) {
        // ensure save is executed from the highest document model.
        var obj = this;

        while (obj.parent || (obj.collection && obj.collection.parent)) {
            obj = obj.parent || obj.collection.parent;
        }

        return Backbone.Model.prototype.save.call(obj, key, val, options);
    }

    function documentClone() {
        return new this.constructor(this.toJSON());
    }

    var DocumentModel = Backbone.Model.extend({
        constructor: function (models, options) {
            options || (options = {});
            _.extend(this, _.pick(options, ['idAttribute', 'parent', 'name', 'pseudoIdAttribute',
                'getNestedModel', 'getNestedCollection']));
            Backbone.Model.apply(this, arguments);

            this.on('all', function () {
                if (this.parent && this.name) {
                    documentEvents.apply(this, arguments)
                }
            }, this);
        },
        pseudoIdAttribute: false,
        toJSON: documentToJSON,
        get: documentModelGet,
        set: documentModelSet,
        save: documentSave,
        clone: documentClone,
        trigger: documentTrigger,
        getNestedModel: documentModelGetNestedModel,
        getNestedCollection: documentModelGetNestedCollection
    });

    var DocumentCollection = Backbone.Collection.extend({
        constructor: function (models, options) {
            options || (options = {});
            _.extend(this, _.pick(options, ['idAttribute', 'parent', 'name']));
            Backbone.Collection.apply(this, arguments);

            this.on('all', function () {
                if (this.parent && this.name) {
                    documentEvents.apply(this, arguments)
                }
            }, this);
        },
        pseudoIdAttribute: false,
        model: DocumentModel,
        toJSON: documentToJSON,
        get: documentCollectionGet,
        set: documentCollectionSet,
        clone: documentClone,
        trigger: documentTrigger,
        _prepareModel: documentModelPrepare
    });

    //Exports
    Backbone.DocumentModel = DocumentModel;
    Backbone.DocumentCollection = DocumentCollection;

    //For use in NodeJS
    if (typeof module != 'undefined') module.exports = DocumentModel;

    return Backbone;
}));
<commit_msg>Fixed set() from modifying the attrs passed in (caller may still want that object intact.)<commit_after>/**
 *
 * Backbone-DocumentModel v0.6.4
 *
 * Copyright (c) 2013 Michael Haselton & Aaron Herres, Loqwai LLC
 *
 * https://github.com/icereval/backbone-documentmodel
 * Licensed under the MIT License
 */
(function (factory) {
    if (typeof define === 'function' && define.amd) {
        // AMD
        define(['underscore', 'backbone'], factory);
    } else if (typeof exports !== 'undefined') {
        // CommonJS / Node.js
        module.exports = factory(require('underscore'), require('backbone'));
    } else {
        // globals
        factory(_, Backbone);
    }
}(function (_, Backbone) {
    // Can get overridden to determine the nested model class based on passed values.
    function documentModelGetNestedModel(nestedKey, value, options) {
        return new Backbone.DocumentModel(value, options);
    }

    // Can get overridden to determine the nested collection class based on passed values.
    function documentModelGetNestedCollection(nestedKey, value, options) {
        return new Backbone.DocumentCollection(value, options);
    }

    function documentCollectionGet(obj) {
        if (this.pseudoIdAttribute) {
            return this.findWhere({value: obj});
        }

        return Backbone.Collection.prototype.get.call(this, obj);
    }

    function documentModelGet(property) {
        if (!_.isString(property)) {
            return Backbone.Model.prototype.get.call(this, property);
        }

        var properties = _.isArray(property) ? property : property.split('.');
        var retVal = Backbone.Model.prototype.get.call(this, properties.shift());

        if (retVal === undefined) {
            return undefined;
        }

        _.each(properties, function (prop) {
            var parseIntProp;

            if (retVal !== undefined) {
                parseIntProp = parseInt(prop, 10);

                retVal = _.isFinite(parseIntProp) ? retVal.at(parseIntProp) : retVal.get(prop);

                // If the value is a 'pseudo' object go ahead and retrieve its 'value' attribute.
                if (retVal !== undefined && retVal.collection && retVal.collection.pseudoIdAttribute) {
                    retVal = retVal.get('value');
                }
            }
        }, this);

        return retVal;
    }

    function documentCollectionSet(models, options) {
        options || (options = {});

        // Model's within Collections do not store parent/name, this can be accessed
        // through the model's collection attribute.
        delete options.name;
        delete options.parent;

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

    function documentModelPrepare(attrs, options) {
        _.extend(options, _.pick(this.idAttribute ? this : _.isObject(attrs) ? attrs : this, ['idAttribute']));

        // If we are parsing an array or values we'll need to generate a pseudoIdAttribute.
        if (Object.prototype.toString.call(attrs) !== '[object Object]' || _.isArray(attrs)) {
            // #5 - Ensure we do not omit wrapped primitives.
            var value = attrs;

            this.pseudoIdAttribute = true;

            attrs = {};
            attrs[options.idAttribute] = _.uniqueId();
            attrs.value = value;
        }

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

    function documentModelSet(key, val, options) {
        var attrs,
            isBackboneObj,
            nestedAttrs = {},
            deepNamedAttrs = {},
            otherAttrs = {};

        if (key == null) return this;

        // Handle both `"key", value` and `{key: value}` -style arguments.
        if (typeof key === 'object') {
            attrs = key;
            options = val;
        } else {
            (attrs = {})[key] = val;
        }

        options || (options = {});

        // If the object is already a Collection or Model assume its a Document object.
        isBackboneObj =  attrs instanceof Backbone.Collection || attrs instanceof Backbone.Model;

        if (!isBackboneObj) {
            _.each(_.keys(attrs), function (attrKey) {
                if (attrKey.indexOf('.') > 0) {
                    deepNamedAttrs[attrKey] = attrs[attrKey];
                } else if (Object.prototype.toString.call(attrs[attrKey]) === '[object Object]' || _.isArray(attrs[attrKey])) {
                    // #5 - Ensure we do not omit wrapped primitives.
                    nestedAttrs[attrKey] = attrs[attrKey];
                }
                else {
                    // make a copy of the attrs with only the keys we need,
                    // since deleting them from attrs would be a bit of a surprise for
                    // the people passing it in.
                    otherAttrs[attrKey] = attrs[attrKey];
                }
            });
        }

        if (!Backbone.Model.prototype.set.call(this, otherAttrs, options)) return false;

        if (!isBackboneObj) {
            // Refactor Deep Named Attributes ( ex: { 'name.first': 'Joe' } ) into Objects/Arrays for nested attribute merge.
            _.each(_.keys(deepNamedAttrs), function (deepAttrKey) {
                var splitDeepAttrs = deepAttrKey.split('.'),
                    deepAttrName = splitDeepAttrs.pop(),
                    deepAttrHandled = false;

                var parentNestedAttr = nestedAttrs;

                for (var i = 0; i < splitDeepAttrs.length; i++) {
                    var splitDeepAttrKey = splitDeepAttrs[i],
                        childSplitDeepAttrKey = splitDeepAttrs[i + 1];

                    if (_.isFinite(childSplitDeepAttrKey)) {
                        var deepAttrParentName = _.reduce(splitDeepAttrs, function (memo, val) {
                                return memo + '.' + val;
                            }),
                            deepAttrParent = this.get.call(this, deepAttrParentName);

                        if (deepAttrParent) {
                            deepAttrParent.set(deepAttrName, deepNamedAttrs[deepAttrKey], options);
                        }

                        deepAttrHandled = true;

                        break;
                    } else {
                        if (!parentNestedAttr[splitDeepAttrKey]) {
                            parentNestedAttr[splitDeepAttrKey] = {};
                        }

                        parentNestedAttr = parentNestedAttr[splitDeepAttrKey];
                    }
                }

                if (!deepAttrHandled) {
                    parentNestedAttr[deepAttrName] = deepNamedAttrs[deepAttrKey];
                }
            }, this);

            // Handle Nested Attribute Creation - ex: { name: { first: 'Joe' } }
            _.each(_.keys(nestedAttrs), function (nestedAttrKey) {
                var nestedOptions;
                var nestedValue = nestedAttrs[nestedAttrKey];
                // If the attribute already exists, merge the objects.
                if (this.attributes[nestedAttrKey]) {
                    this.attributes[nestedAttrKey].set.call(this.attributes[nestedAttrKey], nestedValue, options);
                } else {
                    nestedOptions = { parent: this };
                    _.extend(nestedOptions, _.pick(this, ['idAttribute']));
                    nestedOptions.name = nestedAttrKey;

                    if (_.isArray(nestedValue)) {
                        // Collection
                        Backbone.Model.prototype.set.call(this, nestedAttrKey, this.getNestedCollection(nestedAttrKey, nestedValue, nestedOptions), options);
                    }  else {
                        // Model
                        if (this instanceof Backbone.DocumentModel) {
                            // Model -> Model
                            if (nestedValue instanceof Backbone.DocumentModel) {
                                if (!nestedValue.get(this.idAttribute)) {
                                    // If no id has was specified for the nested Model, use it's parent id.
                                    // This is required for patching updates and will be omitted on JSON build.
                                    nestedValue.set(this.idAttribute, this.get(this.idAttribute), {silent:true});
                                    nestedOptions.pseudoIdAttribute = true;
                                }
                                _.extend(nestedValue, nestedOptions);
                                Backbone.Model.prototype.set.call(this, nestedAttrKey, nestedValue, options);
                            } else if (!nestedValue[this.idAttribute]) {
                                // If no id has was specified for the nested Model, use it's parent id.
                                // This is required for patching updates and will be omitted on JSON build.
                                nestedValue[this.idAttribute] = this.get(this.idAttribute);
                                nestedOptions.pseudoIdAttribute = true;
                                Backbone.Model.prototype.set.call(this, nestedAttrKey, this.getNestedModel(nestedAttrKey, nestedValue, nestedOptions), options);
                            }
                        }
                    }
                }
            }, this);
        }

        return this;
    }

    function documentToJSON() {
        var omitList = [],
            response;

        if (this instanceof Backbone.Collection) {
            var models = this.models;
            response = [];

            _.each(_.keys(models), function (modelKey) {
                var modelValues = models[modelKey].toJSON();

                if (this.pseudoIdAttribute) {
                    modelValues = modelValues.value;
                }

                response.push(modelValues);
            }, this);
        } else if (this instanceof Backbone.Model && this.attributes) {
            var attributes = this.attributes;
            response = {};

            // #7 - Strange output on nested collection models toJSON()
            if (this.collection && this.collection.pseudoIdAttribute) {
                response = this.get('value');
            } else {
                _.each(_.keys(attributes), function (attrKey) {
                    if (attributes[attrKey] instanceof Backbone.Model || attributes[attrKey] instanceof Backbone.Collection) {
                        omitList.push(attrKey);
                    }
                });

                // clear pseudo parent id reference.
                if (this.pseudoIdAttribute) {
                    delete attributes[this.idAttribute];
                }

                response = _.omit(attributes, omitList);

                _.each(omitList, function (omitKey) {
                    response[omitKey] = attributes[omitKey].toJSON();
                });
            }
        }

        return response;
    }

    function documentEvents(eventName) {
        var eventSplit = eventName.split(':'),
            eventType = eventSplit[0],
            eventAttrs = eventSplit.length > 1 ? _.last(eventSplit, eventSplit.length - 1)[0].split('.') : [],
            args = Array.prototype.slice.call(arguments, 0);

        //console.log('DocumentEvent:event:this (' + this.name + ') [' + (this instanceof Backbone.Model ? 'M' : 'C') + ']:' + eventName);

        if (eventName === 'change') {
            return;
        }

        // Only trigger events on Models, Collections automatically replicate Child Model events.
        eventAttrs.unshift(this.name);

        var event = _.reduce(eventAttrs, function (memo, val) {
            return memo + '.' + val;
        });

        args[0] = eventType + ':' + event;

        //console.log('DocumentEvent:trigger:this (' + this.name + ') [' + (this instanceof Backbone.Model ? 'M' : 'C') + ']:parent (' + (this.parent.name || (this.parent.collection ? this.parent.collection.name : 'undefined')) + ') [' + (this.parent instanceof Backbone.Model ? 'M' : 'C') + ']:' + args[0]);
        this.parent.trigger.apply(this.parent, args);
    }

    function documentTrigger(name) {
        Backbone.Events.trigger.apply(this, arguments);

        if (this._events) {
            var eventMatches = _.filter(_.keys(this._events), function (eventKey) {
                var match = false;

                // Do not trigger on an exact match
                if (name !== eventKey) {
                    if (name.substring(0, 6) === 'change') {
                        if (name.indexOf('.') >= 0) {
                            match = true;
                        }
                    } else {
                        match = true;
                    }
                }

                return match && eventKey.indexOf(':') >= 0 && name.indexOf(':') >= 0 && name.match(eventKey);
            });

            if (eventMatches.length) {
                var args = Array.prototype.slice.call(arguments, 0);

                _.each(eventMatches, function (event) {
                    args[0] = event;
                    Backbone.Events.trigger.apply(this, args);
                }, this);
            }
        }
    }

    function documentSave(key, val, options) {
        // ensure save is executed from the highest document model.
        var obj = this;

        while (obj.parent || (obj.collection && obj.collection.parent)) {
            obj = obj.parent || obj.collection.parent;
        }

        return Backbone.Model.prototype.save.call(obj, key, val, options);
    }

    function documentClone() {
        return new this.constructor(this.toJSON());
    }

    var DocumentModel = Backbone.Model.extend({
        constructor: function (models, options) {
            options || (options = {});
            _.extend(this, _.pick(options, ['idAttribute', 'parent', 'name', 'pseudoIdAttribute',
                'getNestedModel', 'getNestedCollection']));
            Backbone.Model.apply(this, arguments);

            this.on('all', function () {
                if (this.parent && this.name) {
                    documentEvents.apply(this, arguments)
                }
            }, this);
        },
        pseudoIdAttribute: false,
        toJSON: documentToJSON,
        get: documentModelGet,
        set: documentModelSet,
        save: documentSave,
        clone: documentClone,
        trigger: documentTrigger,
        getNestedModel: documentModelGetNestedModel,
        getNestedCollection: documentModelGetNestedCollection
    });

    var DocumentCollection = Backbone.Collection.extend({
        constructor: function (models, options) {
            options || (options = {});
            _.extend(this, _.pick(options, ['idAttribute', 'parent', 'name']));
            Backbone.Collection.apply(this, arguments);

            this.on('all', function () {
                if (this.parent && this.name) {
                    documentEvents.apply(this, arguments)
                }
            }, this);
        },
        pseudoIdAttribute: false,
        model: DocumentModel,
        toJSON: documentToJSON,
        get: documentCollectionGet,
        set: documentCollectionSet,
        clone: documentClone,
        trigger: documentTrigger,
        _prepareModel: documentModelPrepare
    });

    //Exports
    Backbone.DocumentModel = DocumentModel;
    Backbone.DocumentCollection = DocumentCollection;

    //For use in NodeJS
    if (typeof module != 'undefined') module.exports = DocumentModel;

    return Backbone;
}));
<|endoftext|>


<commit_before>
var BackbonePolymerAttach = function(element, pathPrefix) {
  console.log('BackbonePolymerAttach', this, element, pathPrefix);

  var indexOf = this.indexOf.bind(this);

  var modelSetup = function(model) {
    this.listenTo(model, 'change', function(ev) {
      for (var attribute in ev.changed) {
        var ix = indexOf(model);
        var value = model.get(attribute);
        element.notifyPath(pathPrefix + '.models.' + ix + '.attributes.' + attribute, value);
      }
    });
  };

  this.each(modelSetup.bind(this));

  // override Backbone add
  var _add = this.add;
  var addOptions = {add: true, remove: false}; // from backbone source
  this.add = function(model, options) {
    this.length = this.length + 1;
    console.log('add (model)', model, '(options)', options);
    if (_.isArray(model)) {
      throw new Error('backbone-polymer only accepts add of single model');
    }
    // we should probably operate on the Collection.set level to be more allowing
    if (!this._isModel(model)) {
      throw new Error('backbone-polymer requires model instances, not just attributes');
    }

    var options = _.extend({merge: false}, options, addOptions);
    var ix = options.at || 0;

    element.splice(pathPrefix + '.models', ix, 0, model);
    if (!options.silent) {
      this.trigger('add', model, this, options);
    }

    modelSetup.bind(model);
    return model;
  };
};

if (typeof module !== 'undefined') {
  module.exports = BackbonePolymerAttach;
};
<commit_msg>Removes debug logging<commit_after>
var BackbonePolymerAttach = function(element, pathPrefix) {

  var indexOf = this.indexOf.bind(this);

  var modelSetup = function(model) {
    this.listenTo(model, 'change', function(ev) {
      for (var attribute in ev.changed) {
        var ix = indexOf(model);
        var value = model.get(attribute);
        element.notifyPath(pathPrefix + '.models.' + ix + '.attributes.' + attribute, value);
      }
    });
  };

  this.each(modelSetup.bind(this));

  // override Backbone add
  var _add = this.add;
  var addOptions = {add: true, remove: false}; // from backbone source
  this.add = function(model, options) {
    this.length = this.length + 1;
    if (_.isArray(model)) {
      throw new Error('backbone-polymer only accepts add of single model');
    }
    // we should probably operate on the Collection.set level to be more allowing
    if (!this._isModel(model)) {
      throw new Error('backbone-polymer requires model instances, not just attributes');
    }

    var options = _.extend({merge: false}, options, addOptions);
    var ix = options.at || 0;

    element.splice(pathPrefix + '.models', ix, 0, model);
    if (!options.silent) {
      this.trigger('add', model, this, options);
    }

    modelSetup.bind(model);
    return model;
  };
};

if (typeof module !== 'undefined') {
  module.exports = BackbonePolymerAttach;
};
<|endoftext|>


<commit_before>export default {
  NAVIGATION_CHANGE: 'NAVIGATION_CHANGE'
};
<commit_msg>Use module.exports syntax<commit_after>module.exports = {
  NAVIGATION_CHANGE: 'NAVIGATION_CHANGE'
};
<|endoftext|>


<commit_before>var React = require('react');
var sinon = require('sinon');
var CountdownComponent = require('../code/views/countdownView.jsx');
var CountdownManager = require('../code/lib/countdownManager');
var TestUtils = React.addons.TestUtils;

describe('CountdownComponent', function() {
  var clock = null;

  beforeEach(function() {
    clock = sinon.useFakeTimers();
    sinon.stub(CountdownManager.prototype, 'time').returns(123);
  });
  afterEach(function() {
    clock.restore();
    CountdownManager.prototype.time.restore();
  });

  it('should render a countdown timer', function() {
    var countdown = TestUtils.renderIntoDocument(
      <CountdownComponent until="2016-07-27" />
    );
    assert.equal(countdown.props.until, '2016-07-27');
  });

  it('check the countdown mnagaer states time is set correctly', function() {
    var date = "2016-07-27";
    var countdown = TestUtils.renderIntoDocument(
      <CountdownComponent until={date} />
    );
    assert.equal(countdown.state.time, 123);
  });

});
<commit_msg>fixing linting<commit_after>var React = require('react');
var sinon = require('sinon');
var CountdownComponent = require('../code/views/countdownView.jsx');
var CountdownManager = require('../code/lib/countdownManager');
var TestUtils = React.addons.TestUtils;

describe('CountdownComponent', function() {
  var clock = null;

  beforeEach(function() {
    clock = sinon.useFakeTimers();
    sinon.stub(CountdownManager.prototype, 'time').returns(123);
  });
  afterEach(function() {
    clock.restore();
    CountdownManager.prototype.time.restore();
  });

  it('should render a countdown timer', function() {
    var countdown = TestUtils.renderIntoDocument(
      <CountdownComponent until="2016-07-27" />
    );
    assert.equal(countdown.props.until, '2016-07-27');
  });

  it('check the countdown mnagaer states time is set correctly', function() {
    var date = '2016-07-27';
    var countdown = TestUtils.renderIntoDocument(
      <CountdownComponent until={date} />
    );
    assert.equal(countdown.state.time, 123);
  });

});
<|endoftext|>


<commit_before>$( window ).load(function() {
  /*var togglePanel = function(panelId, link){
    var panel = $(panelId);
    panel.toggle();
    if(panel.is(":visible")){
      $(link).html('Hide');
    }else{
      $(link).html('Show');
    }
  };
  $('#togglePanel').click(function(){ togglePanel('#input_panel', this); });
  $('#toggleLegend').click(function(){ togglePanel('#zone_legend', this); });
  $('#toggleMapLegend').click(function(){ togglePanel('#map_legend', this); });
  */
  $('select').addClass("form-control");
  var urlUpdater = function(lMap, oldRegion){
    var grp = lMap.layerManager.getLayerGroup("regionName");
    var currentRegion;
    if(grp && grp.getLayers()[0]) {
      currentRegion = grp.getLayers()[0].options.layerId;
    }
    if(!!oldRegion && !!currentRegion && oldRegion != currentRegion){
      var newUrl = (window.history.state == "changed") ? currentRegion : "../" + currentRegion
      window.history.pushState("changed", currentRegion, newUrl);
      setTimeout(urlUpdater, 500, lMap, currentRegion);
    } else {
      setTimeout(urlUpdater, 500, lMap, currentRegion || oldRegion);
    }
  };

  var initMap = function(){
    if($(map).data('leaflet-map')){
      // lMap is the leaflet map object see http://leafletjs.com/reference.html
      var lMap = $(map).data('leaflet-map');
      L.control.scale().addTo(lMap);
      urlUpdater(lMap, undefined);
    }
    else {
      setTimeout(initMap, 100);
    }
  };
  initMap();

  $("#printBtn").click(function(){
    $('#map').print();
  });
});
<commit_msg>Uncomment code to change icons for hide/show for panels. Fix #227<commit_after>$( window ).load(function() {
  var togglePanel = function(panelId, link){
    var panel = $(panelId);
    // Commment toggling as the toggle function is being handled by shinyjs
    //panel.toggle();
    if(panel.is(":visible")){
      $(link).html('Show');
    }else{
      $(link).html('Hide');
    }
  };

  $('#togglePanel').click(function(){ togglePanel('#input_panel', this); });
  $('#toggleLegend').click(function(){ togglePanel('#zone_legend', this); });
  $('#toggleMapLegend').click(function(){ togglePanel('#map_legend', this); });

  $('select').addClass("form-control");
  var urlUpdater = function(lMap, oldRegion){
    var grp = lMap.layerManager.getLayerGroup("regionName");
    var currentRegion;
    if(grp && grp.getLayers()[0]) {
      currentRegion = grp.getLayers()[0].options.layerId;
    }
    if(!!oldRegion && !!currentRegion && oldRegion != currentRegion){
      var newUrl = (window.history.state == "changed") ? currentRegion : "../" + currentRegion
      window.history.pushState("changed", currentRegion, newUrl);
      setTimeout(urlUpdater, 500, lMap, currentRegion);
    } else {
      setTimeout(urlUpdater, 500, lMap, currentRegion || oldRegion);
    }
  };

  var initMap = function(){
    if($(map).data('leaflet-map')){
      // lMap is the leaflet map object see http://leafletjs.com/reference.html
      var lMap = $(map).data('leaflet-map');
      L.control.scale().addTo(lMap);
      urlUpdater(lMap, undefined);
    }
    else {
      setTimeout(initMap, 100);
    }
  };
  initMap();

  $("#printBtn").click(function(){
    $('#map').print();
  });
});
<|endoftext|>


<commit_before>jQuery(document).ready(function($) {

	$('.site-header .logo a').show();

	if(!Cookies.get('returning_visitor')) {
		var paths = $('.site-header .logo path:not(defs path)');
	}

	var paths = $('.site-header .logo path:not(defs path)');
	paths.each(function(i, e) {
	    e.style.strokeDasharray = e.style.strokeDashoffset = e.getTotalLength();
	});
	var tl = new TimelineMax();

	var e = Power0.easeIn;
	var d = 1;

	tl.add([
	    TweenLite.to(paths.eq(0), .3, {strokeDashoffset: 0, delay: d+0, ease: e}), // T
	    TweenLite.to(paths.eq(1), .3, {strokeDashoffset: 0, delay: d+0.3, ease: e}), // T
	    TweenLite.to(paths.eq(2), 1, {strokeDashoffset: 0, delay: d+.5, ease: e}), // ro
	    TweenLite.to(paths.eq(3), .5, {strokeDashoffset: 0, delay: d+1.5, ease: e}), // y

	    TweenLite.to(paths.eq(4), .5, {strokeDashoffset: 0, delay: d+2.5}), // S
	   	TweenLite.to(paths.eq(5), .15, {strokeDashoffset: 0, delay: d+3}), // t
	    TweenLite.to(paths.eq(6), .75, {strokeDashoffset: 0, delay: d+3.15}), // ori
	    TweenLite.to(paths.eq(7), .15, {strokeDashoffset: 0, delay: d+3.90}), // i
	    TweenLite.to(paths.eq(8), .35, {strokeDashoffset: 0, delay: d+4.05}), // es

	]).timeScale(2.5);

	$('.site-header .logo').mouseenter(function() { tl.pause(); });
	$('.site-header .logo').mouseleave(function() { tl.play(); });

});

jQuery(window).on('load', function(){ var $ = jQuery;

    var $container = $('.story-list');

	$container.masonry({
		// set itemSelector so .grid-sizer is not used in layout
		//itemSelector: '.grid-item',
		// use element for option
		//columnWidth: '.grid-sizer',
		//percentPosition: true
		percentPosition: true,
		itemSelector: '.story',
		transitionDuration: 0
 	});

});

<commit_msg>Use cookies to only show animation once per visit<commit_after>jQuery(document).ready(function($) {

	$('.site-header .logo a').show();

	if(Cookies.get('returning_visitor')) {

		var paths = $('.site-header .logo path:not(defs path)');
		paths.each(function(i, e) {
		    e.style.strokeDasharray = e.style.strokeDashoffset = e.getTotalLength();
		});
		var tl = new TimelineMax();

		var e = Power0.easeIn;
		var d = 1;

		tl.add([
		    TweenLite.to(paths.eq(0), .3, {strokeDashoffset: 0, delay: d+0, ease: e}), // T
		    TweenLite.to(paths.eq(1), .3, {strokeDashoffset: 0, delay: d+0.3, ease: e}), // T
		    TweenLite.to(paths.eq(2), 1, {strokeDashoffset: 0, delay: d+.5, ease: e}), // ro
		    TweenLite.to(paths.eq(3), .5, {strokeDashoffset: 0, delay: d+1.5, ease: e}), // y

		    TweenLite.to(paths.eq(4), .5, {strokeDashoffset: 0, delay: d+2.5}), // S
		   	TweenLite.to(paths.eq(5), .15, {strokeDashoffset: 0, delay: d+3}), // t
		    TweenLite.to(paths.eq(6), .75, {strokeDashoffset: 0, delay: d+3.15}), // ori
		    TweenLite.to(paths.eq(7), .15, {strokeDashoffset: 0, delay: d+3.90}), // i
		    TweenLite.to(paths.eq(8), .35, {strokeDashoffset: 0, delay: d+4.05}), // es

		]).timeScale(2.5);

		$('.site-header .logo').mouseenter(function() { tl.pause(); });
		$('.site-header .logo').mouseleave(function() { tl.play(); });

	} else {
		Cookies.set('returning_visitor', '1', { expires: 1 });
	}

});

jQuery(window).on('load', function(){ var $ = jQuery;

    var $container = $('.story-list');

	$container.masonry({
		// set itemSelector so .grid-sizer is not used in layout
		//itemSelector: '.grid-item',
		// use element for option
		//columnWidth: '.grid-sizer',
		//percentPosition: true
		percentPosition: true,
		itemSelector: '.story',
		transitionDuration: 0
 	});

});

<|endoftext|>


<commit_before>var qualitySlider = function(){

	var elem, slider, output;

	var init = function(){
		elem = $('.quality').show();
		slider = elem.find('input');
		output = elem.find('output');
		slider.change(change);
		App.quality = App.initialQuality;
		change();
	};

	var change = function(){
		App.quality = slider.val();
                output.html(App.quality + 'goodnesses');
	}

	init();
};

var sizeSlider = function(){

	var elem, slider, output;

	var init = function(){
		elem = $('.size').show();
		slider = elem.find('input');
		output = elem.find('output');
		slider.change(change);
		change();
	};

	var change = function(){
		var resolvedWidth = Math.floor(slider.val()/100 * App.initialWidth);

                output.html(resolvedWidth + 'px');

		App.animWidth  = resolvedWidth;
		App.animHeight = Math.floor(resolvedWidth * App.initialHeight / App.initialWidth);
	}

	init();
};

var rateSlider = function(){

	var elem, slider, output, max;

	var init = function(){
		elem = $('.rate').show();
		slider = elem.find('input').change(change);
		output = elem.find('output');

		App.rate = App.initialRate;
		max = App.initialRate / (slider.val() / 100);
		change();
	};

	var change = function(){
		var rate = Math.floor(slider.val()/100 * max);
                output.html(rate + 'ms');
		App.rate = rate;
	};

	init();
};

$(window).bind('firstimage', function(){
	new sizeSlider();
	new rateSlider();
	new qualitySlider();
});

Element.prototype.hasClassName = function(name) {
  return new RegExp("(?:^|\\s+)" + name + "(?:\\s+|$)").test(this.className);
};

Element.prototype.addClassName = function(name) {
  if (!this.hasClassName(name)) {
    this.className = this.className ? [this.className, name].join(' ') : name;
  }
};

Element.prototype.removeClassName = function(name) {
  if (this.hasClassName(name)) {
    var c = this.className;
    this.className = c.replace(new RegExp("(?:^|\\s+)" + name + "(?:\\s+|$)", "g"), "");
  }
};

var samples = samples || {};

// http://www.html5rocks.com/en/tutorials/dnd/basics/#toc-examples
function setupDrag() {

  var container = $("#inimglist");
  var dragSrcEl_ = null;

  var handleDragStart = function(e) {
    e.originalEvent.dataTransfer.effectAllowed = 'move';
    e.originalEvent.dataTransfer.setData('text/html', this.innerHTML);
    dragSrcEl_ = this;
    $(this).addClass('moving');
  };

  var handleDragOver = function(e) {
    if (e.originalEvent.preventDefault) {
      e.originalEvent.preventDefault(); // Allows us to drop.
    }

    e.originalEvent.dataTransfer.dropEffect = 'move';

  };

  var handleDragEnter = function(e) {
    $(this).addClass('over');
  };

  var handleDragLeave = function(e) {
    // this/e.target is previous target element.
    $(this).removeClass('over');
  };

  var handleDrop = function(e) {

    if (e.originalEvent.stopPropagation) {
      e.originalEvent.stopPropagation(); // stops the browser from redirecting.
    }

    if (dragSrcEl_ != this) {
       dragSrcEl_.innerHTML = this.innerHTML;
       this.innerHTML = e.originalEvent.dataTransfer.getData('text/html');
       App.rebuildTimeline();
       handleDragEnd();
    }

  };

  var handleDragEnd = function() {
    container.find(".col").removeClass("over moving");
  };

  container.on("dragstart", ".col", handleDragStart);
  container.on("dragenter", ".col", handleDragEnter);
  container.on("dragover", ".col", handleDragOver);
  container.on("dragleave", ".col", handleDragLeave);
  container.on("drop", ".col", handleDrop);
  container.on("dragend", ".col", handleDragEnd);
}

<commit_msg>Removing unused code<commit_after>var qualitySlider = function(){

	var elem, slider, output;

	var init = function(){
		elem = $('.quality').show();
		slider = elem.find('input');
		output = elem.find('output');
		slider.change(change);
		App.quality = App.initialQuality;
		change();
	};

	var change = function(){
		App.quality = slider.val();
                output.html(App.quality + 'goodnesses');
	}

	init();
};

var sizeSlider = function(){

	var elem, slider, output;

	var init = function(){
		elem = $('.size').show();
		slider = elem.find('input');
		output = elem.find('output');
		slider.change(change);
		change();
	};

	var change = function(){
		var resolvedWidth = Math.floor(slider.val()/100 * App.initialWidth);

                output.html(resolvedWidth + 'px');

		App.animWidth  = resolvedWidth;
		App.animHeight = Math.floor(resolvedWidth * App.initialHeight / App.initialWidth);
	}

	init();
};

var rateSlider = function(){

	var elem, slider, output, max;

	var init = function(){
		elem = $('.rate').show();
		slider = elem.find('input').change(change);
		output = elem.find('output');

		App.rate = App.initialRate;
		max = App.initialRate / (slider.val() / 100);
		change();
	};

	var change = function(){
		var rate = Math.floor(slider.val()/100 * max);
                output.html(rate + 'ms');
		App.rate = rate;
	};

	init();
};

$(window).bind('firstimage', function(){
	new sizeSlider();
	new rateSlider();
	new qualitySlider();
});

var samples = samples || {};

// http://www.html5rocks.com/en/tutorials/dnd/basics/#toc-examples
function setupDrag() {

  var container = $("#inimglist");
  var dragSrcEl_ = null;

  var handleDragStart = function(e) {
    e.originalEvent.dataTransfer.effectAllowed = 'move';
    e.originalEvent.dataTransfer.setData('text/html', this.innerHTML);
    dragSrcEl_ = this;
    $(this).addClass('moving');
  };

  var handleDragOver = function(e) {
    if (e.originalEvent.preventDefault) {
      e.originalEvent.preventDefault(); // Allows us to drop.
    }

    e.originalEvent.dataTransfer.dropEffect = 'move';

  };

  var handleDragEnter = function(e) {
    $(this).addClass('over');
  };

  var handleDragLeave = function(e) {
    // this/e.target is previous target element.
    $(this).removeClass('over');
  };

  var handleDrop = function(e) {

    if (e.originalEvent.stopPropagation) {
      e.originalEvent.stopPropagation(); // stops the browser from redirecting.
    }

    if (dragSrcEl_ != this) {
       dragSrcEl_.innerHTML = this.innerHTML;
       this.innerHTML = e.originalEvent.dataTransfer.getData('text/html');
       App.rebuildTimeline();
       handleDragEnd();
    }

  };

  var handleDragEnd = function() {
    container.find(".col").removeClass("over moving");
  };

  container.on("dragstart", ".col", handleDragStart);
  container.on("dragenter", ".col", handleDragEnter);
  container.on("dragover", ".col", handleDragOver);
  container.on("dragleave", ".col", handleDragLeave);
  container.on("drop", ".col", handleDrop);
  container.on("dragend", ".col", handleDragEnd);
}

<|endoftext|>


<commit_before>var volume_lockout = false;
setInterval(function(){ volume_lockout = false; }, 500);

var _query_queue = [];
var _runquery_timeout;
var BASE_URL = "http://localhost:9000/";

function deferQuery(data, cb, err){
    //TODO: err does nothing
    _query_queue.push({"data": data, "cb": cb, "err": err});
}

function forceQuery(data, cb, err){
    deferQuery(data, cb, err);
    runQueries();
}

function runQueries(cb){
    window.clearTimeout(_runquery_timeout);
    if(_query_queue.length){
        var cbs = _.pluck(_query_queue, "cb");
        var errs = _.pluck(_query_queue, "cb");
        var datas = _.pluck(_query_queue, "data");
        $.post(BASE_URL, JSON.stringify(datas), function(resp){
            if(resp.length != datas.length){
                console.error("Did not recieve correct number of responses from server!");
                return;
            }
            for(var i = 0; i < resp.length; i++){
                var r = resp[i];
                if(!r.success){
                    console.log(r.error);
                }else if(cbs[i]){
                    cbs[i](r.result);
                }
            }
            if(cb){
                cb();
            }
            _runquery_timeout = window.setTimeout(runQueries, 0); // Defer
        }, 'json');
    }else{
        _runquery_timeout = window.setTimeout(runQueries, 50);
    }
    _query_queue = [];
}

/*
// http://www.knockmeout.net/2011/05/dragging-dropping-and-sorting-with.html
//connect items with observableArrays
ko.bindingHandlers.sortableList = {
  init: function(element, valueAccessor) {
      var list = valueAccessor();
      $(element).sortable({
          update: function(event, ui) {
              //retrieve our actual data item
              var item = ui.item.tmplItem().data;
              //figure out its new position
              var position = ko.utils.arrayIndexOf(ui.item.parent().children(), ui.item[0]);
              //remove the item and add it back in the right spot
              if (position >= 0) {
                  list.remove(item);
                  list.splice(position, 0, item);
              }
          }
      });
  }
};
*/

$(document).ready(function(){
    $(".uploadFile").submit(function(){
        $(".queueform");
    });

/*
    $("input.addtxt").keyup(function(){
        var query = $(this).val();
        if(query == ""){
            $(".results").html("");
            return;
        }
        var ytrequrl = "http://gdata.youtube.com/feeds/api/videos?v=2&orderby=relevance&alt=jsonc&q=" + encodeURIComponent(query) + "&max-results=5&callback=?"
        $.getJSON(ytrequrl, function(data){
            var list = $("

");
            var i = 0;
            var index = query.indexOf(" ");

            if(index == -1){
                cmd_ = "";
                cmd = query.toLowerCase();
            }else{
                var cmd_ = query.substr(index);
                var cmd = query.substr(0, index).toLowerCase();
            }

            var isCmdPrefix = function(prefix){
                if(cmd.length < prefix.length){
                    return cmd == prefix.substr(0, cmd.length);
                }
                if(cmd.length == 0){
                    return false;
                }
                return cmd == prefix
            }

            for(var j = 0; j < window.commands.length && i < 5; j++){
                var c = window.commands[j];
                console.log(c, cmd);

                if(isCmdPrefix(c)){
                    console.log(c, cmd_);
                    list.append($("
" + c + "" + cmd_ + "
"));
                    i++
                }
            }

            for(var j = 0; j < data.data.items.length && j + i < 5; j++){
                var vid = data.data.items[j];
                list.append($("
" + vid.title + "
"));
            }
            $(".results").html("").append(list);
        });
        return true;
    });

    $(".queueform").submit(function(){
        if($("input[type=file]").val()){
            return;
        }
        var query = $(".addtxt").val();
        if(!query){
            return false;
        }
        $(".addtxt").val("");
        $.post("/add/" + encodeURIComponent(query),  function(data){
            console.log(data);
            if(!data.success){
                $("div.error").html(data.error).show(300, function(){
                    setTimeout(5000, function(){
                        $("div.error").hide(200);
                    });
                });
            }
            refreshPlaylist();
            $(".addtxt").val("");
        });
        return false; // Prevent form submitting
    });

    */

        /*
    $("ol.playlist").sortable({
        update: function(ev, ui){
            var ordering = $("ol.playlist li").map(function(i, e){return $(e).attr('id')}).toArray().join(";");
            var url = "/msg?queue_cmd=mv&ordering=" + ordering;
            $.get(url);
        },
        start: function(ev, ui){
            window.no_autorefresh = true;
        },
        stop: function(ev, ui){
            window.no_autorefresh = false;
        }
    });
    */

});

var loadSlider = function(){
    $("div.vol-slider").slider({
        orientation: "horizontal",
        range: "min",
        min: 0,
        max: 100,
        value: window.volume,
        slide: function(ev, ui) {
            updateSlider(ui.value);
            if(volume_lockout)
                return;
            volume_lockout = true;
            console.log(ui.value);
            deferQuery({"cmd": "set_vol", "args": [ui.value], "target": vm.statics().volume.uid() }, function(){ volume_lockout = false; });
            console.log({"cmd": "set_vol", "args": [ui.value], "target": vm.statics().volume.uid() });
            /*
            $.get("/vol/" + ui.value, function(){
                volume_lockout = false;
            });
            */
        }
    });
    updateSlider(window.volume);
}

var updateSlider = function(value){
    console.log(value);
    $("div.vol-slider").slider("option", "value", value);
    $(".ui-slider-range").html("" + value + "");
}

var MODULES = {
    "youtube" : {
        _params: ["url"],
        _template: "youtube",
        _template_act: "youtube_act"
    }
};

var STATICS = {
    "volume" : {
        _template: "volume",
        _params: ["vol"],
        create: function(options){
            return ko.mapping.fromJS(options.data, {}, this);
        }
    }
};

/*
function Musicazoo() {
    var self = this;
    self.MODULES = MODULES;
    self.STATICS = STATICS;
    // The following are sub View-Models
    self.queue = ko.observable([]);
    self.activeq = ko.observable([]);
    self.statics = ko.observable({volume: {vol: ko.observable(0)}});
    self.statics().volume.vol.subscribe(updateSlider);

    self.reload = function() {
        if(window.no_autorefresh) return;
        var fetch_params = function(defs){
            return function(q){
                if(defs[q.type]){
                    _.each(defs[q.type]._params, function(mp){
                        deferQuery({"cmd": "get_" + mp, "target": q.uid}, function(v){
                            q[mp] = v;
                        });
                    });
                }else{
                    console.log("Unknown static/module: " + q.type);
                }
            };
        }

        deferQuery({"cmd": "queue"}, function(queue_list) {
            _.each(queue_list, fetch_params(self.MODULES));

            runQueries(function(){
                console.log("Loaded queue:");
                console.log(queue_list);
                ko.mapping.fromJS(queue_list, {}, self.queue);
                $("ol.playlist").sortable("refresh");
            });

        });
        deferQuery({"cmd": "cur"}, function(queue_cur_list) {
            _.each(queue_cur_list, fetch_params(self.MODULES));

            runQueries(function(){
                console.log("Loaded current queue:");
                console.log(queue_cur_list);
                ko.mapping.fromJS(queue_cur_list, {}, self.activeq);
            });

        });
        deferQuery({"cmd": "statics"}, function(statics_list) {
            _.each(statics_list, fetch_params(self.STATICS));

            runQueries(function(){
                var _sts = {};
                for(var i = 0; i < statics_list.length; i++){
                    _sts[statics_list[i].type] = statics_list[i];
                }
                //updateSlider(statics.volume.vol)
                //console.log(_sts);
                ko.mapping.fromJS(_sts, self.STATICS, self.statics);
                //self.statics().volume.vol.subscribe(function(nv){ console.log("VOL HIT"); console.log(nv); });
                //self.statics().volume.vol_test = ko.computed(function(){ return self.statics().volume.vol(); });
            });
        });
    };
};
*/

Backbone.sync = function(method, model, options){
    if(method == "read"){
        _.each(model.keys(), function(k){
            deferQuery({cmd: "get_" + k, target: model.id}, function(v){
                model.set(k, v);
            });
        });
    }else if(method == "update"){
        _.each(model.keys(), function(k){
            if(model.hasChanged(k)){
                deferQuery({cmd: "set_" + k, target: model.id, args: [model.get(k)]});
            }
        });
    }else if(method == "delete"){
        deferQuery({cmd: "rm", target: 0, args: [model.id]});
    }else if(method == "create"){
        //TODO
        console.log("Can't create");
    }
    runQueries(function(){
        options.success(model)
    });
}

var Musicazoo = Backbone.Model.extend({
    defaults: function(){
        return {
            queue: new Queue();
            statics: new StaticSet();
            active: null;
        };
    }
});

var action_types = {};

var Action = Backbone.Model.extend({
    defaults: function(){
        return {

        };
    },
    idAttribute: "uid"
});

var Queue = Backbone.Collection.extend({
    model: Action,
    parse: function(resp, options){
        console.log("queue parse");
        console.log(resp);
    }
});

var refreshPlaylist = function(firstTime){
    vm.reload();
}

refreshPlaylist(true);
// Refresh playlist every 1 seconds
setInterval(refreshPlaylist, 1000);

runQueries();
<commit_msg>Stashing changes<commit_after>var volume_lockout = false;
setInterval(function(){ volume_lockout = false; }, 500);

var _query_queue = [];
var _runquery_timeout;
var BASE_URL = "http://localhost:9000/";

function deferQuery(data, cb, err){
    //TODO: err does nothing
    _query_queue.push({"data": data, "cb": cb, "err": err});
}

function forceQuery(data, cb, err){
    deferQuery(data, cb, err);
    runQueries();
}

function runQueries(cb){
    window.clearTimeout(_runquery_timeout);
    if(_query_queue.length){
        var cbs = _.pluck(_query_queue, "cb");
        var errs = _.pluck(_query_queue, "cb");
        var datas = _.pluck(_query_queue, "data");
        $.post(BASE_URL, JSON.stringify(datas), function(resp){
            if(resp.length != datas.length){
                console.error("Did not recieve correct number of responses from server!");
                return;
            }
            for(var i = 0; i < resp.length; i++){
                var r = resp[i];
                if(!r.success){
                    console.log(r.error);
                }else if(cbs[i]){
                    cbs[i](r.result);
                }
            }
            if(cb){
                cb();
            }
            _runquery_timeout = window.setTimeout(runQueries, 0); // Defer
        }, 'json');
    }else{
        _runquery_timeout = window.setTimeout(runQueries, 50);
    }
    _query_queue = [];
}

function authenticate(cb){
    // Auth & get capabilities
    forceQuery({cmd: "capabilities"}, function(cap){
        cb(cap);
    });
}

/*
// http://www.knockmeout.net/2011/05/dragging-dropping-and-sorting-with.html
//connect items with observableArrays
ko.bindingHandlers.sortableList = {
  init: function(element, valueAccessor) {
      var list = valueAccessor();
      $(element).sortable({
          update: function(event, ui) {
              //retrieve our actual data item
              var item = ui.item.tmplItem().data;
              //figure out its new position
              var position = ko.utils.arrayIndexOf(ui.item.parent().children(), ui.item[0]);
              //remove the item and add it back in the right spot
              if (position >= 0) {
                  list.remove(item);
                  list.splice(position, 0, item);
              }
          }
      });
  }
};
*/

$(document).ready(function(){
    $(".uploadFile").submit(function(){
        $(".queueform");
    });

/*
    $("input.addtxt").keyup(function(){
        var query = $(this).val();
        if(query == ""){
            $(".results").html("");
            return;
        }
        var ytrequrl = "http://gdata.youtube.com/feeds/api/videos?v=2&orderby=relevance&alt=jsonc&q=" + encodeURIComponent(query) + "&max-results=5&callback=?"
        $.getJSON(ytrequrl, function(data){
            var list = $("

");
            var i = 0;
            var index = query.indexOf(" ");

            if(index == -1){
                cmd_ = "";
                cmd = query.toLowerCase();
            }else{
                var cmd_ = query.substr(index);
                var cmd = query.substr(0, index).toLowerCase();
            }

            var isCmdPrefix = function(prefix){
                if(cmd.length < prefix.length){
                    return cmd == prefix.substr(0, cmd.length);
                }
                if(cmd.length == 0){
                    return false;
                }
                return cmd == prefix
            }

            for(var j = 0; j < window.commands.length && i < 5; j++){
                var c = window.commands[j];
                console.log(c, cmd);

                if(isCmdPrefix(c)){
                    console.log(c, cmd_);
                    list.append($("
" + c + "" + cmd_ + "
"));
                    i++
                }
            }

            for(var j = 0; j < data.data.items.length && j + i < 5; j++){
                var vid = data.data.items[j];
                list.append($("
" + vid.title + "
"));
            }
            $(".results").html("").append(list);
        });
        return true;
    });

    $(".queueform").submit(function(){
        if($("input[type=file]").val()){
            return;
        }
        var query = $(".addtxt").val();
        if(!query){
            return false;
        }
        $(".addtxt").val("");
        $.post("/add/" + encodeURIComponent(query),  function(data){
            console.log(data);
            if(!data.success){
                $("div.error").html(data.error).show(300, function(){
                    setTimeout(5000, function(){
                        $("div.error").hide(200);
                    });
                });
            }
            refreshPlaylist();
            $(".addtxt").val("");
        });
        return false; // Prevent form submitting
    });

    */

        /*
    $("ol.playlist").sortable({
        update: function(ev, ui){
            var ordering = $("ol.playlist li").map(function(i, e){return $(e).attr('id')}).toArray().join(";");
            var url = "/msg?queue_cmd=mv&ordering=" + ordering;
            $.get(url);
        },
        start: function(ev, ui){
            window.no_autorefresh = true;
        },
        stop: function(ev, ui){
            window.no_autorefresh = false;
        }
    });
    */

});

var loadSlider = function(){
    $("div.vol-slider").slider({
        orientation: "horizontal",
        range: "min",
        min: 0,
        max: 100,
        value: window.volume,
        slide: function(ev, ui) {
            updateSlider(ui.value);
            if(volume_lockout)
                return;
            volume_lockout = true;
            console.log(ui.value);
            deferQuery({"cmd": "set_vol", "args": [ui.value], "target": vm.statics().volume.uid() }, function(){ volume_lockout = false; });
            console.log({"cmd": "set_vol", "args": [ui.value], "target": vm.statics().volume.uid() });
            /*
            $.get("/vol/" + ui.value, function(){
                volume_lockout = false;
            });
            */
        }
    });
    updateSlider(window.volume);
}

var updateSlider = function(value){
    console.log(value);
    $("div.vol-slider").slider("option", "value", value);
    $(".ui-slider-range").html("" + value + "");
}

/*
var MODULES = {
    "youtube" : {
        _params: ["url"],
        _template: "youtube",
        _template_act: "youtube_act"
    }
};

var STATICS = {
    "volume" : {
        _template: "volume",
        _params: ["vol"],
        create: function(options){
            return ko.mapping.fromJS(options.data, {}, this);
        }
    }
};
*/

/*
function Musicazoo() {
    var self = this;
    self.MODULES = MODULES;
    self.STATICS = STATICS;
    // The following are sub View-Models
    self.queue = ko.observable([]);
    self.activeq = ko.observable([]);
    self.statics = ko.observable({volume: {vol: ko.observable(0)}});
    self.statics().volume.vol.subscribe(updateSlider);

    self.reload = function() {
        if(window.no_autorefresh) return;
        var fetch_params = function(defs){
            return function(q){
                if(defs[q.type]){
                    _.each(defs[q.type]._params, function(mp){
                        deferQuery({"cmd": "get_" + mp, "target": q.uid}, function(v){
                            q[mp] = v;
                        });
                    });
                }else{
                    console.log("Unknown static/module: " + q.type);
                }
            };
        }

        deferQuery({"cmd": "queue"}, function(queue_list) {
            _.each(queue_list, fetch_params(self.MODULES));

            runQueries(function(){
                console.log("Loaded queue:");
                console.log(queue_list);
                ko.mapping.fromJS(queue_list, {}, self.queue);
                $("ol.playlist").sortable("refresh");
            });

        });
        deferQuery({"cmd": "cur"}, function(queue_cur_list) {
            _.each(queue_cur_list, fetch_params(self.MODULES));

            runQueries(function(){
                console.log("Loaded current queue:");
                console.log(queue_cur_list);
                ko.mapping.fromJS(queue_cur_list, {}, self.activeq);
            });

        });
        deferQuery({"cmd": "statics"}, function(statics_list) {
            _.each(statics_list, fetch_params(self.STATICS));

            runQueries(function(){
                var _sts = {};
                for(var i = 0; i < statics_list.length; i++){
                    _sts[statics_list[i].type] = statics_list[i];
                }
                //updateSlider(statics.volume.vol)
                //console.log(_sts);
                ko.mapping.fromJS(_sts, self.STATICS, self.statics);
                //self.statics().volume.vol.subscribe(function(nv){ console.log("VOL HIT"); console.log(nv); });
                //self.statics().volume.vol_test = ko.computed(function(){ return self.statics().volume.vol(); });
            });
        });
    };
};
*/

authenticate(function(capabilities){
    var modules = capabilities.modules; // We care about everything
    var statics = capabilities.statics;
    Backbone.sync = function(method, model, options){
        if(method == "read"){
            _.each(model.parameters(), function(k){
                deferQuery({cmd: "get_" + k, target: model.id}, function(v){
                    model.set(k, v);
                });
            });
        }else if(method == "update"){
            _.each(model.parameters(), function(k){
                if(model.hasChanged(k)){
                    deferQuery({cmd: "set_" + k, target: model.id, args: [model.get(k)]});
                }
            });
        }else if(method == "delete"){
            deferQuery({cmd: "rm", target: 0, args: [model.id]});
        }else if(method == "create"){
            //TODO
            console.log("Can't create");
            deferQuery({cmd: "add"});
        }
        runQueries(function(){
            options.success(model)
        });
    }

    var Action = Backbone.Model.extend({
        defaults: function(){
            return {
                active: false,
                template_queue: "unknown",
                template_active: "unknown_active"
            };
        },
        idAttribute: "uid"
    });

    var Queue = Backbone.Collection.extend({
        model: Action,
        parse: function(resp, options){
            console.log("queue parse");
            console.log(resp);
        }
    });

    _.each(modules, function(v, k){
        modules[k].Model = Action.extend({
            type: k,
            parameters: function(){
                return v.parameters;
            },
            commands: function(){
                return v.commands;
            }
        });
    });

    var Static = Backbone.Model.extend({
        defaults: function(){
            return {

            };
        },
        idAttribute: "uid"
    });

    var StaticSet = Backbone.Collection.extend({
        model: Static,
        parse: function(resp, options){
            console.log("statics parse");
            console.log(resp);
        }

    });

    _.each(statics, function(v, k){
        statics[k].Model = Static.extend({
            type: k,
            parameters: function(){
                return v.parameters;
            },
            commands: function(){
                return v.commands;
            }
        });
    });

    var Musicazoo = Backbone.Model.extend({
        defaults: function(){
            return {
                queue: new Queue();
                statics: new StaticSet();
                active: null;
            };
        }
    });

    var refreshPlaylist = function(firstTime){
        vm.reload();
    }

    refreshPlaylist(true);
    // Refresh playlist every 1 seconds
    setInterval(refreshPlaylist, 1000);
}
<|endoftext|>


<commit_before>/**
 * Copyright 2015-2019 OpenCB
 *
 * 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 {LitElement, html} from "/web_modules/lit-element.js";
import UtilsNew from "../../../utilsNew.js";
import PolymerUtils from "../../PolymerUtils.js";

export default class DiseaseFilter extends LitElement {

    constructor() {
        super();

        // Set status and init private properties
        this._init();
    }

    createRenderRoot() {
        return this;
    }

    static get properties() {
        return {
            opencgaSession: {
                type: Object
            },
            panel: {
                type: Array
            },
            diseasePanels: {
                type: Array
            },
            mode: {
                type: String
            },
            config: {
                type: Object
            }
        };
    }

    _init() {
        this._prefix = "ff-" + UtilsNew.randomString(6) + "_";
        this.panel = [];
        this.genes = [];
    }

    connectedCallback() {
        super.connectedCallback();
        this._config = {...this.getDefaultConfig(), ...this.config};

    }

    updated(changedProperties) {
        if (changedProperties.has("panel") ) {
        }

        if (changedProperties.has("diseasePanels") ) {
            if (this.diseasePanels) {
                this.genes = this.diseasePanels?.[0]?.genes ?? [];
                this.requestUpdate();
            }
        }
    }

    showPanelGenes(panels) {
        PolymerUtils.getElementById(this._prefix + "DiseasePanelsTextarea").value = "";
        const _this = this;

        if (panels && panels.length) {
            this.opencgaSession.opencgaClient.panels()
                .info(panels.join(","), {
                    study: _this.opencgaSession.study.fqn,
                    include: "id,name,stats,genes.id,genes.name,regions.id"
                })
                .then(function(response) {
                    let text = "";
                    for (const panelResponse of response.response) {
                        const panel = panelResponse.result[0];
                        const geneNames = panel.genes.map(gene => gene.name);
                        const regions = panel.regions.map(region => region.id);
                        text += `${panel.name} (${geneNames.length} genes and ${regions.length} regions): ${geneNames.join(",")} \n`;
                        text += `${geneNames.join(",")} \n`;
                        text += `${regions.join(",")} \n\n`;
                    }
                    PolymerUtils.getElementById(_this._prefix + "DiseasePanelsTextarea").value = text;
                })
                .catch(function(response) {
                    console.error(response);
                });
        } else {
            PolymerUtils.getElementById(_this._prefix + "DiseasePanelsTextarea").value = "";
        }
    }

    panelChange(e) {
        const select_vals = e.detail.value || null;
        this.genes = this.diseasePanels.find( diseasePanel => diseasePanel.id === select_vals)?.genes ?? [];
        this.requestUpdate();
    }

    filterChange(e) {
        //select-field-filter already emits a bubbled filterChange event.
    }

    getDefaultConfig() {
        return {
            showSummary: false
        };
    }

    render() {
        this.diseasePanels.sort( (a, b) => {
            if (a.name  b.name) {
                return 1;
            }
            return 0;
        });

        const opts = this.diseasePanels.map(panel => ({
            id: panel.id,
            name: `${panel.name}
                          ${panel.source ? ` - ${panel.source.project || panel.source.id} ${panel.source.version ? "v" + panel.source.version : ""}` : ""}
                          ${panel.stats ? ` (${panel.stats.numberOfGenes} genes, ${panel.stats.numberOfRegions} regions)` : ""}`
        }))

        if (this.mode === "gene") {
            return html`

                        <select-field-filter .liveSearch=${"true"} .data="${opts}" .value=${this.panel} @filterChange="${this.panelChange}"></select-field-filter>

                        <select-field-filter .data="${this.genes.map( gene => ({id:gene.name, name: `${gene.name} (${gene.id})`}))}" @filterChange="${this.filterChange}"></select-field-filter>

            `;
        } else {
            return html`

                    <select-field-filter multiple .liveSearch=${"true"} .data="${opts}" .value=${this.panel} @filterChange="${this.filterChange}"></select-field-filter>
                    ${this._config.showSummary
                        ? html`
                            <textarea class="form-control" rows="4" style="margin-top: 5px;background: #f7f7f7" disabled>${this.panel}</textarea>`
                        : null
                    }

        `;
        }

        // return html`
        //

        //         <select id="${this._prefix}DiseasePanels" class="selectpicker" data-size="10" data-live-search="true" data-selected-text-format="count" multiple @change="${e => this.filterChange(e)}">
        //             ${this.diseasePanels && this.diseasePanels.length && this.diseasePanels.map(panel => html`
        //                 <option value="${panel.id}">
        //                     ${panel.name}
        //                     ${panel.source ? "v" + panel.source.version : ""}
        //                     ${panel.stats ? `${panel.stats.numberOfGenes} genes, ${panel.stats.numberOfRegions} regions` : ""}
        //                 </option>
        //             `)}
        //         </select>
        //
        //         ${this.mode === "gene"
        //             ? html`
        //                 <select id="${this._prefix}Genes" class="selectpicker" data-size="10" data-live-search="true" @change="${e => this.filterChange(e)}">
        //                     ${this.genes && this.genes.length && this.genes.map(gene => html`
        //                         <option value="${gene.name}">
        //                             ${gene.name} (${gene.id})
        //                         </option>
        //                     `)}
        //                 </select>
        //             `
        //             : null
        //         }
        //
        //         ${this._config.showSummary
        //             ? html`
        //                 <textarea id="${this._prefix}DiseasePanelsTextarea" class="form-control" rows="4" style="margin-top: 5px;background: #f7f7f7" disabled> </textarea>`
        //             : null
        //         }
        //

        // `;
    }

}

customElements.define("disease-filter", DiseaseFilter);
<commit_msg>wc: rename panels<commit_after>/**
 * Copyright 2015-2019 OpenCB
 *
 * 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 {LitElement, html} from "/web_modules/lit-element.js";
import UtilsNew from "../../../utilsNew.js";
import PolymerUtils from "../../PolymerUtils.js";

export default class DiseaseFilter extends LitElement {

    constructor() {
        super();

        // Set status and init private properties
        this._init();
    }

    createRenderRoot() {
        return this;
    }

    static get properties() {
        return {
            opencgaSession: {
                type: Object
            },
            panel: {
                type: Array
            },
            diseasePanels: {
                type: Array
            },
            mode: {
                type: String
            },
            config: {
                type: Object
            }
        };
    }

    _init() {
        this._prefix = "ff-" + UtilsNew.randomString(6) + "_";
        this.panel = [];
        this.genes = [];
    }

    connectedCallback() {
        super.connectedCallback();
        this._config = {...this.getDefaultConfig(), ...this.config};

    }

    updated(changedProperties) {
        if (changedProperties.has("panel") ) {
        }

        if (changedProperties.has("diseasePanels") ) {
            if (this.diseasePanels) {
                this.genes = this.diseasePanels?.[0]?.genes ?? [];
                this.requestUpdate();
            }
        }
    }

    showPanelGenes(panels) {
        PolymerUtils.getElementById(this._prefix + "DiseasePanelsTextarea").value = "";
        const _this = this;

        if (panels && panels.length) {
            this.opencgaSession.opencgaClient.panels()
                .info(panels.join(","), {
                    study: _this.opencgaSession.study.fqn,
                    include: "id,name,stats,genes.id,genes.name,regions.id"
                })
                .then(function(response) {
                    let text = "";
                    for (const panelResponse of response.response) {
                        const panel = panelResponse.result[0];
                        const geneNames = panel.genes.map(gene => gene.name);
                        const regions = panel.regions.map(region => region.id);
                        text += `${panel.name} (${geneNames.length} genes and ${regions.length} regions): ${geneNames.join(",")} \n`;
                        text += `${geneNames.join(",")} \n`;
                        text += `${regions.join(",")} \n\n`;
                    }
                    PolymerUtils.getElementById(_this._prefix + "DiseasePanelsTextarea").value = text;
                })
                .catch(function(response) {
                    console.error(response);
                });
        } else {
            PolymerUtils.getElementById(_this._prefix + "DiseasePanelsTextarea").value = "";
        }
    }

    panelChange(e) {
        const select_vals = e.detail.value || null;
        this.genes = this.diseasePanels.find( diseasePanel => diseasePanel.id === select_vals)?.genes ?? [];
        this.requestUpdate();
    }

    filterChange(e) {
        //select-field-filter already emits a bubbled filterChange event.
    }

    getDefaultConfig() {
        return {
            showSummary: false
        };
    }

    render() {
        this.diseasePanels.sort( (a, b) => {
            if (a.name  b.name) {
                return 1;
            }
            return 0;
        });

        const opts = this.diseasePanels.map(panel => ({
            id: panel.id,
            name: `${panel.name}
                          ${panel.source ? ` - ${panel.source.author} ${panel.source.project} ${panel.source.version ? "v" + panel.source.version : ""}` : ""}
                          ${panel.stats ? ` (${panel.stats.numberOfGenes} genes, ${panel.stats.numberOfRegions} regions)` : ""}`
        }))

        if (this.mode === "gene") {
            return html`

                        <select-field-filter .liveSearch=${"true"} .data="${opts}" .value=${this.panel} @filterChange="${this.panelChange}"></select-field-filter>

                        <select-field-filter .data="${this.genes.map( gene => ({id:gene.name, name: `${gene.name} (${gene.id})`}))}" @filterChange="${this.filterChange}"></select-field-filter>

            `;
        } else {
            return html`

                    <select-field-filter multiple .liveSearch=${"true"} .data="${opts}" .value=${this.panel} @filterChange="${this.filterChange}"></select-field-filter>
                    ${this._config.showSummary
                        ? html`
                            <textarea class="form-control" rows="4" style="margin-top: 5px;background: #f7f7f7" disabled>${this.panel}</textarea>`
                        : null
                    }

        `;
        }

        // return html`
        //

        //         <select id="${this._prefix}DiseasePanels" class="selectpicker" data-size="10" data-live-search="true" data-selected-text-format="count" multiple @change="${e => this.filterChange(e)}">
        //             ${this.diseasePanels && this.diseasePanels.length && this.diseasePanels.map(panel => html`
        //                 <option value="${panel.id}">
        //                     ${panel.name}
        //                     ${panel.source ? "v" + panel.source.version : ""}
        //                     ${panel.stats ? `${panel.stats.numberOfGenes} genes, ${panel.stats.numberOfRegions} regions` : ""}
        //                 </option>
        //             `)}
        //         </select>
        //
        //         ${this.mode === "gene"
        //             ? html`
        //                 <select id="${this._prefix}Genes" class="selectpicker" data-size="10" data-live-search="true" @change="${e => this.filterChange(e)}">
        //                     ${this.genes && this.genes.length && this.genes.map(gene => html`
        //                         <option value="${gene.name}">
        //                             ${gene.name} (${gene.id})
        //                         </option>
        //                     `)}
        //                 </select>
        //             `
        //             : null
        //         }
        //
        //         ${this._config.showSummary
        //             ? html`
        //                 <textarea id="${this._prefix}DiseasePanelsTextarea" class="form-control" rows="4" style="margin-top: 5px;background: #f7f7f7" disabled> </textarea>`
        //             : null
        //         }
        //

        // `;
    }

}

customElements.define("disease-filter", DiseaseFilter);
<|endoftext|>


<commit_before>/**
 * Magister Calendar v1.4.0
 * https://git.io/magister
 *
 * Copyright 2015 Sander Laarhoven
 * Licensed under MIT (http://git.io/magister-calendar-license)
 */

var fs = require("fs");

module.exports = {
  validjson: function (string) {
    try {
      JSON.parse(string);
    }
    catch (e) {
      return false;
    }
    return true;
  },
  log: function(status, text, error) {
    if (status == "error") {
      var prefix = "!";
    }
    else {
      var prefix = "*";
    }
    var date = new Date();
    var time = date.getHours() + ":" + date.getMinutes() + ":" + date.getSeconds();
    var logtext = "[" + prefix + "] " + time + " " + text;
    if (error) {
      var logtext = logtext + " " + JSON.stringify(error);
    }
    console.log(logtext);
  },
  loadJSONfile: function(path) {
    var file;
    try {
      file = fs.readFileSync(path, "utf8");
    }
    catch (e) {
      if (e.code == "ENOENT") {
        module.exports.log("error", "Config file " + path + " not found.", e);
        process.exit(1);
      }
      else {
        module.exports.log("error", "An error occured when opening " + path + ".", e);
        throw e;
      }
    }
    if (!module.exports.validjson(file)) {
      module.exports.log("error", "File " + path + " contains bogus JSON.");
      process.exit(1);
    }
    return JSON.parse(file);
  },
  sendPushMessage: function(appointment) {
    // To be implemented..
    return;
  }
}
<commit_msg>Add crashReport function<commit_after>/**
 * Magister Calendar v1.4.0
 * https://git.io/magister
 *
 * Copyright 2015 Sander Laarhoven
 * Licensed under MIT (http://git.io/magister-calendar-license)
 */

var fs = require("fs");
var LOG_HISTORY = "";

module.exports = {
  validjson: function (string) {
    try {
      JSON.parse(string);
    }
    catch (e) {
      return false;
    }
    return true;
  },
  log: function(status, text, error) {
    if (status == "error" || status == "critical") {
      var prefix = "!";
    }
    else {
      var prefix = "*";
    }
    var date = new Date();
    var time = date.getHours() + ":" + date.getMinutes() + ":" + date.getSeconds();
    var logtext = "[" + prefix + "] " + time + " " + text;
    if (error) {
      var logtext = logtext + " " + JSON.stringify(error);
    }
    var LOG_HISTORY += logtext;
    console.log(logtext);
    if (status == "critical") {
      module.exports.crashReport(LOG_HISTORY);
    }
  },
  loadJSONfile: function(path) {
    var file;
    try {
      file = fs.readFileSync(path, "utf8");
    }
    catch (e) {
      if (e.code == "ENOENT") {
        module.exports.log("error", "Config file " + path + " not found.", e);
        process.exit(1);
      }
      else {
        module.exports.log("error", "An error occured when opening " + path + ".", e);
        throw e;
      }
    }
    if (!module.exports.validjson(file)) {
      module.exports.log("error", "File " + path + " contains bogus JSON.");
      process.exit(1);
    }
    return JSON.parse(file);
  },
  sendPushMessage: function(appointment) {
    // To be implemented..
    return;
  },
  crashReport: function(loghistory) {
    var loghistory += "Magister Calendar has crashed!\nPlease open a new issue at https://git.io/magister with this logfile.\n\n";
    fs.writeFile("crash_" + new Date().getTime() + ".log", loghistory, function(err) {
      if (err) {
        module.exports.log("error", "Could not save crash file to disk.", err);
      }
      else {
        module.exports.log("notice", "Saved crash report to disk.");
      }
    });
  }
}
<|endoftext|>


<commit_before>/**
 * Magister Calendar v1.5.2
 * https://git.io/magister
 *
 * Copyright 2015 Sander Laarhoven
 * Licensed under MIT (http://git.io/magister-calendar-license)
 */

var fs = require("fs");
var request = require("request");
var LOG_HISTORY = "";

module.exports = {
  validjson: function (string) {
    try {
      JSON.parse(string);
    }
    catch (e) {
      return false;
    }
    return true;
  },
  log: function(status, text, error) {
    if (status == "error" || status == "critical") {
      var prefix = "!";
    }
    else {
      var prefix = "*";
    }
    var date = new Date();
    var time = date.getHours() + ":" + date.getMinutes() + ":" + date.getSeconds();
    var logtext = "[" + prefix + "] " + time + " " + text;
    if (error) {
      var logtext = logtext + " " + JSON.stringify(error);
    }
    LOG_HISTORY += logtext + "\n";
    console.log(logtext);
    if (status == "critical") {
      module.exports.crashReport(LOG_HISTORY);
    }
  },
  loadJSONfile: function(path) {
    var file;
    try {
      file = fs.readFileSync(path, "utf8");
    }
    catch (e) {
      if (e.code == "ENOENT") {
        module.exports.log("error", "Config file " + path + " not found.", e);
        process.exit(1);
      }
      else {
        module.exports.log("error", "An error occured when opening " + path + ".", e);
        throw e;
      }
    }
    if (!module.exports.validjson(file)) {
      module.exports.log("error", "File " + path + " contains bogus JSON.");
      process.exit(1);
    }
    return JSON.parse(file);
  },
  sendPushMessage: function(config, type, appointment, oldvalue) {

    // Check if push messages are enabled.
    if (config.enabled !== true) {
      return false;
    }

    // Check config.
    if (config.token.length !== 30 || config.user.length !== 30) {
      module.exports.log("notice", "sendPushMessage is not configured properly.");
      return false;
    }

    // Determine message type.
    var appointmentDate = new Date(appointment.begin).toDateString();
    if (type == "homework") {
      var title = "Homework changed";
      var message = "Homework for "+appointment.formatted.title+" on "+appointmentDate+" ";
          message += "was changed.\n Before:\n"+oldvalue+"\nAfter:\n"+appointment.homework;
    } else if (type == "location") {
      var title = "Location changed";
      var message = "Location for "+appointment.formatted.title+" on "+appointmentDate+" ";
          message += "was changed.\n Old location: "+oldvalue+"\nCurrent: "+appointment.location;
    } else if (type == "cancelled") {
      var title = "Appointment cancelled";
      var message = "Appointment "+appointment.formatted.title+" on "+appointmentDate+" ";
          message += "has been cancelled.";
    } else {
      module.exports.log("notice", "Unknown type parameter for function sendPushMessage");
      return false;
    }
    message += "\nDocent(e): "+appointment.teacher+"\nId: "+appointment.id;

    // Prepare POST data.
    var form = {
      token: config.token,
      user: config.user,
      title: title,
      message: message
    };

    // Check device(s) to send message to.
    if (config.device !== "") {
      form.device = config.device;
    }

    // Execute request.
    request({
      url: "https://api.pushover.net/1/messages.json",
      method: "POST",
      form: form
    }, function(err, response, body) {
      if (err) tools.log("error", "Failed to send push message.", err);
      // json encode?
      console.log(body);
      if (body.errors) {
        tools.log("error", "Push message was not sent: ", body.errors);
      } else {
        tools.log("info", "Push message was sent with id "+body.request);
      }
    });
    return;
  },
  crashReport: function(loghistory) {
    loghistory += "Magister Calendar has crashed!\nPlease open a new issue at https://git.io/magister with this logfile.\n\n";
    fs.writeFile("crash_" + new Date().getTime() + ".log", loghistory, function(err) {
      if (err) {
        module.exports.log("error", "Could not save crash file to disk.", err);
      }
      else {
        module.exports.log("notice", "Saved crash report to disk.");
      }
    });
  }
}
<commit_msg>Minor improvements of messages.<commit_after>/**
 * Magister Calendar v1.5.2
 * https://git.io/magister
 *
 * Copyright 2015 Sander Laarhoven
 * Licensed under MIT (http://git.io/magister-calendar-license)
 */

var fs = require("fs");
var request = require("request");
var LOG_HISTORY = "";

module.exports = {
  validjson: function (string) {
    try {
      JSON.parse(string);
    }
    catch (e) {
      return false;
    }
    return true;
  },
  log: function(status, text, error) {
    if (status == "error" || status == "critical") {
      var prefix = "!";
    }
    else {
      var prefix = "*";
    }
    var date = new Date();
    var time = date.getHours() + ":" + date.getMinutes() + ":" + date.getSeconds();
    var logtext = "[" + prefix + "] " + time + " " + text;
    if (error) {
      var logtext = logtext + " " + JSON.stringify(error);
    }
    LOG_HISTORY += logtext + "\n";
    console.log(logtext);
    if (status == "critical") {
      module.exports.crashReport(LOG_HISTORY);
    }
  },
  loadJSONfile: function(path) {
    var file;
    try {
      file = fs.readFileSync(path, "utf8");
    }
    catch (e) {
      if (e.code == "ENOENT") {
        module.exports.log("error", "Config file " + path + " not found.", e);
        process.exit(1);
      }
      else {
        module.exports.log("error", "An error occured when opening " + path + ".", e);
        throw e;
      }
    }
    if (!module.exports.validjson(file)) {
      module.exports.log("error", "File " + path + " contains bogus JSON.");
      process.exit(1);
    }
    return JSON.parse(file);
  },
  sendPushMessage: function(config, type, appointment, oldvalue) {

    // Check if push messages are enabled.
    if (config.enabled !== true) {
      return false;
    }

    // Check config.
    if (config.token.length !== 30 || config.user.length !== 30) {
      module.exports.log("notice", "sendPushMessage is not configured properly.");
      return false;
    }

    // Determine message type.
    var appointmentDate = new Date(appointment.begin).toDateString();
    if (type == "homework") {
      var title = "Homework changed";
      var message = "Homework for "+appointment.formatted.title+" on "+appointmentDate+" ";
          message += "was changed.\nBefore:\n"+oldvalue+"\nAfter:\n"+appointment.homework;
    } else if (type == "location") {
      var title = "Location changed";
      var message = "Location for "+appointment.formatted.title+" on "+appointmentDate+" ";
          message += "was changed.\nOld location: "+oldvalue+"\nNew location: "+appointment.location;
    } else if (type == "cancelled") {
      var title = "Appointment cancelled";
      var message = "Appointment "+appointment.formatted.title+" on "+appointmentDate+" ";
          message += "has been cancelled.";
    } else {
      module.exports.log("notice", "Unknown type parameter for function sendPushMessage");
      return false;
    }
    message += "\nDocent(e): "+appointment.teacher+"\nId: "+appointment.id;

    // Prepare POST data.
    var form = {
      token: config.token,
      user: config.user,
      title: title,
      message: message
    };

    // Check device(s) to send message to.
    if (config.device !== "") {
      form.device = config.device;
    }

    // Execute request.
    request({
      url: "https://api.pushover.net/1/messages.json",
      method: "POST",
      form: form
    }, function(err, response, body) {
      if (err) module.exports.log("error", "Failed to send push message.", err);
      // json encode?
      console.log(body);
      if (body.errors) {
        module.exports.log("error", "Push message was not sent: ", body.errors);
      } else {
        module.exports.log("info", "Push message was sent with id "+body.request);
      }
    });
    return;
  },
  crashReport: function(loghistory) {
    loghistory += "Magister Calendar has crashed!\nPlease open a new issue at https://git.io/magister with this logfile.\n\n";
    fs.writeFile("crash_" + new Date().getTime() + ".log", loghistory, function(err) {
      if (err) {
        module.exports.log("error", "Could not save crash file to disk.", err);
      }
      else {
        module.exports.log("notice", "Saved crash report to disk.");
      }
    });
  }
}
<|endoftext|>