<commit_before>// The Font object

'use strict';

var path = require('./path');
var sfnt = require('./tables/sfnt');
var encoding = require('./encoding');
var glyphset = require('./glyphset');

// A Font represents a loaded OpenType font file.
// It contains a set of glyphs and methods to draw text on a drawing context,
// or to get a path representing the text.
function Font(options) {
    options = options || {};

    // OS X will complain if the names are empty, so we put a single space everywhere by default.
    this.names = {
        fontFamily: {en: options.familyName || ' '},
        fontSubfamily: {en: options.styleName || ' '},
        designer: {en: options.designer || ' '},
        designerURL: {en: options.designerURL || ' '},
        manufacturer: {en: options.manufacturer || ' '},
        manufacturerURL: {en: options.manufacturerURL || ' '},
        license: {en: options.license || ' '},
        licenseURL: {en: options.licenseURL || ' '},
        version: {en: options.version || 'Version 0.1'},
        description: {en: options.description || ' '},
        copyright: {en: options.copyright || ' '},
        trademark: {en: options.trademark || ' '}
    };
    this.unitsPerEm = options.unitsPerEm || 1000;
    this.ascender = options.ascender;
    this.descender = options.descender;
    this.supported = true; // Deprecated: parseBuffer will throw an error if font is not supported.
    this.glyphs = new glyphset.GlyphSet(this, options.glyphs || []);
    this.encoding = new encoding.DefaultEncoding(this);
    this.tables = {};
}

// Check if the font has a glyph for the given character.
Font.prototype.hasChar = function(c) {
    return this.encoding.charToGlyphIndex(c) !== null;
};

// Convert the given character to a single glyph index.
// Note that this function assumes that there is a one-to-one mapping between
// the given character and a glyph; for complex scripts this might not be the case.
Font.prototype.charToGlyphIndex = function(s) {
    return this.encoding.charToGlyphIndex(s);
};

// Convert the given character to a single Glyph object.
// Note that this function assumes that there is a one-to-one mapping between
// the given character and a glyph; for complex scripts this might not be the case.
Font.prototype.charToGlyph = function(c) {
    var glyphIndex = this.charToGlyphIndex(c);
    var glyph = this.glyphs.get(glyphIndex);
    if (!glyph) {
        // .notdef
        glyph = this.glyphs.get(0);
    }

    return glyph;
};

// Convert the given text to a list of Glyph objects.
// Note that there is no strict one-to-one mapping between characters and
// glyphs, so the list of returned glyphs can be larger or smaller than the
// length of the given string.
Font.prototype.stringToGlyphs = function(s) {
    var glyphs = [];
    for (var i = 0; i < s.length; i += 1) {
        var c = s[i];
        glyphs.push(this.charToGlyph(c));
    }

    return glyphs;
};

Font.prototype.nameToGlyphIndex = function(name) {
    return this.glyphNames.nameToGlyphIndex(name);
};

Font.prototype.nameToGlyph = function(name) {
    var glyphIndex = this.nametoGlyphIndex(name);
    var glyph = this.glyphs.get(glyphIndex);
    if (!glyph) {
        // .notdef
        glyph = this.glyphs.get(0);
    }

    return glyph;
};

Font.prototype.glyphIndexToName = function(gid) {
    if (!this.glyphNames.glyphIndexToName) {
        return '';
    }

    return this.glyphNames.glyphIndexToName(gid);
};

// Retrieve the value of the kerning pair between the left glyph (or its index)
// and the right glyph (or its index). If no kerning pair is found, return 0.
// The kerning value gets added to the advance width when calculating the spacing
// between glyphs.
Font.prototype.getKerningValue = function(leftGlyph, rightGlyph) {
    leftGlyph = leftGlyph.index || leftGlyph;
    rightGlyph = rightGlyph.index || rightGlyph;
    var gposKerning = this.getGposKerningValue;
    return gposKerning ? gposKerning(leftGlyph, rightGlyph) :
        (this.kerningPairs[leftGlyph + ',' + rightGlyph] || 0);
};

// Helper function that invokes the given callback for each glyph in the given text.
// The callback gets `(glyph, x, y, fontSize, options)`.
Font.prototype.forEachGlyph = function(text, x, y, fontSize, options, callback) {
    x = x !== undefined ? x : 0;
    y = y !== undefined ? y : 0;
    fontSize = fontSize !== undefined ? fontSize : 72;
    options = options || {};
    var kerning = options.kerning === undefined ? true : options.kerning;
    var fontScale = 1 / this.unitsPerEm * fontSize;
    var glyphs = this.stringToGlyphs(text);
    for (var i = 0; i < glyphs.length; i += 1) {
        var glyph = glyphs[i];
        callback(glyph, x, y, fontSize, options);
        if (glyph.advanceWidth) {
            x += glyph.advanceWidth * fontScale;
        }

        if (kerning && i < glyphs.length - 1) {
            var kerningValue = this.getKerningValue(glyph, glyphs[i + 1]);
            x += kerningValue * fontScale;
        }
    }
};

// Create a Path object that represents the given text.
//
// text - The text to create.
// x - Horizontal position of the beginning of the text. (default: 0)
// y - Vertical position of the *baseline* of the text. (default: 0)
// fontSize - Font size in pixels. We scale the glyph units by `1 / unitsPerEm * fontSize`. (default: 72)
// Options is an optional object that contains:
// - kerning - Whether to take kerning information into account. (default: true)
//
// Returns a Path object.
Font.prototype.getPath = function(text, x, y, fontSize, options) {
    var fullPath = new path.Path();
    this.forEachGlyph(text, x, y, fontSize, options, function(glyph, gX, gY, gFontSize) {
        var glyphPath = glyph.getPath(gX, gY, gFontSize);
        fullPath.extend(glyphPath);
    });

    return fullPath;
};

// Draw the text on the given drawing context.
//
// ctx - A 2D drawing context, like Canvas.
// text - The text to create.
// x - Horizontal position of the beginning of the text. (default: 0)
// y - Vertical position of the *baseline* of the text. (default: 0)
// fontSize - Font size in pixels. We scale the glyph units by `1 / unitsPerEm * fontSize`. (default: 72)
// Options is an optional object that contains:
// - kerning - Whether to take kerning information into account. (default: true)
Font.prototype.draw = function(ctx, text, x, y, fontSize, options) {
    this.getPath(text, x, y, fontSize, options).draw(ctx);
};

// Draw the points of all glyphs in the text.
// On-curve points will be drawn in blue, off-curve points will be drawn in red.
//
// ctx - A 2D drawing context, like Canvas.
// text - The text to create.
// x - Horizontal position of the beginning of the text. (default: 0)
// y - Vertical position of the *baseline* of the text. (default: 0)
// fontSize - Font size in pixels. We scale the glyph units by `1 / unitsPerEm * fontSize`. (default: 72)
// Options is an optional object that contains:
// - kerning - Whether to take kerning information into account. (default: true)
Font.prototype.drawPoints = function(ctx, text, x, y, fontSize, options) {
    this.forEachGlyph(text, x, y, fontSize, options, function(glyph, gX, gY, gFontSize) {
        glyph.drawPoints(ctx, gX, gY, gFontSize);
    });
};

// Draw lines indicating important font measurements for all glyphs in the text.
// Black lines indicate the origin of the coordinate system (point 0,0).
// Blue lines indicate the glyph bounding box.
// Green line indicates the advance width of the glyph.
//
// ctx - A 2D drawing context, like Canvas.
// text - The text to create.
// x - Horizontal position of the beginning of the text. (default: 0)
// y - Vertical position of the *baseline* of the text. (default: 0)
// fontSize - Font size in pixels. We scale the glyph units by `1 / unitsPerEm * fontSize`. (default: 72)
// Options is an optional object that contains:
// - kerning - Whether to take kerning information into account. (default: true)
Font.prototype.drawMetrics = function(ctx, text, x, y, fontSize, options) {
    this.forEachGlyph(text, x, y, fontSize, options, function(glyph, gX, gY, gFontSize) {
        glyph.drawMetrics(ctx, gX, gY, gFontSize);
    });
};

Font.prototype.getEnglishName = function(name) {
    var translations = this.names[name];
    if (translations) {
        return translations.en;
    }
};

// Validate
Font.prototype.validate = function() {
    var warnings = [];
    var _this = this;

    function assert(predicate, message) {
        if (!predicate) {
            warnings.push(message);
        }
    }

    function assertNamePresent(name) {
        var englishName = _this.getEnglishName(name);
        assert(englishName && englishName.trim().length > 0,
               'No English ' + name + ' specified.');
    }

    // Identification information
    assertNamePresent('fontFamily');
    assertNamePresent('weightName');
    assertNamePresent('manufacturer');
    assertNamePresent('copyright');
    assertNamePresent('version');

    // Dimension information
    assert(this.unitsPerEm > 0, 'No unitsPerEm specified.');
};

// Convert the font object to a SFNT data structure.
// This structure contains all the necessary tables and metadata to create a binary OTF file.
Font.prototype.toTables = function() {
    return sfnt.fontToTable(this);
};

Font.prototype.toBuffer = function() {
    var sfntTable = this.toTables();
    var bytes = sfntTable.encode();
    var buffer = new ArrayBuffer(bytes.length);
    var intArray = new Uint8Array(buffer);
    for (var i = 0; i < bytes.length; i++) {
        intArray[i] = bytes[i];
    }

    return buffer;
};

// Initiate a download of the OpenType font.
Font.prototype.download = function() {
    var familyName = this.getEnglishName('fontFamily');
    var styleName = this.getEnglishName('fontSubfamily');
    var fileName = familyName.replace(/\s/g, '') + '-' + styleName + '.otf';
    var buffer = this.toBuffer();

    window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem;
    window.requestFileSystem(window.TEMPORARY, buffer.byteLength, function(fs) {
        fs.root.getFile(fileName, {create: true}, function(fileEntry) {
            fileEntry.createWriter(function(writer) {
                var dataView = new DataView(buffer);
                var blob = new Blob([dataView], {type: 'font/opentype'});
                writer.write(blob);

                writer.addEventListener('writeend', function() {
                    // Navigating to the file will download it.
                    location.href = fileEntry.toURL();
                }, false);
            });
        });
    },

    function(err) {
        throw err;
    });
};

exports.Font = Font;
<commit_msg>Added: font.getPaths, which creates an array of Path objects that represent the glyps of a given text<commit_after>// The Font object

'use strict';

var path = require('./path');
var sfnt = require('./tables/sfnt');
var encoding = require('./encoding');
var glyphset = require('./glyphset');

// A Font represents a loaded OpenType font file.
// It contains a set of glyphs and methods to draw text on a drawing context,
// or to get a path representing the text.
function Font(options) {
    options = options || {};

    // OS X will complain if the names are empty, so we put a single space everywhere by default.
    this.names = {
        fontFamily: {en: options.familyName || ' '},
        fontSubfamily: {en: options.styleName || ' '},
        designer: {en: options.designer || ' '},
        designerURL: {en: options.designerURL || ' '},
        manufacturer: {en: options.manufacturer || ' '},
        manufacturerURL: {en: options.manufacturerURL || ' '},
        license: {en: options.license || ' '},
        licenseURL: {en: options.licenseURL || ' '},
        version: {en: options.version || 'Version 0.1'},
        description: {en: options.description || ' '},
        copyright: {en: options.copyright || ' '},
        trademark: {en: options.trademark || ' '}
    };
    this.unitsPerEm = options.unitsPerEm || 1000;
    this.ascender = options.ascender;
    this.descender = options.descender;
    this.supported = true; // Deprecated: parseBuffer will throw an error if font is not supported.
    this.glyphs = new glyphset.GlyphSet(this, options.glyphs || []);
    this.encoding = new encoding.DefaultEncoding(this);
    this.tables = {};
}

// Check if the font has a glyph for the given character.
Font.prototype.hasChar = function(c) {
    return this.encoding.charToGlyphIndex(c) !== null;
};

// Convert the given character to a single glyph index.
// Note that this function assumes that there is a one-to-one mapping between
// the given character and a glyph; for complex scripts this might not be the case.
Font.prototype.charToGlyphIndex = function(s) {
    return this.encoding.charToGlyphIndex(s);
};

// Convert the given character to a single Glyph object.
// Note that this function assumes that there is a one-to-one mapping between
// the given character and a glyph; for complex scripts this might not be the case.
Font.prototype.charToGlyph = function(c) {
    var glyphIndex = this.charToGlyphIndex(c);
    var glyph = this.glyphs.get(glyphIndex);
    if (!glyph) {
        // .notdef
        glyph = this.glyphs.get(0);
    }

    return glyph;
};

// Convert the given text to a list of Glyph objects.
// Note that there is no strict one-to-one mapping between characters and
// glyphs, so the list of returned glyphs can be larger or smaller than the
// length of the given string.
Font.prototype.stringToGlyphs = function(s) {
    var glyphs = [];
    for (var i = 0; i < s.length; i += 1) {
        var c = s[i];
        glyphs.push(this.charToGlyph(c));
    }

    return glyphs;
};

Font.prototype.nameToGlyphIndex = function(name) {
    return this.glyphNames.nameToGlyphIndex(name);
};

Font.prototype.nameToGlyph = function(name) {
    var glyphIndex = this.nametoGlyphIndex(name);
    var glyph = this.glyphs.get(glyphIndex);
    if (!glyph) {
        // .notdef
        glyph = this.glyphs.get(0);
    }

    return glyph;
};

Font.prototype.glyphIndexToName = function(gid) {
    if (!this.glyphNames.glyphIndexToName) {
        return '';
    }

    return this.glyphNames.glyphIndexToName(gid);
};

// Retrieve the value of the kerning pair between the left glyph (or its index)
// and the right glyph (or its index). If no kerning pair is found, return 0.
// The kerning value gets added to the advance width when calculating the spacing
// between glyphs.
Font.prototype.getKerningValue = function(leftGlyph, rightGlyph) {
    leftGlyph = leftGlyph.index || leftGlyph;
    rightGlyph = rightGlyph.index || rightGlyph;
    var gposKerning = this.getGposKerningValue;
    return gposKerning ? gposKerning(leftGlyph, rightGlyph) :
        (this.kerningPairs[leftGlyph + ',' + rightGlyph] || 0);
};

// Helper function that invokes the given callback for each glyph in the given text.
// The callback gets `(glyph, x, y, fontSize, options)`.
Font.prototype.forEachGlyph = function(text, x, y, fontSize, options, callback) {
    x = x !== undefined ? x : 0;
    y = y !== undefined ? y : 0;
    fontSize = fontSize !== undefined ? fontSize : 72;
    options = options || {};
    var kerning = options.kerning === undefined ? true : options.kerning;
    var fontScale = 1 / this.unitsPerEm * fontSize;
    var glyphs = this.stringToGlyphs(text);
    for (var i = 0; i < glyphs.length; i += 1) {
        var glyph = glyphs[i];
        callback(glyph, x, y, fontSize, options);
        if (glyph.advanceWidth) {
            x += glyph.advanceWidth * fontScale;
        }

        if (kerning && i < glyphs.length - 1) {
            var kerningValue = this.getKerningValue(glyph, glyphs[i + 1]);
            x += kerningValue * fontScale;
        }
    }
};

// Create a Path object that represents the given text.
//
// text - The text to create.
// x - Horizontal position of the beginning of the text. (default: 0)
// y - Vertical position of the *baseline* of the text. (default: 0)
// fontSize - Font size in pixels. We scale the glyph units by `1 / unitsPerEm * fontSize`. (default: 72)
// Options is an optional object that contains:
// - kerning - Whether to take kerning information into account. (default: true)
//
// Returns a Path object.
Font.prototype.getPath = function(text, x, y, fontSize, options) {
    var fullPath = new path.Path();
    this.forEachGlyph(text, x, y, fontSize, options, function(glyph, gX, gY, gFontSize) {
        var glyphPath = glyph.getPath(gX, gY, gFontSize);
        fullPath.extend(glyphPath);
    });

    return fullPath;
};

// Create an array of Path objects that represent the glyps of a given text.
//
// text - The text to create.
// x - Horizontal position of the beginning of the text. (default: 0)
// y - Vertical position of the *baseline* of the text. (default: 0)
// fontSize - Font size in pixels. We scale the glyph units by `1 / unitsPerEm * fontSize`. (default: 72)
// Options is an optional object that contains:
// - kerning - Whether to take kerning information into account. (default: true)
//
// Returns an array of Path objects.
Font.prototype.getPaths = function(text, x, y, fontSize, options) {
    var glyphPaths = [];
    this.forEachGlyph(text, x, y, fontSize, options, function(glyph, gX, gY, gFontSize) {
        var glyphPath = glyph.getPath(gX, gY, gFontSize);
        glyphPaths.push(glyphPath);
    });

    return glyphPaths;
};

// Draw the text on the given drawing context.
//
// ctx - A 2D drawing context, like Canvas.
// text - The text to create.
// x - Horizontal position of the beginning of the text. (default: 0)
// y - Vertical position of the *baseline* of the text. (default: 0)
// fontSize - Font size in pixels. We scale the glyph units by `1 / unitsPerEm * fontSize`. (default: 72)
// Options is an optional object that contains:
// - kerning - Whether to take kerning information into account. (default: true)
Font.prototype.draw = function(ctx, text, x, y, fontSize, options) {
    this.getPath(text, x, y, fontSize, options).draw(ctx);
};

// Draw the points of all glyphs in the text.
// On-curve points will be drawn in blue, off-curve points will be drawn in red.
//
// ctx - A 2D drawing context, like Canvas.
// text - The text to create.
// x - Horizontal position of the beginning of the text. (default: 0)
// y - Vertical position of the *baseline* of the text. (default: 0)
// fontSize - Font size in pixels. We scale the glyph units by `1 / unitsPerEm * fontSize`. (default: 72)
// Options is an optional object that contains:
// - kerning - Whether to take kerning information into account. (default: true)
Font.prototype.drawPoints = function(ctx, text, x, y, fontSize, options) {
    this.forEachGlyph(text, x, y, fontSize, options, function(glyph, gX, gY, gFontSize) {
        glyph.drawPoints(ctx, gX, gY, gFontSize);
    });
};

// Draw lines indicating important font measurements for all glyphs in the text.
// Black lines indicate the origin of the coordinate system (point 0,0).
// Blue lines indicate the glyph bounding box.
// Green line indicates the advance width of the glyph.
//
// ctx - A 2D drawing context, like Canvas.
// text - The text to create.
// x - Horizontal position of the beginning of the text. (default: 0)
// y - Vertical position of the *baseline* of the text. (default: 0)
// fontSize - Font size in pixels. We scale the glyph units by `1 / unitsPerEm * fontSize`. (default: 72)
// Options is an optional object that contains:
// - kerning - Whether to take kerning information into account. (default: true)
Font.prototype.drawMetrics = function(ctx, text, x, y, fontSize, options) {
    this.forEachGlyph(text, x, y, fontSize, options, function(glyph, gX, gY, gFontSize) {
        glyph.drawMetrics(ctx, gX, gY, gFontSize);
    });
};

Font.prototype.getEnglishName = function(name) {
    var translations = this.names[name];
    if (translations) {
        return translations.en;
    }
};

// Validate
Font.prototype.validate = function() {
    var warnings = [];
    var _this = this;

    function assert(predicate, message) {
        if (!predicate) {
            warnings.push(message);
        }
    }

    function assertNamePresent(name) {
        var englishName = _this.getEnglishName(name);
        assert(englishName && englishName.trim().length > 0,
               'No English ' + name + ' specified.');
    }

    // Identification information
    assertNamePresent('fontFamily');
    assertNamePresent('weightName');
    assertNamePresent('manufacturer');
    assertNamePresent('copyright');
    assertNamePresent('version');

    // Dimension information
    assert(this.unitsPerEm > 0, 'No unitsPerEm specified.');
};

// Convert the font object to a SFNT data structure.
// This structure contains all the necessary tables and metadata to create a binary OTF file.
Font.prototype.toTables = function() {
    return sfnt.fontToTable(this);
};

Font.prototype.toBuffer = function() {
    var sfntTable = this.toTables();
    var bytes = sfntTable.encode();
    var buffer = new ArrayBuffer(bytes.length);
    var intArray = new Uint8Array(buffer);
    for (var i = 0; i < bytes.length; i++) {
        intArray[i] = bytes[i];
    }

    return buffer;
};

// Initiate a download of the OpenType font.
Font.prototype.download = function() {
    var familyName = this.getEnglishName('fontFamily');
    var styleName = this.getEnglishName('fontSubfamily');
    var fileName = familyName.replace(/\s/g, '') + '-' + styleName + '.otf';
    var buffer = this.toBuffer();

    window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem;
    window.requestFileSystem(window.TEMPORARY, buffer.byteLength, function(fs) {
        fs.root.getFile(fileName, {create: true}, function(fileEntry) {
            fileEntry.createWriter(function(writer) {
                var dataView = new DataView(buffer);
                var blob = new Blob([dataView], {type: 'font/opentype'});
                writer.write(blob);

                writer.addEventListener('writeend', function() {
                    // Navigating to the file will download it.
                    location.href = fileEntry.toURL();
                }, false);
            });
        });
    },

    function(err) {
        throw err;
    });
};

exports.Font = Font;
<|endoftext|>


<commit_before>/**
 * User: Martin Martimeo
 * Date: 13.08.13
 * Time: 18:30
 *
 * Extension to backbone-forms
 */

require(["jquery", "underscore", "backbone", "backbone-forms"],function ($, _, Backbone) {
    var self = this.Tornado || {};
    var Tornado = this.Tornado = self;

    Tornado.BackboneForm = Backbone.View.extend({

        initialize: function () {

            // Set Model
            if (this.options.model) {
                if (_.isString(this.options.model)) {
                    this.model = this.options.model = new window[this.options.model]();
                } else {
                    this.model = this.options.model;
                }
                if (_.isObject(this.options.value)) {
                    this.model.set(this.options.value);
                }
            }

            // Create Form
            this.form = new Backbone.Form(this.options);
            this.listenTo(this.form, 'all', this.handleFormEvent);
        },

        handleFormEvent: function (event, form, node) {
            this.trigger(event, node || form || this);

            // Retrigger event under tb:* namespace
            var args = event.split(":");
            if (args.length > 1) {
                this.trigger("tb:" + args[1], form, node);
                this.trigger("tb:" + args[1] + ":" + args[0], form, node);
            }
        },

        render: function () {
            var self = this.form,
                $form = this.$el,
                fields = this.form.fields;

            //Render standalone editors
            $form.find('[data-editors]').add($form).each(function (i, el) {
                var $container = $(el),
                    selection = $container.data('editors');

                if (_.isUndefined(selection)) {
                    return;
                }

                //Work out which fields to include
                var keys = (selection == '*')
                    ? self.selectedFields || _.keys(fields)
                    : selection.split(',');

                //Add them
                _.each(keys, function (key) {
                    var field = fields[key];

                    var $el, el = field.editor.render().el;
                    if ($.webshims) {
                        $el = $container.appendPolyfill(el);
                    } else {
                        $el = $container.append(el);
                    }
                });

                $container.removeAttr('data-editors');
            });

            //Render standalone fields
            $form.find('[data-fields]').add($form).each(function (i, el) {
                var $container = $(el),
                    selection = $container.data('fields');

                if (_.isUndefined(selection)) {
                    return;
                }

                //Work out which fields to include
                var keys = (selection == '*')
                    ? self.selectedFields || _.keys(fields)
                    : selection.split(',');

                //Add them
                _.each(keys, function (key) {
                    var field = fields[key];

                    field.schema = field.schema || {};
                    field.schema = _.extend(field.schema, $container.data("schema"));

                    var $el, el = field.render().el;
                    if ($.webshims) {
                        $el = $container.appendPolyfill(el);
                    } else {
                        $el = $container.append(el);
                    }

                    // Update editor Attrs
                    field.schema.editorAttrs = field.schema.editorAttrs || {};
                    field.schema.editorAttrs = _.extend(field.schema.editorAttrs, $container.data("editorAttrs"));
                    field.editor.$el.attr(field.schema.editorAttrs);

                    // Add custom editor Class
                    field.editor.$el.addClass($container.data("editorClass"));

                });

                $container.removeAttr('data-fields');
            });

            //Render fieldsets
            $form.find('[data-fieldsets]').add($form).each(function (i, el) {
                var $container = $(el),
                    selection = $container.data('fieldsets');

                if (_.isUndefined(selection)) {
                    return;
                }

                _.each(self.fieldsets, function (fieldset) {

                    var $el, el = fieldset.render().el;
                    if ($.webshims) {
                        $el = $container.appendPolyfill(el);
                    } else {
                        $el = $container.append(el);
                    }

                    // Update editor Attrs
                    fieldset.schema.editorAttrs = fieldset.schema.editorAttrs || {};
                    fieldset.schema.editorAttrs = _.extend(fieldset.schema.editorAttrs, $container.data("editorAttrs"));
                    fieldset.editor.$el.find("[data-editor] input").attr(fieldset.schema.editorAttrs);

                    // Add custom editor Class
                    fieldset.editor.$el.addClass($container.data("editorClass"));
                });

                $container.removeAttr('data-fieldsets');
            });

            //Set the main element
            self.setElement($form);

            //Set class
            $form.addClass(self.className);

            return self;
        }

    });

    /**
     * Allows to facility html elements with backbone-forms or model functionality
     *
     * @param option
     */
    $.fn.tbform = function (option) {
        var args = Array.prototype.slice.call(arguments, 1);

        return this.each(function () {
            var $this = $(this);
            var data = $this.data('tb.form');

            var options = typeof option == 'object' && option;

            if (!data) {
                options["el"] = this;
                $this.data('tb.form', (data = new Tornado.BackboneForm(options)));
                $this.data('tb.form').render();
            }
            if (typeof option == 'string') {
                data[option].apply(data, args);
            }
        });
    };
    $.fn.tbform.Constructor = Tornado.BackboneForm;

    // Facile elements with backbone-forms
    $('[data-model][data-require]').each(function () {
        var $form = $(this);

        require($(this).data('require').split(" "), function () {
            $form.tbform($form.data())
        });
    });
    $('[data-model]:not([data-require])').each(function () {
        var $form = $(this);
        $form.tbform($form.data());
    });

    return Tornado;
}).call(window);
<commit_msg>Log error when building form queries<commit_after>/**
 * User: Martin Martimeo
 * Date: 13.08.13
 * Time: 18:30
 *
 * Extension to backbone-forms
 */

require(["jquery", "underscore", "backbone", "backbone-forms"],function ($, _, Backbone) {
    var self = this.Tornado || {};
    var Tornado = this.Tornado = self;

    Tornado.BackboneForm = Backbone.View.extend({

        initialize: function () {

            // Set Model
            if (this.options.model) {
                if (_.isString(this.options.model)) {
                    this.model = this.options.model = new window[this.options.model]();
                } else {
                    this.model = this.options.model;
                }
                if (_.isObject(this.options.value)) {
                    this.model.set(this.options.value);
                }
            }

            // Create Form
            this.form = new Backbone.Form(this.options);
            this.listenTo(this.form, 'all', this.handleFormEvent);
        },

        handleFormEvent: function (event, form, node) {
            this.trigger(event, node || form || this);

            // Retrigger event under tb:* namespace
            var args = event.split(":");
            if (args.length > 1) {
                this.trigger("tb:" + args[1], form, node);
                this.trigger("tb:" + args[1] + ":" + args[0], form, node);
            }
        },

        render: function () {
            var self = this.form,
                $form = this.$el,
                fields = this.form.fields;

            //Render standalone editors
            $form.find('[data-editors]').add($form).each(function (i, el) {
                var $container = $(el),
                    selection = $container.data('editors');

                if (_.isUndefined(selection)) {
                    return;
                }

                //Work out which fields to include
                var keys = (selection == '*')
                    ? self.selectedFields || _.keys(fields)
                    : selection.split(',');

                //Add them
                _.each(keys, function (key) {
                    var field = fields[key];

                    var $el, el = field.editor.render().el;
                    if ($.webshims) {
                        $el = $container.appendPolyfill(el);
                    } else {
                        $el = $container.append(el);
                    }
                });

                $container.removeAttr('data-editors');
            });

            //Render standalone fields
            $form.find('[data-fields]').add($form).each(function (i, el) {
                var $container = $(el),
                    selection = $container.data('fields');

                if (_.isUndefined(selection)) {
                    return;
                }

                //Work out which fields to include
                var keys = (selection == '*')
                    ? self.selectedFields || _.keys(fields)
                    : selection.split(',');

                //Add them
                _.each(keys, function (key) {
                    var field = fields[key];

                    if (!field) {
                        console.error("Could not find " + key + " in fields for " + $form);
                        return;
                    }

                    field.schema = field.schema || {};
                    field.schema = _.extend(field.schema, $container.data("schema"));

                    var $el, el = field.render().el;
                    if ($.webshims) {
                        $el = $container.appendPolyfill(el);
                    } else {
                        $el = $container.append(el);
                    }

                    // Update editor Attrs
                    field.schema.editorAttrs = field.schema.editorAttrs || {};
                    field.schema.editorAttrs = _.extend(field.schema.editorAttrs, $container.data("editorAttrs"));
                    field.editor.$el.attr(field.schema.editorAttrs);

                    // Add custom editor Class
                    field.editor.$el.addClass($container.data("editorClass"));

                });

                $container.removeAttr('data-fields');
            });

            //Render fieldsets
            $form.find('[data-fieldsets]').add($form).each(function (i, el) {
                var $container = $(el),
                    selection = $container.data('fieldsets');

                if (_.isUndefined(selection)) {
                    return;
                }

                _.each(self.fieldsets, function (fieldset) {

                    var $el, el = fieldset.render().el;
                    if ($.webshims) {
                        $el = $container.appendPolyfill(el);
                    } else {
                        $el = $container.append(el);
                    }

                    // Update editor Attrs
                    fieldset.schema.editorAttrs = fieldset.schema.editorAttrs || {};
                    fieldset.schema.editorAttrs = _.extend(fieldset.schema.editorAttrs, $container.data("editorAttrs"));
                    fieldset.editor.$el.find("[data-editor] input").attr(fieldset.schema.editorAttrs);

                    // Add custom editor Class
                    fieldset.editor.$el.addClass($container.data("editorClass"));
                });

                $container.removeAttr('data-fieldsets');
            });

            //Set the main element
            self.setElement($form);

            //Set class
            $form.addClass(self.className);

            return self;
        }

    });

    /**
     * Allows to facility html elements with backbone-forms or model functionality
     *
     * @param option
     */
    $.fn.tbform = function (option) {
        var args = Array.prototype.slice.call(arguments, 1);

        return this.each(function () {
            var $this = $(this);
            var data = $this.data('tb.form');

            var options = typeof option == 'object' && option;

            if (!data) {
                options["el"] = this;
                $this.data('tb.form', (data = new Tornado.BackboneForm(options)));
                $this.data('tb.form').render();
            }
            if (typeof option == 'string') {
                data[option].apply(data, args);
            }
        });
    };
    $.fn.tbform.Constructor = Tornado.BackboneForm;

    // Facile elements with backbone-forms
    $('[data-model][data-require]').each(function () {
        var $form = $(this);

        require($(this).data('require').split(" "), function () {
            $form.tbform($form.data())
        });
    });
    $('[data-model]:not([data-require])').each(function () {
        var $form = $(this);
        $form.tbform($form.data());
    });

    return Tornado;
}).call(window);
<|endoftext|>


<commit_before>/* jshint unused: false */
/* global _Element, ElementFactory, Me, Input, M, document.$, E, Grid, startup, sprite,
Grass, score, Water, Flower, Grass, Earth, Region, Plants, Fire, Rock, Eye, Ice, HeadPlants, level, Lava, Canvas */
var G = {
	width: 0,
	height: 0,
	scale: 4,
	sw: 0,
	sh: 0,
	context: null,
	color: '#2C2C2C',

	ent: null,
	ent2: null,

	entities: [],
	grid: null,

	delay: 0,
	ceDelay: 0.1,

	ce: null,
	requestElement: 0,

	_cleanRequested: false,

	score: 0,
	gameOver: false,

	collideDelay: 0.2,

	shadows: {},

	dx: 0,

	level: 0,
	levels: [
		{
			elementCount: 30 / 4,
			elementSpeed: 0.3,
			c: "#23758C"
		},
		{
			elementCount: 60 / 4,
			elementSpeed: 0.29,
			c: "#42B665"
		},
		{
			elementCount: 90 / 4,
			elementSpeed: 0.28,
			c: "#E28A32"
		},
		{
			elementCount: 120 / 4,
			elementSpeed: 0.25,
			c: "#E24A32"
		},
		{
			elementCount: 130 / 4,
			elementSpeed: 0.22,
			c: "#9B1800"

		},
		{
			elementCount: 150 / 4,
			elementSpeed: 0.2,
			c: "#2A0700"
		}
	],

	_initShadows: function() {
		var e = null;
		for (var el in Me) {
			var c = Canvas.get(10, 10);
			Canvas.pixelate(c);
			e = Me[el];

			var x = ((e - 1) % (sprite.width / E)) * E;
			var y = M.floor((e - 1) / (sprite.width / E)) * E;
			c.getContext('2d').drawImage(sprite, x, y, 10 ,10, 0, 0, 10, 10);
			this.shadows[e] = Canvas.createAlphaMask('#000000', c, 0, 0, 10, 10);
		}
	},

	load: function(onload) {
		onload();
		this.grid = new Grid(this.sw / E, this.sh / E);
		//this.add(Lava.new(3, this.grid.r - 1));
		var i = 0;
		for (var j = 1; j < 3; j++) {
			for (i = 0; i < this.grid.c; i++) {
				this.add(Earth.new(i, this.grid.r - j));
			}
		}

		this.add(Eye.new());

		G.get(0, this.grid.r - 2).replace(Grass);
		this.add(Plants.new(0, this.grid.r - 3));
		G.get(1, this.grid.r - 2).replace(Ice);
		G.get(1, this.grid.r - 1).replace(Ice);

		this.add(Earth.new(3, this.grid.r - 3));
		this.add(Earth.new(4, this.grid.r - 3));
		this.add(Grass.new(5, this.grid.r - 3));
		this.add(Plants.new(5, this.grid.r - 4));

		this.add(Fire.new(2, this.grid.r - 3));
		this.add(Water.new(6, this.grid.r - 3));
		this.add(Water.new(7, this.grid.r - 3));

		G.get(6, this.grid.r - 2).replace(Rock);
		G.get(7, this.grid.r - 2).replace(Rock);

		this.add(Grass.new(4, this.grid.r - 4));
		this.add(Plants.new(4, this.grid.r - 5));

		// update grid:
		var c = null;
		this.grid.empty();
		var l = this.entities.length;
		for (i = 0; i < l; i++) {
			c = this.entities[i];
			//c.update(0);
			//this.grid.set(c.x, c.y, c.type);
		}

		this.dx = 0;

		this.ent = Canvas.get(G.width, G.height);
		this.ent2 = Canvas.get(G.width, G.height);

		this._initShadows();
	},

	// debug
	onclick: function(x, y) {
		//console.log('click tile', x, y);
		x = ~~(((x) / G.scale) / E);
		y = ~~((y / G.scale) / E);

		var tr = -1;
		var l = this.entities.length;
		var e = null;
		for (var i = 0; i < l; i++) {
			e = this.entities[i];
			if (e.x === x && e.y === y) {
				this.remove(e);
				break;
			}
		}
	},

	get: function(x, y) {
		var l = this.entities.length, c = null;
		for (var i = 0; i < l; i++) {
			c = this.entities[i];
			if (c.x === x && c.y === y) {
				return c;
			}
		}
		return null;
	},

	displayCount: function(x, y, v) {
		console.log('displayCount', x, y, v);
		var c = document.createElement('div');
		c.innerHTML = '+ ' + v;
		c.style.fontSize = '20px';
		c.style.position = "absolute";
		c.style.left = x + "px";
		c.style.top = y + "px";
		c.style.color = 'white';
		document.$('gameContent').appendChild(c);
		setTimeout(function() {
			document.$('gameContent').removeChild(c);
		}, 800);
	},

	update: function(dt) {

		if (this.gameOver === true) {
			return;
		}

		var i = 0;

		// levels up?
		var cl = null;
		for (i = this.level; i < this.levels.length - 1; i++) {
			cl = this.levels[i];
			if (ElementFactory.c > cl.elementCount) {
				//console.log('UP', 'current', ElementFactory.c, 'limit', cl.elementCount);
				this.level = i + 1;
				break;
			}
		}
		cl = this.levels[this.level];
		this.ceDelay = cl.elementSpeed;

		if (this._cleanRequested) {
			this._cleanRequested = false;
			this._cleanEntities();
		}

		var l = this.entities.length;
		var c = null;

		// update grid:
		this.grid.empty();
		for (i = 0; i < l; i++) {
			c = this.entities[i];
			this.grid.set(c.x, c.y, c.type);
		}

		for (i = 0; i < l; i++) {
			c = this.entities[i];
			c.update(dt);
		}

		// update to know if some block must be changed
		if ((this.collideDelay -= dt) < 0) {
			this.collideDelay = 0.2;
			var t = 0;
			for (i = 0; i < l; i++) {
				c = this.entities[i];
				if (!c.selected) {
					t = this.grid.get(c.x, c.y + 1);
					// test the entity above each one:
					if (t !== 0) {
						var ne = this.get(c.x, c.y + 1);
						if (ne) {
							c.collide(ne);
						}
					}
				}
			}
		}

		if (this.requestElement > 0) {
			this.requestElement -= dt;
			if (this.requestElement <= 0) {
				if (this.ce) {
					this.ce.free();
					this.ce = null; // next frame a new element will be spawn
				}

				var polygon = [];
				var el = null, cost = 0, x = 0, y = 0;
				var chain = this.grid.getChain();
				for (i = 0; i < chain.length; i++) {
					for (var j = 0; j < chain[i].length; j++) {
						if (chain[i][j] === 1) {
							el = this.get(j, i);
							if (el) {
								polygon.push({x: j, y: i});
								el.selected = true;
								cost += el.cost;
							}
						}
					}
				}

				if (cost > 0) {
					var ct = null;
					if (polygon.length === 1) {
						ct = polygon[0];
					} else {
						var region = new Region(polygon);
						ct = region.centroid();
						if (isNaN(ct.x) || isNaN(ct.y)) {
							ct = polygon[0];
						}
 					}
					this.displayCount(ct.x * E * G.scale, ct.y * E * G.scale, cost);
					G.score += cost;
				}
			}
		}

		if (this.ce) this.ce.gravity = (Input.keys.d) ? 20: 0;

		if (this.requestElement <= 0) {
			// current element:
			if (this.ce === null) {
				//this.ce = this.add(ElementFactory.getRandom(~~(Math.random() * 10), 0));
				this.ce = this.add(ElementFactory.getRandom(4 + ~~(Math.random() * 1), 0));
				this.ce.free();
			}

			if (this.ce._toRemove === true) {
				this.requestElement = cl.elementSpeed * 2;
				this.ce.free();
				this.ce = null;
			}

			if (this.ce && this.ce.gravity === 0) {

				var dx = this.dx;
				this.dx = 0;
				if (Input.keys.r) {
					dx = 1;
				} else if (Input.keys.l) {
					dx = -1;
				}

				if ((this.delay -= dt) <= 0) {
					this.delay = this.ceDelay;

					// check if move is possible
					if (this.grid.get(this.ce.x + dx, this.ce.y + 1) > 0 || this.ce.y === G.grid.r - 1) {
						if (this.grid.get(this.ce.x, this.ce.y + 1) > 0) {
							// we can't move down
							if (this.ce.y === 0) {
								// GAME OVER
								this.gameOver = true;
								document.$('gameOver').style.display = "block";

							} else {
								this.dx = 0;
								this.requestElement = cl.elementSpeed * 2;
							}
							//var a = new Audio("hurt.wav");
							//a.volume = 0.5;
							//a.play();

						} else {
							this.ce.cy += 1;//0.5;
						}
					} else {
						this.ce.cx += dx;
						this.ce.cy += 1;// 0.5;
					}

				} else {
					this.dx = dx;
				}
			}
		}

		level.innerHTML = "LEVEL " + (this.level + 1);
		score.innerHTML = this.score;
	},

	render: function() {
		this.context.clearRect(0, 0, this.width, this.height);
		this.context.fillStyle = this.color;
		this.context.fillRect(0, 0, this.width, this.height);

		var e = this.ent.getContext('2d');
		e.clearRect(0, 0, this.width, this.height);

		var e2 = this.ent2.getContext('2d');
		e2.clearRect(0, 0, this.width, this.height);
		e2.globalAlpha = 0.4;

		// draw shadows:
		var et = null, s = null;
		var l = this.entities.length;
		for (var i = 0; i < l; i++) {
			et = this.entities[i];
			et.render(e);
			if (et.blink === 0.1) {
				s = this.shadows[et._type];
				if (s) {
					e2.drawImage(s, ~~et.cx * E, ~~et.cy * E);
				}
			}
		}

		this.context.drawImage(this.ent2, -4, 0);
		this.context.drawImage(this.ent, 0, 0);
	},

	// ENGINE PART
	add: function(e) {
		this.entities.push(e);
		return e;
	},

	_cleanEntities: function() {
		var newEntities = [];
		var l = this.entities.length;
		for (var i = 0; i < l; i++) {
			if (this.entities[i]._toRemove !== true) {
				newEntities.push(this.entities[i]);
			}
		}
		this.entities = newEntities;
	},

	remove: function(e) {
		this._cleanRequested = true;
		e._toRemove = true;
	}
};<commit_msg>Each n block, the ground is increased with shaking style :)<commit_after>/* jshint unused: false */
/* global _Element, ElementFactory, Me, Input, M, document.$, E, Grid, startup, sprite,
Grass, score, Water, Flower, Grass, Earth, Region, Plants, Fire, Rock, Eye, Ice, HeadPlants, level, Lava, Canvas */
var G = {
	width: 0,
	height: 0,
	scale: 4,
	sw: 0,
	sh: 0,
	context: null,
	color: '#2C2C2C',

	ent: null,
	ent2: null,

	entities: [],
	grid: null,

	delay: 0,
	ceDelay: 0.1,

	ce: null,
	requestElement: 0,

	_cleanRequested: false,

	score: 0,
	gameOver: false,

	collideDelay: 0.2,

	shadows: {},

	dx: 0,

	shake: 0,

	level: 0,
	levels: [
		{
			elementCount: 30 / 4,
			elementSpeed: 0.3,
			c: "#23758C"
		},
		{
			elementCount: 60 / 4,
			elementSpeed: 0.29,
			c: "#42B665"
		},
		{
			elementCount: 90 / 4,
			elementSpeed: 0.28,
			c: "#E28A32"
		},
		{
			elementCount: 120 / 4,
			elementSpeed: 0.25,
			c: "#E24A32"
		},
		{
			elementCount: 130 / 4,
			elementSpeed: 0.22,
			c: "#9B1800"

		},
		{
			elementCount: 150 / 4,
			elementSpeed: 0.2,
			c: "#2A0700"
		}
	],

	_initShadows: function() {
		var e = null;
		for (var el in Me) {
			var c = Canvas.get(10, 10);
			Canvas.pixelate(c);
			e = Me[el];

			var x = ((e - 1) % (sprite.width / E)) * E;
			var y = M.floor((e - 1) / (sprite.width / E)) * E;
			c.getContext('2d').drawImage(sprite, x, y, 10 ,10, 0, 0, 10, 10);
			this.shadows[e] = Canvas.createAlphaMask('#000000', c, 0, 0, 10, 10);
		}
	},

	load: function(onload) {
		onload();
		this.grid = new Grid(this.sw / E, this.sh / E);
		//this.add(Lava.new(3, this.grid.r - 1));
		var i = 0;
		for (var j = 1; j < 3; j++) {
			for (i = 0; i < this.grid.c; i++) {
				this.add(Earth.new(i, this.grid.r - j));
			}
		}

		this.add(Eye.new());

		G.get(0, this.grid.r - 2).replace(Grass);
		this.add(Plants.new(0, this.grid.r - 3));
		G.get(1, this.grid.r - 2).replace(Ice);
		G.get(1, this.grid.r - 1).replace(Ice);

		this.add(Earth.new(3, this.grid.r - 3));
		this.add(Earth.new(4, this.grid.r - 3));
		this.add(Grass.new(5, this.grid.r - 3));
		this.add(Plants.new(5, this.grid.r - 4));

		this.add(Fire.new(2, this.grid.r - 3));
		this.add(Water.new(6, this.grid.r - 3));
		this.add(Water.new(7, this.grid.r - 3));

		G.get(6, this.grid.r - 2).replace(Rock);
		G.get(7, this.grid.r - 2).replace(Rock);

		this.add(Grass.new(4, this.grid.r - 4));
		this.add(Plants.new(4, this.grid.r - 5));

		// update grid:
		var c = null;
		this.grid.empty();
		var l = this.entities.length;
		for (i = 0; i < l; i++) {
			c = this.entities[i];
			//c.update(0);
			//this.grid.set(c.x, c.y, c.type);
		}

		this.dx = 0;

		this.ent = Canvas.get(G.width, G.height);
		this.ent2 = Canvas.get(G.width, G.height);

		this._initShadows();
	},

	// debug
	onclick: function(x, y) {
		//console.log('click tile', x, y);
		x = ~~(((x) / G.scale) / E);
		y = ~~((y / G.scale) / E);

		var tr = -1;
		var l = this.entities.length;
		var e = null;
		for (var i = 0; i < l; i++) {
			e = this.entities[i];
			if (e.x === x && e.y === y) {
				this.remove(e);
				break;
			}
		}
	},

	get: function(x, y) {
		var l = this.entities.length, c = null;
		for (var i = 0; i < l; i++) {
			c = this.entities[i];
			if (c.x === x && c.y === y) {
				return c;
			}
		}
		return null;
	},

	displayCount: function(x, y, v) {
		console.log('displayCount', x, y, v);
		var c = document.createElement('div');
		c.innerHTML = '+ ' + v;
		c.style.fontSize = '20px';
		c.style.position = "absolute";
		c.style.left = x + "px";
		c.style.top = y + "px";
		c.style.color = 'white';
		document.$('gameContent').appendChild(c);
		setTimeout(function() {
			document.$('gameContent').removeChild(c);
		}, 800);
	},

	increaseRow: function() {
		var l = this.entities.length;
		var i = 0;
		for (i = 0; i < l; i++) {
			var c = this.entities[i];
			if (c.type !== 61) {
				if (c.y - 1 < 0) {
					c._toRemove = true;
				} else {
					c.y -= 1;
				}
			}
		}
		// add a line below:
		for (i = 0; i < G.grid.c; i++) {
			var r = M.random();
			if (r > 0.4) {
				G.add(Earth.new(i, G.grid.r - 1));
			} else if (r > 0.1) {
				G.add(Rock.new(i, G.grid.r - 1));
		 	} else {
				G.add(Ice.new(i, G.grid.r - 1));
			}
		}
	},

	update: function(dt) {

		if (this.gameOver === true) {
			return;
		}

		if (this.shake > 0 && (this.shake -= dt) < 0) {
			this.shake = 0;
			this.increaseRow();
		}

		var i = 0;

		// levels up?
		var cl = null;
		for (i = this.level; i < this.levels.length - 1; i++) {
			cl = this.levels[i];
			if (ElementFactory.c > cl.elementCount) {
				//console.log('UP', 'current', ElementFactory.c, 'limit', cl.elementCount);
				this.level = i + 1;
				break;
			}
		}
		cl = this.levels[this.level];
		this.ceDelay = cl.elementSpeed;

		if (this._cleanRequested) {
			this._cleanRequested = false;
			this._cleanEntities();
		}

		var l = this.entities.length;
		var c = null;

		// update grid:
		this.grid.empty();
		for (i = 0; i < l; i++) {
			c = this.entities[i];
			this.grid.set(c.x, c.y, c.type);
		}

		for (i = 0; i < l; i++) {
			c = this.entities[i];
			c.update(dt);
		}

		// update to know if some block must be changed
		if ((this.collideDelay -= dt) < 0) {
			this.collideDelay = 0.2;
			var t = 0;
			for (i = 0; i < l; i++) {
				c = this.entities[i];
				if (!c.selected) {
					t = this.grid.get(c.x, c.y + 1);
					// test the entity above each one:
					if (t !== 0) {
						var ne = this.get(c.x, c.y + 1);
						if (ne) {
							c.collide(ne);
						}
					}
				}
			}
		}

		if (this.requestElement > 0) {
			this.requestElement -= dt;
			if (this.requestElement <= 0) {
				if (this.ce) {
					this.ce.free();
					this.ce = null; // next frame a new element will be spawn
				}

				var polygon = [];
				var el = null, cost = 0, x = 0, y = 0;
				var chain = this.grid.getChain();
				for (i = 0; i < chain.length; i++) {
					for (var j = 0; j < chain[i].length; j++) {
						if (chain[i][j] === 1) {
							el = this.get(j, i);
							if (el) {
								polygon.push({x: j, y: i});
								el.selected = true;
								cost += el.cost;
							}
						}
					}
				}

				if (cost > 0) {
					var ct = null;
					if (polygon.length === 1) {
						ct = polygon[0];
					} else {
						var region = new Region(polygon);
						ct = region.centroid();
						if (isNaN(ct.x) || isNaN(ct.y)) {
							ct = polygon[0];
						}
 					}
					this.displayCount(ct.x * E * G.scale, ct.y * E * G.scale, cost);
					G.score += cost;
				}
			}
		}

		if (this.ce) this.ce.gravity = (Input.keys.d) ? 20: 0;

		if (this.requestElement <= 0) {
			// current element:
			if (this.ce === null) {
				this.ce = this.add(ElementFactory.getRandom(4 + ~~(Math.random() * 1), 0));
				this.ce.free();
			}

			if (this.ce._toRemove === true) {
				this.dx = 0;
				this.requestElement = cl.elementSpeed * 2;
				this.ce.free();
				this.ce = null;
				if (ElementFactory.c > 0 && ElementFactory.c % 10 === 0) {
					this.shake = 0.8;
				}
			}

			if (this.ce && this.ce.gravity === 0) {

				var dx = this.dx;
				this.dx = 0;
				if (Input.keys.r) {
					dx = 1;
				} else if (Input.keys.l) {
					dx = -1;
				}

				if ((this.delay -= dt) <= 0) {
					this.delay = this.ceDelay;

					// check if move is possible
					if (this.grid.get(this.ce.x + dx, this.ce.y + 1) > 0 || this.ce.y === G.grid.r - 1) {
						if (this.grid.get(this.ce.x, this.ce.y + 1) > 0) {
							// we can't move down
							if (this.ce.y === 0) {
								// GAME OVER
								this.gameOver = true;
								document.$('gameOver').style.display = "block";

							} else {
								this.ce._toRemove = true;
							}
							//var a = new Audio("hurt.wav");
							//a.volume = 0.5;
							//a.play();

						} else {
							this.ce.cy += 1;//0.5;
						}
					} else {
						this.ce.cx += dx;
						this.ce.cy += 1;// 0.5;
					}

				} else {
					this.dx = dx;
				}
			}
		}

		level.innerHTML = "LEVEL " + (this.level + 1);
		score.innerHTML = this.score;
	},

	render: function() {
		this.context.clearRect(0, 0, this.width, this.height);
		this.context.fillStyle = this.color;
		this.context.fillRect(0, 0, this.width, this.height);

		var e = this.ent.getContext('2d');
		e.clearRect(0, 0, this.width, this.height);

		var e2 = this.ent2.getContext('2d');
		e2.clearRect(0, 0, this.width, this.height);
		e2.globalAlpha = 0.4;

		// draw shadows:
		var et = null, s = null;
		var l = this.entities.length;
		for (var i = 0; i < l; i++) {
			et = this.entities[i];
			et.render(e);
			if (et.blink === 0.1) {
				s = this.shadows[et._type];
				if (s) {
					e2.drawImage(s, ~~et.cx * E, ~~et.cy * E);
				}
			}
		}

		if (this.shake > 0) {
			this.context.save();
			this.context.translate((0.5 - M.random()) * 3.4, (0.5 - M.random()) * 3.4);
		}

		this.context.drawImage(this.ent2, -4, 0);
		this.context.drawImage(this.ent, 0, 0);

		this.context.restore();
	},

	// ENGINE PART
	add: function(e) {
		this.entities.push(e);
		return e;
	},

	_cleanEntities: function() {
		var newEntities = [];
		var l = this.entities.length;
		for (var i = 0; i < l; i++) {
			if (this.entities[i]._toRemove !== true) {
				newEntities.push(this.entities[i]);
			}
		}
		this.entities = newEntities;
	},

	remove: function(e) {
		this._cleanRequested = true;
		e._toRemove = true;
	}
};<|endoftext|>


<commit_before>require("babel-register");

//var Hex = require('./colors/Hex.js')
import Hex from './color-space/Hex'
import RGB from './color-space/RGB'
import HSL from './color-space/HSL'

class Glow {

  hexToHsl(hex) {
    var rgb = this.hexToRgb(hex)
    return this.rgbToHsl(rgb)
  }

  hslToHex(hsl) {
    var rgb = this.hslToRgb(hsl)
    return this.rgbToHex(rgb)
  }

}

export { Glow, Hex, RGB, HSL };<commit_msg>include palette in corejs<commit_after>require("babel-register");

import Hex from './color-space/Hex'
import RGB from './color-space/RGB'
import HSL from './color-space/HSL'

import Palette from './palette/Palette'

class Glow {

  hexToHsl(hex) {
    var rgb = this.hexToRgb(hex)
    return this.rgbToHsl(rgb)
  }

  hslToHex(hsl) {
    var rgb = this.hslToRgb(hsl)
    return this.rgbToHex(rgb)
  }

}

export { Glow, Hex, RGB, HSL, Palette }<|endoftext|>


<commit_before>import { rebind } from '@zambezi/d3-utils'
import { createSetupGridTemplate } from './setup-grid-template'

export function createGrid() {
  function grid(s) {
    s.text('this is the grid—!').call(createSetupGridTemplate())
  }

  return grid
}
<commit_msg>prime grid call stack<commit_after>import { rebind, call } from '@zambezi/d3-utils'
import { createSetupGridTemplate } from './setup-grid-template'
import { compose } from 'underscore'

export function createGrid() {

  const setupTemplate = createSetupGridTemplate()
      , grid = compose(call(setupTemplate))

  return grid
}
<|endoftext|>


<commit_before>import React from 'react'
import Style from './app.style'

const sampleCardsData = [
  {
    title: "Vacuum Handbook",
    description: `The first thing you should read when you start working at VacuumLabs.`,
    icon: "fa fa-users",
    //updatedAt: "20160107T14:39:21",
    link: "/vacuum-book/",
  },
  {
    title: "House Rules — Radlinského",
    description: "House rules for Radlinského 10 office.",
    icon: "fa fa-home",
    link: "/house-rules-radlinskeho/",
  },
  {
    title: "House Rules — Košice",
    description: "House rules for Košice office.",
    icon: "fa fa-home",
    link: "/house-rules-kosice/",
  },
  {
    title: "House Rules — Prague",
    description: "House rules for our Prague office.",
    icon: "fa fa-home",
    link: "/house-rules-prague/",
  },
  {
    title: "House Rules — London",
    description: "House rules for our London office.",
    icon: "fa fa-home",
    link: "/house-rules-london/",
  },
  {
    title: "Coding Tips",
    description: `This public handbook provides useful tips and tricks for programmers.`,
    icon: "fa fa-code",
    //updatedAt: "20160207T11:39:21",
    link: "/coding-tips/",
  },
  {
    title: "Management Tips",
    description: "VacuumLabs Management tips, tricks, guidelines, and best practices.",
    icon: "fas fa-tasks",
    link: "/management-tips/",
  },
  {
    title: "PM Handbook",
    description: "VacuumLabs PM tips, tricks, guidelines, and best practices.",
    icon: "fas fa-tasks",
    link: "/pm-book/",
  },
  {
    title: "Tech Handbook",
    description: `Various technical stuff such as Google Drive backup, or JIRA management are documented here.`,
    icon: "fa fa-terminal",
    //updatedAt: "20160307T14:23:21",
    link: "/tech-book/",
  },
  {
    title: "Assessment and Interview",
    description: `Set of guides, tips, and interview questions for our technical assessments.`,
    icon: "fa fa-user-plus",
    //updatedAt: "20160307T14:23:21",
    link: "/assessment/",
  },
  {
    title: "HQ",
    description: "Relevant information for the VacuumLabs' management.",
    icon: "fa fa-chart-line",
    link: "/hq/",
  },
  {
    title: "Sales Guidelines",
    description: "How do we sell our services.",
    icon: "fas fa-briefcase",
    link: "/sales-book/",
  },
  {
    title: "ReactiveConf",
    description: "How to organize ReactiveConf.",
    icon: "fab fa-react",
    link: "/reactiveconf/",
  },
  {
    title: "ReactiveMeetups",
    description: "How to organize ReactiveMeetups.",
    icon: "fab fa-react",
    link: "/reactivemeetups/",
  },
  {
    title: "Finance Handbook",
    description: "No money, no honey",
    icon: "fab fa-react",
    link: "/finance-handbook/",
  },
  {
    title: "Travel Tips",
    description: "How to survive jet lag and much more.",
    icon: "fas fa-plane",
    link: "/travel-tips/",
  },
  {
    title: "Asciidoctor Cheatsheet",
    description: "The ultimate copy & paste guide to writing Asciidoctor documents.",
    icon: "fas fa-pencil-alt",
    link: "/asciidoctor-cheatsheet/"
  },
]

export default () => (


<commit_before>'use strict';

var inherits = require('inherits');

var Promise = require('./promise-or-lie');

var Port = require('./port'),
	resizer = require('./plugins/iframe-resizer/host'),
	syncFont = require('./plugins/sync-font/host'),
	syncLang = require('./plugins/sync-lang/host'),
	syncIntl = require('./plugins/sync-intl/host'),
	syncTimezone = require('./plugins/sync-timezone/host'),
	syncTitle = require('./plugins/sync-title/host'),
	syncCssVariable = require('./plugins/sync-css-variable/host');

var originRe = /^(http:\/\/|https:\/\/)[^/]+/i;

function Host(elementProvider, src, options) {
	if (!(this instanceof Host)) {
		return new Host(elementProvider, src, options);
	}

	options = options || {};

	var origin = Host._tryGetOrigin(src);
	if (origin === null) {
		throw new Error('Unable to extract origin from "' + src + '"');
	}

	var parent = elementProvider();
	if (parent === null) {
		throw new Error('Could not find parent node');
	}

	var iframe = Host._createIFrame(src, options.id, options.height, options.allowFullScreen, options.allowMicrophone, options.allowCamera);
	parent.appendChild(iframe);

	Port.call(this, iframe.contentWindow, origin, options);

	this.iframe = iframe;

	if (options.syncLang) {
		this.use(syncLang);
		this.use(syncIntl);
		this.use(syncTimezone);
	}
	this.use(syncTitle({page: options.syncPageTitle ? true : false}));

	if (!(options.height || options.height === 0) && options.resizeFrame !== false) {
		this.use(resizer);
	}

	if (options.syncFont) {
		this.use(syncFont);
	}
	if (options.syncCssVariable) {
		this.use(syncCssVariable);
	}
}
inherits(Host, Port);

Host.prototype.connect = function connect() {
	var me = this;
	return new Promise(function(resolve/*, reject*/) {
		me.onEvent('ready', function() {
			if (me._isConnected) {
				return;
			}

			resolve(Port.prototype.connect.call(me));
		});
		me.open();
	});
};

Host._createIFrame = function createIFrame(src, frameId, height, allowFullScreen, allowMicrophone, allowCamera) {
	var iframe = document.createElement('iframe');
	iframe.width = '100%';
	if (height || height === 0) {
		iframe.style.height = height;
	}
	iframe.style.border = 'none';
	iframe.style.overflow = 'hidden';
	iframe.scrolling = 'no';
	iframe.src = src;
	if (frameId) {
		iframe.id = frameId;
	}
	if (allowMicrophone || allowCamera) {
		let allow = [];
		if (allowCamera) {
			allow.push('camera *;');
		}
		if (allowMicrophone) {
			allow.push('microphone *;');
		}
		iframe.setAttribute('allow', allow.join(' '));
	}
	if (allowFullScreen) {
		iframe.setAttribute('allowfullscreen', 'allowfullscreen');
	}

	return iframe;
};

Host._tryGetOrigin = function tryGetOrigin(url) {
	if (url && url.indexOf('//') === 0) {
		url = window.location.protocol + url;
	}
	var match = originRe.exec(url);
	return (match !== null) ? match[0] : null;
};

module.exports = Host;
<commit_msg>DE32856 - browserify did not like let<commit_after>'use strict';

var inherits = require('inherits');

var Promise = require('./promise-or-lie');

var Port = require('./port'),
	resizer = require('./plugins/iframe-resizer/host'),
	syncFont = require('./plugins/sync-font/host'),
	syncLang = require('./plugins/sync-lang/host'),
	syncIntl = require('./plugins/sync-intl/host'),
	syncTimezone = require('./plugins/sync-timezone/host'),
	syncTitle = require('./plugins/sync-title/host'),
	syncCssVariable = require('./plugins/sync-css-variable/host');

var originRe = /^(http:\/\/|https:\/\/)[^/]+/i;

function Host(elementProvider, src, options) {
	if (!(this instanceof Host)) {
		return new Host(elementProvider, src, options);
	}

	options = options || {};

	var origin = Host._tryGetOrigin(src);
	if (origin === null) {
		throw new Error('Unable to extract origin from "' + src + '"');
	}

	var parent = elementProvider();
	if (parent === null) {
		throw new Error('Could not find parent node');
	}

	var iframe = Host._createIFrame(src, options.id, options.height, options.allowFullScreen, options.allowMicrophone, options.allowCamera);
	parent.appendChild(iframe);

	Port.call(this, iframe.contentWindow, origin, options);

	this.iframe = iframe;

	if (options.syncLang) {
		this.use(syncLang);
		this.use(syncIntl);
		this.use(syncTimezone);
	}
	this.use(syncTitle({page: options.syncPageTitle ? true : false}));

	if (!(options.height || options.height === 0) && options.resizeFrame !== false) {
		this.use(resizer);
	}

	if (options.syncFont) {
		this.use(syncFont);
	}
	if (options.syncCssVariable) {
		this.use(syncCssVariable);
	}
}
inherits(Host, Port);

Host.prototype.connect = function connect() {
	var me = this;
	return new Promise(function(resolve/*, reject*/) {
		me.onEvent('ready', function() {
			if (me._isConnected) {
				return;
			}

			resolve(Port.prototype.connect.call(me));
		});
		me.open();
	});
};

Host._createIFrame = function createIFrame(src, frameId, height, allowFullScreen, allowMicrophone, allowCamera) {
	var iframe = document.createElement('iframe');
	iframe.width = '100%';
	if (height || height === 0) {
		iframe.style.height = height;
	}
	iframe.style.border = 'none';
	iframe.style.overflow = 'hidden';
	iframe.scrolling = 'no';
	iframe.src = src;
	if (frameId) {
		iframe.id = frameId;
	}
	if (allowMicrophone || allowCamera) {
		var allow = [];
		if (allowCamera) {
			allow.push('camera *;');
		}
		if (allowMicrophone) {
			allow.push('microphone *;');
		}
		iframe.setAttribute('allow', allow.join(' '));
	}
	if (allowFullScreen) {
		iframe.setAttribute('allowfullscreen', 'allowfullscreen');
	}

	return iframe;
};

Host._tryGetOrigin = function tryGetOrigin(url) {
	if (url && url.indexOf('//') === 0) {
		url = window.location.protocol + url;
	}
	var match = originRe.exec(url);
	return (match !== null) ? match[0] : null;
};

module.exports = Host;
<|endoftext|>


<commit_before>/**
 * @license MIT
 * @fileOverview Favico animations
 * @author Miroslav Magda, http://blog.ejci.net
 * @version 0.3.4
 */

/**
 * Create new favico instance
 * @param {Object} Options
 * @return {Object} Favico object
 * @example
 * var favico = new Favico({
 *    bgColor : '#d00',
 *    textColor : '#fff',
 *    fontFamily : 'sans-serif',
 *    fontStyle : 'bold',
 *    position : 'down',
 *    type : 'circle',
 *    animation : 'slide',
 * });
 */
(function() {

    var Favico = (function(opt) {'use strict';
        opt = (opt) ? opt : {};
        var _def = {
            bgColor : '#d00',
            textColor : '#fff',
            fontFamily : 'sans-serif', //Arial,Verdana,Times New Roman,serif,sans-serif,...
            fontStyle : 'bold', //normal,italic,oblique,bold,bolder,lighter,100,200,300,400,500,600,700,800,900
            type : 'circle',
            position : 'down', // down, up, left, leftup (upleft)
            animation : 'slide',
            elementId : false
        };
        var _opt, _orig, _h, _w, _canvas, _context, _img, _ready, _lastBadge, _running, _readyCb, _stop, _browser, _animTimeout, _drawTimeout;

        _browser = {};
        _browser.ff = (/firefox/i.test(navigator.userAgent.toLowerCase()));
        _browser.chrome = (/chrome/i.test(navigator.userAgent.toLowerCase()));
        _browser.opera = (/opera/i.test(navigator.userAgent.toLowerCase()));
        _browser.ie = (/msie/i.test(navigator.userAgent.toLowerCase())) || (/trident/i.test(navigator.userAgent.toLowerCase()));
        _browser.supported = (_browser.chrome || _browser.ff || _browser.opera);

        var _queue = [];
        _readyCb = function() {
        };
        _ready = _stop = false;
        /**
         * Initialize favico
         */
        var init = function() {
            //merge initial options
            _opt = merge(_def, opt);
            _opt.bgColor = hexToRgb(_opt.bgColor);
            _opt.textColor = hexToRgb(_opt.textColor);
            _opt.position = _opt.position.toLowerCase();
            _opt.animation = (animation.types['' + _opt.animation]) ? _opt.animation : _def.animation;

            var isUp = _opt.position.indexOf('up') > -1;
            var isLeft = _opt.position.indexOf('left') > -1;

            //transform animation
            if (isUp || isLeft) {
                for (var i = 0; i < animation.types['' + _opt.animation].length; i++) {
                    var step = animation.types['' + _opt.animation][i];

                    if (isUp) {
                        if (step.y < 0.6) {
                            step.y = step.y - 0.4;
                        } else {
                            step.y = step.y - 2 * step.y + (1 - step.w);
                        }
                    }

                    if (isLeft) {
                        if (step.x < 0.6) {
                            step.x = step.x - 0.4;
                        } else {
                            step.x = step.x - 2 * step.x + (1 - step.h);
                        }
                    }

                    animation.types['' + _opt.animation][i] = step;
                }
            }
            _opt.type = (type['' + _opt.type]) ? _opt.type : _def.type;
            try {
                _orig = link.getIcon();
                //create temp canvas
                _canvas = document.createElement('canvas');
                //create temp image
                _img = document.createElement('img');
                if (_orig.hasAttribute('href')) {
                    _img.setAttribute('src', _orig.getAttribute('href'));
                    //get width/height
                    _img.onload = function() {
                        _h = (_img.height > 0) ? _img.height : 32;
                        _w = (_img.width > 0) ? _img.width : 32;
                        _canvas.height = _h;
                        _canvas.width = _w;
                        _context = _canvas.getContext('2d');
                        icon.ready();
                    };
                } else {
                    _img.setAttribute('src', '');
                    _h = 32;
                    _w = 32;
                    _img.height = _h;
                    _img.width = _w;
                    _canvas.height = _h;
                    _canvas.width = _w;
                    _context = _canvas.getContext('2d');
                    icon.ready();
                }
            } catch(e) {
                throw 'Error initializing favico. Message: ' + e.message;
            }

        };
        /**
         * Icon namespace
         */
        var icon = {};
        /**
         * Icon is ready (reset icon) and start animation (if ther is any)
         */
        icon.ready = function() {
            _ready = true;
            icon.reset();
            _readyCb();
        };
        /**
         * Reset icon to default state
         */
        icon.reset = function() {
            //reset
            if (!_ready) {
                return;
            }
            _queue = [];
            _lastBadge = false;
            _context.clearRect(0, 0, _w, _h);
            _context.drawImage(_img, 0, 0, _w, _h);
            //_stop=true;
            link.setIcon(_canvas);
            //webcam('stop');
            //video('stop');
            window.clearTimeout(_animTimeout);
            window.clearTimeout(_drawTimeout);
        };
        /**
         * Start animation
         */
        icon.start = function() {
            if (!_ready || _running) {
                return;
            }
            var finished = function() {
                _lastBadge = _queue[0];
                _running = false;
                if (_queue.length > 0) {
                    _queue.shift();
                    icon.start();
                } else {

                }
            };
            if (_queue.length > 0) {
                _running = true;
                var run = function() {
                    // apply options for this animation
                    ['type', 'animation', 'bgColor', 'textColor',
                     'fontFamily', 'fontStyle'].forEach(function(a) {
                        if (a in _queue[0].options) {
                            _opt[a] = _queue[0].options[a];
                        }
                    });
                    animation.run(_queue[0].options, function() {
                        finished();
                    }, false);
                };
                if (_lastBadge) {
                    animation.run(_lastBadge.options, function() {
                        run();
                    }, true);
                } else {
                    run();
                }
            }
        };

        /**
         * Badge types
         */
        var type = {};
        var options = function(opt) {
            opt.n = ((typeof opt.n)==='number') ? Math.abs(opt.n|0) : opt.n;
            opt.x = _w * opt.x;
            opt.y = _h * opt.y;
            opt.w = _w * opt.w;
            opt.h = _h * opt.h;
            opt.len = ("" + opt.n).length;
            return opt;
        };
        /**
         * Generate circle
         * @param {Object} opt Badge options
         */
        type.circle = function(opt) {
            opt = options(opt);
            var more = false;
            if (opt.len === 2) {
                opt.x = opt.x - opt.w * 0.4;
                opt.w = opt.w * 1.4;
                more = true;
            } else if (opt.len >= 3) {
                opt.x = opt.x - opt.w * 0.65;
                opt.w = opt.w * 1.65;
                more = true;
            }
            _context.clearRect(0, 0, _w, _h);
            _context.drawImage(_img, 0, 0, _w, _h);
            _context.beginPath();
            _context.font = _opt.fontStyle + " " + Math.floor(opt.h * (opt.n > 99 ? 0.85 : 1)) + "px " + _opt.fontFamily;
            _context.textAlign = 'center';
            if (more) {
                _context.moveTo(opt.x + opt.w / 2, opt.y);
                _context.lineTo(opt.x + opt.w - opt.h / 2, opt.y);
                _context.quadraticCurveTo(opt.x + opt.w, opt.y, opt.x + opt.w, opt.y + opt.h / 2);
                _context.lineTo(opt.x + opt.w, opt.y + opt.h - opt.h / 2);
                _context.quadraticCurveTo(opt.x + opt.w, opt.y + opt.h, opt.x + opt.w - opt.h / 2, opt.y + opt.h);
                _context.lineTo(opt.x + opt.h / 2, opt.y + opt.h);
                _context.quadraticCurveTo(opt.x, opt.y + opt.h, opt.x, opt.y + opt.h - opt.h / 2);
                _context.lineTo(opt.x, opt.y + opt.h / 2);
                _context.quadraticCurveTo(opt.x, opt.y, opt.x + opt.h / 2, opt.y);
            } else {
                _context.arc(opt.x + opt.w / 2, opt.y + opt.h / 2, opt.h / 2, 0, 2 * Math.PI);
            }
            _context.fillStyle = 'rgba(' + _opt.bgColor.r + ',' + _opt.bgColor.g + ',' + _opt.bgColor.b + ',' + opt.o + ')';
            _context.fill();
            _context.closePath();
            _context.beginPath();
            _context.stroke();
            _context.fillStyle = 'rgba(' + _opt.textColor.r + ',' + _opt.textColor.g + ',' + _opt.textColor.b + ',' + opt.o + ')';
            //_context.fillText((more) ? '9+' : opt.n, Math.floor(opt.x + opt.w / 2), Math.floor(opt.y + opt.h - opt.h * 0.15));
            if ((typeof opt.n)==='number' && opt.n > 999) {
                _context.fillText(((opt.n > 9999) ? 9 : Math.floor(opt.n / 1000) ) + 'k+', Math.floor(opt.x + opt.w / 2), Math.floor(opt.y + opt.h - opt.h * 0.2));
            } else {
                _context.fillText(opt.n, Math.floor(opt.x + opt.w / 2), Math.floor(opt.y + opt.h - opt.h * 0.15));
            }
            _context.closePath();
        };
        /**
         * Generate rectangle
         * @param {Object} opt Badge options
         */
        type.rectangle = function(opt) {
            opt = options(opt);
            var more = false;
            if (opt.len === 2) {
                opt.x = opt.x - opt.w * 0.4;
                opt.w = opt.w * 1.4;
                more = true;
            } else if (opt.len >= 3) {
                opt.x = opt.x - opt.w * 0.65;
                opt.w = opt.w * 1.65;
                more = true;
            }
            _context.clearRect(0, 0, _w, _h);
            _context.drawImage(_img, 0, 0, _w, _h);
            _context.beginPath();
            _context.font = "bold " + Math.floor(opt.h * (opt.n > 99 ? 0.9 : 1)) + "px sans-serif";
            _context.textAlign = 'center';
            _context.fillStyle = 'rgba(' + _opt.bgColor.r + ',' + _opt.bgColor.g + ',' + _opt.bgColor.b + ',' + opt.o + ')';
            _context.fillRect(opt.x, opt.y, opt.w, opt.h);
            _context.fillStyle = 'rgba(' + _opt.textColor.r + ',' + _opt.textColor.g + ',' + _opt.textColor.b + ',' + opt.o + ')';
            //_context.fillText((more) ? '9+' : opt.n, Math.floor(opt.x + opt.w / 2), Math.floor(opt.y + opt.h - opt.h * 0.15));
            if ((typeof opt.n)==='number' && opt.len > 3) {
                _context.fillText(((opt.n > 9999) ? 9 : Math.floor(opt.n / 1000) ) + 'k+', Math.floor(opt.x + opt.w / 2), Math.floor(opt.y + opt.h - opt.h * 0.2));
            } else {
                _context.fillText(opt.n, Math.floor(opt.x + opt.w / 2), Math.floor(opt.y + opt.h - opt.h * 0.15));
            }
            _context.closePath();
        };

        /**
         * Set badge
         */
        var badge = function(number, opts) {
            opts = ((typeof opts)==='string' ? {animation:opts} : opts) || {};
            _readyCb = function() {
                try {
                    if (typeof(number)==='number' ? (number > 0) : (number !== '')) {
                        var q = {
                            type : 'badge',
                            options : {
                                n : number
                            }
                        };
                        if ('animation' in opts &&
                            animation.types['' + opts.animation]) {
                            q.options.animation = '' + opts.animation;
                        }
                        if ('type' in opts && type['' + opts.type]) {
                            q.options.type = '' + opts.type;
                        }
                        ['bgColor', 'textColor'].forEach(function(o) {
                            if (o in opts) {
                                q.options[o] = hexToRgb(opts[o]);
                            }
                        });
                        ['fontStyle', 'fontFamily'].forEach(function(o) {
                            if (o in opts) {
                                q.options[o] = opts[o];
                            }
                        });
                        _queue.push(q);
                        if (_queue.length > 100) {
                            throw 'Too many badges requests in queue.';
                        }
                        icon.start();
                    } else {
                        icon.reset();
                    }
                } catch(e) {
                    throw 'Error setting badge. Message: ' + e.message;
                }
            };
            if (_ready) {
                _readyCb();
            }
        };

        /**
         * Set image as icon
         */
        var image = function(imageElement) {
            _readyCb = function() {
                try {
                    var w = imageElement.width;
                    var h = imageElement.height;
                    var newImg = document.createElement('img');
                    var ratio = (w / _w < h / _h) ? (w / _w) : (h / _h);
                    newImg.setAttribute('src', imageElement.getAttribute('src'));
                    newImg.height = (h / ratio);
                    newImg.width = (w / ratio);
                    _context.clearRect(0, 0, _w, _h);
                    _context.drawImage(newImg, 0, 0, _w, _h);
                    link.setIcon(_canvas);
                } catch(e) {
                    throw 'Error setting image. Message: ' + e.message;
                }
            };
            if (_ready) {
                _readyCb();
            }
        };
        /**
         * Set video as icon
         */
        var video = function(videoElement) {
            _readyCb = function() {
                try {
                    if (videoElement === 'stop') {
                        _stop = true;
                        icon.reset();
                        _stop = false;
                        return;
                    }
                    //var w = videoElement.width;
                    //var h = videoElement.height;
                    //var ratio = (w / _w < h / _h) ? (w / _w) : (h / _h);
                    videoElement.addEventListener('play', function() {
                        drawVideo(this);
                    }, false);

                } catch(e) {
                    throw 'Error setting video. Message: ' + e.message;
                }
            };
            if (_ready) {
                _readyCb();
            }
        };
        /**
         * Set video as icon
         */
        var webcam = function(action) {
            //UR
            if (!window.URL || !window.URL.createObjectURL) {
                window.URL = window.URL || {};
                window.URL.createObjectURL = function(obj) {
                    return obj;
                };
            }
            if (_browser.supported) {
                var newVideo = false;
                navigator.getUserMedia = navigator.getUserMedia || navigator.oGetUserMedia || navigator.msGetUserMedia || navigator.mozGetUserMedia || navigator.webkitGetUserMedia;
                _readyCb = function() {
                    try {
                        if (action === 'stop') {
                            _stop = true;
                            icon.reset();
                            _stop = false;
                            return;
                        }
                        newVideo = document.createElement('video');
                        newVideo.width = _w;
                        newVideo.height = _h;
                        navigator.getUserMedia({
                            video : true,
                            audio : false
                        }, function(stream) {
                            newVideo.src = URL.createObjectURL(stream);
                            newVideo.play();
                            drawVideo(newVideo);
                        }, function() {
                        });
                    } catch(e) {
                        throw 'Error setting webcam. Message: ' + e.message;
                    }
                };
                if (_ready) {
                    _readyCb();
                }
            }

        };

        /**
         * Draw video to context and repeat :)
         */
        function drawVideo(video) {
            if (video.paused || video.ended || _stop) {
                return false;
            }
            //nasty hack for FF webcam (Thanks to Julian Ćwirko, kontakt@redsunmedia.pl)
            try {
                _context.clearRect(0, 0, _w, _h);
                _context.drawImage(video, 0, 0, _w, _h);
            } catch(e) {

            }
            _drawTimeout = setTimeout(drawVideo, animation.duration, video);
            link.setIcon(_canvas);
        }

        var link = {};
        /**
         * Get icon from HEAD tag or create a new <link> element
         */
        link.getIcon = function() {
            var elm = false;
            var url = '';
            //get link element
            var getLink = function() {
                var link = document.getElementsByTagName('head')[0].getElementsByTagName('link');
                for (var l = link.length, i = (l - 1); i >= 0; i--) {
                    if ((/(^|\s)icon(\s|$)/i).test(link[i].getAttribute('rel'))) {
                        return link[i];
                    }
                }
                return false;
            };
            if (_opt.elementId) {
                //if img element identified by elementId
                elm = document.getElementById(_opt.elementId);
                elm.setAttribute('href', elm.getAttribute('src'));
            } else {
                //if link element
                elm = getLink();
                if (elm === false) {
                    elm = document.createElement('link');
                    elm.setAttribute('rel', 'icon');
                    document.getElementsByTagName('head')[0].appendChild(elm);
                }
            }
            //check if image and link url is on same domain. if not raise error
            url = (_opt.elementId) ? elm.src : elm.href;
            if (url.indexOf(document.location.hostname) === -1) {
                throw new Error('Error setting favicon. Favicon image is on different domain (Icon: ' + url + ', Domain: ' + document.location.hostname + ')');
            }
            elm.setAttribute('type', 'image/png');
            return elm;
        };
        link.setIcon = function(canvas) {
            var url = canvas.toDataURL('image/png');
            if (_opt.elementId) {
                //if is attached to element (image)
                document.getElementById(_opt.elementId).setAttribute('src', url);
            } else {
                //if is attached to fav icon
                if (_browser.ff || _browser.opera) {
                    //for FF we need to "recreate" element, atach to dom and remove old <link>
                    //var originalType = _orig.getAttribute('rel');
                    var old = _orig;
                    _orig = document.createElement('link');
                    //_orig.setAttribute('rel', originalType);
                    if (_browser.opera) {
                        _orig.setAttribute('rel', 'icon');
                    }
                    _orig.setAttribute('rel', 'icon');
                    _orig.setAttribute('type', 'image/png');
                    document.getElementsByTagName('head')[0].appendChild(_orig);
                    _orig.setAttribute('href', url);
                    if (old.parentNode) {
                        old.parentNode.removeChild(old);
                    }
                } else {
                    _orig.setAttribute('href', url);
                }
            }
        };

        //http://stackoverflow.com/questions/5623838/rgb-to-hex-and-hex-to-rgb#answer-5624139
        //HEX to RGB convertor
        function hexToRgb(hex) {
            var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
            hex = hex.replace(shorthandRegex, function(m, r, g, b) {
                return r + r + g + g + b + b;
            });
            var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
            return result ? {
                r : parseInt(result[1], 16),
                g : parseInt(result[2], 16),
                b : parseInt(result[3], 16)
            } : false;
        }

        /**
         * Merge options
         */
        function merge(def, opt) {
            var mergedOpt = {};
            var attrname;
            for (attrname in def) {
                mergedOpt[attrname] = def[attrname];
            }
            for (attrname in opt) {
                mergedOpt[attrname] = opt[attrname];
            }
            return mergedOpt;
        }

        /**
         * Cross-browser page visibility shim
         * http://stackoverflow.com/questions/12536562/detect-whether-a-window-is-visible
         */
        function isPageHidden() {
            return document.hidden || document.msHidden || document.webkitHidden || document.mozHidden;
        }

        /**
         * @namespace animation
         */
        var animation = {};
        /**
         * Animation "frame" duration
         */
        animation.duration = 40;
        /**
         * Animation types (none,fade,pop,slide)
         */
        animation.types = {};
        animation.types.fade = [{
            x : 0.4,
            y : 0.4,
            w : 0.6,
            h : 0.6,
            o : 0.0
        }, {
            x : 0.4,
            y : 0.4,
            w : 0.6,
            h : 0.6,
            o : 0.1
        }, {
            x : 0.4,
            y : 0.4,
            w : 0.6,
            h : 0.6,
            o : 0.2
        }, {
            x : 0.4,
            y : 0.4,
            w : 0.6,
            h : 0.6,
            o : 0.3
        }, {
            x : 0.4,
            y : 0.4,
            w : 0.6,
            h : 0.6,
            o : 0.4
        }, {
            x : 0.4,
            y : 0.4,
            w : 0.6,
            h : 0.6,
            o : 0.5
        }, {
            x : 0.4,
            y : 0.4,
            w : 0.6,
            h : 0.6,
            o : 0.6
        }, {
            x : 0.4,
            y : 0.4,
            w : 0.6,
            h : 0.6,
            o : 0.7
        }, {
            x : 0.4,
            y : 0.4,
            w : 0.6,
            h : 0.6,
            o : 0.8
        }, {
            x : 0.4,
            y : 0.4,
            w : 0.6,
            h : 0.6,
            o : 0.9
        }, {
            x : 0.4,
            y : 0.4,
            w : 0.6,
            h : 0.6,
            o : 1.0
        }];
        animation.types.none = [{
            x : 0.4,
            y : 0.4,
            w : 0.6,
            h : 0.6,
            o : 1
        }];
        animation.types.pop = [{
            x : 1,
            y : 1,
            w : 0,
            h : 0,
            o : 1
        }, {
            x : 0.9,
            y : 0.9,
            w : 0.1,
            h : 0.1,
            o : 1
        }, {
            x : 0.8,
            y : 0.8,
            w : 0.2,
            h : 0.2,
            o : 1
        }, {
            x : 0.7,
            y : 0.7,
            w : 0.3,
            h : 0.3,
            o : 1
        }, {
            x : 0.6,
            y : 0.6,
            w : 0.4,
            h : 0.4,
            o : 1
        }, {
            x : 0.5,
            y : 0.5,
            w : 0.5,
            h : 0.5,
            o : 1
        }, {
            x : 0.4,
            y : 0.4,
            w : 0.6,
            h : 0.6,
            o : 1
        }];
        animation.types.popFade = [{
            x : 0.75,
            y : 0.75,
            w : 0,
            h : 0,
            o : 0
        }, {
            x : 0.65,
            y : 0.65,
            w : 0.1,
            h : 0.1,
            o : 0.2
        }, {
            x : 0.6,
            y : 0.6,
            w : 0.2,
            h : 0.2,
            o : 0.4
        }, {
            x : 0.55,
            y : 0.55,
            w : 0.3,
            h : 0.3,
            o : 0.6
        }, {
            x : 0.50,
            y : 0.50,
            w : 0.4,
            h : 0.4,
            o : 0.8
        }, {
            x : 0.45,
            y : 0.45,
            w : 0.5,
            h : 0.5,
            o : 0.9
        }, {
            x : 0.4,
            y : 0.4,
            w : 0.6,
            h : 0.6,
            o : 1
        }];
        animation.types.slide = [{
            x : 0.4,
            y : 1,
            w : 0.6,
            h : 0.6,
            o : 1
        }, {
            x : 0.4,
            y : 0.9,
            w : 0.6,
            h : 0.6,
            o : 1
        }, {
            x : 0.4,
            y : 0.9,
            w : 0.6,
            h : 0.6,
            o : 1
        }, {
            x : 0.4,
            y : 0.8,
            w : 0.6,
            h : 0.6,
            o : 1
        }, {
            x : 0.4,
            y : 0.7,
            w : 0.6,
            h : 0.6,
            o : 1
        }, {
            x : 0.4,
            y : 0.6,
            w : 0.6,
            h : 0.6,
            o : 1
        }, {
            x : 0.4,
            y : 0.5,
            w : 0.6,
            h : 0.6,
            o : 1
        }, {
            x : 0.4,
            y : 0.4,
            w : 0.6,
            h : 0.6,
            o : 1
        }];
        /**
         * Run animation
         * @param {Object} opt Animation options
         * @param {Object} cb Callabak after all steps are done
         * @param {Object} revert Reverse order? true|false
         * @param {Object} step Optional step number (frame bumber)
         */
        animation.run = function(opt, cb, revert, step) {
            var animationType = animation.types[isPageHidden() ? 'none' : _opt.animation];
            if (revert === true) {
                step = ( typeof step !== 'undefined') ? step : animationType.length - 1;
            } else {
                step = ( typeof step !== 'undefined') ? step : 0;
            }
            cb = (cb) ? cb : function() {
            };
            if ((step < animationType.length) && (step >= 0)) {
                type[_opt.type](merge(opt, animationType[step]));
                _animTimeout = setTimeout(function() {
                    if (revert) {
                        step = step - 1;
                    } else {
                        step = step + 1;
                    }
                    animation.run(opt, cb, revert, step);
                }, animation.duration);

                link.setIcon(_canvas);
            } else {
                cb();
                return;
            }
        };
        //auto init
        init();
        return {
            badge : badge,
            video : video,
            image : image,
            webcam : webcam,
            reset : icon.reset
        };
    });

    // AMD / RequireJS
    if ( typeof define !== 'undefined' && define.amd) {
        define([], function() {
            return Favico;
        });
    }
    // CommonJS
    else if ( typeof module !== 'undefined' && module.exports) {
        module.exports = Favico;
    }
    // included directly via <script> tag
    else {
        this.Favico = Favico;
    }

})();
<commit_msg>Removed favico.js (there is already a minified version)<commit_after><|endoftext|>


<commit_before>import {default as React} from "react";

const {PropTypes} = React;

class ReactHtml extends React.Component {

  _render_link_to_stylesheet_ (clientAssets) {
    if (clientAssets["client"]) {
      return (
        <link rel="stylesheet" href={clientAssets["client"].replace(/js$/, "css")} />
      );
    }
  }

  render () {
    const {props, state} = this,
          {clientAssets} = props,
          innerHtml = {__html: props.componentString};

    return (

          <title>React Google Maps | tomchentw</title>
          <link href="http://fonts.googleapis.com/css?family=Roboto:400,300,500" rel="stylesheet" type="text/css" />
          {this._render_link_to_stylesheet_(clientAssets)}