<commit_before>// ==========================================================================
// Project:   The M-Project - Mobile HTML5 Application Framework
// Copyright: 2010 M-Way Solutions GmbH. All rights reserved.
// Creator:   Dominik
// Date:      27.10.2010
// License:   Dual licensed under the MIT or GPL Version 2 licenses.
//            http://github.com/mwaylabs/The-M-Project/blob/master/MIT-LICENSE
//            http://github.com/mwaylabs/The-M-Project/blob/master/GPL-LICENSE
// ==========================================================================

/* Available transitions for page changes */
M.TRANSITION = {};
M.TRANSITION.SLIDE = 'slide';

m_require('observable.js');

/**
 * @class
 *
 * The root class for every controller.
 *
 * Controllers, respectively their properties, are observables. Views can observe them.
 *
 */
M.Controller = M.Object.extend({

    /**
     * The type of this object.
     *
     * @property {String}
     */
    type: 'M.Controller',

    /**
     * Makes the controller's properties observable.
     */
    observable: M.Observable.extend({}),

    /**
     * Helper function to build the location href for the view to be displayed.
     *
     * @param {String} id The id of the new target.
     */
    buildLocationHref: function(id) {
        return location.pathname + '#' + id;
    },

    /**
     * Returns the class property behind the given key and informs its observers.
     *
     * @param {Object} page The page to be displayed.
     * @param {String} transition The transition that should be used. Default: horizontal slide
     * @param {Boolean} isBack YES will cause a reverse-direction transition. Default: NO
     * @param {Boolean} changeLoc Update the browser history. Default: YES
     */
    switchToPage: function(page, transition, isBack, changeLoc) {
        var id = M.Application.viewManager.getIdByView(page);
        if(id) {
            transition = transition ? transition : M.TRANSITION.SLIDE;
            isBack = isBack !== undefined ? isBack : false;
            changeLoc = changeLoc !== undefined ? changeLoc : true;

            /* Now do the page change by using a jquery mobile method and pass the properties */
            $.mobile.changePage(id, transition, isBack, changeLoc);

            /* Save the current page in the view manager */
            M.Application.viewManager.setCurrentPage(page);
        } else {
            M.Logger.log('"' + page + '" not found', M.WARN);
        }
    },

    /**
     * Returns the class property behind the given key and informs its observers.
     *
     * @param {String} key The key of the property to be changed.
     * @param {Object, String} value The value to be set.
     */
    set: function(key, value) {
        this[key] = value;
        this.observable.notifyObservers(key);
    }

});<commit_msg>Refactoring: Changed true/false to YES/NO<commit_after>// ==========================================================================
// Project:   The M-Project - Mobile HTML5 Application Framework
// Copyright: 2010 M-Way Solutions GmbH. All rights reserved.
// Creator:   Dominik
// Date:      27.10.2010
// License:   Dual licensed under the MIT or GPL Version 2 licenses.
//            http://github.com/mwaylabs/The-M-Project/blob/master/MIT-LICENSE
//            http://github.com/mwaylabs/The-M-Project/blob/master/GPL-LICENSE
// ==========================================================================

/* Available transitions for page changes */
M.TRANSITION = {};
M.TRANSITION.SLIDE = 'slide';

m_require('observable.js');

/**
 * @class
 *
 * The root class for every controller.
 *
 * Controllers, respectively their properties, are observables. Views can observe them.
 *
 */
M.Controller = M.Object.extend({

    /**
     * The type of this object.
     *
     * @property {String}
     */
    type: 'M.Controller',

    /**
     * Makes the controller's properties observable.
     */
    observable: M.Observable.extend({}),

    /**
     * Helper function to build the location href for the view to be displayed.
     *
     * @param {String} id The id of the new target.
     */
    buildLocationHref: function(id) {
        return location.pathname + '#' + id;
    },

    /**
     * Returns the class property behind the given key and informs its observers.
     *
     * @param {Object} page The page to be displayed.
     * @param {String} transition The transition that should be used. Default: horizontal slide
     * @param {Boolean} isBack YES will cause a reverse-direction transition. Default: NO
     * @param {Boolean} changeLoc Update the browser history. Default: YES
     */
    switchToPage: function(page, transition, isBack, changeLoc) {
        var id = M.Application.viewManager.getIdByView(page);
        if(id) {
            transition = transition ? transition : M.TRANSITION.SLIDE;
            isBack = isBack !== undefined ? isBack : NO;
            changeLoc = changeLoc !== undefined ? changeLoc : YES;

            /* Now do the page change by using a jquery mobile method and pass the properties */
            $.mobile.changePage(id, transition, isBack, changeLoc);

            /* Save the current page in the view manager */
            M.Application.viewManager.setCurrentPage(page);
        } else {
            M.Logger.log('"' + page + '" not found', M.WARN);
        }
    },

    /**
     * Returns the class property behind the given key and informs its observers.
     *
     * @param {String} key The key of the property to be changed.
     * @param {Object, String} value The value to be set.
     */
    set: function(key, value) {
        this[key] = value;
        this.observable.notifyObservers(key);
    }

});<|endoftext|>


<commit_before>(function()
{
    'use strict';

    angular
        .module('lumx.dialog')
        .directive('lxDialog', lxDialog)
        .directive('lxDialogHeader', lxDialogHeader)
        .directive('lxDialogContent', lxDialogContent)
        .directive('lxDialogFooter', lxDialogFooter)
        .directive('lxDialogClose', lxDialogClose);

    function lxDialog()
    {
        return {
            restrict: 'E',
            template: '

',
            scope:
            {
                autoClose: '=?lxAutoClose',
                escapeClose: '=?lxEscapeClose',
                size: '@?lxSize'
            },
            link: link,
            controller: LxDialogController,
            controllerAs: 'lxDialog',
            bindToController: true,
            replace: true,
            transclude: true
        };

        function link(scope, element, attrs, ctrl)
        {
            attrs.$observe('id', function(_newId)
            {
                ctrl.id = _newId;
            });
        }
    }

    LxDialogController.$inject = ['$element', '$interval', '$rootScope', '$scope', '$timeout', '$window', 'LxDepthService', 'LxEventSchedulerService'];

    function LxDialogController($element, $interval, $rootScope, $scope, $timeout, $window, LxDepthService, LxEventSchedulerService)
    {
        var lxDialog = this;
        var dialogFilter = angular.element('
',
        {
            class: 'dialog-filter'
        });
        var dialogHeight;
        var dialogInterval;
        var dialogScrollable;
        var elementParent = $element.parent();
        var idEventScheduler;
        var resizeDebounce;
        var windowHeight;

        lxDialog.autoClose = angular.isDefined(lxDialog.autoClose) ? lxDialog.autoClose : true;
        lxDialog.escapeClose = angular.isDefined(lxDialog.escapeClose) ? lxDialog.escapeClose : true;
        lxDialog.isOpen = false;

        $scope.$on('lx-dialog__open', function(event, id)
        {
            if (id === lxDialog.id)
            {
                open();
            }
        });

        $scope.$on('lx-dialog__close', function(event, id)
        {
            if (id === lxDialog.id)
            {
                close();
            }
        });

        ////////////

        function checkDialogHeight()
        {
            var dialog = $element;
            var dialogHeader = dialog.find('.dialog__header');
            var dialogContent = dialog.find('.dialog__content');
            var dialogFooter = dialog.find('.dialog__footer');

            if (!dialogFooter.length)
            {
                dialogFooter = dialog.find('.dialog__actions');
            }

            if (angular.isUndefined(dialogHeader))
            {
                return;
            }

            var heightToCheck = 60 + dialogHeader.outerHeight() + dialogContent.outerHeight() + dialogFooter.outerHeight();

            if (dialogHeight === heightToCheck && windowHeight === $window.innerHeight)
            {
                return;
            }

            dialogHeight = heightToCheck;
            windowHeight = $window.innerHeight;

            if (heightToCheck >= $window.innerHeight)
            {
                dialog.addClass('dialog--is-fixed');

                dialogScrollable
                    .css(
                    {
                        top: dialogHeader.outerHeight(),
                        bottom: dialogFooter.outerHeight()
                    })
                    .off('scroll', checkScrollEnd)
                    .on('scroll', checkScrollEnd);
            }
            else
            {
                dialog.removeClass('dialog--is-fixed');

                dialogScrollable
                    .removeAttr('style')
                    .off('scroll', checkScrollEnd);
            }
        }

        function checkDialogHeightOnResize()
        {
            if (resizeDebounce)
            {
                $timeout.cancel(resizeDebounce);
            }

            resizeDebounce = $timeout(function()
            {
                checkDialogHeight();
            }, 200);
        }

        function checkScrollEnd()
        {
            if (dialogScrollable.scrollTop() + dialogScrollable.innerHeight() >= dialogScrollable[0].scrollHeight)
            {
                $rootScope.$broadcast('lx-dialog__scroll-end', lxDialog.id);

                dialogScrollable.off('scroll', checkScrollEnd);

                $timeout(function()
                {
                    dialogScrollable.on('scroll', checkScrollEnd);
                }, 500);
            }
        }

        function onKeyUp(_event)
        {
            if (_event.keyCode == 27)
            {
                close();
            }

            _event.stopPropagation();
        }

        function open()
        {
            LxDepthService.register();

            angular.element('body').css(
            {
                overflow: 'hidden'
            });

            dialogFilter
                .css('z-index', LxDepthService.getDepth())
                .appendTo('body');

            if (lxDialog.autoClose)
            {
                dialogFilter.on('click', function()
                {
                    close();
                });
            }

            if (lxDialog.escapeClose)
            {
                idEventScheduler = LxEventSchedulerService.register('keyup', onKeyUp);
            }

            $element
                .css('z-index', LxDepthService.getDepth() + 1)
                .appendTo('body')
                .show();

            $timeout(function()
            {
                $rootScope.$broadcast('lx-dialog__open-start', lxDialog.id);

                lxDialog.isOpen = true;

                dialogFilter.addClass('dialog-filter--is-shown');
                $element.addClass('dialog--is-shown');
            }, 100);

            $timeout(function()
            {
                if ($element.find('.dialog__scrollable').length === 0)
                {
                    $element.find('.dialog__content').wrap(angular.element('
',
                    {
                        class: 'dialog__scrollable'
                    }));
                }

                dialogScrollable = $element.find('.dialog__scrollable');
            }, 200);

            $timeout(function()
            {
                $rootScope.$broadcast('lx-dialog__open-end', lxDialog.id);
            }, 700);

            dialogInterval = $interval(function()
            {
                checkDialogHeight();
            }, 500);

            angular.element($window).on('resize', checkDialogHeightOnResize);
        }

        function close()
        {
            if (angular.isDefined(idEventScheduler))
            {
                LxEventSchedulerService.unregister(idEventScheduler);
                idEventScheduler = undefined;
            }

            angular.element($window).off('resize', checkDialogHeightOnResize);
            $element.find('.dialog__scrollable').off('scroll', checkScrollEnd);

            $rootScope.$broadcast('lx-dialog__close-start', lxDialog.id);

            if (resizeDebounce)
            {
                $timeout.cancel(resizeDebounce);
            }

            $interval.cancel(dialogInterval);

            dialogFilter.removeClass('dialog-filter--is-shown');
            $element.removeClass('dialog--is-shown');

            $timeout(function()
            {
                angular.element('body').css(
                {
                    overflow: 'visible'
                });

                dialogFilter.remove();

                $element
                    .hide()
                    .removeClass('dialog--is-fixed')
                    .appendTo(elementParent);

                lxDialog.isOpen = false;
                dialogHeight = undefined;
                $rootScope.$broadcast('lx-dialog__close-end', lxDialog.id);
            }, 600);
        }
    }

    function lxDialogHeader()
    {
        return {
            restrict: 'E',
            template: '

',
            replace: true,
            transclude: true
        };
    }

    function lxDialogContent()
    {
        return {
            restrict: 'E',
            template: '

',
            replace: true,
            transclude: true
        };
    }

    function lxDialogFooter()
    {
        return {
            restrict: 'E',
            template: '

',
            replace: true,
            transclude: true
        };
    }

    lxDialogClose.$inject = ['LxDialogService'];

    function lxDialogClose(LxDialogService)
    {
        return {
            restrict: 'A',
            link: function(scope, element)
            {
                element.on('click', function()
                {
                    LxDialogService.close(element.parents('.dialog').attr('id'));
                });

                scope.$on('$destroy', function()
                {
                    element.off();
                });
            }
        };
    }
})();<commit_msg>fix dialog: close dialog on destroy<commit_after>(function()
{
    'use strict';

    angular
        .module('lumx.dialog')
        .directive('lxDialog', lxDialog)
        .directive('lxDialogHeader', lxDialogHeader)
        .directive('lxDialogContent', lxDialogContent)
        .directive('lxDialogFooter', lxDialogFooter)
        .directive('lxDialogClose', lxDialogClose);

    function lxDialog()
    {
        return {
            restrict: 'E',
            template: '

',
            scope:
            {
                autoClose: '=?lxAutoClose',
                escapeClose: '=?lxEscapeClose',
                size: '@?lxSize'
            },
            link: link,
            controller: LxDialogController,
            controllerAs: 'lxDialog',
            bindToController: true,
            replace: true,
            transclude: true
        };

        function link(scope, element, attrs, ctrl)
        {
            attrs.$observe('id', function(_newId)
            {
                ctrl.id = _newId;
            });
        }
    }

    LxDialogController.$inject = ['$element', '$interval', '$rootScope', '$scope', '$timeout', '$window', 'LxDepthService', 'LxEventSchedulerService'];

    function LxDialogController($element, $interval, $rootScope, $scope, $timeout, $window, LxDepthService, LxEventSchedulerService)
    {
        var lxDialog = this;
        var dialogFilter = angular.element('
',
        {
            class: 'dialog-filter'
        });
        var dialogHeight;
        var dialogInterval;
        var dialogScrollable;
        var elementParent = $element.parent();
        var idEventScheduler;
        var resizeDebounce;
        var windowHeight;

        lxDialog.autoClose = angular.isDefined(lxDialog.autoClose) ? lxDialog.autoClose : true;
        lxDialog.escapeClose = angular.isDefined(lxDialog.escapeClose) ? lxDialog.escapeClose : true;
        lxDialog.isOpen = false;

        $scope.$on('lx-dialog__open', function(event, id)
        {
            if (id === lxDialog.id)
            {
                open();
            }
        });

        $scope.$on('lx-dialog__close', function(event, id)
        {
            if (id === lxDialog.id)
            {
                close();
            }
        });

        $scope.$on('$destroy', function()
        {
            close();
        });

        ////////////

        function checkDialogHeight()
        {
            var dialog = $element;
            var dialogHeader = dialog.find('.dialog__header');
            var dialogContent = dialog.find('.dialog__content');
            var dialogFooter = dialog.find('.dialog__footer');

            if (!dialogFooter.length)
            {
                dialogFooter = dialog.find('.dialog__actions');
            }

            if (angular.isUndefined(dialogHeader))
            {
                return;
            }

            var heightToCheck = 60 + dialogHeader.outerHeight() + dialogContent.outerHeight() + dialogFooter.outerHeight();

            if (dialogHeight === heightToCheck && windowHeight === $window.innerHeight)
            {
                return;
            }

            dialogHeight = heightToCheck;
            windowHeight = $window.innerHeight;

            if (heightToCheck >= $window.innerHeight)
            {
                dialog.addClass('dialog--is-fixed');

                dialogScrollable
                    .css(
                    {
                        top: dialogHeader.outerHeight(),
                        bottom: dialogFooter.outerHeight()
                    })
                    .off('scroll', checkScrollEnd)
                    .on('scroll', checkScrollEnd);
            }
            else
            {
                dialog.removeClass('dialog--is-fixed');

                dialogScrollable
                    .removeAttr('style')
                    .off('scroll', checkScrollEnd);
            }
        }

        function checkDialogHeightOnResize()
        {
            if (resizeDebounce)
            {
                $timeout.cancel(resizeDebounce);
            }

            resizeDebounce = $timeout(function()
            {
                checkDialogHeight();
            }, 200);
        }

        function checkScrollEnd()
        {
            if (dialogScrollable.scrollTop() + dialogScrollable.innerHeight() >= dialogScrollable[0].scrollHeight)
            {
                $rootScope.$broadcast('lx-dialog__scroll-end', lxDialog.id);

                dialogScrollable.off('scroll', checkScrollEnd);

                $timeout(function()
                {
                    dialogScrollable.on('scroll', checkScrollEnd);
                }, 500);
            }
        }

        function onKeyUp(_event)
        {
            if (_event.keyCode == 27)
            {
                close();
            }

            _event.stopPropagation();
        }

        function open()
        {
            LxDepthService.register();

            angular.element('body').css(
            {
                overflow: 'hidden'
            });

            dialogFilter
                .css('z-index', LxDepthService.getDepth())
                .appendTo('body');

            if (lxDialog.autoClose)
            {
                dialogFilter.on('click', function()
                {
                    close();
                });
            }

            if (lxDialog.escapeClose)
            {
                idEventScheduler = LxEventSchedulerService.register('keyup', onKeyUp);
            }

            $element
                .css('z-index', LxDepthService.getDepth() + 1)
                .appendTo('body')
                .show();

            $timeout(function()
            {
                $rootScope.$broadcast('lx-dialog__open-start', lxDialog.id);

                lxDialog.isOpen = true;

                dialogFilter.addClass('dialog-filter--is-shown');
                $element.addClass('dialog--is-shown');
            }, 100);

            $timeout(function()
            {
                if ($element.find('.dialog__scrollable').length === 0)
                {
                    $element.find('.dialog__content').wrap(angular.element('
',
                    {
                        class: 'dialog__scrollable'
                    }));
                }

                dialogScrollable = $element.find('.dialog__scrollable');
            }, 200);

            $timeout(function()
            {
                $rootScope.$broadcast('lx-dialog__open-end', lxDialog.id);
            }, 700);

            dialogInterval = $interval(function()
            {
                checkDialogHeight();
            }, 500);

            angular.element($window).on('resize', checkDialogHeightOnResize);
        }

        function close()
        {
            if (angular.isDefined(idEventScheduler))
            {
                LxEventSchedulerService.unregister(idEventScheduler);
                idEventScheduler = undefined;
            }

            angular.element($window).off('resize', checkDialogHeightOnResize);
            $element.find('.dialog__scrollable').off('scroll', checkScrollEnd);

            $rootScope.$broadcast('lx-dialog__close-start', lxDialog.id);

            if (resizeDebounce)
            {
                $timeout.cancel(resizeDebounce);
            }

            $interval.cancel(dialogInterval);

            dialogFilter.removeClass('dialog-filter--is-shown');
            $element.removeClass('dialog--is-shown');

            $timeout(function()
            {
                angular.element('body').css(
                {
                    overflow: 'visible'
                });

                dialogFilter.remove();

                $element
                    .hide()
                    .removeClass('dialog--is-fixed')
                    .appendTo(elementParent);

                lxDialog.isOpen = false;
                dialogHeight = undefined;
                $rootScope.$broadcast('lx-dialog__close-end', lxDialog.id);
            }, 600);
        }
    }

    function lxDialogHeader()
    {
        return {
            restrict: 'E',
            template: '

',
            replace: true,
            transclude: true
        };
    }

    function lxDialogContent()
    {
        return {
            restrict: 'E',
            template: '

',
            replace: true,
            transclude: true
        };
    }

    function lxDialogFooter()
    {
        return {
            restrict: 'E',
            template: '

',
            replace: true,
            transclude: true
        };
    }

    lxDialogClose.$inject = ['LxDialogService'];

    function lxDialogClose(LxDialogService)
    {
        return {
            restrict: 'A',
            link: function(scope, element)
            {
                element.on('click', function()
                {
                    LxDialogService.close(element.parents('.dialog').attr('id'));
                });

                scope.$on('$destroy', function()
                {
                    element.off();
                });
            }
        };
    }
})();<|endoftext|>


<commit_before>import  * as THREE from '../node_modules/three/build/three.module.js'

const cube = new THREE.CubeGeometry(1, 1, 1);
const wiremat = new THREE.MeshBasicMaterial({ color: 0x00FF88, wireframe: true, wireframeLinewidth: 1, transparent: true, opacity: 0.3 });

class MeshBVHVisualizer extends THREE.Object3D {
    constructor(mesh, depth = 10) {
        super();

        this.depth = depth;
        this._mesh = mesh;
        this._boundsTree = null;

        this.update();
    }

    update() {
        if (this._mesh.geometry.boundsTree !== this._boundsTree || this._oldDepth !== this.depth) {
            while (this.children.length) this.remove(this.children.pop());

            this._oldDepth = this.depth;
            this._boundsTree = this._mesh.geometry.boundsTree;

            if (this._boundsTree) {
                const recurse = (n, d) => {
                    if (d === this.depth) return;

                    if (d === this.depth - 1 || n.children.length === 0) {
                        const m = new THREE.Mesh(cube, wiremat);
                        this.add(m);
                        n.boundingBox.getCenter(m.position)
                        m.scale.subVectors(n.boundingBox.max, n.boundingBox.min);
                        m.raycast = () => [];
                    }
                    n.children.forEach(n => recurse(n, d + 1))
                }

                recurse(this._boundsTree._root, 0);
            }
        }

        this.position.copy(this._mesh.position);
        this.rotation.copy(this._mesh.rotation);
        this.scale.copy(this._mesh.scale);
    }
}

export default MeshBVHVisualizer;<commit_msg>Fix box line rendering<commit_after>import  * as THREE from '../node_modules/three/build/three.module.js'

const cube = new THREE.CubeGeometry(1, 1, 1);
const wiremat = new THREE.LineBasicMaterial({ color: 0x00FF88, wireframe: true, wireframeLinewidth: 1, transparent: true, opacity: 0.3 });
const boxGeom = new THREE.Box3Helper().geometry;

console.log();

class MeshBVHVisualizer extends THREE.Object3D {
    constructor(mesh, depth = 10) {
        super();

        this.depth = depth;
        this._mesh = mesh;
        this._boundsTree = null;

        this.update();
    }

    update() {
        if (this._mesh.geometry.boundsTree !== this._boundsTree || this._oldDepth !== this.depth) {
            while (this.children.length) this.remove(this.children.pop());

            this._oldDepth = this.depth;
            this._boundsTree = this._mesh.geometry.boundsTree;

            if (this._boundsTree) {
                const recurse = (n, d) => {
                    if (d === this.depth) return;

                    if (d === this.depth - 1 || n.children.length === 0) {
                        let m = new THREE.LineSegments(boxGeom, wiremat);
                        n.boundingBox.getCenter(m.position)
                        m.scale.subVectors(n.boundingBox.max, n.boundingBox.min).multiplyScalar(0.5);
                        this.add(m);
                    }
                    n.children.forEach(n => recurse(n, d + 1))
                }

                recurse(this._boundsTree._root, 0);
            }
        }

        this.position.copy(this._mesh.position);
        this.rotation.copy(this._mesh.rotation);
        this.scale.copy(this._mesh.scale);
    }
}

export default MeshBVHVisualizer;<|endoftext|>


<commit_before>"use strict"

var mache = require('../index.js')
  , assert = require('assert')
  , temp = require('temp')
  , fs = require('fs')
  , path = require('path')

// Temporary directory to base our mache out of.
var testDir = fs.realpathSync(temp.mkdirSync())

// Create some files in the temporary directory so we have something to test.
var testData1 = '{"id": 1}'
fs.writeFileSync(path.join(testDir, '1.json'), testData1)
var testData2 = '{"id": 2}'
fs.writeFileSync(path.join(testDir, '2.json'), testData2)

// Set up the mache object we'll use for most of these tests.
var testMache
beforeEach(function () {
	testMache = mache.create(testDir, function (filePath, data, macheUpdate) {
		var testObj = JSON.parse(data)
		testObj._path = filePath
		return macheUpdate(testObj)
	})
})

describe('#get', function () {
	it('should return the correct object for the given file', function (done) {
		testMache.get('1.json', function (err, testObj1) {
			assert.ifError(err)
			assert.strictEqual(testObj1.id, 1)
			done()
		})
	})

    it("should return an error if the requested file does not exist", function (done) {
        testMache.get('foo.json', function (err, testObjFoo) {
            assert.ok(err)
            done()
        })
    })

    it("should return an error if the requested file is outside the base directory", function (done) {
        var outsideJSONFile = path.join(__dirname, 'data/foo.json')
        var relativePathToOutsideFile = path.relative(testDir, outsideJSONFile)
        testMache.get(relativePathToOutsideFile, function (err, testObjFoo) {
            assert.ok(err)
            done()
        })
    })

    it("should return the exact same object if underlying file has not changed", function (done) {
        testMache.get('1.json', function (err, expectedObj) {
            assert.ifError(err)
            testMache.get('1.json', function (err, cachedObj) {
                assert.ifError(err)
                assert.strictEqual(expectedObj, cachedObj)
                done()
            })
        })
    })

    it("should return a new object if the underlying file has changed", function (done) {
        setModifiedTimeOnTestFileToDistantPast('2.json')
        testMache.get('2.json', function (err, objFromFirstGet) {
            assert.ifError(err)

            setModifiedTimeOnTestFileToNow('2.json')
            testMache.get('2.json', function (err, objFromSecondGet) {
                assert.ifError(err)

                assert.notStrictEqual(objFromFirstGet, objFromSecondGet)
                done()
            })
        })
    })
})

describe("#baseDir", function () {
    it("should return the full path even when created with a relative path", function (done) {
        // Make our own testMache using a relative path
        testMache = mache.create('.', function (fp, d, macheUpdate) {
            macheUpdate(null)
        })

        var actualPath = fs.realpathSync('.')
        testMache.baseDir(function (err, machePath) {
            assert.ifError(err)
            assert.strictEqual(actualPath, machePath)
            done()
        })
    })

    it("should return an error if the directory doesn't exist", function (done) {
        // Make our own testMache using a non-existent path
        testMache = mache.create('./does/not/exist/i/hope', function (fp, d, macheUpdate) {
            macheUpdate(null)
        })

        testMache.baseDir(function (err, machePath) {
            assert.ok(err)
            done()
        })
    })

    it("should return the same directory on subsequent calls", function (done) {
        testMache.baseDir(function (err, firstResult) {
            assert.ifError(err)
            assert.ok(firstResult)

            testMache.baseDir(function (err, secondResult) {
                assert.ifError(err)
                assert.ok(secondResult)

                assert.strictEqual(firstResult, secondResult)
                done()
            })
        })
    })
})

describe("#on invalidation", function () {
    it("should call the invalidation callback with the old object when a file changes", function (done) {
        var objFromFirstGet
          , invalidationEventFired

        testMache.on('invalidation', function (err, invalidatedObj) {
            assert.ifError(err)
            assert.ok(objFromFirstGet)
            assert.ok(invalidatedObj)
            assert.strictEqual(objFromFirstGet, invalidatedObj)
            invalidationEventFired = true
        })

        testMache.get('2.json', function (err, _objFromFirstGet) {
            assert.ifError(err)

            objFromFirstGet = _objFromFirstGet

            setModifiedTimeOnTestFileToDistantPast('2.json')
            testMache.get('2.json', function (err, objFromSecondGet) {
                assert.ifError(err)
                assert.ok(invalidationEventFired)
                done()
            })
        })
    })
})

function setModifiedTimeOnTestFileToDistantPast (testFile) {
    var testFilePath = path.join(testDir, testFile)
    var oldTime = new Date("June 4, 1981 18:00:00")
    fs.utimesSync(testFilePath, oldTime, oldTime)
}

function setModifiedTimeOnTestFileToNow (testFile) {
    var testFilePath = path.join(testDir, testFile)
    var newTime = new Date()
    fs.utimesSync(testFilePath, newTime, newTime)
}
<commit_msg>Failing test for cache stampede prevention.<commit_after>"use strict"

var mache = require('../index.js')
  , assert = require('assert')
  , temp = require('temp')
  , fs = require('fs')
  , path = require('path')

// Temporary directory to base our mache out of.
var testDir = fs.realpathSync(temp.mkdirSync())

// Create some files in the temporary directory so we have something to test.
var testData1 = '{"id": 1}'
fs.writeFileSync(path.join(testDir, '1.json'), testData1)
var testData2 = '{"id": 2}'
fs.writeFileSync(path.join(testDir, '2.json'), testData2)

// Set up the mache object we'll use for most of these tests.
var testMache
beforeEach(function () {
	testMache = mache.create(testDir, function (filePath, data, macheUpdate) {
		var testObj = JSON.parse(data)
		testObj._path = filePath
		return macheUpdate(testObj)
	})
})

describe('#get', function () {
	it('should return the correct object for the given file', function (done) {
		testMache.get('1.json', function (err, testObj1) {
			assert.ifError(err)
			assert.strictEqual(testObj1.id, 1)
			done()
		})
	})

    it("should return an error if the requested file does not exist", function (done) {
        testMache.get('foo.json', function (err, testObjFoo) {
            assert.ok(err)
            done()
        })
    })

    it("should return an error if the requested file is outside the base directory", function (done) {
        var outsideJSONFile = path.join(__dirname, 'data/foo.json')
        var relativePathToOutsideFile = path.relative(testDir, outsideJSONFile)
        testMache.get(relativePathToOutsideFile, function (err, testObjFoo) {
            assert.ok(err)
            done()
        })
    })

    it("should return the exact same object if underlying file has not changed", function (done) {
        testMache.get('1.json', function (err, expectedObj) {
            assert.ifError(err)
            testMache.get('1.json', function (err, cachedObj) {
                assert.ifError(err)
                assert.strictEqual(expectedObj, cachedObj)
                done()
            })
        })
    })

    it("should return a new object if the underlying file has changed", function (done) {
        setModifiedTimeOnTestFileToDistantPast('2.json')
        testMache.get('2.json', function (err, objFromFirstGet) {
            assert.ifError(err)

            setModifiedTimeOnTestFileToNow('2.json')
            testMache.get('2.json', function (err, objFromSecondGet) {
                assert.ifError(err)

                assert.notStrictEqual(objFromFirstGet, objFromSecondGet)
                done()
            })
        })
    })

    it("should return the cached object when object creation callback is in-flight (to prevent cache stampedes)", function (done) {
        // To test this, we make a object creation callback that is slow on
        // the first call, but fast on subsequent calls. Calling mache.get()
        // twice, we make sure the object from the first get is the first
        // object that gets created.

        var objectsCreated = 0
        testMache = mache.create(testDir, function (filePath, data, macheUpdate) {
            var obj = { id: objectsCreated }
            if (objectsCreated === 0) {
                setTimeout(function () { macheUpdate(obj) }, 20)
            }
            else {
                macheUpdate(obj)
            }
            objectsCreated += 1
        })

        var obj1, obj2
        testMache.get('1.json', function (err, obj) {
            obj1 = obj
            runAssertionsIfDone()
        })
        testMache.get('1.json', function (err, obj) {
            obj2 = obj
            runAssertionsIfDone()
        })

        function runAssertionsIfDone () {
            if (obj1 && obj2) {
                assert.strictEqual(obj1.id, obj2.id)
                assert.strictEqual(obj1.id, 0)
                done()
            }
        }
    })
})

describe("#baseDir", function () {
    it("should return the full path even when created with a relative path", function (done) {
        // Make our own testMache using a relative path
        testMache = mache.create('.', function (fp, d, macheUpdate) {
            macheUpdate(null)
        })

        var actualPath = fs.realpathSync('.')
        testMache.baseDir(function (err, machePath) {
            assert.ifError(err)
            assert.strictEqual(actualPath, machePath)
            done()
        })
    })

    it("should return an error if the directory doesn't exist", function (done) {
        // Make our own testMache using a non-existent path
        testMache = mache.create('./does/not/exist/i/hope', function (fp, d, macheUpdate) {
            macheUpdate(null)
        })

        testMache.baseDir(function (err, machePath) {
            assert.ok(err)
            done()
        })
    })

    it("should return the same directory on subsequent calls", function (done) {
        testMache.baseDir(function (err, firstResult) {
            assert.ifError(err)
            assert.ok(firstResult)

            testMache.baseDir(function (err, secondResult) {
                assert.ifError(err)
                assert.ok(secondResult)

                assert.strictEqual(firstResult, secondResult)
                done()
            })
        })
    })
})

describe("#on invalidation", function () {
    it("should call the invalidation callback with the old object when a file changes", function (done) {
        var objFromFirstGet
          , invalidationEventFired

        testMache.on('invalidation', function (err, invalidatedObj) {
            assert.ifError(err)
            assert.ok(objFromFirstGet)
            assert.ok(invalidatedObj)
            assert.strictEqual(objFromFirstGet, invalidatedObj)
            invalidationEventFired = true
        })

        testMache.get('2.json', function (err, _objFromFirstGet) {
            assert.ifError(err)

            objFromFirstGet = _objFromFirstGet

            setModifiedTimeOnTestFileToDistantPast('2.json')
            testMache.get('2.json', function (err, objFromSecondGet) {
                assert.ifError(err)
                assert.ok(invalidationEventFired)
                done()
            })
        })
    })
})

function setModifiedTimeOnTestFileToDistantPast (testFile) {
    var testFilePath = path.join(testDir, testFile)
    var oldTime = new Date("June 4, 1981 18:00:00")
    fs.utimesSync(testFilePath, oldTime, oldTime)
}

function setModifiedTimeOnTestFileToNow (testFile) {
    var testFilePath = path.join(testDir, testFile)
    var newTime = new Date()
    fs.utimesSync(testFilePath, newTime, newTime)
}
<|endoftext|>


<commit_before><commit_msg>render translation in commentary view<commit_after><|endoftext|>


<commit_before>import {Widget} from './widget'
import {compose} from 'compose'
import {withContext} from 'context'
import PropTypes from 'prop-types'
import React from 'react'
import _ from 'lodash'
import withForwardedRef from 'ref'

const Context = React.createContext()

export const withButtonGroupContext = withContext(Context, 'buttonGroupContext')

const _ButtonGroup = ({className, layout, alignment, spacing, framed, label, disabled, onMouseOver, onMouseOut, forwardedRef, children}) => {
    const mapChild = (child, index, childrenCount) => {
        const joinLeft = childrenCount > 1 && index !== 0
        const joinRight = childrenCount > 1 && index !== childrenCount - 1
        return (
            <Context.Provider value={{joinLeft, joinRight}}>
                {child}
            </Context.Provider>
        )
    }

    const mapChildren = children =>
        React.Children.map(children, (child, index) =>
            mapChild(child, index, children.length)
        )

    return (
        <Widget
            ref={forwardedRef}
            className={className}
            label={label}
            layout={layout}
            alignment={alignment}
            spacing={spacing}
            framed={framed}
            disabled={disabled}
            onMouseOver={onMouseOver}
            onMouseOut={onMouseOut}>
            {spacing === 'none' ? mapChildren(_.compact(children)) : children}
        </Widget>
    )
}

export const ButtonGroup = compose(
    _ButtonGroup,
    withForwardedRef()
)

ButtonGroup.propTypes = {
    alignment: PropTypes.any,
    children: PropTypes.any,
    className: PropTypes.string,
    disabled: PropTypes.any,
    framed: PropTypes.any,
    label: PropTypes.any,
    layout: PropTypes.any,
    spacing: PropTypes.any,
    onMouseOut: PropTypes.func,
    onMouseOver: PropTypes.func
}

ButtonGroup.defaultProps = {
    alignment: 'left',
    layout: 'horizontal',
    spacing: 'compact'
}
<commit_msg>Implemented ButtonGroup contentClassName.<commit_after>import {Widget} from './widget'
import {compose} from 'compose'
import {withContext} from 'context'
import PropTypes from 'prop-types'
import React from 'react'
import _ from 'lodash'
import withForwardedRef from 'ref'

const Context = React.createContext()

export const withButtonGroupContext = withContext(Context, 'buttonGroupContext')

const _ButtonGroup = ({className, contentClassName, layout, alignment, spacing, framed, label, disabled, onMouseOver, onMouseOut, forwardedRef, children}) => {
    const mapChild = (child, index, childrenCount) => {
        const joinLeft = childrenCount > 1 && index !== 0
        const joinRight = childrenCount > 1 && index !== childrenCount - 1
        return (
            <Context.Provider value={{joinLeft, joinRight}}>
                {child}
            </Context.Provider>
        )
    }

    const mapChildren = children =>
        React.Children.map(children, (child, index) =>
            mapChild(child, index, children.length)
        )

    return (
        <Widget
            ref={forwardedRef}
            className={className}
            contentClassName={contentClassName}
            label={label}
            layout={layout}
            alignment={alignment}
            spacing={spacing}
            framed={framed}
            disabled={disabled}
            onMouseOver={onMouseOver}
            onMouseOut={onMouseOut}>
            {spacing === 'none' ? mapChildren(_.compact(children)) : children}
        </Widget>
    )
}

export const ButtonGroup = compose(
    _ButtonGroup,
    withForwardedRef()
)

ButtonGroup.propTypes = {
    alignment: PropTypes.any,
    children: PropTypes.any,
    className: PropTypes.string,
    contentClassName: PropTypes.string,
    disabled: PropTypes.any,
    framed: PropTypes.any,
    label: PropTypes.any,
    layout: PropTypes.any,
    spacing: PropTypes.any,
    onMouseOut: PropTypes.func,
    onMouseOver: PropTypes.func
}

ButtonGroup.defaultProps = {
    alignment: 'left',
    layout: 'horizontal',
    spacing: 'compact'
}
<|endoftext|>


<commit_before>/*
 * Webtags v0.2.0-alpha1, Dashboard for webtags v1.0.4-alpha1
 * Webtags GitHub page (source code and links): https://github.com/earthperson/Webtags
 * Webtags site: http://earthperson.github.io/Webtags/
 * Dashboard for webtags: http://earthperson.github.io/Webtags/dashboard/
 * Author website: http://earthperson.info
 *
 * Copyright (c) 2013 Dmitry Ponomarev (email: ponomarev.dev@gmail.com)
 * Licensed under the MIT License: http://www.opensource.org/licenses/mit-license.php
 */
if (!window.JSON) {
	window.JSON = {
		parse: function (sJSON) { return eval("(" + sJSON + ")"); },
		stringify: function (vContent) {
			if (vContent instanceof Object) {
				var sOutput = "";
				if (vContent.constructor === Array) {
					for (var nId = 0; nId < vContent.length; sOutput += this.stringify(vContent[nId]) + ",", nId++);
					return "[" + sOutput.substr(0, sOutput.length - 1) + "]";
				}
				if (vContent.toString !== Object.prototype.toString) { return "\"" + vContent.toString().replace(/"/g, "\\$&") + "\""; }
				for (var sProp in vContent) { sOutput += "\"" + sProp.replace(/"/g, "\\$&") + "\":" + this.stringify(vContent[sProp]) + ","; }
				return "{" + sOutput.substr(0, sOutput.length - 1) + "}";
			}
			return typeof vContent === "string" ? "\"" + vContent.replace(/"/g, "\\$&") + "\"" : String(vContent);
		}
	};
}
$(function() {
	$.fn.setCheckboxesIndex = function () {
		this.each(function(index) {
			$(this).parent().contents().filter(function() {
				return this.nodeType === 3;
			}).remove();
			$(this).after('#'+(++index));
		});
		return this;
	};
	$.fn.updateButtonValue = function(checked) {
		this.parent().contents().filter(function() {
			return this.nodeType === 3;
		}).remove();
		this.after(checked ? this.data('values')[0] : this.data('values')[1]);
	};
	$.fn.serializeObject = function() {
		var o = {},
			items = [],
			item = {},
			v = '',
			a = this.serializeArray();
		$.each(a, function() {
			if(this.name === 'label') {
				v = $.trim(this.value);
				if (v) {
					item['label'] = v;
				}
			}
			else if (item['label']) {
				v = $.trim(this.value);
				if (v) {
					item['url'] = v;
					items.push(item);
					item = {};
				}
			}
		});
		if (items.length > 0) {
			o['items'] = items;
			o['type'] = $('.panel input[name="type"]:checked').val();
			o['grid'] = $('.panel input[name="grid"]:checked').val() == 1;
			o['border'] = $('.panel :checkbox[value="border"]').prop('checked');
		}
		return o;
	};
	$.fn.validate = function() {
		var re = $(this).attr('type') == 'text' ? /.{1,}/ : /\..{1,}$/;
		if (!re.test($(this).val())) {
			$(this).parent().addClass('has-error');
		}
		else {
			$(this).parent().removeClass('has-error');
		}
		return this;
	};
	function stripTags(str){
		return str.replace(/<\/?[^>]+>/gi, '');
	}
	$.fn.setLaunchAble = function() {
		var o = $('.col-xs-10 .form-group:not(.has-error)').children('input').serializeObject();
		if (o instanceof Object && o['items']) {
			$('.col-md-4 .btn-primary:last').removeAttr('disabled'); // Export
			$('.col-md-4 .btn-success:last').removeAttr('disabled'); // Launch
		}
		else {
			$('.col-md-4 .btn-primary:last').attr('disabled','disabled'); // Export
			$('.col-md-4 .btn-success:last').attr('disabled','disabled'); // Launch
		}
		return this;
	};
	$('.col-md-4 .btn-primary:first').click(function() {
		var row = $('.col-md-8 .row:first').clone(true),
			index = $('.btn-danger').size(),
			checkbox = $(':checkbox', row);
		$('.btn-group', row).remove();
		$('input:not(:checkbox)', row).val('').parent().removeClass('has-error');
		checkbox.prop('checked', false).parent().contents().filter(function() {
		    return this.nodeType === 3;
		}).remove();
		checkbox.after('#'+index);
		$('.row:first', row).removeClass('hidden');
		row.appendTo('.col-md-8');
		$(window).scrollTop(row.offset().top);
	});
	$('.btn-danger:not(.dropdown-toggle)').on('click', function() { // Remove
		if($('.btn-danger').size() > 1) {
			$(this).parents('.row:eq(1)').remove();
			$(':checkbox', $('.col-md-8')).setCheckboxesIndex().setLaunchAble();
		}
	});
	$('.btn-group .dropdown-menu a').click(function(event) {
		event.preventDefault();
		var index = $(this).parent().index(),
			checkboxes = $(this).closest('.col-md-8').find(':checkbox');
		if (index == 0) { // Check all
			checkboxes.prop('checked', true);
		}
		else if (index == 1) { // Uncheck all
			checkboxes.prop('checked', false);
		}
		else if (index == 3) { // Remove checked
			$($(this).closest('.col-md-8').children('.row:not(:first-child)')).each(function() {
				if ($(this).has(':checked').length > 0) {
					$(this).remove();
				}
			});
			$(':checkbox', $('.col-md-8')).setCheckboxesIndex().setLaunchAble();
		}
		else if (index == 4) { // Empty checked
			$('.col-md-8 .row:has(:checked):not(:first) input:not(:checkbox)').val('').parent().removeClass('has-error').setLaunchAble();
		}
		else if (index == 6) { // Empty all
			$('.col-md-8 .row input:not(:checkbox)').val('').parent().removeClass('has-error').setLaunchAble();
		}
	});
	$('.glyphicon-export')
		.data('values', [' Export as full code', ' Export JSON'])
		.updateButtonValue($(':checkbox[value="exportType"]').prop('checked')); // F5 (page reload) fix
	$(':checkbox[value="exportType"]').click(function() {
		$('.glyphicon-export').updateButtonValue($(this).prop('checked'));
	});
	$('div[role="complementary"]').affix({
		offset: {
			top: 0
		}
	});
	$('.col-xs-10 input').keyup(function() {
		$(this).validate().setLaunchAble();
	});
	$('.col-xs-10 input').change(function() {
		var v = $.trim($(this).val());
		$(this).val(v).validate().setLaunchAble();
	});
	$('.col-xs-10 input[type="url"]').change(function() {
		var v = $.trim($(this).val());
		if(v && !/^.*?:\/\//.test(v)) {
			$(this).val('http://'+v);
		}
	});
	var modalImportBody = $('#modalImport .modal-body').html();
	$('.col-md-4 .btn-primary:eq(1)').click(function() { // Import
		$('#modalImport .modal-body').html(modalImportBody);
		$('#modalImport').modal();
		$(this).addClass('active');
		$('#modalImport').on('hidden.bs.modal', function (e) {
			$('.col-md-4 .btn-primary:eq(1)').removeClass('active');
		});
	});
	$('.modal .btn-primary').click(function() {
		var data = $('#modalImport textarea').val();
		try {
			data = JSON.parse($.trim(stripTags(data).replace(/(?:\/\*(?:[\s\S]*?)\*\/)|(?:([\s;])+\/\/(?:.*)$)/gm, '$1').replace(/new Webtags\(((.*\s*)*)\);/i, '$1')));
			$('#modalImport').modal('hide');
			$('.btn-group .dropdown-menu li:eq(0) a').click();
			$('.btn-group .dropdown-menu li:eq(3) a').click();
			$('.panel input[name="type"]').filter('input[value="'+data.type+'"]').prop('checked', true);
			$('.panel :checkbox[value="border"]').prop('checked', data.border);
			var inputs = $('.col-md-8 .row:last input:not(:checkbox)'),
			    i = 0,
			    n = data.items.length;
			for(; i < n; i++) {
				if (i > 0) {
					$('.col-md-4 .btn-primary:first').click();
					inputs = $('.col-md-8 .row:last input:not(:checkbox)');
				}
				$(inputs).first().val(data.items[i].label).validate().setLaunchAble();
				$(inputs).last().val(data.items[i].url).validate().setLaunchAble();
			}
		}
		catch (e) {
			$('#modalImport .modal-body').html('
Incorrect format.
');
		}
	});
	$('.col-md-4 .btn-primary:last').click(function() { // Export
		$('#modalExport .modal-title').text(
				$(':checkbox[value="exportType"]').prop('checked') ? 'Export as full code' : 'Export JSON'
		);
		var t = JSON.stringify($('.col-xs-10 .form-group:not(.has-error)').children('input').serializeObject());
		if($(':checkbox[value="exportType"]').prop('checked')) {
			t = "\n"+
				"\n";
		}
		$('#modalExport textarea').text(t).focus(function() {
			var $this = $(this);
			$this.select();
			$this.mouseup(function(event) {
				event.preventDefault();
				// Prevent further mouseup intervention
				$this.unbind('mouseup');
			});
		});
		$('#modalExport').modal();
		$(this).addClass('active');
		$('#modalExport').on('hidden.bs.modal', function (e) {
			$('.col-md-4 .btn-primary:last').removeClass('active');
		});
	});
	$('.col-md-4 .btn-success:last').click(function() { // Launch
		var o = $('.col-xs-10 .form-group:not(.has-error)').children('input').serializeObject();
		if (o instanceof Object && o['items']) {
			$('#modalLaunch').modal();
			$(this).addClass('active');
			$('#modalLaunch').on('hidden.bs.modal', function (e) {
				$('.col-md-4 .btn-success:last').removeClass('active');
			});
			new Webtags(o);
		}
	});
});
<commit_msg>In the dashboard improved export as code for paste in a HTML page<commit_after>/*
 * Webtags v0.2.0-alpha1, Dashboard for webtags v1.0.4-alpha1
 * Webtags GitHub page (source code and links): https://github.com/earthperson/Webtags
 * Webtags site: http://earthperson.github.io/Webtags/
 * Dashboard for webtags: http://earthperson.github.io/Webtags/dashboard/
 * Author website: http://earthperson.info
 *
 * Copyright (c) 2013 Dmitry Ponomarev (email: ponomarev.dev@gmail.com)
 * Licensed under the MIT License: http://www.opensource.org/licenses/mit-license.php
 */
if (!window.JSON) {
	window.JSON = {
		parse: function (sJSON) { return eval("(" + sJSON + ")"); },
		stringify: function (vContent) {
			if (vContent instanceof Object) {
				var sOutput = "";
				if (vContent.constructor === Array) {
					for (var nId = 0; nId < vContent.length; sOutput += this.stringify(vContent[nId]) + ",", nId++);
					return "[" + sOutput.substr(0, sOutput.length - 1) + "]";
				}
				if (vContent.toString !== Object.prototype.toString) { return "\"" + vContent.toString().replace(/"/g, "\\$&") + "\""; }
				for (var sProp in vContent) { sOutput += "\"" + sProp.replace(/"/g, "\\$&") + "\":" + this.stringify(vContent[sProp]) + ","; }
				return "{" + sOutput.substr(0, sOutput.length - 1) + "}";
			}
			return typeof vContent === "string" ? "\"" + vContent.replace(/"/g, "\\$&") + "\"" : String(vContent);
		}
	};
}
$(function() {
	$.fn.setCheckboxesIndex = function () {
		this.each(function(index) {
			$(this).parent().contents().filter(function() {
				return this.nodeType === 3;
			}).remove();
			$(this).after('#'+(++index));
		});
		return this;
	};
	$.fn.updateButtonValue = function(checked) {
		this.parent().contents().filter(function() {
			return this.nodeType === 3;
		}).remove();
		this.after(checked ? this.data('values')[0] : this.data('values')[1]);
	};
	$.fn.serializeObject = function() {
		var o = {},
			items = [],
			item = {},
			v = '',
			a = this.serializeArray();
		$.each(a, function() {
			if(this.name === 'label') {
				v = $.trim(this.value);
				if (v) {
					item['label'] = v;
				}
			}
			else if (item['label']) {
				v = $.trim(this.value);
				if (v) {
					item['url'] = v;
					items.push(item);
					item = {};
				}
			}
		});
		if (items.length > 0) {
			o['items'] = items;
			o['type'] = $('.panel input[name="type"]:checked').val();
			o['grid'] = $('.panel input[name="grid"]:checked').val() == 1;
			o['border'] = $('.panel :checkbox[value="border"]').prop('checked');
		}
		return o;
	};
	$.fn.validate = function() {
		var re = $(this).attr('type') == 'text' ? /.{1,}/ : /\..{1,}$/;
		if (!re.test($(this).val())) {
			$(this).parent().addClass('has-error');
		}
		else {
			$(this).parent().removeClass('has-error');
		}
		return this;
	};
	function stripTags(str, re){
		if(re != null) {
			str = str.replace(re, '');
		}
		str = str.replace(/<\/?[^>]+>/gi, '');
		return str;
	}
	$.fn.setLaunchAble = function() {
		var o = $('.col-xs-10 .form-group:not(.has-error)').children('input').serializeObject();
		if (o instanceof Object && o['items']) {
			$('.col-md-4 .btn-primary:last').removeAttr('disabled'); // Export
			$('.col-md-4 .btn-success:last').removeAttr('disabled'); // Launch
		}
		else {
			$('.col-md-4 .btn-primary:last').attr('disabled','disabled'); // Export
			$('.col-md-4 .btn-success:last').attr('disabled','disabled'); // Launch
		}
		return this;
	};
	$('.col-md-4 .btn-primary:first').click(function() {
		var row = $('.col-md-8 .row:first').clone(true),
			index = $('.btn-danger').size(),
			checkbox = $(':checkbox', row);
		$('.btn-group', row).remove();
		$('input:not(:checkbox)', row).val('').parent().removeClass('has-error');
		checkbox.prop('checked', false).parent().contents().filter(function() {
		    return this.nodeType === 3;
		}).remove();
		checkbox.after('#'+index);
		$('.row:first', row).removeClass('hidden');
		row.appendTo('.col-md-8');
		$(window).scrollTop(row.offset().top);
	});
	$('.btn-danger:not(.dropdown-toggle)').on('click', function() { // Remove
		if($('.btn-danger').size() > 1) {
			$(this).parents('.row:eq(1)').remove();
			$(':checkbox', $('.col-md-8')).setCheckboxesIndex().setLaunchAble();
		}
	});
	$('.btn-group .dropdown-menu a').click(function(event) {
		event.preventDefault();
		var index = $(this).parent().index(),
			checkboxes = $(this).closest('.col-md-8').find(':checkbox');
		if (index == 0) { // Check all
			checkboxes.prop('checked', true);
		}
		else if (index == 1) { // Uncheck all
			checkboxes.prop('checked', false);
		}
		else if (index == 3) { // Remove checked
			$($(this).closest('.col-md-8').children('.row:not(:first-child)')).each(function() {
				if ($(this).has(':checked').length > 0) {
					$(this).remove();
				}
			});
			$(':checkbox', $('.col-md-8')).setCheckboxesIndex().setLaunchAble();
		}
		else if (index == 4) { // Empty checked
			$('.col-md-8 .row:has(:checked):not(:first) input:not(:checkbox)').val('').parent().removeClass('has-error').setLaunchAble();
		}
		else if (index == 6) { // Empty all
			$('.col-md-8 .row input:not(:checkbox)').val('').parent().removeClass('has-error').setLaunchAble();
		}
	});
	$('.glyphicon-export')
		.data('values', [' Export as full code', ' Export JSON'])
		.updateButtonValue($(':checkbox[value="exportType"]').prop('checked')); // F5 (page reload) fix
	$(':checkbox[value="exportType"]').click(function() {
		$('.glyphicon-export').updateButtonValue($(this).prop('checked'));
	});
	$('div[role="complementary"]').affix({
		offset: {
			top: 0
		}
	});
	$('.col-xs-10 input').keyup(function() {
		$(this).validate().setLaunchAble();
	});
	$('.col-xs-10 input').change(function() {
		var v = $.trim($(this).val());
		$(this).val(v).validate().setLaunchAble();
	});
	$('.col-xs-10 input[type="url"]').change(function() {
		var v = $.trim($(this).val());
		if(v && !/^.*?:\/\//.test(v)) {
			$(this).val('http://'+v);
		}
	});
	var modalImportBody = $('#modalImport .modal-body').html();
	$('.col-md-4 .btn-primary:eq(1)').click(function() { // Import
		$('#modalImport .modal-body').html(modalImportBody);
		$('#modalImport').modal();
		$(this).addClass('active');
		$('#modalImport').on('hidden.bs.modal', function (e) {
			$('.col-md-4 .btn-primary:eq(1)').removeClass('active');
		});
	});
	$('.modal .btn-primary').click(function() {
		var data = $('#modalImport textarea').val();
		try {
			data = JSON.parse($.trim(stripTags(data, /<canvas[^>]+>.*?<\/[^>]+>/gi).replace(/(?:\/\*(?:[\s\S]*?)\*\/)|(?:([\s;])+\/\/(?:.*)$)/gm, '$1').replace(/new Webtags\(((.*\s*)*)\);/i, '$1')));
			$('#modalImport').modal('hide');
			$('.btn-group .dropdown-menu li:eq(0) a').click();
			$('.btn-group .dropdown-menu li:eq(3) a').click();
			$('.panel input[name="type"]').filter('input[value="'+data.type+'"]').prop('checked', true);
			$('.panel :checkbox[value="border"]').prop('checked', data.border);
			var inputs = $('.col-md-8 .row:last input:not(:checkbox)'),
			    i = 0,
			    n = data.items.length;
			for(; i < n; i++) {
				if (i > 0) {
					$('.col-md-4 .btn-primary:first').click();
					inputs = $('.col-md-8 .row:last input:not(:checkbox)');
				}
				$(inputs).first().val(data.items[i].label).validate().setLaunchAble();
				$(inputs).last().val(data.items[i].url).validate().setLaunchAble();
			}
		}
		catch (e) {
			$('#modalImport .modal-body').html('
Incorrect format.
');
		}
	});
	$('.col-md-4 .btn-primary:last').click(function() { // Export
		$('#modalExport .modal-title').text(
				$(':checkbox[value="exportType"]').prop('checked') ? 'Export as full code' : 'Export JSON'
		);
		var t = JSON.stringify($('.col-xs-10 .form-group:not(.has-error)').children('input').serializeObject());
		if($(':checkbox[value="exportType"]').prop('checked')) {
			t = "<canvas id=\"webtags\">This text is displayed if your browser does not support HTML5 Canvas.</canvas>\n"+
				"\n"+
				"\n";
		}
		$('#modalExport textarea').text(t).focus(function() {
			var $this = $(this);
			$this.select();
			$this.mouseup(function(event) {
				event.preventDefault();
				// Prevent further mouseup intervention
				$this.unbind('mouseup');
			});
		});
		$('#modalExport').modal();
		$(this).addClass('active');
		$('#modalExport').on('hidden.bs.modal', function (e) {
			$('.col-md-4 .btn-primary:last').removeClass('active');
		});
	});
	$('.col-md-4 .btn-success:last').click(function() { // Launch
		var o = $('.col-xs-10 .form-group:not(.has-error)').children('input').serializeObject();
		if (o instanceof Object && o['items']) {
			$('#modalLaunch').modal();
			$(this).addClass('active');
			$('#modalLaunch').on('hidden.bs.modal', function (e) {
				$('.col-md-4 .btn-success:last').removeClass('active');
			});
			new Webtags(o);
		}
	});
});
<|endoftext|>


<commit_before>var conn = require('./conn.js')
var logger = (require('../logging/vip-winston')).Logger;
var uuidv4 = require('uuid/v4');
var resp = require('./response.js');

module.exports = {
  simpleQueryCallback: function(sqlQuery, params, callback) {
    conn.query(function(client) {
      client.query(sqlQuery, params, callback);
    });
  },
  simpleQueryResponder: function(sqlQuery, paramsFn) {
    return function(req, res) {

      var callback = function(err, result) {
        if(err) {
          logger.error(err.name + ": " + err.message);
          res.writeHead(500, {'Content-Type': 'text/plain'});
          res.write(err.name + ": " + err.message);
          res.end();
        } else {
          resp.writeResponse(result.rows, res);
        }
      }

      conn.query(function(client) {
        if (paramsFn) {
          client.query(sqlQuery, paramsFn(req), callback);
        } else {
          console.log(sqlQuery);
          client.query(sqlQuery, callback);
        };
      });
    }
  },
  simpleCommandResponder: function(sqlCommand, paramsFn, idFn) {
    return function(req, res) {
      var params = null;
      var callback = function(err, result) {
        if(err) {
          logger.error(err.name + ": " + err.message);
          res.writeHead(500, {'Content-Type': 'text/plain'});
          res.write(err.name + ": " + err.message);
          res.end();
        } else {
          res.writeHead(201, {'Content-Type': 'application/json'});
          if (idFn) {
            res.write(idFn(params));
          } else {
            res.write("{}");
          }
          res.end();
        }
      }

      conn.query(function(client) {
        logger.info("sqlCommand: " + sqlCommand);
        if (paramsFn) {
          params = paramsFn(req);
          logger.info("params: " + params);
          client.query(sqlCommand, params, callback);
        } else {
          client.query(sqlCommand, callback);
        };
      });
    }
  },
  newIdParamFn: function(params) {
    return function(req) {
      var ret = [uuidv4()];
      if (params) {
        for (var i = 0; i < params.length; i++) {
          ret.push(decodeURIComponent(req.params[params[i]]));
        }
      }
      logger.info(req.params);
      logger.info(ret);
      return ret;
    }
  },
  queryParamExtractor: function(params) {
    return function(req) {
      var ret = [];
      if (params) {
        for (var i = 0; i < params.length; i++) {
          ret.push(decodeURIComponent(req.query[params[i]]));
        }
      }
      return ret;
    }
  },
  pathParamExtractor: function(params) {
    return function(req) {
      var ret = [];
      if (params) {
        for (var i = 0; i < params.length; i++) {
          ret.push(decodeURIComponent(req.params[params[i]]));
        }
      }
      return ret;
    }
  },
  bodyParamExtractor: function(params) {
    return function(req) {
      var ret = [];
      if (params) {
        for (var i = 0; i < params.length; i++) {
          ret.push(req.body[params[i]]);
        }
      }
      return ret;
    }
  },
  compoundParamExtractor: function(paramFns) {
    return function(req) {
      var ret = [];
        for (var i = 0; i < paramFns.length; i++) {
          var params = paramFns[i](req);
          if (params) {
            for (var j = 0; j < params.length; j++) {
              ret.push(params[j]);
            }
          }
        }
      return ret;
    }
  },
  uuidGenerator: function() {
    return function (req) {
      return [uuidv4()];
    }
  }
}
<commit_msg>fun with arrow functions and map and reduce<commit_after>var conn = require('./conn.js')
var logger = (require('../logging/vip-winston')).Logger;
var uuidv4 = require('uuid/v4');
var resp = require('./response.js');

module.exports = {
  simpleQueryCallback: function(sqlQuery, params, callback) {
    conn.query(function(client) {
      client.query(sqlQuery, params, callback);
    });
  },
  simpleQueryResponder: function(sqlQuery, paramsFn) {
    return function(req, res) {

      var callback = function(err, result) {
        if(err) {
          logger.error(err.name + ": " + err.message);
          res.writeHead(500, {'Content-Type': 'text/plain'});
          res.write(err.name + ": " + err.message);
          res.end();
        } else {
          resp.writeResponse(result.rows, res);
        }
      }

      conn.query(function(client) {
        if (paramsFn) {
          client.query(sqlQuery, paramsFn(req), callback);
        } else {
          console.log(sqlQuery);
          client.query(sqlQuery, callback);
        };
      });
    }
  },
  simpleCommandResponder: function(sqlCommand, paramsFn, idFn) {
    return function(req, res) {
      var params = null;
      var callback = function(err, result) {
        if(err) {
          logger.error(err.name + ": " + err.message);
          res.writeHead(500, {'Content-Type': 'text/plain'});
          res.write(err.name + ": " + err.message);
          res.end();
        } else {
          res.writeHead(201, {'Content-Type': 'application/json'});
          if (idFn) {
            res.write(idFn(params));
          } else {
            res.write("{}");
          }
          res.end();
        }
      }

      conn.query(function(client) {
        logger.info("sqlCommand: " + sqlCommand);
        if (paramsFn) {
          params = paramsFn(req);
          logger.info("params: " + params);
          client.query(sqlCommand, params, callback);
        } else {
          client.query(sqlCommand, callback);
        };
      });
    }
  },
  queryParamExtractor: params => req => params.map(param => decodeURIComponent(req.query[param])),
  pathParamExtractor: params => req => params.map(param => decodeURIComponent(req.params[param])),
  bodyParamExtractor: params => req => params.map(param => req.body[param]),
  compoundParamExtractor: paramFns => req => paramFns.reduce((allParams, paramFn) => allParams.concat(paramFn(req)), []),
  uuidGenerator: () => req => ([uuidv4()])
}
<|endoftext|>


<commit_before>var utils  = require('../utils');

/**
 * session
 *
 * Takes a list of files and creates a set of file names that occur in subject
 * directories. Then generates a warning if a given subject is missing any
 * files from the set.
 */
var session = function missingSessionFiles(fileList) {
    var subjects = [];
    var issues = [];
    for (var key in fileList) {
        var file = fileList[key];
        var filename;

        if (!file || (typeof window != 'undefined' && !file.webkitRelativePath)) {
            continue;
        }

        var path = utils.files.relativePath(file);
        if (!utils.type.isBIDS(path)) {
            continue;
        }
        var subject;
        //match the subject identifier up to the '/' in the full path to a file.
        var match = path.match(/sub-(.*?)(?=\/)/);
        if (match === null) {
            continue;
        } else {
            subject = match[0];
        }
        // initialize an empty array if we haven't seen this subject before
        if (typeof(subjects[subject]) === 'undefined') {
            subjects[subject] = [];
        }
        // files are prepended with subject name, the following two commands
        // remove the subject from the file name to allow filenames to be more
        // easily compared
        filename = path.substring(path.match(subject).index + subject.length);
        filename = filename.replace(subject, '<sub>');
        subjects[subject].push(filename);
    }

    var subject_files = [];
    for (var key in subjects) {
        var subject = subjects[key];
        for (var file of subject) {
            if (subject_files.indexOf(file) < 0) {
                subject_files.push(file);
            }
        }
    }

    for (var subject in subjects) {
        for (var set_file in subject_files) {
            if (subjects[subject].indexOf(subject_files[set_file]) === -1) {
                filename = subject_files[set_file].replace('<sub>', subject);
                file.relativePath = '/' + subject + filename;
                issues.push(new utils.Issue({
                    file: file,
                    evidence: "Subject: " + subject + "; Missing file: " + filename,
                    code: 38
                }));
            }
        }
    }
    return issues;
};

module.exports = session;
<commit_msg>Converted 'for of' loop to a traditional loop to avoid minification errors during gulp build in web version<commit_after>var utils  = require('../utils');

/**
 * session
 *
 * Takes a list of files and creates a set of file names that occur in subject
 * directories. Then generates a warning if a given subject is missing any
 * files from the set.
 */
var session = function missingSessionFiles(fileList) {
    var subjects = [];
    var issues = [];
    for (var key in fileList) {
        var file = fileList[key];
        var filename;

        if (!file || (typeof window != 'undefined' && !file.webkitRelativePath)) {
            continue;
        }

        var path = utils.files.relativePath(file);
        if (!utils.type.isBIDS(path)) {
            continue;
        }
        var subject;
        //match the subject identifier up to the '/' in the full path to a file.
        var match = path.match(/sub-(.*?)(?=\/)/);
        if (match === null) {
            continue;
        } else {
            subject = match[0];
        }
        // initialize an empty array if we haven't seen this subject before
        if (typeof(subjects[subject]) === 'undefined') {
            subjects[subject] = [];
        }
        // files are prepended with subject name, the following two commands
        // remove the subject from the file name to allow filenames to be more
        // easily compared
        filename = path.substring(path.match(subject).index + subject.length);
        filename = filename.replace(subject, '<sub>');
        subjects[subject].push(filename);
    }

    var subject_files = [];
    for (var key in subjects) {
        var subject = subjects[key];
        for (var i = 0; i < subject.length; i++) {
            var file = subject[i];
            if (subject_files.indexOf(file) < 0) {
                subject_files.push(file);
            }
        }
    }

    for (var subject in subjects) {
        for (var set_file in subject_files) {
            if (subjects[subject].indexOf(subject_files[set_file]) === -1) {
                filename = subject_files[set_file].replace('<sub>', subject);
                file.relativePath = '/' + subject + filename;
                issues.push(new utils.Issue({
                    file: file,
                    evidence: "Subject: " + subject + "; Missing file: " + filename,
                    code: 38
                }));
            }
        }
    }
    return issues;
};

module.exports = session;
<|endoftext|>


<commit_before>(function (angular) {

  angular.module('angular-keenio.directives')

    .directive('tbkKeenMetric', ['tbkKeenClient', function (tbkKeenClient) {
      var prepareClasses = function (scope) {
        var containerClass = scope.containerClass || 'tbk-keen-metric';
        return {
          container: containerClass,
          loading: scope.loadingClass || containerClass + '-loading',
          error: scope.errorClass || containerClass + '-error',
          success: scope.successClass || containerClass + '-success'
        };
      };
      var prepareTexts = function (scope) {
        return {
          prefix: scope.prefix || '',
          postfix: scope.postfix || '',
          loading: scope.loadingText || 'Loading...',
          error: scope.errorText || 'An error occured!'
        };
      };
      var prepareOptions = function (scope) {
        return {
          scale: parseInt(scope.scale, 10) || 0,
          factor: parseInt(scope.factor, 10) || 1
        };
      };

      var d = {
        scope: {
          query: '=',
          prefix: '@',
          postfix: '@',
          scale: '@',
          factor: '@',
          loadingText: '@',
          errorText: '@',
          containerClass: '@',
          loadingClass: '@',
          successClass: '@',
          errorClass: '@'
        },
        controller: ['$scope', function ($scope) {
          $scope.texts = prepareTexts($scope);
          $scope.classes = prepareClasses($scope);
          $scope.options = prepareOptions($scope);

          $scope.flags = {
            loading: false,
            error: false
          };

          $scope.response = null;
        }],
        link: function ($scope, $element) {
          $element.addClass($scope.classes.container);

          var resetState = function () {
            $scope.flags.loading = true;
            $scope.flags.error = false;

            $element.addClass($scope.classes.loading);
            $element.removeClass($scope.classes.success);
            $element.removeClass($scope.classes.error);
          };

          (function fetchMetric() {
            resetState();

            tbkKeenClient.run($scope.query, function (error, response) {
              $scope.response = response;
              $scope.error = error;
              $scope.flags.error = !!error;
              $scope.flags.loading = false;
              $scope.result = error ? null : response.result * $scope.options.factor;

              $element.removeClass($scope.classes.loading);
              $element.addClass(error ? $scope.classes.error : $scope.classes.success);

              $scope.$digest();
            });
          })();
        },
        template: '' +
        '' +
        '{{ texts.prefix }}' +
        '{{ result | number:options.scale }}' +
        '{{ texts.postfix }}' +
        '' +
        '' +
        '{{ texts.loading }}' +
        '' +
        '' +
        '{{ texts.error }}' +
        '' +
        ''
      };

      return d;
    }])

    .directive('tbkKeenCountUniqueMetric', [function () {
      var d = {
        scope: {
          eventCollection: '@',
          targetProperty: '@',
          queryConfig: '=?'
        },
        controller: ['$scope', 'tbkKeen', function ($scope, tbkKeen) {
          var config = $scope.queryConfig || {};

          config.eventCollection = config.eventCollection || $scope.eventCollection;
          config.targetProperty = config.targetProperty || $scope.targetProperty;

          $scope.query = new tbkKeen.Query('count_unique', config);
        }],
        template: ''
      };

      return d;
    }])
  ;

})(angular);
<commit_msg>parse factor as float in tbkKeenMetric<commit_after>(function (angular) {

  angular.module('angular-keenio.directives')

    .directive('tbkKeenMetric', ['tbkKeenClient', function (tbkKeenClient) {
      var prepareClasses = function (scope) {
        var containerClass = scope.containerClass || 'tbk-keen-metric';
        return {
          container: containerClass,
          loading: scope.loadingClass || containerClass + '-loading',
          error: scope.errorClass || containerClass + '-error',
          success: scope.successClass || containerClass + '-success'
        };
      };
      var prepareTexts = function (scope) {
        return {
          prefix: scope.prefix || '',
          postfix: scope.postfix || '',
          loading: scope.loadingText || 'Loading...',
          error: scope.errorText || 'An error occured!'
        };
      };
      var prepareOptions = function (scope) {
        return {
          scale: parseInt(scope.scale, 10) || 0,
          factor: parseFloat(scope.factor) || 1
        };
      };

      var d = {
        scope: {
          query: '=',
          prefix: '@',
          postfix: '@',
          scale: '@',
          factor: '@',
          loadingText: '@',
          errorText: '@',
          containerClass: '@',
          loadingClass: '@',
          successClass: '@',
          errorClass: '@'
        },
        controller: ['$scope', function ($scope) {
          $scope.texts = prepareTexts($scope);
          $scope.classes = prepareClasses($scope);
          $scope.options = prepareOptions($scope);

          $scope.flags = {
            loading: false,
            error: false
          };

          $scope.response = null;
        }],
        link: function ($scope, $element) {
          $element.addClass($scope.classes.container);

          var resetState = function () {
            $scope.flags.loading = true;
            $scope.flags.error = false;

            $element.addClass($scope.classes.loading);
            $element.removeClass($scope.classes.success);
            $element.removeClass($scope.classes.error);
          };

          (function fetchMetric() {
            resetState();

            tbkKeenClient.run($scope.query, function (error, response) {
              $scope.response = response;
              $scope.error = error;
              $scope.flags.error = !!error;
              $scope.flags.loading = false;
              $scope.result = error ? null : response.result * $scope.options.factor;

              $element.removeClass($scope.classes.loading);
              $element.addClass(error ? $scope.classes.error : $scope.classes.success);

              $scope.$digest();
            });
          })();
        },
        template: '' +
        '' +
        '{{ texts.prefix }}' +
        '{{ result | number:options.scale }}' +
        '{{ texts.postfix }}' +
        '' +
        '' +
        '{{ texts.loading }}' +
        '' +
        '' +
        '{{ texts.error }}' +
        '' +
        ''
      };

      return d;
    }])

    .directive('tbkKeenCountUniqueMetric', [function () {
      var d = {
        scope: {
          eventCollection: '@',
          targetProperty: '@',
          queryConfig: '=?'
        },
        controller: ['$scope', 'tbkKeen', function ($scope, tbkKeen) {
          var config = $scope.queryConfig || {};

          config.eventCollection = config.eventCollection || $scope.eventCollection;
          config.targetProperty = config.targetProperty || $scope.targetProperty;

          $scope.query = new tbkKeen.Query('count_unique', config);
        }],
        template: ''
      };

      return d;
    }])
  ;

})(angular);
<|endoftext|>