<commit_before>// Backbone.Validation v0.1.3
//
// Copyright (C)2011 Thomas Pedersen
// Distributed under MIT License
//
// Documentation and full license availabe at:
// http://github.com/thedersen/backbone.validation
// ----------------------------
// Backbone.Validation
// ----------------------------
Backbone.Validation = (function(Backbone, _) {
    var getValidators = function(model, attr) {
        var validation = model.validation[attr],
            validators = [];

        if (_.isFunction(validation)) {
            return validation;
        } else if(_.isString(validation)) {
            return model[validation];
        } else {
            for (var validator in validation) {
                if (validator !== 'msg' && validation.hasOwnProperty(validator)) {
                    validators.push({
                        fn: Backbone.Validation.validators[validator],
                        val: validation[validator],
                        msg: validation.msg
                    });
                }
            }
            return validators;
        }
    };

    var validateAttr = function(model, attr, value) {
        var validators = getValidators(model, attr),
            error = '',
            validator,
            result;

        if (_.isFunction(validators)) {
            return validators.call(model, value);
        } else {
            for (var i = 0; i < validators.length; i++) {
                validator = validators[i];
                result = validator.fn(value, attr, validator.val);
                if (result) {
                    error += validator.msg || result;
                }
            };
            return error;
        }
    };

    return {
        version: '0.1.3',

        bind: function(view, options) {
            options = options || {};
            var model = view.model,
                validFn = options.valid || Backbone.Validation.callbacks.valid,
                invalidFn = options.invalid || Backbone.Validation.callbacks.invalid;

            model.validate = function(attrs) {
                var invalidAttr = false,
                    isValid = true,
                    error;

                for (var changedAttr in attrs) {
                    if (changedAttr === 'isValid') {
                        return false;
                    }

                    error = validateAttr(model, changedAttr, attrs[changedAttr]);
                    if (error) {
                        invalidAttr = true;
                        invalidFn(view, changedAttr, error);
                    } else {
                        validFn(view, changedAttr);
                    }
                }

                if (invalidAttr) {
                    model.set({
                        isValid: false
                    });
                } else {
                    for (var validatedAttr in model.validation) {
                        if (_.isUndefined(attrs[validatedAttr]) && validateAttr(model, validatedAttr, model.get(validatedAttr))) {
                            isValid = false;
                            break;
                        }
                    }
                    model.set({
                        isValid: isValid
                    });
                }

                return invalidAttr;
            };
        },

        unbind: function(view) {
            view.model.validate = undefined;
        }
    };
} (Backbone, _));

Backbone.Validation.callbacks = {
    valid: function(view, attr) {
        view.$('#' + attr).removeClass('invalid');
        view.$('#' + attr).removeAttr('data-error');
    },

    invalid: function(view, attr, error) {
        view.$('#' + attr).addClass('invalid');
        view.$('#' + attr).attr('data-error', error);
    }
};

Backbone.Validation.patterns = {
    number: /^-?\d+$/,
    email: /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/,
    url: /^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i
};

Backbone.Validation.validators = (function(patterns, _, $) {
    var numberPattern = patterns.number;
    var isNumber = function(value){
        return _.isNumber(value) || (_.isString(value) && value.match(numberPattern));
    };

    return {
        required: function(value, attr) {
            var isEmptyString = _.isString(value) && $.trim(value) === '';
            var isFalseBoolean = _.isBoolean(value) && value === false;

            if (_.isNull(value) || _.isUndefined(value) || isEmptyString || isFalseBoolean) {
                return attr + ' is required';
            }
        },
        min: function(value, attr, minValue) {
            if (!isNumber(value) || value < minValue) {
                return attr + ' must be larger than or equal to ' + minValue;
            }
        },
        max: function(value, attr, maxValue) {
            if (!isNumber(value) || value > maxValue) {
                return attr + ' must be less than or equal to ' + maxValue;
            }
        },
        length: function(value, attr, length) {
          value = $.trim(value);
            if (_.isString(value) && value.length !== length) {
                return attr + ' must have exact ' + length + ' characters';
            }
        },
        minLength: function(value, attr, minLength) {
            value = $.trim(value);
            if (_.isString(value) && value.length < minLength) {
                return attr + ' must be longer than or equal to ' + minLength + ' characters';
            }
        },
        maxLength: function(value, attr, maxLength) {
            value = $.trim(value);
            if (_.isString(value) && value.length > maxLength) {
                return attr + ' must be shorter than or equal to' + maxLength + ' characters';
            }
        },
        pattern: function(value, attr, pattern) {
            pattern = patterns[pattern] || pattern;
            if (_.isString(value) && !value.match(pattern)) {
                return attr + ' is not a valid ' + pattern;
            }
        }
    };
} (Backbone.Validation.patterns, _, jQuery));
<commit_msg>Removed dependency to jQuery in the Backbone.Validation.validators function<commit_after>// Backbone.Validation v0.1.3
//
// Copyright (C)2011 Thomas Pedersen
// Distributed under MIT License
//
// Documentation and full license availabe at:
// http://github.com/thedersen/backbone.validation
// ----------------------------
// Backbone.Validation
// ----------------------------
Backbone.Validation = (function(Backbone, _) {
    var getValidators = function(model, attr) {
        var validation = model.validation[attr],
            validators = [];

        if (_.isFunction(validation)) {
            return validation;
        } else if(_.isString(validation)) {
            return model[validation];
        } else {
            for (var validator in validation) {
                if (validator !== 'msg' && validation.hasOwnProperty(validator)) {
                    validators.push({
                        fn: Backbone.Validation.validators[validator],
                        val: validation[validator],
                        msg: validation.msg
                    });
                }
            }
            return validators;
        }
    };

    var validateAttr = function(model, attr, value) {
        var validators = getValidators(model, attr),
            error = '',
            validator,
            result;

        if (_.isFunction(validators)) {
            return validators.call(model, value);
        } else {
            for (var i = 0; i < validators.length; i++) {
                validator = validators[i];
                result = validator.fn(value, attr, validator.val);
                if (result) {
                    error += validator.msg || result;
                }
            };
            return error;
        }
    };

    return {
        version: '0.1.3',

        bind: function(view, options) {
            options = options || {};
            var model = view.model,
                validFn = options.valid || Backbone.Validation.callbacks.valid,
                invalidFn = options.invalid || Backbone.Validation.callbacks.invalid;

            model.validate = function(attrs) {
                var invalidAttr = false,
                    isValid = true,
                    error;

                for (var changedAttr in attrs) {
                    if (changedAttr === 'isValid') {
                        return false;
                    }

                    error = validateAttr(model, changedAttr, attrs[changedAttr]);
                    if (error) {
                        invalidAttr = true;
                        invalidFn(view, changedAttr, error);
                    } else {
                        validFn(view, changedAttr);
                    }
                }

                if (invalidAttr) {
                    model.set({
                        isValid: false
                    });
                } else {
                    for (var validatedAttr in model.validation) {
                        if (_.isUndefined(attrs[validatedAttr]) && validateAttr(model, validatedAttr, model.get(validatedAttr))) {
                            isValid = false;
                            break;
                        }
                    }
                    model.set({
                        isValid: isValid
                    });
                }

                return invalidAttr;
            };
        },

        unbind: function(view) {
            view.model.validate = undefined;
        }
    };
} (Backbone, _));

Backbone.Validation.callbacks = {
    valid: function(view, attr) {
        view.$('#' + attr).removeClass('invalid');
        view.$('#' + attr).removeAttr('data-error');
    },

    invalid: function(view, attr, error) {
        view.$('#' + attr).addClass('invalid');
        view.$('#' + attr).attr('data-error', error);
    }
};

Backbone.Validation.patterns = {
    number: /^-?\d+$/,
    email: /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/,
    url: /^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i
};

Backbone.Validation.validators = (function(patterns, _) {
    var numberPattern = patterns.number;
    var isNumber = function(value){
        return _.isNumber(value) || (_.isString(value) && value.match(numberPattern));
    };

    var trim = String.prototype.trim ?
    		function(text) {
    			return text == null ?
    				"" :
    				String.prototype.trim.call(text);
    		} :
    		function(text) {
    		    var trimLeft = /^\s+/,
                    trimRight = /\s+$/;

    			return text == null ?
    				"" :
    				text.toString().replace(trimLeft, "").replace(trimRight, "");
    		};

    return {
        required: function(value, attr) {
            var isEmptyString = _.isString(value) && trim(value) === '';
            var isFalseBoolean = _.isBoolean(value) && value === false;

            if (_.isNull(value) || _.isUndefined(value) || isEmptyString || isFalseBoolean) {
                return attr + ' is required';
            }
        },
        min: function(value, attr, minValue) {
            if (!isNumber(value) || value < minValue) {
                return attr + ' must be larger than or equal to ' + minValue;
            }
        },
        max: function(value, attr, maxValue) {
            if (!isNumber(value) || value > maxValue) {
                return attr + ' must be less than or equal to ' + maxValue;
            }
        },
        length: function(value, attr, length) {
          value = trim(value);
            if (_.isString(value) && value.length !== length) {
                return attr + ' must have exact ' + length + ' characters';
            }
        },
        minLength: function(value, attr, minLength) {
            value = trim(value);
            if (_.isString(value) && value.length < minLength) {
                return attr + ' must be longer than or equal to ' + minLength + ' characters';
            }
        },
        maxLength: function(value, attr, maxLength) {
            value = trim(value);
            if (_.isString(value) && value.length > maxLength) {
                return attr + ' must be shorter than or equal to' + maxLength + ' characters';
            }
        },
        pattern: function(value, attr, pattern) {
            pattern = patterns[pattern] || pattern;
            if (_.isString(value) && !value.match(pattern)) {
                return attr + ' is not a valid ' + pattern;
            }
        }
    };
} (Backbone.Validation.patterns, _));
<|endoftext|>


<commit_before>var Fraction = require('../src/fractions');
var Variable = require('../src/variables');

describe("A variable", function() {
    var x = new Variable("x");

    it("is initalized with a variable name", function() {
        expect(x.variable).toEqual("x");
    });

    it("is initialized with a degree of 1", function() {
        expect(x.degree).toEqual(1);
    });

    it("should throw an error if initialized with an integer", function() {
        expect(function(){new Variable(5)}).toThrow("InvalidArgument");
    });

    it("should throw an error if initialized with a float", function() {
        expect(function(){new Variable(5.1)}).toThrow("InvalidArgument");
    });
});

describe("Variable printing to string", function() {
    var x = new Variable("x");

    it("should print just the variable when the degree is 1", function() {
        expect(x.print()).toEqual("x");
    });

    it("should print the degree if it's greater than 1", function() {
        x.degree = 2;
        expect(x.print()).toEqual("x^2");
    });

    it("should print an empty string if the degree is 0", function() {
        x.degree = 0;
        expect(x.print()).toEqual("");
    })
});<commit_msg>Add tests for printing Variables to tex<commit_after>var Fraction = require('../src/fractions');
var Variable = require('../src/variables');

describe("A variable", function() {
    var x = new Variable("x");

    it("is initalized with a variable name", function() {
        expect(x.variable).toEqual("x");
    });

    it("is initialized with a degree of 1", function() {
        expect(x.degree).toEqual(1);
    });

    it("should throw an error if initialized with an integer", function() {
        expect(function(){new Variable(5)}).toThrow("InvalidArgument");
    });

    it("should throw an error if initialized with a float", function() {
        expect(function(){new Variable(5.1)}).toThrow("InvalidArgument");
    });
});

describe("Variable printing to string", function() {
    var x = new Variable("x");

    it("should print just the variable when the degree is 1", function() {
        expect(x.print()).toEqual("x");
    });

    it("should print the degree if it's greater than 1", function() {
        x.degree = 2;
        expect(x.print()).toEqual("x^2");
    });

    it("should print an empty string if the degree is 0", function() {
        x.degree = 0;
        expect(x.print()).toEqual("");
    });
});

describe("Variable printing to tex", function() {
    var x = new Variable("x");

    it("should print just the variable when the degree is 1", function() {
        expect(x.tex()).toEqual("x");
    });

    it("should print the degree if it's greater than 1", function() {
        x.degree = 2;
        expect(x.tex()).toEqual("x^{2}");
    });

    it("should print an empty string if the degree is 0", function() {
        x.degree = 0;
        expect(x.tex()).toEqual("");
    });
});<|endoftext|>


<commit_before>/**
 * Created by fuj01 on 2016/6/21.
 */
$(document).ready(function() {
    //展示图例
    showLegend();
    $('#requirementCalendar').fullCalendar({
        lang:'zh-cn',//引入语言包
        header: {
            left: 'prev,next today',
            center: 'title',
            right: ''
        },
        editable: true,
        dragOpacity: {
            agenda: .5,
            '':.6
        },
        selectable: true,
        selectHelper: true,
        //events: 'index.php?r=site/calendar-list',
        events:function (start,end,timezone,callback) {
            var abuName = "";
            $("#select2 dd").each(function () {
                if($(this).hasClass("selected")){
                    abuName = $(this).text();
                    return false;
                }
            });
            $.ajax({
                url:'index.php?r=site/requirement-calendar-list&abuname=' + abuName,
                success:function (data) {
                    var events = [];
                    events = JSON.parse(data);
                    callback(events);
                }
            });
        },
        select: function(start, end) {
            var formatStart = start.format();
            var formatEnd = end.format();
            showProjModal(formatStart,formatEnd);
            //$('#calendar').fullCalendar('unselect');
        },
        eventClick:function (calEvent,jsEvent,view) {
            editProjPlan(calEvent.id);
        }
    });

    $('#resourceCalendar').fullCalendar({
        lang:'zh-cn',//引入语言包
        header: {
            left: 'prev,next today',
            center: 'title',
            right: ''
        },
        editable: true,
        dragOpacity: {
            agenda: .5,
            '':.6
        },
        selectable: true,
        selectHelper: true,
        eventOrder:'userid',
        events: function (start,end,timezone,callback) {
            var abuName = "";
            $("#select2 dd").each(function () {
                if($(this).hasClass("selected")){
                    abuName = $(this).text();
                    return false;
                }
            });
            $.ajax({
                url:'index.php?r=site/task-calendar-list&abuname=' + abuName,
                success:function (data) {
                    var events = [];
                    events = JSON.parse(data);
                    callback(events);
                }
            });
        },
        select: function(start, end) {
            var formatStart = start.format();
            var formatEnd = end.format();
            addTaskModal(formatStart,formatEnd);
        },
        eventClick:function (calEvent,jsEvent,view) {
            editTaskModal(calEvent.id);
        }
    });

    //由于日历无法在隐藏的div中加载，所以在显示的时候加载一次
    var resourceCalendarIsloaded = false;
    $("#navResource").on('shown.bs.tab',function(e) {
        if(!resourceCalendarIsloaded){
            //console.log("加载了111");
            $("#resourceCalendar").fullCalendar('render');
            resourceCalendarIsloaded = true;
        }else {
            $('#resourceCalendar').fullCalendar('refetchEvents');
        }
    });

    $("#navRequirement").on('shown.bs.tab',function(e) {
        $('#requirementCalendar').fullCalendar('refetchEvents');
    });
});

function showLegend() {
    var abuName = "";
    $("#select2 dd").each(function () {
        if($(this).hasClass("selected")){
            abuName = $(this).text();
            return false;
        }
    });
    $.ajax({
        url:'index.php?r=site/user-list&abuname=' + abuName,
        success:function (data) {
            var events = [];
            events = JSON.parse(data);
            console.log(events);
            //加载图例
            var legendHTML = "";
            $("#resourceLegend").empty();
            for(var i = 0;i<events.length;i++) {
                legendHTML += "" + events[i].usernameChn + "";
            }
            $("#resourceLegend").append(legendHTML);
        }
    });
}<commit_msg>解决fullcalendar的结束时间多一天的问题<commit_after>/**
 * Created by fuj01 on 2016/6/21.
 */
$(document).ready(function() {
    //展示图例
    showLegend();
    $('#requirementCalendar').fullCalendar({
        lang:'zh-cn',//引入语言包
        header: {
            left: 'prev,next today',
            center: 'title',
            right: ''
        },
        editable: true,
        dragOpacity: {
            agenda: .5,
            '':.6
        },
        selectable: true,
        selectHelper: true,
        //events: 'index.php?r=site/calendar-list',
        events:function (start,end,timezone,callback) {
            var abuName = "";
            $("#select2 dd").each(function () {
                if($(this).hasClass("selected")){
                    abuName = $(this).text();
                    return false;
                }
            });
            $.ajax({
                url:'index.php?r=site/requirement-calendar-list&abuname=' + abuName,
                success:function (data) {
                    var events = [];
                    events = JSON.parse(data);
                    callback(events);
                }
            });
        },
        select: function(start, end) {
            var formatStart = start.format();
            var formatEnd = end.format();
            var preEnd = calDate(formatEnd);
            showProjModal(formatStart,preEnd);
            //$('#calendar').fullCalendar('unselect');
        },
        eventClick:function (calEvent,jsEvent,view) {
            editProjPlan(calEvent.id);
        }
    });

    $('#resourceCalendar').fullCalendar({
        lang:'zh-cn',//引入语言包
        header: {
            left: 'prev,next today',
            center: 'title',
            right: ''
        },
        editable: true,
        dragOpacity: {
            agenda: .5,
            '':.6
        },
        selectable: true,
        selectHelper: true,
        eventOrder:'userid',
        events: function (start,end,timezone,callback) {
            var abuName = "";
            $("#select2 dd").each(function () {
                if($(this).hasClass("selected")){
                    abuName = $(this).text();
                    return false;
                }
            });
            $.ajax({
                url:'index.php?r=site/task-calendar-list&abuname=' + abuName,
                success:function (data) {
                    var events = [];
                    events = JSON.parse(data);
                    callback(events);
                }
            });
        },
        select: function(start, end) {
            var formatStart = start.format();
            var formatEnd = end.format();
            var preEnd = calDate(formatEnd);
            addTaskModal(formatStart,preEnd);
        },
        eventClick:function (calEvent,jsEvent,view) {
            editTaskModal(calEvent.id);
        }
    });

    //由于日历无法在隐藏的div中加载，所以在显示的时候加载一次
    var resourceCalendarIsloaded = false;
    $("#navResource").on('shown.bs.tab',function(e) {
        if(!resourceCalendarIsloaded){
            //console.log("加载了111");
            $("#resourceCalendar").fullCalendar('render');
            resourceCalendarIsloaded = true;
        }else {
            $('#resourceCalendar').fullCalendar('refetchEvents');
        }
    });

    $("#navRequirement").on('shown.bs.tab',function(e) {
        $('#requirementCalendar').fullCalendar('refetchEvents');
    });
});

function showLegend() {
    var abuName = "";
    $("#select2 dd").each(function () {
        if($(this).hasClass("selected")){
            abuName = $(this).text();
            return false;
        }
    });
    $.ajax({
        url:'index.php?r=site/user-list&abuname=' + abuName,
        success:function (data) {
            var events = [];
            events = JSON.parse(data);
            console.log(events);
            //加载图例
            var legendHTML = "";
            $("#resourceLegend").empty();
            for(var i = 0;i<events.length;i++) {
                legendHTML += "" + events[i].usernameChn + "";
            }
            $("#resourceLegend").append(legendHTML);
        }
    });
}

//计算date的前一天
//传入的date参数格式必须为：XXXX-XX-XX
function calDate(date) {
    var arrDate = date.split("-");
    var newDate = new Date();
    newDate.setFullYear(arrDate[0]);
    newDate.setMonth(arrDate[1]);
    newDate.setDate(arrDate[2]);
    var preDate = new Date(newDate.getTime() - 24*60*60*1000);  //前一天
    return preDate.getFullYear() + "-" + (preDate.getMonth() < 10 ? "0"+preDate.getMonth():preDate.getMonth()) + "-" + (preDate.getDate() < 10 ? "0"+preDate.getDate():preDate.getDate());
}<|endoftext|>


<commit_before>/**
 * mSupply Mobile
 * Sustainable Solutions (NZ) Ltd. 2019
 */

import { BACKGROUND_COLOR, BLUE_WHITE, DARK_GREY, LIGHT_GREY } from './colors';
import { APP_FONT_FAMILY, APP_GENERAL_FONT_SIZE } from './fonts';

const newDataTableStyles = {
  cellContainer: {
    left: {
      borderRightWidth: 2,
      borderColor: '#ecf3fc',
      flex: 1,
      justifyContent: 'center',
      textAlign: 'left',
    },
    right: {
      borderRightWidth: 2,
      borderColor: '#ecf3fc',
      flex: 1,
      justifyContent: 'center',
      textAlign: 'right',
    },
    center: {
      borderRightWidth: 2,
      borderColor: '#ecf3fc',
      flex: 1,
      justifyContent: 'center',
      textAlign: 'center',
    },
  },
  cellText: {
    left: {
      marginLeft: 20,
      textAlign: 'left',
      fontFamily: APP_FONT_FAMILY,
      fontSize: APP_GENERAL_FONT_SIZE,
      color: DARK_GREY,
    },
    right: {
      marginRight: 20,
      textAlign: 'right',
      fontFamily: APP_FONT_FAMILY,
      fontSize: APP_GENERAL_FONT_SIZE,
      color: DARK_GREY,
    },
    center: {
      textAlign: 'center',
      fontFamily: APP_FONT_FAMILY,
      fontSize: APP_GENERAL_FONT_SIZE,
      color: DARK_GREY,
    },
  },
  editableCellUnfocused: {
    right: {
      textAlign: 'right',
      fontFamily: APP_FONT_FAMILY,
      fontSize: APP_GENERAL_FONT_SIZE,
      color: DARK_GREY,
    },
    center: {
      textAlign: 'center',
      fontFamily: APP_FONT_FAMILY,
      fontSize: APP_GENERAL_FONT_SIZE,
      color: DARK_GREY,
    },
    left: {
      textAlign: 'left',
      fontFamily: APP_FONT_FAMILY,
      fontSize: APP_GENERAL_FONT_SIZE,
      color: DARK_GREY,
    },
  },
  editableCellText: {
    textAlign: 'right',
    fontFamily: APP_FONT_FAMILY,
    fontSize: APP_GENERAL_FONT_SIZE,
    color: DARK_GREY,
    marginRight: 20,
  },
  editableCellTextView: {
    borderBottomColor: '#cbcbcb',
    borderBottomWidth: 1,
    flex: 1,
    flexDirection: 'row',
    width: '88%',
    maxHeight: '65%',
    justifyContent: 'center',
    alignItems: 'center',
    alignSelf: 'center',
    marginRight: 20,
  },
  touchableCellContainer: {
    borderRightWidth: 2,
    borderColor: '#ecf3fc',
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center',
  },
  row: {
    backgroundColor: BACKGROUND_COLOR,
    flex: 1,
    flexDirection: 'row',
    height: 45,
  },
  alternateRow: {
    backgroundColor: 'white',
    flex: 1,
    flexDirection: 'row',
    height: 45,
  },
  headerRow: {
    backgroundColor: 'white',
    flexDirection: 'row',
  },
  headerCells: {
    left: {
      height: 40,
      borderRightWidth: 2,
      borderBottomWidth: 2,
      backgroundColor: 'white',
      borderColor: BLUE_WHITE,
      flexDirection: 'row',
      alignItems: 'center',
      justifyContent: 'space-between',
    },
    right: {
      height: 40,
      borderRightWidth: 2,
      borderBottomWidth: 2,
      backgroundColor: 'white',
      borderColor: BLUE_WHITE,
      flexDirection: 'row',
      alignItems: 'center',
      justifyContent: 'flex-end',
    },
    center: {
      height: 40,
      borderRightWidth: 2,
      borderBottomWidth: 2,
      backgroundColor: 'white',
      borderColor: BLUE_WHITE,
      flexDirection: 'row',
      alignItems: 'center',
      justifyContent: 'center',
    },
  },
  expiryBatchTextView: {
    borderBottomColor: '#cbcbcb',
    borderBottomWidth: 1,
    flex: 1,
    flexDirection: 'row',
    width: '88%',
    maxHeight: '65%',
    justifyContent: 'center',
    alignItems: 'center',
    alignSelf: 'center',
  },
  expiryBatchView: {
    borderRightWidth: 2,
    borderColor: '#ecf3fc',
    flex: 1,
    justifyContent: 'center',
    textAlign: 'center',
  },
  expiryBatchText: {
    textAlign: 'center',
    fontFamily: APP_FONT_FAMILY,
    fontSize: APP_GENERAL_FONT_SIZE,
    color: DARK_GREY,
  },
  expiryBatchPlaceholderText: {
    textAlign: 'center',
    fontFamily: APP_FONT_FAMILY,
    fontSize: APP_GENERAL_FONT_SIZE,
    color: LIGHT_GREY,
  },
  dropDownCellTextContainer: { flex: 2, justfyContent: 'center', alignItems: 'center' },
  dropDownCellIconContainer: { flex: 1, justfyContent: 'center', alignItems: 'center' },
  dropDownFont: {
    marginLeft: 20,
    textAlign: 'left',
    fontFamily: APP_FONT_FAMILY,
    fontSize: APP_GENERAL_FONT_SIZE,
    color: DARK_GREY,
  },
  dropDownPlaceholderFont: {
    textAlign: 'center',
    fontFamily: APP_FONT_FAMILY,
    fontSize: APP_GENERAL_FONT_SIZE,
    color: LIGHT_GREY,
  },
};

export default newDataTableStyles;
<commit_msg>Add selectedRow style to newDataPageStyles<commit_after>/**
 * mSupply Mobile
 * Sustainable Solutions (NZ) Ltd. 2019
 */

import { BACKGROUND_COLOR, BLUE_WHITE, DARK_GREY, LIGHT_GREY } from './colors';
import { APP_FONT_FAMILY, APP_GENERAL_FONT_SIZE } from './fonts';

const newDataTableStyles = {
  cellContainer: {
    left: {
      borderRightWidth: 2,
      borderColor: '#ecf3fc',
      flex: 1,
      justifyContent: 'center',
      textAlign: 'left',
    },
    right: {
      borderRightWidth: 2,
      borderColor: '#ecf3fc',
      flex: 1,
      justifyContent: 'center',
      textAlign: 'right',
    },
    center: {
      borderRightWidth: 2,
      borderColor: '#ecf3fc',
      flex: 1,
      justifyContent: 'center',
      textAlign: 'center',
    },
  },
  cellText: {
    left: {
      marginLeft: 20,
      textAlign: 'left',
      fontFamily: APP_FONT_FAMILY,
      fontSize: APP_GENERAL_FONT_SIZE,
      color: DARK_GREY,
    },
    right: {
      marginRight: 20,
      textAlign: 'right',
      fontFamily: APP_FONT_FAMILY,
      fontSize: APP_GENERAL_FONT_SIZE,
      color: DARK_GREY,
    },
    center: {
      textAlign: 'center',
      fontFamily: APP_FONT_FAMILY,
      fontSize: APP_GENERAL_FONT_SIZE,
      color: DARK_GREY,
    },
  },
  editableCellUnfocused: {
    right: {
      textAlign: 'right',
      fontFamily: APP_FONT_FAMILY,
      fontSize: APP_GENERAL_FONT_SIZE,
      color: DARK_GREY,
    },
    center: {
      textAlign: 'center',
      fontFamily: APP_FONT_FAMILY,
      fontSize: APP_GENERAL_FONT_SIZE,
      color: DARK_GREY,
    },
    left: {
      textAlign: 'left',
      fontFamily: APP_FONT_FAMILY,
      fontSize: APP_GENERAL_FONT_SIZE,
      color: DARK_GREY,
    },
  },
  editableCellText: {
    textAlign: 'right',
    fontFamily: APP_FONT_FAMILY,
    fontSize: APP_GENERAL_FONT_SIZE,
    color: DARK_GREY,
    marginRight: 20,
  },
  editableCellTextView: {
    borderBottomColor: '#cbcbcb',
    borderBottomWidth: 1,
    flex: 1,
    flexDirection: 'row',
    width: '88%',
    maxHeight: '65%',
    justifyContent: 'center',
    alignItems: 'center',
    alignSelf: 'center',
    marginRight: 20,
  },
  touchableCellContainer: {
    borderRightWidth: 2,
    borderColor: '#ecf3fc',
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center',
  },
  row: {
    backgroundColor: BACKGROUND_COLOR,
    flex: 1,
    flexDirection: 'row',
    height: 45,
  },
  alternateRow: {
    backgroundColor: 'white',
    flex: 1,
    flexDirection: 'row',
    height: 45,
  },
  selectedRow: {
    backgroundColor: LIGHT_GREY,
    flex: 1,
    flexDirection: 'row',
    height: 45,
  },
  headerRow: {
    backgroundColor: 'white',
    flexDirection: 'row',
  },
  headerCells: {
    left: {
      height: 40,
      borderRightWidth: 2,
      borderBottomWidth: 2,
      backgroundColor: 'white',
      borderColor: BLUE_WHITE,
      flexDirection: 'row',
      alignItems: 'center',
      justifyContent: 'space-between',
    },
    right: {
      height: 40,
      borderRightWidth: 2,
      borderBottomWidth: 2,
      backgroundColor: 'white',
      borderColor: BLUE_WHITE,
      flexDirection: 'row',
      alignItems: 'center',
      justifyContent: 'flex-end',
    },
    center: {
      height: 40,
      borderRightWidth: 2,
      borderBottomWidth: 2,
      backgroundColor: 'white',
      borderColor: BLUE_WHITE,
      flexDirection: 'row',
      alignItems: 'center',
      justifyContent: 'center',
    },
  },
  expiryBatchTextView: {
    borderBottomColor: '#cbcbcb',
    borderBottomWidth: 1,
    flex: 1,
    flexDirection: 'row',
    width: '88%',
    maxHeight: '65%',
    justifyContent: 'center',
    alignItems: 'center',
    alignSelf: 'center',
  },
  expiryBatchView: {
    borderRightWidth: 2,
    borderColor: '#ecf3fc',
    flex: 1,
    justifyContent: 'center',
    textAlign: 'center',
  },
  expiryBatchText: {
    textAlign: 'center',
    fontFamily: APP_FONT_FAMILY,
    fontSize: APP_GENERAL_FONT_SIZE,
    color: DARK_GREY,
  },
  expiryBatchPlaceholderText: {
    textAlign: 'center',
    fontFamily: APP_FONT_FAMILY,
    fontSize: APP_GENERAL_FONT_SIZE,
    color: LIGHT_GREY,
  },
  dropDownCellTextContainer: { flex: 2, justfyContent: 'center', alignItems: 'center' },
  dropDownCellIconContainer: { flex: 1, justfyContent: 'center', alignItems: 'center' },
  dropDownFont: {
    marginLeft: 20,
    textAlign: 'left',
    fontFamily: APP_FONT_FAMILY,
    fontSize: APP_GENERAL_FONT_SIZE,
    color: DARK_GREY,
  },
  dropDownPlaceholderFont: {
    textAlign: 'center',
    fontFamily: APP_FONT_FAMILY,
    fontSize: APP_GENERAL_FONT_SIZE,
    color: LIGHT_GREY,
  },
};

export default newDataTableStyles;
<|endoftext|>


<commit_before>import RoiMap from '../RoiMap';
import PriorityQueue from 'js-priority-queue';
import {dxs, dys} from './../../../util/dxdy.js';

/**
 * This method allows to create a ROIMap using the water shed algorithm. By default this algorithm
 * will fill the holes and therefore the lowest value of the image (black zones).
 * If no points are given, the function will look for all the minimal points.
 * If no mask is given the algorithm will completely fill the image.
 * Please take care about the value that has be in the mask ! In order to be coherent with the expected mask,
 * meaning that if it is a dark zone, the mask will be dark the normal behaviour to fill a zone
 * is that the mask pixel is clear (value of 0) !
 * However if you work in the 'invert' mode, the mask value has to be 'set' and the method will look for
 * maxima.
 * @memberof RoiManager
 * @instance
 * @param {Object} [options={}]
 * @param {number[][]} [options.points[ - Array of points [[x1,y1], [x2,y2], ...].
 * @param {number} [options.fillMaxValue] - Limit of filling. By example, we can fill to a maximum value 32000 of a 16 bitDepth image.
 *          If invert this will corresponds to the minimal value
 * @param {Image} [options.image=this] - By default the waterShed will be applied on the current image. However waterShed can only be applied
 *                              on 1 component image. This allows to specify a grey scale image on which to apply waterShed..
 * @param {Image} [options.mask] - A binary image, the same size as the image. The algorithm will fill only if the current pixel in the binary mask is true.
 * @param {boolean} [options.invert = false] - By default we fill the minima
 * @returns {RoiMap}
 */

export default function fromWaterShed(options = {}) {
    let {
        points,
        mask,
        fillMaxValue = this.maxValue,
        invert = false
    } = options;
    let currentImage = image || this;
    currentImage.checkProcessable('fromWaterShed', {
        bitDepth: [8, 16],
        components: 1
    });

    /*
     We need to invert the logic because we are always using method to look for maxima and not minima and
     here water is expected to fill the minima first ...
    */

    invert = !invert;

    //WaterShed is done from points in the image. We can either specify those points in options,
    // or it is gonna take the minimum locals of the image by default.
    if (!points) {
        points = currentImage.getLocalMaxima({
            invert,
            mask
        });
    }

    let maskExpectedValue = (invert) ? 0 : 1;

    let data = new Int16Array(currentImage.size);
    let width = currentImage.width;
    let height = currentImage.height;
    let toProcess = new PriorityQueue({
        comparator: (a, b) => a[2] - b[2],
        strategy: PriorityQueue.BinaryHeapStrategy
    });
    for (let i = 0; i < points.length; i++) {
        let index = points[i][0] + points[i][1] * width;
        data[index] = i + 1;
        let intensity = currentImage.data[index];
        if (
            (invert && intensity <= fillMaxValue) ||
            (!invert && intensity >= fillMaxValue)
        ) {
            toProcess.queue([points[i][0], points[i][1], intensity]);
        }
    }

    //Then we iterate through each points
    while (toProcess.length > 0) {
        let currentPoint = toProcess.dequeue();
        let currentValueIndex = currentPoint[0] + currentPoint[1] * width;

        for (let dir = 0; dir < 4; dir++) {
            let newX = currentPoint[0] + dxs[dir];
            let newY = currentPoint[1] + dys[dir];
            if (newX >= 0 && newY >= 0 && newX < width && newY < height) {
                let currentNeighbourIndex = newX + newY * width;
                if (!mask || (mask.getBit(currentNeighbourIndex) === maskExpectedValue)) {
                    let intensity = currentImage.data[currentNeighbourIndex];
                    if (
                        (invert && intensity <= fillMaxValue) ||
                        (!invert && intensity >= fillMaxValue)
                    ) {
                        if (data[currentNeighbourIndex] === 0) {
                            data[currentNeighbourIndex] = data[currentValueIndex];
                            toProcess.queue([currentPoint[0] + dxs[dir], currentPoint[1] + dys[dir], intensity]);
                        }
                    }
                }
            }
        }
    }

    return new RoiMap(currentImage, data);
}
<commit_msg>Add image definition<commit_after>import RoiMap from '../RoiMap';
import PriorityQueue from 'js-priority-queue';
import {dxs, dys} from './../../../util/dxdy.js';

/**
 * This method allows to create a ROIMap using the water shed algorithm. By default this algorithm
 * will fill the holes and therefore the lowest value of the image (black zones).
 * If no points are given, the function will look for all the minimal points.
 * If no mask is given the algorithm will completely fill the image.
 * Please take care about the value that has be in the mask ! In order to be coherent with the expected mask,
 * meaning that if it is a dark zone, the mask will be dark the normal behaviour to fill a zone
 * is that the mask pixel is clear (value of 0) !
 * However if you work in the 'invert' mode, the mask value has to be 'set' and the method will look for
 * maxima.
 * @memberof RoiManager
 * @instance
 * @param {Object} [options={}]
 * @param {number[][]} [options.points[ - Array of points [[x1,y1], [x2,y2], ...].
 * @param {number} [options.fillMaxValue] - Limit of filling. By example, we can fill to a maximum value 32000 of a 16 bitDepth image.
 *          If invert this will corresponds to the minimal value
 * @param {Image} [options.image=this] - By default the waterShed will be applied on the current image. However waterShed can only be applied
 *                              on 1 component image. This allows to specify a grey scale image on which to apply waterShed..
 * @param {Image} [options.mask] - A binary image, the same size as the image. The algorithm will fill only if the current pixel in the binary mask is true.
 * @param {boolean} [options.invert = false] - By default we fill the minima
 * @returns {RoiMap}
 */

export default function fromWaterShed(options = {}) {
    let {
        points,
        mask,
        image,
        fillMaxValue = this.maxValue,
        invert = false
    } = options;
    let currentImage = image || this;
    currentImage.checkProcessable('fromWaterShed', {
        bitDepth: [8, 16],
        components: 1
    });

    /*
     We need to invert the logic because we are always using method to look for maxima and not minima and
     here water is expected to fill the minima first ...
    */

    invert = !invert;

    //WaterShed is done from points in the image. We can either specify those points in options,
    // or it is gonna take the minimum locals of the image by default.
    if (!points) {
        points = currentImage.getLocalMaxima({
            invert,
            mask
        });
    }

    let maskExpectedValue = (invert) ? 0 : 1;

    let data = new Int16Array(currentImage.size);
    let width = currentImage.width;
    let height = currentImage.height;
    let toProcess = new PriorityQueue({
        comparator: (a, b) => a[2] - b[2],
        strategy: PriorityQueue.BinaryHeapStrategy
    });
    for (let i = 0; i < points.length; i++) {
        let index = points[i][0] + points[i][1] * width;
        data[index] = i + 1;
        let intensity = currentImage.data[index];
        if (
            (invert && intensity <= fillMaxValue) ||
            (!invert && intensity >= fillMaxValue)
        ) {
            toProcess.queue([points[i][0], points[i][1], intensity]);
        }
    }

    //Then we iterate through each points
    while (toProcess.length > 0) {
        let currentPoint = toProcess.dequeue();
        let currentValueIndex = currentPoint[0] + currentPoint[1] * width;

        for (let dir = 0; dir < 4; dir++) {
            let newX = currentPoint[0] + dxs[dir];
            let newY = currentPoint[1] + dys[dir];
            if (newX >= 0 && newY >= 0 && newX < width && newY < height) {
                let currentNeighbourIndex = newX + newY * width;
                if (!mask || (mask.getBit(currentNeighbourIndex) === maskExpectedValue)) {
                    let intensity = currentImage.data[currentNeighbourIndex];
                    if (
                        (invert && intensity <= fillMaxValue) ||
                        (!invert && intensity >= fillMaxValue)
                    ) {
                        if (data[currentNeighbourIndex] === 0) {
                            data[currentNeighbourIndex] = data[currentValueIndex];
                            toProcess.queue([currentPoint[0] + dxs[dir], currentPoint[1] + dys[dir], intensity]);
                        }
                    }
                }
            }
        }
    }

    return new RoiMap(currentImage, data);
}
<|endoftext|>


<commit_before>var React = require('react'),
		ticker = require('../components/ticker.js'),
        numeral = require('numeral'),
        moment = require('moment'),
        _ = require('underscore'),
        lastSelectedRow;

var countries = ['GR','DK','ZA','RU','CO','IT','IN','BR','AE','AF','AG','AI','AM','AO','AS','AR','AT','AU','AX','BA','BB','BD','BE','BF','BH','BI','BJ','BM','BN','BS','BT','BV','BY','CA','CC','CD','CG','CH','CK','CL','CM','CN','CO','CR','CU','CV','CX','CY','CZ','DE','DM','DO','DZ','EE','EH','ES','FI','FJ','FK','FM','FR','GB','GE','GI','GL','GM','GN','GP','GQ','GS','GT','GU','GW','GY','HK','HM','HN','HR','HU','ID','IE','IL','IO','IQ','IR','JO','JP','KE','KG','KH','KM','KY','KZ','LC','LI','LK','LR','LS','LT','LU','LV','LY','MD','MH','MK','MM','MO','MQ','MR','MS','MT','MU','MV','MW','MX','MY','MZ','NA','NC','NE','NF','NG','NI','NL','NO','NP','NR','NU','NZ','OM','PA','PE','PF','PH','PK','PL','PM','PN','PR','PS','PW','PY','QA','RE','RO','RS','SA','SB','SD','SE','SG','SH','SJ','SM','SN','SO','SR','ST','SV','TC','TD','TH','TJ','TK','TL','TN','TO','TR','TT','TV','TW','UM','UY','UZ','VA','VE','VI','VN','WS','ZA','ZW','KR'];
var imageCache = {};

(function() {
    var each, img;
    for (var i = 0; i < countries.length; i++) {
        each = countries[i];
        img = new Image();
        img.src = 'images/famfamfam_flag_icons/png/' + each.toLowerCase() + '.png';
        imageCache[each] = img;
    }
})();

var typeAlignmentMap = {
    j: 'right',
    s: 'left',
    t: 'center',
    f: 'right',
    d: 'center'
};

var isInt = function(n){
        return Number(n)===n && n%1===0;
};

var isFloat = function(n){
        return   n===Number(n)  && n%1!==0
};

var format = function(data) {
    if (isInt(data)) {
        if (data > 1431446226436) { // this is a time
            return moment(data).format('HH:mm:ss.SSS');
        } else {
            return numeral(data).format('0,0');
        }
    } else if (isFloat(data)) {
        return numeral(data).format('0,0.00');
    } else {
        return data;
    }
};

var HyperGrid = React.createClass({
    componentDidMount: function(){

        window.addEventListener('polymer-ready',function(){
            var jsonGrid = document.querySelector('#stock-example');
            var jsonModel = jsonGrid.getBehavior();

            jsonGrid.getRenderer().paint = function(gc) {
                if (!this.grid) {
                    return;
                }
                this.renderGrid(gc);

                //draw the thick blue line at the bottom of the header
                gc.beginPath();
                var fixedColumnsWidth = jsonModel.getFixedColumnsWidth();
                var viewWidth = this.getBounds().width() - 200; // look in fin-hypergrid and initializtion of fin-canvas
                var height = this.getFixedRowHeight(0);
                gc.strokeStyle = '#3D77FE';
                gc.lineWidth = 4;
                gc.moveTo(0, height + 0.5);
                gc.lineTo(viewWidth, height + 0.5);
                gc.stroke();

                this.getGrid().gridRenderedNotification();
            };
            jsonGrid.getRenderer().paint.bind(jsonGrid);

            var cellProvider = jsonModel.getCellProvider();

            jsonModel.setData(ticker.stocks);
            jsonModel.setFixedColumnCount(1);
            jsonModel.setHeaders(['Symbol','High','Low','Last','Today', 'Change','% Change','Volume','Bid Qty','Bid','Spread','Ask','Ask Qty','Country Code','Country','ICB','Industry','Super Sector','Sector','Sub Sector','Date','Time','Open','Cls','Previous Cls','Previous Cls Dt','Name']);
            jsonModel.setFields(['TICKER','High','Low','Last','Today', 'Change','PercentChange','Volume','BidQuantity','Bid','Spread','Ask','AskQuantity','countryCode', 'COUNTRY','ICB','INDUS','SUP_SEC','SEC','SUB_SEC','Date','Time','Open','Close','PreviousClose','PreviousCloseDate','NAME']);

            var bgColor = '#07071E';
            var fixedAreasBGColor = bgColor;

            var font = "24px Roboto Condensed";
            var headingFont = "14px Roboto Condensed";
            var headingFGColor = '#3D77FE';

            var lnfOverrides = {
                font: font,
                topLeftFont: headingFont,
                fixedRowFont: headingFont,
                fixedColumnFont: font,
                backgroundColor2: bgColor,
                backgroundColor: bgColor,
                topLeftBackgroundColor: fixedAreasBGColor,
                fixedColumnBackgroundColor: fixedAreasBGColor,
                fixedRowBackgroundColor: fixedAreasBGColor,
                color: 'white',
                topLeftColor: headingFGColor,
                fixedColumnColor: 'white',
                fixedRowColor: headingFGColor,
                lineColor: '#131C23',
                gridLinesV: false,
                gridLinesH: true,
                defaultFixedRowHeight: 40
            };
            jsonModel.defaultRowHeight = 57,

            //to apply to a specific table
            jsonGrid.addProperties(lnfOverrides);
            setInterval(function() {
                ticker.randomize();
                jsonModel.dataModified();
            }, 10);

            jsonModel.fixedColumnClicked = (grid, cellData) => {
                    lastSelectedRow =  cellData.gridCell.y;
                        var row = jsonModel.getRow(lastSelectedRow)

                        require('./child-window.js').createChildWindow({
                            name: row.NAME,
                            url: 'row-view.html?row=' + lastSelectedRow,
                            autoShow: true,
                            width: 350,
                            maxWidth: 350,
                            frame: false,
                            maximizable: false,
                            height: 594 / 2,
                            maxHeight: 594 / 2,
                            minHeight: 594 / 2,
                        })

            };

            jsonModel.highlightCellOnHover= function(isColumnHovered, isRowHovered) {
                return isRowHovered;
            };
            var flashMap = {
              red: function(v) {
                return 'rgba(255, 0, 0, '+ (1.0-(40-v)/40) +')';
              },
              green: function(v) {
                return 'rgba(0, 255, 0, '+ (1.0-(40-v)/40) +')';
              }
            };
            cellProvider.getCell = function(config) {
                var renderer = cellProvider.cellCache.simpleCellRenderer;
                config.halign = 'right';
                var x = config.x;
                var y = config.y;
                var row = jsonModel.getRow(y) || {
                  flash: 0,
                  flashColor: 'green'
                };
                if (x === 4) {
                    renderer = cellProvider.cellCache.sparklineCellRenderer;
                } else if (x === 5 || x === 6) {
                    config.value = format(config.value);
                    if (config.value.indexOf('-') === 0) {
                      config.value = '(' + config.value.substring(1) + ')';
                      config.fgColor = 'red';
                    } else {
                      config.fgColor = 'green';
                    }
                    //config.font = '24px Verdana';
                } else if (x === 3) {
                  config.value = format(config.value);
                  if (row.flash > 0) {
                    config.bgColor = flashMap[row.flashColor](row.flash);
                    config.fgColor = 'white';
                    row.flash = row.flash - 1;
                    // if (y === 0) {
                    //   console.log('update flash = ' + row.flash + ' ' + Date.now());
                    // }
                  }
                } else if (x === 13) {
                  config.value = [imageCache[config.value],config.value,null];
                } else {
                  config.value = format(config.value);
                }

                row.lastViewedTime = Date.now();
                // if (row.flash > 15) {
                //   config.bgColor = 'yellow';
                // }

                renderer.config = config;
                return renderer;
            };

            var state = {
   "columnIndexes":[
      0,
      4,
      3,
      1,
      5,
      7,
      27,
      28
   ],
   "fixedColumnIndexes":[

   ],
   "hiddenColumns":[
      26,
      25,
      24,
      14,
      8,
      9,
      10,
      11,
      12,
      13,
      21,
      6,
      2,
      15,
      16,
      17,
      18,
      19,
      20,
      23,
      22
   ],
   "columnWidths":[
      null,
      76,
      95.01953125,
      76,
      160,
      86.30078125,
      86.30078125,
      85.796875,
      95.01953125,
      95.01953125,
      64.50390625,
      95.01953125,
      79.76171875,
      92.306640625,
      86.5908203125,
      38.38671875,
      118.5322265625,
      167.72021484375,
      213.3408203125,
      248.8876953125,
      266.775390625,
      177.84765625,
      49.4189453125,
      25.3046875,
      73.591796875,
      269.416015625,
      217.42236328125,
      86.30078125,
      86.30078125
   ],
   "fixedColumnWidths":[
      60.84765625
   ],
   "rowHeights":{

   },
   "fixedRowHeights":{

   },
   "sorted":[

   ]
};
            jsonModel.setState(state);
        });

    },
    openBidOffer: () => {
                console.log('start buddy')
                require('./child-window.js').createChildWindow({
                    name: 'orders',
                    url: 'order.html',
                    autoShow: true,
                    width: 960,
                    maxWidth: 960,
                    minWidth: 960,
                    height: 594 / 2,
                    maxHeight: 594 / 2,
                    minHeight: 594 / 2,
                    frame: false
                });
            },
            openOrders: () => {

                var jsonGrid = document.querySelector('#stock-example')
                var jsonModel = jsonGrid.getBehavior()

                lastSelectedRow = lastSelectedRow || 0;
                var row = jsonModel.getRow(lastSelectedRow)

                require('./child-window.js').createChildWindow({
                    name: row.NAME,
                    url: 'row-view.html?row=' + lastSelectedRow,
                    autoShow: true,
                    width: 350,
                    maxWidth: 350,
                    frame: false,
                    maximizable: false,
                    height: 594 / 2,
                    maxHeight: 594 / 2,
                    minHeight: 594 / 2,
                })
            },
    render: function (){
        return

        <fin-hypergrid id="stock-example">
            <fin-hypergrid-behavior-json></fin-hypergrid-behavior-json>
            <fin-hypergrid-excel></fin-hypergrid-excel>
        </fin-hypergrid>

    }
});
// <fin-hypergrid id="q-example"></fin-hypergrid>

module.exports = HyperGrid;

<commit_msg>fixed selection and it's colors<commit_after>var React = require('react'),
		ticker = require('../components/ticker.js'),
        numeral = require('numeral'),
        moment = require('moment'),
        _ = require('underscore'),
        lastSelectedRow;

var countries = ['GR','DK','ZA','RU','CO','IT','IN','BR','AE','AF','AG','AI','AM','AO','AS','AR','AT','AU','AX','BA','BB','BD','BE','BF','BH','BI','BJ','BM','BN','BS','BT','BV','BY','CA','CC','CD','CG','CH','CK','CL','CM','CN','CO','CR','CU','CV','CX','CY','CZ','DE','DM','DO','DZ','EE','EH','ES','FI','FJ','FK','FM','FR','GB','GE','GI','GL','GM','GN','GP','GQ','GS','GT','GU','GW','GY','HK','HM','HN','HR','HU','ID','IE','IL','IO','IQ','IR','JO','JP','KE','KG','KH','KM','KY','KZ','LC','LI','LK','LR','LS','LT','LU','LV','LY','MD','MH','MK','MM','MO','MQ','MR','MS','MT','MU','MV','MW','MX','MY','MZ','NA','NC','NE','NF','NG','NI','NL','NO','NP','NR','NU','NZ','OM','PA','PE','PF','PH','PK','PL','PM','PN','PR','PS','PW','PY','QA','RE','RO','RS','SA','SB','SD','SE','SG','SH','SJ','SM','SN','SO','SR','ST','SV','TC','TD','TH','TJ','TK','TL','TN','TO','TR','TT','TV','TW','UM','UY','UZ','VA','VE','VI','VN','WS','ZA','ZW','KR'];
var imageCache = {};

(function() {
    var each, img;
    for (var i = 0; i < countries.length; i++) {
        each = countries[i];
        img = new Image();
        img.src = 'images/famfamfam_flag_icons/png/' + each.toLowerCase() + '.png';
        imageCache[each] = img;
    }
})();

var typeAlignmentMap = {
    j: 'right',
    s: 'left',
    t: 'center',
    f: 'right',
    d: 'center'
};

var isInt = function(n){
        return Number(n)===n && n%1===0;
};

var isFloat = function(n){
        return   n===Number(n)  && n%1!==0
};

var format = function(data) {
    if (isInt(data)) {
        if (data > 1431446226436) { // this is a time
            return moment(data).format('HH:mm:ss.SSS');
        } else {
            return numeral(data).format('0,0');
        }
    } else if (isFloat(data)) {
        return numeral(data).format('0,0.00');
    } else {
        return data;
    }
};

var HyperGrid = React.createClass({
    componentDidMount: function(){

        window.addEventListener('polymer-ready',function(){
            var jsonGrid = document.querySelector('#stock-example');
            var jsonModel = jsonGrid.getBehavior();

            jsonGrid.getRenderer().paint = function(gc) {
                if (!this.grid) {
                    return;
                }
                this.renderGrid(gc);

                //draw the thick blue line at the bottom of the header
                gc.beginPath();
                var fixedColumnsWidth = jsonModel.getFixedColumnsWidth();
                var viewWidth = this.getBounds().width() - 200; // look in fin-hypergrid and initializtion of fin-canvas
                var height = this.getFixedRowHeight(0);
                gc.strokeStyle = '#3D77FE';
                gc.lineWidth = 4;
                gc.moveTo(0, height + 0.5);
                gc.lineTo(viewWidth, height + 0.5);
                gc.stroke();

                this.getGrid().gridRenderedNotification();
            };
            jsonGrid.getRenderer().paint.bind(jsonGrid);

            var cellProvider = jsonModel.getCellProvider();

            jsonModel.setData(ticker.stocks);
            jsonModel.setFixedColumnCount(1);
            jsonModel.setHeaders(['Symbol','High','Low','Last','Today', 'Change','% Change','Volume','Bid Qty','Bid','Spread','Ask','Ask Qty','Country Code','Country','ICB','Industry','Super Sector','Sector','Sub Sector','Date','Time','Open','Cls','Previous Cls','Previous Cls Dt','Name']);
            jsonModel.setFields(['TICKER','High','Low','Last','Today', 'Change','PercentChange','Volume','BidQuantity','Bid','Spread','Ask','AskQuantity','countryCode', 'COUNTRY','ICB','INDUS','SUP_SEC','SEC','SUB_SEC','Date','Time','Open','Close','PreviousClose','PreviousCloseDate','NAME']);

            var bgColor = '#07071E';
            var fixedAreasBGColor = bgColor;

            var font = "24px Roboto Condensed";
            var headingFont = "14px Roboto Condensed";
            var headingFGColor = '#3D77FE';

            var lnfOverrides = {
                font: font,
                topLeftFont: headingFont,
                fixedRowFont: headingFont,
                fixedColumnFont: font,
                backgroundColor2: bgColor,
                backgroundColor: bgColor,
                topLeftBackgroundColor: fixedAreasBGColor,
                fixedColumnBackgroundColor: fixedAreasBGColor,
                fixedRowBackgroundColor: fixedAreasBGColor,
                color: 'white',
                topLeftColor: headingFGColor,
                fixedColumnColor: 'white',
                fixedRowColor: headingFGColor,
                lineColor: '#131C23',
                gridLinesV: false,
                gridLinesH: true,

                fixedColumnFGSelColor: 'white',
                fixedColumnBGSelColor: '#3D77FE',
                fixedRowFGSelColor: 'white',
                fixedRowBGSelColor: '#3D77FE',

                defaultFixedRowHeight: 40
            };
            jsonModel.defaultRowHeight = 57,

            //to apply to a specific table
            jsonGrid.addProperties(lnfOverrides);
            jsonGrid.editAt = function(){};

            setInterval(function() {
                ticker.randomize();
                jsonModel.dataModified();
            }, 10);

            jsonModel.fixedColumnClicked = (grid, cellData) => {
                    lastSelectedRow =  cellData.gridCell.y;
                        var row = jsonModel.getRow(lastSelectedRow)

                        require('./child-window.js').createChildWindow({
                            name: row.NAME,
                            url: 'row-view.html?row=' + lastSelectedRow,
                            autoShow: true,
                            width: 350,
                            maxWidth: 350,
                            frame: false,
                            maximizable: false,
                            height: 594 / 2,
                            maxHeight: 594 / 2,
                            minHeight: 594 / 2,
                        })

            };

            jsonModel.highlightCellOnHover= function(isColumnHovered, isRowHovered) {
                return isRowHovered;
            };
            var flashMap = {
              red: function(v) {
                return 'rgba(255, 0, 0, '+ (1.0-(40-v)/40) +')';
              },
              green: function(v) {
                return 'rgba(0, 255, 0, '+ (1.0-(40-v)/40) +')';
              }
            };
            cellProvider.getCell = function(config) {
                var renderer = cellProvider.cellCache.simpleCellRenderer;
                config.halign = 'right';
                var x = config.x;
                var y = config.y;
                var row = jsonModel.getRow(y) || {
                  flash: 0,
                  flashColor: 'green'
                };
                if (x === 4) {
                    renderer = cellProvider.cellCache.sparklineCellRenderer;
                } else if (x === 5 || x === 6) {
                    config.value = format(config.value);
                    if (config.value.indexOf('-') === 0) {
                      config.value = '(' + config.value.substring(1) + ')';
                      config.fgColor = 'red';
                    } else {
                      config.fgColor = 'green';
                    }
                    //config.font = '24px Verdana';
                } else if (x === 3) {
                  config.value = format(config.value);
                  if (row.flash > 0) {
                    config.bgColor = flashMap[row.flashColor](row.flash);
                    config.fgColor = 'white';
                    row.flash = row.flash - 1;
                    // if (y === 0) {
                    //   console.log('update flash = ' + row.flash + ' ' + Date.now());
                    // }
                  }
                } else if (x === 13) {
                  config.value = [imageCache[config.value],config.value,null];
                } else {
                  config.value = format(config.value);
                }

                row.lastViewedTime = Date.now();
                // if (row.flash > 15) {
                //   config.bgColor = 'yellow';
                // }

                renderer.config = config;
                return renderer;
            };

            var state = {"columnIndexes":[0,26,4,3,1,5,7,27,28],"fixedColumnIndexes":[],"hiddenColumns":[25,18,24,14,8,9,10,11,12,13,21,6,2,15,16,17,19,20,23,22],"columnWidths":[null,85.796875,95.01953125,103.9609375,160,102.35546875,86.30078125,85.796875,95.01953125,95.01953125,64.50390625,95.01953125,79.76171875,92.306640625,86.5908203125,38.38671875,118.5322265625,167.72021484375,341.04296875,248.8876953125,266.775390625,177.84765625,49.4189453125,25.3046875,73.591796875,269.416015625,262.3046875,86.30078125,86.30078125],"fixedColumnWidths":[71.62890625],"rowHeights":{},"fixedRowHeights":{},"sorted":[]};
            jsonModel.setState(state);
        });

    },
    openBidOffer: () => {
                console.log('start buddy')
                require('./child-window.js').createChildWindow({
                    name: 'orders',
                    url: 'order.html',
                    autoShow: true,
                    width: 960,
                    maxWidth: 960,
                    minWidth: 960,
                    height: 594 / 2,
                    maxHeight: 594 / 2,
                    minHeight: 594 / 2,
                    frame: false
                });
            },
            openOrders: () => {

                var jsonGrid = document.querySelector('#stock-example')
                var jsonModel = jsonGrid.getBehavior()

                lastSelectedRow = lastSelectedRow || 0;
                var row = jsonModel.getRow(lastSelectedRow)

                require('./child-window.js').createChildWindow({
                    name: row.NAME,
                    url: 'row-view.html?row=' + lastSelectedRow,
                    autoShow: true,
                    width: 350,
                    maxWidth: 350,
                    frame: false,
                    maximizable: false,
                    height: 594 / 2,
                    maxHeight: 594 / 2,
                    minHeight: 594 / 2,
                })
            },
    render: function (){
        return

        <fin-hypergrid id="stock-example">
            <fin-hypergrid-behavior-json></fin-hypergrid-behavior-json>
            <fin-hypergrid-excel></fin-hypergrid-excel>
        </fin-hypergrid>

    }
});
// <fin-hypergrid id="q-example"></fin-hypergrid>

module.exports = HyperGrid;

<|endoftext|>


<commit_before>module("calendar rendering", {
  setup: createCalendarContainer
});

test("shows year", function() {
  createCalendarWithOneWeek();
  assertHasValues(".continuousCalendar thead th.month", ["2008"]);
});

test("shows week days", function() {
  calendar().continuousCalendar({startDate: [30, 4, 2008],weeksBefore: 0,weeksAfter: 0});
  assertHasValues(".continuousCalendar thead th.weekDay", [
    "ma", "ti", "ke", "to", "pe", "la", "su"
  ]);
});

test("lists week days for vappu 2009", function() {
  calendar({startDate: "4/20/2009", endDate: "4/26/2009"}).continuousCalendar({weeksBefore: 0,weeksAfter: 0});
  equals($.trim(calendar().find(".continuousCalendar tbody").html()),
    '
' +
    '	' +
    '17	' +
    '20	' +
    '21	' +
    '22	' +
    '23	' +
    '24	' +
    '25	' +
    '26	' +
    '
'
    );
});

test("lists given number of weeks before given date", function() {
  calendar().continuousCalendar({startDate: [18, 4, 2009],weeksBefore: 2,weeksAfter: 0});
  assertHasValues(".date", [
    "30","31","1","2","3","4","5",
    "6","7","8","9","10","11","12",
    "13","14","15","16","17","18","19"
  ]);
});

test("lists given number of weeks after given date", function() {
  calendar().continuousCalendar({startDate: [18, 4, 2009],weeksBefore: 0,weeksAfter: 2});
  assertHasValues(".date", [
    "13","14","15","16","17","18","19",
    "20","21","22","23","24","25","26",
    "27","28","29","30","1","2","3"
  ]);
});

test("shows month name on first row of full week", function() {
  calendar().continuousCalendar({startDate: [30, 4, 2009],weeksBefore: 0,weeksAfter: 5});
  var months = calendar().find(" tbody .month");
  equals(months.size(), 6);
  var firstMonth = months.eq(1);
  equals(firstMonth.text(), "toukokuu");
  equals(firstMonth.next().next().text(), "4");
  var secondMonth = months.eq(5);
  equals(secondMonth.text(), "kesäkuu");
  equals(secondMonth.next().next().text(), "1");
});

test("highlights current date and shows year for janary", function() {
  var today = new Date();
  calendar().continuousCalendar({startDate: [
    today.getDate(), today.getMonth() + 1, today.getFullYear()],
    weeksBefore: 20,weeksAfter: 20});
  var cells = calendar().find(".today");
  equals(cells.size(), 1);
  equals(cells.text(), today.getDate());
  equals(calendar().find(".month:contains(tammikuu)").parent().next().find(".month").text(), "2009");
});

test("highlights selected date", function() {
  calendar().continuousCalendar({startDate:  [30, 4, 2009],weeksBefore:2,weeksAfter:2});
  equals(calendar().find(".selected").text(), "30");
});

test("higlights selected date range", function() {
  calendar().continuousCalendar({startDate:  [29, 4, 2009],endDate: [5, 5, 2009],weeksBefore:2,weeksAfter:2});
  equals(calendar().find(".selected").size(), 7);
});

test("if start date not selected show around current day instead", function() {
  calendar().continuousCalendar({weeksBefore: 0,weeksAfter: 0});
  var today = new Date();
  equals(calendar().find(".date").size(), 7);
  equals(calendar().find(".date:contains(" + today.getDay() + ")").size(), 1);
  //assertHasValues(".date", ["20","21","22","23","24","25","26"]);
  equals(calendar().find(".selected").size(), 0);
});

test("render week numbers", function() {
  createCalendarWithOneWeek();
  var today = new Date();
  ok(calendar().find(".week").text() > 0);
});

module("calendar events", {
  setup: createCalendarContainer
});

test("highlight clicked day", function() {
  createCalendarWithOneWeek();
  calendar().find(".date:eq(1)").click();
  equals(calendar().find(".selected").text(), "29");
});

//TODO week number selects week
//TODO month nam selects month
//TODO kahva selectioniin
var testIndex = 0;

function createCalendarContainer() {
  testIndex++;
  var container = $("

");
  var index = $('

').append(testIndex).css({
    "float": "left",
    "font-weight": "bold",
    "color": "green"
  });
  container.attr("id", calendarId());
  $("#main").append(index).append(container);
}

function calendar(params) {
  var container = $("#" + calendarId());
  addFieldIfRequired("startDate");
  addFieldIfRequired("endDate");
  function addFieldIfRequired(fieldName) {
    if (params && params[fieldName]) {
      console.log(params[fieldName]);
      var field = $("<input>").attr("type", "text").addClass(fieldName).val(params[fieldName]);
      container.append(field);
    }
  }
  return container;
}

function calendarId() {
  return "continuousCalendar" + testIndex;
}

function createCalendarWithOneWeek() {
  calendar().continuousCalendar({
    startDate: [30, 4, 2008],
    weeksBefore: 0,
    weeksAfter: 0
  });
}

function assertHasValues(selector, expectedArray) {
  same($.map(calendar().find(selector), function (elem) {
    return $(elem).text();
  }), expectedArray);
}<commit_msg>unused var<commit_after>module("calendar rendering", {
  setup: createCalendarContainer
});

test("shows year", function() {
  createCalendarWithOneWeek();
  assertHasValues(".continuousCalendar thead th.month", ["2008"]);
});

test("shows week days", function() {
  calendar().continuousCalendar({startDate: [30, 4, 2008],weeksBefore: 0,weeksAfter: 0});
  assertHasValues(".continuousCalendar thead th.weekDay", [
    "ma", "ti", "ke", "to", "pe", "la", "su"
  ]);
});

test("lists week days for vappu 2009", function() {
  calendar({startDate: "4/20/2009", endDate: "4/26/2009"}).continuousCalendar({weeksBefore: 0,weeksAfter: 0});
  equals($.trim(calendar().find(".continuousCalendar tbody").html()),
    '
' +
    '	' +
    '17	' +
    '20	' +
    '21	' +
    '22	' +
    '23	' +
    '24	' +
    '25	' +
    '26	' +
    '
'
    );
});

test("lists given number of weeks before given date", function() {
  calendar().continuousCalendar({startDate: [18, 4, 2009],weeksBefore: 2,weeksAfter: 0});
  assertHasValues(".date", [
    "30","31","1","2","3","4","5",
    "6","7","8","9","10","11","12",
    "13","14","15","16","17","18","19"
  ]);
});

test("lists given number of weeks after given date", function() {
  calendar().continuousCalendar({startDate: [18, 4, 2009],weeksBefore: 0,weeksAfter: 2});
  assertHasValues(".date", [
    "13","14","15","16","17","18","19",
    "20","21","22","23","24","25","26",
    "27","28","29","30","1","2","3"
  ]);
});

test("shows month name on first row of full week", function() {
  calendar().continuousCalendar({startDate: [30, 4, 2009],weeksBefore: 0,weeksAfter: 5});
  var months = calendar().find(" tbody .month");
  equals(months.size(), 6);
  var firstMonth = months.eq(1);
  equals(firstMonth.text(), "toukokuu");
  equals(firstMonth.next().next().text(), "4");
  var secondMonth = months.eq(5);
  equals(secondMonth.text(), "kesäkuu");
  equals(secondMonth.next().next().text(), "1");
});

test("highlights current date and shows year for janary", function() {
  var today = new Date();
  calendar().continuousCalendar({startDate: [
    today.getDate(), today.getMonth() + 1, today.getFullYear()],
    weeksBefore: 20,weeksAfter: 20});
  var cells = calendar().find(".today");
  equals(cells.size(), 1);
  equals(cells.text(), today.getDate());
  equals(calendar().find(".month:contains(tammikuu)").parent().next().find(".month").text(), "2009");
});

test("highlights selected date", function() {
  calendar().continuousCalendar({startDate:  [30, 4, 2009],weeksBefore:2,weeksAfter:2});
  equals(calendar().find(".selected").text(), "30");
});

test("higlights selected date range", function() {
  calendar().continuousCalendar({startDate:  [29, 4, 2009],endDate: [5, 5, 2009],weeksBefore:2,weeksAfter:2});
  equals(calendar().find(".selected").size(), 7);
});

test("if start date not selected show around current day instead", function() {
  calendar().continuousCalendar({weeksBefore: 0,weeksAfter: 0});
  var today = new Date();
  equals(calendar().find(".date").size(), 7);
  equals(calendar().find(".date:contains(" + today.getDay() + ")").size(), 1);
  //assertHasValues(".date", ["20","21","22","23","24","25","26"]);
  equals(calendar().find(".selected").size(), 0);
});

test("render week numbers", function() {
  createCalendarWithOneWeek();
  ok(calendar().find(".week").text() > 0);
});

module("calendar events", {
  setup: createCalendarContainer
});

test("highlight clicked day", function() {
  createCalendarWithOneWeek();
  calendar().find(".date:eq(1)").click();
  equals(calendar().find(".selected").text(), "29");
});

//TODO week number selects week
//TODO month nam selects month
//TODO kahva selectioniin
var testIndex = 0;

function createCalendarContainer() {
  testIndex++;
  var container = $("

");
  var index = $('

').append(testIndex).css({
    "float": "left",
    "font-weight": "bold",
    "color": "green"
  });
  container.attr("id", calendarId());
  $("#main").append(index).append(container);
}

function calendar(params) {
  var container = $("#" + calendarId());
  addFieldIfRequired("startDate");
  addFieldIfRequired("endDate");
  function addFieldIfRequired(fieldName) {
    if (params && params[fieldName]) {
      console.log(params[fieldName]);
      var field = $("<input>").attr("type", "text").addClass(fieldName).val(params[fieldName]);
      container.append(field);
    }
  }
  return container;
}

function calendarId() {
  return "continuousCalendar" + testIndex;
}

function createCalendarWithOneWeek() {
  calendar().continuousCalendar({
    startDate: [30, 4, 2008],
    weeksBefore: 0,
    weeksAfter: 0
  });
}

function assertHasValues(selector, expectedArray) {
  same($.map(calendar().find(selector), function (elem) {
    return $(elem).text();
  }), expectedArray);
}<|endoftext|>


<commit_before>(function () {
  var ns = $.namespace("pskl.controller");
  ns.DrawingController = function (piskelController, paletteController, container) {
    /**
     * @public
     */
    this.piskelController = piskelController;

    this.paletteController = paletteController;

    /**
     * @public
     */
    this.overlayFrame = pskl.model.Frame.createEmptyFromFrame(piskelController.getCurrentFrame());

    /**
     * @private
     */
    this.container = container;

    // TODO(vincz): Store user prefs in a localstorage string ?
    var renderingOptions = {
      "zoom": this.calculateZoom_(),
      "supportGridRendering" : true,
      "height" : this.getContainerHeight_(),
      "width" : this.getContainerWidth_(),
      "xOffset" : 0,
      "yOffset" : 0
    };

    this.overlayRenderer = new pskl.rendering.frame.CachedFrameRenderer(this.container, renderingOptions, ["canvas-overlay"]);
    this.renderer = new pskl.rendering.frame.CachedFrameRenderer(this.container, renderingOptions, ["drawing-canvas"]);
    this.layersRenderer = new pskl.rendering.layer.LayersRenderer(this.container, renderingOptions, piskelController);

    this.compositeRenderer = new pskl.rendering.CompositeRenderer();
    this.compositeRenderer
      .add(this.overlayRenderer)
      .add(this.renderer)
      .add(this.layersRenderer);

    // State of drawing controller:
    this.isClicked = false;
    this.previousMousemoveTime = 0;
    this.currentToolBehavior = null;

    // State of clicked button (need to be stateful here, see comment in getCurrentColor_)
    this.currentMouseButton_ = Constants.LEFT_BUTTON;
  };

  ns.DrawingController.prototype.init = function () {
    this.initMouseBehavior();

    $.subscribe(Events.TOOL_SELECTED, $.proxy(function(evt, toolBehavior) {
      this.currentToolBehavior = toolBehavior;
      this.overlayFrame.clear();
    }, this));

    $(window).resize($.proxy(this.startResizeTimer_, this));

    $.subscribe(Events.USER_SETTINGS_CHANGED, $.proxy(this.onUserSettingsChange_, this));
    $.subscribe(Events.FRAME_SIZE_CHANGED, $.proxy(this.onFrameSizeChanged_, this));

    this.centerColumnWrapperHorizontally_();
  };

  ns.DrawingController.prototype.initMouseBehavior = function() {
    var body = $('body');
    this.container.mousedown($.proxy(this.onMousedown_, this));
    this.container.mouseenter($.proxy(this.onMouseenter_, this));
    this.container.mouseleave($.proxy(this.onMouseleave_, this));

    if (pskl.utils.UserAgent.isChrome) {
      this.container.on('mousewheel', $.proxy(this.onMousewheel_, this));
    } else {
      this.container.on('wheel', $.proxy(this.onMousewheel_, this));
    }

    body.mouseup($.proxy(this.onMouseup_, this));

    // Deactivate right click:
    body.contextmenu(this.onCanvasContextMenu_);
  };

  ns.DrawingController.prototype.startResizeTimer_ = function () {
    if (this.resizeTimer) {
      window.clearInterval(this.resizeTimer);
    }
    this.resizeTimer = window.setTimeout($.proxy(this.afterWindowResize_, this), 200);
  };

  ns.DrawingController.prototype.afterWindowResize_ = function () {
    var initialWidth = this.compositeRenderer.getDisplaySize().width;
    this.compositeRenderer.setDisplaySize(this.getContainerWidth_(), this.getContainerHeight_());
    this.centerColumnWrapperHorizontally_();
    var ratio = this.compositeRenderer.getDisplaySize().width / initialWidth;
    var newZoom = ratio * this.compositeRenderer.getZoom();
    this.compositeRenderer.setZoom(newZoom);

    $.publish(Events.ZOOM_CHANGED);
  };

  /**
   * @private
   */
  ns.DrawingController.prototype.onUserSettingsChange_ = function (evt, settingsName, settingsValue) {
    if(settingsName == pskl.UserSettings.SHOW_GRID) {
      console.warn('DrawingController:onUserSettingsChange_ not implemented !');
    }
  };

  ns.DrawingController.prototype.onFrameSizeChanged_ = function () {
    this.compositeRenderer.setDisplaySize(this.getContainerWidth_(), this.getContainerHeight_());
    this.compositeRenderer.setZoom(this.calculateZoom_());
    this.compositeRenderer.setOffset(0, 0);
    $.publish(Events.ZOOM_CHANGED);
  };

  /**
   * @private
   */
  ns.DrawingController.prototype.onMouseenter_ = function (event) {
    this.container.bind('mousemove', $.proxy(this.onMousemove_, this));
  };

  /**
   * @private
   */
  ns.DrawingController.prototype.onMouseleave_ = function (event) {
    this.container.unbind('mousemove');
    this.currentToolBehavior.hideHighlightedPixel(this.overlayFrame);
  };

  /**
   * @private
   */
  ns.DrawingController.prototype.onMousedown_ = function (event) {
    var frame = this.piskelController.getCurrentFrame();
    var coords = this.renderer.getCoordinates(event.clientX, event.clientY);

    if (event.button === Constants.MIDDLE_BUTTON) {
      if (frame.containsPixel(coords.x, coords.y)) {
        $.publish(Events.SELECT_PRIMARY_COLOR, [frame.getPixel(coords.x, coords.y)]);
      }
    } else {
      this.isClicked = true;
      this.setCurrentButton(event);
      this.currentToolBehavior.hideHighlightedPixel(this.overlayFrame);

      this.currentToolBehavior.applyToolAt(
        coords.x,
        coords.y,
        this.getCurrentColor_(),
        frame,
        this.overlayFrame,
        event
      );

      $.publish(Events.LOCALSTORAGE_REQUEST);
    }
  };

  /**
   * @private
   */
  ns.DrawingController.prototype.onMousemove_ = function (event) {
    var currentTime = new Date().getTime();
    // Throttling of the mousemove event:

    if ((currentTime - this.previousMousemoveTime) > Constants.MOUSEMOVE_THROTTLING ) {
      var coords = this.renderer.getCoordinates(event.clientX, event.clientY);

      if (this.isClicked) {
        // Warning : do not call setCurrentButton here
        // mousemove do not have the correct mouse button information on all browsers
        this.currentToolBehavior.moveToolAt(
          coords.x,
          coords.y,
          this.getCurrentColor_(event),
          this.piskelController.getCurrentFrame(),
          this.overlayFrame,
          event
        );

        // TODO(vincz): Find a way to move that to the model instead of being at the interaction level.
        // Eg when drawing, it may make sense to have it here. However for a non drawing tool,
        // you don't need to draw anything when mousemoving and you request useless localStorage.
        $.publish(Events.LOCALSTORAGE_REQUEST);
      } else {

        this.currentToolBehavior.moveUnactiveToolAt(
          coords.x,
          coords.y,
          this.getCurrentColor_(event),
          this.piskelController.getCurrentFrame(),
          this.overlayFrame,
          event
        );
      }
      this.previousMousemoveTime = currentTime;
    }
  };

  ns.DrawingController.prototype.onMousewheel_ = function (jQueryEvent) {
    var event = jQueryEvent.originalEvent;
    var delta = event.wheelDeltaY || (-2 * event.deltaY);
    var currentZoom = this.renderer.getZoom();

    var perfectZoom = this.calculateZoom_();
    var step = perfectZoom / 10;

    if (delta > 0) {
      this.compositeRenderer.setZoom(currentZoom + step);
    } else if (delta < 0) {
      this.compositeRenderer.setZoom(currentZoom - step);
    }
    $.publish(Events.ZOOM_CHANGED);
  };

  /**
   * @private
   */
  ns.DrawingController.prototype.onMouseup_ = function (event) {
    if(this.isClicked) {
      // A mouse button was clicked on the drawing canvas before this mouseup event,
      // the user was probably drawing on the canvas.
      // Note: The mousemove movement (and the mouseup) may end up outside
      // of the drawing canvas.

      this.isClicked = false;
      this.setCurrentButton(event);

      var coords = this.renderer.getCoordinates(event.clientX, event.clientY);
      this.currentToolBehavior.releaseToolAt(
        coords.x,
        coords.y,
        this.getCurrentColor_(),
        this.piskelController.getCurrentFrame(),
        this.overlayFrame,
        event
      );

      $.publish(Events.TOOL_RELEASED);
    }
  };

  /**
   * @private
   */
  ns.DrawingController.prototype.getSpriteCoordinates = function(event) {
    return this.renderer.getCoordinates(event.clientX, event.clientY);
  };

  ns.DrawingController.prototype.setCurrentButton = function (event) {
    this.currentMouseButton_ = event.button;
  };

  /**
   * @private
   */
  ns.DrawingController.prototype.getCurrentColor_ = function () {
    // WARNING : Do not rely on the current event to get the current color!
    // It might seem like a good idea, and works perfectly fine on Chrome
    // Sadly Firefox and IE found clever, for some reason, to set event.button to 0
    // on a mouse move event
    // This always matches a LEFT mouse button which is __really__ not helpful

    if(this.currentMouseButton_ == Constants.RIGHT_BUTTON) {
      return this.paletteController.getSecondaryColor();
    } else if(this.currentMouseButton_ == Constants.LEFT_BUTTON) {
      return this.paletteController.getPrimaryColor();
    } else {
      return Constants.DEFAULT_PEN_COLOR;
    }
  };

  /**
   * @private
   */
  ns.DrawingController.prototype.onCanvasContextMenu_ = function (event) {
    if ($(event.target).closest('#drawing-canvas-container').length) {
      // Deactivate right click on drawing canvas only.
      event.preventDefault();
      event.stopPropagation();
      event.cancelBubble = true;
      return false;
    }
  };

  ns.DrawingController.prototype.render = function () {
    var currentFrame = this.piskelController.getCurrentFrame();
    if (!currentFrame.isSameSize(this.overlayFrame)) {
      this.overlayFrame = pskl.model.Frame.createEmptyFromFrame(currentFrame);
    }

    this.layersRenderer.render();
    this.renderer.render(currentFrame);
    this.overlayRenderer.render(this.overlayFrame);
  };

  /**
   * @private
   */
  ns.DrawingController.prototype.calculateZoom_ = function() {
    var frameHeight = this.piskelController.getCurrentFrame().getHeight(),
        frameWidth = this.piskelController.getCurrentFrame().getWidth();

    return Math.min(this.getAvailableWidth_()/frameWidth, this.getAvailableHeight_()/frameHeight);
  };

  ns.DrawingController.prototype.getAvailableHeight_ = function () {
    return $('#main-wrapper').height();
  };

  ns.DrawingController.prototype.getAvailableWidth_ = function () {
    var leftSectionWidth = $('.left-column').outerWidth(true),
    rightSectionWidth = $('.right-column').outerWidth(true),
    toolsContainerWidth = $('#tool-section').outerWidth(true),
    settingsContainerWidth = $('#application-action-section').outerWidth(true),
    availableWidth = $('#main-wrapper').width() - leftSectionWidth - rightSectionWidth - toolsContainerWidth - settingsContainerWidth;

    return availableWidth-50;
  };

  ns.DrawingController.prototype.getContainerHeight_ = function () {
    return this.calculateZoom_() * this.piskelController.getCurrentFrame().getHeight();
  };

  ns.DrawingController.prototype.getContainerWidth_ = function () {
    return this.calculateZoom_() * this.piskelController.getCurrentFrame().getWidth();
  };

  /**
   * @private
   */
  ns.DrawingController.prototype.centerColumnWrapperHorizontally_ = function() {
    var containerHeight = this.getContainerHeight_();
    var verticalGapInPixel = Math.floor(($('#main-wrapper').height() - containerHeight) / 2);
    $('#column-wrapper').css({
      'top': verticalGapInPixel + 'px'
    });
  };

  ns.DrawingController.prototype.getRenderer = function () {
    return this.compositeRenderer;
  };

  ns.DrawingController.prototype.setOffset = function (x, y) {
    this.compositeRenderer.setOffset(x, y);
    $.publish(Events.ZOOM_CHANGED);
  };
})();<commit_msg>Fix : resize application on startup to adapt correctly to narrow screens<commit_after>(function () {
  var ns = $.namespace("pskl.controller");
  ns.DrawingController = function (piskelController, paletteController, container) {
    /**
     * @public
     */
    this.piskelController = piskelController;

    this.paletteController = paletteController;

    /**
     * @public
     */
    this.overlayFrame = pskl.model.Frame.createEmptyFromFrame(piskelController.getCurrentFrame());

    /**
     * @private
     */
    this.container = container;

    // TODO(vincz): Store user prefs in a localstorage string ?
    var renderingOptions = {
      "zoom": this.calculateZoom_(),
      "supportGridRendering" : true,
      "height" : this.getContainerHeight_(),
      "width" : this.getContainerWidth_(),
      "xOffset" : 0,
      "yOffset" : 0
    };

    this.overlayRenderer = new pskl.rendering.frame.CachedFrameRenderer(this.container, renderingOptions, ["canvas-overlay"]);
    this.renderer = new pskl.rendering.frame.CachedFrameRenderer(this.container, renderingOptions, ["drawing-canvas"]);
    this.layersRenderer = new pskl.rendering.layer.LayersRenderer(this.container, renderingOptions, piskelController);

    this.compositeRenderer = new pskl.rendering.CompositeRenderer();
    this.compositeRenderer
      .add(this.overlayRenderer)
      .add(this.renderer)
      .add(this.layersRenderer);

    // State of drawing controller:
    this.isClicked = false;
    this.previousMousemoveTime = 0;
    this.currentToolBehavior = null;

    // State of clicked button (need to be stateful here, see comment in getCurrentColor_)
    this.currentMouseButton_ = Constants.LEFT_BUTTON;
  };

  ns.DrawingController.prototype.init = function () {
    this.initMouseBehavior();

    $.subscribe(Events.TOOL_SELECTED, $.proxy(function(evt, toolBehavior) {
      this.currentToolBehavior = toolBehavior;
      this.overlayFrame.clear();
    }, this));

    $(window).resize($.proxy(this.startResizeTimer_, this));

    $.subscribe(Events.USER_SETTINGS_CHANGED, $.proxy(this.onUserSettingsChange_, this));
    $.subscribe(Events.FRAME_SIZE_CHANGED, $.proxy(this.onFrameSizeChanged_, this));

    window.setTimeout(this.afterWindowResize_.bind(this), 100);
  };

  ns.DrawingController.prototype.initMouseBehavior = function() {
    var body = $('body');
    this.container.mousedown($.proxy(this.onMousedown_, this));
    this.container.mouseenter($.proxy(this.onMouseenter_, this));
    this.container.mouseleave($.proxy(this.onMouseleave_, this));

    if (pskl.utils.UserAgent.isChrome) {
      this.container.on('mousewheel', $.proxy(this.onMousewheel_, this));
    } else {
      this.container.on('wheel', $.proxy(this.onMousewheel_, this));
    }

    body.mouseup($.proxy(this.onMouseup_, this));

    // Deactivate right click:
    body.contextmenu(this.onCanvasContextMenu_);
  };

  ns.DrawingController.prototype.startResizeTimer_ = function () {
    if (this.resizeTimer) {
      window.clearInterval(this.resizeTimer);
    }
    this.resizeTimer = window.setTimeout($.proxy(this.afterWindowResize_, this), 200);
  };

  ns.DrawingController.prototype.afterWindowResize_ = function () {
    var initialWidth = this.compositeRenderer.getDisplaySize().width;
    this.compositeRenderer.setDisplaySize(this.getContainerWidth_(), this.getContainerHeight_());
    this.centerColumnWrapperHorizontally_();
    var ratio = this.compositeRenderer.getDisplaySize().width / initialWidth;
    var newZoom = ratio * this.compositeRenderer.getZoom();
    this.compositeRenderer.setZoom(newZoom);

    $.publish(Events.ZOOM_CHANGED);
  };

  /**
   * @private
   */
  ns.DrawingController.prototype.onUserSettingsChange_ = function (evt, settingsName, settingsValue) {
    if(settingsName == pskl.UserSettings.SHOW_GRID) {
      console.warn('DrawingController:onUserSettingsChange_ not implemented !');
    }
  };

  ns.DrawingController.prototype.onFrameSizeChanged_ = function () {
    this.compositeRenderer.setDisplaySize(this.getContainerWidth_(), this.getContainerHeight_());
    this.compositeRenderer.setZoom(this.calculateZoom_());
    this.compositeRenderer.setOffset(0, 0);
    $.publish(Events.ZOOM_CHANGED);
  };

  /**
   * @private
   */
  ns.DrawingController.prototype.onMouseenter_ = function (event) {
    this.container.bind('mousemove', $.proxy(this.onMousemove_, this));
  };

  /**
   * @private
   */
  ns.DrawingController.prototype.onMouseleave_ = function (event) {
    this.container.unbind('mousemove');
    this.currentToolBehavior.hideHighlightedPixel(this.overlayFrame);
  };

  /**
   * @private
   */
  ns.DrawingController.prototype.onMousedown_ = function (event) {
    var frame = this.piskelController.getCurrentFrame();
    var coords = this.renderer.getCoordinates(event.clientX, event.clientY);

    if (event.button === Constants.MIDDLE_BUTTON) {
      if (frame.containsPixel(coords.x, coords.y)) {
        $.publish(Events.SELECT_PRIMARY_COLOR, [frame.getPixel(coords.x, coords.y)]);
      }
    } else {
      this.isClicked = true;
      this.setCurrentButton(event);
      this.currentToolBehavior.hideHighlightedPixel(this.overlayFrame);

      this.currentToolBehavior.applyToolAt(
        coords.x,
        coords.y,
        this.getCurrentColor_(),
        frame,
        this.overlayFrame,
        event
      );

      $.publish(Events.LOCALSTORAGE_REQUEST);
    }
  };

  /**
   * @private
   */
  ns.DrawingController.prototype.onMousemove_ = function (event) {
    var currentTime = new Date().getTime();
    // Throttling of the mousemove event:

    if ((currentTime - this.previousMousemoveTime) > Constants.MOUSEMOVE_THROTTLING ) {
      var coords = this.renderer.getCoordinates(event.clientX, event.clientY);

      if (this.isClicked) {
        // Warning : do not call setCurrentButton here
        // mousemove do not have the correct mouse button information on all browsers
        this.currentToolBehavior.moveToolAt(
          coords.x,
          coords.y,
          this.getCurrentColor_(event),
          this.piskelController.getCurrentFrame(),
          this.overlayFrame,
          event
        );

        // TODO(vincz): Find a way to move that to the model instead of being at the interaction level.
        // Eg when drawing, it may make sense to have it here. However for a non drawing tool,
        // you don't need to draw anything when mousemoving and you request useless localStorage.
        $.publish(Events.LOCALSTORAGE_REQUEST);
      } else {

        this.currentToolBehavior.moveUnactiveToolAt(
          coords.x,
          coords.y,
          this.getCurrentColor_(event),
          this.piskelController.getCurrentFrame(),
          this.overlayFrame,
          event
        );
      }
      this.previousMousemoveTime = currentTime;
    }
  };

  ns.DrawingController.prototype.onMousewheel_ = function (jQueryEvent) {
    var event = jQueryEvent.originalEvent;
    var delta = event.wheelDeltaY || (-2 * event.deltaY);
    var currentZoom = this.renderer.getZoom();

    var perfectZoom = this.calculateZoom_();
    var step = perfectZoom / 10;

    if (delta > 0) {
      this.compositeRenderer.setZoom(currentZoom + step);
    } else if (delta < 0) {
      this.compositeRenderer.setZoom(currentZoom - step);
    }
    $.publish(Events.ZOOM_CHANGED);
  };

  /**
   * @private
   */
  ns.DrawingController.prototype.onMouseup_ = function (event) {
    if(this.isClicked) {
      // A mouse button was clicked on the drawing canvas before this mouseup event,
      // the user was probably drawing on the canvas.
      // Note: The mousemove movement (and the mouseup) may end up outside
      // of the drawing canvas.

      this.isClicked = false;
      this.setCurrentButton(event);

      var coords = this.renderer.getCoordinates(event.clientX, event.clientY);
      this.currentToolBehavior.releaseToolAt(
        coords.x,
        coords.y,
        this.getCurrentColor_(),
        this.piskelController.getCurrentFrame(),
        this.overlayFrame,
        event
      );

      $.publish(Events.TOOL_RELEASED);
    }
  };

  /**
   * @private
   */
  ns.DrawingController.prototype.getSpriteCoordinates = function(event) {
    return this.renderer.getCoordinates(event.clientX, event.clientY);
  };

  ns.DrawingController.prototype.setCurrentButton = function (event) {
    this.currentMouseButton_ = event.button;
  };

  /**
   * @private
   */
  ns.DrawingController.prototype.getCurrentColor_ = function () {
    // WARNING : Do not rely on the current event to get the current color!
    // It might seem like a good idea, and works perfectly fine on Chrome
    // Sadly Firefox and IE found clever, for some reason, to set event.button to 0
    // on a mouse move event
    // This always matches a LEFT mouse button which is __really__ not helpful

    if(this.currentMouseButton_ == Constants.RIGHT_BUTTON) {
      return this.paletteController.getSecondaryColor();
    } else if(this.currentMouseButton_ == Constants.LEFT_BUTTON) {
      return this.paletteController.getPrimaryColor();
    } else {
      return Constants.DEFAULT_PEN_COLOR;
    }
  };

  /**
   * @private
   */
  ns.DrawingController.prototype.onCanvasContextMenu_ = function (event) {
    if ($(event.target).closest('#drawing-canvas-container').length) {
      // Deactivate right click on drawing canvas only.
      event.preventDefault();
      event.stopPropagation();
      event.cancelBubble = true;
      return false;
    }
  };

  ns.DrawingController.prototype.render = function () {
    var currentFrame = this.piskelController.getCurrentFrame();
    if (!currentFrame.isSameSize(this.overlayFrame)) {
      this.overlayFrame = pskl.model.Frame.createEmptyFromFrame(currentFrame);
    }

    this.layersRenderer.render();
    this.renderer.render(currentFrame);
    this.overlayRenderer.render(this.overlayFrame);
  };

  /**
   * @private
   */
  ns.DrawingController.prototype.calculateZoom_ = function() {
    var frameHeight = this.piskelController.getCurrentFrame().getHeight(),
        frameWidth = this.piskelController.getCurrentFrame().getWidth();

    return Math.min(this.getAvailableWidth_()/frameWidth, this.getAvailableHeight_()/frameHeight);
  };

  ns.DrawingController.prototype.getAvailableHeight_ = function () {
    return $('#main-wrapper').height();
  };

  ns.DrawingController.prototype.getAvailableWidth_ = function () {
    var leftSectionWidth = $('.left-column').outerWidth(true),
    rightSectionWidth = $('.right-column').outerWidth(true),
    toolsContainerWidth = $('#tool-section').outerWidth(true),
    settingsContainerWidth = $('#application-action-section').outerWidth(true),
    availableWidth = $('#main-wrapper').width() - leftSectionWidth - rightSectionWidth - toolsContainerWidth - settingsContainerWidth;

    var comfortMargin = 10;
    return availableWidth - comfortMargin;
  };

  ns.DrawingController.prototype.getContainerHeight_ = function () {
    return this.calculateZoom_() * this.piskelController.getCurrentFrame().getHeight();
  };

  ns.DrawingController.prototype.getContainerWidth_ = function () {
    return this.calculateZoom_() * this.piskelController.getCurrentFrame().getWidth();
  };

  /**
   * @private
   */
  ns.DrawingController.prototype.centerColumnWrapperHorizontally_ = function() {
    var containerHeight = this.getContainerHeight_();
    var verticalGapInPixel = Math.floor(($('#main-wrapper').height() - containerHeight) / 2);
    $('#column-wrapper').css({
      'top': verticalGapInPixel + 'px'
    });
  };

  ns.DrawingController.prototype.getRenderer = function () {
    return this.compositeRenderer;
  };

  ns.DrawingController.prototype.setOffset = function (x, y) {
    this.compositeRenderer.setOffset(x, y);
    $.publish(Events.ZOOM_CHANGED);
  };
})();<|endoftext|>