<commit_before>// Karma configuration
// Generated on Sun Apr 10 2016 12:06:14 GMT+0200 (Central European Daylight Time)

module.exports = function (config) {
    if (process.env.TRAVIS && (!process.env.SAUCE_USERNAME || !process.env.SAUCE_ACCESS_KEY)) {
        console.log('Make sure the SAUCE_USERNAME and SAUCE_ACCESS_KEY environment variables are set.');
        process.exit(1);
    }

    var customLaunchers = new CustomLaunchers();

    customLaunchers
        //.addChrome('36', '42', '43', '44', '45')('Windows 8')
        //.addEdge('13.10586')('Windows 10')
        //.addIE('9.0', '10.0', '11.0')('Windows 7')
        //.addIE('10.0')('Windows 8')
        //.addIE('11.0')('Windows 8.1')
        //.addSafari('7.0')('OS X 10.9')
        //.addSafari('8.0')('OS X 10.10')
        //.addSafari('9.0')('OS X 10.11')
        //.addFirefox('6.0', '33', '34', '38', '39')('Windows 8')
        //.addFirefox('6.0', '33', '34', '38', '39')()
        //.addLatest('chrome', 'OS X 10.11')
        .addChrome('36', '45')('Windows 8')
        //.addLatest('chrome', 'Windows 8')
        //.addLatest('chrome', 'linux')
        //.addLatest('firefox', 'linux')
        //.addLatest('firefox', 'Windows 10')
        //.addLatest('firefox', 'OS X 10.11')
        .addLatest('MicrosoftEdge', 'Windows 10');

    config.set({

        // base path that will be used to resolve all patterns (eg. files, exclude)
        basePath: '',

        // frameworks to use
        // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
        frameworks: ['systemjs', 'jasmine'],

        // list of files / patterns to load in the browser
        files: [
            'tests/*-spec.ts',
            'tests/*-specs.ts'
        ],

        // list of files to exclude
        exclude: [],

        // preprocess matching files before serving them to the browser
        // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
        preprocessors: {},

        // test results reporter to use
        // possible values: 'dots', 'progress'
        // available reporters: https://npmjs.org/browse/keyword/karma-reporter
        reporters: process.env.TRAVIS ? ['dots', 'saucelabs'] : ['progress'],

        // web server port
        port: 9876,

        // enable / disable colors in the output (reporters and logs)
        colors: true,

        // level of logging
        // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
        logLevel: config.LOG_INFO,

        // enable / disable watching file and executing tests whenever any file changes
        autoWatch: true,

        // start these browsers
        // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
        browsers: process.env.TRAVIS
            ? Object.keys(customLaunchers).filter(function(key) { return !key.startsWith('add'); })
            :['Chrome'],

        // Continuous Integration mode
        // if true, Karma captures browsers, runs the tests and exits
        singleRun: process.env.TRAVIS ? true : false,

        // Concurrency level
        // how many browser should be started simultaneous
        concurrency: 4,

        systemjs: {
            configFile: 'config.js',
            serveFiles: [
                'src/**/*.ts',
                'tests/**/*.ts',
                'jspm_packages/**/*',
                'node_modules/**/*'
            ]
        },

        customLaunchers: JSON.parse(JSON.stringify(customLaunchers)),

        sauceLabs: {
            testName: 'Web App Unit Tests'
        }
    })
};

function CustomLaunchers() {
    var self = this;

    this.addChrome = addBrowser('chrome');
    this.addEdge = addBrowser('MicrosoftEdge');
    this.addOpera = addBrowser('opera');
    this.addSafari = addBrowser('safari');
    this.addFirefox = addBrowser('firefox');
    this.addIE = addBrowser('internet explorer');

    this.addLatest = function(browser, system) {
        self[browser + '_latest_' + system] = {
            base: 'SauceLabs',
            seleniumKey: browser,
            platform: system
        };

        return self;
    }

    function addBrowser(browser) {
        return function () {
            var versions = Array.from(arguments);
            return function (system) {

                versions.forEach(function (version) {
                    var seleniumKey = browser + '_' + version + '_' + system;

                    self[seleniumKey] = {
                        base: 'SauceLabs',
                        browserName: browser,
                        version: version
                    };

                    if (system) {
                        self[seleniumKey].platform = system;
                    }
                });

                return self;
            };
        };
    }
}
<commit_msg>chrome only<commit_after>// Karma configuration
// Generated on Sun Apr 10 2016 12:06:14 GMT+0200 (Central European Daylight Time)

module.exports = function (config) {
    if (process.env.TRAVIS && (!process.env.SAUCE_USERNAME || !process.env.SAUCE_ACCESS_KEY)) {
        console.log('Make sure the SAUCE_USERNAME and SAUCE_ACCESS_KEY environment variables are set.');
        process.exit(1);
    }

    var customLaunchers = new CustomLaunchers();

    customLaunchers
        .addChrome('36', '42', '43', '44', '45')('Windows 8')
        .addEdge('13.10586')('Windows 10')
        .addIE('9.0', '10.0', '11.0')('Windows 7')
        .addIE('10.0')('Windows 8')
        .addIE('11.0')('Windows 8.1')
        .addSafari('7.0')('OS X 10.9')
        .addSafari('8.0')('OS X 10.10')
        .addSafari('9.0')('OS X 10.11')
        .addFirefox('6.0', '33', '34', '38', '39')('Windows 8')
        .addFirefox('6.0', '33', '34', '38', '39')()
        .addLatest('chrome', 'OS X 10.11')
        .addLatest('chrome', 'Windows 8')
        .addLatest('chrome', 'linux')
        .addLatest('firefox', 'linux')
        .addLatest('firefox', 'Windows 10')
        .addLatest('firefox', 'OS X 10.11')
        .addLatest('MicrosoftEdge', 'Windows 10');

    config.set({

        // base path that will be used to resolve all patterns (eg. files, exclude)
        basePath: '',

        // frameworks to use
        // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
        frameworks: ['systemjs', 'jasmine'],

        // list of files / patterns to load in the browser
        files: [
            'tests/*-spec.ts',
            'tests/*-specs.ts'
        ],

        // list of files to exclude
        exclude: [],

        // preprocess matching files before serving them to the browser
        // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
        preprocessors: {},

        // test results reporter to use
        // possible values: 'dots', 'progress'
        // available reporters: https://npmjs.org/browse/keyword/karma-reporter
        reporters: process.env.TRAVIS ? ['dots', 'saucelabs'] : ['progress'],

        // web server port
        port: 9876,

        // enable / disable colors in the output (reporters and logs)
        colors: true,

        // level of logging
        // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
        logLevel: config.LOG_INFO,

        // enable / disable watching file and executing tests whenever any file changes
        autoWatch: true,

        // start these browsers
        // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
        browsers: //process.env.TRAVIS
            //? Object.keys(customLaunchers).filter(function(key) { return !key.startsWith('add'); })
            //:
            ['Chrome'],

        // Continuous Integration mode
        // if true, Karma captures browsers, runs the tests and exits
        singleRun: process.env.TRAVIS ? true : false,

        // Concurrency level
        // how many browser should be started simultaneous
        concurrency: 4,

        systemjs: {
            configFile: 'config.js',
            serveFiles: [
                'src/**/*.ts',
                'tests/**/*.ts',
                'jspm_packages/**/*',
                'node_modules/**/*'
            ]
        },

        customLaunchers: JSON.parse(JSON.stringify(customLaunchers)),

        sauceLabs: {
            testName: 'Web App Unit Tests'
        }
    })
};

function CustomLaunchers() {
    var self = this;

    this.addChrome = addBrowser('chrome');
    this.addEdge = addBrowser('MicrosoftEdge');
    this.addOpera = addBrowser('opera');
    this.addSafari = addBrowser('safari');
    this.addFirefox = addBrowser('firefox');
    this.addIE = addBrowser('internet explorer');

    this.addLatest = function(browser, system) {
        self[browser + '_latest_' + system] = {
            base: 'SauceLabs',
            seleniumKey: browser,
            platform: system
        };

        return self;
    }

    function addBrowser(browser) {
        return function () {
            var versions = Array.from(arguments);
            return function (system) {

                versions.forEach(function (version) {
                    var seleniumKey = browser + '_' + version + '_' + system;

                    self[seleniumKey] = {
                        base: 'SauceLabs',
                        browserName: browser,
                        version: version
                    };

                    if (system) {
                        self[seleniumKey].platform = system;
                    }
                });

                return self;
            };
        };
    }
}
<|endoftext|>


<commit_before>(function($){
    var Tree = {

        _init: function(){
            var self = this;
            this.element.addClass('marinemap-tree');
            this.defaults = {
                classname: '',
                id: '',
                context: false,
                select: false,
                doubleclick: false,
                collapsible: false,
                toggle: false,
                icon: false,
                data: {},
                children: false,
                extra: '',
                snippet: false,
                checked: false,
                open: false,
                description: false
            };

            this._template = tmpl([
                '<li class="',
                '<%= (context ? "context " : "") %>',
                '<%= (toggle ? "toggle " : "") %>',
                '<%= (select ? "select " : "unselectable ") %>',
                '<%= (doubleclick ? "doubleclick " : "") %>',
                '<%= (open ? "open " : "") %>',
                '<%= (toggle ? "toggle " : "") %>',
                '<%= (description ? "description " : "") %>',
                '<%= classname %> <%= id %> marinemap-tree-item',
                '">',
                    '<% if(collapsible) { %>',
                        '',
                    '<% } %>',
                    '<% if(toggle) { %>',
                        '<input type="checkbox" <% if(checked){ %>CHECKED<%}%>></input>',
                    '<% } %>',
                    '<% if(icon) { %>',
                        '<img class="icon" src="<%= icon %>" width="16" height="16" />',
                    '<% } %>',
                    '<%= name %>',
                    '<%= extra %>',
                    '<% if(snippet){ %>',
                        '
<%= snippet %>
',
                    '<% } %>',
                    '<% if(children) { %>',
                    '<% if(collapsible) { %>',
                    '
<%= children %>
',
                    '<% }else{ %>',
                    '
<%= children %>
',
                    '<% } %>',
                    '<% } else if(collapsible) { %>',
                        '

',
                    '<% } %>',
                '
'
            ].join(''))

            $(this).find('span.collapsible').live('click', function(event){
                event.preventDefault();
                // alert('collapsible click');
                var li = $(this).parent();
                var list = li.find('>ul');
                if(list.find('li').length == 0){
                    list.html('
No items.
');
                }else{
                    list.find('p.no-items').remove();
                }
                li.toggleClass('open');
                var img = $(this).find('img');
                if($(this).find('img[src*=/media/common/images/arrow-right.png]').length != 0){
                    img.attr('src', "/media/common/images/arrow-right.png");
                }else{
                    img.attr('src', "/media/common/images/arrow-right.png");
                }
                return false;
            });

            $(this).find('li.marinemap-tree-item a').live('dblclick', function(event){
                if($(event.target).parent().hasClass('doubleclick')){
                    $(self.element).trigger('itemDoubleClick', [$(event.target).parent(), event]);
                }
                event.preventDefault();
                return false;
            });

            $(this).find('li a').live('contextmenu', function(event){
                var item = $(event.target).parent();
                if(item.hasClass('context')){
                    self.element.trigger('itemContext', [event, item]);
                }
                event.preventDefault();
                return false;
            });

            $(this).find('li.marinemap-tree-item a').live('click', function(event){
                if(event.button == 2){

                }else{
                    var parent = $(event.target).parent();
                    self.element.trigger('itemClick', [parent, event]);
                    if(parent.hasClass('select')){
                        var e = jQuery.Event("itemSelect");
                        self.element.trigger(e, [parent]);
                        if(!e.isDefaultPrevented()){
                            self.selectItem(parent);
                        }
                    }else{
                        var e = jQuery.Event("itemSelect");
                        self.element.trigger(e, [null, parent]);
                        if(!e.isDefaultPrevented()){
                            self.clearSelection();
                        }
                    }
                    event.preventDefault();
                    return false;
                }
            });

            $(this).find('li span.collapsible, li span.collapsible a').live('contextmenu', function(event){
                event.preventDefault();
                return false;
            });
            // $(this).find('li').live('click', function(event){
            //     // var sorted = jQuery.makeArray($(event.target).find('>ul>li').sort(function(a, b){
            //     //     return $(a).data('data') != undefined && $(b).data('data') != undefined && $(a).data('data').date_modified > $(b).data('data').date_modified;
            //     // }));
            //     // var ul = $(event.target).find('>ul');
            //     // ul.empty('');
            //     // for(var i=0; i<sorted.length; i++){
            //     //     ul.append(sorted[i]);
            //     // }
            // });
            $(this).find('li.marinemap-tree-item input[type=checkbox]').live('click', function(e){
                var element = $(this);
                var checked = element.attr('checked');
                var parent = element.parent();
                if(parent.hasClass('selected')){
                    var e = jQuery.Event('itemSelect');
                    self.element.trigger(e, [null, null]);
                    if(!e.isDefaultPrevented()){
                        self.clearSelection();
                    }
                }
                var clickedData = [parent];
                var list = parent.find('>ul');
                if(list.length > 0){
                    var clickedData = self._toggleCheckboxes(list, checked, clickedData);
                }

                parent.parents('li.toggle').each(function(){
                    var el = $(this);
                    if(checked == true){
                        el.find(' > input[type=checkbox]').attr('checked', true);
                        clickedData.push(el);
                    }else{
                        // if you cant find any child elements turned on
                        if(el.find('> ul input[type=checkbox][checked=true]').length == 0){
                            el.find('> input[type=checkbox]').attr('checked', false);
                            clickedData.push(el);
                        }
                        if(el.hasClass('selected')){
                            self.clearSelection();
                            self.element.trigger('itemSelect', [null, null]);
                        }
                    }
                });
                self.element.trigger('itemToggle', [clickedData, checked]);
                if(checked == false){
                    if(parent.find('li.selected').length > 0){
                        parent.find('li.selected').removeClass('selected');
                        var e = jQuery.Event("itemSelect");
                        self.element.trigger(e, [null, null]);
                    }
                }
            });
        },

        selectItem: function(item, scrollTo){
            var wasHidden = false;
            if(typeof item == 'string'){
                item = this.element.find(item);
                wasHidden = this._expandAndToggleRecursive(item);
            }else{
                item = $(item);
            }
            var input = item.find('>input');
            var wasChecked = input.attr('checked');
            if(!wasChecked){
                input.click();
            }

            var list = item.find('>ul');
            var checked = []
            if(list.length > 0){
                this._toggleCheckboxes(list, true, checked);
            }
            if(!wasChecked || checked.length){
                this.element.trigger('itemToggle', [checked, true]);
            }

            var data = [];
            this.clearSelection();
            this._toggleCheckboxes(item, true, data);
            item.addClass('selected');

            if(scrollTo){
                var s = (this.options.scrollEl) ? $(this.options.scrollEl) : $(this.element).parent();
                var parent = s.parent();
                var ph = parent.height();
                var st = s.scrollTop();
                var visibleBounds = [st, st + ph - 20];
                var position = $(item).position().top + st;
                if(position > visibleBounds[0] && position < visibleBounds[1]){
                    // already visible
                }else{
                    s.scrollTop(position - (ph / 2) + 20);
                }
            }
        },

        _expandAndToggleRecursive: function(item, wasHidden){
            if(!(wasHidden === true || wasHidden === false)){
                wasHidden = false;
            }
            var parent = item.parent().parent();
            if(parent.hasClass('marinemap-tree-item')){
                if(parent.find('>ul:visible').length == 0){
                    wasHidden = true;
                    parent.find('>span.collapsible').click();
                }
                var input = parent.find('>input');
                if(input){
                    input.attr('checked', true);
                }
                return this._expandAndToggleRecursive(parent, wasHidden);
            }else{
                return wasHidden;
            }
        },

        clearSelection: function(){
            $(".marinemap-tree li.selected").removeClass('selected');
        },

        _toggleCheckboxes: function(el, state, data){
            var self = this;
            el.find('>li.toggle').each(function(){
                var input = $(this).find('>input');
                // this code might not work for deeply nested trees, needs
                // testing for use cases other than array->mpa
                if(input.attr('checked') != state){
                    input.attr('checked', state);
                    data.push($(this));
                }
                var ul = $(this).find('>ul');
                if(ul.length > 0){
                    data = self._toggleCheckboxes(ul, state, data);
                }
            });
            return data;
        },

        add: function(options){
            var element = $(this._rTemplate(options));
            // add metadata
            for(var k in options['data']){
                element.data(k, options['data'][k]);
            }
            var parent;
            if(typeof options['parent'] == 'string'){
                parent = this.element.find(options['parent']);
            }else if(typeof options['parent'] == 'undefined' || options['parent'] == null || options['parent'] == false){
                parent = this.element;
            }else{
                parent = options['parent'];
            }
            if(parent == this.element){
                var ul = parent;
            }else{
                var ul = parent.find('>ul');
                if(ul.size() == 0){
                    parent.append('

');
                    var ul = parent.find('>ul');
                }
            }
            if(ul.find('li').length == 0){
                ul.html('');
            }
            ul.append(element);
            // Here the parent needs to have something set on it
            // if(options.checked && options.parent){
            //     $(options.parent).find('> input[type="checkbox"]').attr('checked', true);
            // }
            // var element = ul.find('.'+options['id']);
            options = null;
            return element;
        },

        renderTemplate: function(options){
            if(jQuery.isArray(options)){
                var strings = [];
                for(var i=0;i<options.length;i++){
                    strings.push(this._rTemplate(options[i]));
                }
                return strings.join('');
            }else{
                var string = this._rTemplate(options);
                return string;
            }
        },

        _rTemplate: function(options){
            return this._template(
                jQuery.extend({}, this.defaults, options)
            );
        },

        nodeExists: function(selector){
            if(this.element.find(selector).length > 0){
                return true;
            }else{
                return false;
            }
        },

        destroy: function(){
            $(this).find('span.collapsible').die('click');
            $(this).find('li.marinemap-tree-item a').die('dblclick');
            $(this).find('li a').die('contextmenu');
            $(this).find('li.marinemap-tree-item input[type=checkbox]').die('click');
            $.widget.prototype.destroy.apply(this, arguments);
        }
    }

    $.widget('marinemap.tree', Tree);

    $.extend($.marinemap.tree, {
        getter: ['add', 'nodeExists', 'renderTemplate'],
        defaults: {
            // uses micro-templating.
            // See http://ejohn.org/blog/javascript-micro-templating/
            scrollEl: false,
            animate: true
        }
    });

    // var CustomTree = $.extend({}, $.marinemap.tree.prototype);

})(jQuery);<commit_msg>made some changes after cleaning up using jslint<commit_after>(function($){
    var Tree = {

        _init: function(){
            var self = this;
            this.element.addClass('marinemap-tree');
            this.defaults = {
                classname: '',
                id: '',
                context: false,
                select: false,
                doubleclick: false,
                collapsible: false,
                toggle: false,
                icon: false,
                data: {},
                children: false,
                extra: '',
                snippet: false,
                checked: false,
                open: false,
                description: false
            };

            this._template = tmpl([
                '<li class="',
                '<%= (context ? "context " : "") %>',
                '<%= (toggle ? "toggle " : "") %>',
                '<%= (select ? "select " : "unselectable ") %>',
                '<%= (doubleclick ? "doubleclick " : "") %>',
                '<%= (open ? "open " : "") %>',
                '<%= (toggle ? "toggle " : "") %>',
                '<%= (description ? "description " : "") %>',
                '<%= classname %> <%= id %> marinemap-tree-item',
                '">',
                    '<% if(collapsible) { %>',
                        '',
                    '<% } %>',
                    '<% if(toggle) { %>',
                        '<input type="checkbox" <% if(checked){ %>CHECKED<%}%>></input>',
                    '<% } %>',
                    '<% if(icon) { %>',
                        '<img class="icon" src="<%= icon %>" width="16" height="16" />',
                    '<% } %>',
                    '<%= name %>',
                    '<%= extra %>',
                    '<% if(snippet){ %>',
                        '
<%= snippet %>
',
                    '<% } %>',
                    '<% if(children) { %>',
                    '<% if(collapsible) { %>',
                    '
<%= children %>
',
                    '<% }else{ %>',
                    '
<%= children %>
',
                    '<% } %>',
                    '<% } else if(collapsible) { %>',
                        '

',
                    '<% } %>',
                '
'
            ].join(''));

            $(this).find('span.collapsible').live('click', function(event){
                event.preventDefault();
                // alert('collapsible click');
                var li = $(this).parent();
                var list = li.find('>ul');
                if(list.find('li').length == 0){
                    list.html('
No items.
');
                }else{
                    list.find('p.no-items').remove();
                }
                li.toggleClass('open');
                var img = $(this).find('img');
                if($(this).find('img[src*=/media/common/images/arrow-right.png]').length != 0){
                    img.attr('src', "/media/common/images/arrow-right.png");
                }else{
                    img.attr('src', "/media/common/images/arrow-right.png");
                }
                return false;
            });

            $(this).find('li.marinemap-tree-item a').live('dblclick', function(event){
                if($(event.target).parent().hasClass('doubleclick')){
                    $(self.element).trigger('itemDoubleClick', [$(event.target).parent(), event]);
                }
                event.preventDefault();
                return false;
            });

            $(this).find('li a').live('contextmenu', function(event){
                var item = $(event.target).parent();
                if(item.hasClass('context')){
                    self.element.trigger('itemContext', [event, item]);
                }
                event.preventDefault();
                return false;
            });

            $(this).find('li.marinemap-tree-item a').live('click', function(event){
                if(event.button == 2){

                }else{
                    var parent = $(event.target).parent();
                    self.element.trigger('itemClick', [parent, event]);
                    if(parent.hasClass('select')){
                        var e = jQuery.Event("itemSelect");
                        self.element.trigger(e, [parent]);
                        if(!e.isDefaultPrevented()){
                            self.selectItem(parent);
                        }
                    }else{
                        var e = jQuery.Event("itemSelect");
                        self.element.trigger(e, [null, parent]);
                        if(!e.isDefaultPrevented()){
                            self.clearSelection();
                        }
                    }
                    event.preventDefault();
                    return false;
                }
            });

            $(this).find('li span.collapsible, li span.collapsible a').live('contextmenu', function(event){
                event.preventDefault();
                return false;
            });
            // $(this).find('li').live('click', function(event){
            //     // var sorted = jQuery.makeArray($(event.target).find('>ul>li').sort(function(a, b){
            //     //     return $(a).data('data') != undefined && $(b).data('data') != undefined && $(a).data('data').date_modified > $(b).data('data').date_modified;
            //     // }));
            //     // var ul = $(event.target).find('>ul');
            //     // ul.empty('');
            //     // for(var i=0; i<sorted.length; i++){
            //     //     ul.append(sorted[i]);
            //     // }
            // });
            $(this).find('li.marinemap-tree-item input[type=checkbox]').live('click', function(e){
                var element = $(this);
                var checked = element.attr('checked');
                var parent = element.parent();
                if(parent.hasClass('selected')){
                    var e = jQuery.Event('itemSelect');
                    self.element.trigger(e, [null, null]);
                    if(!e.isDefaultPrevented()){
                        self.clearSelection();
                    }
                }
                var clickedData = [parent];
                var list = parent.find('>ul');
                if(list.length > 0){
                    var clickedData = self._toggleCheckboxes(list, checked, clickedData);
                }

                parent.parents('li.toggle').each(function(){
                    var el = $(this);
                    if(checked == true){
                        el.find(' > input[type=checkbox]').attr('checked', true);
                        clickedData.push(el);
                    }else{
                        // if you cant find any child elements turned on
                        if(el.find('> ul input[type=checkbox][checked=true]').length == 0){
                            el.find('> input[type=checkbox]').attr('checked', false);
                            clickedData.push(el);
                        }
                        if(el.hasClass('selected')){
                            self.clearSelection();
                            self.element.trigger('itemSelect', [null, null]);
                        }
                    }
                });
                self.element.trigger('itemToggle', [clickedData, checked]);
                if(checked == false){
                    if(parent.find('li.selected').length > 0){
                        parent.find('li.selected').removeClass('selected');
                        var e = jQuery.Event("itemSelect");
                        self.element.trigger(e, [null, null]);
                    }
                }
            });
        },

        selectItem: function(item, scrollTo){
            var wasHidden = false;
            if(typeof item == 'string'){
                item = this.element.find(item);
                wasHidden = this._expandAndToggleRecursive(item);
            }else{
                item = $(item);
            }
            var input = item.find('>input');
            var wasChecked = input.attr('checked');
            if(!wasChecked){
                input.click();
            }

            var list = item.find('>ul');
            var checked = [];
            if(list.length > 0){
                this._toggleCheckboxes(list, true, checked);
            }
            if(!wasChecked || checked.length){
                this.element.trigger('itemToggle', [checked, true]);
            }

            var data = [];
            this.clearSelection();
            this._toggleCheckboxes(item, true, data);
            item.addClass('selected');

            if(scrollTo){
                var s = (this.options.scrollEl) ? $(this.options.scrollEl) : $(this.element).parent();
                var parent = s.parent();
                var ph = parent.height();
                var st = s.scrollTop();
                var visibleBounds = [st, st + ph - 20];
                var position = $(item).position().top + st;
                if(position > visibleBounds[0] && position < visibleBounds[1]){
                    // already visible
                }else{
                    s.scrollTop(position - (ph / 2) + 20);
                }
            }
        },

        _expandAndToggleRecursive: function(item, wasHidden){
            if(!(wasHidden === true || wasHidden === false)){
                wasHidden = false;
            }
            var parent = item.parent().parent();
            if(parent.hasClass('marinemap-tree-item')){
                if(parent.find('>ul:visible').length == 0){
                    wasHidden = true;
                    parent.find('>span.collapsible').click();
                }
                var input = parent.find('>input');
                if(input){
                    input.attr('checked', true);
                }
                return this._expandAndToggleRecursive(parent, wasHidden);
            }else{
                return wasHidden;
            }
        },

        clearSelection: function(){
            $(".marinemap-tree li.selected").removeClass('selected');
        },

        _toggleCheckboxes: function(el, state, data){
            var self = this;
            el.find('>li.toggle').each(function(){
                var input = $(this).find('>input');
                // this code might not work for deeply nested trees, needs
                // testing for use cases other than array->mpa
                if(input.attr('checked') != state){
                    input.attr('checked', state);
                    data.push($(this));
                }
                var ul = $(this).find('>ul');
                if(ul.length > 0){
                    data = self._toggleCheckboxes(ul, state, data);
                }
            });
            return data;
        },

        add: function(options){
            var element = $(this._rTemplate(options));
            // add metadata
            for(var k in options.data){
                element.data(k, options.data[k]);
            }
            var parent;
            if(typeof options.parent == 'string'){
                parent = this.element.find(options.parent);
            }else if(typeof options.parent == 'undefined' || options.parent == null || options.parent == false){
                parent = this.element;
            }else{
                parent = options.parent;
            }
            if(parent == this.element){
                var ul = parent;
            }else{
                var ul = parent.find('>ul');
                if(ul.size() == 0){
                    parent.append('

');
                    var ul = parent.find('>ul');
                }
            }
            if(ul.find('li').length == 0){
                ul.html('');
            }
            ul.append(element);
            // Here the parent needs to have something set on it
            // if(options.checked && options.parent){
            //     $(options.parent).find('> input[type="checkbox"]').attr('checked', true);
            // }
            // var element = ul.find('.'+options['id']);
            options = null;
            return element;
        },

        renderTemplate: function(options){
            if(jQuery.isArray(options)){
                var strings = [];
                for(var i=0;i<options.length;i++){
                    strings.push(this._rTemplate(options[i]));
                }
                return strings.join('');
            }else{
                var string = this._rTemplate(options);
                return string;
            }
        },

        _rTemplate: function(options){
            return this._template(
                jQuery.extend({}, this.defaults, options)
            );
        },

        nodeExists: function(selector){
            if(this.element.find(selector).length > 0){
                return true;
            }else{
                return false;
            }
        },

        destroy: function(){
            $(this).find('span.collapsible').die('click');
            $(this).find('li.marinemap-tree-item a').die('dblclick');
            $(this).find('li a').die('contextmenu');
            $(this).find('li.marinemap-tree-item input[type=checkbox]').die('click');
            $.widget.prototype.destroy.apply(this, arguments);
        }
    };

    $.widget('marinemap.tree', Tree);

    $.extend($.marinemap.tree, {
        getter: ['add', 'nodeExists', 'renderTemplate'],
        defaults: {
            // uses micro-templating.
            // See http://ejohn.org/blog/javascript-micro-templating/
            scrollEl: false,
            animate: true
        }
    });

    // var CustomTree = $.extend({}, $.marinemap.tree.prototype);

})(jQuery);<|endoftext|>


<commit_before>/*
jspsych-consent

a jspsych plugin to create a consent page and check for response without requring an external html page

Ayse Zeynep Enkavi*/

//Look at text plugin for text and likert scale plugin for button

// parameters:
// consent_text
// checkbox_text
// button_text

(function($) {
  jsPsych['consent'] = (function(){

    var plugin = {};

    plugin.create = function(params){

      params = jsPsych.pluginAPI.enforceArray(params, ['consent_text', 'checkbox_text', 'button_text']);

      var trials = new Array(params.consent_text.length);

      for(var i = 0; i<trials.length; i++){
        trials[i] = {};
        trials[i].consent_text = params.consent_text[i];
        trials[i].checkbox_text = params.checkbox_text[i];
        trials[i].button_text = params.button_text[i];
        trials[i].container = params.container || -1
      }

      return trials;
    }

    plugin.trial = function(display_element, trial){

      trial = jsPsych.pluginAPI.evaluateFunctionParameters(trial);

      //display consent text, checkbox and button
      display_element.append($('
', {
					html: trial.consent_text + //consent_text - should specify a container
						"
<input type='checkbox' id = 'checkbox'>" + trial.checkbox_text + "
" +
						"<button type='button' id = 'start'>" + trial.button_text +"</button>",
					id: 'jspsych-consent-text'
				}));

      //specify what happens when start button is clicked
      $("#start").click(function() {

        // measure response time
        var endTime = (new Date()).getTime();
        var response_time = endTime - startTime;

        // check if consent given
        if ($('#checkbox').is(':checked')) {
          // save data
          jsPsych.data.write({
            "rt": response_time,
          });

          display_element.html('');

          // next trial
          jsPsych.finishTrial();

          //return true;
        }

        // if consent not given alert subject and don't start
        else {
          alert("If you wish to participate, you must check the box to agree to participate in this study.");
          return false;
        }

      });

   var startTime = (new Date()).getTime();
  };

    return plugin;

  })();
})(jQuery);
<commit_msg>Made jspsych-consent.js jspsych-5.0 compatible.<commit_after>/*
jspsych-consent

a jspsych plugin to create a consent page and check for response without requring an external html page

Ayse Zeynep Enkavi*/

jsPsych.plugins["consent"] = (function() {

  var plugin = {};

  plugin.trial = function(display_element, trial) {

    // set default values for parameters
    trial.consent_text = trial.consent_text;
    trial.checkbox_text = trial.checkbox_text;
    trial.button_text = trial.button_text;
    trial.container = trial.container || -1

    // allow variables as functions
    // this allows any trial variable to be specified as a function
    // that will be evaluated when the trial runs. this allows users
    // to dynamically adjust the contents of a trial as a result
    // of other trials, among other uses. you can leave this out,
    // but in general it should be included
    trial = jsPsych.pluginAPI.evaluateFunctionParameters(trial);

    //display consent text, checkbox and button
      display_element.append($('
', {
          html: trial.consent_text + //consent_text - should specify a container
            "
<input type='checkbox' id = 'checkbox'>" + trial.checkbox_text + "
" +
            "<button type='button' id = 'start'>" + trial.button_text +"</button>",
          id: 'jspsych-consent-text'
        }));

      //specify what happens when start button is clicked
      $("#start").click(function() {

        // measure response time
        var endTime = (new Date()).getTime();
        var response_time = endTime - startTime;

        // check if consent given
        if ($('#checkbox').is(':checked')) {
          // save data
          jsPsych.data.write({
            "rt": response_time,
          });

          display_element.html('');

          // next trial
          jsPsych.finishTrial();

          //return true;
        }

        // if consent not given alert subject and don't start
        else {
          alert("If you wish to participate, you must check the box to agree to participate in this study.");
          return false;
        }

      });

   var startTime = (new Date()).getTime();

  };

  return plugin;
})();
<|endoftext|>


<commit_before>/*************************************************
 * Copyright (c) 2015 Ansible, Inc.
 *
 * All Rights Reserved
 *************************************************/

/**
 * @ngdoc function
 * @name controllers.function:Authentication
 * @description
 * Controller for handling /#/login and /#/logout routes.
 *
 * Tower (app.js) verifies the user is authenticated and that the user session is not expired. If either condition is not true,
 * the user is redirected to /#/login and the Authentication controller.
 *
 * Methods for checking the session state are found in [js/shared/AuthService.js](/static/docs/api/shared.function:AuthService), which is referenced here as Authorization.
 *
 * #Login Modal Dialog
 *
 * The modal dialog prompting for username and password is found in templates/ui/index.html.
 *```
 *     <!-- login modal -->
 *     <div id="login-modal" class="modal fade">
 *         <div class="modal-dialog">
 *             <div class="modal-content" id="login-modal-content">
 *             </div><!-- modal-content -->
 *         </div><!-- modal-dialog -->
 *     </div><!-- modal -->
 *```
 * HTML for the login form is generated, compiled and injected into

 by the controller. This is done to associate the form with the controller's scope. Because
 *

 is outside of the ng-view container, it gets associated with $rootScope by default. In the controller we create a new scope using $rootScope.$new() and associate
 * that with the login form. Doing this each time the controller is instantiated insures the form is clean and not pre-populated with a prior user's username and password.
 *
 * Just before the release of 2.0 a bug was discovered where clicking logout and then immediately clicking login without providing a username and password would successfully log
 * the user back into Tower. Implementing the above approach fixed this, forcing a new username/password to be entered each time the login dialog appears.
 *
 * #Login Workflow
 *
 * When the the login button is clicked, the following occurs:
 *
 * - Call Authorization.retrieveToken(username, password) - sends a POST request to /api/v1/authtoken to get a new token value.
 * - Call Authorization.setToken(token, expires) to store the token and exipration time in a session cookie.
 * - Start the expiration timer by calling the init() method of [js/shared/Timer.js](/static/docs/api/shared.function:Timer)
 * - Get user informaton by calling Authorization.getUser() - sends a GET request to /api/v1/me
 * - Store user information in the session cookie by calling Authorization.setUser().
 * - Get the Tower license by calling Authorization.getLicense() - sends a GET request to /api/vi/config
 * - Stores the license object in local storage by calling Authorization.setLicense(). This adds the Tower version and a tested flag to the license object. The tested flag is initially set to false.
 *
 * Note that there is a session timer kept on the server side as well as the client side. Each time an API request is made, Tower (in app.js) calls
 * Timer.isExpired(). This verifies the UI does not think the session is expired, and if not, moves the expiration time into the future. The number of
 * seconds between API calls before a session is considered expired is set in config.js as session_timeout.
 *
 * @Usage
 * This is usage information.
 */

export default ['$log', '$cookieStore', '$compile', '$window', '$rootScope',
    '$location', 'Authorization', 'ToggleClass', 'Alert', 'Wait', 'Timer',
    'Empty', 'ClearScope', '$scope', 'pendoService', 'ConfigService',
    'CheckLicense', 'FeaturesService',
    function ($log, $cookieStore, $compile, $window, $rootScope, $location,
        Authorization, ToggleClass, Alert, Wait, Timer, Empty, ClearScope,
        scope, pendoService, ConfigService, CheckLicense, FeaturesService) {

    var lastPath, lastUser, sessionExpired, loginAgain;

    loginAgain = function() {
        setTimeout(function() {
            $location.path('/logout');
        }, 1000);
    };

    scope.sessionExpired = (Empty($rootScope.sessionExpired)) ? $cookieStore.get('sessionExpired') : $rootScope.sessionExpired;
    scope.login_username = '';
    scope.login_password = '';

    lastPath = function () {
        return (Empty($rootScope.lastPath)) ? $cookieStore.get('lastPath') : $rootScope.lastPath;
    };

    lastUser = function(){
        if(!Empty($rootScope.lastUser) && $rootScope.lastUser === $rootScope.current_user.id){
            return true;
        }
        else {
            return false;
        }
    };

    $log.debug('User session expired: ' + sessionExpired);
    $log.debug('Last URL: ' + lastPath());

    $rootScope.loginConfig.promise.then(function () {
        if ($AnsibleConfig.custom_logo) {
            scope.customLogo = "custom_console_logo.png";
            scope.customLogoPresent = true;
        } else {
            scope.customLogo = "tower-logo-login.svg";
            scope.customLogoPresent = false;
        }

        scope.customLoginInfo = $AnsibleConfig.custom_login_info;
        scope.customLoginInfoPresent = (scope.customLoginInfo) ? true : false;
    });

    // Reset the login form
    //scope.loginForm.login_username.$setPristine();
    //scope.loginForm.login_password.$setPristine();
    //$rootScope.userLoggedIn = false; //hide the logout link. if you got here, you're logged out.
    //$cookieStore.put('userLoggedIn', false); //gets set back to true by Authorization.setToken().

    if (scope.removeAuthorizationGetLicense) {
        scope.removeAuthorizationGetLicense();
    }
    scope.removeAuthorizationGetLicense = scope.$on('AuthorizationGetLicense', function() {
        ConfigService.getConfig().then(function(){
                CheckLicense.test();
                pendoService.issuePendoIdentity();
                FeaturesService.get();
                Wait("stop");
                if (lastPath() && lastUser()) {
                    // Go back to most recent navigation path
                    $location.path(lastPath());
                } else {
                    $location.url('/home');
                }
            })
            .catch(function () {
                Wait('stop');
                Alert('Error', 'Failed to access license information. GET returned status: ' + status, 'alert-danger', loginAgain);
            });
    });

    if (scope.removeAuthorizationGetUser) {
        scope.removeAuthorizationGetUser();
    }
    scope.removeAuthorizationGetUser = scope.$on('AuthorizationGetUser', function() {
        // Get all the profile/access info regarding the logged in user
        Authorization.getUser()
            .success(function (data) {
                Authorization.setUserInfo(data);
                Timer.init().then(function(timer){
                    $rootScope.sessionTimer = timer;
                    $rootScope.$emit('OpenSocket');
                    $rootScope.user_is_superuser = data.results[0].is_superuser;
                    scope.$emit('AuthorizationGetLicense');
                });
            })
            .error(function (data, status) {
                Authorization.logout();
                Wait('stop');
                Alert('Error', 'Failed to access user information. GET returned status: ' + status, 'alert-danger', loginAgain);
            });
    });

    // Call the API to get an auth token
    scope.systemLogin = function (username, password) {
        $('.api-error').empty();
        if (Empty(username) || Empty(password)) {
            scope.reset();
            scope.attemptFailed = true;
            $('#login-username').focus();
        } else {
            Wait('start');
            Authorization.retrieveToken(username, password)
                .then(function (data) {
                    $('#login-modal').modal('hide');
                    Authorization.setToken(data.data.token, data.data.expires);
                    scope.$emit('AuthorizationGetUser');
                },
                function (data) {
                    var key;
                    Wait('stop');
                    if (data && data.data && data.data.non_field_errors && data.data.non_field_errors.length === 0) {
                        // show field specific errors returned by the API
                        for (key in data.data) {
                            scope[key + 'Error'] = data.data[key][0];
                        }
                    } else {
                        scope.reset();
                        scope.attemptFailed = true;
                        $('#login-username').focus();
                    }
                });
        }
    };
}];
<commit_msg>Updating documentation on login process for new config workflow<commit_after>/*************************************************
 * Copyright (c) 2015 Ansible, Inc.
 *
 * All Rights Reserved
 *************************************************/

/**
 * @ngdoc function
 * @name controllers.function:Authentication
 * @description
 * Controller for handling /#/login and /#/logout routes.
 *
 * Tower (app.js) verifies the user is authenticated and that the user session is not expired. If either condition is not true,
 * the user is redirected to /#/login and the Authentication controller.
 *
 * Methods for checking the session state are found in [js/shared/AuthService.js](/static/docs/api/shared.function:AuthService), which is referenced here as Authorization.
 *
 * #Login Modal Dialog
 *
 * The modal dialog prompting for username and password is found in templates/ui/index.html.
 *```
 *     <!-- login modal -->
 *     <div id="login-modal" class="modal fade">
 *         <div class="modal-dialog">
 *             <div class="modal-content" id="login-modal-content">
 *             </div><!-- modal-content -->
 *         </div><!-- modal-dialog -->
 *     </div><!-- modal -->
 *```
 * HTML for the login form is generated, compiled and injected into

 by the controller. This is done to associate the form with the controller's scope. Because
 *

 is outside of the ng-view container, it gets associated with $rootScope by default. In the controller we create a new scope using $rootScope.$new() and associate
 * that with the login form. Doing this each time the controller is instantiated insures the form is clean and not pre-populated with a prior user's username and password.
 *
 * Just before the release of 2.0 a bug was discovered where clicking logout and then immediately clicking login without providing a username and password would successfully log
 * the user back into Tower. Implementing the above approach fixed this, forcing a new username/password to be entered each time the login dialog appears.
 *
 * #Login Workflow
 *
 * When the the login button is clicked, the following occurs:
 *
 * - Call Authorization.retrieveToken(username, password) - sends a POST request to /api/v1/authtoken to get a new token value.
 * - Call Authorization.setToken(token, expires) to store the token and exipration time in a session cookie.
 * - Start the expiration timer by calling the init() method of [js/shared/Timer.js](/static/docs/api/shared.function:Timer)
 * - Get user informaton by calling Authorization.getUser() - sends a GET request to /api/v1/me
 * - Store user information in the session cookie by calling Authorization.setUser().
 * - Get the Tower license by calling ConfigService.getConfig() - sends a GET request to /api/vi/config
 * - Stores the license object in memory by calling CheckLicense.test(). This adds the Tower version and a tested flag to the license object. The tested flag is initially set to false. Additionally, the pendoService and FeaturesService are called to initiate the other startup services of Tower
 *
 * Note that there is a session timer kept on the server side as well as the client side. Each time an API request is made, Tower (in app.js) calls
 * Timer.isExpired(). This verifies the UI does not think the session is expired, and if not, moves the expiration time into the future. The number of
 * seconds between API calls before a session is considered expired is set in config.js as session_timeout.
 *
 * @Usage
 * This is usage information.
 */

export default ['$log', '$cookieStore', '$compile', '$window', '$rootScope',
    '$location', 'Authorization', 'ToggleClass', 'Alert', 'Wait', 'Timer',
    'Empty', 'ClearScope', '$scope', 'pendoService', 'ConfigService',
    'CheckLicense', 'FeaturesService',
    function ($log, $cookieStore, $compile, $window, $rootScope, $location,
        Authorization, ToggleClass, Alert, Wait, Timer, Empty, ClearScope,
        scope, pendoService, ConfigService, CheckLicense, FeaturesService) {

    var lastPath, lastUser, sessionExpired, loginAgain;

    loginAgain = function() {
        setTimeout(function() {
            $location.path('/logout');
        }, 1000);
    };

    scope.sessionExpired = (Empty($rootScope.sessionExpired)) ? $cookieStore.get('sessionExpired') : $rootScope.sessionExpired;
    scope.login_username = '';
    scope.login_password = '';

    lastPath = function () {
        return (Empty($rootScope.lastPath)) ? $cookieStore.get('lastPath') : $rootScope.lastPath;
    };

    lastUser = function(){
        if(!Empty($rootScope.lastUser) && $rootScope.lastUser === $rootScope.current_user.id){
            return true;
        }
        else {
            return false;
        }
    };

    $log.debug('User session expired: ' + sessionExpired);
    $log.debug('Last URL: ' + lastPath());

    $rootScope.loginConfig.promise.then(function () {
        if ($AnsibleConfig.custom_logo) {
            scope.customLogo = "custom_console_logo.png";
            scope.customLogoPresent = true;
        } else {
            scope.customLogo = "tower-logo-login.svg";
            scope.customLogoPresent = false;
        }

        scope.customLoginInfo = $AnsibleConfig.custom_login_info;
        scope.customLoginInfoPresent = (scope.customLoginInfo) ? true : false;
    });

    // Reset the login form
    //scope.loginForm.login_username.$setPristine();
    //scope.loginForm.login_password.$setPristine();
    //$rootScope.userLoggedIn = false; //hide the logout link. if you got here, you're logged out.
    //$cookieStore.put('userLoggedIn', false); //gets set back to true by Authorization.setToken().

    if (scope.removeAuthorizationGetLicense) {
        scope.removeAuthorizationGetLicense();
    }
    scope.removeAuthorizationGetLicense = scope.$on('AuthorizationGetLicense', function() {
        ConfigService.getConfig().then(function(){
                CheckLicense.test();
                pendoService.issuePendoIdentity();
                FeaturesService.get();
                Wait("stop");
                if (lastPath() && lastUser()) {
                    // Go back to most recent navigation path
                    $location.path(lastPath());
                } else {
                    $location.url('/home');
                }
            })
            .catch(function () {
                Wait('stop');
                Alert('Error', 'Failed to access license information. GET returned status: ' + status, 'alert-danger', loginAgain);
            });
    });

    if (scope.removeAuthorizationGetUser) {
        scope.removeAuthorizationGetUser();
    }
    scope.removeAuthorizationGetUser = scope.$on('AuthorizationGetUser', function() {
        // Get all the profile/access info regarding the logged in user
        Authorization.getUser()
            .success(function (data) {
                Authorization.setUserInfo(data);
                Timer.init().then(function(timer){
                    $rootScope.sessionTimer = timer;
                    $rootScope.$emit('OpenSocket');
                    $rootScope.user_is_superuser = data.results[0].is_superuser;
                    scope.$emit('AuthorizationGetLicense');
                });
            })
            .error(function (data, status) {
                Authorization.logout();
                Wait('stop');
                Alert('Error', 'Failed to access user information. GET returned status: ' + status, 'alert-danger', loginAgain);
            });
    });

    // Call the API to get an auth token
    scope.systemLogin = function (username, password) {
        $('.api-error').empty();
        if (Empty(username) || Empty(password)) {
            scope.reset();
            scope.attemptFailed = true;
            $('#login-username').focus();
        } else {
            Wait('start');
            Authorization.retrieveToken(username, password)
                .then(function (data) {
                    $('#login-modal').modal('hide');
                    Authorization.setToken(data.data.token, data.data.expires);
                    scope.$emit('AuthorizationGetUser');
                },
                function (data) {
                    var key;
                    Wait('stop');
                    if (data && data.data && data.data.non_field_errors && data.data.non_field_errors.length === 0) {
                        // show field specific errors returned by the API
                        for (key in data.data) {
                            scope[key + 'Error'] = data.data[key][0];
                        }
                    } else {
                        scope.reset();
                        scope.attemptFailed = true;
                        $('#login-username').focus();
                    }
                });
        }
    };
}];
<|endoftext|>


<commit_before>/**
 * Copyright 2017-present, Callstack.
 * All rights reserved.
 *
 * @flow
 */

const utils = require('loader-utils');
const size = require('image-size');
const path = require('path');
const dedent = require('dedent');
const hasha = require('hasha');
const escapeStringRegexp = require('escape-string-regexp');
const AssetResolver = require('../resolvers/AssetResolver');

type Config = {
  platform: string,
  bundle?: boolean,
  root: string,
  outputPath?: string | ((path: string) => string),
  publicPath?: string | ((path: string) => string),
};

module.exports = async function assetLoader() {
  this.cacheable();

  const callback = this.async();

  const query = utils.getOptions(this) || {};
  const config: Config = Object.assign(
    {},
    { platform: 'ios', root: process.cwd() },
    query
  );

  const pathSepPattern = new RegExp(`\\${path.sep}`, 'g');
  const filepath = this.resourcePath;
  const dirname = path.dirname(filepath);
  const url = path.relative(config.root, dirname);
  const type = path.extname(filepath).replace(/^\./, '');
  const assets = path.join('assets', config.bundle ? '' : config.platform);
  const suffix = `(@\\d+(\\.\\d+)?x)?(\\.(${config.platform}|native))?\\.${type}$`;
  const filename = path.basename(filepath).replace(new RegExp(suffix), '');
  const longname = `${`${url.replace(pathSepPattern, '_')}_${filename}`
    .toLowerCase()
    .replace(/[^a-z0-9_]/g, '')}.${type}`;

  const result = await new Promise((resolve, reject) =>
    this.fs.readdir(dirname, (err, res) => {
      if (err) {
        reject(err);
      } else {
        resolve(res);
      }
    })
  );

  const map = AssetResolver.collect(result, {
    name: filename,
    type,
    platform: config.platform,
  });

  const scales = Object.keys(map)
    .map(s => Number(s.replace(/[^\d.]/g, '')))
    .sort();

  const pairs = await Promise.all(
    Object.keys(map).map(scale => {
      this.addDependency(path.join(dirname, map[scale].name));

      return new Promise((resolve, reject) =>
        this.fs.readFile(path.join(dirname, map[scale].name), (err, res) => {
          if (err) {
            reject(err);
          } else {
            let dest;

            if (config.bundle && config.platform === 'android') {
              switch (scale) {
                case '@0.75x':
                  dest = 'drawable-ldpi';
                  break;
                case '@1x':
                  dest = 'drawable-mdpi';
                  break;
                case '@1.5x':
                  dest = 'drawable-hdpi';
                  break;
                case '@2x':
                  dest = 'drawable-xhdpi';
                  break;
                case '@3x':
                  dest = 'drawable-xxhdpi';
                  break;
                case '@4x':
                  dest = 'drawable-xxxhdpi';
                  break;
                default:
                  throw new Error(`Unknown scale ${scale} for ${filepath}`);
              }

              dest = path.join(dest, longname);
            } else {
              const name = `${filename}${scale === '@1x' ? '' : scale}.${type}`;
              dest = path.join(assets, url, name);
            }

            resolve({
              destination: dest,
              content: res,
            });
          }
        })
      );
    })
  );

  pairs.forEach(item => {
    let dest = item.destination;

    if (config.outputPath) {
      // support functions as outputPath to generate them dynamically
      dest =
        typeof config.outputPath === 'function'
          ? config.outputPath(dest)
          : path.join(config.outputPath, dest);
    }

    this.emitFile(dest, item.content);
  });

  let publicPath = JSON.stringify(
    path.join(assets, url).replace(pathSepPattern, '/')
  );

  if (config.publicPath) {
    // support functions as publicPath to generate them dynamically
    publicPath = JSON.stringify(
      typeof config.publicPath === 'function'
        ? config.publicPath(url)
        : path.join(config.publicPath, url)
    );
  }

  const hashes = pairs.map(item => hasha(item.content, { algorithm: 'md5' }));

  let info: ?{ width: number, height: number, type: string };

  try {
    info = size(this.resourcePath);

    const match = path
      .basename(this.resourcePath)
      .match(new RegExp(`^${escapeStringRegexp(filename)}${suffix}`));

    if (match && match[1]) {
      const scale = Number(match[1].replace(/[^\d.]/g, ''));

      if (typeof scale === 'number' && Number.isFinite(scale)) {
        info.width /= scale;
        info.height /= scale;
      }
    }
  } catch (e) {
    // Asset is not an image
  }

  callback(
    null,
    dedent`
    var AssetRegistry = require('react-native/Libraries/Image/AssetRegistry');
    module.exports = AssetRegistry.registerAsset({
      __packager_asset: true,
      scales: ${JSON.stringify(scales)},
      name: ${JSON.stringify(filename)},
      type: ${JSON.stringify(type)},
      hash: ${JSON.stringify(hashes.join())},
      httpServerLocation: ${publicPath},
      ${config.bundle ? '' : `fileSystemLocation: ${JSON.stringify(dirname)},`}
      ${info ? `height: ${info.height},` : ''}
      ${info ? `width: ${info.width},` : ''}
    });
    `
  );
};

module.exports.raw = true;
<commit_msg>fix: assetLoader android path issue when bundling (#436)<commit_after>/**
 * Copyright 2017-present, Callstack.
 * All rights reserved.
 *
 * @flow
 */

const utils = require('loader-utils');
const size = require('image-size');
const path = require('path');
const dedent = require('dedent');
const hasha = require('hasha');
const escapeStringRegexp = require('escape-string-regexp');
const AssetResolver = require('../resolvers/AssetResolver');

type Config = {
  platform: string,
  bundle?: boolean,
  root: string,
  outputPath?: string | ((path: string) => string),
  publicPath?: string | ((path: string) => string),
};

module.exports = async function assetLoader() {
  this.cacheable();

  const callback = this.async();

  const query = utils.getOptions(this) || {};
  const config: Config = Object.assign(
    {},
    { platform: 'ios', root: process.cwd() },
    query
  );

  const pathSepPattern = new RegExp(`\\${path.sep}`, 'g');
  const filepath = this.resourcePath;
  const dirname = path.dirname(filepath);
  const url = path.relative(config.root, dirname);
  const type = path.extname(filepath).replace(/^\./, '');
  const assets = path.join('assets', config.bundle ? '' : config.platform);
  const suffix = `(@\\d+(\\.\\d+)?x)?(\\.(${config.platform}|native))?\\.${type}$`;
  const filename = path.basename(filepath).replace(new RegExp(suffix), '');
  const normalizedUrl = url.replace(new RegExp(`^[\\.\\${path.sep}]+`), '');
  const normalizedName =
    normalizedUrl.length === 0
      ? filename
      : `${normalizedUrl.replace(pathSepPattern, '_')}_${filename}`;
  const longname = `${normalizedName
    .toLowerCase()
    .replace(/[^a-z0-9_]/g, '')}.${type}`;

  const result = await new Promise((resolve, reject) =>
    this.fs.readdir(dirname, (err, res) => {
      if (err) {
        reject(err);
      } else {
        resolve(res);
      }
    })
  );

  const map = AssetResolver.collect(result, {
    name: filename,
    type,
    platform: config.platform,
  });

  const scales = Object.keys(map)
    .map(s => Number(s.replace(/[^\d.]/g, '')))
    .sort();

  const pairs = await Promise.all(
    Object.keys(map).map(scale => {
      this.addDependency(path.join(dirname, map[scale].name));

      return new Promise((resolve, reject) =>
        this.fs.readFile(path.join(dirname, map[scale].name), (err, res) => {
          if (err) {
            reject(err);
          } else {
            let dest;

            if (config.bundle && config.platform === 'android') {
              switch (scale) {
                case '@0.75x':
                  dest = 'drawable-ldpi';
                  break;
                case '@1x':
                  dest = 'drawable-mdpi';
                  break;
                case '@1.5x':
                  dest = 'drawable-hdpi';
                  break;
                case '@2x':
                  dest = 'drawable-xhdpi';
                  break;
                case '@3x':
                  dest = 'drawable-xxhdpi';
                  break;
                case '@4x':
                  dest = 'drawable-xxxhdpi';
                  break;
                default:
                  throw new Error(`Unknown scale ${scale} for ${filepath}`);
              }

              dest = path.join(dest, longname);
            } else {
              const name = `${filename}${scale === '@1x' ? '' : scale}.${type}`;
              dest = path.join(assets, url, name);
            }

            resolve({
              destination: dest,
              content: res,
            });
          }
        })
      );
    })
  );

  pairs.forEach(item => {
    let dest = item.destination;

    if (config.outputPath) {
      // support functions as outputPath to generate them dynamically
      dest =
        typeof config.outputPath === 'function'
          ? config.outputPath(dest)
          : path.join(config.outputPath, dest);
    }

    this.emitFile(dest, item.content);
  });

  let publicPath = JSON.stringify(
    path.join(assets, url).replace(pathSepPattern, '/')
  );

  if (config.publicPath) {
    // support functions as publicPath to generate them dynamically
    publicPath = JSON.stringify(
      typeof config.publicPath === 'function'
        ? config.publicPath(url)
        : path.join(config.publicPath, url)
    );
  }

  const hashes = pairs.map(item => hasha(item.content, { algorithm: 'md5' }));

  let info: ?{ width: number, height: number, type: string };

  try {
    info = size(this.resourcePath);

    const match = path
      .basename(this.resourcePath)
      .match(new RegExp(`^${escapeStringRegexp(filename)}${suffix}`));

    if (match && match[1]) {
      const scale = Number(match[1].replace(/[^\d.]/g, ''));

      if (typeof scale === 'number' && Number.isFinite(scale)) {
        info.width /= scale;
        info.height /= scale;
      }
    }
  } catch (e) {
    // Asset is not an image
  }

  callback(
    null,
    dedent`
    var AssetRegistry = require('react-native/Libraries/Image/AssetRegistry');
    module.exports = AssetRegistry.registerAsset({
      __packager_asset: true,
      scales: ${JSON.stringify(scales)},
      name: ${JSON.stringify(filename)},
      type: ${JSON.stringify(type)},
      hash: ${JSON.stringify(hashes.join())},
      httpServerLocation: ${publicPath},
      ${config.bundle ? '' : `fileSystemLocation: ${JSON.stringify(dirname)},`}
      ${info ? `height: ${info.height},` : ''}
      ${info ? `width: ${info.width},` : ''}
    });
    `
  );
};

module.exports.raw = true;
<|endoftext|>


<commit_before>var ws = require("nodejs-websocket");
var Autolinker = require('autolinker');
var microtime = require("microtime");
var util = require("util");

function htmlspecialchars(string,quote_style,charset,double_encode){var optTemp=0,i=0,noquotes=false;if(typeof quote_style==='undefined'||quote_style===null){quote_style=2}string=string.toString();if(double_encode!==false){string=string.replace(/&/g,'&')}string=string.replace(/</g,'<').replace(/>/g,'>');var OPTS={'ENT_NOQUOTES':0,'ENT_HTML_QUOTE_SINGLE':1,'ENT_HTML_QUOTE_DOUBLE':2,'ENT_COMPAT':2,'ENT_QUOTES':3,'ENT_IGNORE':4};if(quote_style===0){noquotes=true}if(typeof quote_style!=='number'){quote_style=[].concat(quote_style);for(i=0;i<quote_style.length;i++){if(OPTS[quote_style[i]]===0){noquotes=true}else if(OPTS[quote_style[i]]){optTemp=optTemp|OPTS[quote_style[i]]}}quote_style=optTemp}if(quote_style&OPTS.ENT_HTML_QUOTE_SINGLE){string=string.replace(/'/g,''')}if(!noquotes){string=string.replace(/"/g,'"')}return string}

var server = ws.createServer(function (connection) {
	connection.nickname = null;
	connection.timerout = setTimeout(connection.timeout,10000);
	connection.timeout = function(){ connection.close(1011,"Ping Timeout"); }
	connection.on("text", function (str) {
		regPacket = /([A-Z]{4})\s?(.*)/g;
		regMatch = regPacket.exec(str.trim());
		if(regMatch === null) {
			connection.close(500, "Bad Request");
			return;
		}
		Protocol = regMatch[1];

		// No TEXT Part
		if(Protocol == "PING") {
			connection.sendText("PONG");
			clearTimeout(connection.timerout);
			connection.timerout = setTimeout(connection.timeout,10000);
			return;
		} else if(Protocol == "LIST") {
			server.connections.forEach(function (user) {
				if(user.nickname != null) {
					connection.sendText("CHAT " + user.nickname + "");
				}
			});
			return;
		}

		// TEXT Part
		regText = htmlspecialchars(regMatch[2], "ENT_QUOTES");

		if(Protocol == "NICK") {
			if (regText == "") {
				connection.sendText("ERRO 올바른 닉네임을 입력해주세요");
				return;
			}
			if (isDuplicateNick(regText)) {
				connection.sendText("ERRO 이미 존재하는 닉네임 입니다");
				return;
			} else {
				if (connection.nickname === null) {
					connection.nickname = regText;
					connection.sendText("HELO");
					broadcast("CHAT " + regText + " 님이 입장하셨습니다");
					return;
				} else {
					var oldNick = connection.nickname;
					connection.nickname = regText;
					broadcast("CHAT " + oldNick + " 님이 닉네임을 " + regText + "로 변경하셨습니다");
					return;
				}
			}
		}

		if (connection.nickname === null) {
			connection.close(401, "Unauthorized");
			return;
		}

		if (Protocol == "CHAT") {
			broadcast("CHAT [" + connection.nickname + "] " + Autolinker.link(regText));
			return;
		} else {
			connection.close(500, "Bad Request");
			return;
		}
	});

	connection.on("close", function (code, reason) {
		if (connection.nickname !== null) {
			broadcast("CHAT " + connection.nickname + " 님이 퇴장하셨습니다 (" + reason + ")");
		}
	});

	connection.on("error", function (e) {
		console.log("An error occurred: " + e);
		if(connection.nickname !== null) {
			broadcast("CHAT " + connection.nickname + " 님이 퇴장하셨습니다 (" + e + ")");
		}
	});
}).listen(8000);

function isDuplicateNick(nickname) {
	var isDup = false;
	server.connections.forEach(function (connection) {
		if(connection.nickname != null) {
			if(nickname.toLowerCase() == connection.nickname.toLowerCase()) {
				isDup = true;
			}
		}
	})
	return isDup;
}

function broadcast(str) {
	server.connections.forEach(function (connection) {
		connection.sendText(str);
	})
}<commit_msg>Added server logging<commit_after>var ws = require("nodejs-websocket");
var Autolinker = require('autolinker');
var microtime = require("microtime");
var util = require("util");

function htmlspecialchars(string,quote_style,charset,double_encode){var optTemp=0,i=0,noquotes=false;if(typeof quote_style==='undefined'||quote_style===null){quote_style=2}string=string.toString();if(double_encode!==false){string=string.replace(/&/g,'&')}string=string.replace(/</g,'<').replace(/>/g,'>');var OPTS={'ENT_NOQUOTES':0,'ENT_HTML_QUOTE_SINGLE':1,'ENT_HTML_QUOTE_DOUBLE':2,'ENT_COMPAT':2,'ENT_QUOTES':3,'ENT_IGNORE':4};if(quote_style===0){noquotes=true}if(typeof quote_style!=='number'){quote_style=[].concat(quote_style);for(i=0;i<quote_style.length;i++){if(OPTS[quote_style[i]]===0){noquotes=true}else if(OPTS[quote_style[i]]){optTemp=optTemp|OPTS[quote_style[i]]}}quote_style=optTemp}if(quote_style&OPTS.ENT_HTML_QUOTE_SINGLE){string=string.replace(/'/g,''')}if(!noquotes){string=string.replace(/"/g,'"')}return string}

var server = ws.createServer(function (connection) {
	connection.nickname = null;
	connection.timerout = setTimeout(connection.timeout,10000);
	connection.timeout = function(){ connection.close(1011,"Ping Timeout"); }
	connection.on("text", function (str) {
		regPacket = /([A-Z]{4})\s?(.*)/g;
		regMatch = regPacket.exec(str.trim());
		if(regMatch === null) {
			connection.close(500, "Bad Request");
			return;
		}
		Protocol = regMatch[1];

		// No TEXT Part
		if(Protocol == "PING") {
			connection.sendText("PONG");
			clearTimeout(connection.timerout);
			connection.timerout = setTimeout(connection.timeout,10000);
			return;
		} else if(Protocol == "LIST") {
			server.connections.forEach(function (user) {
				if(user.nickname != null) {
					connection.sendText("CHAT " + user.nickname + "");
				}
			});
			return;
		}

		// TEXT Part
		regText = htmlspecialchars(regMatch[2], "ENT_QUOTES");

		if(Protocol == "NICK") {
			if (regText == "") {
				connection.sendText("ERRO 올바른 닉네임을 입력해주세요");
				return;
			}
			if (isDuplicateNick(regText)) {
				connection.sendText("ERRO 이미 존재하는 닉네임 입니다");
				return;
			} else {
				if (connection.nickname === null) {
					connection.nickname = regText;
					connection.sendText("HELO");
					broadcast("CHAT " + regText + " 님이 입장하셨습니다");
					console.log(getTime() + regText + " connected");
					return;
				} else {
					var oldNick = connection.nickname;
					connection.nickname = regText;
					broadcast("CHAT " + oldNick + " 님이 닉네임을 " + regText + "로 변경하셨습니다");
					console.log(getTime() + oldNick + " changed to " + regText);
					return;
				}
			}
		}

		if (connection.nickname === null) {
			connection.close(401, "Unauthorized");
			return;
		}

		if (Protocol == "CHAT") {
			broadcast("CHAT [" + connection.nickname + "] " + Autolinker.link(regText));
			console.log(getTime() + getTime() + "[" + connection.nickname + "] " + regText);
			return;
		} else {
			connection.close(500, "Bad Request");
			return;
		}
	});

	connection.on("close", function (code, reason) {
		if (connection.nickname !== null) {
			broadcast("CHAT " + connection.nickname + " 님이 퇴장하셨습니다 (" + reason + ")");
			console.log(getTime() + connection.nickname + " disconnected (" + reason + ")");
		}
	});

	connection.on("error", function (e) {
		console.log(getTime() + "An error occurred: " + e);
		if(connection.nickname !== null) {
			broadcast("CHAT " + connection.nickname + " 님이 퇴장하셨습니다 (" + e + ")");
		}
	});
}).listen(8000);

function isDuplicateNick(nickname) {
	var isDup = false;
	server.connections.forEach(function (connection) {
		if(connection.nickname != null) {
			if(nickname.toLowerCase() == connection.nickname.toLowerCase()) {
				isDup = true;
			}
		}
	})
	return isDup;
}

function broadcast(str) {
	server.connections.forEach(function (connection) {
		connection.sendText(str);
	})
}<|endoftext|>


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

    angular
        .module('promort.slides_manager.controllers')
        .controller('QualityControlController', QualityControlController);

    QualityControlController.$inject = ['$scope', '$routeParams', '$location',
        'QualityControlService', 'ReviewStepsService'];

    function QualityControlController($scope, $routeParams, $location,
                                      QualityControlService, ReviewStepsService) {
        var vm = this;
        vm.slide_id = undefined;
        vm.case_id = undefined;
        vm.not_adequacy_reasons = undefined;
        vm.checkFormSubmission = checkFormSubmission;
        vm.submit = submit;

        vm.slideQualityControl = {};
        vm.reviewNotes = '';

        activate();

        function activate() {
            vm.slide_id = $routeParams.slide;
            vm.case_id = $routeParams.case;
            QualityControlService.get(vm.slide_id)
                .then(qualityControlSuccessFn, qualityControlErrorFn);

            function qualityControlSuccessFn(response) {
                // move to the ROIs review page
                $location.url('worklist/' + vm.case_id + '/' + vm.slide_id + '/rois');
            }

            function qualityControlErrorFn(response) {
                if (response.status === 404) {
                    // initialize not_adequacy_reason
                    QualityControlService.fetchNotAdequacyReasons()
                        .then(fetchNotAdequacyReasonSuccessFn);

                    //noinspection JSAnnotator
                    function fetchNotAdequacyReasonSuccessFn(response) {
                        vm.not_adequacy_reasons = response.data;
                    }
                } else {
                    console.error(response.error);
                }
            }
        }

        function checkFormSubmission() {
            if (vm.slideQualityControl.goodImageQuality &&
                vm.slideQualityControl.goodImageQuality === 'true') {
                return true;
            }
            if (vm.slideQualityControl.goodImageQuality &&
                vm.slideQualityControl.goodImageQuality === 'false' &&
                vm.slideQualityControl.notAdequacyReason) {
                return true;
            }
            return false;
        }

        function submit() {
            QualityControlService.create(
                vm.slide_id,
                $.parseJSON(vm.slideQualityControl.goodImageQuality),
                vm.slideQualityControl.notAdequacyReason
            ).then(qualityControlCreationSuccessFn, qualityControlCreationErrorFn);

            function qualityControlCreationSuccessFn(response) {
                if(vm.slideQualityControl.goodImageQuality === 'true') {
                    $location.url('worklist/' + vm.case_id + '/' + vm.slide_id + '/rois');
                } else {
                    // close the review because image quality is bad
                    ReviewStepsService.closeReviewStep(vm.case_id, 'REVIEW_1',
                        vm.slide_id, vm.reviewNotes)
                        .then(closeReviewSuccessFn, closeReviewErrorFn);

                    //noinspection JSAnnotator
                    function closeReviewSuccessFn(response) {
                        // review closed, go back to case worklist
                        $location.url('worklist/' + vm.case_id);
                    }

                    //noinspection JSAnnotator
                    function closeReviewErrorFn(response) {
                        console.error(response.error);
                    }
                }
            }

            function qualityControlCreationErrorFn(response) {
                console.error(response.error);
            }
        }
    }
})();<commit_msg>fixed link<commit_after>(function () {
    'use strict';

    angular
        .module('promort.slides_manager.controllers')
        .controller('QualityControlController', QualityControlController);

    QualityControlController.$inject = ['$scope', '$routeParams', '$location',
        'QualityControlService', 'ReviewStepsService'];

    function QualityControlController($scope, $routeParams, $location,
                                      QualityControlService, ReviewStepsService) {
        var vm = this;
        vm.slide_id = undefined;
        vm.case_id = undefined;
        vm.not_adequacy_reasons = undefined;
        vm.checkFormSubmission = checkFormSubmission;
        vm.submit = submit;

        vm.slideQualityControl = {};
        vm.reviewNotes = '';

        activate();

        function activate() {
            vm.slide_id = $routeParams.slide;
            vm.case_id = $routeParams.case;
            QualityControlService.get(vm.slide_id)
                .then(qualityControlSuccessFn, qualityControlErrorFn);

            function qualityControlSuccessFn(response) {
                // move to the ROIs review page
                $location.url('worklist/' + vm.case_id + '/' + vm.slide_id + '/rois_manager');
            }

            function qualityControlErrorFn(response) {
                if (response.status === 404) {
                    // initialize not_adequacy_reason
                    QualityControlService.fetchNotAdequacyReasons()
                        .then(fetchNotAdequacyReasonSuccessFn);

                    //noinspection JSAnnotator
                    function fetchNotAdequacyReasonSuccessFn(response) {
                        vm.not_adequacy_reasons = response.data;
                    }
                } else {
                    console.error(response.error);
                }
            }
        }

        function checkFormSubmission() {
            if (vm.slideQualityControl.goodImageQuality &&
                vm.slideQualityControl.goodImageQuality === 'true') {
                return true;
            }
            if (vm.slideQualityControl.goodImageQuality &&
                vm.slideQualityControl.goodImageQuality === 'false' &&
                vm.slideQualityControl.notAdequacyReason) {
                return true;
            }
            return false;
        }

        function submit() {
            QualityControlService.create(
                vm.slide_id,
                $.parseJSON(vm.slideQualityControl.goodImageQuality),
                vm.slideQualityControl.notAdequacyReason
            ).then(qualityControlCreationSuccessFn, qualityControlCreationErrorFn);

            function qualityControlCreationSuccessFn(response) {
                if(vm.slideQualityControl.goodImageQuality === 'true') {
                    $location.url('worklist/' + vm.case_id + '/' + vm.slide_id + '/rois');
                } else {
                    // close the review because image quality is bad
                    ReviewStepsService.closeReviewStep(vm.case_id, 'REVIEW_1',
                        vm.slide_id, vm.reviewNotes)
                        .then(closeReviewSuccessFn, closeReviewErrorFn);

                    //noinspection JSAnnotator
                    function closeReviewSuccessFn(response) {
                        // review closed, go back to case worklist
                        $location.url('worklist/' + vm.case_id);
                    }

                    //noinspection JSAnnotator
                    function closeReviewErrorFn(response) {
                        console.error(response.error);
                    }
                }
            }

            function qualityControlCreationErrorFn(response) {
                console.error(response.error);
            }
        }
    }
})();<|endoftext|>


<commit_before>// customize-home.js

// logo spin
$('#logo').hover(function(){
    $(this).addClass('fa-spin text-yellow-inverted');
}, function(){
    $(this).removeClass('fa-spin text-yellow-inverted');
});

// progress bar
$('#page-loading-progress').progress({
    total: 2,
    onSuccess: function() {
        $('#page-loading-progress').fadeOut(1000, function() {
            $('#page-loading-progress').remove();
        });
    }
});

// GitHub
function updateGitHub() {
    $('#github-watch img').attr('src', 'https://img.shields.io/github/watchers/iROCKBUNNY/BYR-Navi.svg?style=social&label=Watch');
    $('#github-star img').attr('src', 'https://img.shields.io/github/stars/iROCKBUNNY/BYR-Navi.svg?style=social&label=Star');
    $('#github-fork img').attr('src', 'https://img.shields.io/github/forks/iROCKBUNNY/BYR-Navi.svg?style=social&label=Fork');
};
updateGitHub();
setInterval(function() {
    updateGitHub();
}, 15000);

// version
moment.locale('zh-cn');
var pushedAt = 'loading';
$.getJSON('https://api.github.com/repos/iROCKBUNNY/BYR-Navi', function(data) {
    pushedAt = data.pushed_at;
    $('#page-loading-progress').progress('increment');
});
function updateVersion(pushedAt) {
    if (pushedAt !== 'loading') {
        $('#version img').attr('src', 'https://img.shields.io/badge/' + encodeURIComponent('更新') + '-' + encodeURIComponent(moment(pushedAt).fromNow()) + '-brightgreen.svg');
    };
};
updateVersion(pushedAt);
setInterval(function() {
    updateVersion(pushedAt);
}, 15000);

// visit
function updateVisit(updateProgressBar) {
    $.getJSON(urlPrefix + '/json/analytics_data.json', function(data) {
        $.getJSON(data.analytics.api_url, {
            'module': 'API',
            'method': 'VisitsSummary.getUniqueVisitors',
            'idSite': '1',
            'period': 'day',
            'date': 'today',
            'format': 'JSON',
            'token_auth': data.analytics.token
        }, function(data) {
            $('#visit img').attr('src', 'https://img.shields.io/badge/' + encodeURIComponent('今日访客') +'-' + encodeURIComponent(data.value) + '-brightgreen.svg');
            if (updateProgressBar) {
                $('#page-loading-progress').progress('increment');
            };
        });
    });
};
updateVisit(true);
setInterval(function() {
    updateVisit(false);
}, 15000);

// search
$('#search-services').dropdown();
if (Cookies.get('byr_navi_previous_search_service_option') == undefined || $('#' + Cookies.get('byr_navi_previous_search_service_option')).length === 0) {
    Cookies.set('byr_navi_previous_search_service_option', $('#search-services').val(), { expires: 365 });
} else {
    $('#search-services').dropdown('set selected', Cookies.get('byr_navi_previous_search_service_option'));
};

$('#search-button').click(function() {
    var service = $('#' + $('#search-services').val());
    var query = $('#search-query').val();
    query = encodeURIComponent(query);
    if (query) {
        Cookies.set('byr_navi_previous_search_service_option', $('#search-services').val(), { expires: 365 });
        window.open(service.attr('data-url') + query + service.attr('data-suffix'), '_blank');
    } else {
        $('#search-div').addClass('error');
        $('#search-query').attr('placeholder', '请输入搜索内容');
    };
});

$('#search-query').click(function() {
    $(this).select();
});

$(document).ready(function() {
    $('#search-query').focus();
});

$(window).keyup(function(event) {
    var windowTop = $(window).scrollTop();
    var windowHeight = $(window).innerHeight();
    var windowBottom = windowTop + windowHeight;
    var searchBoxTop = $('#search-div').offset().top;
    var searchBoxHeight = $('#search-div').innerHeight();
    var searchBoxBottom = searchBoxTop + searchBoxHeight;
    if (event.key == 'Enter' && searchBoxBottom > windowTop && searchBoxTop < windowBottom) {
        var service = $('#' + $('#search-services').val());
        var query = $('#search-query').val();
        query = encodeURIComponent(query);
        if (query) {
            if ($('#search-query:focus').length > 0) {
                Cookies.set('byr_navi_previous_search_service_option', $('#search-services').val(), { expires: 365 });
                window.open(service.attr('data-url') + query + service.attr('data-suffix'), '_blank');
            } else {
                $('#search-query').focus().select();
            };
        } else {
            $('#search-div').addClass('error');
            $('#search-query').attr('placeholder', '请输入搜索内容').focus();
        };
    };
});

$('#search-query').keyup(function(event) {
    if (event.key) {
        if ($('#search-query').val()) {
            $('#search-div').removeClass('error');
            $('#search-query').attr('placeholder', '立即搜索');
        };
    };
});

// query suggestions
var sugParams = {
    "XOffset": -3, //提示框位置横向偏移量,单位px
    "YOffset": -2, //提示框位置纵向偏移量,单位px
    // "width": $('#search-query').innerWidth(), //提示框宽度，单位px
    "fontColor": "rgba(0, 0, 0, 0.87)", //提示框文字颜色
    "fontColorHI": "rgba(0, 0, 0, 0.87)", //提示框高亮选择时文字颜色
    "fontSize": "14px", //文字大小
    "fontFamily": "Lato, 'Helvetica Neue', Arial, Helvetica, sans-serif", //文字字体
    "borderColor": "rgba(34, 36, 38, 0.14902)", //提示框的边框颜色
    "bgcolorHI": "rgba(0, 0, 0, 0.05)", //提示框高亮选择的颜色
    "sugSubmit": false //选中提示框中词条时是否提交表单
};
BaiduSuggestion.bind('search-query', sugParams);<commit_msg>Update<commit_after>// customize-home.js

// logo spin
$('#logo').hover(function(){
    $(this).addClass('fa-spin text-yellow-inverted');
}, function(){
    $(this).removeClass('fa-spin text-yellow-inverted');
});

// progress bar
$('#page-loading-progress').progress({
    total: 2,
    onSuccess: function() {
        $('#page-loading-progress').fadeOut(1000, function() {
            $('#page-loading-progress').remove();
        });
    }
});

// GitHub
function updateGitHub() {
    $('#github-watch img').attr('src', 'https://img.shields.io/github/watchers/iROCKBUNNY/BYR-Navi.svg?style=social&label=Watch');
    $('#github-star img').attr('src', 'https://img.shields.io/github/stars/iROCKBUNNY/BYR-Navi.svg?style=social&label=Star');
    $('#github-fork img').attr('src', 'https://img.shields.io/github/forks/iROCKBUNNY/BYR-Navi.svg?style=social&label=Fork');
};
updateGitHub();
setInterval(function() {
    updateGitHub();
}, 15000);

// version
moment.locale('zh-cn');
var pushedAt = 'loading';
$.getJSON('https://api.github.com/repos/iROCKBUNNY/BYR-Navi', function(data) {
    pushedAt = data.pushed_at;
    $('#page-loading-progress').progress('increment');
});
function updateVersion(timestamp) {
    if (timestamp !== 'loading') {
        $('#version img').attr('src', 'https://img.shields.io/badge/' + encodeURIComponent('更新') + '-' + encodeURIComponent(moment(timestamp).fromNow()) + '-brightgreen.svg');
    };
};
updateVersion(pushedAt);
setInterval(function() {
    updateVersion(pushedAt);
}, 15000);

// visit
function updateVisit(updateProgressBar) {
    $.getJSON(urlPrefix + '/json/analytics_data.json', function(data) {
        $.getJSON(data.analytics.api_url, {
            'module': 'API',
            'method': 'VisitsSummary.getUniqueVisitors',
            'idSite': '1',
            'period': 'day',
            'date': 'today',
            'format': 'JSON',
            'token_auth': data.analytics.token
        }, function(data) {
            $('#visit img').attr('src', 'https://img.shields.io/badge/' + encodeURIComponent('今日访客') +'-' + encodeURIComponent(data.value) + '-brightgreen.svg');
            if (updateProgressBar) {
                $('#page-loading-progress').progress('increment');
            };
        });
    });
};
updateVisit(true);
setInterval(function() {
    updateVisit(false);
}, 15000);

// search
$('#search-services').dropdown();
if (Cookies.get('byr_navi_previous_search_service_option') == undefined || $('#' + Cookies.get('byr_navi_previous_search_service_option')).length === 0) {
    Cookies.set('byr_navi_previous_search_service_option', $('#search-services').val(), { expires: 365 });
} else {
    $('#search-services').dropdown('set selected', Cookies.get('byr_navi_previous_search_service_option'));
};

$('#search-button').click(function() {
    var service = $('#' + $('#search-services').val());
    var query = $('#search-query').val();
    query = encodeURIComponent(query);
    if (query) {
        Cookies.set('byr_navi_previous_search_service_option', $('#search-services').val(), { expires: 365 });
        window.open(service.attr('data-url') + query + service.attr('data-suffix'), '_blank');
    } else {
        $('#search-div').addClass('error');
        $('#search-query').attr('placeholder', '请输入搜索内容');
    };
});

$('#search-query').click(function() {
    $(this).select();
});

$(document).ready(function() {
    $('#search-query').focus();
});

$(window).keyup(function(event) {
    var windowTop = $(window).scrollTop();
    var windowHeight = $(window).innerHeight();
    var windowBottom = windowTop + windowHeight;
    var searchBoxTop = $('#search-div').offset().top;
    var searchBoxHeight = $('#search-div').innerHeight();
    var searchBoxBottom = searchBoxTop + searchBoxHeight;
    if (event.key == 'Enter' && searchBoxBottom > windowTop && searchBoxTop < windowBottom) {
        var service = $('#' + $('#search-services').val());
        var query = $('#search-query').val();
        query = encodeURIComponent(query);
        if (query) {
            if ($('#search-query:focus').length > 0) {
                Cookies.set('byr_navi_previous_search_service_option', $('#search-services').val(), { expires: 365 });
                window.open(service.attr('data-url') + query + service.attr('data-suffix'), '_blank');
            } else {
                $('#search-query').focus().select();
            };
        } else {
            $('#search-div').addClass('error');
            $('#search-query').attr('placeholder', '请输入搜索内容').focus();
        };
    };
});

$('#search-query').keyup(function(event) {
    if (event.key) {
        if ($('#search-query').val()) {
            $('#search-div').removeClass('error');
            $('#search-query').attr('placeholder', '立即搜索');
        };
    };
});

// query suggestions
var sugParams = {
    "XOffset": -3, //提示框位置横向偏移量,单位px
    "YOffset": -2, //提示框位置纵向偏移量,单位px
    // "width": $('#search-query').innerWidth(), //提示框宽度，单位px
    "fontColor": "rgba(0, 0, 0, 0.87)", //提示框文字颜色
    "fontColorHI": "rgba(0, 0, 0, 0.87)", //提示框高亮选择时文字颜色
    "fontSize": "14px", //文字大小
    "fontFamily": "Lato, 'Helvetica Neue', Arial, Helvetica, sans-serif", //文字字体
    "borderColor": "rgba(34, 36, 38, 0.14902)", //提示框的边框颜色
    "bgcolorHI": "rgba(0, 0, 0, 0.05)", //提示框高亮选择的颜色
    "sugSubmit": false //选中提示框中词条时是否提交表单
};
BaiduSuggestion.bind('search-query', sugParams);<|endoftext|>