<commit_before>define(["js/ui/View", "sprd/entity/TextConfiguration", "sprd/entity/DesignConfiguration", "sprd/model/PrintType", "js/core/Bus", "js/core/List", "js/core/I18n"], function (View, TextConfiguration, DesignConfiguration, PrintType, Bus, List, I18n) {

    var DEFAULT_DIGITAL_COLORS = {
        black: 0x000000,
        white: 0xFFFFFF,
        cream: 0xEAD080,
        yellow: 0xEAE44B,
        "neon-yellow": 0xD9FF03,
        "yellow-gold": 0xFFC028,
        "orange": 0xE35110,
        "neon-orange": 0xFF4C0D,
        "light-brown": 0xAC8249,
        "brown": 0x4B1B00,
        "burgundy-red": 0x5B0B20,
        "pink": 0xFF9090,
        "red": 0xD41C3B,
        "neon-pink": 0xFF3484,
        "magenta": 0xA92355,
        "purple": 0x521973,
        "lavender": 0xCDBFE3,
        "sky-blue": 0x9DC8D9,
        "light-blue": 0x0091D3,
        "blue": 0x192F97,
        "navy": 0x141754,
        "emerald-green": 0x007E80,
        "green": 0x007D44,
        "neon-green": 0x00FF00,
        "bright-green": 0xB7ED6F,
        "silver-metallic": 0x7C8FA3,
        "grey": 0x787878,
        "gold-metallic": 0x8B7426
    };

    return View.inherit("sprd.view.ConfigurationColorSelectorClass", {

        defaults: {
            componentClass: "configuration-color-selector",

            /***
             * the configuration, to switch the color
             * @type sprd.entity.Configuration
             */
            configuration: null,

            layers: "{layers()}",

            autoSelectLayer: false,

            selectedLayer: null
        },

        inject: {
            bus: Bus,
            i18n: I18n
        },

        events: [
            "on:colorSelected"
        ],

        ctor: function() {
            var self = this;

            this.callBase();

            this.bind("colorPicker", "change:menuVisible", function() {
                if (!this.$.colorPicker.$.menuVisible) {
                    this.set("selectedLayer", null);
                }
            }, this);

            window.onorientationchange = function () {
                self.trigger("orientationChanged");
            };
        },

        _commitConfiguration: function() {
            this.set("layers", null);
        },

        _commitLayers: function(layers) {

            this.set("selectedLayer", null);

            if (layers && this.$.autoSelectLayer) {
                var configuration = this.$.configuration,
                    layerIndex = 0;
                if (configuration && configuration.$lastLayerIndex) {
                    layerIndex = configuration.$lastLayerIndex;
                }

                this.set("selectedLayer", layers[layerIndex]);
            }

        },

        selectLayer: function(e, layer) {

            e.preventDefault();
            e.stopPropagation();

            var configuration = this.$.configuration;
            if (configuration && layer) {
                configuration.$lastLayerIndex = layer.index;
            }

            if (layer !== this.$.selectedLayer) {
                this.set("selectedLayer", layer);
            } else {
                this.set("selectedLayer", null);
            }
        },

        getItemHeight: function () {
            var mediaQuery = window.matchMedia("(max-height: 650px)");

            return mediaQuery.matches ? 10 : 15;
        }.on("orientationChanged"),

        boolean: function(v) {
            return !!v;
        },

        _handleColorSelect: function (e) {
            if (this.$.configuration) {
                this.$.configuration.setColor(this.$.selectedLayer.index, e.$);
                this.trigger("on:colorSelected");

                // TODO: trigger custom event
                this.$.bus.trigger('Application.productChanged', this.$.product);
            }
        },

        nameForColor: function (color) {
            if (color) {
                if (color.$.name) {
                    return color.$.name;
                } else if (color.$.key) {
                    return this.$.i18n.ts('color', color.$.key);
                }
            }
            return "";

        },

        layers: function () {

            var configuration = this.$.configuration;

            if (!configuration) {
                return null;
            }

            if (configuration instanceof TextConfiguration) {
                return [{
                    index: 0
                }];
            } else if (configuration instanceof DesignConfiguration) {
                if (configuration.$.printType.$.id === PrintType.Mapping.SpecialFlex) {
                    return [{
                        index: 0
                    }];
                }
                return configuration.$.printColors.toArray(function (item, index) {
                    return {
                        index: index
                    };
                });
            }
        }.onChange("configuration").on(["configuration", "change:printType"]),

        _printTypeToColors: function (printType) {

            if (printType) {
                if (printType.isPrintColorColorSpace()) {
                    return printType.$.colors;
                } else {
                    if (!this.$digitalColorsCache) {
                        this.$digitalColorsCache = new List();

                        for (var color in DEFAULT_DIGITAL_COLORS) {
                            if (DEFAULT_DIGITAL_COLORS.hasOwnProperty(color)) {
                                var printColor = printType.getClosestPrintColor(DEFAULT_DIGITAL_COLORS[color]);
                                printColor.$.key = color;
                                this.$digitalColorsCache.add(printColor);
                            }
                        }
                    }

                    return this.$digitalColorsCache;
                }
            }

            return null;
        }
    });

});<commit_msg>DEV-66444 - Tablomat not usable under Internet Explorer with Touch Events * fixed matchMedia issue in IE9<commit_after>define(["js/ui/View", "sprd/entity/TextConfiguration", "sprd/entity/DesignConfiguration", "sprd/model/PrintType", "js/core/Bus", "js/core/List", "js/core/I18n"], function (View, TextConfiguration, DesignConfiguration, PrintType, Bus, List, I18n) {

    var DEFAULT_DIGITAL_COLORS = {
        black: 0x000000,
        white: 0xFFFFFF,
        cream: 0xEAD080,
        yellow: 0xEAE44B,
        "neon-yellow": 0xD9FF03,
        "yellow-gold": 0xFFC028,
        "orange": 0xE35110,
        "neon-orange": 0xFF4C0D,
        "light-brown": 0xAC8249,
        "brown": 0x4B1B00,
        "burgundy-red": 0x5B0B20,
        "pink": 0xFF9090,
        "red": 0xD41C3B,
        "neon-pink": 0xFF3484,
        "magenta": 0xA92355,
        "purple": 0x521973,
        "lavender": 0xCDBFE3,
        "sky-blue": 0x9DC8D9,
        "light-blue": 0x0091D3,
        "blue": 0x192F97,
        "navy": 0x141754,
        "emerald-green": 0x007E80,
        "green": 0x007D44,
        "neon-green": 0x00FF00,
        "bright-green": 0xB7ED6F,
        "silver-metallic": 0x7C8FA3,
        "grey": 0x787878,
        "gold-metallic": 0x8B7426
    };

    return View.inherit("sprd.view.ConfigurationColorSelectorClass", {

        defaults: {
            componentClass: "configuration-color-selector",

            /***
             * the configuration, to switch the color
             * @type sprd.entity.Configuration
             */
            configuration: null,

            layers: "{layers()}",

            autoSelectLayer: false,

            selectedLayer: null
        },

        inject: {
            bus: Bus,
            i18n: I18n
        },

        events: [
            "on:colorSelected"
        ],

        ctor: function() {
            var self = this;

            this.callBase();

            this.bind("colorPicker", "change:menuVisible", function() {
                if (!this.$.colorPicker.$.menuVisible) {
                    this.set("selectedLayer", null);
                }
            }, this);

            window.onorientationchange = function () {
                self.trigger("orientationChanged");
            };
        },

        _commitConfiguration: function() {
            this.set("layers", null);
        },

        _commitLayers: function(layers) {

            this.set("selectedLayer", null);

            if (layers && this.$.autoSelectLayer) {
                var configuration = this.$.configuration,
                    layerIndex = 0;
                if (configuration && configuration.$lastLayerIndex) {
                    layerIndex = configuration.$lastLayerIndex;
                }

                this.set("selectedLayer", layers[layerIndex]);
            }

        },

        selectLayer: function(e, layer) {

            e.preventDefault();
            e.stopPropagation();

            var configuration = this.$.configuration;
            if (configuration && layer) {
                configuration.$lastLayerIndex = layer.index;
            }

            if (layer !== this.$.selectedLayer) {
                this.set("selectedLayer", layer);
            } else {
                this.set("selectedLayer", null);
            }
        },

        getItemHeight: function () {
            var window = this.$stage.$window;
            if (window && window.matchMedia) {
                var mediaQuery = window.matchMedia("(max-height: 650px)");

                return mediaQuery.matches ? 10 : 15;
            }
            return 10;
        }.on("orientationChanged"),

        boolean: function(v) {
            return !!v;
        },

        _handleColorSelect: function (e) {
            if (this.$.configuration) {
                this.$.configuration.setColor(this.$.selectedLayer.index, e.$);
                this.trigger("on:colorSelected");

                // TODO: trigger custom event
                this.$.bus.trigger('Application.productChanged', this.$.product);
            }
        },

        nameForColor: function (color) {
            if (color) {
                if (color.$.name) {
                    return color.$.name;
                } else if (color.$.key) {
                    return this.$.i18n.ts('color', color.$.key);
                }
            }
            return "";

        },

        layers: function () {

            var configuration = this.$.configuration;

            if (!configuration) {
                return null;
            }

            if (configuration instanceof TextConfiguration) {
                return [{
                    index: 0
                }];
            } else if (configuration instanceof DesignConfiguration) {
                if (configuration.$.printType.$.id === PrintType.Mapping.SpecialFlex) {
                    return [{
                        index: 0
                    }];
                }
                return configuration.$.printColors.toArray(function (item, index) {
                    return {
                        index: index
                    };
                });
            }
        }.onChange("configuration").on(["configuration", "change:printType"]),

        _printTypeToColors: function (printType) {

            if (printType) {
                if (printType.isPrintColorColorSpace()) {
                    return printType.$.colors;
                } else {
                    if (!this.$digitalColorsCache) {
                        this.$digitalColorsCache = new List();

                        for (var color in DEFAULT_DIGITAL_COLORS) {
                            if (DEFAULT_DIGITAL_COLORS.hasOwnProperty(color)) {
                                var printColor = printType.getClosestPrintColor(DEFAULT_DIGITAL_COLORS[color]);
                                printColor.$.key = color;
                                this.$digitalColorsCache.add(printColor);
                            }
                        }
                    }

                    return this.$digitalColorsCache;
                }
            }

            return null;
        }
    });

});<|endoftext|>


<commit_before>if (typeof RedactorPlugins === 'undefined') var RedactorPlugins = {};
RedactorPlugins.blockquote_break   = {

  init: function() {
    that = this;

    this.opts.keydownCallback =  function(obj, event) {
      if (event.which != 13) {
        return ;
      }

      current_node = obj.getCurrentNode();

      bq_node = that.getMostTopBlockquote(current_node, that.getCode());
      closeTags = that.getClose(current_node, bq_node);
      openTags = that.getOpen(current_node, bq_node);

      splitToken = '

';
      split_node = $(splitToken)[0]
      obj.insertNodeAtCaret(split_node);

      split_contents = obj.getCode().split(splitToken);
      obj.setCode(split_contents[0] + closeTags + "

" + openTags + split_contents[1]);

      /* get the
 element and put cursor on it */
      el = that.$editor.find('#__');
      node = el.get(0);
      el.removeAttr('id');
      sel = obj.getSelection();
      range = sel.getRangeAt(0);
      range.collapse(false);
      range.selectNodeContents(node);
      range.collapse(false);
      sel.removeAllRanges();
      sel.addRange(range);

      event.preventDefault();
    }

  },

  getMostTopBlockquote: function(n, r) {
    var last_bq = null;
    while (n) {
      if (n == r)
        break;
      if (n.nodeName === 'BLOCKQUOTE')
        last_bq = n;
      n = n.parentNode;
    }
    return last_bq;
  },
  getClose: function(n, r) {
    // get the htnk "close-tag" of a node
    function getCloseTag(n) {
        return "</" + n.nodeName.toLowerCase() + ">";
    }

      var result = '';
      while (n) {
        if (n == r)
          break;
        result += getCloseTag(n);
        n = n.parentNode;
      }
      return result;
  },
  getOpen: function (n, r) {
    // get the html "open-tag" of a node
    function getOpenTag(n) {
      var attr, copy;
      copy = n.cloneNode(false);
      if (!copy) {
        return '';
      }
      copy.innerHTML = '';
      attr = $(copy)[0].outerHTML
               .replace(new RegExp( '<'  + copy.nodeName, "i"), '')
               .replace(new RegExp( '</' + copy.nodeName + '>', "i" ), '');
      return '<' + copy.nodeName.toLowerCase() + attr;
    };

    var result = '';
    while (n) {
      if (n == r)
        break;
      result = getOpenTag(n) + result;
      n = n.parentNode;
    }
    return result;
    }
}<commit_msg>should only execute insideblockquote<commit_after>if (typeof RedactorPlugins === 'undefined') var RedactorPlugins = {};
RedactorPlugins.blockquote_break   = {

  init: function() {
    that = this;

    this.opts.keydownCallback =  function(obj, event) {
      if (event.which != 13) {
        return ;
      }
      event.preventDefault();

      current_node = obj.getCurrentNode();

      bq_node = that.getMostTopBlockquote(current_node, that.getCode());

      if (!bq_node) {
        return;
      }

      closeTags = that.getClose(current_node, bq_node);
      openTags = that.getOpen(current_node, bq_node);

      splitToken = '

';
      split_node = $(splitToken)[0]
      obj.insertNodeAtCaret(split_node);

      split_contents = obj.getCode().split(splitToken);
      obj.setCode(split_contents[0] + closeTags + "

" + openTags + split_contents[1]);

      /* get the
 element and put cursor on it */
      el = that.$editor.find('#__');
      node = el.get(0);
      el.removeAttr('id');
      sel = obj.getSelection();
      range = sel.getRangeAt(0);
      range.collapse(false);
      range.selectNodeContents(node);
      range.collapse(false);
      sel.removeAllRanges();
      sel.addRange(range);
    }

  },

  getMostTopBlockquote: function(n, r) {
    var last_bq = null;
    while (n) {
      if (n == r)
        break;
      if (n.nodeName === 'BLOCKQUOTE')
        last_bq = n;
      n = n.parentNode;
    }
    return last_bq;
  },
  getClose: function(n, r) {
    // get the htnk "close-tag" of a node
    function getCloseTag(n) {
        return "</" + n.nodeName.toLowerCase() + ">";
    }

      var result = '';
      while (n) {
        if (n == r)
          break;
        result += getCloseTag(n);
        n = n.parentNode;
      }
      return result;
  },
  getOpen: function (n, r) {
    // get the html "open-tag" of a node
    function getOpenTag(n) {
      var attr, copy;
      copy = n.cloneNode(false);
      if (!copy) {
        return '';
      }
      copy.innerHTML = '';
      attr = $(copy)[0].outerHTML
               .replace(new RegExp( '<'  + copy.nodeName, "i"), '')
               .replace(new RegExp( '</' + copy.nodeName + '>', "i" ), '');
      return '<' + copy.nodeName.toLowerCase() + attr;
    };

    var result = '';
    while (n) {
      if (n == r)
        break;
      result = getOpenTag(n) + result;
      n = n.parentNode;
    }
    return result;
    }
}<|endoftext|>


<commit_before>define(["js/core/Component", "js/core/Base", "js/data/Collection", "underscore", "js/data/Model", "js/data/Entity"],
    function (Component, Base, Collection, _, Model, Entity) {

        var Context = Base.inherit("js.data.DataSource", {

            defaults: {
                collectionPageSize: null
            },

            ctor: function (dataSource, properties, parentContext) {
                this.callBase();

                this.$datasource = dataSource;
                this.$properties = properties;
                this.$parent = parentContext;
                this.$cache = {};

            },

            addEntityToCache: function (model) {
                this.$cache[Context.generateCacheIdFromEntity(model)] = model;
            },

            addCollectionToCache: function (collection) {
                this.$cache[Context.generateCacheIdFromCollection(collection)] = collection;
            },

            getInstanceByCacheId: function (cacheId) {
                return this.$cache[cacheId];
            },

            createEntity: function (factory, id, alias) {

                if (_.isFunction(factory)) {

                    var entityClassName = factory.prototype.constructor.name;
                    alias = alias || (factory.classof(Model) ? this.$datasource.getAliasForModelClassName(entityClassName) : entityClassName);

                    if (factory.classof(Model) && !alias) {
                        throw "Alias for '" + entityClassName + "' not found";
                    }

                    var cachedItem = this.getInstanceByCacheId(Context.generateCacheId(alias, id));

                    if (!cachedItem) {
                        // create new Entity
                        cachedItem = new factory({
                            id: id
                        });
                        // set context
                        cachedItem.$context = this;
                        cachedItem.$alias = alias;

                        // and add it to the cache
                        this.addEntityToCache(cachedItem);
                    }

                    return cachedItem;

                } else {
                    throw "Factory has to be a function";
                }
            },

            createCollection: function (factory, options, alias) {
                options = options || {};

                if (_.isFunction(factory)) {

                    var collectionClassName = factory.prototype.constructor.name;
                    alias = alias || this.$datasource.getAliasForCollectionClassName(collectionClassName);

                    if (!alias) {
                        throw "Alias for '" + collectionClassName + "' not found";
                    }

                    _.defaults(options, {
                        factory: factory,
                        type: alias
                    });

                    var cachedCollection = this.getInstanceByCacheId(Context.generateCacheId(alias));

                    if (!cachedCollection) {
                        // create new Collection
                        cachedCollection = new factory(null, options);
                        // set context
                        cachedCollection.$context = this;
                        cachedCollection.$alias = alias;

                        // and add it to the cache
                        this.addCollectionToCache(cachedCollection);
                    }

                    return cachedCollection;

                } else {
                    throw "Factory has to be a function";
                }
            }
        });

        Context.generateCacheId = function (type, id) {
            if (id) {
                return type + "_" + id;
            } else {
                return type;
            }
        };

        Context.generateCacheIdFromEntity = function (entity) {
            return Context.generateCacheId(entity.$alias, entity.$.id);
        };

        Context.generateCacheIdFromCollection = function (collection) {
            return Context.generateCacheId(collection.className);
        };

        var DataSource = Component.inherit({

            ctor: function () {

                this.$configuredTypes = [];
                this.$contextCache = {};
                this.$processors = [];

                this.callBase();

                this.initializeProcessors();
            },

            $modelFactory: Model,
            $entityFactory: Entity,
            $collectionFactory: Collection,

            initializeProcessors: function () {
                // hook
            },

            _childrenInitialized: function () {
                this.callBase();

                for (var c = 0; c < this.$configurations.length; c++) {
                    var config = this.$configurations[c];
                    this.addTypeConfiguration(config);

                }
            },

            getAliasForModelClassName: function (modelClassName) {

                for (var i = 0; i < this.$configuredTypes.length; i++) {
                    var config = this.$configuredTypes[i];
                    if (config.$.modelClassName === modelClassName) {
                        return config.$.alias;
                    }
                }

                return null;
            },

            getAliasForCollectionClassName: function (collectionClassName) {
                for (var i = 0; i < this.$configuredTypes.length; i++) {
                    var config = this.$configuredTypes[i];
                    if (config.$.collectionClassName === collectionClassName) {
                        return config.$.alias;
                    }
                }

                return null;
            },

            addTypeConfiguration: function (configuration) {

                if (!configuration.$.modelClassName && !configuration.$.alias) {
                    throw "neither modelClassName nor alias defined";
                }

                if (configuration.$.modelClassName && !configuration.$.alias) {
                    configuration.$.alias = configuration.$.modelClassName.split(".").pop();
                }

                if (!configuration.$.modelClassName) {
                    configuration.$.modelClassName = "js.data.Model";
                }

                this.$configuredTypes.push(configuration);
            },

            getFqClassName: function (alias) {

                for (var i = 0; i < this.$configuredTypes.length; i++) {
                    var typeConfig = this.$configuredTypes[i];

                    if (typeConfig.$.alias == alias) {
                        return typeConfig.$.modelClassName;
                    }
                }
            },

            getContext: function (properties, parentContext) {

                var cacheId = this.createContextCacheId(properties, parentContext ? parentContext.$properties : null);

                if (!this.$contextCache.hasOwnProperty(cacheId)) {
                    this.$contextCache[cacheId] = this.createContext(properties, parentContext);
                }

                return this.$contextCache[cacheId];
            },

            /**
             * returns the root context
             */
            root: function () {
                return this.getContext();
            },

            createContext: function (properties, parentContext) {
                return new Context(this, properties, parentContext)
            },

            createContextCacheId: function (properties, parentProperties) {
                var ret = [];
                _.each(_.extend({}, parentProperties, properties), function (value, key) {
                    ret.push(key + "=" + value);
                });

                ret.sort();

                if (ret.length == 0) {
                    return "root";
                }

                return ret.join("&");
            },

            createEntity: function (factory, id, type, context) {
                context = context || this.getContext();

                return context.createEntity(factory, id, type);
            },

            createCollection: function (factory, options, type, context) {
                context = context || this.getContext();

                return context.createCollection(factory, options, type);
            },

            /**
             * resolve references to models and collections
             * @param {js.data.Model} model
             * @param {JSON} data deserialized, parsed data
             * @param {Object} options
             * @param {Function} callback - function (err, resolvedData)
             */
            resolveReferences: function (model, data, options, callback) {
                if (callback) {
                    callback("Abstract method", data);
                }
            },

            loadModel: function (model, options, callback) {
                if (callback) {
                    callback("Abstract method", model);
                }
            },

            /***
             *
             * @param list
             * @param options
             * @param callback
             */
            loadCollectionPage: function (list, options, callback) {
                if (callback) {
                    callback("Abstact method loadCollectionPage", list);
                }
            },

            saveModel: function(model, options, callback) {
                if (callback) {
                    callback("Abstract method saveModel", model);
                }
            },

            update: function (data, callback) {
            },
            remove: function (data, callback) {
            },
            find: function (data, callback) {
            }
        });

        DataSource.Context = Context;

        return DataSource;
    });<commit_msg>introduced processors and formatProcessors<commit_after>define(["js/core/Component", "js/core/Base", "js/data/Collection", "underscore", "js/data/Model", "js/data/Entity", "js/core/List", "flow"],
    function (Component, Base, Collection, _, Model, Entity, List, flow) {

        var Context = Base.inherit("js.data.DataSource.Context", {

            defaults: {
                collectionPageSize: null
            },

            ctor: function (dataSource, properties, parentContext) {
                this.callBase();

                this.$datasource = dataSource;
                this.$properties = properties;
                this.$parent = parentContext;
                this.$cache = {};

            },

            addEntityToCache: function (model) {
                this.$cache[Context.generateCacheIdFromEntity(model)] = model;
            },

            addCollectionToCache: function (collection) {
                this.$cache[Context.generateCacheIdFromCollection(collection)] = collection;
            },

            getInstanceByCacheId: function (cacheId) {
                return this.$cache[cacheId];
            },

            createEntity: function (factory, id, alias) {

                if (_.isFunction(factory)) {

                    var entityClassName = factory.prototype.constructor.name;
                    alias = alias || (factory.classof(Model) ? this.$datasource.getAliasForModelClassName(entityClassName) : entityClassName);

                    if (factory.classof(Model) && !alias) {
                        throw "Alias for '" + entityClassName + "' not found";
                    }

                    var cachedItem = this.getInstanceByCacheId(Context.generateCacheId(alias, id));

                    if (!cachedItem) {
                        // create new Entity
                        cachedItem = new factory({
                            id: id
                        });
                        // set context
                        cachedItem.$context = this;
                        cachedItem.$alias = alias;

                        // and add it to the cache
                        this.addEntityToCache(cachedItem);
                    }

                    return cachedItem;

                } else {
                    throw "Factory has to be a function";
                }
            },

            createCollection: function (factory, options, alias) {
                options = options || {};

                if (_.isFunction(factory)) {

                    var collectionClassName = factory.prototype.constructor.name;
                    alias = alias || this.$datasource.getAliasForCollectionClassName(collectionClassName);

                    if (!alias) {
                        throw "Alias for '" + collectionClassName + "' not found";
                    }

                    _.defaults(options, {
                        factory: factory,
                        type: alias
                    });

                    var cachedCollection = this.getInstanceByCacheId(Context.generateCacheId(alias));

                    if (!cachedCollection) {
                        // create new Collection
                        cachedCollection = new factory(null, options);
                        // set context
                        cachedCollection.$context = this;
                        cachedCollection.$alias = alias;

                        // and add it to the cache
                        this.addCollectionToCache(cachedCollection);
                    }

                    return cachedCollection;

                } else {
                    throw "Factory has to be a function";
                }
            }
        });

        Context.generateCacheId = function (type, id) {
            if (id) {
                return type + "_" + id;
            } else {
                return type;
            }
        };

        Context.generateCacheIdFromEntity = function (entity) {
            return Context.generateCacheId(entity.$alias, entity.$.id);
        };

        Context.generateCacheIdFromCollection = function (collection) {
            return Context.generateCacheId(collection.$alias);
        };

        var Processor = Base.inherit("js.data.DataSource.Processor", {
            ctor: function(dataSource) {
                if (!dataSource) {
                    throw "dataSource is required for Processor";
                }

                this.$datasource = dataSource;
            },

            /***
             * prepares the data for being serialized
             * @param {JSON} data
             * @param {js.data.DataSource.ACTION} action
             * @return {JSON}
             */
            serialize: function(data, action) {
                return data;
            },

            /***
             *
             * parses the deserialized data
             *
             * @param {JSON} data
             * @param {js.data.DataSource.ACTION} action
             * @return {JSON}
             */
            deserialize: function(data, action) {
                return data;
            },

            /***
             * saves sub models
             */
            saveSubModels: function(model, options, callback) {
                // TODO: handle circular dependencies

//                flow()
//                    .parEach(this.getSubModelsForModel(model), function(model, cb) {
//                        model.save(options, cb);
//                    })
//                    .exec(callback);

                // TODO: uncomment
                callback();
            },

            getSubModelsForModel: function (model) {

                var ret = [];

                function getSubModel(obj) {

                    if (obj === model) {
                        return;
                    }

                    if (_.indexOf(ret, obj) !== -1) {
                        // already in list
                        return;
                    }

                    if (obj instanceof Model) {
                        ret.push(obj);
                        return;
                    }

                    for (var key in obj) {
                        if (obj.hasOwnProperty(key)) {
                            var value = obj[key];

                            if (value instanceof Array) {
                                for (var i = 0; i < value.length; i++) {
                                    getSubModel(value[i]);
                                }
                            } else if (value instanceof List) {
                                value.each(function(v) {
                                    getSubModel(v);
                                });
                            } else if (value instanceof Object) {
                                getSubModel(value);
                            }
                        }
                    }
                }

                getSubModel(model.$);

                return ret;

            }
        });

        var DataSource = Component.inherit('js.data.DataSource', {

            ctor: function () {

                this.$configuredTypes = [];
                this.$contextCache = {};
                this.$formatProcessors = [];
                this.$processors = {};

                this.callBase();

                this.initializeFormatProcessors();
                this.initializeProcessors();
            },

            $modelFactory: Model,
            $entityFactory: Entity,
            $collectionFactory: Collection,
            $defaultProcessorFactory: Processor,
            $defaultProcessor: null,

            initializeFormatProcessors: function () {
                // hook
            },

            initializeProcessors: function () {
                this.$defaultProcessor = new (this.$defaultProcessorFactory)(this);
            },

            _childrenInitialized: function () {
                this.callBase();

                for (var c = 0; c < this.$configurations.length; c++) {
                    var config = this.$configurations[c];
                    this.addTypeConfiguration(config);

                }
            },

            getAliasForModelClassName: function (modelClassName) {

                for (var i = 0; i < this.$configuredTypes.length; i++) {
                    var config = this.$configuredTypes[i];
                    if (config.$.modelClassName === modelClassName) {
                        return config.$.alias;
                    }
                }

                return null;
            },

            getAliasForCollectionClassName: function (collectionClassName) {
                for (var i = 0; i < this.$configuredTypes.length; i++) {
                    var config = this.$configuredTypes[i];
                    if (config.$.collectionClassName === collectionClassName) {
                        return config.$.alias;
                    }
                }

                return null;
            },

            addTypeConfiguration: function (configuration) {

                if (!configuration.$.modelClassName && !configuration.$.alias) {
                    throw "neither modelClassName nor alias defined";
                }

                if (configuration.$.modelClassName && !configuration.$.alias) {
                    configuration.$.alias = configuration.$.modelClassName.split(".").pop();
                }

                if (!configuration.$.modelClassName) {
                    configuration.$.modelClassName = "js.data.Model";
                }

                this.$configuredTypes.push(configuration);
            },

            getFqClassName: function (alias) {

                for (var i = 0; i < this.$configuredTypes.length; i++) {
                    var typeConfig = this.$configuredTypes[i];

                    if (typeConfig.$.alias == alias) {
                        return typeConfig.$.modelClassName;
                    }
                }
            },

            getContext: function (properties, parentContext) {

                var cacheId = this.createContextCacheId(properties, parentContext ? parentContext.$properties : null);

                if (!this.$contextCache.hasOwnProperty(cacheId)) {
                    this.$contextCache[cacheId] = this.createContext(properties, parentContext);
                }

                return this.$contextCache[cacheId];
            },

            /**
             * returns the root context
             */
            root: function () {
                return this.getContext();
            },

            createContext: function (properties, parentContext) {
                return new Context(this, properties, parentContext)
            },

            createContextCacheId: function (properties, parentProperties) {
                var ret = [];
                _.each(_.extend({}, parentProperties, properties), function (value, key) {
                    ret.push(key + "=" + value);
                });

                ret.sort();

                if (ret.length == 0) {
                    return "root";
                }

                return ret.join("&");
            },

            createEntity: function (factory, id, type, context) {
                context = context || this.getContext();

                return context.createEntity(factory, id, type);
            },

            createCollection: function (factory, options, type, context) {
                context = context || this.getContext();

                return context.createCollection(factory, options, type);
            },

            /**
             * resolve references to models and collections
             * @param {js.data.Model} model
             * @param {JSON} data deserialized, parsed data
             * @param {Object} options
             * @param {Function} callback - function (err, resolvedData)
             */
            resolveReferences: function (model, data, options, callback) {
                if (callback) {
                    callback("Abstract method", data);
                }
            },

            loadModel: function (model, options, callback) {
                if (callback) {
                    callback("Abstract method", model);
                }
            },

            /***
             *
             * @param list
             * @param options
             * @param callback
             */
            loadCollectionPage: function (list, options, callback) {
                if (callback) {
                    callback("Abstact method loadCollectionPage", list);
                }
            },

            saveModel: function(model, options, callback) {
                if (callback) {
                    callback("Abstract method saveModel", model);
                }
            },

            /***
             * returns the configuration entry for the model class
             * @param modelClassName
             * @return {Configuration} configuration matching the model class name
             */
            getConfigurationForModelClass: function (modelClassName) {

                for (var i = 0; i < this.$configuredTypes.length; i++) {
                    var config = this.$configuredTypes[i];
                    if (config.$.modelClassName === modelClassName) {
                        return config;
                    }
                }

                return null;
            },

            /***
             *
             * returns a configuration entry by matching the alias
             *
             * @param alias
             * @return {*}
             */
            getConfigurationByAlias: function(alias) {
                for (var i = 0; i < this.$datasource.$configuredTypes.length; i++) {
                    var config = this.$datasource.$configuredTypes[i];
                    if (config.$.alias === alias) {
                        return config;
                    }
                }

                return null;
            },

            getProcessorForModel: function (model, options) {

                if (model) {

                    var config;
                    if (model.constructor === this.$modelFactory) {
                        // default model -> working with alias
                        config = this.getConfigurationByAlias(model.$alias);
                    } else {
                        config = this.getConfigurationForModelClass(model.$modelClassName);
                    }

                    if (config && config.$.processor) {
                        var processor = this.$processors[config.$.processor];

                        if (!(processor instanceof (DataSource.Processor))) {
                            throw "Processor for '" + config.$.processor + "' not an instance of js.data.DataSource.Processor."
                        }

                        return processor;
                    }
                }

                return this.$defaultProcessor;
            },

            getFormatProcessor: function(action) {
                return this.$formatProcessors[0];
            },

            update: function (data, callback) {
            },
            remove: function (data, callback) {
            },
            find: function (data, callback) {
            }
        });

        DataSource.FormatProcessor = Base.inherit("js.data.DataSource.FormatProcessor", {
            serialize: function (data) {
                throw "abstract method";
            },
            deserialize: function (responses) {
                throw "abstract method";
            }
        });

        DataSource.Context = Context;

        DataSource.Processor = Processor;

        DataSource.ACTION = {
            CREATE: 'create',
            UPDATE: 'update',
            DELETE: 'delete'
        };

        return DataSource;
    });<|endoftext|>


<commit_before>import { isArray } from './../common/util/check'
import { remAttr, getAttr, getOuterHTML, createDOMPlaceholder, safeInsert, createFrag } from './../common/util/dom'
import { each, contains, extend } from './../common/util/misc'
import { tmpl } from 'riot-tmpl'
import Tag from './tag'

import {
  T_STRING,
  T_OBJECT,
  __TAG_IMPL,
  CONDITIONAL_DIRECTIVE,
  LOOP_DIRECTIVE,
  LOOP_NO_REORDER_DIRECTIVE
} from './../common/global-variables'

import {
  moveChildTag,
  getTag,
  getTagName,
  getRefAttr,
  remRefAttr,
  arrayishAdd,
  arrayishRemove,
  makeVirtual,
  moveVirtual
} from './../common/util/tags'

/**
 * Convert the item looped into an object used to extend the child tag properties
 * @param   { Object } expr - object containing the keys used to extend the children tags
 * @param   { * } key - value to assign to the new object returned
 * @param   { * } val - value containing the position of the item in the array
 * @param   { Object } base - prototype object for the new item
 * @returns { Object } - new object containing the values of the original item
 *
 * The variables 'key' and 'val' are arbitrary.
 * They depend on the collection type looped (Array, Object)
 * and on the expression used on the each tag
 *
 */
function mkitem(expr, key, val, base) {
  var item = base ? Object.create(base) : {}
  item[expr.key] = key
  if (expr.pos) item[expr.pos] = val
  return item
}

/**
 * Unmount the redundant tags
 * @param   { Array } items - array containing the current items to loop
 * @param   { Array } tags - array containing all the children tags
 */
function unmountRedundant(items, tags) {
  var i = tags.length,
    j = items.length

  while (i > j) {
    i--
    remove.apply(tags[i], [tags, i])
  }
}

/**
 * Remove a child tag
 * @this Tag
 * @param   { Array } tags - tags collection
 * @param   { Number } i - index of the tag to remove
 */
function remove(tags, i) {
  tags.splice(i, 1)
  this.unmount()
  arrayishRemove(this.parent, this, this.__.tagName, true)
}

/**
 * Move the nested custom tags in non custom loop tags
 * @this Tag
 * @param   { Number } i - current position of the loop tag
 */
function moveNestedTags(i) {
  each(Object.keys(this.tags), (tagName) => {
    var tag = this.tags[tagName]
    if (isArray(tag))
      each(tag, function (t) {
        moveChildTag.apply(t, [tagName, i])
      })
    else
      moveChildTag.apply(tag, [tagName, i])
  })
}

/**
 * Move a child tag
 * @this Tag
 * @param   { HTMLElement } root - dom node containing all the loop children
 * @param   { Tag } nextTag - instance of the next tag preceding the one we want to move
 * @param   { Boolean } isVirtual - is it a virtual tag?
 */
function move(root, nextTag, isVirtual) {
  if (isVirtual)
    moveVirtual.apply(this, [root, nextTag])
  else
    safeInsert(root, this.root, nextTag.root)
}

/**
 * Insert and mount a child tag
 * @this Tag
 * @param   { HTMLElement } root - dom node containing all the loop children
 * @param   { Tag } nextTag - instance of the next tag preceding the one we want to insert
 * @param   { Boolean } isVirtual - is it a virtual tag?
 */
function insert(root, nextTag, isVirtual) {
  if (isVirtual)
    makeVirtual.apply(this, [root, nextTag])
  else
    safeInsert(root, this.root, nextTag.root)
}

/**
 * Append a new tag into the DOM
 * @this Tag
 * @param   { HTMLElement } root - dom node containing all the loop children
 * @param   { Boolean } isVirtual - is it a virtual tag?
 */
function append(root, isVirtual) {
  if (isVirtual)
    makeVirtual.call(this, root)
  else
    root.appendChild(this.root)
}

/**
 * Manage tags having the 'each'
 * @param   { HTMLElement } dom - DOM node we need to loop
 * @param   { Tag } parent - parent tag instance where the dom node is contained
 * @param   { String } expr - string contained in the 'each' attribute
 * @returns { Object } expression object for this each loop
 */
export default function _each(dom, parent, expr) {

  // remove the each property from the original tag
  remAttr(dom, LOOP_DIRECTIVE)

  var mustReorder = typeof getAttr(dom, LOOP_NO_REORDER_DIRECTIVE) !== T_STRING || remAttr(dom, LOOP_NO_REORDER_DIRECTIVE),
    tagName = getTagName(dom),
    impl = __TAG_IMPL[tagName] || { tmpl: getOuterHTML(dom) },
    parentNode = dom.parentNode,
    placeholder = createDOMPlaceholder(),
    child = getTag(dom),
    refExpr = getRefAttr(dom),
    ifExpr = getAttr(dom, CONDITIONAL_DIRECTIVE),
    tags = [],
    oldItems = [],
    hasKeys,
    isLoop = true,
    hasRefExpr = false,
    isAnonymous = !__TAG_IMPL[tagName],
    isVirtual = dom.tagName === 'VIRTUAL'

  // parse the each expression
  expr = tmpl.loopKeys(expr)
  expr.isLoop = true

  if (ifExpr) remAttr(dom, CONDITIONAL_DIRECTIVE)

  // check if the loop tag has a ref attribute
  if (refExpr) {
    // detect if the ref attribute is an expression
    hasRefExpr = tmpl.hasExpr(refExpr)
    remRefAttr(dom)
  }

  // insert a marked where the loop tags will be injected
  parentNode.insertBefore(placeholder, dom)
  parentNode.removeChild(dom)

  expr.update = function updateEach() {
    // get the new items collection
    var items = tmpl(expr.val, parent),
      frag = createFrag(),
      refAttr = refExpr,
      isObject = !isArray(items),
      root = placeholder.parentNode

    // object loop. any changes cause full redraw
    if (isObject) {
      hasKeys = items || false
      items = hasKeys ?
        Object.keys(items).map(function (key) {
          return mkitem(expr, items[key], key)
        }) : []
    } else {
      hasKeys = false
    }

    if (ifExpr) {
      items = items.filter(function(item, i) {
        if (expr.key && !isObject)
          return !!tmpl(ifExpr, mkitem(expr, item, i, parent))

        return !!tmpl(ifExpr, extend(Object.create(parent), item))
      })
    }

    if (refAttr && hasRefExpr) {
      refAttr = tmpl(refExpr, parent)
    }

    // reset the parent ref
    if (refAttr) parent.refs[refAttr] = []

    // loop all the new items
    each(items, function(item, i) {
      // reorder only if the items are objects
      var
        doReorder = mustReorder && typeof item === T_OBJECT && !hasKeys,
        oldPos = oldItems.indexOf(item),
        isNew = !~oldPos,
        pos = !isNew && doReorder ? oldPos : i,
        // does a tag exist in this position?
        tag = tags[pos],
        mustAppend = i >= oldItems.length,
        mustCreate =  doReorder && isNew || !doReorder && !tag

      item = !hasKeys && expr.key ? mkitem(expr, item, i) : item

      // new tag
      if (mustCreate) {
        tag = new Tag(impl, {
          parent,
          isLoop,
          isAnonymous,
          root: dom.cloneNode(),
          item
        }, dom.innerHTML)

        // mount the tag
        tag.mount()

        if (mustAppend)
          append.apply(tag, [frag || root, isVirtual])
        else
          insert.apply(tag, [root, tags[i], isVirtual])

        if (!mustAppend) oldItems.splice(i, 0, item)
        tags.splice(i, 0, tag)
        if (child) arrayishAdd(parent.tags, tagName, tag, true)
      } else if (pos !== i && doReorder) {
        // move
        if (contains(items, oldItems[i])) {
          move.apply(tag, [root, tags[i], isVirtual])
          // move the old tag instance
          tags.splice(i, 0, tags.splice(pos, 1)[0])
          // move the old item
          oldItems.splice(i, 0, oldItems.splice(pos, 1)[0])
        } else { // remove
          remove.apply(tags[i], [tags, i])
          oldItems.splice(i, 1)
        }

        // update the position attribute if it exists
        if (expr.pos) tag[expr.pos] = i

        // if the loop tags are not custom
        // we need to move all their custom tags into the right position
        if (!child && tag.tags) moveNestedTags.call(tag, i)

        // update the parent ref
        if (refAttr) {
          parent.refs[refAttr].push(isAnonymous ? tag.root : tag)
        }
      }

      if (!mustCreate) tag.update(item)

      // cache the original item to use it in the events bound to this node
      // and its children
      tag.__.item = item
      tag.__.parent = parent
    })

    // remove the redundant tags
    unmountRedundant(items, tags)

    // clone the items array
    oldItems = items.slice()

    root.insertBefore(frag, placeholder)
  }

  expr.unmount = function() {
    each(tags, function(t) { t.unmount() })
  }

  return expr
}<commit_msg>fixed: stupid ie9 issue<commit_after>import { isArray, isString } from './../common/util/check'
import { remAttr, getAttr, getOuterHTML, createDOMPlaceholder, safeInsert, createFrag } from './../common/util/dom'
import { each, contains, extend } from './../common/util/misc'
import { tmpl } from 'riot-tmpl'
import Tag from './tag'

import {
  T_STRING,
  T_OBJECT,
  __TAG_IMPL,
  CONDITIONAL_DIRECTIVE,
  LOOP_DIRECTIVE,
  LOOP_NO_REORDER_DIRECTIVE
} from './../common/global-variables'

import {
  moveChildTag,
  getTag,
  getTagName,
  getRefAttr,
  remRefAttr,
  arrayishAdd,
  arrayishRemove,
  makeVirtual,
  moveVirtual
} from './../common/util/tags'

/**
 * Convert the item looped into an object used to extend the child tag properties
 * @param   { Object } expr - object containing the keys used to extend the children tags
 * @param   { * } key - value to assign to the new object returned
 * @param   { * } val - value containing the position of the item in the array
 * @param   { Object } base - prototype object for the new item
 * @returns { Object } - new object containing the values of the original item
 *
 * The variables 'key' and 'val' are arbitrary.
 * They depend on the collection type looped (Array, Object)
 * and on the expression used on the each tag
 *
 */
function mkitem(expr, key, val, base) {
  var item = base ? Object.create(base) : {}
  item[expr.key] = key
  if (expr.pos) item[expr.pos] = val
  return item
}

/**
 * Unmount the redundant tags
 * @param   { Array } items - array containing the current items to loop
 * @param   { Array } tags - array containing all the children tags
 */
function unmountRedundant(items, tags) {
  var i = tags.length,
    j = items.length

  while (i > j) {
    i--
    remove.apply(tags[i], [tags, i])
  }
}

/**
 * Remove a child tag
 * @this Tag
 * @param   { Array } tags - tags collection
 * @param   { Number } i - index of the tag to remove
 */
function remove(tags, i) {
  tags.splice(i, 1)
  this.unmount()
  arrayishRemove(this.parent, this, this.__.tagName, true)
}

/**
 * Move the nested custom tags in non custom loop tags
 * @this Tag
 * @param   { Number } i - current position of the loop tag
 */
function moveNestedTags(i) {
  each(Object.keys(this.tags), (tagName) => {
    var tag = this.tags[tagName]
    if (isArray(tag))
      each(tag, function (t) {
        moveChildTag.apply(t, [tagName, i])
      })
    else
      moveChildTag.apply(tag, [tagName, i])
  })
}

/**
 * Move a child tag
 * @this Tag
 * @param   { HTMLElement } root - dom node containing all the loop children
 * @param   { Tag } nextTag - instance of the next tag preceding the one we want to move
 * @param   { Boolean } isVirtual - is it a virtual tag?
 */
function move(root, nextTag, isVirtual) {
  if (isVirtual)
    moveVirtual.apply(this, [root, nextTag])
  else
    safeInsert(root, this.root, nextTag.root)
}

/**
 * Insert and mount a child tag
 * @this Tag
 * @param   { HTMLElement } root - dom node containing all the loop children
 * @param   { Tag } nextTag - instance of the next tag preceding the one we want to insert
 * @param   { Boolean } isVirtual - is it a virtual tag?
 */
function insert(root, nextTag, isVirtual) {
  if (isVirtual)
    makeVirtual.apply(this, [root, nextTag])
  else
    safeInsert(root, this.root, nextTag.root)
}

/**
 * Append a new tag into the DOM
 * @this Tag
 * @param   { HTMLElement } root - dom node containing all the loop children
 * @param   { Boolean } isVirtual - is it a virtual tag?
 */
function append(root, isVirtual) {
  if (isVirtual)
    makeVirtual.call(this, root)
  else
    root.appendChild(this.root)
}

/**
 * Manage tags having the 'each'
 * @param   { HTMLElement } dom - DOM node we need to loop
 * @param   { Tag } parent - parent tag instance where the dom node is contained
 * @param   { String } expr - string contained in the 'each' attribute
 * @returns { Object } expression object for this each loop
 */
export default function _each(dom, parent, expr) {

  // remove the each property from the original tag
  remAttr(dom, LOOP_DIRECTIVE)

  var mustReorder = typeof getAttr(dom, LOOP_NO_REORDER_DIRECTIVE) !== T_STRING || remAttr(dom, LOOP_NO_REORDER_DIRECTIVE),
    tagName = getTagName(dom),
    impl = __TAG_IMPL[tagName] || { tmpl: getOuterHTML(dom) },
    parentNode = dom.parentNode,
    placeholder = createDOMPlaceholder(),
    child = getTag(dom),
    refExpr = getRefAttr(dom),
    ifExpr = getAttr(dom, CONDITIONAL_DIRECTIVE),
    tags = [],
    oldItems = [],
    hasKeys,
    isLoop = true,
    hasRefExpr = false,
    isAnonymous = !__TAG_IMPL[tagName],
    isVirtual = dom.tagName === 'VIRTUAL'

  // parse the each expression
  expr = tmpl.loopKeys(expr)
  expr.isLoop = true

  if (ifExpr) remAttr(dom, CONDITIONAL_DIRECTIVE)

  // check if the loop tag has a ref attribute
  if (refExpr) {
    // detect if the ref attribute is an expression
    hasRefExpr = tmpl.hasExpr(refExpr)
    remRefAttr(dom)
  }

  // insert a marked where the loop tags will be injected
  parentNode.insertBefore(placeholder, dom)
  parentNode.removeChild(dom)

  expr.update = function updateEach() {
    // get the new items collection
    var items = tmpl(expr.val, parent),
      frag = createFrag(),
      refAttr = refExpr,
      isObject = !isArray(items) && !isString(items),
      root = placeholder.parentNode

    // object loop. any changes cause full redraw
    if (isObject) {
      hasKeys = items || false
      items = hasKeys ?
        Object.keys(items).map(function (key) {
          return mkitem(expr, items[key], key)
        }) : []
    } else {
      hasKeys = false
    }

    if (ifExpr) {
      items = items.filter(function(item, i) {
        if (expr.key && !isObject)
          return !!tmpl(ifExpr, mkitem(expr, item, i, parent))

        return !!tmpl(ifExpr, extend(Object.create(parent), item))
      })
    }

    if (refAttr && hasRefExpr) {
      refAttr = tmpl(refExpr, parent)
    }

    // reset the parent ref
    if (refAttr) parent.refs[refAttr] = []

    // loop all the new items
    each(items, function(item, i) {
      // reorder only if the items are objects
      var
        doReorder = mustReorder && typeof item === T_OBJECT && !hasKeys,
        oldPos = oldItems.indexOf(item),
        isNew = !~oldPos,
        pos = !isNew && doReorder ? oldPos : i,
        // does a tag exist in this position?
        tag = tags[pos],
        mustAppend = i >= oldItems.length,
        mustCreate =  doReorder && isNew || !doReorder && !tag

      item = !hasKeys && expr.key ? mkitem(expr, item, i) : item

      // new tag
      if (mustCreate) {
        tag = new Tag(impl, {
          parent,
          isLoop,
          isAnonymous,
          root: dom.cloneNode(),
          item
        }, dom.innerHTML)

        // mount the tag
        tag.mount()

        if (mustAppend)
          append.apply(tag, [frag || root, isVirtual])
        else
          insert.apply(tag, [root, tags[i], isVirtual])

        if (!mustAppend) oldItems.splice(i, 0, item)
        tags.splice(i, 0, tag)
        if (child) arrayishAdd(parent.tags, tagName, tag, true)
      } else if (pos !== i && doReorder) {
        // move
        if (contains(items, oldItems[i])) {
          move.apply(tag, [root, tags[i], isVirtual])
          // move the old tag instance
          tags.splice(i, 0, tags.splice(pos, 1)[0])
          // move the old item
          oldItems.splice(i, 0, oldItems.splice(pos, 1)[0])
        } else { // remove
          remove.apply(tags[i], [tags, i])
          oldItems.splice(i, 1)
        }

        // update the position attribute if it exists
        if (expr.pos) tag[expr.pos] = i

        // if the loop tags are not custom
        // we need to move all their custom tags into the right position
        if (!child && tag.tags) moveNestedTags.call(tag, i)

        // update the parent ref
        if (refAttr) {
          parent.refs[refAttr].push(isAnonymous ? tag.root : tag)
        }
      }

      if (!mustCreate) tag.update(item)

      // cache the original item to use it in the events bound to this node
      // and its children
      tag.__.item = item
      tag.__.parent = parent
    })

    // remove the redundant tags
    unmountRedundant(items, tags)

    // clone the items array
    oldItems = items.slice()

    root.insertBefore(frag, placeholder)
  }

  expr.unmount = function() {
    each(tags, function(t) { t.unmount() })
  }

  return expr
}<|endoftext|>


<commit_before>YUI().use('*', function(Y) {
	window.Y = Y;
});

// Create Namespace
Ext.ns('Ext.test');
Ext.ns('Ext.test.view');<commit_msg>minor update<commit_after>YUI().use('*', function(Y) {
	window.Y = Y;
});

// Create Namespace
Ext.ns('Ext.test', 'Ext.test.view');<|endoftext|>


<commit_before>__DATA({
  model_: 'foam.lib.email.EMail',
  id: 'foam.test.EMail',
  from: 'Adam Van Ymeren',
  to: ['kgr@google.com'],
  body: 'Hello world!\n'
});
<commit_msg>Add missing @license headers<commit_after>/**
 * @license
 * Copyright 2015 Google Inc. All Rights Reserved.
 *
 * 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.
 */

__DATA({
  model_: 'foam.lib.email.EMail',
  id: 'foam.test.EMail',
  from: 'Adam Van Ymeren',
  to: ['kgr@google.com'],
  body: 'Hello world!\n'
});
<|endoftext|>


<commit_before>/**
 * Worker to handle counting and caching tasks performed when a match is inserted or parsed.
 * All operations in this worker should deal with ephemeral data (can be reconstructed from persistent data stores)
 **/
var constants = require('../constants');
var config = require('../config');
var redis = require('../store/redis');
var queue = require('../store/queue');
var queries = require('../store/queries');
var utility = require('../util/utility');
var benchmarks = require('../util/benchmarks');
var cQueue = queue.getQueue('cache');
var moment = require('moment');
var async = require('async');
var getMatchRating = queries.getMatchRating;
cQueue.process(10, processCache);
cQueue.on('completed', function(job)
{
    job.remove();
});

function processCache(job, cb)
{
    var match = job.data.payload;
    console.log('match: %s, %s', match.match_id, match.origin);
    async.parallel(
    {
        "updateRankings": function(cb)
        {
            if (match.origin === "scanner")
            {
                return updateRankings(match, cb);
            }
            else
            {
                return cb();
            }
        },
        "updateMatchRating": function(cb)
        {
            if (match.origin === "scanner")
            {
                return updateMatchRating(match, cb);
            }
            else
            {
                return cb();
            }
        },
        "incrCounts": function(cb)
        {
            try
            {
                if (match.origin === "scanner")
                {
                    incrCounts(match);
                }
                cb();
            }
            catch (e)
            {
                return cb(e);
            }
        },
        "updateBenchmarks": function(cb)
        {
            try
            {
                if (match.origin === "scanner")
                {
                    updateBenchmarks(match);
                }
                cb();
            }
            catch (e)
            {
                return cb(e);
            }
        }
    }, function(err)
    {
        if (err)
        {
            console.error(err);
        }
        return cb(err);
    });
}

function incrCounts(match)
{
    var expire = moment().add(1, 'week').startOf('week').format('X');
    //count match for telemetry
    redis.zadd("added_match", moment().format('X'), match.match_id);
    //increment picks
    var radiant = [];
    var dire = [];
    for (var i = 0; i < match.players.length; i++)
    {
        var p = match.players[i];
        if (p.hero_id === 0)
        {
            //exclude this match
            return;
        }
        if (utility.isRadiant(p))
        {
            radiant.push(p.hero_id);
        }
        else
        {
            dire.push(p.hero_id);
        }
    }
    //compute singles, dyads, triads, etc.
    for (var i = 1; i < 4; i++)
    {
        addToPickResults(k_combinations(radiant, i), i, match.radiant_win, match);
        addToPickResults(k_combinations(dire, i), i, !match.radiant_win, match);
    }
    redis.incr('picks_match_count');
    redis.expireat('picks_match_count', expire);

    function addToPickResults(groups, i, win, m)
    {
        groups.forEach(function(g)
        {
            //sort and join the g into a unique key
            g = g.sort(function(a, b)
            {
                return a - b;
            }).join(',');
            //redis.zadd('picks:' + i + ":" + g, moment().format('X'), match.match_id);
            redis.zincrby('picks_counts:' + i, 1, g);
            redis.expireat('picks_counts:' + i, expire);
            if (win)
            {
                //redis.zadd('picks_wins:' + i + ":" + g, moment().format('X'), match.match_id);
                redis.zincrby('picks_wins_counts:' + i, 1, g);
                redis.expireat('picks_wins_counts:' + i, expire);
            }
        });
    }
}

function k_combinations(arr, k)
{
    var i, j, combs, head, tailcombs;
    if (k > arr.length || k <= 0)
    {
        return [];
    }
    if (k === arr.length)
    {
        return [arr];
    }
    if (k == 1)
    {
        combs = [];
        for (i = 0; i < arr.length; i++)
        {
            combs.push([arr[i]]);
        }
        return combs;
    }
    // Assert {1 < k < arr.length}
    combs = [];
    for (i = 0; i < arr.length - k + 1; i++)
    {
        head = arr.slice(i, i + 1);
        //recursively get all combinations of the remaining array
        tailcombs = k_combinations(arr.slice(i + 1), k - 1);
        for (j = 0; j < tailcombs.length; j++)
        {
            combs.push(head.concat(tailcombs[j]));
        }
    }
    return combs;
}

function updateRankings(match, cb)
{
    getMatchRating(redis, match, function(err, avg)
    {
        if (err)
        {
            return cb(err);
        }
        var score = (avg && !Number.isNaN(avg)) ? Math.pow(avg, 5) / 1000000000000 : undefined;
        async.each(match.players, function(player, cb)
        {
            if (!player.account_id || player.account_id === constants.anonymous_account_id)
            {
                return cb();
            }
            player.radiant_win = match.radiant_win;
            var start = moment().startOf('quarter').format('X');
            var expire = moment().add(1, 'quarter').startOf('quarter').format('X');
            var win = Number(utility.isRadiant(player) === player.radiant_win);
            if (score && utility.isSignificant(match))
            {
                console.log(match.match_id, score);
                redis.zincrby(['hero_rankings', start, player.hero_id].join(':'), win ? score : 0, player.account_id);
                redis.expireat(['hero_rankings', start, player.hero_id].join(':'), expire);
            }
            cb();
        }, cb);
    });
}

function updateBenchmarks(match)
{
    for (var i = 0; i < match.players.length; i++)
    {
        var p = match.players[i];
        if (!p.hero_id)
        {
            //exclude this match
            return;
        }
        for (var key in benchmarks)
        {
            var metric = benchmarks[key](match, p);
            if (metric !== undefined && metric !== null && !Number.isNaN(metric))
            {
                var rkey = ["benchmarks", utility.getStartOfBlockHours(config.BENCHMARK_RETENTION_HOURS, 0), key, p.hero_id].join(':');
                redis.zadd(rkey, metric, match.match_id);
                //expire at time two blocks later (after prev/current cycle)
                redis.expireat(rkey, utility.getStartOfBlockHours(config.BENCHMARK_RETENTION_HOURS, 2));
            }
        }
    }
}

function updateMatchRating(match, cb)
{
    getMatchRating(redis, match, function(err, avg)
    {
        if (avg && !Number.isNaN(avg))
        {
            var rkey = 'match_ratings:' + utility.getStartOfBlockHours(config.MATCH_RATING_RETENTION_HOURS, 0);
            redis.zadd(rkey, avg, match.match_id);
            redis.expireat(rkey, utility.getStartOfBlockHours(config.MATCH_RATING_RETENTION_HOURS, 2));
            //for each player
            match.players.forEach(function(player)
            {
                if (player.account_id && player.account_id !== constants.anonymous_account_id)
                {
                    //push into list, limit elements
                    redis.lpush('mmr_estimates:' + player.account_id, avg);
                    redis.ltrim('mmr_estimates:' + player.account_id, 0, 24);
                }
            });
            cb();
        }
        else
        {
            return cb(err);
        }
    });
}<commit_msg>shorten mmr estimate to 20 matches<commit_after>/**
 * Worker to handle counting and caching tasks performed when a match is inserted or parsed.
 * All operations in this worker should deal with ephemeral data (can be reconstructed from persistent data stores)
 **/
var constants = require('../constants');
var config = require('../config');
var redis = require('../store/redis');
var queue = require('../store/queue');
var queries = require('../store/queries');
var utility = require('../util/utility');
var benchmarks = require('../util/benchmarks');
var cQueue = queue.getQueue('cache');
var moment = require('moment');
var async = require('async');
var getMatchRating = queries.getMatchRating;
cQueue.process(10, processCache);
cQueue.on('completed', function(job)
{
    job.remove();
});

function processCache(job, cb)
{
    var match = job.data.payload;
    console.log('match: %s, %s', match.match_id, match.origin);
    async.parallel(
    {
        "updateRankings": function(cb)
        {
            if (match.origin === "scanner")
            {
                return updateRankings(match, cb);
            }
            else
            {
                return cb();
            }
        },
        "updateMatchRating": function(cb)
        {
            if (match.origin === "scanner")
            {
                return updateMatchRating(match, cb);
            }
            else
            {
                return cb();
            }
        },
        "incrCounts": function(cb)
        {
            try
            {
                if (match.origin === "scanner")
                {
                    incrCounts(match);
                }
                cb();
            }
            catch (e)
            {
                return cb(e);
            }
        },
        "updateBenchmarks": function(cb)
        {
            try
            {
                if (match.origin === "scanner")
                {
                    updateBenchmarks(match);
                }
                cb();
            }
            catch (e)
            {
                return cb(e);
            }
        }
    }, function(err)
    {
        if (err)
        {
            console.error(err);
        }
        return cb(err);
    });
}

function incrCounts(match)
{
    var expire = moment().add(1, 'week').startOf('week').format('X');
    //count match for telemetry
    redis.zadd("added_match", moment().format('X'), match.match_id);
    //increment picks
    var radiant = [];
    var dire = [];
    for (var i = 0; i < match.players.length; i++)
    {
        var p = match.players[i];
        if (p.hero_id === 0)
        {
            //exclude this match
            return;
        }
        if (utility.isRadiant(p))
        {
            radiant.push(p.hero_id);
        }
        else
        {
            dire.push(p.hero_id);
        }
    }
    //compute singles, dyads, triads, etc.
    for (var i = 1; i < 4; i++)
    {
        addToPickResults(k_combinations(radiant, i), i, match.radiant_win, match);
        addToPickResults(k_combinations(dire, i), i, !match.radiant_win, match);
    }
    redis.incr('picks_match_count');
    redis.expireat('picks_match_count', expire);

    function addToPickResults(groups, i, win, m)
    {
        groups.forEach(function(g)
        {
            //sort and join the g into a unique key
            g = g.sort(function(a, b)
            {
                return a - b;
            }).join(',');
            //redis.zadd('picks:' + i + ":" + g, moment().format('X'), match.match_id);
            redis.zincrby('picks_counts:' + i, 1, g);
            redis.expireat('picks_counts:' + i, expire);
            if (win)
            {
                //redis.zadd('picks_wins:' + i + ":" + g, moment().format('X'), match.match_id);
                redis.zincrby('picks_wins_counts:' + i, 1, g);
                redis.expireat('picks_wins_counts:' + i, expire);
            }
        });
    }
}

function k_combinations(arr, k)
{
    var i, j, combs, head, tailcombs;
    if (k > arr.length || k <= 0)
    {
        return [];
    }
    if (k === arr.length)
    {
        return [arr];
    }
    if (k == 1)
    {
        combs = [];
        for (i = 0; i < arr.length; i++)
        {
            combs.push([arr[i]]);
        }
        return combs;
    }
    // Assert {1 < k < arr.length}
    combs = [];
    for (i = 0; i < arr.length - k + 1; i++)
    {
        head = arr.slice(i, i + 1);
        //recursively get all combinations of the remaining array
        tailcombs = k_combinations(arr.slice(i + 1), k - 1);
        for (j = 0; j < tailcombs.length; j++)
        {
            combs.push(head.concat(tailcombs[j]));
        }
    }
    return combs;
}

function updateRankings(match, cb)
{
    getMatchRating(redis, match, function(err, avg)
    {
        if (err)
        {
            return cb(err);
        }
        var score = (avg && !Number.isNaN(avg)) ? Math.pow(avg, 5) / 1000000000000 : undefined;
        async.each(match.players, function(player, cb)
        {
            if (!player.account_id || player.account_id === constants.anonymous_account_id)
            {
                return cb();
            }
            player.radiant_win = match.radiant_win;
            var start = moment().startOf('quarter').format('X');
            var expire = moment().add(1, 'quarter').startOf('quarter').format('X');
            var win = Number(utility.isRadiant(player) === player.radiant_win);
            if (score && utility.isSignificant(match))
            {
                console.log(match.match_id, score);
                redis.zincrby(['hero_rankings', start, player.hero_id].join(':'), win ? score : 0, player.account_id);
                redis.expireat(['hero_rankings', start, player.hero_id].join(':'), expire);
            }
            cb();
        }, cb);
    });
}

function updateBenchmarks(match)
{
    for (var i = 0; i < match.players.length; i++)
    {
        var p = match.players[i];
        if (!p.hero_id)
        {
            //exclude this match
            return;
        }
        for (var key in benchmarks)
        {
            var metric = benchmarks[key](match, p);
            if (metric !== undefined && metric !== null && !Number.isNaN(metric))
            {
                var rkey = ["benchmarks", utility.getStartOfBlockHours(config.BENCHMARK_RETENTION_HOURS, 0), key, p.hero_id].join(':');
                redis.zadd(rkey, metric, match.match_id);
                //expire at time two blocks later (after prev/current cycle)
                redis.expireat(rkey, utility.getStartOfBlockHours(config.BENCHMARK_RETENTION_HOURS, 2));
            }
        }
    }
}

function updateMatchRating(match, cb)
{
    getMatchRating(redis, match, function(err, avg)
    {
        if (avg && !Number.isNaN(avg))
        {
            var rkey = 'match_ratings:' + utility.getStartOfBlockHours(config.MATCH_RATING_RETENTION_HOURS, 0);
            redis.zadd(rkey, avg, match.match_id);
            redis.expireat(rkey, utility.getStartOfBlockHours(config.MATCH_RATING_RETENTION_HOURS, 2));
            //for each player
            match.players.forEach(function(player)
            {
                if (player.account_id && player.account_id !== constants.anonymous_account_id)
                {
                    //push into list, limit elements
                    redis.lpush('mmr_estimates:' + player.account_id, avg);
                    redis.ltrim('mmr_estimates:' + player.account_id, 0, 19);
                }
            });
            cb();
        }
        else
        {
            return cb(err);
        }
    });
}
<|endoftext|>


<commit_before>
var FrameSheetModel = (function() {

    var inst;
    var frames = [];
    var width;
    var height;

    var createEmptyFrame_ = function() {
    	var emptyFrame = new Array(width);
		for (var columnIndex=0; columnIndex < width; columnIndex++) {
			emptyFrame[columnIndex] = new Array(height);
    	}
        return emptyFrame;
    };

	return {
		validate: function() {
			return true; // I'm always right dude
		},

		// Could be used to pass around model using long GET param (good enough for simple models) and
		// do some temporary locastorage
		serialize: function() {
			return JSON.stringify(frames);
		},

		/**
		 * Load a framesheet from a string that might have been persisted in db / localstorage
		 * Overrides existing frames.
		 * @param {String} serialized
		 */
		deserializeFramesheet : function (serialized) {
			try {
				frames = eval(serialized);
			} catch (e) {
				throw "Could not load serialized framesheet." + e.getMessage()
			}
		},

		addEmptyFrame: function() {
			frames.push(createEmptyFrame_());
		},

		getFrameCount: function() {
			return frames.length;
		},

		getFrameByIndex: function(index) {
			if (isNaN(index)) {
				throw "Bad argument value for getFrameByIndex method: <" + index + ">"
			} else if (index < 0 || index > frames.length) {
				throw "Out of bound index for frameSheet object."
			}

			return frames[index];
		},

		removeFrameByIndex: function(index) {
		  if(index < 0 || index > inst.getFrameCount()) {
		  	throw "Bad index value for removeFrameByIndex.";
		  }
		  frames.splice(index, 1);
		},

		duplicateFrameByIndex: function(frameToDuplicateIndex) {
			var frame = inst.getFrameByIndex(frameToDuplicateIndex);
			var clonedFrame = [];
			for(var i=0, l=frame.length; i<l; i++) {
				clonedFrame.push(frame[i].slice(0));
			}
			frames.splice(frameToDuplicateIndex + 1, 0, clonedFrame);
		},

		getInstance: function(width_, height_) {

			if (isNaN(width_) || isNaN(height_)) {
				throw "Bad FrameSheetModel initialization in getInstance method.";
			}

			inst = this;

			width = width_;
			height = height_;

			return inst;
		}
	}
})();<commit_msg>Update js/frameSheetModel.js<commit_after>var FrameSheetModel = (function() {

    var inst;
    var frames = [];
    var width;
    var height;

    var createEmptyFrame_ = function() {
    	var emptyFrame = new Array(width);
		for (var columnIndex=0; columnIndex < width; columnIndex++) {
			emptyFrame[columnIndex] = new Array(height);
    	}
        return emptyFrame;
    };

	return {
		validate: function() {
			return true; // I'm always right dude
		},

		// Could be used to pass around model using long GET param (good enough for simple models) and
		// do some temporary locastorage
		serialize: function() {
			return JSON.stringify(frames);
		},

		/**
		 * Load a framesheet from a string that might have been persisted in db / localstorage
		 * Overrides existing frames.
		 * @param {String} serialized
		 */
		deserialize : function (serialized) {
			try {
				frames = eval(serialized);
			} catch (e) {
				throw "Could not load serialized framesheet." + e.getMessage()
			}
		},

		addEmptyFrame: function() {
			frames.push(createEmptyFrame_());
		},

		getFrameCount: function() {
			return frames.length;
		},

		getFrameByIndex: function(index) {
			if (isNaN(index)) {
				throw "Bad argument value for getFrameByIndex method: <" + index + ">"
			} else if (index < 0 || index > frames.length) {
				throw "Out of bound index for frameSheet object."
			}

			return frames[index];
		},

		removeFrameByIndex: function(index) {
		  if(index < 0 || index > inst.getFrameCount()) {
		  	throw "Bad index value for removeFrameByIndex.";
		  }
		  frames.splice(index, 1);
		},

		duplicateFrameByIndex: function(frameToDuplicateIndex) {
			var frame = inst.getFrameByIndex(frameToDuplicateIndex);
			var clonedFrame = [];
			for(var i=0, l=frame.length; i<l; i++) {
				clonedFrame.push(frame[i].slice(0));
			}
			frames.splice(frameToDuplicateIndex + 1, 0, clonedFrame);
		},

		getInstance: function(width_, height_) {

			if (isNaN(width_) || isNaN(height_)) {
				throw "Bad FrameSheetModel initialization in getInstance method.";
			}

			inst = this;

			width = width_;
			height = height_;

			return inst;
		}
	}
})();<|endoftext|>