<commit_before>/*
 * jQuery-handlebars
 * https://github.com/softwarespot/jquery-handlebars
 * Author: softwarespot
 * Licensed under the MIT license
 * Version: 0.1.0-beta
 */
; (function ($, undefined) {

    // Initial idea from: http://blog.teamtreehouse.com/handlebars-js-part-3-tips-and-tricks

    // Plugin Logic
    $.fn.extend({

        // data doubles up as options when the action is either 'clear' or 'remove'
        handlebars: function (action, template, dataOrOptions, options) {

            // jQuery object reference for this. Only select the first selector of the collection
            var $this = $(this).first(),

                // Store whether the template is valid or not
                isTemplate = typeof template === 'string' && /^#[\w\-]+$/.test(template);

            // If a 'get' action is provided, then get the template(s)
            // The template string if not defined will return all template(s)
            if (typeof action === 'string' && /^FIND|GET$/i.test(action)) {

                // The include parameter will be true, if the template is a string and valid anchor
                return getTemplate($this, template, isTemplate);

            }

            // Set our options from the defaults, overriding with the
            // parameter we pass into this function
            options = $.extend({}, $.fn.handlebars.options, options);

            // START: Sanitize the options

            // Check if the option type is a string and valid
            if (typeof options.type === 'string' && /^APPEND|FILL|REFILL$/i.test(options.type)) {

                // Set to uppercase
                options.type = options.type.toUpperCase();

            } else {

                // Otherwise default to 'append' i.e. if null or simply is invalid
                options.type = Type.APPEND;

            }

            // If the removal type is a string and valid, then set to uppercase
            if (typeof options.remove_type === 'string' && /^ALL|NONE|SAME$/i.test(options.remove_type)) {

                // Set to uppercase
                options.remove_type = options.remove_type.toUpperCase();

            } else {

                // Otherwise default to 'none' i.e. if null or simply is invalid
                options.remove_type = Remove.NONE;

            }

            // END: Sanitize the options

            // If a 'clear' action is provided, then remove the template from the content element
            if (/^CLEAR|REMOVE$/i.test(action)) {

                // Extend the options again, as the dataOrOptions acts as an alias for options when a removal action is
                // specified
                options = $.extend(options, dataOrOptions);

                // If the options parameter is not the 'same' and a template string exists, the
                // temporarily override
                if (isTemplate && options.remove_type !== Remove.SAME) {

                    options.remove_type = Remove.SAME;

                } else {

                    // Otherwise use 'all'
                    options.remove_type = Remove.ALL;

                }

                // If the template is not defined, then set as null before removing
                if (!isTemplate) {

                    template = null;

                }

                return removeTemplate(this, $this, template, options);

            }

            // Assume it's an addition i.e. 'add'

            // The data object literal must contain data
            if (typeof options.validate === 'boolean' && options.validate && $.isEmptyObject(dataOrOptions)) {

                console.log('jQuery-handlebars: Data was not passed to the plugin or is simply an empty plain object');
                return this;

            }

            // jQuery object reference
            var $selector = null;

            // If a valid string template is passed then check if it's compiled or get the jQuery object instead
            if (isTemplate) {

                // If compiled already then no need to re-compile
                if (typeof compiled[template] === 'function') {

                    // Debugging only
                    console.log('jQuery-handlebars: ' + template + ' already exists');

                    // Return to continue chaining
                    return setTemplate(this, $this, template, dataOrOptions, options);

                }

                // Not compiled

                // Get the first selection only
                $selector = $(template).first();

                // If the selector doesn't exist for whatever reason, then set to null
                if ($selector.length === 0) {

                    $selector = null;

                }

                // If a valid jQuery selector object
            } else if (template instanceof $ && typeof template.length === 'number' && template.length > 0) {

                // Get the first selection only
                $selector = template.first();

                // Get the selector name for using with the compiled object literal
                // If the selector property doesn't exist, then this will be set to null
                template = typeof $selector.selector !== 'undefined' ? $selector.selector : null;

                // If compiled already then no need to re-compile
                if (template !== null && typeof compiled[template] === 'function') {

                    // Debugging only
                    console.log('jQuery-handlebars: %s already exists', template);

                    // Return to continue chaining
                    return setTemplate(this, $this, template, dataOrOptions, options);

                }
            }

            // If an invalid selector, then return this to continue chaining
            if ($selector === null || template === null || $selector.length === 0) {

                // Debugging only
                console.log('jQuery-handlebars: Template cannot be found');
                return this;

            }

            // Get the HTML of the template only
            var html = $selector.html();

            // Store the compiled template in the compiled store
            compiled[template] = Handlebars.compile(html);

            // Return to continue chaining
            return setTemplate(this, $this, template, dataOrOptions, options);
        }

    });

    // Fields (Private)

    // Store the compiled template(s) using the template string as the identifier i.e. key
    var compiled = {};

    // Methods (Private)

    // Note: Variable are called 'self' to avoid conflict with 'this'

    // Get the template in the content selector
    // include refers to whether to include the template in the selection
    var getTemplate = function ($self, template, include) {

            // Get the divs with the template data attribute and optional specified template string e.g. #some-template
            var templateLocate = (include && template ? '="' + template + '"' : '');
            return $self.find('div[' + DATA_ATTRIBUTE + templateLocate + ']');

        },

        // Remove the specified template from the content selector. If a template is not provided
        // then all template(s) that are contained within the content selector will be removed
        removeTemplate = function (self, $self, template, options) {

            // If the option has been passed to remove 'none', then respect this choice
            if (options.remove_type === Remove.NONE) {

                // Debugging only
                console.log('jQuery-handlebars: Template(s) were not removed [%s]', options.remove_type);

                // Return self to maintain chaining if there is nothing to remove
                return self;

            }

            var filtered = getTemplate($self, template, options.remove_type === Remove.SAME);
            if (filtered.length === 0) {

                // Debugging only
                console.log('jQuery-handlebars: Unable to find any template(s) for removal [%s]', options.remove_type);

                // Return self to maintain chaining if there is nothing to remove
                return self;

            }

            // Remove from the DOM
            filtered.remove();

            // Debugging only
            console.log('jQuery-handlebars: Removing template(s) [%s]', options.remove_type);

            // Remove the template from the compiled store, if the option is true
            if (typeof options.delete_compiled === 'boolean' && options.delete_compiled) {

                // Iterate through the filtered collection and remove from the template string from the compiled store
                $.each(filtered, function (index, element) {

                    // Get the data attribute for the template string if it's not null or has already been removed
                    var attribute = $(this).attr(DATA_ATTRIBUTE);
                    if (attribute === null || compiled[attribute] === undefined) {

                        return;

                    }

                    // Set to undefined to mimic deletion of the template
                    compiled[attribute] = undefined;

                    // Debugging only
                    console.log('jQuery-handlebars: Removing compiled template [%s]', attribute);

                });

                if (template !== null) {

                    // Debugging only
                    console.log('jQuery-handlebars: Removed the template from the compiled store [%s]', template);

                }

            }

        },

        // Set the specified template to the content selector
        setTemplate = function (self, $self, template, data, options) {

            // Previous implementations
            /*
                $self.children('*').not('script[type="text/x-handlebars-template"]').empty();
                $self.children('*:not(script[type="text/x-handlebars-template"])').empty();

                // Get all nodes apart from the Handlebarjs template script elements
                 var filtered = $self.contents().filter(function () {

                    return this.nodeType !== Node.COMMENT_NODE && // Not a comment
                        (this.nodeName !== 'SCRIPT' && this.type !== 'text/x-handlebars-template') // Not a handlebars template
                        ; // /[^\t\n\r ]/.test(this.textContent); // Not whitespace

                });
             */

            // The include parameter will be set to true, when specifically looking for the provided template string
            var filtered = getTemplate($self, template, options.remove_type === Remove.SAME);

            // Remove from the DOM if specified to do so
            if (options.remove_type !== Remove.NONE) {

                // Remove from the DOM
                filtered.remove();

                // Debugging only
                console.log('jQuery-handlebars: Removed previous template(s) [%s]', options.remove_type);

            }

            // If set to not refill and template node(s) exist, then return this
            if (typeof options.refill === 'boolean' && !options.refill) {

                // Get the template(s) after potential removal. The parameter include has been set to true, as we are checking
                // if only the same template(s) exists (perhaps an option could/should be created)
                filtered = getTemplate($self, template, true);
                if (filtered.length > 0) {

                    // Debugging only
                    console.log('jQuery-handlebars: Refill has been set to false and the content element contains template(s) [%s]', options.remove_type);

                    return self;

                }

            }

            // Append to the content element by checking the type. Default is 'append'
            switch (options.type) {
                case 'FILL':
                case 'REFILL':
                    // $self.html(compiled[template](data)); // Dangerous to do if handlebarsjs template(s) are embedded inside the element

                    // Debugging only
                    console.log('jQuery-handlebars: The type fill/refill is NOT implemented [%s]', template);
                    break;

                default:
                    // Create a div element with the template appended to it
                    // This contains a data-* attribute called data-jquery-handlebars for easy association
                    // that it's a Handlebarjs template
                    var $div = $('<div/>')
                        .attr(DATA_ATTRIBUTE, template)
                        .append(compiled[template](data));

                    // Append the div to content element
                    $self.append($div);

                    // Debugging only
                    console.log('jQuery-handlebars: Appending template to the content element [%s]', template);
                    break;
            }

            return self;
        };

    // Constants

    // The data-* attribute name
    var DATA_ATTRIBUTE = 'data-jquery-handlebars',

        // Removal constants. Who enjoys magic values?
        Remove = {
            ALL: 'ALL',
            NONE: 'NONE',
            SAME: 'SAME'
        },

        // Type constants. Who enjoys magic values?
        Type = {
            APPEND: 'APPEND',
            FILL: 'FILL',
            REFILL: 'REFILL'
        };

    // Defaults

    $.fn.handlebars.options = {
        // Delete the template from the compiled store on removal
        delete_compiled: true,

        // Allow the option of adding multiple template(s) inside an element
        refill: true,

        // Remove pre-existing templates from the content element
        // The following options are:
        //      'all': Remove all valid template(s) from the content element
        //      'same': Remove only those template(s) that match the provided template string
        //      'none' (default): Don't remove any template(s)
        remove_type: Remove.NONE,

        // Type of writing: fill, refill, append (default)
        // type: Type.APPEND,

        // Check whether the data passed is empty
        validate: true
    };

})(jQuery);
<commit_msg>Updated debug comment about being already compiled<commit_after>/*
 * jQuery-handlebars
 * https://github.com/softwarespot/jquery-handlebars
 * Author: softwarespot
 * Licensed under the MIT license
 * Version: 0.1.0-beta
 */
; (function ($, undefined) {

    // Initial idea from: http://blog.teamtreehouse.com/handlebars-js-part-3-tips-and-tricks

    // Plugin Logic
    $.fn.extend({

        // data doubles up as options when the action is either 'clear' or 'remove'
        handlebars: function (action, template, dataOrOptions, options) {

            // jQuery object reference for this. Only select the first selector of the collection
            var $this = $(this).first(),

                // Store whether the template is valid or not
                isTemplate = typeof template === 'string' && /^#[\w\-]+$/.test(template);

            // If a 'get' action is provided, then get the template(s)
            // The template string if not defined will return all template(s)
            if (typeof action === 'string' && /^FIND|GET$/i.test(action)) {

                // The include parameter will be true, if the template is a string and valid anchor
                return getTemplate($this, template, isTemplate);

            }

            // Set our options from the defaults, overriding with the
            // parameter we pass into this function
            options = $.extend({}, $.fn.handlebars.options, options);

            // START: Sanitize the options

            // Check if the option type is a string and valid
            if (typeof options.type === 'string' && /^APPEND|FILL|REFILL$/i.test(options.type)) {

                // Set to uppercase
                options.type = options.type.toUpperCase();

            } else {

                // Otherwise default to 'append' i.e. if null or simply is invalid
                options.type = Type.APPEND;

            }

            // If the removal type is a string and valid, then set to uppercase
            if (typeof options.remove_type === 'string' && /^ALL|NONE|SAME$/i.test(options.remove_type)) {

                // Set to uppercase
                options.remove_type = options.remove_type.toUpperCase();

            } else {

                // Otherwise default to 'none' i.e. if null or simply is invalid
                options.remove_type = Remove.NONE;

            }

            // END: Sanitize the options

            // If a 'clear' action is provided, then remove the template from the content element
            if (/^CLEAR|REMOVE$/i.test(action)) {

                // Extend the options again, as the dataOrOptions acts as an alias for options when a removal action is
                // specified
                options = $.extend(options, dataOrOptions);

                // If the options parameter is not the 'same' and a template string exists, the
                // temporarily override
                if (isTemplate && options.remove_type !== Remove.SAME) {

                    options.remove_type = Remove.SAME;

                } else {

                    // Otherwise use 'all'
                    options.remove_type = Remove.ALL;

                }

                // If the template is not defined, then set as null before removing
                if (!isTemplate) {

                    template = null;

                }

                return removeTemplate(this, $this, template, options);

            }

            // Assume it's an addition i.e. 'add'

            // The data object literal must contain data
            if (typeof options.validate === 'boolean' && options.validate && $.isEmptyObject(dataOrOptions)) {

                console.log('jQuery-handlebars: Data was not passed to the plugin or is simply an empty plain object');
                return this;

            }

            // jQuery object reference
            var $selector = null;

            // If a valid string template is passed then check if it's compiled or get the jQuery object instead
            if (isTemplate) {

                // If compiled already then no need to re-compile
                if (typeof compiled[template] === 'function') {

                    // Debugging only
                    console.log('jQuery-handlebars: %s has already been compiled', template);

                    // Return to continue chaining
                    return setTemplate(this, $this, template, dataOrOptions, options);

                }

                // Not compiled

                // Get the first selection only
                $selector = $(template).first();

                // If the selector doesn't exist for whatever reason, then set to null
                if ($selector.length === 0) {

                    $selector = null;

                }

                // If a valid jQuery selector object
            } else if (template instanceof $ && typeof template.length === 'number' && template.length > 0) {

                // Get the first selection only
                $selector = template.first();

                // Get the selector name for using with the compiled object literal
                // If the selector property doesn't exist, then this will be set to null
                template = typeof $selector.selector !== 'undefined' ? $selector.selector : null;

                // If compiled already then no need to re-compile
                if (template !== null && typeof compiled[template] === 'function') {

                    // Debugging only
                    console.log('jQuery-handlebars: %s has already been compiled', template);

                    // Return to continue chaining
                    return setTemplate(this, $this, template, dataOrOptions, options);

                }
            }

            // If an invalid selector, then return this to continue chaining
            if ($selector === null || template === null || $selector.length === 0) {

                // Debugging only
                console.log('jQuery-handlebars: Template cannot be found');
                return this;

            }

            // Get the HTML of the template only
            var html = $selector.html();

            // Store the compiled template in the compiled store
            compiled[template] = Handlebars.compile(html);

            // Return to continue chaining
            return setTemplate(this, $this, template, dataOrOptions, options);
        }

    });

    // Fields (Private)

    // Store the compiled template(s) using the template string as the identifier i.e. key
    var compiled = {};

    // Methods (Private)

    // Note: Variable are called 'self' to avoid conflict with 'this'

    // Get the template in the content selector
    // include refers to whether to include the template in the selection
    var getTemplate = function ($self, template, include) {

            // Get the divs with the template data attribute and optional specified template string e.g. #some-template
            var templateLocate = (include && template ? '="' + template + '"' : '');
            return $self.find('div[' + DATA_ATTRIBUTE + templateLocate + ']');

        },

        // Remove the specified template from the content selector. If a template is not provided
        // then all template(s) that are contained within the content selector will be removed
        removeTemplate = function (self, $self, template, options) {

            // If the option has been passed to remove 'none', then respect this choice
            if (options.remove_type === Remove.NONE) {

                // Debugging only
                console.log('jQuery-handlebars: Template(s) were not removed [%s]', options.remove_type);

                // Return self to maintain chaining if there is nothing to remove
                return self;

            }

            var filtered = getTemplate($self, template, options.remove_type === Remove.SAME);
            if (filtered.length === 0) {

                // Debugging only
                console.log('jQuery-handlebars: Unable to find any template(s) for removal [%s]', options.remove_type);

                // Return self to maintain chaining if there is nothing to remove
                return self;

            }

            // Remove from the DOM
            filtered.remove();

            // Debugging only
            console.log('jQuery-handlebars: Removing template(s) [%s]', options.remove_type);

            // Remove the template from the compiled store, if the option is true
            if (typeof options.delete_compiled === 'boolean' && options.delete_compiled) {

                // Iterate through the filtered collection and remove from the template string from the compiled store
                $.each(filtered, function (index, element) {

                    // Get the data attribute for the template string if it's not null or has already been removed
                    var attribute = $(this).attr(DATA_ATTRIBUTE);
                    if (attribute === null || compiled[attribute] === undefined) {

                        return;

                    }

                    // Set to undefined to mimic deletion of the template
                    compiled[attribute] = undefined;

                    // Debugging only
                    console.log('jQuery-handlebars: Removing compiled template [%s]', attribute);

                });

                if (template !== null) {

                    // Debugging only
                    console.log('jQuery-handlebars: Removed the template from the compiled store [%s]', template);

                }

            }

        },

        // Set the specified template to the content selector
        setTemplate = function (self, $self, template, data, options) {

            // Previous implementations
            /*
                $self.children('*').not('script[type="text/x-handlebars-template"]').empty();
                $self.children('*:not(script[type="text/x-handlebars-template"])').empty();

                // Get all nodes apart from the Handlebarjs template script elements
                 var filtered = $self.contents().filter(function () {

                    return this.nodeType !== Node.COMMENT_NODE && // Not a comment
                        (this.nodeName !== 'SCRIPT' && this.type !== 'text/x-handlebars-template') // Not a handlebars template
                        ; // /[^\t\n\r ]/.test(this.textContent); // Not whitespace

                });
             */

            // The include parameter will be set to true, when specifically looking for the provided template string
            var filtered = getTemplate($self, template, options.remove_type === Remove.SAME);

            // Remove from the DOM if specified to do so
            if (options.remove_type !== Remove.NONE) {

                // Remove from the DOM
                filtered.remove();

                // Debugging only
                console.log('jQuery-handlebars: Removed previous template(s) [%s]', options.remove_type);

            }

            // If set to not refill and template node(s) exist, then return this
            if (typeof options.refill === 'boolean' && !options.refill) {

                // Get the template(s) after potential removal. The parameter include has been set to true, as we are checking
                // if only the same template(s) exists (perhaps an option could/should be created)
                filtered = getTemplate($self, template, true);
                if (filtered.length > 0) {

                    // Debugging only
                    console.log('jQuery-handlebars: Refill has been set to false and the content element contains template(s) [%s]', options.remove_type);

                    return self;

                }

            }

            // Append to the content element by checking the type. Default is 'append'
            switch (options.type) {
                case 'FILL':
                case 'REFILL':
                    // $self.html(compiled[template](data)); // Dangerous to do if handlebarsjs template(s) are embedded inside the element

                    // Debugging only
                    console.log('jQuery-handlebars: The type fill/refill is NOT implemented [%s]', template);
                    break;

                default:
                    // Create a div element with the template appended to it
                    // This contains a data-* attribute called data-jquery-handlebars for easy association
                    // that it's a Handlebarjs template
                    var $div = $('<div/>')
                        .attr(DATA_ATTRIBUTE, template)
                        .append(compiled[template](data));

                    // Append the div to content element
                    $self.append($div);

                    // Debugging only
                    console.log('jQuery-handlebars: Appending template to the content element [%s]', template);
                    break;
            }

            return self;
        };

    // Constants

    // The data-* attribute name
    var DATA_ATTRIBUTE = 'data-jquery-handlebars',

        // Removal constants. Who enjoys magic values?
        Remove = {
            ALL: 'ALL',
            NONE: 'NONE',
            SAME: 'SAME'
        },

        // Type constants. Who enjoys magic values?
        Type = {
            APPEND: 'APPEND',
            FILL: 'FILL',
            REFILL: 'REFILL'
        };

    // Defaults

    $.fn.handlebars.options = {
        // Delete the template from the compiled store on removal
        delete_compiled: true,

        // Allow the option of adding multiple template(s) inside an element
        refill: true,

        // Remove pre-existing templates from the content element
        // The following options are:
        //      'all': Remove all valid template(s) from the content element
        //      'same': Remove only those template(s) that match the provided template string
        //      'none' (default): Don't remove any template(s)
        remove_type: Remove.NONE,

        // Type of writing: fill, refill, append (default)
        // type: Type.APPEND,

        // Check whether the data passed is empty
        validate: true
    };

})(jQuery);
<|endoftext|>


<commit_before><commit_msg>bug fix<commit_after><|endoftext|>


<commit_before>
var hundo = {}

hundo.PieceTypeEnum = {
    BALL: "BALL",
    BLOCK: "BLOCK"
}

hundo.DirectionEnum = {
    UP: 0,
    DOWN: 1,
    LEFT: 2,
    RIGHT: 3,
    NODIR: 4
}

// every piece has unique id
hundo.Block = function(id, row, col) {
    this.id = id;
    this.type = hundo.PieceTypeEnum.BLOCK;
    this.row = row;
    this.col = col;
}

hundo.Ball = function(id, row, col) {
    this.id = id;
    this.type = hundo.PieceTypeEnum.BALL;
    this.row = row;
    this.col = col;
    this.dir = hundo.PieceTypeEnum.NODIR;
}

// TODO: Assume boardConfig is untrusted
hundo.Board = function(boardConfig) {

    this.numRows = boardConfig.numRows;
    this.numCols = boardConfig.numCols;

    // this.matrix[row][call] == array of piece objects
    this.matrix = new Array(this.numRows);
    for (var i = 0; i < this.numRows; i++) {
      this.matrix[i] = new Array(this.numCols);
      for (var j = 0; j < this.numCols; j++) {
        this.matrix[i][j] = new Array();
      }
    }

    var nextId = 0;

    var THIS = this;

    // Add blocks to the matrix
    $.each(boardConfig.blocks, function(index, block) {
        var row = block.row;
        var col = block.col;
        THIS.matrix[row][col].push(new hundo.Block(nextId++, row, col));
    })

    // Add the ball to the matrix
    var row = boardConfig.ball.row;
    var col = boardConfig.ball.col;
    this.matrix[row][col].push(new hundo.Ball(nextId++, row, col));

}

// func(piece) should return true iff the piece is of the type being gotten
hundo.Board.prototype.getPieces = function(func) {

    var pieces = [];

    $.each(this.matrix, function(i, row) {
        $.each(row, function(j, col) {
            $.each(col, function(k, piece) {
                if (func(piece)) {
                    pieces.push(piece);
                }
            })
        })
    });

    return pieces;
}

hundo.Board.prototype.getBlocks = function() {
    return this.getPieces(function(piece){
        return piece.type == hundo.PieceTypeEnum.BLOCK;
    });
};

hundo.Board.prototype.getBalls = function() {
    return this.getPieces(function(piece){
        return piece.type == hundo.PieceTypeEnum.BALL;
    });
};

// removes the first element in array for which func(element) is true
// if an element is removed, returns the index of the element removed
// otherwise, returns -1
hundo.arrayRemove = function(array, func) {

    var i;
    for (i = 0; i < array.length; i++) {
        if (func(array[i])) {
            break;
        }
    }

    if (i == array.length) {
        return -1;
    }

    array.splice(i, 1);

    return i;
}

hundo.Board.prototype.movePiece = function(piece, row, col) {

    var pieces = this.matrix[piece.row][piece.col];

    var i = hundo.arrayRemove(pieces, function(p) {
        return p.id == piece.id;
    })

    if (i == -1) {
        console.error("Could not remove piece");
        return;
    }

    // add the piece to its new location
    this.matrix[row][col].push(piece);

    piece.row = row;
    piece.col = col;

}

// returns null on fatal error
// else, returns an animation object, which describes how the
// the step should be animated
hundo.Board.prototype.step = function() {

    var direction = ball.dir;

    if (direction == DirectionEnum.NODIR) {
        console.error("Ball must have a direction to step");
        return;
    }

    var dr = 0, dc = 0;
    if (direction == DirectionEnum.UP) {
        dr = -1;
    } else if (direction == DirectionEnum.DOWN) {
        dr = 1;
    } else if (direction == DirectionEnum.LEFT) {
        dc = -1;
    } else if (direction == DirectionEnum.RIGHT) {
        dc = 1;
    } else {
        console.error("Ball must have a direction to step");
        return;
    }

    var newRow = this.ball.row + dr;
    var newCol = this.ball.col + dc;

    // Check for out of bounds
    if (newRow < 0 || newRow > this.numRows ||
        newCol < 0 || newColcol > this.numCols) {

        // TODO: update matrix state

        return {
            "move": {
                "dir": "direction"
            },
            "oob": true
        };
    }

    if (this.matrix[newRow][newCol].length > 0) {
        return {
            "collide": {
                "dir": direction,
                "recipients": [this.matrix[newRow][newCol]]
            }
        };
    } else {
        this.movePiece(this.ball, newRow, newCol);
        return {
            "move": {
                "dir": direction
            }
        }
    }
}

boardConfig = {
    numRows: 5,
    numCols: 10,
    blocks : [
        {
            row: 2,
            col: 1
        },
        {
            row: 2,
            col: 2
        }
    ],
    ball: {
        row: 2,
        col: 3,
    }
}

var board = new hundo.Board(boardConfig);

var vizConfig = {
    cellSize : 32
}

hundo.viz = d3.select("#boardSvg")
    .attr("width", boardConfig.numCols * vizConfig.cellSize)
    .attr("height", boardConfig.numRows * vizConfig.cellSize);

hundo.viz.select("#background")
    .attr("width", boardConfig.numCols * vizConfig.cellSize)
    .attr("height", boardConfig.numRows * vizConfig.cellSize)
    .attr("style", "fill:black");

hundo.viz.selectAll(".block")
    .data(board.getBlocks())
    .enter()
    .append("svg:use")
    .attr("class", "block")
    .attr("xlink:href", "#blockTemplate")
    .attr("transform", function(ball) {
      var x = ball.col * vizConfig.cellSize;
      var y = ball.row * vizConfig.cellSize;
      return "translate(" + x + ", " + y + ") "
    })

hundo.viz.selectAll(".ball")
    .data(board.getBalls())
    .enter()
    .append("svg:use")
    .attr("class", "ball")
    .attr("xlink:href", "#ballTemplate")
    .attr("transform", function(block) {
      var x = block.col * vizConfig.cellSize;
      var y = block.row * vizConfig.cellSize;
      return "translate(" + x + ", " + y + ") "
    })

document.onkeydown = checkKey;

function checkKey(e) {

    if (!boardConfig.waiting) {
        return;
    }

    var e = e || window.event;

    if (e.keyCode == '38') {
        console.log("up")
    } else if (e.keyCode == '40') {
        console.log("down")
    } else if (e.keyCode == '37') {
        console.log("left")
    } else if (e.keyCode == '39') {
        console.log("right")

    }

}
<commit_msg>Board.done<commit_after>
var hundo = {}

hundo.PieceTypeEnum = {
    BALL: "BALL",
    BLOCK: "BLOCK"
}

hundo.DirectionEnum = {
    UP: 0,
    DOWN: 1,
    LEFT: 2,
    RIGHT: 3,
    NODIR: 4
}

// every piece has unique id
hundo.Block = function(id, row, col) {
    this.id = id;
    this.type = hundo.PieceTypeEnum.BLOCK;
    this.row = row;
    this.col = col;
}

hundo.Ball = function(id, row, col) {
    this.id = id;
    this.type = hundo.PieceTypeEnum.BALL;
    this.row = row;
    this.col = col;
    this.dir = hundo.PieceTypeEnum.NODIR;
}

// TODO: Assume boardConfig is untrusted
hundo.Board = function(boardConfig) {

    this.done = false;

    this.numRows = boardConfig.numRows;
    this.numCols = boardConfig.numCols;

    // this.matrix[row][call] == array of piece objects
    this.matrix = new Array(this.numRows);
    for (var i = 0; i < this.numRows; i++) {
      this.matrix[i] = new Array(this.numCols);
      for (var j = 0; j < this.numCols; j++) {
        this.matrix[i][j] = new Array();
      }
    }

    var nextId = 0;

    var THIS = this;

    // Add blocks to the matrix
    $.each(boardConfig.blocks, function(index, block) {
        var row = block.row;
        var col = block.col;
        THIS.matrix[row][col].push(new hundo.Block(nextId++, row, col));
    })

    // Add the ball to the matrix
    var row = boardConfig.ball.row;
    var col = boardConfig.ball.col;
    this.matrix[row][col].push(new hundo.Ball(nextId++, row, col));

}

// func(piece) should return true iff the piece is of the type being gotten
hundo.Board.prototype.getPieces = function(func) {

    var pieces = [];

    $.each(this.matrix, function(i, row) {
        $.each(row, function(j, col) {
            $.each(col, function(k, piece) {
                if (func(piece)) {
                    pieces.push(piece);
                }
            })
        })
    });

    return pieces;
}

hundo.Board.prototype.getBlocks = function() {
    return this.getPieces(function(piece){
        return piece.type == hundo.PieceTypeEnum.BLOCK;
    });
};

hundo.Board.prototype.getBalls = function() {
    return this.getPieces(function(piece){
        return piece.type == hundo.PieceTypeEnum.BALL;
    });
};

// removes the first element in array for which func(element) is true
// if an element is removed, returns the index of the element removed
// otherwise, returns -1
hundo.arrayRemove = function(array, func) {

    var i;
    for (i = 0; i < array.length; i++) {
        if (func(array[i])) {
            break;
        }
    }

    if (i == array.length) {
        return -1;
    }

    array.splice(i, 1);

    return i;
}

hundo.Board.prototype.movePiece = function(piece, row, col) {

    var pieces = this.matrix[piece.row][piece.col];

    var i = hundo.arrayRemove(pieces, function(p) {
        return p.id == piece.id;
    })

    if (i == -1) {
        console.error("Could not remove piece");
        return;
    }

    // add the piece to its new location
    this.matrix[row][col].push(piece);

    piece.row = row;
    piece.col = col;

}

// returns null on fatal error
// else, returns an animation object, which describes how the
// the step should be animated
hundo.Board.prototype.step = function() {

    var direction = ball.dir;

    if (direction == DirectionEnum.NODIR) {
        console.error("Ball must have a direction to step");
        return;
    }

    var dr = 0, dc = 0;
    if (direction == DirectionEnum.UP) {
        dr = -1;
    } else if (direction == DirectionEnum.DOWN) {
        dr = 1;
    } else if (direction == DirectionEnum.LEFT) {
        dc = -1;
    } else if (direction == DirectionEnum.RIGHT) {
        dc = 1;
    } else {
        console.error("Ball must have a direction to step");
        return;
    }

    var newRow = this.ball.row + dr;
    var newCol = this.ball.col + dc;

    // Check for out of bounds
    if (newRow < 0 || newRow > this.numRows ||
        newCol < 0 || newColcol > this.numCols) {

        this.done = true;

        return {
            "move": {
                "dir": "direction"
            },
            "oob": true
        };
    }

    if (this.matrix[newRow][newCol].length > 0) {
        return {
            "collide": {
                "dir": direction,
                "recipients": [this.matrix[newRow][newCol]]
            }
        };
    } else {
        this.movePiece(this.ball, newRow, newCol);
        return {
            "move": {
                "dir": direction
            }
        }
    }
}

boardConfig = {
    numRows: 5,
    numCols: 10,
    blocks : [
        {
            row: 2,
            col: 1
        },
        {
            row: 2,
            col: 2
        }
    ],
    ball: {
        row: 2,
        col: 3,
    }
}

var board = new hundo.Board(boardConfig);

var vizConfig = {
    cellSize : 32
}

hundo.viz = d3.select("#boardSvg")
    .attr("width", boardConfig.numCols * vizConfig.cellSize)
    .attr("height", boardConfig.numRows * vizConfig.cellSize);

hundo.viz.select("#background")
    .attr("width", boardConfig.numCols * vizConfig.cellSize)
    .attr("height", boardConfig.numRows * vizConfig.cellSize)
    .attr("style", "fill:black");

hundo.viz.selectAll(".block")
    .data(board.getBlocks())
    .enter()
    .append("svg:use")
    .attr("class", "block")
    .attr("xlink:href", "#blockTemplate")
    .attr("transform", function(ball) {
      var x = ball.col * vizConfig.cellSize;
      var y = ball.row * vizConfig.cellSize;
      return "translate(" + x + ", " + y + ") "
    })

hundo.viz.selectAll(".ball")
    .data(board.getBalls())
    .enter()
    .append("svg:use")
    .attr("class", "ball")
    .attr("xlink:href", "#ballTemplate")
    .attr("transform", function(block) {
      var x = block.col * vizConfig.cellSize;
      var y = block.row * vizConfig.cellSize;
      return "translate(" + x + ", " + y + ") "
    })

document.onkeydown = checkKey;

function checkKey(e) {

    if (!boardConfig.waiting) {
        return;
    }

    var e = e || window.event;

    if (e.keyCode == '38') {
        console.log("up")
    } else if (e.keyCode == '40') {
        console.log("down")
    } else if (e.keyCode == '37') {
        console.log("left")
    } else if (e.keyCode == '39') {
        console.log("right")

    }

}
<|endoftext|>


<commit_before>/*!
 * CF Popover v1.2
 * A lightweight framework for positioning iPad-style popover elements against triggers.
 *
 * Copyright 2011-2012, Crowd Favorite (http://crowdfavorite.com)
 * Released under the MIT license.
 * http://www.opensource.org/licenses/mit-license.php
 */
;(function ($) {
	/* Proxy this once to save computation */
	var uiPosition = $.ui.position;

	/**
	 * Constructor function for popovers
	 */
	var Popover = function ($trigger, opts) {
		this.opts = $.extend({}, this.opts, opts);
		this.$trigger = $($trigger.get(0));

		this.$popover = $(( this.opts.popover || this.$trigger.attr('href') ));
		this.$popover = $(this.$popover.get(0));

		if (!this.$popover.hasClass('popover-before-after-applied')) {
			this.$popover.addClass('popover-before-after-applied')
				.prepend('')
				.append('')
				.hide();
		}
	};

	Popover.prototype = {
		timeout: null,
		$win: $(window),

		opts: {
			my: 'center bottom',
			at: 'center top',
			offset: '0 0',
			collision: 'flop flop',
			popover: null,
			thereCanBeOnlyOne: true
		},

		/**
		 * Custom collision handling for popovers (access via "flop" keyword)
		 * Identical to "flip", but adds class to element being flipped to let
		 * you know when it has been changed from default position.
		 * Functions get bound to this.$popover in the constructor.
		 * Used as a monkey patch below.
		 */
		flop: {
			left: function (position, data) {
				var cPosition = data.collisionPosition,
					$popover = $(this);

				// Modifies position and data by reference
				var out = uiPosition.flip.left(position, data);

				if (position.left !== undefined) {
					$popover.toggleClass('flopped-x', cPosition.left !== position.left);
				}

				return out;
			},
			top: function (position, data) {
				var cPosition = data.collisionPosition,
					$popover = $(this);

				// Modifies position and data by reference
				var out = uiPosition.flip.top(position, data);

				if (position.top !== undefined) {
					$popover.toggleClass('flopped-y', cPosition.top !== position.top);
				}

				return out;
			}
		},

		positionPopover: function(position, data) {
			var $popover = $(this);

			if (data) {
				var opener = $popover.data('opener'),
					popover = $(opener).data('popover');

				if (popover && popover.opts && popover.opts.my) {
					var my = popover.opts.my.split(' ');
					if (my.length > 0) {
						$popover.toggleClass('flopped-x', data.horizontal !== my[0]);
						$popover.toggleClass('flopped-y', data.vertical !== (my.length > 1 ? my[1] : my[0]));
					}
				}
			}

			$popover.css(position);
		},

		bindEvents: function () {
			this.$trigger.click($.proxy(function (e) {
				if (this.popoverIsOpen()) {
					this.hidePopover(e);
				}
				else {
					this.showPopover(e);
				};
				if (this.opts.thereCanBeOnlyOne) {
					$('body').trigger('popover-hide-all');
				};
			}, this));

			$('body').click($.proxy(function (e) {
				if (this.popoverIsOpen()) {
					if (!$(this.$popover).has($(e.target)).size() && !$(this.$popover).filter($(e.target)).size()) {
						this.hide();
					}
				};
			}, this)).bind('popover-hide-all', $.proxy(function() {
				if (this.popoverIsOpen() && !this.currentTrigger()) {
					this.hide(true);
				};
			}, this));

			this.$win.resize($.proxy(this.pinToTargetDebounced, this));
		},

		/* is the popover the this trigger open? */
		popoverIsOpen: function() {
			var opener = (this.$trigger.length == this.$trigger.filter(this.$popover.data('opener')).length);
			return (this.$popover.is(':visible') && opener);
		},

		/* is this trigger the last trigger clicked? */
		currentTrigger: function() {
			return (this.$trigger.length == this.$trigger.filter($.fn.popover.lastTrigger).length);
		},

		/* Method for showing the popover */
		show: function (e) {
			$.fn.popover.lastTrigger = this.$trigger;
			this.$popover.fadeIn('medium', $.proxy(function () {
				this.$trigger.trigger('popover-show-animation-complete');
			}, this)).data('opener', this.$trigger);
			this.pinToTarget();
			this.$trigger.trigger('popover-show');
		},

		/* Method for hiding the popover */
		hide: function (immediate) {
			var callback = $.proxy(function () {
				this.$trigger.trigger('popover-hide-animation-complete');
			}, this);
			if (immediate) {
				this.$popover.hide(0, callback);
			}
			else {
				this.$popover.fadeOut('fast', callback);
			};
			this.$trigger.trigger('popover-hide');
		},

		toggle: function(immediate) {
			if (this.popoverIsOpen()) {
				this.hide(immediate);
			}
			else {
				this.show();
			}
		},

		/* Event handler for showing popover */
		showPopover: function (e) {
			e.preventDefault();
			e.stopPropagation();
			this.show(e);
		},

		/* Event handler for hiding popover */
		hidePopover: function (e) {
			e.preventDefault();
			e.stopPropagation();
			this.hide();
		},

		/* Calculate and position against trigger */
		pinToTarget: function () {
			if (!this.popoverIsOpen()) {
				return;
			}
			var $popover = this.$popover,
				posOpts = $.extend({
					of: this.$trigger,
					using: this.positionPopover
				}, this.opts),

				/* Monkey-patch in our custom collision handling */
				flop = {
					/* Bind our custom collision handling to the popover element */
					left: $.proxy(this.flop.left, this.$popover),
					top: $.proxy(this.flop.top, this.$popover)
				};

			uiPosition.flop = flop;
			$popover.position(posOpts);
			uiPosition.flop = undefined;
		},

		/* Debounced to prevent hitting lots of times while resizing happens.
		Will fire a maximum of 20x per second. Useful for binding to the window
		resize event. */
		pinToTargetDebounced: function () {
			clearTimeout(this.timeout);
			this.timeout = setTimeout($.proxy(this.pinToTarget, this), 50);
		}
	};

	var fn = $.fn;

	fn.popover = function (opts) {
		var Popover = fn.popover.Popover;

		this.each(function() {
			var $this = $(this);
			var popover = new Popover($this, opts);
			popover.bindEvents();

			/* Store Popover instance for easy method access.
			See: http://alexsexton.com/?p=51

			Example: $('.trigger').data('popover').hidePopover(); */
			$this.data('popover', popover);
		});

		return this;
	};

	fn.popover.lastTrigger = null;

	/* Expose constructor function for folks to duck-type when necessary */
	fn.popover.Popover = Popover;
})(jQuery);
<commit_msg>Remove using function for setting element positions.  Update flop detection to allow negative offsets and position's custom offset notation.  See http://api.jqueryui.com/position/<commit_after>/*!
 * CF Popover v1.2
 * A lightweight framework for positioning iPad-style popover elements against triggers.
 *
 * Copyright 2011-2012, Crowd Favorite (http://crowdfavorite.com)
 * Released under the MIT license.
 * http://www.opensource.org/licenses/mit-license.php
 */
;(function ($) {
	/* Proxy this once to save computation */
	var uiPosition = $.ui.position;

	/**
	 * Constructor function for popovers
	 */
	var Popover = function ($trigger, opts) {
		this.opts = $.extend({}, this.opts, opts);
		this.$trigger = $($trigger.get(0));

		this.$popover = $(( this.opts.popover || this.$trigger.attr('href') ));
		this.$popover = $(this.$popover.get(0));

		if (!this.$popover.hasClass('popover-before-after-applied')) {
			this.$popover.addClass('popover-before-after-applied')
				.prepend('')
				.append('')
				.hide();
		}
	};

	Popover.prototype = {
		timeout: null,
		$win: $(window),

		opts: {
			my: 'center bottom',
			at: 'center top',
			offset: '0 0',
			collision: 'flop flop',
			popover: null,
			thereCanBeOnlyOne: true
		},

		/**
		 * Custom collision handling for popovers (access via "flop" keyword)
		 * Identical to "flip", but adds class to element being flipped to let
		 * you know when it has been changed from default position.
		 * Functions get bound to this.$popover in the constructor.
		 * Used as a monkey patch below.
		 */
		flop: {
			left: function (position, data) {
				var $popover = $(this),
					startPositionLeft = position.left;

				// Modifies position and data by reference
				var out = uiPosition.flip.left(position, data);

				$popover.toggleClass('flopped-x', position.left !== undefined && position.left !== startPositionLeft);

				return out;
			},
			top: function (position, data) {
				var $popover = $(this),
					startPositionTop = position.top;

				// Modifies position and data by reference
				var out = uiPosition.flip.top(position, data);

				$popover.toggleClass('flopped-y', position.top !== undefined && position.top !== startPositionTop);

				return out;
			}
		},

		bindEvents: function () {
			this.$trigger.click($.proxy(function (e) {
				if (this.popoverIsOpen()) {
					this.hidePopover(e);
				}
				else {
					this.showPopover(e);
				};
				if (this.opts.thereCanBeOnlyOne) {
					$('body').trigger('popover-hide-all');
				};
			}, this));

			$('body').click($.proxy(function (e) {
				if (this.popoverIsOpen()) {
					if (!$(this.$popover).has($(e.target)).size() && !$(this.$popover).filter($(e.target)).size()) {
						this.hide();
					}
				};
			}, this)).bind('popover-hide-all', $.proxy(function() {
				if (this.popoverIsOpen() && !this.currentTrigger()) {
					this.hide(true);
				};
			}, this));

			this.$win.resize($.proxy(this.pinToTargetDebounced, this));
		},

		/* is the popover the this trigger open? */
		popoverIsOpen: function() {
			var opener = (this.$trigger.length == this.$trigger.filter(this.$popover.data('opener')).length);
			return (this.$popover.is(':visible') && opener);
		},

		/* is this trigger the last trigger clicked? */
		currentTrigger: function() {
			return (this.$trigger.length == this.$trigger.filter($.fn.popover.lastTrigger).length);
		},

		/* Method for showing the popover */
		show: function (e) {
			$.fn.popover.lastTrigger = this.$trigger;
			this.$popover.fadeIn('medium', $.proxy(function () {
				this.$trigger.trigger('popover-show-animation-complete');
			}, this)).data('opener', this.$trigger);
			this.pinToTarget();
			this.$trigger.trigger('popover-show');
		},

		/* Method for hiding the popover */
		hide: function (immediate) {
			var callback = $.proxy(function () {
				this.$trigger.trigger('popover-hide-animation-complete');
			}, this);
			if (immediate) {
				this.$popover.hide(0, callback);
			}
			else {
				this.$popover.fadeOut('fast', callback);
			};
			this.$trigger.trigger('popover-hide');
		},

		toggle: function(immediate) {
			if (this.popoverIsOpen()) {
				this.hide(immediate);
			}
			else {
				this.show();
			}
		},

		/* Event handler for showing popover */
		showPopover: function (e) {
			e.preventDefault();
			e.stopPropagation();
			this.show(e);
		},

		/* Event handler for hiding popover */
		hidePopover: function (e) {
			e.preventDefault();
			e.stopPropagation();
			this.hide();
		},

		/* Calculate and position against trigger */
		pinToTarget: function () {
			if (!this.popoverIsOpen()) {
				return;
			}
			var $popover = this.$popover,
				posOpts = $.extend({
					of: this.$trigger
				}, this.opts),

				/* Monkey-patch in our custom collision handling */
				flop = {
					/* Bind our custom collision handling to the popover element */
					left: $.proxy(this.flop.left, this.$popover),
					top: $.proxy(this.flop.top, this.$popover)
				};

			uiPosition.flop = flop;
			$popover.position(posOpts);
			uiPosition.flop = undefined;
		},

		/* Debounced to prevent hitting lots of times while resizing happens.
		Will fire a maximum of 20x per second. Useful for binding to the window
		resize event. */
		pinToTargetDebounced: function () {
			clearTimeout(this.timeout);
			this.timeout = setTimeout($.proxy(this.pinToTarget, this), 50);
		}
	};

	var fn = $.fn;

	fn.popover = function (opts) {
		var Popover = fn.popover.Popover;

		this.each(function() {
			var $this = $(this);
			var popover = new Popover($this, opts);
			popover.bindEvents();

			/* Store Popover instance for easy method access.
			See: http://alexsexton.com/?p=51

			Example: $('.trigger').data('popover').hidePopover(); */
			$this.data('popover', popover);
		});

		return this;
	};

	fn.popover.lastTrigger = null;

	/* Expose constructor function for folks to duck-type when necessary */
	fn.popover.Popover = Popover;
})(jQuery);
<|endoftext|>


<commit_before>import _$ from 'jquery';
import React from 'react';
import ReactDOM from 'react-dom';
import TestUtils from 'react-addons-test-utils';
import jsdom from 'jsdom';
import chai, { expect } from 'chai';
import chaiJquery from 'chai-jquery';
import { Provider } from 'react-redux';
import { createStore } from 'redux';
import reducers from '../src/reducers';

global.document = jsdom.jsdom('<!doctype html>');
global.window = global.document.defaultView;
global.navigator = global.window.navigator;
const $ = _$(window);

chaiJquery(chai, chai.util, $);

function renderComponent(ComponentClass, props = {}, state = {}) {
  const componentInstance =  TestUtils.renderIntoDocument(
    <Provider store={createStore(reducers, state)}>
      <ComponentClass {...props} />
    </Provider>
  );

  return $(ReactDOM.findDOMNode(componentInstance));
}

$.fn.simulate = function(eventName, value) {
  if (value) {
    this.val(value);
  }
  TestUtils.Simulate[eventName](this[0]);
};

export {renderComponent, expect};
<commit_msg>wrote test_helper to make testing possible.<commit_after>import jsdom from 'jsdom';
import jquery from 'jquery';
import TestUtils from 'react-addons-test-utils';
import ReactDOM from 'react-dom';
import chai, { expect } from 'chai';
import React from 'react';
import { Provider } from 'react-redux';
import { createStore } from 'redux';
import reducers from '../src/reducers';
import chaiJquery from 'chai-jquery';

// Set up testing environment to run like a browser in the command line
global.document = jsdom.jsdom('<!doctype html>');
global.window = global.document.defaultView;
const $ = jquery(global.window);

// Build 'renderComponent' helper that should render a given react class
function renderComponent(ComponentClass, props, state) {
  const componentInstance = TestUtils.renderIntoDocument(
    <Provider store={createStore(reducers, state)}>
      <ComponentClass {...props} />
    </Provider>
  );

  return $(ReactDOM.findDOMNode(componentInstance)); // produces HTML
}

// Build helper for simulating events
$.fn.simulate = function (eventName, value) {
  if (value) {
    this.val(value);
  };
  TestUtils.Simulate[eventName](this[0]);
}

// Set up chai-jquery
chaiJquery(chai, chai.util, $);

export { renderComponent, expect };
<|endoftext|>


<commit_before>
function openImage(imageID) {
  var image = document.getElementById(imageID);
  var savedImages = document.getElementById("savedImages");
  // clone element
  //   http://stackoverflow.com/questions/921290/is-it-possible-to-clone-html-element-objects-in-javascript-jquery
  var newElement = image.cloneNode(true);
  image.parentElement.insertBefore(newElement, image);
  image.classList.remove("renew-image");
  image.removeAttribute("id");
  // insert at beginning
  //   http://www.javascriptkit.com/javatutors/dom2.shtml
  savedImages.insertBefore(image, savedImages.firstChild);
}<commit_msg>removed bug that terminates renewal<commit_after>
function openImage(imageID) {
  var image = document.getElementById(imageID);
  var savedImages = document.getElementById("savedImages");
  // clone element
  //   http://stackoverflow.com/questions/921290/is-it-possible-to-clone-html-element-objects-in-javascript-jquery
  var newElement = image.cloneNode(true);
  newElement.classList.remove("renew-image");
  newElement.removeAttribute("id");
  // insert at beginning
  //   http://www.javascriptkit.com/javatutors/dom2.shtml
  savedImages.insertBefore(newElement, savedImages.firstChild);
}<|endoftext|>


<commit_before>'use strict'

import init from './component/init'
import events from './component/events'
import control from './component/control'
import emitter from './module/emitter'
import attach from './module/attach'
import insert from './element/insert'
import build from './element/build'
import css from './module/css'

import icon from './skin/material/icon/checkbox.svg'
// element related modules

let defaults = {
  prefix: 'material',
  class: 'checkbox',
  type: 'control',
  modules: [events, control, emitter, attach],
  build: ['$wrapper.material-checkbox', {},
    ['input$input', {}],
    ['span$control.checkbox-control']
  ],
  events: [
    ['element.control.click', 'click', {}],
    ['element.label.click', 'toggle', {}],
    // for accessibility purpose
    // ['element.input.click', 'toggle', {}],
    ['element.input.focus', 'focus'],
    ['element.input.blur', 'blur']
  ]
}
/**
 * Checkbox control class
 * @class
 * @extends Control
 * @since 0.0.1
 * @example
 * var chkbox = checkbox({
 *   label: 'Primary raised button',
 *   type: 'raised',
 *   primary: true
 * }).on('click', function(e) {
 *   console.log('button click', e);
 * }).insert(document.body);
 */
class Checkbox {
  /**
   * Constructor
   * @param  {Object} options - Component options
   * @return {Object} Class instance
   */
  constructor(options) {
    this.options = Object.assign({}, defaults, options || {})
    // init and build
    this.init()
    this.build()
    this.attach()

    return this
  }

  /**
   * Constructor
   * @param  {Object} options The class options
   * @return {Object} This class instance
   */
  init() {
    init(this)
    // init options and merge options to defaults

    return this
  }

  /**
   * build the component using the super method
   * @return {Object} The class instance
   */
  build() {
    this.element = build(this.options.build)
    this.wrapper = this.element.wrapper

    this.element.control.innerHTML = icon

    this.label(this.options.label)

    this.element.input.setAttribute('type', 'checkbox')
    this.element.input.setAttribute('name', this.options.name)
    this.element.input.setAttribute('value', this.options.value)

    if (this.options.disabled) {
      this.disabled = this.options.disabled
      this.element.input.setAttribute('disabled', 'disabled')
      css.add(this.wrapper, 'is-disabled')
    }

    if (this.options.checked) {
      this.check(true)
    }

    if (this.options.value) {
      this.set('value', this.value)
    }

    // insert if container options is given
    if (this.options.container) {
      insert(this.wrapper, this.options.container)
    }

    return this
  }

  /**
   * Setter
   * @param {string} prop
   * @param {string} value
   * @return {Object} The class instance
   */
  set(prop, value) {
    switch (prop) {
      case 'checked':
        this.check(value)
        break
      case 'value':
        this.setValue(value)
        break
      case 'label':
        this.setLabel(value)
        break
      default:
        this.check(prop)
    }

    return this
  }

  insert(container, context) {
    insert(this.wrapper, container, context)

    return this
  }

  /**
   * [click description]
   * @param  {event} e [description]
   * @return {[type]}   [description]
   */
  click(e) {
    this.toggle(e)
    this.element.input.focus()

    return this
  }

  /**
   * Set checkbox value
   * @param {boolean} value [description]
   */
  setValue(value) {
    console.log('setValue', value)
    this.value = value
    this.element.input.setAttribute('value', value)

    return this
  }
}

export default Checkbox<commit_msg>add docs block<commit_after>'use strict'

import init from './component/init'
import events from './component/events'
import control from './component/control'
import emitter from './module/emitter'
import attach from './module/attach'
import insert from './element/insert'
import build from './element/build'
import css from './module/css'

import icon from './skin/material/icon/checkbox.svg'
// element related modules

let defaults = {
  prefix: 'material',
  class: 'checkbox',
  type: 'control',
  modules: [events, control, emitter, attach],
  build: ['$wrapper.material-checkbox', {},
    ['input$input', {}],
    ['span$control.checkbox-control']
  ],
  events: [
    ['element.control.click', 'click', {}],
    ['element.label.click', 'toggle', {}],
    // for accessibility purpose
    // ['element.input.click', 'toggle', {}],
    ['element.input.focus', 'focus'],
    ['element.input.blur', 'blur']
  ]
}
/**
 * Checkbox control class
 * @class
 * @extends Control
 * @since 0.0.1
 * @example
 * var chkbox = checkbox({
 *   label: 'Primary raised button',
 *   type: 'raised',
 *   primary: true
 * }).on('click', function(e) {
 *   console.log('button click', e);
 * }).insert(document.body);
 */
class Checkbox {
  /**
   * Constructor
   * @param  {Object} options - Component options
   * @return {Object} Class instance
   */
  constructor(options) {
    this.options = Object.assign({}, defaults, options || {})
    // init and build
    this.init()
    this.build()
    this.attach()

    return this
  }

  /**
   * Constructor
   * @param  {Object} options The class options
   * @return {Object} This class instance
   */
  init() {
    init(this)
    // init options and merge options to defaults

    return this
  }

  /**
   * build the component using the super method
   * @return {Object} The class instance
   */
  build() {
    this.element = build(this.options.build)
    this.wrapper = this.element.wrapper

    this.element.control.innerHTML = icon

    this.label(this.options.label)

    this.element.input.setAttribute('type', 'checkbox')
    this.element.input.setAttribute('name', this.options.name)
    this.element.input.setAttribute('value', this.options.value)

    if (this.options.disabled) {
      this.disabled = this.options.disabled
      this.element.input.setAttribute('disabled', 'disabled')
      css.add(this.wrapper, 'is-disabled')
    }

    if (this.options.checked) {
      this.check(true)
    }

    if (this.options.value) {
      this.set('value', this.value)
    }

    // insert if container options is given
    if (this.options.container) {
      insert(this.wrapper, this.options.container)
    }

    return this
  }

  /**
   * Setter
   * @param {string} prop
   * @param {string} value
   * @return {Object} The class instance
   */
  set(prop, value) {
    switch (prop) {
      case 'checked':
        this.check(value)
        break
      case 'value':
        this.setValue(value)
        break
      case 'label':
        this.setLabel(value)
        break
      default:
        this.check(prop)
    }

    return this
  }

  /**
   * [insert description]
   * @param  {?} container [description]
   * @param  {?} context   [description]
   * @return {?}           [description]
   */
  insert(container, context) {
    insert(this.wrapper, container, context)

    return this
  }

  /**
   * [click description]
   * @param  {event} e [description]
   * @return {?}   [description]
   */
  click(e) {
    this.toggle(e)
    this.element.input.focus()

    return this
  }

  /**
   * Set checkbox value
   * @param {boolean} value [description]
   */
  setValue(value) {
    console.log('setValue', value)
    this.value = value
    this.element.input.setAttribute('value', value)

    return this
  }
}

export default Checkbox<|endoftext|>


<commit_before>$.widget('colorwheel.colorwheel', {
    options: {
        size: 200,
        ringSize: 30,
        color: 180
    },
    _create: function () {
        this.radius = this.options.size / 2;
        var can = $('<canvas>').attr({
            width: this.options.size,
            height: this.options.size,
            id: 'colorwheel'
        });

        var outer = $('<div/>').addClass('colorwheel-outer').css({
            width: this.options.ringSize,
            height: this.options.ringSize
        });

        var inner = $('<div/>').addClass('colorwheel-inner');

        this.element.append(outer).append(inner).append(can);

        var ctx = can.get(0).getContext('2d');
        var x = y = this.radius;
        focusOut = focusIn = false;

        //Initialize outer wheel
        for (var i = 0; i < 360; i++) {
            ctx.beginPath();
            ctx.fillStyle = 'hsl(' + i + ', 100%, 50%)';
            ctx.moveTo(x, y);
            ctx.arc(x, y, this.radius, (i - 2) * (Math.PI / 180), (i * (Math.PI / 180)), false);
            ctx.lineTo(x, y);
            ctx.fill();
        }
        //Draw white to hide the center area
        ctx.beginPath();
        ctx.fillStyle = 'white';
        ctx.moveTo(x, y);
        ctx.arc(x, y, this.radius - this.options.ringSize, 0, 2 * Math.PI, false);
        ctx.fill();
        var _this = this;
        var length = Math.sqrt(2 * Math.pow(_this.radius - _this.options.ringSize, 2));
        var renderInner = function() {
            //Draw inner box
            var half = length / 2;
            ctx.lineWidth = 1;
            ctx.strokeRect(x - half + 2, y - half + 2, length - 2, length - 2);

            for (var i = 0; i < 100; i++) {
                var line = ctx.createLinearGradient(
                    x - half + 2,
                    (y - half) + 2 + ((i * (length - 3)) / 100),
                    length - 2,
                    1 + (length - 2) / 100
                );
                var sat = 100 - i
                line.addColorStop(0, 'hsl(' + _this.options.color + ',' + 100 + '%,' + sat + '%)');
                line.addColorStop(.5, 'hsl(' + _this.options.color + ',' + sat + '%,' + sat + '%)');
                line.addColorStop(1, 'hsl(' + _this.options.color + ',' + 0 + '%,' + sat + '%)');
                ctx.fillStyle = line;
                ctx.fillRect(
                    x - half + 2,
                    (y - half) + 2 + ((i * (length - 3)) / 100),
                    length - 2,
                    1 + (length - 2) / 100);
                };
        };

        renderInner();
        var updateInner = function(evt) {
            //TODO: Cleanup more?
            var offset = _this._getRelativePos(can, evt);
            var xDiff = Math.abs(x - offset.x);
            var yDiff = Math.abs(y - offset.y);
            var dist = Math.sqrt(Math.pow(x - offset.x, 2) + Math.pow(y - offset.y, 2));
            if (dist < _this.radius - _this.options.ringSize &&
                xDiff < length/2 &&
                yDiff < length / 2) {
                    inner.css({
                        left: evt.pageX -5,
                        top: evt.pageY - 5
                    });
            }
        }
        var updateOuter = function(evt) {
            var rawAngle = Math.atan2(evt.pageY - y, evt.pageX - x), angle = rawAngle * 180 / Math.PI;
            if (rawAngle < 0) {
                angle = 360 - (angle * -1);
            }

            var middle = _this.radius - ((_this.options.ringSize) / 2);
            outer.css({
                left: Math.cos(rawAngle) * middle + x - (_this.options.ringSize / 2) + 5,
                top: Math.sin(rawAngle) * middle + y - (_this.options.ringSize / 2) + 5
            });
            _this.options.color = Math.round(angle);
            renderInner();
        }

        $('#colorwheel, .colorwheel-outer, .colorwheel-inner').on('mousedown', function (evt) {
            evt.preventDefault();
            var parentOffset = can.parent().offset();
            var eX = evt.pageX - parentOffset.left;
            var eY = evt.pageY - parentOffset.top;
            var dist = Math.sqrt(Math.pow(x -eX, 2) + Math.pow(y - eY, 2));
            if (dist < _this.radius && dist > _this.radius - _this.options.ringSize) {
                focusOut = true;
                updateOuter(evt);
            } else if (dist < _this.radius - _this.options.ringSize) {
                focusIn = true;
                updateInner(evt);
            }
        });

        $(document).on('mouseup', function (evt) {
            focusOut = false;
            focusIn = false;
        }).on('mousemove', function (evt) {
            if (focusOut) {
                updateOuter(evt);
            } else if (focusIn) {
                updateInner(evt);
            }
        });
    },

    getColor: function() {
        var c = ctx.getImageData(offset.x, offset.y, 1, 1).data;
        return {'r':c[0], 'g':c[1], 'b':c[2]};
    },

    _getRelativePos: function (element, evt) {
        var parentOffset = $(element).offset();
        var eX = evt.pageX - parentOffset.left;
        var eY = evt.pageY - parentOffset.top;
        return {x: eX, y: eY};
    },

    destroy: function() {
        this.element.children('.colorwheel, .colorwheel-inner, .colorwheel-outer').remove();
    }
});<commit_msg>Replace all jquery-ui code with regular jquery code<commit_after>(function ($) {
    $.fn.colorwheel = function(options) {
        return this.each(function() {
            var element = $(this);
            var options = $.extend({
                size: 500,
                ringSize: 50,
                color: 180,
                onInput: function(evt) {}
            }, options);

            var radius = x = y = options.size / 2;
            var length = Math.sqrt(2 * Math.pow(radius - options.ringSize, 2));
            var half = length / 2;
            var can = $('<canvas>').attr({
                width: options.size,
                height: options.size,
                id: 'colorwheel'
            });

            var ctx = can.get(0).getContext('2d');

            var outer = $('<div/>').addClass('colorwheel-outer').css({
                width: options.ringSize,
                height: options.ringSize
            });

            var inner = $('<div/>').addClass('colorwheel-inner');
            element.append(outer).append(inner).append(can);

            var focusOut = false, focusIn = false;
            console.log(element);
            $('#colorwheel, .colorwheel-outer, .colorwheel-inner').on('mousedown', function (evt) {
                evt.preventDefault();
                var parentOffset = can.parent().offset();
                var eX = evt.pageX - parentOffset.left;
                var eY = evt.pageY - parentOffset.top;
                var dist = Math.sqrt(Math.pow(x -eX, 2) + Math.pow(y - eY, 2));
                if (dist < radius && dist > radius - options.ringSize) {
                    focusOut = true;
                    updateOuter(evt);
                } else if (dist < radius - options.ringSize) {
                    focusIn = true;
                    updateInner(evt);
                }
            });

            $(document).on('mouseup', function (evt) {
                focusOut = focusIn = false;
            }).on('mousemove', function (evt) {
                if (focusOut) {
                    updateOuter(evt);
                } else if (focusIn) {
                    updateInner(evt);
                }
            });
            var updateOuter = function(evt) {
                var rawAngle = Math.atan2(evt.pageY - y, evt.pageX - x), angle = rawAngle * 180 / Math.PI;
                if (rawAngle < 0) {
                    angle = 360 - (angle * -1);
                }

                var middle = radius - ((options.ringSize) / 2);
                outer.css({
                    left: Math.cos(rawAngle) * middle + x - (options.ringSize / 2) + 5,
                    top: Math.sin(rawAngle) * middle + y - (options.ringSize / 2) + 5
                });
                options.color = Math.round(angle);
                renderInner();
            };

            var updateInner = function(evt) {
                var offset = getRelativePos(can, evt);
                var xDiff = Math.abs(x - offset.x);
                var yDiff = Math.abs(y - offset.y);
                var dist = Math.sqrt(Math.pow(x - offset.x, 2) + Math.pow(y - offset.y, 2));
                if (dist < radius - options.ringSize && xDiff < half && yDiff < half) {
                    inner.css({
                        left: evt.pageX -5,
                        top: evt.pageY - 5
                    });
                }
            };

            var renderOuter = function() {
                for (var i = 0; i < 360; i++) {
                    ctx.beginPath();
                    ctx.fillStyle = 'hsl(' + i + ', 100%, 50%)';
                    ctx.moveTo(x, y);
                    ctx.arc(x, y, radius, (i - 2) * (Math.PI / 180), (i * (Math.PI / 180)), false);
                    ctx.lineTo(x, y);
                    ctx.fill();
                }
                //Draw white to hide the center area
                ctx.beginPath();
                ctx.fillStyle = 'white';
                ctx.moveTo(x, y);
                ctx.arc(x, y, radius - options.ringSize, 0, 2 * Math.PI, false);
                ctx.fill();
            };

            var renderInner = function() {
                ctx.lineWidth = 1;
                ctx.strokeRect(x - half + 2, y - half + 2, length - 2, length - 2);

                for (var i = 0; i < 100; i++) {
                    var line = ctx.createLinearGradient(
                        x - half + 2,
                        (y - half) + 2 + ((i * (length - 3)) / 100),
                        length - 2,
                        1 + (length - 2) / 100
                    )
                    var sat = 100 - i
                    line.addColorStop(0, 'hsl(' + options.color + ',' + 100 + '%,' + sat + '%)');
                    line.addColorStop(.5, 'hsl(' + options.color + ',' + sat + '%,' + sat + '%)');
                    line.addColorStop(1, 'hsl(' + options.color + ',' + 0 + '%,' + sat + '%)');
                    ctx.fillStyle = line;
                    ctx.fillRect(
                        x - half + 2,
                        (y - half) + 2 + ((i * (length - 3)) / 100),
                        length - 2,
                        (length - 2) / 100
                    );
                };
            };

            var getColor = function() {
                var x = inner.position().left + 15;
                var y = inner.position().top + 15;
                var c = ctx.getImageData(x, y, 1, 1).data;
                return {'r':c[0], 'g':c[1], 'b':c[2]};
            }
            var getRelativePos = function (element, evt) {
                var parentOffset = $(element).offset();
                var eX = evt.pageX - parentOffset.left;
                var eY = evt.pageY - parentOffset.top;
                return {x: eX, y: eY};
            }
            renderOuter();
            renderInner();

            return this;
        });
    }
})(jQuery);
<|endoftext|>


<commit_before>(function() {

    String.prototype.escape = function() {
        var tagsToReplace = {
            '&': '&',
            '<': '<',
            '>': '>'
        };
        return this.replace(/[&<>]/g, function(tag) {
            return tagsToReplace[tag] || tag;
        });
    };

    var ExtractEndpoint = 'https://natasha.b-labs.pro/api/extract',
        VersionEndpoint = 'https://natasha.b-labs.pro/api/version',
        StartAnalysisButton = document.getElementById('start-analysis');

    var request = new XMLHttpRequest();
    request.onreadystatechange = function() {
        if (request.readyState == 4 && request.status == 200) {
            var element = document.getElementById('version');
                versions = JSON.parse(request.responseText);
            element.innerHTML = versions.yargy + ' / ' + versions.natasha;
        };
    };
    request.open('GET', VersionEndpoint, true);
    request.send();

    StartAnalysisButton.addEventListener('click', function(e) {
        e.preventDefault();
        var request = new XMLHttpRequest(),
            container = document.getElementById('display'),
            results = document.getElementById('results'),
            text = container.textContent.replace(/\n/g, ' '),
            button = this;
        button.className = button.className.replace('button-default', 'button-disabled');
        results.innerHTML = '';
        request.onreadystatechange = function() {
            if (request.readyState == 4 && request.status == 200) {
                var matches = JSON.parse(request.responseText)
                    resultHTML = text.substring(0);
                matches.sort(function(a, b){
                    if(a.span[1] - a.span[0]  b.span[1] - b.span[0]) return 1;
                    return 0;
                });
                for (var i = matches.length - 1; i >= 0; i--) {
                    var match = matches[i],
                        start = match.span[0],
                        finish = match.span[1],
                        replacement = text.substring(start, finish),
                        result = '
' + replacement + '
';
                    resultHTML = resultHTML.replace(replacement, result);
                };
                container.innerHTML = resultHTML;
            };
            button.className = button.className.replace('button-disabled', 'button-default');
        };
        request.open('POST', ExtractEndpoint, true);
        request.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
        request.send('text=' + encodeURIComponent(text));
    });
})();
<commit_msg>Update natasha playground code<commit_after>(function() {

    String.prototype.escape = function() {
        var tagsToReplace = {
            '&': '&',
            '<': '<',
            '>': '>'
        };
        return this.replace(/[&<>]/g, function(tag) {
            return tagsToReplace[tag] || tag;
        });
    };

    var ExtractEndpoint = 'https://natasha.b-labs.pro/api/extract',
        VersionEndpoint = 'https://natasha.b-labs.pro/api/version',
        StartAnalysisButton = document.getElementById('start-analysis');

    var request = new XMLHttpRequest();
    request.onreadystatechange = function() {
        if (request.readyState == 4 && request.status == 200) {
            var element = document.getElementById('version');
                versions = JSON.parse(request.responseText);
            element.innerHTML = versions.yargy + ' / ' + versions.natasha;
        };
    };
    request.open('GET', VersionEndpoint, true);
    request.send();

    StartAnalysisButton.addEventListener('click', function(e) {
        e.preventDefault();
        var request = new XMLHttpRequest(),
            container = document.getElementById('display'),
            text = container.textContent.replace(/\n/g, ' '),
            button = this;
        button.className = button.className.replace('button-default', 'button-disabled');
        request.onreadystatechange = function() {
            if (request.readyState == 4 && request.status == 200) {
                var matches = JSON.parse(request.responseText)
                    resultHTML = text.substring(0);
                matches.sort(function(a, b){
                    if(a.span[1] - a.span[0]  b.span[1] - b.span[0]) return 1;
                    return 0;
                });
                for (var i = matches.length - 1; i >= 0; i--) {
                    var match = matches[i],
                        start = match.span[0],
                        finish = match.span[1],
                        replacement = text.substring(start, finish),
                        result = '
' + replacement + '
';
                    resultHTML = resultHTML.replace(replacement, result);
                };
                container.innerHTML = resultHTML;
            };
            button.className = button.className.replace('button-disabled', 'button-default');
        };
        request.open('POST', ExtractEndpoint, true);
        request.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
        request.send('text=' + encodeURIComponent(text));
    });
})();
<|endoftext|>