<commit_before>var checkin = require('./checkin.js'),
    getDetails = require('./getDetails.js'),
    offer = require('./offers.js'),
    register = require('./register.js'),
    del = require('./del.js'),
    groups = require('./groups.js'),
    update = require('./update.js');

exports.getRoutes = function(server){
    var users = "/users",
        business = "/business",
        offers = '/offers',
        group = '/groups';

   // The way this works by sending a parameter of "business" and looks up how many points to add from couchDB
    server.get({
        path: users + "/test"
    }, function(req, res,next) {
        res.send('works')
        res.end();
    });
    // The way this works by sending a parameter of "business" and looks up how many points to add from couchDB
    server.put({
        path: users + "/checkin"
    }, function(req, res, next) {
        checkin.checkin(req, res, next);
    });
    // Get details for user
    server.get({
        path: users + "/get/:username"
    }, function(req, res, next) {
        getDetails.getDetails(req, res, next, 'users');
    });
    // Get details for business
    server.get({
        path: business + "/get/:businessname"
    }, function(req, res, next) {
        getDetails.getDetails(req, res, next, 'business');
    });
    //Register user
    server.post({
        path: users
    }, function(req, res, next) {
        if(req.authorization.scheme !== 'Basic') {
            return next(new restify.UnauthorizedError('Basic HTTP auth required'));
            failed = true;
        } else {
            register.register(req, res, next, 'users');
        }
    });
    // Register business.
    server.post({
        path: business
    }, function(req, res, next) {
        if(req.authorization.scheme !== 'Basic') {
            return next(new restify.UnauthorizedError('Basic HTTP auth required'));
            failed = true;
        } else {
            register.register(req, res, next, 'business');
        }
    });
    //Update User
    server.put({
        path: users + "/:username"
    }, function(req, res, next) {
        if(req.authorization.scheme !== 'Basic') {
            return next(new restify.UnauthorizedError('Basic HTTP auth required'));
            failed = true;
        } else {
            update.update(req, res, next, 'users');
        }
    });
    //Update Business
    server.put({
        path: business + "/:businessname"
    }, function(req, res, next) {
        if(req.authorization.scheme !== 'Basic') {
            return next(new restify.UnauthorizedError('Basic HTTP auth required'));
            failed = true;
        } else {
            update.update(req, res, next, 'business');
        }
    });
    // Delete user
    server.del({
        path: users
    }, function(req, res, next) {
        del.del(req, res, next, 'users');
    });
    // Delete business
    server.del({
        path: business
    }, function(req, res, next) {
        del.del(req, res, next, 'business');
    });
    server.post({
        path: group
    }, function(req, res, next) {
        groups.groups.createGroup(req, res, next);
    });
    //?username=username&groupname=test21
    server.get({
        path: group +"/:groupname"
    }, function(req, res, next) {
        groups.showgroup(req, res, next);
    });
    //?username=username&competition=freshers
    server.get({
        path: group
    }, function(req, res, next) {

        groups.showcompetitiongroup(req, res, next);
    });
    //?username=username&groupname=test21
    server.put({
        path: users + "/joingroup"
    }, function(req, res, next) {
        groups.joinGroup(req, res, next);
    });
    //Create Offer
    server.post({
        path: business + offers
    }, function(req, res, next) {
        offer.addOffer(req, res, next);
    });
    //Get all Offers
    server.get({
        path: business + offers + '/:businessname'
    }, function(req, res, next) {
        offer.getAllOffers(req, res, next);
    });
    //Redeem Offer
    server.put({
        path: business + offers + '/redeem'
    }, function(req, res, next) {
        offer.redeemOffer(req, res, next);
    });
 }
<commit_msg>changed route for update<commit_after>var checkin = require('./checkin.js'),
    getDetails = require('./getDetails.js'),
    offer = require('./offers.js'),
    register = require('./register.js'),
    del = require('./del.js'),
    groups = require('./groups.js'),
    update = require('./update.js');

exports.getRoutes = function(server){
    var users = "/users",
        business = "/business",
        offers = '/offers',
        group = '/groups';

   // The way this works by sending a parameter of "business" and looks up how many points to add from couchDB
    server.get({
        path: users + "/test"
    }, function(req, res,next) {
        res.send('works')
        res.end();
    });
    // The way this works by sending a parameter of "business" and looks up how many points to add from couchDB
    server.put({
        path: users + "/checkin"
    }, function(req, res, next) {
        checkin.checkin(req, res, next);
    });
    // Get details for user
    server.get({
        path: users + "/get/:username"
    }, function(req, res, next) {
        getDetails.getDetails(req, res, next, 'users');
    });
    // Get details for business
    server.get({
        path: business + "/get/:businessname"
    }, function(req, res, next) {
        getDetails.getDetails(req, res, next, 'business');
    });
    //Register user
    server.post({
        path: users
    }, function(req, res, next) {
        if(req.authorization.scheme !== 'Basic') {
            return next(new restify.UnauthorizedError('Basic HTTP auth required'));
            failed = true;
        } else {
            register.register(req, res, next, 'users');
        }
    });
    // Register business.
    server.post({
        path: business
    }, function(req, res, next) {
        if(req.authorization.scheme !== 'Basic') {
            return next(new restify.UnauthorizedError('Basic HTTP auth required'));
            failed = true;
        } else {
            register.register(req, res, next, 'business');
        }
    });
    //Update User
    server.put({
        path: users + "/:username"
    }, function(req, res, next) {
        if(req.authorization.scheme !== 'Basic') {
            return next(new restify.UnauthorizedError('Basic HTTP auth required'));
            failed = true;
        } else {
            update.update(req, res, next, 'users');
        }
    });
    //Update Business
    server.put({
        path: business + "/:businessname"
    }, function(req, res, next) {
        if(req.authorization.scheme !== 'Basic') {
            return next(new restify.UnauthorizedError('Basic HTTP auth required'));
            failed = true;
        } else {
            update.updateBusiness(req, res, next);
        }
    });
    // Delete user
    server.del({
        path: users
    }, function(req, res, next) {
        del.del(req, res, next, 'users');
    });
    // Delete business
    server.del({
        path: business
    }, function(req, res, next) {
        del.del(req, res, next, 'business');
    });
    server.post({
        path: group
    }, function(req, res, next) {
        groups.groups.createGroup(req, res, next);
    });
    //?username=username&groupname=test21
    server.get({
        path: group +"/:groupname"
    }, function(req, res, next) {
        groups.showgroup(req, res, next);
    });
    //?username=username&competition=freshers
    server.get({
        path: group
    }, function(req, res, next) {

        groups.showcompetitiongroup(req, res, next);
    });
    //?username=username&groupname=test21
    server.put({
        path: users + "/joingroup"
    }, function(req, res, next) {
        groups.joinGroup(req, res, next);
    });
    //Create Offer
    server.post({
        path: business + offers
    }, function(req, res, next) {
        offer.addOffer(req, res, next);
    });
    //Get all Offers
    server.get({
        path: business + offers + '/:businessname'
    }, function(req, res, next) {
        offer.getAllOffers(req, res, next);
    });
    //Redeem Offer
    server.put({
        path: business + offers + '/redeem'
    }, function(req, res, next) {
        offer.redeemOffer(req, res, next);
    });
 }
<|endoftext|>


<commit_before>/* Copyright (c) 2010, Sage Software, Inc. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

define('Sage/Platform/Mobile/Calendar', ['Sage/Platform/Mobile/View'], function() {

    var pad = function(n) { return n < 10 ? '0' + n : n };
    var uCase = function (str) { return str.charAt(0).toUpperCase() + str.substring(1); }

    return dojo.declare('Sage.Platform.Mobile.Calendar', [Sage.Platform.Mobile.View], {
        // Localization
        titleText: 'Calendar',
        amText: 'AM',
        pmText: 'PM',

        id: 'generic_calendar',
        contentNode: null,
        calendarNode: null,
        timeNode: null,
        meridiemNode: null,
        months: Date.CultureInfo.abbreviatedMonthNames,
        dateFormat: Date.CultureInfo.formatPatterns.shortDate,
        timeFormat: Date.CultureInfo.formatPatterns.shortTime,
        is24hrTimeFormat: Date.CultureInfo.formatPatterns.shortTime.match(/H\:/),
        date: false,
        showTimePicker: false,
        selectorTemplate:  '<select id="${0}-field" data-dojo-attach-point="${0}Node"></select>',
        incrementTemplate: '<button data-action="increment${0}" class="button">+</button>',
        decrementTemplate: '<button data-action="decrement${0}" class="button">-</button>',
        widgetTemplate: new Simplate([
            '
',
                '
',
                    '
',
                    '
',
                        '

',
                        '
',
                            '{%= $.localizeViewTemplate("incrementTemplate", 0) %}	',
                            '{%= $.localizeViewTemplate("incrementTemplate", 1) %}	',
                            '{%= $.localizeViewTemplate("incrementTemplate", 2) %}	',
                        '
',
                        '
',
                            '{%= $.localizeViewTemplate("selectorTemplate", 0) %}	',
                            '{%= $.localizeViewTemplate("selectorTemplate", 1) %}	',
                            '{%= $.localizeViewTemplate("selectorTemplate", 2) %}	',
                        '
',
                        '
',
                            '{%= $.localizeViewTemplate("decrementTemplate", 0) %}	',
                            '{%= $.localizeViewTemplate("decrementTemplate", 1) %}	',
                            '{%= $.localizeViewTemplate("decrementTemplate", 2) %}	',
                        '
',
                    '
',
                    '
',
                    '
',
                        '
',
                            '

',
                            '
',
                                '{%= $.localizeViewTemplate("incrementTemplate", 3) %}	',
                                '{%= $.localizeViewTemplate("incrementTemplate", 4) %}	',
                            '
',
                            '
',
                                '{%= $.localizeViewTemplate("selectorTemplate", 3) %}	',
                                '{%= $.localizeViewTemplate("selectorTemplate", 4) %}	',
                                '',
                                    '
',
                                        '
',
                                            '',
                                            '{%= $.amText %}',
                                            '{%= $.pmText %}',
                                        '
',
                                    '
',
                                '	',
                            '
',
                            '
',
                                '{%= $.localizeViewTemplate("decrementTemplate", 3) %}	',
                                '{%= $.localizeViewTemplate("decrementTemplate", 4) %}	',
                            '
',
                        '
',
                    '
',
                    '

',
                '
',
            '
'
        ]),

        daysInMonth: function() {
            var dlo = (1==this.month) ? 28 : 30;
            var dhi = (1==this.month) ? 29 : 31;
            return (new Date(this.year, this.month, dlo).getMonth() == new Date(this.year, this.month, dhi).getMonth())
                ? dhi
                : dlo
                ;
        },
        init: function() {
            this.inherited(arguments);

            dojo.connect(this.dayNode,    'onchange', this, this.validate);
            dojo.connect(this.monthNode,  'onchange', this, this.validate);
            dojo.connect(this.yearNode,   'onchange', this, this.validate);
            dojo.connect(this.hourNode,   'onchange', this, this.validate);
            dojo.connect(this.minuteNode, 'onchange', this, this.validate);
        },

        validate: function() {
            this.year = this.yearNode.value;
            this.month = this.monthNode.value;
            // adjust dayNode selector from changes to monthNode or leap/non-leap year
            if (this.dayNode.options.length != this.daysInMonth()) {
                this.populateSelector(this.dayNode, this.dayNode.selectedIndex + 1, 1, this.daysInMonth());
            }

            this.date = new Date(this.year, this.month, this.dayNode.value),
                isPM = this.is24hrTimeFormat ? (11 < this.hourNode.value) : this.meridiemNode.getAttribute('toggled') !== 'true',
                hours = parseInt(this.hourNode.value, 10),
                minutes = parseInt(this.minuteNode.value, 10);
            hours = isPM ? (hours % 12) + 12 : (hours % 12);
            this.date.setHours(hours);
            this.date.setMinutes(minutes);

            this.updateDatetimeCaption();
        },
        toggleMeridiem: function(params) {
            var el = params.$source,
                toggledValue = el && (el.getAttribute('toggled') !== 'true');

            if (el) el.setAttribute('toggled', toggledValue);
            this.updateDatetimeCaption();
        },
        populateSelector: function(el, val, min, max) {
            if (val > max) { val = max; }
            el.options.length = 0;
            for (var i=min; i <= max; i++) {
                opt = new Option((this.monthNode == el) ? uCase(this.months[i]) : pad(i), i);
                opt.selected = (i == val);
                el.options[el.options.length] = opt;
            }
        },
        localizeViewTemplate: function() {
            var whichTemplate = arguments[0],
                formatIndex = arguments[1],
                fields = { y:'year', M:'month', d:'day', h:'hour', H:'hour', m:'minute' };
            var whichField = fields[ (3 > formatIndex)
                ? this.dateFormat.split(/[^a-z]/i)[formatIndex].charAt(0)
                : Date.CultureInfo.formatPatterns.shortTime.split(/[^a-z]/i)[formatIndex - 3].charAt(0)
                ];
            var whichFormat = ('selectorTemplate' == whichTemplate)
                ? whichField
                : uCase(whichField);

            return dojo.string.substitute(this[whichTemplate], [whichFormat]);
        },
        show: function(options) {
            this.inherited(arguments);

            this.titleText = options.label ? options.label : this.titleText;

            this.showTimePicker = this.options && this.options.showTimePicker;

            this.date  = (this.options && this.options.date) || new Date();
            this.year  = this.date.getFullYear();
            this.month = this.date.getMonth();

            var today = new Date();
            this.populateSelector(this.yearNode, this.year,
                    (this.year < today.getFullYear() ? this.year : today.getFullYear()),
                    (10 + today.getFullYear()) // max 10 years into future - arbitrary limit
            );
            this.populateSelector(this.monthNode, this.month, 0, 11);
            this.populateSelector(this.dayNode, this.date.getDate(), 1, this.daysInMonth());
            this.populateSelector(this.hourNode,
                this.date.getHours() > 12 && !this.is24hrTimeFormat
                    ? this.date.getHours() - 12
                    : (this.date.getHours() || 12),
                this.is24hrTimeFormat ? 0 : 1,
                this.is24hrTimeFormat ? 23 : 12
            );
            this.populateSelector(this.minuteNode, this.date.getMinutes(), 0, 59);
            this.meridiemNode.setAttribute('toggled', this.date.getHours() < 12);

            this.updateDatetimeCaption();

            if (this.showTimePicker) {
                dojo.removeClass(this.timeNode, 'time-content-hidden');
                // hide meridiem toggle when using 24hr time format:
                if (this.is24hrTimeFormat) { this.meridiemNode.parentNode.style.display='none'; }
            } else {
                dojo.addClass(this.timeNode, 'time-content-hidden');
            }
        },

        decrementYear: function() { this.decrement(this.yearNode); },
        decrementMonth: function() { this.decrement(this.monthNode); },
        decrementDay: function() { this.decrement(this.dayNode); },
        decrementHour: function() {
            this.decrement(this.hourNode);
            if (11 == this.hourNode.value % 12) {
                this.toggleMeridiem({$source:this.meridiemNode});
            }
        },
        decrementMinute: function() { this.decrement(this.minuteNode, 15); },
        decrement: function(el, inc) { // all fields are <select> elements
            var inc = inc || 1;
            if (0 <= (el.selectedIndex - inc)) {
                el.selectedIndex = inc * Math.floor((el.selectedIndex -1)/ inc);
            } else {
                if (el == this.yearNode)   { return false; }
                if (el == this.dayNode)    { this.decrementMonth(); }
                if (el == this.monthNode)  { this.decrementYear();  }
                if (el == this.minuteNode) { this.decrementHour();  }
                el.selectedIndex = el.options.length - inc;
            }
            this.validate(null,el);
        },

        incrementYear: function() { this.increment(this.yearNode); },
        incrementMonth: function() { this.increment(this.monthNode); },
        incrementDay: function() { this.increment(this.dayNode); },
        incrementHour: function() {
            this.increment(this.hourNode);
            if (this.hourNode.selectedIndex == (this.hourNode.options.length - 1)) {
                this.toggleMeridiem({$source:this.meridiemNode});
            }
        },
        incrementMinute: function() { this.increment(this.minuteNode, 15); },
        increment: function(el, inc) {
            var inc = inc || 1;
            if (el.options.length > (el.selectedIndex + inc)) {
                el.selectedIndex += inc;
            } else {
                if (el == this.yearNode) { return false; }
                if (el == this.dayNode) { this.incrementMonth(); }
                if (el == this.monthNode)  { this.incrementYear(); }
                if (el == this.minuteNode) { this.incrementHour(); }
                el.selectedIndex = 0;
            }
            this.validate(null,el);
        },
        updateDatetimeCaption: function() {
            var t = this.getDateTime();
            this.datePickControl.caption.innerHTML = t.toString('dddd'); // weekday text
            if (this.showTimePicker) {
                this.timePickControl.caption.innerHTML = t.toString(this.timeFormat);
            }
        },
        getDateTime: function() {
            var result = new Date(this.date.getTime()),
                isPM = this.is24hrTimeFormat ? (11 < this.hourNode.value) : this.meridiemNode.getAttribute('toggled') !== 'true',
                hours = parseInt(this.hourNode.value, 10),
                minutes = parseInt(this.minuteNode.value, 10);

            hours = isPM
                ? (hours % 12) + 12
                : (hours % 12);

            result.setHours(hours);
            result.setMinutes(minutes);

            return result;
        }
    });
});<commit_msg>vertical ampm control<commit_after>/* Copyright (c) 2010, Sage Software, Inc. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

define('Sage/Platform/Mobile/Calendar', ['Sage/Platform/Mobile/View'], function() {

    var pad = function(n) { return n < 10 ? '0' + n : n };
    var uCase = function (str) { return str.charAt(0).toUpperCase() + str.substring(1); }

    return dojo.declare('Sage.Platform.Mobile.Calendar', [Sage.Platform.Mobile.View], {
        // Localization
        titleText: 'Calendar',
        amText: 'AM',
        pmText: 'PM',

        id: 'generic_calendar',
        contentNode: null,
        calendarNode: null,
        timeNode: null,
        meridiemNode: null,
        months: Date.CultureInfo.abbreviatedMonthNames,
        dateFormat: Date.CultureInfo.formatPatterns.shortDate,
        timeFormat: Date.CultureInfo.formatPatterns.shortTime,
        is24hrTimeFormat: Date.CultureInfo.formatPatterns.shortTime.match(/H\:/),
        date: false,
        showTimePicker: false,
        selectorTemplate:  '<select id="${0}-field" data-dojo-attach-point="${0}Node"></select>',
        incrementTemplate: '<button data-action="increment${0}" class="button">+</button>',
        decrementTemplate: '<button data-action="decrement${0}" class="button">-</button>',
        widgetTemplate: new Simplate([
            '
',
                '
',
                    '
',
                    '
',
                        '

',
                        '
',
                            '{%= $.localizeViewTemplate("incrementTemplate", 0) %}	',
                            '{%= $.localizeViewTemplate("incrementTemplate", 1) %}	',
                            '{%= $.localizeViewTemplate("incrementTemplate", 2) %}	',
                        '
',
                        '
',
                            '{%= $.localizeViewTemplate("selectorTemplate", 0) %}	',
                            '{%= $.localizeViewTemplate("selectorTemplate", 1) %}	',
                            '{%= $.localizeViewTemplate("selectorTemplate", 2) %}	',
                        '
',
                        '
',
                            '{%= $.localizeViewTemplate("decrementTemplate", 0) %}	',
                            '{%= $.localizeViewTemplate("decrementTemplate", 1) %}	',
                            '{%= $.localizeViewTemplate("decrementTemplate", 2) %}	',
                        '
',
                    '
',
                    '
',
                    '
',
                        '
',
                            '

',
                            '
',
                                '{%= $.localizeViewTemplate("incrementTemplate", 3) %}	',
                                '{%= $.localizeViewTemplate("incrementTemplate", 4) %}	',
                                '',
                                    '
',
                                        '',
                                        '{%= $.amText %}',
                                        '{%= $.pmText %}',
                                    '
',
                                '	',
                            '
',
                            '
',
                                '{%= $.localizeViewTemplate("selectorTemplate", 3) %}	',
                                '{%= $.localizeViewTemplate("selectorTemplate", 4) %}	',
                            '
',
                            '
',
                                '{%= $.localizeViewTemplate("decrementTemplate", 3) %}	',
                                '{%= $.localizeViewTemplate("decrementTemplate", 4) %}	',
                            '
',
                        '
',
                    '
',
                    '

',
                '
',
            '
'
        ]),

        daysInMonth: function() {
            var dlo = (1==this.month) ? 28 : 30;
            var dhi = (1==this.month) ? 29 : 31;
            return (new Date(this.year, this.month, dlo).getMonth() == new Date(this.year, this.month, dhi).getMonth())
                ? dhi
                : dlo
                ;
        },
        init: function() {
            this.inherited(arguments);

            dojo.connect(this.dayNode,    'onchange', this, this.validate);
            dojo.connect(this.monthNode,  'onchange', this, this.validate);
            dojo.connect(this.yearNode,   'onchange', this, this.validate);
            dojo.connect(this.hourNode,   'onchange', this, this.validate);
            dojo.connect(this.minuteNode, 'onchange', this, this.validate);
        },

        validate: function() {
            this.year = this.yearNode.value;
            this.month = this.monthNode.value;
            // adjust dayNode selector from changes to monthNode or leap/non-leap year
            if (this.dayNode.options.length != this.daysInMonth()) {
                this.populateSelector(this.dayNode, this.dayNode.selectedIndex + 1, 1, this.daysInMonth());
            }

            this.date = new Date(this.year, this.month, this.dayNode.value),
                isPM = this.is24hrTimeFormat ? (11 < this.hourNode.value) : this.meridiemNode.getAttribute('toggled') !== 'true',
                hours = parseInt(this.hourNode.value, 10),
                minutes = parseInt(this.minuteNode.value, 10);
            hours = isPM ? (hours % 12) + 12 : (hours % 12);
            this.date.setHours(hours);
            this.date.setMinutes(minutes);

            this.updateDatetimeCaption();
        },
        toggleMeridiem: function(params) {
            var el = params.$source,
                toggledValue = el && (el.getAttribute('toggled') !== 'true');

            if (el) el.setAttribute('toggled', toggledValue);
            this.updateDatetimeCaption();
        },
        populateSelector: function(el, val, min, max) {
            if (val > max) { val = max; }
            el.options.length = 0;
            for (var i=min; i <= max; i++) {
                opt = new Option((this.monthNode == el) ? uCase(this.months[i]) : pad(i), i);
                opt.selected = (i == val);
                el.options[el.options.length] = opt;
            }
        },
        localizeViewTemplate: function() {
            var whichTemplate = arguments[0],
                formatIndex = arguments[1],
                fields = { y:'year', M:'month', d:'day', h:'hour', H:'hour', m:'minute' };
            var whichField = fields[ (3 > formatIndex)
                ? this.dateFormat.split(/[^a-z]/i)[formatIndex].charAt(0)
                : Date.CultureInfo.formatPatterns.shortTime.split(/[^a-z]/i)[formatIndex - 3].charAt(0)
                ];
            var whichFormat = ('selectorTemplate' == whichTemplate)
                ? whichField
                : uCase(whichField);

            return dojo.string.substitute(this[whichTemplate], [whichFormat]);
        },
        show: function(options) {
            this.inherited(arguments);

            this.titleText = options.label ? options.label : this.titleText;

            this.showTimePicker = this.options && this.options.showTimePicker;

            this.date  = (this.options && this.options.date) || new Date();
            this.year  = this.date.getFullYear();
            this.month = this.date.getMonth();

            var today = new Date();
            this.populateSelector(this.yearNode, this.year,
                    (this.year < today.getFullYear() ? this.year : today.getFullYear()),
                    (10 + today.getFullYear()) // max 10 years into future - arbitrary limit
            );
            this.populateSelector(this.monthNode, this.month, 0, 11);
            this.populateSelector(this.dayNode, this.date.getDate(), 1, this.daysInMonth());
            this.populateSelector(this.hourNode,
                this.date.getHours() > 12 && !this.is24hrTimeFormat
                    ? this.date.getHours() - 12
                    : (this.date.getHours() || 12),
                this.is24hrTimeFormat ? 0 : 1,
                this.is24hrTimeFormat ? 23 : 12
            );
            this.populateSelector(this.minuteNode, this.date.getMinutes(), 0, 59);
            this.meridiemNode.setAttribute('toggled', this.date.getHours() < 12);

            this.updateDatetimeCaption();

            if (this.showTimePicker) {
                dojo.removeClass(this.timeNode, 'time-content-hidden');
                // hide meridiem toggle when using 24hr time format:
                if (this.is24hrTimeFormat) { this.meridiemNode.parentNode.style.display='none'; }
            } else {
                dojo.addClass(this.timeNode, 'time-content-hidden');
            }
        },

        decrementYear: function() { this.decrement(this.yearNode); },
        decrementMonth: function() { this.decrement(this.monthNode); },
        decrementDay: function() { this.decrement(this.dayNode); },
        decrementHour: function() {
            this.decrement(this.hourNode);
            if (11 == this.hourNode.value % 12) {
                this.toggleMeridiem({$source:this.meridiemNode});
            }
        },
        decrementMinute: function() { this.decrement(this.minuteNode, 15); },
        decrement: function(el, inc) { // all fields are <select> elements
            var inc = inc || 1;
            if (0 <= (el.selectedIndex - inc)) {
                el.selectedIndex = inc * Math.floor((el.selectedIndex -1)/ inc);
            } else {
                if (el == this.yearNode)   { return false; }
                if (el == this.dayNode)    { this.decrementMonth(); }
                if (el == this.monthNode)  { this.decrementYear();  }
                if (el == this.minuteNode) { this.decrementHour();  }
                el.selectedIndex = el.options.length - inc;
            }
            this.validate(null,el);
        },

        incrementYear: function() { this.increment(this.yearNode); },
        incrementMonth: function() { this.increment(this.monthNode); },
        incrementDay: function() { this.increment(this.dayNode); },
        incrementHour: function() {
            this.increment(this.hourNode);
            if (this.hourNode.selectedIndex == (this.hourNode.options.length - 1)) {
                this.toggleMeridiem({$source:this.meridiemNode});
            }
        },
        incrementMinute: function() { this.increment(this.minuteNode, 15); },
        increment: function(el, inc) {
            var inc = inc || 1;
            if (el.options.length > (el.selectedIndex + inc)) {
                el.selectedIndex += inc;
            } else {
                if (el == this.yearNode) { return false; }
                if (el == this.dayNode) { this.incrementMonth(); }
                if (el == this.monthNode)  { this.incrementYear(); }
                if (el == this.minuteNode) { this.incrementHour(); }
                el.selectedIndex = 0;
            }
            this.validate(null,el);
        },
        updateDatetimeCaption: function() {
            var t = this.getDateTime();
            this.datePickControl.caption.innerHTML = t.toString('dddd'); // weekday text
            if (this.showTimePicker) {
                this.timePickControl.caption.innerHTML = t.toString(this.timeFormat);
            }
        },
        getDateTime: function() {
            var result = new Date(this.date.getTime()),
                isPM = this.is24hrTimeFormat ? (11 < this.hourNode.value) : this.meridiemNode.getAttribute('toggled') !== 'true',
                hours = parseInt(this.hourNode.value, 10),
                minutes = parseInt(this.minuteNode.value, 10);

            hours = isPM
                ? (hours % 12) + 12
                : (hours % 12);

            result.setHours(hours);
            result.setMinutes(minutes);

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


<commit_before>/*jshint -W054 */
(function (exports) {
  'use strict';

  var rrkeys
    , localeWarn1 = true
    , localeWarn2 = true
    ;

  rrkeys = [
    'FREQ'

  , 'INTERVAL'
  , 'UNTIL'
  , 'COUNT'

  , 'BYWEEKNO'
  , 'BYYEARDAY'
  , 'BYDAY'
  , 'BYMONTH'
  , 'BYMONTHDAY'
  , 'BYHOUR'
  , 'BYMINUTE'
  , 'BYSECOND'

  , 'WKST'
  , 'BYSETPOS'

  , 'DTSTART' // non-standard as part of this string, but used by rrule
  ]
  ;

  function pad(str, len, padchar, rpad) {
    if ('number' === typeof str) {
      padchar = padchar || '0';
    } else if ('string' === typeof str) {
      padchar = padchar || ' ';
    }
    str = str.toString();
    while (str.length < len) {
      if (rpad) {
        str += padchar;
      } else {
        str = padchar + str;
      }
    }
    return str;
  }

  function Rrecur(rules, date) {
    var me = this
      ;

    if (!(me instanceof Rrecur)) {
      return new Rrecur(rules, date);
    }

    me.init(rules, date);
  }

  Rrecur.toAdjustedISOString = function (date, locale) {
    locale = Rrecur.getLocaleFromGmtString(locale.toString());
    return new Date(Rrecur.toLocaleISOString(date, locale)).toISOString();
  };

  Rrecur.toLocaleISOString = function (date, useoffset) {
    // This outputs local time in ISO format with a UTC offset
    var str
      ;

    // YYYY-MM-DDTHH:MM:SS.sss+nnnn
    // d.getTimezoneOffset()
    str = date.getFullYear()
      + '-'
      + pad(date.getMonth() + 1, 2, '0')
      + '-'
      + pad(date.getDate(), 2, '0')
      + 'T'
      + pad(date.getHours(), 2, '0')
      + ':'
      + pad(date.getMinutes(), 2, '0')
      + ':'
      + pad(date.getSeconds(), 2, '0')
      + '.'
      + pad(date.getMilliseconds(), 3, '0')
      ;

    if ('undefined' === typeof useoffset) {
      useoffset = true;
    }

    if ('boolean' !== typeof useoffset) {
      // perhaps GMT-0600 (MDT) or just -0600
      str += Rrecur.getOffsetFromLocale(useoffset);
    } else {
      // GMT-0400 (MDT) => -0400
      // -04:00 => -0400
      str += date
        .toString()
        .replace(/.*GMT([+\-]\d{2}:?\d{2})\s.*/, '$1')
        .replace(/:/, '')
        ;
    }

    return str;
  };

  function parseDateStr(vstr) {
    return vstr.replace(/-/, '').replace(/:/, '').replace(/Z.*/, 'Z');
  }

  Rrecur.toRruleDateString = function (vstr) {
    if ('object' === typeof vstr) {
      // TODO timezone
      vstr = parseDateStr(Rrecur.toLocaleISOString(vstr, false));
    }
    if ('string' === typeof vstr) {
      vstr = parseDateStr(vstr);
    }
    var m
      , str
      ;

    m = /(\d{4,4})(\d{2,2})(\d{2,2})(T(\d{2,2})(\d{2,2})(\d{2,2})(Z)?)?$/.exec(vstr);

    if (!m) {
      return '';
    }

    str = m[1] + '-' + m[2] + '-' + m[3];

    // TODO handle local time
    // TODO handle tz DTSTART;TZID=US-Eastern:19970714T133000
    if (m[4]) {
      str += 'T' + m[5] + ':' + m[6] + ':' + m[7] + '.000' + (m[8] || '');
    }

    return str;
  };

  // DTSTART is not part of RRULE
  function parse(str) {
    str = str.replace(/\n/, ';');
    str = str.replace(/RRULE:/, '');
    str = str.replace(/DTSTART;/, 'DTSTART__SEMI__');
    var pairs = str.split(';')
      , obj = {}
      ;

    pairs.forEach(function (pair) {
      pair = pair.replace(/DTSTART__SEMI__/, 'DTSTART;');
      var parts = pair.split('=')
        , k = parts[0]
        , ks
        , param
        , tzid
        , vstr = parts[1]
        , v
        ;

      // Handle case of DTSTART;TZID=US-Eastern:{{yyyymmddThhmmss}} // NO Z ALLOWED
      ks = k.split(';');
      k = ks[0];

      // TZID exists
      if ('TZID' === ks[1]) {
        param = ks[1].split(':');
        tzid = param[0];
        obj.tzid = tzid;
        v = param[1];
      }

      // Handle case of DTSTART;LOCALE=GMT-0600 (MDT):{{yyyymmddThhmmss}} // NO Z ALLOWED
      // obj.locale = obj.locale || stringifyGmtZone(obj.dtstart);
      if ('LOCALE' === ks[1]) {
        if (localeWarn2) {
          console.warn('[parse] falling back to non-standard locale definition for timezone');
          localeWarn2 = false;
        }
        param = vstr.split(':');
        obj.locale = param[0];

        // Continue with DTSTART
        k = ks[0];
        vstr = v = param[1];
      }

      switch (k) {
      case 'DTSTART':
      case 'UNTIL':
        v = Rrecur.toRruleDateString(vstr);
        break;
      case 'FREQ':
      case 'WKST':
        v = vstr.toLowerCase();
        break;
      case 'INTERVAL':
      case 'COUNT':
        v = vstr;
        break;
      case 'BYWEEKDAY':
        console.warn('converting rrule.js BYWEEKDAY to rrule rfc BYDAY');
        k = 'BYDAY';
        /* fall through */
      case 'BYSETPOS':
      case 'BYYEARDAY':
      case 'BYMONTH':
      case 'BYWEEKNO':
      case 'BYDAY':
      case 'BYMONTHDAY':
      case 'BYHOUR':
      case 'BYMINUTE':
      case 'BYSECOND':
      case 'BYEASTER':
        v = vstr.split(',');
        v.forEach(function (val, i) {
          v[i] = val.toLowerCase();
        });
        break;
      }

      obj[k.toLowerCase()] = v;
    });

    return obj;
  }

  function stringifyGmtZone(date) {
    if ('string' === typeof date) {
      date = stringifyDateStr(date);
    }
    if ('object' !== typeof date) {
      date = new Date(date);
    }
    return Rrecur.getLocaleFromGmtString(date.toString());
  }
  Rrecur.stringifyGmtZone = stringifyGmtZone;
  Rrecur.getLocaleFromGmtString = function (locale) {
    // 'Mon Jun 23 2014 10:30:00 GMT-0600 (MDT)' => 'GMT-0600 (MDT)'
    // 'Mon Jun 23 2014 10:30:00 GMT-0600' => 'GMT-0600'
    // 'GMT-0600 (MDT)' => 'GMT-0600 (MDT)'
    // '-0600 (MDT)' => 'GMT-0600 (MDT)'
    // 'GMT-0600' => 'GMT-0600'
    // '-0600' => 'GMT-0600'
    return locale
      .replace(/.*(?:GMT)?([\-+]\d{2}):?(00)(\s\(\w{1,6}\))?$/g, 'GMT$1$2$3')
      ;
  };
  Rrecur.swapLocale = function (date, locale) {
    return date
      .toString()
      .replace(/(.*)GMT.*$/g, '$1' + locale)
      ;
  };
  Rrecur.getOffsetFromLocale = function (locale) {
    // GMT-0600 (MDT) => -0600
    // -0600 (MDT) => -0600
    // GMT-0600 => -0600
    // -0600 => -0600
    return locale
      .toString()
      .replace(/.*(?:GMT)?([\-+]\d{2}):?(00)\s?(\(\w{1,6}\))?$/g, '$1$2') // $3 is EST/MDT/etc
      ;
  };
  Rrecur.swapOffset = function (date, locale) {
    return date
      .toString()
      .replace(/(.*)GMT.*$/g, '$1' + Rrecur.getOffsetFromLocale(locale))
      ;
  };

  function stringifyDateStr(str) {
    return str.replace(
      /(\d{4})-?(\d{2})-?(\d{2})T(\d{2}):?(\d{2}):?(\d{2})(?:\.\d+)?([-+Z]\d*)?(.*)/
    , "$1-$2-$3T$4:$5:$6$7$8"
    );
  }
  function stringifyRruleDate(v, forceZ) {
    if ('number' === typeof v) {
      v = Rrecur.toLocaleISOString(new Date(v), false);
    } else if ('object' === typeof v) {
      v = Rrecur.toLocaleISOString(v, false);
    }

    if (forceZ && !/Z/.test(v)) {
      if ('string' === typeof forceZ) {
        v = new Date(v + forceZ).toISOString();
      } else {
        v = v += 'Z';
      }
    }

    v = v
      .replace(/[\-+]\d{4}(\s \(\w{1,6}\))?$/, '')
      .replace(/\-|:/g, '')
      .replace(/\.\d+/, '')
      ;

    return v;
  }
  Rrecur.stringify = function (orig) {
    var pairs = []
      , lkeys
      , obj = {}
      ;

    Object.keys(orig).forEach(function (k) {
      obj[k] = orig[k];
    });

    if (obj.tzid) {
      console.error('[stringify] tzid not yet supported');
      //pairs.push('DTSTART;TZID' + '=' + obj.tzid + ':' + stringifyRruleDate(obj.dtstart));
      //delete obj.dtstart;
      //delete obj.tzid;
    }

    if (obj.dtstart) {
      if (localeWarn1) {
        console.warn('[stringify] falling back to non-standard locale definition for timezone');
        localeWarn1 = false;
      }

      if (obj.locale) {
        if (!/UTC/.test(obj.locale)) {
          pairs.push('DTSTART;LOCALE' + '=' + obj.locale + ':' + stringifyRruleDate(obj.dtstart));
          delete obj.dtstart;
        }
        delete obj.locale;
      }
    }

    // compensate for RRULE.js non-standardness
    // (although it does happen to make more sense than the standard)
    if (obj.byweekday) {
      console.warn('converting rrule.js obj.byweekday to rrule rfc obj.byday');
      obj.byday = obj.byweekday;
      delete obj.byweekday;
    }

    lkeys = Object.keys(obj);

    // http://www.ietf.org/rfc/rfc2445.txt
    // 4.3.10 Recurrence Rule
    lkeys.forEach(function (k) {
      var v
        , vs
        ;

      v = obj[k.toLowerCase()];
      k = k.toUpperCase();

      if (!v) {
        return;
      }

      if ('UNTIL' === k || 'DTSTART' === k) {
        v = stringifyRruleDate(v, Rrecur.getOffsetFromLocale(obj.locale || new Date()));
      }

      if (Array.isArray(v)) {
        vs = [];
        v.forEach(function (val) {
          if ('string' === typeof val) {
            val = val.toUpperCase();
          }
          vs.push(val);
        });
        v = vs;
      } else if ('string' === typeof v) {
        v = v.toUpperCase();
      }
      // if array, it'll join with ',' automatically
      pairs.push(k + '=' + v);
    });

    return pairs.join(';');
  };

  // TODO timezone support (in dtstart)? // -0400 +0530
  function defaults(freq, dtstart, rrule/*, tzoffset*/) {
    rrule = rrule || {};

    if ('object' !== typeof dtstart) {
      if ('string' === typeof dtstart) {
        dtstart = stringifyDateStr(dtstart);
      }
      dtstart = new Date(dtstart);
    }
    switch(freq) {
      case 'secondly':
        break;
      case 'minutely':
        if (!rrule.bysecond) {
          rrule.bysecond = [dtstart.getUTCSeconds()];
        }
        /* falls through */
      case 'hourly':
        if (!rrule.byminute) {
          rrule.byminute = [dtstart.getUTCMinutes()];
        }
        /* falls through */
      case 'daily':
        if (!rrule.byhour) {
          rrule.byhour = [dtstart.getUTCHours()];
        }
        /* falls through */
      case 'weekly':
        if (!rrule.byday) {
          rrule.byday = [Rrecur.weekdays[dtstart.getUTCDay()]];
        }
        /* falls through */
      case 'monthly':
        if (!rrule.bymonthday) {
          rrule.bymonthday = [dtstart.getUTCDate()];
        }
        /* falls through */
      case 'yearly':
        if (!rrule.bymonth) {
          rrule.bymonth = [dtstart.getUTCMonth() + 1];
        }
        /* falls through */
    }

    return rrule;
  }
  Rrecur.create = Rrecur;

  exports.Rrecur = Rrecur;
  exports.Rrecur.parse = parse;
  exports.Rrecur.parseDtstart = Rrecur.toRruleDateString;
  exports.Rrecur.weekdays = ['su','mo','tu','we','th','fi','sa','su']; // sunday is 0 and 7
  exports.Rrecur.dtstartDefaults = defaults;
}('undefined' !== typeof exports && exports || new Function('return this')()));
<commit_msg>rrecur.js: Correct 'fi' to the proper 'fr'<commit_after>/*jshint -W054 */
(function (exports) {
  'use strict';

  var rrkeys
    , localeWarn1 = true
    , localeWarn2 = true
    ;

  rrkeys = [
    'FREQ'

  , 'INTERVAL'
  , 'UNTIL'
  , 'COUNT'

  , 'BYWEEKNO'
  , 'BYYEARDAY'
  , 'BYDAY'
  , 'BYMONTH'
  , 'BYMONTHDAY'
  , 'BYHOUR'
  , 'BYMINUTE'
  , 'BYSECOND'

  , 'WKST'
  , 'BYSETPOS'

  , 'DTSTART' // non-standard as part of this string, but used by rrule
  ]
  ;

  function pad(str, len, padchar, rpad) {
    if ('number' === typeof str) {
      padchar = padchar || '0';
    } else if ('string' === typeof str) {
      padchar = padchar || ' ';
    }
    str = str.toString();
    while (str.length < len) {
      if (rpad) {
        str += padchar;
      } else {
        str = padchar + str;
      }
    }
    return str;
  }

  function Rrecur(rules, date) {
    var me = this
      ;

    if (!(me instanceof Rrecur)) {
      return new Rrecur(rules, date);
    }

    me.init(rules, date);
  }

  Rrecur.toAdjustedISOString = function (date, locale) {
    locale = Rrecur.getLocaleFromGmtString(locale.toString());
    return new Date(Rrecur.toLocaleISOString(date, locale)).toISOString();
  };

  Rrecur.toLocaleISOString = function (date, useoffset) {
    // This outputs local time in ISO format with a UTC offset
    var str
      ;

    // YYYY-MM-DDTHH:MM:SS.sss+nnnn
    // d.getTimezoneOffset()
    str = date.getFullYear()
      + '-'
      + pad(date.getMonth() + 1, 2, '0')
      + '-'
      + pad(date.getDate(), 2, '0')
      + 'T'
      + pad(date.getHours(), 2, '0')
      + ':'
      + pad(date.getMinutes(), 2, '0')
      + ':'
      + pad(date.getSeconds(), 2, '0')
      + '.'
      + pad(date.getMilliseconds(), 3, '0')
      ;

    if ('undefined' === typeof useoffset) {
      useoffset = true;
    }

    if ('boolean' !== typeof useoffset) {
      // perhaps GMT-0600 (MDT) or just -0600
      str += Rrecur.getOffsetFromLocale(useoffset);
    } else {
      // GMT-0400 (MDT) => -0400
      // -04:00 => -0400
      str += date
        .toString()
        .replace(/.*GMT([+\-]\d{2}:?\d{2})\s.*/, '$1')
        .replace(/:/, '')
        ;
    }

    return str;
  };

  function parseDateStr(vstr) {
    return vstr.replace(/-/, '').replace(/:/, '').replace(/Z.*/, 'Z');
  }

  Rrecur.toRruleDateString = function (vstr) {
    if ('object' === typeof vstr) {
      // TODO timezone
      vstr = parseDateStr(Rrecur.toLocaleISOString(vstr, false));
    }
    if ('string' === typeof vstr) {
      vstr = parseDateStr(vstr);
    }
    var m
      , str
      ;

    m = /(\d{4,4})(\d{2,2})(\d{2,2})(T(\d{2,2})(\d{2,2})(\d{2,2})(Z)?)?$/.exec(vstr);

    if (!m) {
      return '';
    }

    str = m[1] + '-' + m[2] + '-' + m[3];

    // TODO handle local time
    // TODO handle tz DTSTART;TZID=US-Eastern:19970714T133000
    if (m[4]) {
      str += 'T' + m[5] + ':' + m[6] + ':' + m[7] + '.000' + (m[8] || '');
    }

    return str;
  };

  // DTSTART is not part of RRULE
  function parse(str) {
    str = str.replace(/\n/, ';');
    str = str.replace(/RRULE:/, '');
    str = str.replace(/DTSTART;/, 'DTSTART__SEMI__');
    var pairs = str.split(';')
      , obj = {}
      ;

    pairs.forEach(function (pair) {
      pair = pair.replace(/DTSTART__SEMI__/, 'DTSTART;');
      var parts = pair.split('=')
        , k = parts[0]
        , ks
        , param
        , tzid
        , vstr = parts[1]
        , v
        ;

      // Handle case of DTSTART;TZID=US-Eastern:{{yyyymmddThhmmss}} // NO Z ALLOWED
      ks = k.split(';');
      k = ks[0];

      // TZID exists
      if ('TZID' === ks[1]) {
        param = ks[1].split(':');
        tzid = param[0];
        obj.tzid = tzid;
        v = param[1];
      }

      // Handle case of DTSTART;LOCALE=GMT-0600 (MDT):{{yyyymmddThhmmss}} // NO Z ALLOWED
      // obj.locale = obj.locale || stringifyGmtZone(obj.dtstart);
      if ('LOCALE' === ks[1]) {
        if (localeWarn2) {
          console.warn('[parse] falling back to non-standard locale definition for timezone');
          localeWarn2 = false;
        }
        param = vstr.split(':');
        obj.locale = param[0];

        // Continue with DTSTART
        k = ks[0];
        vstr = v = param[1];
      }

      switch (k) {
      case 'DTSTART':
      case 'UNTIL':
        v = Rrecur.toRruleDateString(vstr);
        break;
      case 'FREQ':
      case 'WKST':
        v = vstr.toLowerCase();
        break;
      case 'INTERVAL':
      case 'COUNT':
        v = vstr;
        break;
      case 'BYWEEKDAY':
        console.warn('converting rrule.js BYWEEKDAY to rrule rfc BYDAY');
        k = 'BYDAY';
        /* fall through */
      case 'BYSETPOS':
      case 'BYYEARDAY':
      case 'BYMONTH':
      case 'BYWEEKNO':
      case 'BYDAY':
      case 'BYMONTHDAY':
      case 'BYHOUR':
      case 'BYMINUTE':
      case 'BYSECOND':
      case 'BYEASTER':
        v = vstr.split(',');
        v.forEach(function (val, i) {
          v[i] = val.toLowerCase();
        });
        break;
      }

      obj[k.toLowerCase()] = v;
    });

    return obj;
  }

  function stringifyGmtZone(date) {
    if ('string' === typeof date) {
      date = stringifyDateStr(date);
    }
    if ('object' !== typeof date) {
      date = new Date(date);
    }
    return Rrecur.getLocaleFromGmtString(date.toString());
  }
  Rrecur.stringifyGmtZone = stringifyGmtZone;
  Rrecur.getLocaleFromGmtString = function (locale) {
    // 'Mon Jun 23 2014 10:30:00 GMT-0600 (MDT)' => 'GMT-0600 (MDT)'
    // 'Mon Jun 23 2014 10:30:00 GMT-0600' => 'GMT-0600'
    // 'GMT-0600 (MDT)' => 'GMT-0600 (MDT)'
    // '-0600 (MDT)' => 'GMT-0600 (MDT)'
    // 'GMT-0600' => 'GMT-0600'
    // '-0600' => 'GMT-0600'
    return locale
      .replace(/.*(?:GMT)?([\-+]\d{2}):?(00)(\s\(\w{1,6}\))?$/g, 'GMT$1$2$3')
      ;
  };
  Rrecur.swapLocale = function (date, locale) {
    return date
      .toString()
      .replace(/(.*)GMT.*$/g, '$1' + locale)
      ;
  };
  Rrecur.getOffsetFromLocale = function (locale) {
    // GMT-0600 (MDT) => -0600
    // -0600 (MDT) => -0600
    // GMT-0600 => -0600
    // -0600 => -0600
    return locale
      .toString()
      .replace(/.*(?:GMT)?([\-+]\d{2}):?(00)\s?(\(\w{1,6}\))?$/g, '$1$2') // $3 is EST/MDT/etc
      ;
  };
  Rrecur.swapOffset = function (date, locale) {
    return date
      .toString()
      .replace(/(.*)GMT.*$/g, '$1' + Rrecur.getOffsetFromLocale(locale))
      ;
  };

  function stringifyDateStr(str) {
    return str.replace(
      /(\d{4})-?(\d{2})-?(\d{2})T(\d{2}):?(\d{2}):?(\d{2})(?:\.\d+)?([-+Z]\d*)?(.*)/
    , "$1-$2-$3T$4:$5:$6$7$8"
    );
  }
  function stringifyRruleDate(v, forceZ) {
    if ('number' === typeof v) {
      v = Rrecur.toLocaleISOString(new Date(v), false);
    } else if ('object' === typeof v) {
      v = Rrecur.toLocaleISOString(v, false);
    }

    if (forceZ && !/Z/.test(v)) {
      if ('string' === typeof forceZ) {
        v = new Date(v + forceZ).toISOString();
      } else {
        v = v += 'Z';
      }
    }

    v = v
      .replace(/[\-+]\d{4}(\s \(\w{1,6}\))?$/, '')
      .replace(/\-|:/g, '')
      .replace(/\.\d+/, '')
      ;

    return v;
  }
  Rrecur.stringify = function (orig) {
    var pairs = []
      , lkeys
      , obj = {}
      ;

    Object.keys(orig).forEach(function (k) {
      obj[k] = orig[k];
    });

    if (obj.tzid) {
      console.error('[stringify] tzid not yet supported');
      //pairs.push('DTSTART;TZID' + '=' + obj.tzid + ':' + stringifyRruleDate(obj.dtstart));
      //delete obj.dtstart;
      //delete obj.tzid;
    }

    if (obj.dtstart) {
      if (localeWarn1) {
        console.warn('[stringify] falling back to non-standard locale definition for timezone');
        localeWarn1 = false;
      }

      if (obj.locale) {
        if (!/UTC/.test(obj.locale)) {
          pairs.push('DTSTART;LOCALE' + '=' + obj.locale + ':' + stringifyRruleDate(obj.dtstart));
          delete obj.dtstart;
        }
        delete obj.locale;
      }
    }

    // compensate for RRULE.js non-standardness
    // (although it does happen to make more sense than the standard)
    if (obj.byweekday) {
      console.warn('converting rrule.js obj.byweekday to rrule rfc obj.byday');
      obj.byday = obj.byweekday;
      delete obj.byweekday;
    }

    lkeys = Object.keys(obj);

    // http://www.ietf.org/rfc/rfc2445.txt
    // 4.3.10 Recurrence Rule
    lkeys.forEach(function (k) {
      var v
        , vs
        ;

      v = obj[k.toLowerCase()];
      k = k.toUpperCase();

      if (!v) {
        return;
      }

      if ('UNTIL' === k || 'DTSTART' === k) {
        v = stringifyRruleDate(v, Rrecur.getOffsetFromLocale(obj.locale || new Date()));
      }

      if (Array.isArray(v)) {
        vs = [];
        v.forEach(function (val) {
          if ('string' === typeof val) {
            val = val.toUpperCase();
          }
          vs.push(val);
        });
        v = vs;
      } else if ('string' === typeof v) {
        v = v.toUpperCase();
      }
      // if array, it'll join with ',' automatically
      pairs.push(k + '=' + v);
    });

    return pairs.join(';');
  };

  // TODO timezone support (in dtstart)? // -0400 +0530
  function defaults(freq, dtstart, rrule/*, tzoffset*/) {
    rrule = rrule || {};

    if ('object' !== typeof dtstart) {
      if ('string' === typeof dtstart) {
        dtstart = stringifyDateStr(dtstart);
      }
      dtstart = new Date(dtstart);
    }
    switch(freq) {
      case 'secondly':
        break;
      case 'minutely':
        if (!rrule.bysecond) {
          rrule.bysecond = [dtstart.getUTCSeconds()];
        }
        /* falls through */
      case 'hourly':
        if (!rrule.byminute) {
          rrule.byminute = [dtstart.getUTCMinutes()];
        }
        /* falls through */
      case 'daily':
        if (!rrule.byhour) {
          rrule.byhour = [dtstart.getUTCHours()];
        }
        /* falls through */
      case 'weekly':
        if (!rrule.byday) {
          rrule.byday = [Rrecur.weekdays[dtstart.getUTCDay()]];
        }
        /* falls through */
      case 'monthly':
        if (!rrule.bymonthday) {
          rrule.bymonthday = [dtstart.getUTCDate()];
        }
        /* falls through */
      case 'yearly':
        if (!rrule.bymonth) {
          rrule.bymonth = [dtstart.getUTCMonth() + 1];
        }
        /* falls through */
    }

    return rrule;
  }
  Rrecur.create = Rrecur;

  exports.Rrecur = Rrecur;
  exports.Rrecur.parse = parse;
  exports.Rrecur.parseDtstart = Rrecur.toRruleDateString;
  exports.Rrecur.weekdays = ['su','mo','tu','we','th','fr','sa','su']; // sunday is 0 and 7
  exports.Rrecur.dtstartDefaults = defaults;
}('undefined' !== typeof exports && exports || new Function('return this')()));
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import './ChopList.css';

const DEFAULT_OVERSCAN = 5;
const DEFAULT_INITIAL_ELEMENTS = 10;

const HORIZONTAL_DIRECTION = 'horizontal';
const VERTICAL_DIRECTION = 'vertical';

const HORIZONTAL_KEYS = {
  flex: 'row',
  offset: 'offsetWidth',
  dimension: 'width',
  inverse_dimension: 'height',
  scroll: 'scrollLeft'
}

const VERTICAL_KEYS = {
  flex: 'column',
  offset: 'offsetHeight',
  dimension: 'height',
  inverse_dimension: 'width',
  scroll: 'scrollTop'
}

class ChopList extends Component {

  constructor(props) {
    super(props);

    const direction = props.direction || VERTICAL_DIRECTION;
    const keys = direction === HORIZONTAL_DIRECTION ? HORIZONTAL_KEYS : VERTICAL_KEYS;

    this.state = {
      keys,
      offset: 0,
      overscan: DEFAULT_OVERSCAN,
      burger: 0,
      windowSize: DEFAULT_INITIAL_ELEMENTS,
      initializing: true,
      debug: false,
    };
  }

  getCurrentChildrenMeanSize() {
    const childSizes = [...this.refs.innerScrollList.children].map(child => child[this.state.keys.offset]);

    return childSizes.reduce((h1, h2) => h1 + h2) / childSizes.length;
  }

  shouldComponentUpdate(nextProps, nextState) {
    return this.state.offset !== nextState.offset ||
           this.state.burger !== nextState.burger ||
           this.state.windowSize !== nextState.windowSize;
  }

  chechInitialization() {
    const { keys, windowSize } = this.state;

    const estimatedSize = this.getCurrentChildrenMeanSize();

    // Just during the initialization
    if (this.state.initializing) {
      const containerSize = this.refs.innerScrollContainer[keys.offset];
      const elementsSize = this.refs.innerScrollList.children.length * estimatedSize;

      if (containerSize > elementsSize) {
        const newWindowSize = windowSize + DEFAULT_INITIAL_ELEMENTS

        if (this.state.debug) {
          console.log(`Initializing with ${newWindowSize} elements...`);
        }

        this.setState({
          windowSize: newWindowSize
        });
      } else {
        const newWindowSize = Math.ceil(this.refs.list[keys.offset] / estimatedSize);

        this.setState({
          initializing: false,
          windowSize: newWindowSize,
          overscan: this.props.overscan || newWindowSize,
        });

        // Set real scrollbar size
        this.refs.innerScrollContainer.style[keys.dimension] = `${this.props.rowCount * estimatedSize}px`;
      }
    }
  }

  componentDidUpdate(prevProps, prevState) {
    this.chechInitialization();
  }

  componentDidMount() {
    this.chechInitialization();
  }

  onScroll(event) {
    const { rowCount } = this.props;
    const { windowSize, overscan, keys } = this.state;

    const scrollRelative = this.refs.list[keys.scroll];
    const meanSize = this.getCurrentChildrenMeanSize();
    const offset = Math.min(Math.floor(scrollRelative / meanSize), rowCount - windowSize - overscan);
    const burger = !offset ? 0 : (offset - overscan) * meanSize;

    if (this.state.debug) {
      console.group();
      console.log('Offset', offset);
      console.log('Element size', meanSize);
      console.log('Elements', rowCount);
      console.log('Overscan', overscan);
      console.log('WindowSize', windowSize);
      console.log('Total', rowCount * meanSize);
      console.log('Burger', burger);
      console.groupEnd();
    }

    this.setState({
      offset,
      burger: Math.round(burger)
    });
  }

  renderElements(renderedElements, realOffset) {
    return (
      [...Array(renderedElements)].map((x, i) =>
        { return this.props.rowRenderer({key: 'k' + (i + realOffset), index: (i + realOffset)}) }
      )
    );
  }

  render() {
    const { offset, burger, overscan, keys, initializing, windowSize } = this.state;
    const realOffset = Math.max(offset - overscan, 0);

    const containerStyle = { flexDirection: keys.flex, [`${keys.inverse_dimension}`]: '100%' };
    const burgerStyle = { [`${keys.dimension}`]: burger };

    let renderedElements;

    if (initializing) {
      renderedElements = windowSize;
    } else {
      renderedElements = windowSize + Math.min(offset, overscan) + Math.min(this.props.rowCount - (overscan + offset), overscan)
    }

    return (

            {renderedElements > 0 && this.renderElements(renderedElements, realOffset)}

    );
  }
};

ChopList.propTypes = {
  rowCount: React.PropTypes.number,
  rowRenderer: React.PropTypes.func,
  direction: React.PropTypes.oneOf([HORIZONTAL_DIRECTION, VERTICAL_DIRECTION]),
};

export default ChopList;
<commit_msg>Better propTypes<commit_after>import React, { Component } from 'react';
import './ChopList.css';

const DEFAULT_OVERSCAN = 5;
const DEFAULT_INITIAL_ELEMENTS = 10;

const HORIZONTAL_DIRECTION = 'horizontal';
const VERTICAL_DIRECTION = 'vertical';

const HORIZONTAL_KEYS = {
  flex: 'row',
  offset: 'offsetWidth',
  dimension: 'width',
  inverse_dimension: 'height',
  scroll: 'scrollLeft'
}

const VERTICAL_KEYS = {
  flex: 'column',
  offset: 'offsetHeight',
  dimension: 'height',
  inverse_dimension: 'width',
  scroll: 'scrollTop'
}

class ChopList extends Component {

  constructor(props) {
    super(props);

    const direction = props.direction || VERTICAL_DIRECTION;
    const keys = direction === HORIZONTAL_DIRECTION ? HORIZONTAL_KEYS : VERTICAL_KEYS;

    this.state = {
      keys,
      offset: 0,
      overscan: DEFAULT_OVERSCAN,
      burger: 0,
      windowSize: DEFAULT_INITIAL_ELEMENTS,
      initializing: true,
      debug: false,
    };
  }

  getCurrentChildrenMeanSize() {
    const childSizes = [...this.refs.innerScrollList.children].map(child => child[this.state.keys.offset]);

    return childSizes.reduce((h1, h2) => h1 + h2) / childSizes.length;
  }

  shouldComponentUpdate(nextProps, nextState) {
    return this.state.offset !== nextState.offset ||
           this.state.burger !== nextState.burger ||
           this.state.windowSize !== nextState.windowSize;
  }

  chechInitialization() {
    const { keys, windowSize } = this.state;

    const estimatedSize = this.getCurrentChildrenMeanSize();

    // Just during the initialization
    if (this.state.initializing) {
      const containerSize = this.refs.innerScrollContainer[keys.offset];
      const elementsSize = this.refs.innerScrollList.children.length * estimatedSize;

      if (containerSize > elementsSize) {
        const newWindowSize = windowSize + DEFAULT_INITIAL_ELEMENTS

        if (this.state.debug) {
          console.log(`Initializing with ${newWindowSize} elements...`);
        }

        this.setState({
          windowSize: newWindowSize
        });
      } else {
        const newWindowSize = Math.ceil(this.refs.list[keys.offset] / estimatedSize);

        this.setState({
          initializing: false,
          windowSize: newWindowSize,
          overscan: this.props.overscan || newWindowSize,
        });

        // Set real scrollbar size
        this.refs.innerScrollContainer.style[keys.dimension] = `${this.props.rowCount * estimatedSize}px`;
      }
    }
  }

  componentDidUpdate(prevProps, prevState) {
    this.chechInitialization();
  }

  componentDidMount() {
    this.chechInitialization();
  }

  onScroll(event) {
    const { rowCount } = this.props;
    const { windowSize, overscan, keys } = this.state;

    const scrollRelative = this.refs.list[keys.scroll];
    const meanSize = this.getCurrentChildrenMeanSize();
    const offset = Math.min(Math.floor(scrollRelative / meanSize), rowCount - windowSize - overscan);
    const burger = !offset ? 0 : (offset - overscan) * meanSize;

    if (this.state.debug) {
      console.group();
      console.log('Offset', offset);
      console.log('Element size', meanSize);
      console.log('Elements', rowCount);
      console.log('Overscan', overscan);
      console.log('WindowSize', windowSize);
      console.log('Total', rowCount * meanSize);
      console.log('Burger', burger);
      console.groupEnd();
    }

    this.setState({
      offset,
      burger: Math.round(burger)
    });
  }

  renderElements(renderedElements, realOffset) {
    return (
      [...Array(renderedElements)].map((x, i) =>
        { return this.props.rowRenderer({key: 'k' + (i + realOffset), index: (i + realOffset)}) }
      )
    );
  }

  render() {
    const { offset, burger, overscan, keys, initializing, windowSize } = this.state;
    const realOffset = Math.max(offset - overscan, 0);

    const containerStyle = { flexDirection: keys.flex, [`${keys.inverse_dimension}`]: '100%' };
    const burgerStyle = { [`${keys.dimension}`]: burger };

    let renderedElements;

    if (initializing) {
      renderedElements = windowSize;
    } else {
      renderedElements = windowSize + Math.min(offset, overscan) + Math.min(this.props.rowCount - (overscan + offset), overscan)
    }

    return (

            {renderedElements > 0 && this.renderElements(renderedElements, realOffset)}

    );
  }
};

ChopList.propTypes = {
  rowCount: React.PropTypes.number.isRequired,
  rowRenderer: React.PropTypes.func.isRequired,
  direction: React.PropTypes.oneOf([HORIZONTAL_DIRECTION, VERTICAL_DIRECTION]),
  overscan: React.PropTypes.number,
};

export default ChopList;
<|endoftext|>


<commit_before>/*jslint sloppy: true */
/*global define */

/**
 * Classify - Sugar syntax for Prototypal Inheritance
 *
 * @author Luís Couto
 * @contact lcouto87@gmail.com
 * @version 1.0.0
 *
 * @example
 *      var Example = Classify({
 *          Implements : [oneInterface, twoInterface],
 *          Extends: ParentClassify,
 *          Borrows: [Mixin1, Mixin2],
 *          Binds: ['method1', 'method2'],
 *          Statics: {
 *              staticMethod1: function(){},
 *              staticMethod2: function(){},
 *              staticMethod3: function(){},
 *          },
 *          initialize: function () {},
 *          method1: function () {},
 *          method2: function () {},
 *          method3: function () {}
 *      });
 *
 * @param {Object} methods Object
 * @returns Function
 */

define("Trinity/Classify", ["Classify.Abstract", "Classify.Interface", "Classify.Singleton"], function (Abstract, Singleton, Interface) {

    function Classify(methods) {

        var classify;

        /**
         * Extends an object with another given object
         *
         * @private
         *
         * @param {Object} target Object's that will get the new methods
         * @returns undefined
         */

        function extend(methods, target) {
            var k;
            for (k in methods) {
                if (methods.hasOwnProperty(k)) {
                    target[k] = methods[k];
                }
            }
        }

        /**
         * For an Array of Objects, add their methods/properties to
         * target's prototype
         *
         * @private
         * @param {Array} arr Array of objects that will give their methods
         * @param {Object} Target that will receive the methods
         * @returns undefined
         */

        function borrows(arr, target) {

            var i = arr.length - 1,
                constructorBck;

            for (i; i >= 0; i -= 1) {
                if (arr[i].prototype && arr[i].prototype.constructor) {
                    constructorBck = arr[i].prototype.constructor;
                    delete arr[i].prototype.constructor;
                    extend(arr[i].prototype, target.prototype);
                    arr[i].prototype.constructor = constructorBck;
                } else {
                    extend(arr[i].prototype || arr[i], target.prototype);
                }
            }
        }

        /**
         * Fixes the context in given methods
         *
         * @private
         * @param {Function}
         * @returns function handler with fixed context
         */

        function binds(arr, context, target) {
            var proxy = function (func) {

                if (Function.prototype.bind) {
                    return func.bind(context);
                }

                return function () {
                    return func.apply(context, arguments);
                };

            },
                i = arr.length - 1;

            for (i; i >= 0; i -= 1) {
                target[arr[i]] = proxy(target[arr[i]], classify);
            }
        }

        /**
         * Copies the given object into a freshly
         * created empty function's prototype
         *
         * @private
         * @param {Object} o Object
         * @returns {Function} Instance
         * @type Function
         */

        function clone(o) {
            function F() {}
            F.prototype = o;
            return new F();
        }

        function interfaces(arr, target) {
            var i = arr.length - 1,
                k;

            for (i; i >= 0; i -= 1) {
                for (k in arr[i]) {
                    if (!(target.hasOwnProperty(k)) && (k !== "Extends" || k !== "Name")) {
                        throw new Error("Class does not implements Interface " + arr[i].Name + "correctly");
                    }
                }
            }
        }

        classify = methods.initialize || function classify() {};

        if (methods.Extends) {
            classify.Parent = methods.Extends.prototype;
            classify.prototype = clone(classify.Parent);
            extend(methods, classify.prototype);
        } else {
            classify.prototype = methods;
        }

        classify.prototype.constructor = classify;

        if (methods.Borrows) {
            borrows(methods.Borrows, classify);
        }

        if (methods.Binds) {
            binds(methods.Binds, classify, classify.prototype);
        }

        if (methods.Statics) {
            extend(methods.Statics, classify);
            delete classify.prototype.Static;
        }

        if (methods.Implements) {
            interfaces(methods.Implements, this);
        }

        return classify;

    }

    Classify.Abstract = Abstract;
    Classify.Interface = Interface;
    Classify.Singleton = Singleton;

    return Classify;
});
<commit_msg>Code standard and documentation fix.<commit_after>/*jslint sloppy: true */
/*global define */

/**
 * Classify - Sugar syntax for Prototypal Inheritance
 *
 * @author Luís Couto <lcouto87@gmail.com>
 * @version 1.0.0
 *
 * @example
 *
 *      var MyClass = Classify({
 *          Implements: [SomeInterface, OtherInterface],
 *          Extends: ParentClass,
 *          Borrows: [SomeMixin, OtherMixin],
 *          Binds: ['method1', 'method2'],
 *          Statics: {
 *              staticMethod1: function () {},
 *              staticMethod2: function () {},
 *              staticMethod3: function () {},
 *          },
 *          initialize: function () {},
 *          method1: function () {},
 *          method2: function () {},
 *          method3: function () {}
 *      });
 */
define("Trinity/Classify", ["Classify.Abstract", "Classify.Interface", "Classify.Singleton"], function (Abstract, Singleton, Interface) {

    /**
     * Create a class definition.
     *
     * @param {Object} params An object containing methods and properties
     *
     * @returns Function
     */
    function Classify(params) {

        var classify;

        /**
         * Extends an object with another given object.
         *
         * @private
         *
         * @param {Object} source The object to copy from
         * @param {Object} target The object that will get the source properties and methods
         */
        function extend(source, target) {

            var k;

            for (k in source) {
                if (source.hasOwnProperty(k)) {
                    target[k] = source[k];
                }
            }
        }

        /**
         * Borrows the properties and methods of various source objects to the target
         *
         * @private
         *
         * @param {Array}  sources Array of objects that will give their methods
         * @param {Object} target  Target that will receive the methods
         */
        function borrows(sources, target) {

            var i = sources.length - 1,
                constructorBck;

            for (i; i >= 0; i -= 1) {
                if (sources[i].prototype && sources[i].prototype.constructor) {
                    constructorBck = sources[i].prototype.constructor;
                    delete sources[i].prototype.constructor;
                    extend(sources[i].prototype, target.prototype);
                    sources[i].prototype.constructor = constructorBck;
                } else {
                    extend(sources[i].prototype || sources[i], target.prototype);
                }
            }
        }

        /**
         * Fixes the context in given methods.
         *
         * @private
         *
         * @param {Array} fns The array of functions to be binded
         * @param {Object} context The context that will be bound
         * @param {Object} target The target class that will have these methods
         */
        function binds(fns, context, target) {

            var proxy = function (func) {

                if (Function.prototype.bind) {
                    return func.bind(context);
                }

                return function () {
                    return func.apply(context, arguments);
                };

            },
                i = fns.length - 1;

            for (i; i >= 0; i -= 1) {
                target[fns[i]] = proxy(target[fns[i]], classify);
            }
        }

        /**
         * Copies the given object into a freshly created empty function's prototype
         *
         * @private
         *
         * @param {Object} object Object
         *
         * @returns {Function} Thew new instance
         */
        function clone(object) {

            function F() {}
            F.prototype = object;

            return new F();
        }

        /**
         *
         */
        function interfaces(interfaces, target) {

            var i = interfaces.length - 1,
                k;

            for (i; i >= 0; i -= 1) {
                for (k in interfaces[i]) {
                    if (!target.hasOwnProperty(k) && (k !== "Extends" || k !== "Name")) {
                        throw new Error("Class does not implements Interface " + arr[i].Name + "correctly");
                    }
                }
            }
        }

        classify = params.initialize || function () {};

        if (params.Extends) {
            classify.Parent = params.Extends.prototype;
            classify.prototype = clone(classify.Parent);
            extend(params, classify.prototype);
        } else {
            classify.prototype = params;
        }

        classify.prototype.constructor = classify;

        if (params.Borrows) {
            borrows(params.Borrows, classify);
        }

        if (params.Binds) {
            binds(params.Binds, classify, classify.prototype);
        }

        if (params.Statics) {
            extend(params.Statics, classify);
            delete classify.prototype.Static;
        }

        if (params.Implements) {
            interfaces(params.Implements, this);
        }

        return classify;
    }

    Classify.Abstract = Abstract;
    Classify.Interface = Interface;
    Classify.Singleton = Singleton;

    return Classify;
});
<|endoftext|>


<commit_before>import React from 'react';
import {shouldComponentUpdate} from 'react/lib/ReactComponentWithPureRenderMixin';
import {Motion, spring} from 'react-motion';
import HeightReporter from 'react-height';

const stringHeight = height => Math.max(0, parseFloat(height)).toFixed(1);

const Collapse = React.createClass({
  propTypes: {
    isOpened: React.PropTypes.bool.isRequired,
    children: React.PropTypes.node.isRequired,
    fixedHeight: React.PropTypes.number,
    style: React.PropTypes.object, // eslint-disable-line react/forbid-prop-types
    springConfig: React.PropTypes.objectOf(React.PropTypes.number),
    keepCollapsedContent: React.PropTypes.bool,
    onHeightReady: React.PropTypes.func
  },

  getDefaultProps() {
    return {
      fixedHeight: -1,
      style: {},
      keepCollapsedContent: false,
      onHeightReady: () => {} // eslint-disable-line no-empty-function
    };
  },

  getInitialState() {
    return {height: -1, isOpenedChanged: false};
  },

  componentWillMount() {
    this.height = stringHeight(0);
    this.renderStatic = true;
  },

  componentWillReceiveProps({isOpened}) {
    this.setState({isOpenedChanged: isOpened !== this.props.isOpened});
  },

  shouldComponentUpdate,

  componentDidUpdate({isOpened}) {
    if (isOpened !== this.props.isOpened) {
      const report = this.props.isOpened ? this.state.height : 0;

      this.props.onHeightReady(report);
    }
  },

  onHeightReady(height) {
    const {isOpened} = this.props;

    if (this.renderStatic && isOpened) {
      this.height = stringHeight(height);
    }
    if (this.state.height !== height) {
      this.setState({height});
    }

    const reportHeight = this.props.isOpened ? height : 0;

    if (this.state.height !== reportHeight) {
      this.props.onHeightReady(reportHeight);
    }
  },

  getMotionHeight(height) {
    const {isOpened, springConfig} = this.props;
    const {isOpenedChanged} = this.state;

    const newHeight = isOpened ? Math.max(0, parseFloat(height)).toFixed(1) : stringHeight(0);

    // No need to animate if content is closed and it was closed previously
    // Also no need to animate if height did not change
    const skipAnimation = !isOpenedChanged && !isOpened || this.height === newHeight;

    const springHeight = spring(isOpened ? Math.max(0, height) : 0, springConfig);
    const instantHeight = isOpened ? Math.max(0, height) : 0;

    return skipAnimation ? instantHeight : springHeight;
  },

  renderFixed() {
    const {
      isOpened, style, children, fixedHeight, springConfig: _, keepCollapsedContent, ...props
    } = this.props;

    if (this.renderStatic) {
      this.renderStatic = false;
      const newStyle = {overflow: 'hidden', height: isOpened ? fixedHeight : 0};

      if (!keepCollapsedContent && !isOpened) {
        return null;
      }
      this.height = stringHeight(fixedHeight);
      return
{children}
;
    }

    return (
      <Motion
        defaultStyle={{height: isOpened ? 0 : fixedHeight}}
        style={{height: this.getMotionHeight(fixedHeight)}}>
        {({height}) => {
          this.height = stringHeight(height);

          // TODO: this should be done using onEnd from ReactMotion, which is not yet implemented
          // See https://github.com/chenglou/react-motion/issues/235
          if (!keepCollapsedContent && !isOpened && this.height === stringHeight(0)) {
            return null;
          }

          const newStyle = {overflow: 'hidden', height};

          return
{children}
;
        }}
      </Motion>
    );
  },

  render() {
    const {
      isOpened, style, children, fixedHeight, springConfig: _, keepCollapsedContent, ...props
    } = this.props;

    if (fixedHeight > -1) {
      return this.renderFixed();
    }

    const renderStatic = this.renderStatic;
    const {height} = this.state;
    const currentStringHeight = parseFloat(height).toFixed(1);

    if (height > -1 && renderStatic) {
      this.renderStatic = false;
    }

    // Cache Content so it is not re-rendered on each animation step
    const content = <HeightReporter onHeightReady={this.onHeightReady}>{children}</HeightReporter>;

    if (renderStatic) {
      const newStyle = isOpened ? {height: 'auto'} : {overflow: 'hidden', height: 0};

      if (!isOpened && height > -1) {
        if (!keepCollapsedContent) {
          return null;
        }
        return (

            {content}

        );
      }

      return
{content}
;
    }

    return (
      <Motion
        defaultStyle={{height: Math.max(0, height)}}
        style={{height: this.getMotionHeight(height)}}>
        {st => {
          this.height = stringHeight(st.height);

          // TODO: this should be done using onEnd from ReactMotion, which is not yet implemented
          // See https://github.com/chenglou/react-motion/issues/235
          if (!isOpened && this.height === '0.0') {
            if (!keepCollapsedContent) {
              return null;
            }
            return (

                {content}

            );
          }

          const newStyle = isOpened && this.height === currentStringHeight ? {height: 'auto'} : {
            height: st.height, overflow: 'hidden'
          };

          return
{content}
;
        }}
      </Motion>
    );
  }
});

export default Collapse;
<commit_msg>fix for initial zero height<commit_after>import React from 'react';
import {shouldComponentUpdate} from 'react/lib/ReactComponentWithPureRenderMixin';
import {Motion, spring} from 'react-motion';
import HeightReporter from 'react-height';

const stringHeight = height => Math.max(0, parseFloat(height)).toFixed(1);

const Collapse = React.createClass({
  propTypes: {
    isOpened: React.PropTypes.bool.isRequired,
    children: React.PropTypes.node.isRequired,
    fixedHeight: React.PropTypes.number,
    style: React.PropTypes.object, // eslint-disable-line react/forbid-prop-types
    springConfig: React.PropTypes.objectOf(React.PropTypes.number),
    keepCollapsedContent: React.PropTypes.bool,
    onHeightReady: React.PropTypes.func
  },

  getDefaultProps() {
    return {
      fixedHeight: -1,
      style: {},
      keepCollapsedContent: false,
      onHeightReady: () => {} // eslint-disable-line no-empty-function
    };
  },

  getInitialState() {
    return {height: -1, isOpenedChanged: false};
  },

  componentWillMount() {
    this.height = stringHeight(0);
    this.renderStatic = true;
  },

  componentWillReceiveProps({isOpened}) {
    this.setState({isOpenedChanged: isOpened !== this.props.isOpened});
  },

  shouldComponentUpdate,

  componentDidUpdate({isOpened}) {
    if (isOpened !== this.props.isOpened) {
      const report = this.props.isOpened ? this.state.height : 0;

      this.props.onHeightReady(report);
    }
  },

  onHeightReady(height) {
    const {isOpened, keepCollapsedContent} = this.props;

    if (this.renderStatic && isOpened) {
      this.height = stringHeight(height);
    }
    if (keepCollapsedContent) {
      this.setState({height});
    } else {
      this.setState({height: isOpened || !this.renderStatic ? height : 0});
    }

    const reportHeight = this.props.isOpened ? height : 0;

    if (this.state.height !== reportHeight) {
      this.props.onHeightReady(reportHeight);
    }
  },

  getMotionHeight(height) {
    const {isOpened, springConfig} = this.props;
    const {isOpenedChanged} = this.state;

    const newHeight = isOpened ? Math.max(0, parseFloat(height)).toFixed(1) : stringHeight(0);

    // No need to animate if content is closed and it was closed previously
    // Also no need to animate if height did not change
    const skipAnimation = !isOpenedChanged && !isOpened || this.height === newHeight;

    const springHeight = spring(isOpened ? Math.max(0, height) : 0, springConfig);
    const instantHeight = isOpened ? Math.max(0, height) : 0;

    return skipAnimation ? instantHeight : springHeight;
  },

  renderFixed() {
    const {
      isOpened, style, children, fixedHeight, springConfig: _, keepCollapsedContent, ...props
    } = this.props;

    if (this.renderStatic) {
      this.renderStatic = false;
      const newStyle = {overflow: 'hidden', height: isOpened ? fixedHeight : 0};

      if (!keepCollapsedContent && !isOpened) {
        return null;
      }
      this.height = stringHeight(fixedHeight);
      return
{children}
;
    }

    return (
      <Motion
        defaultStyle={{height: isOpened ? 0 : fixedHeight}}
        style={{height: this.getMotionHeight(fixedHeight)}}>
        {({height}) => {
          this.height = stringHeight(height);

          // TODO: this should be done using onEnd from ReactMotion, which is not yet implemented
          // See https://github.com/chenglou/react-motion/issues/235
          if (!keepCollapsedContent && !isOpened && this.height === stringHeight(0)) {
            return null;
          }

          const newStyle = {overflow: 'hidden', height};

          return
{children}
;
        }}
      </Motion>
    );
  },

  render() {
    const {
      isOpened, style, children, fixedHeight, springConfig: _, keepCollapsedContent, ...props
    } = this.props;

    if (fixedHeight > -1) {
      return this.renderFixed();
    }

    const renderStatic = this.renderStatic;
    const {height} = this.state;
    const currentStringHeight = parseFloat(height).toFixed(1);

    if (height > -1 && renderStatic) {
      this.renderStatic = false;
    }

    // Cache Content so it is not re-rendered on each animation step
    const content = <HeightReporter onHeightReady={this.onHeightReady}>{children}</HeightReporter>;

    if (renderStatic) {
      const newStyle = isOpened ? {height: 'auto'} : {overflow: 'hidden', height: 0};

      if (!isOpened && height > -1) {
        if (!keepCollapsedContent) {
          return null;
        }
        return (

            {content}

        );
      }

      return
{content}
;
    }

    return (
      <Motion
        defaultStyle={{height: Math.max(0, height)}}
        style={{height: this.getMotionHeight(height)}}>
        {st => {
          this.height = stringHeight(st.height);

          // TODO: this should be done using onEnd from ReactMotion, which is not yet implemented
          // See https://github.com/chenglou/react-motion/issues/235
          if (!isOpened && this.height === '0.0') {
            if (!keepCollapsedContent) {
              return null;
            }
            return (

                {content}

            );
          }

          const newStyle = isOpened && this.height === currentStringHeight ? {height: 'auto'} : {
            height: st.height, overflow: 'hidden'
          };

          return
{content}
;
        }}
      </Motion>
    );
  }
});

export default Collapse;
<|endoftext|>


<commit_before>'use strict';

var Brain = require('./Brain');
var Config = require('./Config');
var Debug = require('./Debug');
var Graphics = require('./Graphics');
var Part = require('./Part');
var Vector =require('./Vector');

function Creature(world, brain, parts, inherited)
{
	var that = this;
	inherited = inherited || {};

	this.world = world;
	this.graphics = this.world.graphics;

	// create the parts and brain
	this.parts = parts || this._generateRandomParts();
	this.parts.forEach(part => part.creature = that);
	this.brain = brain || new Brain();

	// connect the parts to the brain
	let inputs = [], outputs = [];
	this.parts.forEach(part => {
		inputs = inputs.concat(part.inputs);
		outputs = outputs.concat(part.outputs);
	});

	// part outputs are brain inputs, and vice-versa
	this.brain.connect(outputs, inputs)

	this.radius = inherited.radius || Config.Creature.MaxRadius;
	this.velocity = new Vector(0, 0).random();
	this.location = this._generateRandomLocation();
	this.color = inherited.color || this._generateRandomColor();

	this.reset();
}

Creature.prototype = {

	world: undefined,
	brain: undefined,
	graphics: undefined,
	radius: undefined,
	location: undefined,
	velocity: undefined,
	color: undefined,
	parts: undefined,

	tick: function()
	{
		var that = this;

		// feed the neural network forward
		this.brain.activate();

		let drag = 0;
		this.velocity.set(0, 0);
		this.parts.forEach(part => {
			part.tick();
			let velocityComponent = part.relativePosition
				.copy()
				.invert();

			let distanceRatio = part.relativePosition.magnitude() / Config.Creature.Part.MaxDistanceFromCreature;
			let radiusRatio = part.radius / Config.Creature.Part.MaxRadius;
			drag += distanceRatio * radiusRatio;
			that.velocity.add(velocityComponent);
		});

		let limitFactor = 1 - Math.min(1, drag);
		this.velocity.limit(Math.min(Config.Creature.LinearMaxSpeed, this.velocity.magnitude()) * limitFactor);
		this.location.add(this.velocity);

		// interact with the world and other creatures
		this.interact();
	},

	interact: function()
	{
		this.parts.forEach(part => part.interact());
	},

	eatFood: function(foodId) {
		this.world.food[foodId].x = null; // invalidate
		this.foodEaten++;
	},

	clone: function()
	{
		let newBrain = this.brain.clone();
		let newParts = this.parts.map(part => part.clone());
		let creature = new Creature(this.world, newBrain, newParts, {
			color: this.color,
			radius: this.radius,
		});
		creature.mutate();
		return creature;
	},

	mutate: function () {
		if (Math.random() < Config.Mutation.GlobalMutationRate) {
			// insane in the membrane
			this.brain.mutate();
		}
	},

	draw: function()
	{
		// draw parts
		for (let i = 0; i < this.parts.length; i++) {
			let partLocation = this.location.copy().add(this.parts[i].relativePosition);

			// draw part
			this.graphics.drawCircle(partLocation, this.parts[i].radius, {
				fillStyle: this.color,
				globalAlpha: .25,
				lineWidth: 1,
			});

			// draw line to part
			this.graphics.drawLine(this.location, partLocation, {
				lineWidth: 2,
				strokeStyle: this.color,
			});

			// draw line to nearest food
			// if (parts[i].nearestFood.magnitude() < parts[i].scanRadius) {
			// 	let absolutePosition = partLocation.copy().add(parts[i].nearestFood);
			// 	this.graphics.drawLine(partLocation, absolutePosition, {
			// 		lineWidth: 1,
			// 		strokeStyle: 'rgba(150, 150, 150, .5)',
			// 	});
			// }
		}

		// // draw pointer (to show what direction the creature is facing)
		// let relativeTarget = this.velocity.copy().setMagnitude(this.radius + 3);
		// let absoluteTarget = this.location.copy().add(relativeTarget);
		// this.graphics.drawLine(this.location, absoluteTarget, {
		// 	lineWidth: 3,
		// 	strokeStyle: 'black',
		// });

		// draw self
		this.graphics.drawCircle(this.location, this.radius, {
			fillStyle: this.color,
			globalAlpha: 1,
			lineWidth: 1
		});
	},

	highlight: function()
	{
		// draw a semitransparent "halo" around the creature, to make it stand out
		this.graphics.drawCircle(this.location, Config.Creature.Part.MaxDistanceFromCreature + this.radius, {
			lineWidth: 1,
			fillStyle: this.color,
			globalAlpha: .2,
		})
	},

	fitness: function()
	{
		return this.foodEaten;
	},

	reset: function()
	{
		this.foodEaten = 0;
	},

	_generateParts: function (numParts) {
		let parts = [];
		for (let i = 0; i < numParts; i++) {
			parts.push(new Part());
		}

		return parts;
	},

	_generateRandomParts: function ()
	{
		return this._generateParts(1 + Math.floor(Math.random() * Config.Creature.MaxStartingParts));
	},

	_generateRandomColor: function ()
	{
		return 'rgb(' +
			Math.floor(Math.random() * 255) + ',' +
			Math.floor(Math.random() * 255) + ',' +
			Math.floor(Math.random() * 255) + ')';
	},

	_generateRandomLocation: function ()
	{
		return new Vector(
			Math.random() * (this.world.width - 100) + 50,
			Math.random() * (this.world.height - 100) + 50
		);
	},
}

module.exports = Creature;
<commit_msg>Fix references<commit_after>'use strict';

var Brain = require('./Brain');
var Config = require('./Config');
var Part = require('./parts/Part');
var Vector =require('./Vector');

function Creature(world, brain, parts, inherited)
{
	var that = this;
	inherited = inherited || {};

	this.world = world;
	this.graphics = this.world.graphics;

	// create the parts and brain
	this.parts = parts || this._generateRandomParts();
	this.parts.forEach(part => part.creature = that);
	this.brain = brain || new Brain();

	// connect the parts to the brain
	let inputs = [], outputs = [];
	this.parts.forEach(part => {
		inputs = inputs.concat(part.inputs);
		outputs = outputs.concat(part.outputs);
	});

	// part outputs are brain inputs, and vice-versa
	this.brain.connect(outputs, inputs)

	this.radius = inherited.radius || Config.Creature.MaxRadius;
	this.velocity = new Vector(0, 0).random();
	this.location = this._generateRandomLocation();
	this.color = inherited.color || this._generateRandomColor();

	this.reset();
}

Creature.prototype = {

	world: undefined,
	brain: undefined,
	graphics: undefined,
	radius: undefined,
	location: undefined,
	velocity: undefined,
	color: undefined,
	parts: undefined,

	tick: function()
	{
		var that = this;

		// feed the neural network forward
		this.brain.activate();

		let drag = 0;
		this.velocity.set(0, 0);
		this.parts.forEach(part => {
			part.tick();
			let velocityComponent = part.relativePosition
				.copy()
				.invert();

			let distanceRatio = part.relativePosition.magnitude() / Config.Creature.Part.MaxDistanceFromCreature;
			let radiusRatio = part.radius / Config.Creature.Part.MaxRadius;
			drag += distanceRatio * radiusRatio;
			that.velocity.add(velocityComponent);
		});

		let limitFactor = 1 - Math.min(1, drag);
		this.velocity.limit(Math.min(Config.Creature.LinearMaxSpeed, this.velocity.magnitude()) * limitFactor);
		this.location.add(this.velocity);

		// interact with the world and other creatures
		this.interact();
	},

	interact: function()
	{
		this.parts.forEach(part => part.interact());
	},

	eatFood: function(foodId) {
		this.world.food[foodId].x = null; // invalidate
		this.foodEaten++;
	},

	clone: function()
	{
		let newBrain = this.brain.clone();
		let newParts = this.parts.map(part => part.clone());
		let creature = new Creature(this.world, newBrain, newParts, {
			color: this.color,
			radius: this.radius,
		});
		creature.mutate();
		return creature;
	},

	mutate: function () {
		if (Math.random() < Config.Mutation.GlobalMutationRate) {
			// insane in the membrane
			this.brain.mutate();
		}
	},

	draw: function()
	{
		// draw parts
		for (let i = 0; i < this.parts.length; i++) {
			let partLocation = this.location.copy().add(this.parts[i].relativePosition);

			// draw part
			this.graphics.drawCircle(partLocation, this.parts[i].radius, {
				fillStyle: this.color,
				globalAlpha: .25,
				lineWidth: 1,
			});

			// draw line to part
			this.graphics.drawLine(this.location, partLocation, {
				lineWidth: 2,
				strokeStyle: this.color,
			});

			// draw line to nearest food
			// if (parts[i].nearestFood.magnitude() < parts[i].scanRadius) {
			// 	let absolutePosition = partLocation.copy().add(parts[i].nearestFood);
			// 	this.graphics.drawLine(partLocation, absolutePosition, {
			// 		lineWidth: 1,
			// 		strokeStyle: 'rgba(150, 150, 150, .5)',
			// 	});
			// }
		}

		// // draw pointer (to show what direction the creature is facing)
		// let relativeTarget = this.velocity.copy().setMagnitude(this.radius + 3);
		// let absoluteTarget = this.location.copy().add(relativeTarget);
		// this.graphics.drawLine(this.location, absoluteTarget, {
		// 	lineWidth: 3,
		// 	strokeStyle: 'black',
		// });

		// draw self
		this.graphics.drawCircle(this.location, this.radius, {
			fillStyle: this.color,
			globalAlpha: 1,
			lineWidth: 1
		});
	},

	highlight: function()
	{
		// draw a semitransparent "halo" around the creature, to make it stand out
		this.graphics.drawCircle(this.location, Config.Creature.Part.MaxDistanceFromCreature + this.radius, {
			lineWidth: 1,
			fillStyle: this.color,
			globalAlpha: .2,
		})
	},

	fitness: function()
	{
		return this.foodEaten;
	},

	reset: function()
	{
		this.foodEaten = 0;
	},

	_generateParts: function (numParts) {
		let parts = [];
		for (let i = 0; i < numParts; i++) {
			parts.push(new Part());
		}

		return parts;
	},

	_generateRandomParts: function ()
	{
		return this._generateParts(1 + Math.floor(Math.random() * Config.Creature.MaxStartingParts));
	},

	_generateRandomColor: function ()
	{
		return 'rgb(' +
			Math.floor(Math.random() * 255) + ',' +
			Math.floor(Math.random() * 255) + ',' +
			Math.floor(Math.random() * 255) + ')';
	},

	_generateRandomLocation: function ()
	{
		return new Vector(
			Math.random() * (this.world.width - 100) + 50,
			Math.random() * (this.world.height - 100) + 50
		);
	},
}

module.exports = Creature;
<|endoftext|>