<commit_before>(function () {
    var SCROLL_SENSITIVITY = 15;
    var RESIZE_SENSITIVITY = 20;

    window.websheet = function () {
        var columns = [];

        function websheet( selection ) {
            return websheet.draw( selection )
        }

        websheet.columns = function ( _columns ) {
            if ( arguments.length == 0 ) {
                return columns
            }
            columns = _columns;
            return this;
        }

        websheet.column = function ( name, accessor ) {
            if ( !accessor ) {
                accessor = function ( d ) {
                    return d[ name ]
                }
            }
            columns.push({
                name: name,
                accessor: accessor,
                w: 200
            });
            return this;
        }

        var el;
        websheet.draw = function ( selection ) {
            if ( selection instanceof Element ) {
                selection = d3.selectAll( [ selection ] );
            }

            selection.each( function ( data ) {
                el = this;
                draw( websheet, this, data );
                var max = getBounderies( websheet, this );
                websheet.__maxx = max.x;
                websheet.__maxy = max.y;
            })
            return this;
        }

        function getBounderies( that, el ) {
            var rect = el.getBoundingClientRect();
            var rows = d3.select( el )
                .selectAll( 'tbody > tr' )[ 0 ];

            var height = Math.floor( rect.height );
            var maxy;
            for ( maxy = rows.length ; maxy > 0 ; maxy -= 1 ) {
                height -= rows[ maxy - 1 ].getBoundingClientRect().height;
                if ( height <= 0 ) {
                    break
                }
            }

            maxy += 2; // extra room for 1 header row

            return { x: that.columns().length - 1, y: maxy }
        }

        var selection = { start: null, end: null }
        var selectAnimFrame;
        websheet.selection = function () {
            return {
                start: function ( xy ) {
                    if ( !arguments.length ) {
                        return selection.start;
                    }
                    selection.start = xy;
                    selection.end = xy;

                    cancelAnimationFrame( selectAnimFrame );
                    selectAnimFrame = requestAnimationFrame( function () {
                        drawSelection( el, selection.start, selection.end );
                    })

                    return this;
                },
                end: function ( xy ) {
                    if ( !arguments.length ) {
                        return selection.end;
                    }

                    selection.end = xy;
                    // debug( "Selection", "End:", xy );

                    cancelAnimationFrame( selectAnimFrame );
                    selectAnimFrame = requestAnimationFrame( function () {
                        drawSelection( el, selection.start, selection.end );
                    });

                    return this;
                },
            }
        }

        var scroll = [ 1, 1 ];
        var scrollAnimFrame;
        websheet.scroll = function ( xy ) {
            var rows = d3.select( el ).datum();
            if ( arguments.length == 0 ) {
                return [ scroll[ 0 ], scroll[ 1 ] ]; // copy
            }

            var x = Math.min( this.__maxx, Math.max( 1, xy[ 0 ] ) );
            var y = Math.min( this.__maxy, Math.max( 1, xy[ 1 ] ) );

            window.cancelAnimationFrame( scrollAnimFrame );

            if ( x == scroll[ 0 ] && y == scroll[ 1 ] ) {
                return this;
            }

            // changing the dom will only take place on the next animation
            // frame in order to throttle the ui repaints while the user scrolls
            scrollAnimFrame = requestAnimationFrame( function () {
                scroll = [ x, y ];
                scrollTo( el, x, y );
            });

            return this;
        }

        var rowNums = false;
        websheet.rowNumbers = function(enabled) {
            if (arguments.length === 0) {
                return rowNums
            }

            rowNums = enabled
            return rowNums
        }

        return websheet
    }

    function draw( that, el, data ) {
        el = d3.select( el )
            .classed( "websheet", true );

        if ( !el.node().__websheet ) {
            el.on( "mousewheel", onMouseWheel() );

            // el.on( "mousedown", onMouseDown() );
            // el.on( "mouseup", onMouseUp() );
            // el.on( "mousemove", onMouseMove() );

            init( el.node() );
        }

        el.node().__websheet = that;

        var columns = [].concat( that.columns() )

        // row-number column
        that.rowNumbers() && columns.unshift({
            accessor: function ( d, i ) {
                return d === undefined ? '' : i + 1;
            },
            w: 40,
            cls: 'row-number'
        })

        // extra right column to keep the display wide.
        columns.push({
            accessor: function () {},
            w: 2000
        });

        columns.forEach( function ( col, i ) {
            col.rown = 0;
            col.coln = i;
        })

        var colwidths = columns.map( function ( d ) {
            return d.w || 0;
        });

        // extra full height row.
        data = [].concat(data)
        data.push(undefined)

        var table = el.selectAll( "table" )
            .data( [ data ] );
        table.enter().append( "table" )
            .style( "position", "relative" )
            .style( "left", "0px" )
            .html( "

" )

        // headers
        var rows = table.select( "thead > tr" )
        var headers = rows.selectAll( "th" )
            .data( columns )
        headers.enter().append( "th" )
            .style( "position", "relative" );
        headers
            .text( function ( d ) {
                return d.name || ""
            })
            .style( "width", function ( d ) {
                return d.w + "px"
            })
            .attr('class', function (d) {
                return d.cls
            })

        // rows
        var tbody = table.select( "tbody" );
        var rows = tbody.selectAll( "tr" )
            .data( data );
        rows.exit().remove();
        rows.enter().append( "tr" );
        rows.style('height', (d) => d === undefined ? 'auto' : '')
        var cells = rows.selectAll( "td" )
            .data( function ( d, i ) {
                return columns.map( function ( col, j ) {
                    return {
                        rown: i + 1,
                        coln: j,
                        v: d === undefined ? '' : col.accessor( d, i ),
                        cls: col.cls
                    }
                })
            })
        cells.enter().append( "td" )
        cells
            .text( function ( d ) {
                return d.v
            })
            .attr('class', (d) => d.cls)
    }

    function init( el ) {
        var options = { el: el };

        document.addEventListener('click', function(ev) {
            if (ev.__inWebsheet === el) {
                return
            }

            // de-select all.
            options.el.__websheet.selection().end(null)
        })

        el.addEventListener('click', function(ev) {
            ev.__inWebsheet = this
        })

        // resize
        el.addEventListener( "mousemove", function ( ev ) {
            ev.preventDefault()
            resizeMove( options, ev )
        });
        el.addEventListener( "mousedown", function ( ev ) {
            resizeDown( options, ev )
        });
        el.addEventListener( "mouseup", function ( ev ) {
            resizeUp( options, ev )
        });

        // select
        el.addEventListener( "mousemove", function ( ev ) {
            selectMove( options, ev );
        })
        el.addEventListener( "mousedown", function ( ev ) {
            selectDown( options, ev );
        })
        el.addEventListener( "mouseup", function ( ev ) {
            selectUp( options, ev );
        })
    }

    function resizeMove( options, ev ) {
        if ( options.resizing ) {
            var dx = ev.clientX - options.resizing.x;
            var w = options.resizing.w + dx;
            options.resizable.style.width = Math.max( w, 14 ) + "px";
            return;
        }

        var th = parentSelector( ev.target, ".websheet th" );
        var resizable;
        if ( th ) {
            var rect = th.getBoundingClientRect();
            var left = ev.clientX - rect.left;
            var right = rect.width - left;

            if ( right < RESIZE_SENSITIVITY ) {
                resizable = th;
            }
        }

        if ( options.resizable && options.resizable != resizable ) {
            options.resizable.classList.remove( "resizable" );
            options.resizable = null;
        }

        if ( resizable ) {
            resizable.classList.add( "resizable" );
            options.resizable = resizable;
        }
    }

    function resizeDown ( options, ev ) {
        if ( !options.resizable ) {
            return;
        }

        options.resizing = {
            w: parseInt( options.resizable.style.width ),
            x: ev.clientX
        }
    }

    function resizeUp ( options ) {
        if ( options.resizing ) {
            var col = d3.select( options.resizable ).datum();
            col.w = parseInt( options.resizable.style.width );
        }
        options.resizing = null;
    }

    function selectDown ( options, ev ) {
        if ( options.resizing ) {
            return
        }
        options.__selecting = true;
        ev.preventDefault();
        var datum = d3.select( ev.target ).datum();
        options.el.__websheet.selection()
            .start([ datum.coln || 0, datum.rown || 0 ])
    }

    function selectMove ( options, ev ) {
        if ( options.__selecting ) {
            var datum = d3.select( ev.target ).datum();
            options.el.__websheet.selection()
                .end([ datum.coln || Infinity, datum.rown || Infinity ]);
        }
    }

    function selectUp ( options, ev ) {
        if ( options.__selecting ) {
            var datum = d3.select( ev.target ).datum();
            options.el.__websheet.selection()
                .end([ datum.coln || Infinity, datum.rown || Infinity ]);
        }
        options.__selecting = false;
    }

    function onMouseWheel () {
        var deltaX = 0, deltaY = 0;
        return function ( ev ) {
            var ev = d3.event;
            ev.preventDefault();
            ev.stopPropagation();

            deltaX += ev.deltaX;
            deltaY += ev.deltaY;

            // debug( "MouseWheel", "X:", deltaX, "Y:", deltaY );
            var scroll = this.__websheet.scroll();
            if ( deltaX > SCROLL_SENSITIVITY ) {
                scroll[ 0 ] += 1;
                deltaX = 0;
            } else if ( deltaX < -SCROLL_SENSITIVITY ) {
                scroll[ 0 ] -= 1;
                deltaX = 0;
            }

            if ( deltaY > SCROLL_SENSITIVITY ) {
                scroll[ 1 ] += 1;
                deltaY = 0;
            } else if ( deltaY < -SCROLL_SENSITIVITY ) {
                scroll[ 1 ] -= 1;
                deltaY = 0;
            }

            this.__websheet.scroll( scroll );
        }
    }

    function drawSelection( el, start, end ) {
        el = d3.select( el );

        // remove previous selection
        el.selectAll( ".selected" )
            .classed( "selected", false );

        // empty selection or deselect
        if ( !start || !end ) {
            return;
        }

        var startx = start[ 0 ];
        var endx = end[ 0 ];
        var starty = start[ 1 ];
        var endy = end[ 1 ];

        // reversed order
        if ( startx > endx ) {
            endx = startx;
            startx = end[ 0 ];
        }
        if ( starty > endy ) {
            endy = starty;
            starty = end[ 1 ];
        }

        // find the relevant rows in the range of starty-endy
        var selector = [
            "tbody > tr",
            ":nth-child(n+" + ( starty ) + ")",
            endy == Infinity ? "" : ":nth-child(-n+" + ( endy ) + ")"
        ].join( "" );
        var rows = el.selectAll( selector );

        // find the relevant columns within these rows in the range
        // of startx-endx
        var selector = [
            "*",
            ":nth-child(n+" + ( startx + 1 ) + ")",
            endx == Infinity ? "" : ":nth-child(-n+" + ( endx + 1 ) + ")"
        ].join( "" );
        var cells = rows.selectAll( selector );

        // add the relevant headers to the selection
        var headers = el.select( "thead > tr" )
            .selectAll( selector );

        // add the relevant row-numbers to the selection
        var rownums = rows.selectAll( "td:first-child" );

        // finally, apply the selected class
        cells.classed( "selected", true );
        headers.classed( "selected", true );
        rownums.classed( "selected", true );
    }

    function scrollTo( el, x, y ) {

        // x-y starts with 1, offset back to 0
        x -= 1;
        y -= 1;

        var headers = el.querySelectorAll( "th" );
        var column = headers[ x + 1 ].getBoundingClientRect();
        var container = el.getBoundingClientRect();
        var rowsn = headers[ 0 ].getBoundingClientRect();
        var left = el.scrollLeft
            + column.left
            - container.left
            - rowsn.width;

        var rows = el.querySelectorAll( "th:first-child,td:first-child" );
        [].forEach.call( rows, function ( row ) {
            row.style.position = "relative";
            row.style.left = ( +row.style.left || 0 ) + left + "px";
        })

        el.scrollLeft = left;

        // find the relevant row element
        var row = el.querySelector( "tbody > tr:nth-child(" + ( y + 1 ) + ")" );
        var rect = row.getBoundingClientRect();
        var top = el.scrollTop
            + rect.top
            - container.top
            - column.height;

        [].forEach.call( headers, function ( row ) {
            row.style.position = "relative";
            row.style.top = ( +row.style.top || 0 ) + top + "px";
        })

        el.scrollTop = top;
    }

    // debug
    window.websheet.debug = true;
    function debug() {
        if ( window.websheet.debug ) {
            console.log.apply( console, arguments );
        }
    }

    function parentSelector( el, selector ) {
        while ( el && el.matches ) {
            if ( el.matches( selector ) ) {
                return el;
            }
            el = el.parentNode;
        }
    }

    var requestAnimationFrame = window.requestAnimationFrame;
    var cancelAnimationFrame = window.cancelAnimationFrame;
})();

// requestAnimationFrame polyfill by Erik Möller. fixes from Paul Irish and Tino Zijdel
// http://paulirish.com/2011/requestanimationframe-for-smart-animating/
// http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating
// MIT license
(function() {
    var lastTime = 0;
    var vendors = ['ms', 'moz', 'webkit', 'o'];
    for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
        window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
        window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame']
                                   || window[vendors[x]+'CancelRequestAnimationFrame'];
    }

    if (!window.requestAnimationFrame)
        window.requestAnimationFrame = function(callback, element) {
            var currTime = new Date().getTime();
            var timeToCall = Math.max(0, 16 - (currTime - lastTime));
            var id = window.setTimeout(function() { callback(currTime + timeToCall); },
              timeToCall);
            lastTime = currTime + timeToCall;
            return id;
        };

    if (!window.cancelAnimationFrame)
        window.cancelAnimationFrame = function(id) {
            clearTimeout(id);
        };
}());
<commit_msg>Reverted to using regular functions instead of arrow functions<commit_after>(function () {
    var SCROLL_SENSITIVITY = 15;
    var RESIZE_SENSITIVITY = 20;

    window.websheet = function () {
        var columns = [];

        function websheet( selection ) {
            return websheet.draw( selection )
        }

        websheet.columns = function ( _columns ) {
            if ( arguments.length == 0 ) {
                return columns
            }
            columns = _columns;
            return this;
        }

        websheet.column = function ( name, accessor ) {
            if ( !accessor ) {
                accessor = function ( d ) {
                    return d[ name ]
                }
            }
            columns.push({
                name: name,
                accessor: accessor,
                w: 200
            });
            return this;
        }

        var el;
        websheet.draw = function ( selection ) {
            if ( selection instanceof Element ) {
                selection = d3.selectAll( [ selection ] );
            }

            selection.each( function ( data ) {
                el = this;
                draw( websheet, this, data );
                var max = getBounderies( websheet, this );
                websheet.__maxx = max.x;
                websheet.__maxy = max.y;
            })
            return this;
        }

        function getBounderies( that, el ) {
            var rect = el.getBoundingClientRect();
            var rows = d3.select( el )
                .selectAll( 'tbody > tr' )[ 0 ];

            var height = Math.floor( rect.height );
            var maxy;
            for ( maxy = rows.length ; maxy > 0 ; maxy -= 1 ) {
                height -= rows[ maxy - 1 ].getBoundingClientRect().height;
                if ( height <= 0 ) {
                    break
                }
            }

            maxy += 2; // extra room for 1 header row

            return { x: that.columns().length - 1, y: maxy }
        }

        var selection = { start: null, end: null }
        var selectAnimFrame;
        websheet.selection = function () {
            return {
                start: function ( xy ) {
                    if ( !arguments.length ) {
                        return selection.start;
                    }
                    selection.start = xy;
                    selection.end = xy;

                    cancelAnimationFrame( selectAnimFrame );
                    selectAnimFrame = requestAnimationFrame( function () {
                        drawSelection( el, selection.start, selection.end );
                    })

                    return this;
                },
                end: function ( xy ) {
                    if ( !arguments.length ) {
                        return selection.end;
                    }

                    selection.end = xy;
                    // debug( "Selection", "End:", xy );

                    cancelAnimationFrame( selectAnimFrame );
                    selectAnimFrame = requestAnimationFrame( function () {
                        drawSelection( el, selection.start, selection.end );
                    });

                    return this;
                },
            }
        }

        var scroll = [ 1, 1 ];
        var scrollAnimFrame;
        websheet.scroll = function ( xy ) {
            var rows = d3.select( el ).datum();
            if ( arguments.length == 0 ) {
                return [ scroll[ 0 ], scroll[ 1 ] ]; // copy
            }

            var x = Math.min( this.__maxx, Math.max( 1, xy[ 0 ] ) );
            var y = Math.min( this.__maxy, Math.max( 1, xy[ 1 ] ) );

            window.cancelAnimationFrame( scrollAnimFrame );

            if ( x == scroll[ 0 ] && y == scroll[ 1 ] ) {
                return this;
            }

            // changing the dom will only take place on the next animation
            // frame in order to throttle the ui repaints while the user scrolls
            scrollAnimFrame = requestAnimationFrame( function () {
                scroll = [ x, y ];
                scrollTo( el, x, y );
            });

            return this;
        }

        var rowNums = false;
        websheet.rowNumbers = function(enabled) {
            if (arguments.length === 0) {
                return rowNums
            }

            rowNums = enabled
            return rowNums
        }

        return websheet
    }

    function draw( that, el, data ) {
        el = d3.select( el )
            .classed( "websheet", true );

        if ( !el.node().__websheet ) {
            el.on( "mousewheel", onMouseWheel() );

            // el.on( "mousedown", onMouseDown() );
            // el.on( "mouseup", onMouseUp() );
            // el.on( "mousemove", onMouseMove() );

            init( el.node() );
        }

        el.node().__websheet = that;

        var columns = [].concat( that.columns() )

        // row-number column
        that.rowNumbers() && columns.unshift({
            accessor: function ( d, i ) {
                return d === undefined ? '' : i + 1;
            },
            w: 40,
            cls: 'row-number'
        })

        // extra right column to keep the display wide.
        columns.push({
            accessor: function () {},
            w: 2000
        });

        columns.forEach( function ( col, i ) {
            col.rown = 0;
            col.coln = i;
        })

        var colwidths = columns.map( function ( d ) {
            return d.w || 0;
        });

        // extra full height row.
        data = [].concat(data)
        data.push(undefined)

        var table = el.selectAll( "table" )
            .data( [ data ] );
        table.enter().append( "table" )
            .style( "position", "relative" )
            .style( "left", "0px" )
            .html( "

" )

        // headers
        var rows = table.select( "thead > tr" )
        var headers = rows.selectAll( "th" )
            .data( columns )
        headers.enter().append( "th" )
            .style( "position", "relative" );
        headers
            .text( function ( d ) {
                return d.name || ""
            })
            .style( "width", function ( d ) {
                return d.w + "px"
            })
            .attr('class', function (d) {
                return d.cls
            })

        // rows
        var tbody = table.select( "tbody" );
        var rows = tbody.selectAll( "tr" )
            .data( data );
        rows.exit().remove();
        rows.enter().append( "tr" );
        rows.style('height', function (d) {
            return d === undefined ? 'auto' : ''
        })
        var cells = rows.selectAll( "td" )
            .data( function ( d, i ) {
                return columns.map( function ( col, j ) {
                    return {
                        rown: i + 1,
                        coln: j,
                        v: d === undefined ? '' : col.accessor( d, i ),
                        cls: col.cls
                    }
                })
            })
        cells.enter().append( "td" )
        cells
            .text( function ( d ) {
                return d.v
            })
            .attr('class', function (d) { return d.cls })
    }

    function init( el ) {
        var options = { el: el };

        document.addEventListener('click', function(ev) {
            if (ev.__inWebsheet === el) {
                return
            }

            // de-select all.
            options.el.__websheet.selection().end(null)
        })

        el.addEventListener('click', function(ev) {
            ev.__inWebsheet = this
        })

        // resize
        el.addEventListener( "mousemove", function ( ev ) {
            ev.preventDefault()
            resizeMove( options, ev )
        });
        el.addEventListener( "mousedown", function ( ev ) {
            resizeDown( options, ev )
        });
        el.addEventListener( "mouseup", function ( ev ) {
            resizeUp( options, ev )
        });

        // select
        el.addEventListener( "mousemove", function ( ev ) {
            selectMove( options, ev );
        })
        el.addEventListener( "mousedown", function ( ev ) {
            selectDown( options, ev );
        })
        el.addEventListener( "mouseup", function ( ev ) {
            selectUp( options, ev );
        })
    }

    function resizeMove( options, ev ) {
        if ( options.resizing ) {
            var dx = ev.clientX - options.resizing.x;
            var w = options.resizing.w + dx;
            options.resizable.style.width = Math.max( w, 14 ) + "px";
            return;
        }

        var th = parentSelector( ev.target, ".websheet th" );
        var resizable;
        if ( th ) {
            var rect = th.getBoundingClientRect();
            var left = ev.clientX - rect.left;
            var right = rect.width - left;

            if ( right < RESIZE_SENSITIVITY ) {
                resizable = th;
            }
        }

        if ( options.resizable && options.resizable != resizable ) {
            options.resizable.classList.remove( "resizable" );
            options.resizable = null;
        }

        if ( resizable ) {
            resizable.classList.add( "resizable" );
            options.resizable = resizable;
        }
    }

    function resizeDown ( options, ev ) {
        if ( !options.resizable ) {
            return;
        }

        options.resizing = {
            w: parseInt( options.resizable.style.width ),
            x: ev.clientX
        }
    }

    function resizeUp ( options ) {
        if ( options.resizing ) {
            var col = d3.select( options.resizable ).datum();
            col.w = parseInt( options.resizable.style.width );
        }
        options.resizing = null;
    }

    function selectDown ( options, ev ) {
        if ( options.resizing ) {
            return
        }
        options.__selecting = true;
        ev.preventDefault();
        var datum = d3.select( ev.target ).datum();
        options.el.__websheet.selection()
            .start([ datum.coln || 0, datum.rown || 0 ])
    }

    function selectMove ( options, ev ) {
        if ( options.__selecting ) {
            var datum = d3.select( ev.target ).datum();
            options.el.__websheet.selection()
                .end([ datum.coln || Infinity, datum.rown || Infinity ]);
        }
    }

    function selectUp ( options, ev ) {
        if ( options.__selecting ) {
            var datum = d3.select( ev.target ).datum();
            options.el.__websheet.selection()
                .end([ datum.coln || Infinity, datum.rown || Infinity ]);
        }
        options.__selecting = false;
    }

    function onMouseWheel () {
        var deltaX = 0, deltaY = 0;
        return function ( ev ) {
            var ev = d3.event;
            ev.preventDefault();
            ev.stopPropagation();

            deltaX += ev.deltaX;
            deltaY += ev.deltaY;

            // debug( "MouseWheel", "X:", deltaX, "Y:", deltaY );
            var scroll = this.__websheet.scroll();
            if ( deltaX > SCROLL_SENSITIVITY ) {
                scroll[ 0 ] += 1;
                deltaX = 0;
            } else if ( deltaX < -SCROLL_SENSITIVITY ) {
                scroll[ 0 ] -= 1;
                deltaX = 0;
            }

            if ( deltaY > SCROLL_SENSITIVITY ) {
                scroll[ 1 ] += 1;
                deltaY = 0;
            } else if ( deltaY < -SCROLL_SENSITIVITY ) {
                scroll[ 1 ] -= 1;
                deltaY = 0;
            }

            this.__websheet.scroll( scroll );
        }
    }

    function drawSelection( el, start, end ) {
        el = d3.select( el );

        // remove previous selection
        el.selectAll( ".selected" )
            .classed( "selected", false );

        // empty selection or deselect
        if ( !start || !end ) {
            return;
        }

        var startx = start[ 0 ];
        var endx = end[ 0 ];
        var starty = start[ 1 ];
        var endy = end[ 1 ];

        // reversed order
        if ( startx > endx ) {
            endx = startx;
            startx = end[ 0 ];
        }
        if ( starty > endy ) {
            endy = starty;
            starty = end[ 1 ];
        }

        // find the relevant rows in the range of starty-endy
        var selector = [
            "tbody > tr",
            ":nth-child(n+" + ( starty ) + ")",
            endy == Infinity ? "" : ":nth-child(-n+" + ( endy ) + ")"
        ].join( "" );
        var rows = el.selectAll( selector );

        // find the relevant columns within these rows in the range
        // of startx-endx
        var selector = [
            "*",
            ":nth-child(n+" + ( startx + 1 ) + ")",
            endx == Infinity ? "" : ":nth-child(-n+" + ( endx + 1 ) + ")"
        ].join( "" );
        var cells = rows.selectAll( selector );

        // add the relevant headers to the selection
        var headers = el.select( "thead > tr" )
            .selectAll( selector );

        // add the relevant row-numbers to the selection
        var rownums = rows.selectAll( "td:first-child" );

        // finally, apply the selected class
        cells.classed( "selected", true );
        headers.classed( "selected", true );
        rownums.classed( "selected", true );
    }

    function scrollTo( el, x, y ) {

        // x-y starts with 1, offset back to 0
        x -= 1;
        y -= 1;

        var headers = el.querySelectorAll( "th" );
        var column = headers[ x + 1 ].getBoundingClientRect();
        var container = el.getBoundingClientRect();
        var rowsn = headers[ 0 ].getBoundingClientRect();
        var left = el.scrollLeft
            + column.left
            - container.left
            - rowsn.width;

        var rows = el.querySelectorAll( "th:first-child,td:first-child" );
        [].forEach.call( rows, function ( row ) {
            row.style.position = "relative";
            row.style.left = ( +row.style.left || 0 ) + left + "px";
        })

        el.scrollLeft = left;

        // find the relevant row element
        var row = el.querySelector( "tbody > tr:nth-child(" + ( y + 1 ) + ")" );
        var rect = row.getBoundingClientRect();
        var top = el.scrollTop
            + rect.top
            - container.top
            - column.height;

        [].forEach.call( headers, function ( row ) {
            row.style.position = "relative";
            row.style.top = ( +row.style.top || 0 ) + top + "px";
        })

        el.scrollTop = top;
    }

    // debug
    window.websheet.debug = true;
    function debug() {
        if ( window.websheet.debug ) {
            console.log.apply( console, arguments );
        }
    }

    function parentSelector( el, selector ) {
        while ( el && el.matches ) {
            if ( el.matches( selector ) ) {
                return el;
            }
            el = el.parentNode;
        }
    }

    var requestAnimationFrame = window.requestAnimationFrame;
    var cancelAnimationFrame = window.cancelAnimationFrame;
})();

// requestAnimationFrame polyfill by Erik Möller. fixes from Paul Irish and Tino Zijdel
// http://paulirish.com/2011/requestanimationframe-for-smart-animating/
// http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating
// MIT license
(function() {
    var lastTime = 0;
    var vendors = ['ms', 'moz', 'webkit', 'o'];
    for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
        window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
        window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame']
                                   || window[vendors[x]+'CancelRequestAnimationFrame'];
    }

    if (!window.requestAnimationFrame)
        window.requestAnimationFrame = function(callback, element) {
            var currTime = new Date().getTime();
            var timeToCall = Math.max(0, 16 - (currTime - lastTime));
            var id = window.setTimeout(function() { callback(currTime + timeToCall); },
              timeToCall);
            lastTime = currTime + timeToCall;
            return id;
        };

    if (!window.cancelAnimationFrame)
        window.cancelAnimationFrame = function(id) {
            clearTimeout(id);
        };
}());
<|endoftext|>


<commit_before>require('fileapi');

var backbone = require('backbone');
var backboneBase = require('backbone-base');
var getUri = require('get-uri');
var Goodtables = require('../goodtables');
var jsonEditor = require('json-editor');
var jtsInfer = require('jts-infer');
var highlight = require('highlight-redux');
var UploadView = require('./upload');
var registry = require('./registry');
var _ = require('underscore');
var $ = require('jquery');

// Upload data file and populate .resource array with item
DataUploadView = backbone.BaseView.extend({
  events: {
    // Set up and append .resources row
    'change [data-id=input]': function(E) {
      FileAPI.readAsText(FileAPI.getFiles(E.currentTarget)[0], (function (EV) {
        if(EV.type === 'load') {
          getUri(['data', EV.target.type, 'utf-8'].join(':') + ',' + EV.result, (function (E, R) {
            if(E) throw E;

            jtsInfer(R, (function(E, S, SR) {
              if(E) throw E;

              this.options.form.getEditor('root.resources').addRow({
                name: EV.target.name,
                path: EV.target.name,
                schema: S
              });

              // Save data source
              _.last(this.options.form.getEditor('root.resources').rows).dataSource = EV.result;
            }).bind(this));
          }).bind(this));
        } else if( EV.type ==='progress' ) {
          this.setProgress(EV.loaded/EV.total * 100);
        } else {
          this.setError('File upload failed');
        }

        this.$(E.currentTarget).val('');
      }).bind(this));
    },

    'click [data-id=upload-data-file]': function() { this.$('[data-id=input]').trigger('click'); }
  },

  render: function() {
    this.$el
      .append('<input data-id="input" type="file" accept="text/csv" style="display: none;">')

      .append(
        $(this.options.form.theme.getButton('Upload data file', '', 'Upload data file'))
          .attr('data-id', 'upload-data-file')
      );

    return this;
  },

  setError: function() { return this; },
  setProgress: function() { return this; }
});

module.exports = {
  DescriptorEditView: backbone.BaseView.extend({
    activate: function(state) {
      backbone.BaseView.prototype.activate.call(this, state);
      this.layout.upload.activate(state);
      return this;
    },

    events: {
      'click #validate-resources': function() {
        var
          goodTables = new Goodtables({method: 'post'});

        // Clear previous
        this.$('#resources-validation-messages [data-id=messages]').remove();

        _.each(this.layout.form.getEditor('root.resources').rows, function(R) {
          goodTables.run(R.dataSource, JSON.stringify( {fields: _.map(R.schema.properties, function(V, K) {
              return _.extend(V, {name: K}) })}
          )).then(
            function(M) {
              // Ok
              window.APP.$('#resources-validation-messages').append(
                _.map(M.isValid() ? ['Validation Success'] : M.getValidationErrors(), function(M) {
                  return ['
', M.result_message, '
'].join('');
                }));
            }
          );
        });
      }
    },

    initialize: function(options) {
      highlight.configure({useBR: true});
      return backbone.BaseView.prototype.initialize.call(this, options);
    },

    render: function() {
      this.layout.upload = new UploadView({el: window.APP.$('#upload-data-package'), parent: this});
      this.layout.registryList = new registry.ListView({el: window.APP.$('#registry-list'), parent: this});
      return this;
    },

    // Utility method to remove empty values from object recursive
    compactObject: function(data) {
      _.each(data, function(v, k) {
        if(_.isEmpty(v)) {
          delete data[k];
        } else if(_.isArray(v) || _.isObject(v)) {
          v = this.compactObject(v);

          if(_.isArray(v))
            v = _.compact(v);

          if(_.isEmpty(v))
            delete data[k];
          else data[k] = v;
        }
      }, this);

      return data;
    },

    getFilledValues: function() { return this.compactObject(this.layout.form.getValue()); },
    getValue: function () { return this.layout.form.getValue(); },
    hasChanges: function() { return Boolean(this.changed); },

    reset: function(schema) {
      var formData;

      // Clean up previous state
      if(this.layout.form) {
        formData = this.getFilledValues();
        this.layout.form.destroy();
        this.layout.uploadData.undelegateEvents().remove();
      }

      this.layout.form = new JSONEditor(this.$('[data-id=form-container]').get(0), {
        schema: schema,
        theme: 'bootstrap3'
      });

      this.layout.uploadData = (new DataUploadView({
        el: this.layout.form.theme.getHeaderButtonHolder(),
        form: this.layout.form,
        parent: this
      })).render();

      this.layout.form.on('ready', (function() {
        // There is no any good way to bind events to custom button or even add cutsom button
        $(this.layout.form.getEditor('root.resources').container)
          .children('h3').append(this.layout.uploadData.el);

        // Detecting changes
        this.changed = false;

        // After `ready` event fired, editor fire `change` event regarding to the initial changes
        this.layout.form.on('change', _.after(2, (function() {
          this.changed = true;
          window.APP.layout.download.reset(this.layout.form.getValue()).activate();
          this.showResult();
        }).bind(this)));

        // If on the previous form was entered values try to apply it to new form
        if(formData) {
          this.layout.form.setValue(_.extend({}, this.layout.form.getValue(formData), formData));

          // Expand editors if it have value
          _.each(this.$('[data-schemapath][data-schemapath!=root]:has(.json-editor-btn-collapse)'), function(E) {
              if(_.isEmpty(this.layout.form.getEditor($(E).data('schemapath')).getValue()))
                $(E).find('.json-editor-btn-collapse').click();
          }, this);
        } else
          // Collapse all
          this.$('.row .json-editor-btn-collapse').click();

      }).bind(this));
    },

    showResult: function() {
      $('#json-code').html(highlight.fixMarkup(
        highlight.highlight('json', JSON.stringify(this.layout.form.getValue(), undefined, 2)).value
      ));

      return this;
    }
  })
};
<commit_msg>Clear validation messages on switch form (#33)<commit_after>require('fileapi');

var backbone = require('backbone');
var backboneBase = require('backbone-base');
var getUri = require('get-uri');
var Goodtables = require('../goodtables');
var jsonEditor = require('json-editor');
var jtsInfer = require('jts-infer');
var highlight = require('highlight-redux');
var UploadView = require('./upload');
var registry = require('./registry');
var _ = require('underscore');
var $ = require('jquery');

// Upload data file and populate .resource array with item
DataUploadView = backbone.BaseView.extend({
  events: {
    // Set up and append .resources row
    'change [data-id=input]': function(E) {
      FileAPI.readAsText(FileAPI.getFiles(E.currentTarget)[0], (function (EV) {
        if(EV.type === 'load') {
          getUri(['data', EV.target.type, 'utf-8'].join(':') + ',' + EV.result, (function (E, R) {
            if(E) throw E;

            jtsInfer(R, (function(E, S, SR) {
              if(E) throw E;

              this.options.form.getEditor('root.resources').addRow({
                name: EV.target.name,
                path: EV.target.name,
                schema: S
              });

              // Save data source
              _.last(this.options.form.getEditor('root.resources').rows).dataSource = EV.result;
            }).bind(this));
          }).bind(this));
        } else if( EV.type ==='progress' ) {
          this.setProgress(EV.loaded/EV.total * 100);
        } else {
          this.setError('File upload failed');
        }

        this.$(E.currentTarget).val('');
      }).bind(this));
    },

    'click [data-id=upload-data-file]': function() { this.$('[data-id=input]').trigger('click'); }
  },

  render: function() {
    this.$el
      .append('<input data-id="input" type="file" accept="text/csv" style="display: none;">')

      .append(
        $(this.options.form.theme.getButton('Upload data file', '', 'Upload data file'))
          .attr('data-id', 'upload-data-file')
      );

    return this;
  },

  setError: function() { return this; },
  setProgress: function() { return this; }
});

module.exports = {
  DescriptorEditView: backbone.BaseView.extend({
    activate: function(state) {
      backbone.BaseView.prototype.activate.call(this, state);
      this.layout.upload.activate(state);
      return this;
    },

    clearResourceValidation: function() {
      this.$('#resources-validation-messages [data-id=messages]').remove();
      return this;
    },

    events: {
      'click #validate-resources': function() {
        var
          goodTables = new Goodtables({method: 'post'});

        // Clear previous
        this.clearResourceValidation();

        _.each(this.layout.form.getEditor('root.resources').rows, function(R) {
          goodTables.run(R.dataSource, JSON.stringify( {fields: _.map(R.schema.properties, function(V, K) {
              return _.extend(V, {name: K}) })}
          )).then(
            function(M) {
              // Ok
              window.APP.$('#resources-validation-messages').append(
                _.map(M.isValid() ? ['Validation Success'] : M.getValidationErrors(), function(M) {
                  return ['
', M.result_message, '
'].join('');
                }));
            }
          );
        });
      }
    },

    initialize: function(options) {
      highlight.configure({useBR: true});
      return backbone.BaseView.prototype.initialize.call(this, options);
    },

    render: function() {
      this.layout.upload = new UploadView({el: window.APP.$('#upload-data-package'), parent: this});
      this.layout.registryList = new registry.ListView({el: window.APP.$('#registry-list'), parent: this});
      return this;
    },

    // Utility method to remove empty values from object recursive
    compactObject: function(data) {
      _.each(data, function(v, k) {
        if(_.isEmpty(v)) {
          delete data[k];
        } else if(_.isArray(v) || _.isObject(v)) {
          v = this.compactObject(v);

          if(_.isArray(v))
            v = _.compact(v);

          if(_.isEmpty(v))
            delete data[k];
          else data[k] = v;
        }
      }, this);

      return data;
    },

    getFilledValues: function() { return this.compactObject(this.layout.form.getValue()); },
    getValue: function () { return this.layout.form.getValue(); },
    hasChanges: function() { return Boolean(this.changed); },

    reset: function(schema) {
      var formData;

      this.clearResourceValidation();

      // Clean up previous state
      if(this.layout.form) {
        formData = this.getFilledValues();
        this.layout.form.destroy();
        this.layout.uploadData.undelegateEvents().remove();
      }

      this.layout.form = new JSONEditor(this.$('[data-id=form-container]').get(0), {
        schema: schema,
        theme: 'bootstrap3'
      });

      this.layout.uploadData = (new DataUploadView({
        el: this.layout.form.theme.getHeaderButtonHolder(),
        form: this.layout.form,
        parent: this
      })).render();

      this.layout.form.on('ready', (function() {
        // There is no any good way to bind events to custom button or even add cutsom button
        $(this.layout.form.getEditor('root.resources').container)
          .children('h3').append(this.layout.uploadData.el);

        // Detecting changes
        this.changed = false;

        // After `ready` event fired, editor fire `change` event regarding to the initial changes
        this.layout.form.on('change', _.after(2, (function() {
          this.changed = true;
          window.APP.layout.download.reset(this.layout.form.getValue()).activate();
          this.showResult();
        }).bind(this)));

        // If on the previous form was entered values try to apply it to new form
        if(formData) {
          this.layout.form.setValue(_.extend({}, this.layout.form.getValue(formData), formData));

          // Expand editors if it have value
          _.each(this.$('[data-schemapath][data-schemapath!=root]:has(.json-editor-btn-collapse)'), function(E) {
              if(_.isEmpty(this.layout.form.getEditor($(E).data('schemapath')).getValue()))
                $(E).find('.json-editor-btn-collapse').click();
          }, this);
        } else
          // Collapse all
          this.$('.row .json-editor-btn-collapse').click();

      }).bind(this));
    },

    showResult: function() {
      $('#json-code').html(highlight.fixMarkup(
        highlight.highlight('json', JSON.stringify(this.layout.form.getValue(), undefined, 2)).value
      ));

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


<commit_before>// Part 1
R={},document.body.innerText.split`\n`.map(l=>l&&([x,a,y,,z,o,v]=l.split` `,R[x]=(R[x]|0)+y*(a[0]=='i'?1:-1)*eval((R[z]|0)+o+v))),Math.max(...Object.values(R))
<commit_msg>Add day 8 solution part 2<commit_after>// Part 1
R={},document.body.innerText.split`\n`.map(l=>l&&([x,a,y,,z,o,v]=l.split` `,R[x]=(R[x]|0)+y*(a[0]=='i'?1:-1)*eval((R[z]|0)+o+v))),Math.max(...Object.values(R))

// Part 2
m=0,R={},document.body.innerText.split`\n`.map(l=>l&&([x,a,y,,z,o,v]=l.split` `,m=Math.max(m,R[x]=(R[x]|0)+y*(a[0]=='i'?1:-1)*eval((R[z]|0)+o+v)))),m
<|endoftext|>


<commit_before>'use strict';

angular
    .module('demo', ['ngWebSocket'])
    .config(function ($webSocketProvider) {
        //$webSocketProvider.baseUrl('ws://localhost');
    })
    .run(function ($webSocket) {
        /*var ws = $webSocket.$new('ws://localhost:12345');

        ws.$on('$message', function (message) {
            console.log('$message');
            console.log(message);
        });

        ws.$on('test', function (message) {
            console.log('test');
            console.log(message);
        });

        ws.$on('$open', function () {
            console.log('Websocket opened');

            ws.$emit('test', {hi: 'dude'})
              .$emit('test', 'asd');
        });*/

        /*ws.$on('$message', function (data) {

        });

        ws.$on('my own event', function (data) {
           $scope.myData = data;
        });

        ws.$bind('my data event', $scope.myData);

        ws.$un('an event');

        ws.$emit('an event', data);

        ws.$close();

        $webSocket.$get('ws:url');*/
    });<commit_msg>removed useless directives<commit_after>'use strict';

angular
    .module('demo', ['ngWebsocket'])
    .config(function ($websocketProvider) {
        //$webSocketProvider.baseUrl('ws://localhost');
    })
    .run(function ($websocket) {
        var ws = $websocket.$new('ws://localhost:12345');

        ws.$on('$message', function (message) {
            console.log('$message');
            console.log(message);
        });

        ws.$on('test', function (message) {
            console.log('test');
            console.log(message);
        });

        ws.$on('$open', function () {
            console.log('Websocket opened');

            ws.$emit('test', {hi: 'dude'})
              .$emit('test', 'asd');
        });

        /*ws.$on('$message', function (data) {

        });

        ws.$on('my own event', function (data) {
           $scope.myData = data;
        });

        ws.$bind('my data event', $scope.myData);

        ws.$un('an event');

        ws.$emit('an event', data);

        ws.$close();

        $webSocket.$get('ws:url');*/
    });<|endoftext|>


<commit_before>/**
 * Created by Dmytro on 4/11/2016.
 */
(function(){
    'use strict';

    angular.module('hereMaps', [])
        .provider()
        .directive('hereMaps', HereMaps);

    function HereMaps() {
        return {
            restrict: EA,
            templateUrl: 'heremaps.tpl.html',
            controller: function($scope, $element){

            },
            link: function(){}

        }
    }
})();<commit_msg>Delete heremaps.directive.js<commit_after><|endoftext|>


<commit_before>"use strict";

var url = require('url'),
	qs = require('querystring'),
	fs = require('fs'),
	formidable = require('formidable');

var print_request = false;
var BACKBONE = 'backbone', BACKBONE_MODEL = 'model', BACKBONE_COLLECTION = 'collection',
	AUTHORIZATION = 'authorization',
	ACCEPT = 'accept',
	ACCEPT_LANGUAGE = 'accept-language',
	USER_AGENT = 'user-agent',
	CONTENT_LENGTH = 'content-length',
	CONTENT_TYPE = 'content-type',
	IF_NONE_MATCH = 'if-none-match',
	IF_MODIFIED_SINCE = 'if-modified-since',
	X_REQUESTED_WITH = 'x-requested-with',
	REFERER = 'referer';

exports.printRequest = function (print) {
	print_request = print;
	return this;
};

function HttpRequest(req, cb) {
	this._httpVersion = req.httpVersion;
	this._headers = req.headers;
	this._url = url.parse(req.url);
	if(this._url.query) this._url.query = qs.parse(this._url.query);
	this._method = req.method;
	this._cookie = parseCookie(this._headers['cookie']);
	this._request = req;
	if(print_request) global.gozy.debug('printing request...\n----------- REQUEST BEGIN -----------\n' + this.toString() + '------------ REQUEST END ------------');

	if((this._method === 'POST' || this._method === 'PUT' || this._method === 'PATCH'))
		return parseBody(req, this, cb);
	else
		return cb(this);
}

HttpRequest.prototype.on = function (evt, func) {
	this._request.on.call(this._request, evt, func);
};

function parseBody(req, http_req, cb) {
	var content_type = (!http_req._headers[CONTENT_TYPE] ? 'application/x-www-form-urlencoded' : http_req._headers[CONTENT_TYPE].split(';')[0]);
	switch(content_type) {
	case 'multipart/form-data':
		new formidable.IncomingForm().parse(req, function(err, fields, files) {
			var _body = {};
			for(var key in fields)
				_body[key] = fields[key];
			for(var key in files) {
				_body[key] = files[key];
				delete _body[key]['hash'];
				delete _body[key]['lastModifiedDate'];
				delete _body[key]['length'];
				delete _body[key]['filename'];
				delete _body[key]['mime'];
				_body[key]['load'] = function () {
					return fs.readFileSync(_body[key]['path']);
				};
			}

			http_req._body = _body;
			return cb(http_req);
		});
		break;
	case 'application/x-www-form-urlencoded':
		var charset = getCharset(http_req._headers[CONTENT_TYPE]);
		if(!charset) charset='utf8';

		var body = [], buf_size = 0;
		req.on('data', function(chunk) {
			body.push(chunk);
			buf_size += chunk.length;
		});

		req.on('end', function() {
			var buf = new Buffer(buf_size);
			for(var i=0, len=body.length, pos=0; i<len; i++) {
				body[i].copy(buf, pos);
				pos += body[i].length;
			}

			try {
				var _body = qs.parse(body.toString(charset));
				for(var key in _body) {
				if(typeof _body[key] === 'string')
					try {
						_body[key] = decodeURIComponent(_body[key]);
					} catch (e) {
						global.gozy.warn(e);
						if(_body[key]) delete _body[key];
					}
				}
				http_req._body = _body;
				return cb(http_req);
			} catch (err) {
				global.gozy.error(err.stack);
				return cb(http_req);
			}
		});
		break;
	case 'application/json':
		var charset = getCharset(http_req._headers[CONTENT_TYPE]);
		if(!charset) charset='utf8';

		var body = [], buf_size = 0;
		req.on('data', function(chunk) {
			body.push(chunk);
			buf_size += chunk.length;
		});

		req.on('end', function() {
			var buf = new Buffer(buf_size);
			for(var i=0, len=body.length, pos=0; i<len; i++) {
				body[i].copy(buf, pos);
				pos += body[i].length;
			}

			try {
				var _body = JSON.parse(buf.toString(charset));
				http_req._body = _body;
				return cb(http_req);
			} catch (err) {
				http_req._body = { };
				return cb(http_req);
			}
		});
		break;
	/* TODO: Support text/xml */
	default:
		global.gozy.warn('unknown content-type: ' + content_type);
		return cb(http_req);
	}
}

HttpRequest.prototype.body = function (item, func) {
	if(!this._body) return undefined;
	else if(item && func)
		return func(this._body[item]);
	else if(item)
		return this._body[item];
	else
		return this._body;
};

HttpRequest.prototype.cookie = function (key) {
	if(key)
		return this._cookie[key];
	else
		return this._cookie;
};

HttpRequest.prototype.header = function (key) {
	if(key)
		return this._headers[key];
	else
		return this._headers;
};

HttpRequest.prototype.authorization = function () {
	var authorization = this._headers[AUTHORIZATION];
	var obj = {};
	if(authorization) {
		authorization = authorization.split(' ');
		if(authorization.length == 2)
			obj[authorization[0]] = authorization[1];
		else if(authorization.length == 1)
			obj[authorization[0]] = '';
		else
			obj[authorization[0]] = '';
		return obj;
	} else
		return null;
};

HttpRequest.prototype.accept = function () {
	var accept = this._headers[ACCEPT], ordered_accept = [];
	if(!accept) return ['*/*'];
	accept = accept.split(',');
	try {
		for(var i=0; i<accept.length; i++) {
			accept[i] = accept[i].split(';');
			if(accept[i].length === 1) accept[i].push(1);
			else accept[i][1] = parseFloat(accept[i][1].split('=')[1]);
		}

		for(var i=0; i<accept.length-1; i++) {
			for(var j=i; j<accept.length; j++) {
				if(accept[i][1] < accept[j][1]) {
					var tmp = accept[i];
					accept[i] = accept[j];
					accept[j] = tmp;
				}
			}
		}

		for(var i=0; i<accept.length; i++)
			ordered_accept.push(accept[i][0].trim());
	} catch(e) {
		return null;
	}

	return ordered_accept;
};

HttpRequest.prototype.setLocale = function (locale) {
	this._headers[ACCEPT_LANGUAGE] = locale + ';q=1';
	return this;
};

HttpRequest.prototype.locale = function () {
	var locale = this._headers[ACCEPT_LANGUAGE], ordered_locale = [];
	if(!locale) return ['en-us', '*'];
	locale = locale.split(',');
	try {
		for(var i=0; i<locale.length; i++) {
			locale[i] = locale[i].split(';');
			if(locale[i].length === 1) locale[i].push(1);
			else locale[i][1] = parseFloat(locale[i][1].split('=')[1]);
		}

		for(var i=0; i<locale.length-1; i++) {
			for(var j=i; j<locale.length; j++) {
				if(locale[i][1] < locale[j][1]) {
					var tmp = locale[i];
					locale[i] = locale[j];
					locale[j] = tmp;
				}
			}
		}

		for(var i=0; i<locale.length; i++)
			ordered_locale.push(locale[i][0].toLowerCase());
	} catch(e) {
		return null;
	}

	return ordered_locale;
};

HttpRequest.prototype.isXHR = function () {
	return this._headers[X_REQUESTED_WITH] === 'XMLHttpRequest';
};

HttpRequest.prototype.isXHROriginatedFrom = function (origin) {
	if(this.isXHR()) {
		if(!this._headers[REFERER]) return false;
		var _referer = url.parse(this._headers[REFERER]);
		return _referer.host === origin;
	}
	return false;
};

HttpRequest.prototype.pathname = function (pathno) {
	if(pathno) {
		var paths = this._url.pathname.split('/');
		return paths[pathno + 1];
	}
	return this._url.pathname;
};

HttpRequest.prototype.query = function (name, func) {
	if(!this._url.query) return undefined;
	else if(name && func)
		return func(this._url.query[name]);
	else if(name)
		return this._url.query[name];
	else
		return this._url.query;
};

HttpRequest.prototype.method = function () {
	return this._method;
};

HttpRequest.prototype.contentLength = function () {
	return parseInt(this._headers[CONTENT_LENGTH]);
};

HttpRequest.prototype.contentType = function () {
	return this._headers[CONTENT_TYPE];
};

HttpRequest.prototype.userAgent = function () {
	return this._headers[USER_AGENT];
};

HttpRequest.prototype.isModified = function (etag, last_modified) {
	var _etag = this._headers[IF_NONE_MATCH];
	var _last_modified = this._headers[IF_MODIFIED_SINCE];

	if(!_etag && !_last_modified)
		return true;
	if(!etag && !last_modified)
		return true;

	if(etag) {
		if(!_etag || _etag !== etag)
			return true;
	}
	if(last_modified) {
		if(!_last_modified || new Date(_last_modified).getTime() < new Date(last_modified).getTime())
			return true;
	}

	return false;
};

HttpRequest.prototype.isBackboneRequest = function () {
	return (this.query(BACKBONE) === BACKBONE_MODEL ? BACKBONE_MODEL : this.query(BACKBONE) === BACKBONE_COLLECTION ? BACKBONE_COLLECTION : null);
};

HttpRequest.prototype._rewriteRequest = function (_method, _url) {
	this._method = _method;
	this._url = url.parse(_url);
	return this;
};

HttpRequest.prototype.toString = function () {
	var str = [];
	str.push('[HTTP REQUEST OBJECT]');
	str.push('--- REQUEST BEGIN ---');
	str.push(this._method + ' ' + url.format(this._url) + ' HTTP/' + this._httpVersion);
	for(var key in this._headers)
		str.push(key + ': ' + this._headers[key]);
	str.push('');
	if(this._body)
		str.push(JSON.stringify(this._body));
	str.push('---- REQUEST END ----');
	return str.join('\n');
};

function parseCookie(cookie_str) {
	if(!cookie_str) return {};

	var cookie = {},
		str = [],
		key = undefined;

	for(var pos=0; pos < cookie_str.length; pos++) {
		switch(cookie_str.charAt(pos)) {
		case ';':
			if(key) {
				cookie[key] = str.join('').trim();
				str = [];
				key = undefined;
			}
			break;
		case '=':
			if(!key) {
				key = str.join('').trim();
				str = [];
				break;
			}
		default:
			str.push(cookie_str.charAt(pos));
			break;
		}
	}

	cookie[key] = str.join('').trim();

	return cookie;
}

function getCharset (str) {
	if(!str) return 'utf8';
	var charset = str.split(';');
	if(charset.length == 2) charset = charset[1];
	else return 'utf8';

	charset = charset.split('=');
	if(!charset || charset.length !== 2) return '';

	switch(charset[1].toLowerCase()) {
	case 'utf-8': return 'utf8';
	default: return null;
	}
}

exports.HttpRequest = HttpRequest;<commit_msg>update content-length when chunked transfer-encoding<commit_after>"use strict";

var url = require('url'),
	qs = require('querystring'),
	fs = require('fs'),
	formidable = require('formidable');

var print_request = false;
var BACKBONE = 'backbone', BACKBONE_MODEL = 'model', BACKBONE_COLLECTION = 'collection',
	AUTHORIZATION = 'authorization',
	ACCEPT = 'accept',
	ACCEPT_LANGUAGE = 'accept-language',
	USER_AGENT = 'user-agent',
	CONTENT_LENGTH = 'content-length',
	CONTENT_TYPE = 'content-type',
	IF_NONE_MATCH = 'if-none-match',
	IF_MODIFIED_SINCE = 'if-modified-since',
	X_REQUESTED_WITH = 'x-requested-with',
	REFERER = 'referer';

exports.printRequest = function (print) {
	print_request = print;
	return this;
};

function HttpRequest(req, cb) {
	this._httpVersion = req.httpVersion;
	this._headers = req.headers;
	this._url = url.parse(req.url);

	if(this._url.query) this._url.query = qs.parse(this._url.query);
	this._method = req.method;
	this._cookie = parseCookie(this._headers['cookie']);
	this._request = req;
	if(print_request) global.gozy.debug('printing request...\n----------- REQUEST BEGIN -----------\n' + this.toString() + '------------ REQUEST END ------------');

	if((this._method === 'POST' || this._method === 'PUT' || this._method === 'PATCH'))
		return parseBody(req, this, cb);
	else
		return cb(this);
}

HttpRequest.prototype.on = function (evt, func) {
	this._request.on.call(this._request, evt, func);
};

function parseBody(req, http_req, cb) {
	var content_type = (!http_req._headers[CONTENT_TYPE] ? 'application/x-www-form-urlencoded' : http_req._headers[CONTENT_TYPE].split(';')[0]);
	switch(content_type) {
	case 'multipart/form-data':
		new formidable.IncomingForm().parse(req, function(err, fields, files) {
			var _body = {};
			for(var key in fields)
				_body[key] = fields[key];
			for(var key in files) {
				_body[key] = files[key];
				delete _body[key]['hash'];
				delete _body[key]['lastModifiedDate'];
				delete _body[key]['length'];
				delete _body[key]['filename'];
				delete _body[key]['mime'];
				_body[key]['load'] = function () {
					return fs.readFileSync(_body[key]['path']);
				};
			}

			http_req._body = _body;
			return cb(http_req);
		});
		break;
	case 'application/x-www-form-urlencoded':
		var charset = getCharset(http_req._headers[CONTENT_TYPE]);
		if(!charset) charset='utf8';

		var body = [], buf_size = 0;
		req.on('data', function(chunk) {
			body.push(chunk);
			buf_size += chunk.length;
		});

		req.on('end', function() {
			var buf = new Buffer(buf_size);
			for(var i=0, len=body.length, pos=0; i<len; i++) {
				body[i].copy(buf, pos);
				pos += body[i].length;
			}

			if(http_req._headers['transfer-encoding'] == 'chunked') http_req._headers['content-length'] = buf_size;

			try {
				var _body = qs.parse(body.toString(charset));
				for(var key in _body) {
				if(typeof _body[key] === 'string')
					try {
						_body[key] = decodeURIComponent(_body[key]);
					} catch (e) {
						global.gozy.warn(e);
						if(_body[key]) delete _body[key];
					}
				}
				http_req._body = _body;
				return cb(http_req);
			} catch (err) {
				global.gozy.error(err.stack);
				return cb(http_req);
			}
		});
		break;
	case 'application/json':
		var charset = getCharset(http_req._headers[CONTENT_TYPE]);
		if(!charset) charset='utf8';

		var body = [], buf_size = 0;
		req.on('data', function(chunk) {
			body.push(chunk);
			buf_size += chunk.length;
		});

		req.on('end', function() {
			var buf = new Buffer(buf_size);
			for(var i=0, len=body.length, pos=0; i<len; i++) {
				body[i].copy(buf, pos);
				pos += body[i].length;
			}

			if(http_req._headers['transfer-encoding'] == 'chunked') http_req._headers['content-length'] = buf_size;

			try {
				var _body = JSON.parse(buf.toString(charset));
				http_req._body = _body;
				return cb(http_req);
			} catch (err) {
				http_req._body = { };
				return cb(http_req);
			}
		});
		break;
	/* TODO: Support text/xml */
	default:
		global.gozy.warn('unknown content-type: ' + content_type);
		return cb(http_req);
	}
}

HttpRequest.prototype.body = function (item, func) {
	if(!this._body) return undefined;
	else if(item && func)
		return func(this._body[item]);
	else if(item)
		return this._body[item];
	else
		return this._body;
};

HttpRequest.prototype.cookie = function (key) {
	if(key)
		return this._cookie[key];
	else
		return this._cookie;
};

HttpRequest.prototype.header = function (key) {
	if(key)
		return this._headers[key];
	else
		return this._headers;
};

HttpRequest.prototype.authorization = function () {
	var authorization = this._headers[AUTHORIZATION];
	var obj = {};
	if(authorization) {
		authorization = authorization.split(' ');
		if(authorization.length == 2)
			obj[authorization[0]] = authorization[1];
		else if(authorization.length == 1)
			obj[authorization[0]] = '';
		else
			obj[authorization[0]] = '';
		return obj;
	} else
		return null;
};

HttpRequest.prototype.accept = function () {
	var accept = this._headers[ACCEPT], ordered_accept = [];
	if(!accept) return ['*/*'];
	accept = accept.split(',');
	try {
		for(var i=0; i<accept.length; i++) {
			accept[i] = accept[i].split(';');
			if(accept[i].length === 1) accept[i].push(1);
			else accept[i][1] = parseFloat(accept[i][1].split('=')[1]);
		}

		for(var i=0; i<accept.length-1; i++) {
			for(var j=i; j<accept.length; j++) {
				if(accept[i][1] < accept[j][1]) {
					var tmp = accept[i];
					accept[i] = accept[j];
					accept[j] = tmp;
				}
			}
		}

		for(var i=0; i<accept.length; i++)
			ordered_accept.push(accept[i][0].trim());
	} catch(e) {
		return null;
	}

	return ordered_accept;
};

HttpRequest.prototype.setLocale = function (locale) {
	this._headers[ACCEPT_LANGUAGE] = locale + ';q=1';
	return this;
};

HttpRequest.prototype.locale = function () {
	var locale = this._headers[ACCEPT_LANGUAGE], ordered_locale = [];
	if(!locale) return ['en-us', '*'];
	locale = locale.split(',');
	try {
		for(var i=0; i<locale.length; i++) {
			locale[i] = locale[i].split(';');
			if(locale[i].length === 1) locale[i].push(1);
			else locale[i][1] = parseFloat(locale[i][1].split('=')[1]);
		}

		for(var i=0; i<locale.length-1; i++) {
			for(var j=i; j<locale.length; j++) {
				if(locale[i][1] < locale[j][1]) {
					var tmp = locale[i];
					locale[i] = locale[j];
					locale[j] = tmp;
				}
			}
		}

		for(var i=0; i<locale.length; i++)
			ordered_locale.push(locale[i][0].toLowerCase());
	} catch(e) {
		return null;
	}

	return ordered_locale;
};

HttpRequest.prototype.isXHR = function () {
	return this._headers[X_REQUESTED_WITH] === 'XMLHttpRequest';
};

HttpRequest.prototype.isXHROriginatedFrom = function (origin) {
	if(this.isXHR()) {
		if(!this._headers[REFERER]) return false;
		var _referer = url.parse(this._headers[REFERER]);
		return _referer.host === origin;
	}
	return false;
};

HttpRequest.prototype.pathname = function (pathno) {
	if(pathno) {
		var paths = this._url.pathname.split('/');
		return paths[pathno + 1];
	}
	return this._url.pathname;
};

HttpRequest.prototype.query = function (name, func) {
	if(!this._url.query) return undefined;
	else if(name && func)
		return func(this._url.query[name]);
	else if(name)
		return this._url.query[name];
	else
		return this._url.query;
};

HttpRequest.prototype.method = function () {
	return this._method;
};

HttpRequest.prototype.contentLength = function () {
	return parseInt(this._headers[CONTENT_LENGTH]);
};

HttpRequest.prototype.contentType = function () {
	return this._headers[CONTENT_TYPE];
};

HttpRequest.prototype.userAgent = function () {
	return this._headers[USER_AGENT];
};

HttpRequest.prototype.isModified = function (etag, last_modified) {
	var _etag = this._headers[IF_NONE_MATCH];
	var _last_modified = this._headers[IF_MODIFIED_SINCE];

	if(!_etag && !_last_modified)
		return true;
	if(!etag && !last_modified)
		return true;

	if(etag) {
		if(!_etag || _etag !== etag)
			return true;
	}
	if(last_modified) {
		if(!_last_modified || new Date(_last_modified).getTime() < new Date(last_modified).getTime())
			return true;
	}

	return false;
};

HttpRequest.prototype.isBackboneRequest = function () {
	return (this.query(BACKBONE) === BACKBONE_MODEL ? BACKBONE_MODEL : this.query(BACKBONE) === BACKBONE_COLLECTION ? BACKBONE_COLLECTION : null);
};

HttpRequest.prototype._rewriteRequest = function (_method, _url) {
	this._method = _method;
	this._url = url.parse(_url);
	return this;
};

HttpRequest.prototype.toString = function () {
	var str = [];
	str.push('[HTTP REQUEST OBJECT]');
	str.push('--- REQUEST BEGIN ---');
	str.push(this._method + ' ' + url.format(this._url) + ' HTTP/' + this._httpVersion);
	for(var key in this._headers)
		str.push(key + ': ' + this._headers[key]);
	str.push('');
	if(this._body)
		str.push(JSON.stringify(this._body));
	str.push('---- REQUEST END ----');
	return str.join('\n');
};

function parseCookie(cookie_str) {
	if(!cookie_str) return {};

	var cookie = {},
		str = [],
		key = undefined;

	for(var pos=0; pos < cookie_str.length; pos++) {
		switch(cookie_str.charAt(pos)) {
		case ';':
			if(key) {
				cookie[key] = str.join('').trim();
				str = [];
				key = undefined;
			}
			break;
		case '=':
			if(!key) {
				key = str.join('').trim();
				str = [];
				break;
			}
		default:
			str.push(cookie_str.charAt(pos));
			break;
		}
	}

	cookie[key] = str.join('').trim();

	return cookie;
}

function getCharset (str) {
	if(!str) return 'utf8';
	var charset = str.split(';');
	if(charset.length == 2) charset = charset[1];
	else return 'utf8';

	charset = charset.split('=');
	if(!charset || charset.length !== 2) return '';

	switch(charset[1].toLowerCase()) {
	case 'utf-8': return 'utf8';
	default: return null;
	}
}

exports.HttpRequest = HttpRequest;<|endoftext|>


<commit_before>CATARSE.ReviewForm = Backbone.View.extend({
  el: '#review_form',

  accepted_terms: function(){
    return $('#accept').is(':checked')
  },

  everything_ok: function(){
    var ok = function(id){
      var value = $(id).val()
      if(value && value.length > 0){
        $(id).addClass("ok").removeClass("error")
        return true
      } else {
        $(id).addClass("error").removeClass("ok")
        return false
      }
    };

    var cpf_ok = function(){
      if($('#user_cpf').isValidCPF()){
        $('#user_cpf').addClass("ok").removeClass("error")
        return true
      } else {
        $('#user_cpf').addClass("error").removeClass("ok")
        return false
      }
    };

    var email_ok = function(){
      var value = $('#user_email').val()
      var re = /^[a-z0-9\._-]+@([a-z0-9][a-z0-9-_]*[a-z0-9-_]\.)+([a-z-_]+\.)?([a-z-_]+)$/
      if(value.match(re)){
        $('#user_email').addClass("ok").removeClass("error")
        return true
      } else {
        $('#user_email').addClass("error").removeClass("ok")
        return false
      }
    };

    var phone_number_ok = function(){
      var value = $('#user_phone_number').val()
      var re = /^\([0-9]{2}\)[0-9]{4}-[0-9]{4}[9_ ]?$/
      if(value.match(re)){
        $('#user_phone_number').addClass("ok").removeClass("error")
        return true
      } else {
        $('#user_phone_number').addClass("error").removeClass("ok")
        return false
      }
    };

    var zip_code_ok = function(){
      if(zip_code_valid){
        $('#user_address_zip_code').addClass("ok").removeClass("error")
        return true
      } else if(/^[0-9]{5}-[0-9]{3}$/i.test($('#user_address_zip_code').val())) {
        if(!$('#user_address_zip_code').hasClass('loading'))
          $('#user_address_zip_code').removeClass("error").removeClass("ok")
        return true
      } else {
        if(!$('#user_address_zip_code').hasClass('loading'))
          $('#user_address_zip_code').addClass("error").removeClass("ok")
        return false
      }
    };

    var verify_zip_code = function(){
      zip_code_valid = false
      if(/^[0-9]{5}-[0-9]{3}$/i.test($('#user_address_zip_code').val())) {
        $('#user_address_zip_code').removeClass("ok").removeClass("error").addClass('loading')
        $.get('/projects/cep/?cep='+$('#user_address_zip_code').val(), function(r){
          $('#user_address_zip_code').removeClass("loading")
          if(r.ok==true){
            zip_code_valid = true
            if(r.street != $('#user_address_street').val()){
              $('#user_address_street').val(r.street).effect("highlight", {}, 1500)
              $('#user_address_number').val(null).effect("highlight", {}, 1500)
              $('#user_address_complement').val(null).effect("highlight", {}, 1500)
              $('#user_address_number').focus()
            }
            if(r.neighbourhood != $('#user_address_neighbourhood').val())
              $('#user_address_neighbourhood').val(r.neighbourhood).effect("highlight", {}, 1500)
            if(r.city != $('#user_address_city').val())
              $('#user_address_city').val(r.city).effect("highlight", {}, 1500)
            if(r.state != $('#user_address_state').val())
              $('#user_address_state').val(r.state).effect("highlight", {}, 1500)
          } else {
            zip_code_valid = false
          }
          everything_ok()
        })
      }
      everything_ok()
    };

    var all_ok = true
    if($('#backer_credits').val() == "false"){
      if(!ok('#user_full_name'))
        all_ok = false
      if(!email_ok())
        all_ok = false
      if(!phone_number_ok())
        all_ok = false
      if(!ok('#user_address_street'))
        all_ok = false
      if(!ok('#user_address_number'))
        all_ok = false
      if(!ok('#user_address_neighbourhood'))
        all_ok = false
      if(!ok('#user_address_city'))
        all_ok = false
    }

    if(!this.accepted_terms()){
      all_ok = false;
    }

    if(all_ok){
      this.updateCurrentBackerInfo();
      $('#user_submit').attr('disabled', false)
      if($('#back_with_credits').length < 1) {
        $('#payment.hide').show();
      }
    } else {
      $('#payment.hide').hide();
      if($('#back_with_credits').length < 1) {
        $('#user_submit').attr('disabled', true)
      }
    }
  },

  events:{
    'keyup input[type=text]' : 'everything_ok',
    'click #accept' : 'everything_ok',
    'change select' : 'everything_ok',
    'keyup #user_address_zip_code' : 'onZipCodeKeyUp',
  },

  onPaymentTabClick: function(e){
    $('.payments_type').hide();
    $('.tab_container #payment_menu a').removeClass('selected');
    e.preventDefault();
    var reference = $(e.currentTarget).attr('href');
    var remote_url = $(e.currentTarget).data('target');
    $(e.currentTarget).addClass('selected');
    $(reference).fadeIn(300);
    if($('div', reference).length <= 0) {
      $.get(remote_url, function(response){
        $(reference).empty().html(response);
      });
    }
  },

  onZipCodeKeyUp: function(){
    zip_code_valid = false;
    this.everything_ok()
  },

  initialize: function() {
    var zip_code_valid = null
    var _this = this;

    $('#user_cpf').mask("999.999.999-99")
    $('#user_address_zip_code').mask("99999-999")
    $('#user_phone_number').mask("(99)9999-9999?9")

    if(this.accepted_terms()){
      this.everything_ok();
    }

    var can_submit_to_moip = true;
  },

  updateCurrentBackerInfo: function() {
    var backer_id = $('input#backer_id').val();
    var project_id = $('input#project_id').val();
    var backer_data = {
      payer_name: $('#user_full_name').val(),
      payer_email: $('#user_email').val(),
      address_street: $('#user_address_street').val(),
      address_number: $('#user_address_number').val(),
      address_complement: $('#user_address_complement').val(),
      address_neighbourhood: $('#user_address_neighbourhood').val(),
      address_zip_code: $('#user_address_zip_code').val(),
      address_city: $('#user_address_city').val(),
      address_state: $('#user_address_state').val(),
      address_phone_number: $('#user_phone_number').val()
    }
    $.post('/projects/'+project_id+'/backers/'+backer_id+'/update_info', {
      backer: backer_data
    });
  }
});

CATARSE.BackersReviewView = Backbone.View.extend({
  events:{
    'click .tab_container #payment_menu a' : 'onPaymentTabClick'
  },

  onPaymentTabClick: function(e){
    $('.payments_type').hide();
    $('.tab_container #payment_menu a').removeClass('selected');
    e.preventDefault();
    var reference = $(e.currentTarget).attr('href');
    var remote_url = $(e.currentTarget).data('target');
    $(e.currentTarget).addClass('selected');
    $(reference).fadeIn(300);
    if($('div', reference).length <= 0) {
      $.get(remote_url, function(response){
        $(reference).empty().html(response);
      });
    }
  },

  initialize: function() {
    $('.payments_type').hide();
    $('.tab_container #payment_menu a').removeClass('selected');
    this.$('.tab_container #payment_menu a:first').trigger('click')
    this.reviewForm = new CATARSE.ReviewForm();
  }
})
<commit_msg>fixed phone number validation for backer review<commit_after>CATARSE.ReviewForm = Backbone.View.extend({
  el: '#review_form',

  accepted_terms: function(){
    return $('#accept').is(':checked')
  },

  everything_ok: function(){
    var ok = function(id){
      var value = $(id).val()
      if(value && value.length > 0){
        $(id).addClass("ok").removeClass("error")
        return true
      } else {
        $(id).addClass("error").removeClass("ok")
        return false
      }
    };

    var cpf_ok = function(){
      if($('#user_cpf').isValidCPF()){
        $('#user_cpf').addClass("ok").removeClass("error")
        return true
      } else {
        $('#user_cpf').addClass("error").removeClass("ok")
        return false
      }
    };

    var email_ok = function(){
      var value = $('#user_email').val()
      var re = /^[a-z0-9\._-]+@([a-z0-9][a-z0-9-_]*[a-z0-9-_]\.)+([a-z-_]+\.)?([a-z-_]+)$/
      if(value.match(re)){
        $('#user_email').addClass("ok").removeClass("error")
        return true
      } else {
        $('#user_email').addClass("error").removeClass("ok")
        return false
      }
    };

    var phone_number_ok = function(){
      var value = $('#user_phone_number').val()
      var re = /^\([0-9]{2}\)[0-9]{4}-[0-9]{4}[0-9_ ]?$/
      if(value.match(re)){
        $('#user_phone_number').addClass("ok").removeClass("error")
        return true
      } else {
        $('#user_phone_number').addClass("error").removeClass("ok")
        return false
      }
    };

    var zip_code_ok = function(){
      if(zip_code_valid){
        $('#user_address_zip_code').addClass("ok").removeClass("error")
        return true
      } else if(/^[0-9]{5}-[0-9]{3}$/i.test($('#user_address_zip_code').val())) {
        if(!$('#user_address_zip_code').hasClass('loading'))
          $('#user_address_zip_code').removeClass("error").removeClass("ok")
        return true
      } else {
        if(!$('#user_address_zip_code').hasClass('loading'))
          $('#user_address_zip_code').addClass("error").removeClass("ok")
        return false
      }
    };

    var verify_zip_code = function(){
      zip_code_valid = false
      if(/^[0-9]{5}-[0-9]{3}$/i.test($('#user_address_zip_code').val())) {
        $('#user_address_zip_code').removeClass("ok").removeClass("error").addClass('loading')
        $.get('/projects/cep/?cep='+$('#user_address_zip_code').val(), function(r){
          $('#user_address_zip_code').removeClass("loading")
          if(r.ok==true){
            zip_code_valid = true
            if(r.street != $('#user_address_street').val()){
              $('#user_address_street').val(r.street).effect("highlight", {}, 1500)
              $('#user_address_number').val(null).effect("highlight", {}, 1500)
              $('#user_address_complement').val(null).effect("highlight", {}, 1500)
              $('#user_address_number').focus()
            }
            if(r.neighbourhood != $('#user_address_neighbourhood').val())
              $('#user_address_neighbourhood').val(r.neighbourhood).effect("highlight", {}, 1500)
            if(r.city != $('#user_address_city').val())
              $('#user_address_city').val(r.city).effect("highlight", {}, 1500)
            if(r.state != $('#user_address_state').val())
              $('#user_address_state').val(r.state).effect("highlight", {}, 1500)
          } else {
            zip_code_valid = false
          }
          everything_ok()
        })
      }
      everything_ok()
    };

    var all_ok = true
    if($('#backer_credits').val() == "false"){
      if(!ok('#user_full_name'))
        all_ok = false
      if(!email_ok())
        all_ok = false
      if(!phone_number_ok())
        all_ok = false
      if(!ok('#user_address_street'))
        all_ok = false
      if(!ok('#user_address_number'))
        all_ok = false
      if(!ok('#user_address_neighbourhood'))
        all_ok = false
      if(!ok('#user_address_city'))
        all_ok = false
    }

    if(!this.accepted_terms()){
      all_ok = false;
    }

    if(all_ok){
      this.updateCurrentBackerInfo();
      $('#user_submit').attr('disabled', false)
      if($('#back_with_credits').length < 1) {
        $('#payment.hide').show();
      }
    } else {
      $('#payment.hide').hide();
      if($('#back_with_credits').length < 1) {
        $('#user_submit').attr('disabled', true)
      }
    }
  },

  events:{
    'keyup input[type=text]' : 'everything_ok',
    'click #accept' : 'everything_ok',
    'change select' : 'everything_ok',
    'keyup #user_address_zip_code' : 'onZipCodeKeyUp',
  },

  onPaymentTabClick: function(e){
    $('.payments_type').hide();
    $('.tab_container #payment_menu a').removeClass('selected');
    e.preventDefault();
    var reference = $(e.currentTarget).attr('href');
    var remote_url = $(e.currentTarget).data('target');
    $(e.currentTarget).addClass('selected');
    $(reference).fadeIn(300);
    if($('div', reference).length <= 0) {
      $.get(remote_url, function(response){
        $(reference).empty().html(response);
      });
    }
  },

  onZipCodeKeyUp: function(){
    zip_code_valid = false;
    this.everything_ok()
  },

  initialize: function() {
    var zip_code_valid = null
    var _this = this;

    $('#user_cpf').mask("999.999.999-99")
    $('#user_address_zip_code').mask("99999-999")
    $('#user_phone_number').mask("(99)9999-9999?9")

    if(this.accepted_terms()){
      this.everything_ok();
    }

    var can_submit_to_moip = true;
  },

  updateCurrentBackerInfo: function() {
    var backer_id = $('input#backer_id').val();
    var project_id = $('input#project_id').val();
    var backer_data = {
      payer_name: $('#user_full_name').val(),
      payer_email: $('#user_email').val(),
      address_street: $('#user_address_street').val(),
      address_number: $('#user_address_number').val(),
      address_complement: $('#user_address_complement').val(),
      address_neighbourhood: $('#user_address_neighbourhood').val(),
      address_zip_code: $('#user_address_zip_code').val(),
      address_city: $('#user_address_city').val(),
      address_state: $('#user_address_state').val(),
      address_phone_number: $('#user_phone_number').val()
    }
    $.post('/projects/'+project_id+'/backers/'+backer_id+'/update_info', {
      backer: backer_data
    });
  }
});

CATARSE.BackersReviewView = Backbone.View.extend({
  events:{
    'click .tab_container #payment_menu a' : 'onPaymentTabClick'
  },

  onPaymentTabClick: function(e){
    $('.payments_type').hide();
    $('.tab_container #payment_menu a').removeClass('selected');
    e.preventDefault();
    var reference = $(e.currentTarget).attr('href');
    var remote_url = $(e.currentTarget).data('target');
    $(e.currentTarget).addClass('selected');
    $(reference).fadeIn(300);
    if($('div', reference).length <= 0) {
      $.get(remote_url, function(response){
        $(reference).empty().html(response);
      });
    }
  },

  initialize: function() {
    $('.payments_type').hide();
    $('.tab_container #payment_menu a').removeClass('selected');
    this.$('.tab_container #payment_menu a:first').trigger('click')
    this.reviewForm = new CATARSE.ReviewForm();
  }
})
<|endoftext|>


<commit_before>(function(global) {
    "use strict";

    var str = "ぶっちゃー";
    var fontSize = 18;
    var fontName ="arial";

    var width = 1200;
    var height = 700;

    var cubes = [];
    var table;

    var scene,renderer,camera,controls;

    initRender();

    // regenerate
    $("#generate").click(function(){
        $("canvas").remove();

        var inputStr = $("#str").val();
        if (inputStr !== "") {
            str = inputStr;
        }

//        var inputFontSize = $("#fontSize").val();
//        if (inputFontSize !== "") {
//            fontSize = inputFontSize;
//        }

        initRender();
    });

    function generateLogo() {
        createCubes(scene,cubes);
        setLight(scene);
        getAsciiBlocks(str,fontSize,fontName)
        render();
    }

    function initRender() {
        // scene
        scene = new THREE.Scene()

        // rendering
        renderer = new THREE.WebGLRenderer();
        renderer.setSize(width, height);
        renderer.setClearColor("#000000", 1);
        renderer.shadowMapEnabled = true;
        document.getElementById('stage').appendChild(renderer.domElement);

        // camera
        camera = new THREE.PerspectiveCamera(100, width / height, 10, 10000);
        camera.position.set(50,-50,500);

        // control
        controls = new THREE.OrbitControls(camera, renderer.domElement);

        // render
        generateLogo(str,fontSize)
    }

    function createCubes(scene,cubes){
        var table = getAsciiBlocks(str,fontSize);

        table.reverse();
        table.forEach(function(row,rowIndex) {
            row.forEach(function(cell,colIndex) {
                if (cell === 1) {
                    var cube = createCube(colIndex,rowIndex,table,row)
                    cubes.push(cube);
                    scene.add(cube);
                }
            })
        })
    }

    function setLight(scene){
        // light
        var light = new THREE.DirectionalLight("#ffffff", 1);
        light.position.set(0,100,30);
        scene.add(light);
        var ambient = new THREE.AmbientLight("#222222", 1);
        scene.add(ambient);
    }

    function createCube(colIndex,rowIndex,table,row) {
        var cubeSize = 12;
        var geometry = new THREE.BoxGeometry(cubeSize,cubeSize,cubeSize);
        var material = new THREE.MeshLambertMaterial({color: "#ffffff"});
        var cube;
        cube = new THREE.Mesh(geometry, material);
        cube.castShadow = true;
        cube.position.set(calcPosition(row,colIndex),calcPosition(table,rowIndex),0)

        return cube;
    }

    function calcPosition(array,index) {
        return index * 15 - (array.length / 2 * 15);
    }

    function render() {
        requestAnimationFrame(render);

        cubes.forEach(function(c){
            c.rotation.x += 0.01; // 追加
            c.rotation.y += 0.01; // 追加
            c.rotation.z += 0.01; // 追加

        });
        renderer.render(scene, camera);
        controls.update();
    }

    function getAsciiBlocks(str,fontSize,fontName) {
        // init
        var i, j;
        var canvas_tmp = $("<canvas>")[0];
        if(!canvas_tmp.getContext) return;
        var context_tmp = canvas_tmp.getContext('2d');
        var fontStyle = fontSize + "px " + fontName;
        var str_width, str_height;
        var table = [];

        // measure text
        context_tmp.font = fontStyle;
        canvas_tmp.width = str_width = context_tmp.measureText(str).width;
        canvas_tmp.height = str_height = Math.ceil(fontSize * 1.5);

        // render text
        context_tmp.font = fontStyle;
        context_tmp.textBaseline = "top";
        context_tmp.fillText(str, 0, 0);

        // get image data
        var imgdata = context_tmp.getImageData(0, 0, str_width, str_height);
        var exist = false;
        var cnt = 0;
        for(i = 0; i < str_height; i++){
            for(j = 0; j < str_width; j++){
                var alpha = imgdata.data[(str_width * i + j) * 4 + 3];
                if(alpha >= 128){
                    if(!exist) exist = true;
                    if(!table[i + cnt]) table[i + cnt] = [];
                    table[i + cnt][j] = 1;
                }
            }
            if(table[i + cnt]){
                for(j = 0; j < str_width; j++){
                    if(!table[i + cnt][j]) table[i + cnt][j] = 0;
                }
            }
            if(!exist) cnt--;
        }

        return table;
    }

})((this || 0).self || global);
<commit_msg>enabled to render single byte character, and refactored.<commit_after>(function(global) {
    "use strict";

    var str = "Rockじゃん";
    var fontSize = 18;
    var fontName ="'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', 'メイリオ', Meiryo, Osaka, 'ＭＳ Ｐゴシック', 'MS PGothic'";

    var width = 1400;
    var height = 700;

    var cubes = [];
    var table;

    var scene,renderer,camera,controls;

    initRender();

    // regenerate
    $("#generate").click(function(){
        $("canvas").remove();

        var inputStr = $("#str").val();
        if (inputStr !== "") {
            str = inputStr;
        }

//        var inputFontSize = $("#fontSize").val();
//        if (inputFontSize !== "") {
//            fontSize = inputFontSize;
//        }

        initRender();
    });

    function generateLogo() {
        createCubes(scene,cubes);
        render();
    }

    function initRender() {
        // scene
        scene = new THREE.Scene()

        // rendering
        renderer = new THREE.WebGLRenderer();
        renderer.setSize(width, height);
        renderer.setClearColor("#000000", 1);
        renderer.shadowMapEnabled = true;
        document.getElementById('stage').appendChild(renderer.domElement);

        // camera
        camera = new THREE.PerspectiveCamera(100, width / height, 10, 10000);
        camera.position.set(50,-50,500);

        // light
        setLight(scene);

        // control
        controls = new THREE.OrbitControls(camera, renderer.domElement);

        // render
        generateLogo(str,fontSize)
    }

    function createCubes(scene,cubes){
        var table = getAsciiBlocks(str,fontSize);

        console.log(table);

        table.reverse();
        table.forEach(function(row,rowIndex) {
            row.forEach(function(cell,colIndex) {
                if (cell === 1) {
                    var cube = createCube(colIndex,rowIndex,table,row)
                    cubes.push(cube);
                    scene.add(cube);
                }
            })
        })
    }

    function setLight(scene){
        // light
        var light = new THREE.DirectionalLight("#ffffff", 1);
        light.position.set(0,100,30);
        scene.add(light);
        var ambient = new THREE.AmbientLight("#222222", 1);
        scene.add(ambient);
    }

    function createCube(colIndex,rowIndex,table,row) {
        var cubeSize = 12;
        var geometry = new THREE.BoxGeometry(cubeSize,cubeSize,cubeSize);
        var material = new THREE.MeshLambertMaterial({color: "#ffffff"});
        var cube;
        cube = new THREE.Mesh(geometry, material);
        cube.castShadow = true;
        cube.position.set(calcPosition(row,colIndex),calcPosition(table,rowIndex),0)

        return cube;
    }

    function calcPosition(array,index) {
        return index * 15 - (array.length / 2 * 15);
    }

    function render() {
        requestAnimationFrame(render);

        cubes.forEach(function(c){
            c.rotation.x += 0.01;
            c.rotation.y += 0.01;
            c.rotation.z += 0.01;

        });
        renderer.render(scene, camera);
        controls.update();
    }

    function getAsciiBlocks(str,fontSize,fontName) {
        // init
        var i, j;
        var canvasTmp = $("<canvas>")[0];
        if(!canvasTmp.getContext) return;
        var contextTmp = canvasTmp.getContext('2d');
        var fontStyle = fontSize + "px " + fontName;
        var strWidth, strHeight;
        var table = [];

        console.log(contextTmp.measureText(str));

        // measure text
        contextTmp.font  = fontStyle;
        canvasTmp.width  = strWidth  = Math.ceil(contextTmp.measureText(str).width);
        canvasTmp.height = strHeight = Math.ceil(fontSize * 1.5);

        // render text
        contextTmp.font = fontStyle;
        contextTmp.textBaseline = "top";
        contextTmp.fillText(str, 0, 0);

        // get image data
        var imgdata = contextTmp.getImageData(0, 0, strWidth, strHeight);
        var exist = false;
        var cnt = 0;
        for(i = 0; i < strHeight; i++){
            for(j = 0; j < strWidth; j++){
                var alpha = imgdata.data[(strWidth * i + j) * 4 + 3];
                if(alpha >= 128){
                    if(!exist) exist = true;
                    if(!table[i + cnt]) table[i + cnt] = [];
                    table[i + cnt][j] = 1;
                }
            }
            if(table[i + cnt]){
                for(j = 0; j < strWidth; j++){
                    if(!table[i + cnt][j]) table[i + cnt][j] = 0;
                }
            }
            if(!exist) cnt--;
        }

        return table;
    }

})((this || 0).self || global);
<|endoftext|>