<commit_before>(function(){

    xtag.register('widget-DAQ', {
        extends: 'div',
        lifecycle: {
            created: function() {
                var xString, option, title, deckWrap;

                this.width = this.offsetWidth;
                this.height = window.innerHeight*0.6;

                //get the DAQ structure
                XHR('http://' + this.MIDAS + '/?cmd=jcopy&odb=/DAQ&encoding=json-nokeys',
                    function(res){
                        this.buildDAQ(res);
                    }.bind(this),
                    'application/json');

                //build DOM
                this.navBlock = document.createElement('div');
                this.navBlock.setAttribute('class', 'DAQnav');
                this.appendChild(this.navBlock);

                title = document.createElement('h1');
                title.innerHTML = 'DAQ';
                this.navBlock.appendChild(title);

                this.cardNav = document.createElement('select');
                this.cardNav.setAttribute('id', 'DAQnav')
                this.cardNav.setAttribute('class', 'stdin');
                this.cardNav.onchange = function(){
                    document.getElementById('DAQdeck').shuffleTo(selected('DAQnav'));
                }.bind(this)
                this.navBlock.appendChild(this.cardNav);

                option = document.createElement('option');
                option.value = 0;
                option.innerHTML = 'Master'
                this.cardNav.appendChild(option);

                deckWrap = document.createElement('div');
                this.appendChild(deckWrap);

                xString = '<x-deck id="DAQdeck" selected-index=0>';
                xString += '<x-card id="DAQmasterCard"></x-card></x-deck>';
                xtag.innerHTML(deckWrap, xString);
                this.nCards = 1

                this.masterBlock = document.createElement('div');
                this.masterBlock.setAttribute('class', 'DAQheadNode');
                document.getElementById('DAQmasterCard').appendChild(this.masterBlock);

                this.collectorBlock = document.createElement('div');
                this.collectorBlock.setAttribute('id', 'collectorBlock');
                document.getElementById('DAQmasterCard').appendChild(this.collectorBlock);

                ////////////////////////////
                //Kinetic.js setup
                ////////////////////////////

                //indices for these arrays correspond to the x-card index on display
                this.stage = [];
                this.mainLayer = [];
                this.scaleLayer = [];
                this.tooltipLayer = [];
                this.TTbkg = [];
                this.text = [];
            },
            inserted: function() {},
            removed: function() {},
            attributeChanged: function() {}
        },
        events: {

        },
        accessors: {
            'MIDAS':{
                attribute: {} //this just needs to be declared
            }
        },
        methods: {
            'buildDAQ' : function(response){
                var data = JSON.parse(response),
                    i, j, k, option,
                    collectorGutter = this.width*0.02,
                    collectorWidth = (this.width - collectorGutter*16) / 16,
                    xLength = collectorGutter/2,
                    xLeft, xRight;

                this.collectors = [];
                this.digitizers = [];
                this.collectorCells = [];

                //determine what collectors are present and instantiate x-cards for each one
                for(i=0; i<16; i++){
                    this.collectors[i] = data.hosts['collector0x' + i.toString(16)];

                    if(this.collectors[i]){
                        document.getElementById('DAQdeck').innerHTML += '<x-card id="collector'+i+'">

</x-card>';
                        option = document.createElement('option');
                        option.value = this.nCards;
                        option.innerHTML = 'Collector 0x' + i.toString(16).toUpperCase();
                        this.cardNav.appendChild(option);
                        this.nCards++;

                    }
                }

                //now that the xdeck is built, paint master canvas:
                //collectors:
                this.setupKinetic('collectorBlock');
                for(i=0; i<16; i++){
                    if(this.collectors[i]){
                        this.collectorCells[i] = new Kinetic.Rect({
                            x:collectorGutter/2 + i*this.width/16,
                            y:this.height*0.6,
                            width: collectorWidth,
                            height:this.height*0.2,
                            fill:'#555555',
                            stroke: '#000000',
                            strokeWidth: 4
                        });
                        this.collectorCells[i].on('click', this.clickCollector.bind(this, i));
                        this.mainLayer[0].add(this.collectorCells[i]);
                    } else{
                        //terminate loose cord with red x
                        xLeft = new Kinetic.Line({
                            points: [(collectorGutter + collectorWidth)/2 + i*(collectorGutter+collectorWidth) - xLength, 0.6*this.height - xLength, (collectorGutter + collectorWidth)/2 + i*(collectorGutter+collectorWidth) + xLength, 0.6*this.height + xLength],
                            stroke: '#FF0000',
                            strokeWidth: 8
                        });
                        xRight = new Kinetic.Line({
                            points: [(collectorGutter + collectorWidth)/2 + i*(collectorGutter+collectorWidth) + xLength, 0.6*this.height - xLength, (collectorGutter + collectorWidth)/2 + i*(collectorGutter+collectorWidth) - xLength, 0.6*this.height + xLength],
                            stroke: '#FF0000',
                            strokeWidth: 8
                        });
                        this.mainLayer[0].add(xLeft);
                        this.mainLayer[0].add(xRight);
                    }
                }

                //cabling:
                this.masterCables = [[],[],[],[]]; //1-to-4 cables: outer index counts master port, inner index counts collector
                for(i=0; i<4; i++){
                    this.masterCables[i][0] = new Kinetic.Line({
                        points: [collectorWidth*2 + collectorGutter*1.75 + i*(collectorWidth + collectorGutter)*4,0, collectorWidth*2 + collectorGutter*1.75 + i*(collectorWidth + collectorGutter)*4, 0.3*this.height],
                        stroke: '#000000',
                        strokeWidth: 4
                    });
                    this.mainLayer[0].add(this.masterCables[i][0]);
                    this.masterCables[i][0].moveToBottom();
                    for(j=1; j<5; j++){
                        this.masterCables[i][j] = new Kinetic.Line({
                            points: [collectorWidth*2 + collectorGutter*1.75 + i*(collectorWidth + collectorGutter)*4, 0.3*this.height, (collectorGutter + collectorWidth)/2 + (4*i+j-1)*(collectorGutter+collectorWidth), 0.6*this.height],
                            stroke: '#000000',
                            strokeWidth: 4
                        });
                        this.mainLayer[0].add(this.masterCables[i][j]);
                        this.masterCables[i][j].moveToBottom();
                    }
                }
                this.mainLayer[0].draw();

                //and again for each collector card
                this.digitizerCells = [];
                this.collectorCables = [];
                for(i=0; i<16; i++){
                    this.digitizerCells[i] = [];

                    if(!this.collectors[i]) continue;

                    this.setupKinetic('digitizerBlock'+i);
                    for(j=0; j<16; j++){
                        if(data.hosts['collector0x' + i.toString(16)].digitizers[j]){
                            this.digitizerCells[i][j] = new Kinetic.Rect({
                                x:collectorGutter/2 + j*this.width/16,
                                y:this.height*0.6,
                                width: collectorWidth,
                                height:this.height*0.2,
                                fill:'#555555',
                                stroke: '#000000',
                                strokeWidth: 4
                            });
                            this.mainLayer[i+1].add(this.digitizerCells[i][j]);
                        } else{
                            //terminate loose cord with red x
                            xLeft = new Kinetic.Line({
                                points: [(collectorGutter + collectorWidth)/2 + j*(collectorGutter+collectorWidth) - xLength, 0.6*this.height - xLength, (collectorGutter + collectorWidth)/2 + j*(collectorGutter+collectorWidth) + xLength, 0.6*this.height + xLength],
                                stroke: '#FF0000',
                                strokeWidth: 8
                            });
                            xRight = new Kinetic.Line({
                                points: [(collectorGutter + collectorWidth)/2 + j*(collectorGutter+collectorWidth) + xLength, 0.6*this.height - xLength, (collectorGutter + collectorWidth)/2 + j*(collectorGutter+collectorWidth) - xLength, 0.6*this.height + xLength],
                                stroke: '#FF0000',
                                strokeWidth: 8
                            });
                            this.mainLayer[i+1].add(xLeft);
                            this.mainLayer[i+1].add(xRight);
                        }

                    }

                    //cabling:
                    this.collectorCables[i] = [];
                    for(j=0; j<4; j++){
                        this.collectorCables[i][j] = [];
                        this.collectorCables[i][j][0] = new Kinetic.Line({
                            points: [collectorWidth*2 + collectorGutter*1.75 + j*(collectorWidth + collectorGutter)*4,0, collectorWidth*2 + collectorGutter*1.75 + j*(collectorWidth + collectorGutter)*4, 0.3*this.height],
                            stroke: '#000000',
                            strokeWidth: 4
                        });
                        this.mainLayer[i+1].add(this.collectorCables[i][j][0]);
                        this.collectorCables[i][j][0].moveToBottom();
                        for(k=1; k<5; k++){
                            this.collectorCables[i][j][k] = new Kinetic.Line({
                                points: [collectorWidth*2 + collectorGutter*1.75 + j*(collectorWidth + collectorGutter)*4, 0.3*this.height, (collectorGutter + collectorWidth)/2 + (4*j+k-1)*(collectorGutter+collectorWidth), 0.6*this.height],
                                stroke: '#000000',
                                strokeWidth: 4
                            });
                            this.mainLayer[i+1].add(this.collectorCables[i][j][k]);
                            this.collectorCables[i][j][k].moveToBottom();
                        }
                    }
                    this.mainLayer[i+1].draw();
                }

            },

            'setupKinetic' : function(targetID){
                var i = this.stage.length;
                //point kinetic at the div and set up the staging and layers:
                this.stage[i] = new Kinetic.Stage({
                    container: targetID,
                    width: this.width,
                    height: this.height
                });
                this.mainLayer[i] = new Kinetic.Layer();       //main rendering layer
                this.scaleLayer[i] = new Kinetic.Layer();      //layer for scales / legends
                this.tooltipLayer[i] = new Kinetic.Layer();    //layer for tooltip info

                //tooltip background:
                this.TTbkg[i] = new Kinetic.Rect({
                    x:-1000,
                    y:-1000,
                    width:100,
                    height:100,
                    fill:'rgba(0,0,0,0.8)',
                    stroke: 'rgba(0,0,0,0)',
                    listening: false
                });
                this.tooltipLayer[i].add(this.TTbkg[i]);

                //tooltip text:
                this.text[i] = new Kinetic.Text({
                    x: -1000,
                    y: -1000,
                    fontFamily: 'Arial',
                    fontSize: 16,
                    text: '',
                    lineHeight: 1.2,
                    fill: '#EEEEEE',
                    listening: false
                });
                this.tooltipLayer[i].add(this.text[i]);

                this.stage[i].add(this.mainLayer[i]);
                this.stage[i].add(this.scaleLayer[i]);
                this.stage[i].add(this.tooltipLayer[i]);
            },

            'clickCollector' : function(index){
                document.getElementById('DAQdeck').shuffleTo(index+1);
            }
        }
    });

})();<commit_msg>master/collector onclick<commit_after>(function(){

    xtag.register('widget-DAQ', {
        extends: 'div',
        lifecycle: {
            created: function() {
                var xString, option, title, deckWrap;

                this.width = this.offsetWidth;
                this.height = window.innerHeight*0.6;

                //get the DAQ structure
                XHR('http://' + this.MIDAS + '/?cmd=jcopy&odb=/DAQ&encoding=json-nokeys',
                    function(res){
                        this.buildDAQ(res);
                    }.bind(this),
                    'application/json');

                //build DOM
                this.navBlock = document.createElement('div');
                this.navBlock.setAttribute('class', 'DAQnav');
                this.appendChild(this.navBlock);

                title = document.createElement('h1');
                title.innerHTML = 'DAQ';
                this.navBlock.appendChild(title);

                this.cardNav = document.createElement('select');
                this.cardNav.setAttribute('id', 'DAQnav')
                this.cardNav.setAttribute('class', 'stdin');
                this.cardNav.onchange = function(){
                    document.getElementById('DAQdeck').shuffleTo(selected('DAQnav'));
                }.bind(this)
                this.navBlock.appendChild(this.cardNav);

                option = document.createElement('option');
                option.value = 0;
                option.innerHTML = 'Master'
                this.cardNav.appendChild(option);

                deckWrap = document.createElement('div');
                this.appendChild(deckWrap);

                xString = '<x-deck id="DAQdeck" selected-index=0>';
                xString += '<x-card id="DAQmasterCard"></x-card></x-deck>';
                xtag.innerHTML(deckWrap, xString);
                this.nCards = 1

                this.masterBlock = document.createElement('div');
                this.masterBlock.setAttribute('class', 'DAQheadNode');
                document.getElementById('DAQmasterCard').appendChild(this.masterBlock);

                this.collectorBlock = document.createElement('div');
                this.collectorBlock.setAttribute('id', 'collectorBlock');
                document.getElementById('DAQmasterCard').appendChild(this.collectorBlock);

                ////////////////////////////
                //Kinetic.js setup
                ////////////////////////////

                //indices for these arrays correspond to the x-card index on display
                this.stage = [];
                this.mainLayer = [];
                this.scaleLayer = [];
                this.tooltipLayer = [];
                this.TTbkg = [];
                this.text = [];
            },
            inserted: function() {},
            removed: function() {},
            attributeChanged: function() {}
        },
        events: {

        },
        accessors: {
            'MIDAS':{
                attribute: {} //this just needs to be declared
            }
        },
        methods: {
            'buildDAQ' : function(response){
                var data = JSON.parse(response),
                    i, j, k, option,
                    collectorGutter = this.width*0.02,
                    collectorWidth = (this.width - collectorGutter*16) / 16,
                    xLength = collectorGutter/2,
                    xLeft, xRight;

                this.collectors = [];
                this.digitizers = [];
                this.collectorCells = [];

                //determine what collectors are present and instantiate x-cards for each one
                for(i=0; i<16; i++){
                    this.collectors[i] = data.hosts['collector0x' + i.toString(16)];

                    if(this.collectors[i]){
                        document.getElementById('DAQdeck').innerHTML += '<x-card id="collector'+i+'">

</x-card>';
                        option = document.createElement('option');
                        option.value = this.nCards;
                        option.innerHTML = 'Collector 0x' + i.toString(16).toUpperCase();
                        this.cardNav.appendChild(option);
                        this.nCards++;

                    }
                }

                //now that the xdeck is built, paint master canvas:
                //collectors:
                this.setupKinetic('collectorBlock');
                for(i=0; i<16; i++){
                    if(this.collectors[i]){
                        this.collectorCells[i] = new Kinetic.Rect({
                            x:collectorGutter/2 + i*this.width/16,
                            y:this.height*0.6,
                            width: collectorWidth,
                            height:this.height*0.2,
                            fill:'#555555',
                            stroke: '#000000',
                            strokeWidth: 4
                        });
                        this.collectorCells[i].on('click', this.clickCollector.bind(this, i));
                        this.mainLayer[0].add(this.collectorCells[i]);
                    } else{
                        //terminate loose cord with red x
                        xLeft = new Kinetic.Line({
                            points: [(collectorGutter + collectorWidth)/2 + i*(collectorGutter+collectorWidth) - xLength, 0.6*this.height - xLength, (collectorGutter + collectorWidth)/2 + i*(collectorGutter+collectorWidth) + xLength, 0.6*this.height + xLength],
                            stroke: '#FF0000',
                            strokeWidth: 8
                        });
                        xRight = new Kinetic.Line({
                            points: [(collectorGutter + collectorWidth)/2 + i*(collectorGutter+collectorWidth) + xLength, 0.6*this.height - xLength, (collectorGutter + collectorWidth)/2 + i*(collectorGutter+collectorWidth) - xLength, 0.6*this.height + xLength],
                            stroke: '#FF0000',
                            strokeWidth: 8
                        });
                        this.mainLayer[0].add(xLeft);
                        this.mainLayer[0].add(xRight);
                    }
                }

                //cabling:
                this.masterCables = [[],[],[],[]]; //1-to-4 cables: outer index counts master port, inner index counts collector
                for(i=0; i<4; i++){
                    this.masterCables[i][0] = new Kinetic.Line({
                        points: [collectorWidth*2 + collectorGutter*1.75 + i*(collectorWidth + collectorGutter)*4,0, collectorWidth*2 + collectorGutter*1.75 + i*(collectorWidth + collectorGutter)*4, 0.3*this.height],
                        stroke: '#000000',
                        strokeWidth: 4
                    });
                    this.mainLayer[0].add(this.masterCables[i][0]);
                    this.masterCables[i][0].moveToBottom();
                    for(j=1; j<5; j++){
                        this.masterCables[i][j] = new Kinetic.Line({
                            points: [collectorWidth*2 + collectorGutter*1.75 + i*(collectorWidth + collectorGutter)*4, 0.3*this.height, (collectorGutter + collectorWidth)/2 + (4*i+j-1)*(collectorGutter+collectorWidth), 0.6*this.height],
                            stroke: '#000000',
                            strokeWidth: 4
                        });
                        this.mainLayer[0].add(this.masterCables[i][j]);
                        this.masterCables[i][j].moveToBottom();
                    }
                }
                this.mainLayer[0].draw();

                //and again for each collector card
                this.digitizerCells = [];
                this.collectorCables = [];
                for(i=0; i<16; i++){
                    this.digitizerCells[i] = [];

                    if(!this.collectors[i]) continue;

                    this.setupKinetic('digitizerBlock'+i);
                    for(j=0; j<16; j++){
                        if(data.hosts['collector0x' + i.toString(16)].digitizers[j]){
                            this.digitizerCells[i][j] = new Kinetic.Rect({
                                x:collectorGutter/2 + j*this.width/16,
                                y:this.height*0.6,
                                width: collectorWidth,
                                height:this.height*0.2,
                                fill:'#555555',
                                stroke: '#000000',
                                strokeWidth: 4
                            });
                            this.mainLayer[i+1].add(this.digitizerCells[i][j]);
                        } else{
                            //terminate loose cord with red x
                            xLeft = new Kinetic.Line({
                                points: [(collectorGutter + collectorWidth)/2 + j*(collectorGutter+collectorWidth) - xLength, 0.6*this.height - xLength, (collectorGutter + collectorWidth)/2 + j*(collectorGutter+collectorWidth) + xLength, 0.6*this.height + xLength],
                                stroke: '#FF0000',
                                strokeWidth: 8
                            });
                            xRight = new Kinetic.Line({
                                points: [(collectorGutter + collectorWidth)/2 + j*(collectorGutter+collectorWidth) + xLength, 0.6*this.height - xLength, (collectorGutter + collectorWidth)/2 + j*(collectorGutter+collectorWidth) - xLength, 0.6*this.height + xLength],
                                stroke: '#FF0000',
                                strokeWidth: 8
                            });
                            this.mainLayer[i+1].add(xLeft);
                            this.mainLayer[i+1].add(xRight);
                        }

                    }

                    //cabling:
                    this.collectorCables[i] = [];
                    for(j=0; j<4; j++){
                        this.collectorCables[i][j] = [];
                        this.collectorCables[i][j][0] = new Kinetic.Line({
                            points: [collectorWidth*2 + collectorGutter*1.75 + j*(collectorWidth + collectorGutter)*4,0, collectorWidth*2 + collectorGutter*1.75 + j*(collectorWidth + collectorGutter)*4, 0.3*this.height],
                            stroke: '#000000',
                            strokeWidth: 4
                        });
                        this.mainLayer[i+1].add(this.collectorCables[i][j][0]);
                        this.collectorCables[i][j][0].moveToBottom();
                        for(k=1; k<5; k++){
                            this.collectorCables[i][j][k] = new Kinetic.Line({
                                points: [collectorWidth*2 + collectorGutter*1.75 + j*(collectorWidth + collectorGutter)*4, 0.3*this.height, (collectorGutter + collectorWidth)/2 + (4*j+k-1)*(collectorGutter+collectorWidth), 0.6*this.height],
                                stroke: '#000000',
                                strokeWidth: 4
                            });
                            this.mainLayer[i+1].add(this.collectorCables[i][j][k]);
                            this.collectorCables[i][j][k].moveToBottom();
                        }
                    }
                    this.mainLayer[i+1].draw();
                }

            },

            'setupKinetic' : function(targetID){
                var i = this.stage.length;
                //point kinetic at the div and set up the staging and layers:
                this.stage[i] = new Kinetic.Stage({
                    container: targetID,
                    width: this.width,
                    height: this.height
                });
                this.mainLayer[i] = new Kinetic.Layer();       //main rendering layer
                this.scaleLayer[i] = new Kinetic.Layer();      //layer for scales / legends
                this.tooltipLayer[i] = new Kinetic.Layer();    //layer for tooltip info

                //tooltip background:
                this.TTbkg[i] = new Kinetic.Rect({
                    x:-1000,
                    y:-1000,
                    width:100,
                    height:100,
                    fill:'rgba(0,0,0,0.8)',
                    stroke: 'rgba(0,0,0,0)',
                    listening: false
                });
                this.tooltipLayer[i].add(this.TTbkg[i]);

                //tooltip text:
                this.text[i] = new Kinetic.Text({
                    x: -1000,
                    y: -1000,
                    fontFamily: 'Arial',
                    fontSize: 16,
                    text: '',
                    lineHeight: 1.2,
                    fill: '#EEEEEE',
                    listening: false
                });
                this.tooltipLayer[i].add(this.text[i]);

                this.stage[i].add(this.mainLayer[i]);
                this.stage[i].add(this.scaleLayer[i]);
                this.stage[i].add(this.tooltipLayer[i]);
            },

            'clickCollector' : function(index){
                //document.getElementById('DAQdeck').shuffleTo(index+1);
                document.getElementById('DAQnav').value = index+1;
                document.getElementById('DAQnav').onchange();
            }
        }
    });

})();<|endoftext|>


<commit_before>import expect from 'expect';
import { fromJS } from 'immutable';
import * as actions from '../../_actions/AssetPickerActions';
import assetPickerReducer from '../assetPickerReducer';

const getInitialState = (props) => ({
    query: '',
    submarket: '',
    ...props,
});

describe('assetPickerReducers', () => {
    describe('updateAssetPickerSearchQuery', () => {
        it('should return empty result when given empty asset list with empty query', () => {
            const stateBefore = fromJS();
            const actual = assetPickerReducer(stateBefore, actions.updateAssetPickerSearchQuery(''));
            const expected = fromJS(getInitialState());
            expect(actual.toJS()).toEqual(expected.toJS());
        });

        it('when query is empty returns all assets', () => {
            const stateBefore = fromJS(getInitialState({
                availableAssets: [{ display_name: 'asset1' }, { display_name: 'asset2' }, { display_name: 'asset3' }],
            }));
            const actual = assetPickerReducer(stateBefore, actions.updateAssetPickerSearchQuery('')).toJS();
            const expected = getInitialState({
                availableAssets: [{ display_name: 'asset1' }, { display_name: 'asset2' }, { display_name: 'asset3' }],
            });
            expect(actual.availableAssets).toEqual(expected.availableAssets);
        });

        it('query containing only spaces is treated as empty', () => {
            const stateBefore = fromJS(getInitialState({
                availableAssets: [{ display_name: 'asset1' }, { display_name: 'asset2' }, { display_name: 'asset3' }],
            }));
            const actual = assetPickerReducer(stateBefore, actions.updateAssetPickerSearchQuery('     ')).toJS();
            const expected = fromJS(getInitialState({
                availableAssets: [{ display_name: 'asset1' }, { display_name: 'asset2' }, { display_name: 'asset3' }],
            })).toJS();
            expect(actual.availableAssets).toEqual(expected.availableAssets);
        });
    });
});
<commit_msg>Fix import case sensitivity<commit_after>import expect from 'expect';
import { fromJS } from 'immutable';
import * as actions from '../../_actions/AssetPickerActions';
import assetPickerReducer from '../AssetPickerReducer';

const getInitialState = (props) => ({
    query: '',
    submarket: '',
    ...props,
});

describe('assetPickerReducers', () => {
    describe('updateAssetPickerSearchQuery', () => {
        it('should return empty result when given empty asset list with empty query', () => {
            const stateBefore = fromJS();
            const actual = assetPickerReducer(stateBefore, actions.updateAssetPickerSearchQuery(''));
            const expected = fromJS(getInitialState());
            expect(actual.toJS()).toEqual(expected.toJS());
        });

        it('when query is empty returns all assets', () => {
            const stateBefore = fromJS(getInitialState({
                availableAssets: [{ display_name: 'asset1' }, { display_name: 'asset2' }, { display_name: 'asset3' }],
            }));
            const actual = assetPickerReducer(stateBefore, actions.updateAssetPickerSearchQuery('')).toJS();
            const expected = getInitialState({
                availableAssets: [{ display_name: 'asset1' }, { display_name: 'asset2' }, { display_name: 'asset3' }],
            });
            expect(actual.availableAssets).toEqual(expected.availableAssets);
        });

        it('query containing only spaces is treated as empty', () => {
            const stateBefore = fromJS(getInitialState({
                availableAssets: [{ display_name: 'asset1' }, { display_name: 'asset2' }, { display_name: 'asset3' }],
            }));
            const actual = assetPickerReducer(stateBefore, actions.updateAssetPickerSearchQuery('     ')).toJS();
            const expected = fromJS(getInitialState({
                availableAssets: [{ display_name: 'asset1' }, { display_name: 'asset2' }, { display_name: 'asset3' }],
            })).toJS();
            expect(actual.availableAssets).toEqual(expected.availableAssets);
        });
    });
});
<|endoftext|>


<commit_before>/**
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

import {
  HostComponent,
  HostText,
  HostRoot,
  SuspenseComponent,
} from 'shared/ReactWorkTags';
import invariant from 'shared/invariant';

import {getParentSuspenseInstance} from './ReactDOMHostConfig';

const randomKey = Math.random()
  .toString(36)
  .slice(2);
const internalInstanceKey = '__reactInternalInstance$' + randomKey;
const internalEventHandlersKey = '__reactEventHandlers$' + randomKey;
const internalContainerInstanceKey = '__reactContainere$' + randomKey;

export function precacheFiberNode(hostInst, node) {
  node[internalInstanceKey] = hostInst;
}

export function markContainerAsRoot(hostRoot, node) {
  node[internalContainerInstanceKey] = hostRoot;
}

// Given a DOM node, return the closest HostComponent or HostText fiber ancestor.
// If the target node is part of a hydrated or not yet rendered subtree, then
// this may also return a SuspenseComponent or HostRoot to indicate that.
// Conceptually the HostRoot fiber is a child of the Container node. So if you
// pass the Container node as the targetNode, you wiill not actually get the
// HostRoot back. To get to the HostRoot, you need to pass a child of it.
// The same thing applies to Suspense boundaries.
export function getClosestInstanceFromNode(targetNode) {
  let targetInst = targetNode[internalInstanceKey];
  if (targetInst) {
    // Don't return HostRoot or SuspenseComponent here.
    return targetInst;
  }
  // If the direct event target isn't a React owned DOM node, we need to look
  // to see if one of its parents is a React owned DOM node.
  let parentNode = targetNode.parentNode;
  while (parentNode) {
    // We'll check if this is a container root that could include
    // React nodes in the future. We need to check this first because
    // if we're a child of a dehydrated container, we need to first
    // find that inner container before moving on to finding the parent
    // instance. Note that we don't check this field on  the targetNode
    // itself because the fibers are conceptually between the container
    // node and the first child. It isn't surrounding the container node.
    // If it's not a container, we check if it's an instance.
    targetInst =
      parentNode[internalContainerInstanceKey] ||
      parentNode[internalInstanceKey];
    if (targetInst) {
      // Since this wasn't the direct target of the event, we might have
      // stepped past dehydrated DOM nodes to get here. However they could
      // also have been non-React nodes. We need to answer which one.

      // If we the instance doesn't have any children, then there can't be
      // a nested suspense boundary within it. So we can use this as a fast
      // bailout. Most of the time, when people add non-React children to
      // the tree, it is using a ref to a child-less DOM node.
      // Normally we'd only need to check one of the fibers because if it
      // has ever gone from having children to deleting them or vice versa
      // it would have deleted the dehydrated boundary nested inside already.
      // However, since the HostRoot starts out with an alternate it might
      // have one on the alternate so we need to check in case this was a
      // root.
      const alternate = targetInst.alternate;
      if (
        targetInst.child !== null ||
        (alternate !== null && alternate.child !== null)
      ) {
        // Next we need to figure out if the node that skipped past is
        // nested within a dehydrated boundary and if so, which one.
        let suspenseInstance = getParentSuspenseInstance(targetNode);
        while (suspenseInstance !== null) {
          // We found a suspense instance. That means that we haven't
          // hydrated it yet. Even though we leave the comments in the
          // DOM after hydrating, and there are boundaries in the DOM
          // that could already be hydrated, we wouldn't have found them
          // through this pass since if the target is hydrated it would
          // have had an internalInstanceKey on it.
          // Let's get the fiber associated with the SuspenseComponent
          // as the deepest instance.
          let targetSuspenseInst = suspenseInstance[internalInstanceKey];
          if (targetSuspenseInst) {
            return targetSuspenseInst;
          }
          // If we don't find a Fiber on the comment, it might be because
          // we haven't gotten to hydrate it yet. There might still be a
          // parent boundary that hasn't above this one so we need to find
          // the outer most that is known.
          suspenseInstance = getParentSuspenseInstance(suspenseInstance);
          // If we don't find one, then that should mean that the parent
          // host component also hasn't hydrated yet. We can return it
          // below since it will bail out on the isMounted check later.
        }
      }
      return targetInst;
    }
    targetNode = parentNode;
    parentNode = targetNode.parentNode;
  }
  return null;
}

/**
 * Given a DOM node, return the ReactDOMComponent or ReactDOMTextComponent
 * instance, or null if the node was not rendered by this React.
 */
export function getInstanceFromNode(node) {
  const inst = node[internalInstanceKey] || node[internalContainerInstanceKey];
  if (inst) {
    if (
      inst.tag === HostComponent ||
      inst.tag === HostText ||
      inst.tag === SuspenseComponent ||
      inst.tag === HostRoot
    ) {
      return inst;
    } else {
      return null;
    }
  }
  return null;
}

/**
 * Given a ReactDOMComponent or ReactDOMTextComponent, return the corresponding
 * DOM node.
 */
export function getNodeFromInstance(inst) {
  if (inst.tag === HostComponent || inst.tag === HostText) {
    // In Fiber this, is just the state node right now. We assume it will be
    // a host component or host text.
    return inst.stateNode;
  }

  // Without this first invariant, passing a non-DOM-component triggers the next
  // invariant for a missing parent, which is super confusing.
  invariant(false, 'getNodeFromInstance: Invalid argument.');
}

export function getFiberCurrentPropsFromNode(node) {
  return node[internalEventHandlersKey] || null;
}

export function updateFiberProps(node, props) {
  node[internalEventHandlersKey] = props;
}
<commit_msg>Typo fix in comment (#17111)<commit_after>/**
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

import {
  HostComponent,
  HostText,
  HostRoot,
  SuspenseComponent,
} from 'shared/ReactWorkTags';
import invariant from 'shared/invariant';

import {getParentSuspenseInstance} from './ReactDOMHostConfig';

const randomKey = Math.random()
  .toString(36)
  .slice(2);
const internalInstanceKey = '__reactInternalInstance$' + randomKey;
const internalEventHandlersKey = '__reactEventHandlers$' + randomKey;
const internalContainerInstanceKey = '__reactContainere$' + randomKey;

export function precacheFiberNode(hostInst, node) {
  node[internalInstanceKey] = hostInst;
}

export function markContainerAsRoot(hostRoot, node) {
  node[internalContainerInstanceKey] = hostRoot;
}

// Given a DOM node, return the closest HostComponent or HostText fiber ancestor.
// If the target node is part of a hydrated or not yet rendered subtree, then
// this may also return a SuspenseComponent or HostRoot to indicate that.
// Conceptually the HostRoot fiber is a child of the Container node. So if you
// pass the Container node as the targetNode, you will not actually get the
// HostRoot back. To get to the HostRoot, you need to pass a child of it.
// The same thing applies to Suspense boundaries.
export function getClosestInstanceFromNode(targetNode) {
  let targetInst = targetNode[internalInstanceKey];
  if (targetInst) {
    // Don't return HostRoot or SuspenseComponent here.
    return targetInst;
  }
  // If the direct event target isn't a React owned DOM node, we need to look
  // to see if one of its parents is a React owned DOM node.
  let parentNode = targetNode.parentNode;
  while (parentNode) {
    // We'll check if this is a container root that could include
    // React nodes in the future. We need to check this first because
    // if we're a child of a dehydrated container, we need to first
    // find that inner container before moving on to finding the parent
    // instance. Note that we don't check this field on  the targetNode
    // itself because the fibers are conceptually between the container
    // node and the first child. It isn't surrounding the container node.
    // If it's not a container, we check if it's an instance.
    targetInst =
      parentNode[internalContainerInstanceKey] ||
      parentNode[internalInstanceKey];
    if (targetInst) {
      // Since this wasn't the direct target of the event, we might have
      // stepped past dehydrated DOM nodes to get here. However they could
      // also have been non-React nodes. We need to answer which one.

      // If we the instance doesn't have any children, then there can't be
      // a nested suspense boundary within it. So we can use this as a fast
      // bailout. Most of the time, when people add non-React children to
      // the tree, it is using a ref to a child-less DOM node.
      // Normally we'd only need to check one of the fibers because if it
      // has ever gone from having children to deleting them or vice versa
      // it would have deleted the dehydrated boundary nested inside already.
      // However, since the HostRoot starts out with an alternate it might
      // have one on the alternate so we need to check in case this was a
      // root.
      const alternate = targetInst.alternate;
      if (
        targetInst.child !== null ||
        (alternate !== null && alternate.child !== null)
      ) {
        // Next we need to figure out if the node that skipped past is
        // nested within a dehydrated boundary and if so, which one.
        let suspenseInstance = getParentSuspenseInstance(targetNode);
        while (suspenseInstance !== null) {
          // We found a suspense instance. That means that we haven't
          // hydrated it yet. Even though we leave the comments in the
          // DOM after hydrating, and there are boundaries in the DOM
          // that could already be hydrated, we wouldn't have found them
          // through this pass since if the target is hydrated it would
          // have had an internalInstanceKey on it.
          // Let's get the fiber associated with the SuspenseComponent
          // as the deepest instance.
          let targetSuspenseInst = suspenseInstance[internalInstanceKey];
          if (targetSuspenseInst) {
            return targetSuspenseInst;
          }
          // If we don't find a Fiber on the comment, it might be because
          // we haven't gotten to hydrate it yet. There might still be a
          // parent boundary that hasn't above this one so we need to find
          // the outer most that is known.
          suspenseInstance = getParentSuspenseInstance(suspenseInstance);
          // If we don't find one, then that should mean that the parent
          // host component also hasn't hydrated yet. We can return it
          // below since it will bail out on the isMounted check later.
        }
      }
      return targetInst;
    }
    targetNode = parentNode;
    parentNode = targetNode.parentNode;
  }
  return null;
}

/**
 * Given a DOM node, return the ReactDOMComponent or ReactDOMTextComponent
 * instance, or null if the node was not rendered by this React.
 */
export function getInstanceFromNode(node) {
  const inst = node[internalInstanceKey] || node[internalContainerInstanceKey];
  if (inst) {
    if (
      inst.tag === HostComponent ||
      inst.tag === HostText ||
      inst.tag === SuspenseComponent ||
      inst.tag === HostRoot
    ) {
      return inst;
    } else {
      return null;
    }
  }
  return null;
}

/**
 * Given a ReactDOMComponent or ReactDOMTextComponent, return the corresponding
 * DOM node.
 */
export function getNodeFromInstance(inst) {
  if (inst.tag === HostComponent || inst.tag === HostText) {
    // In Fiber this, is just the state node right now. We assume it will be
    // a host component or host text.
    return inst.stateNode;
  }

  // Without this first invariant, passing a non-DOM-component triggers the next
  // invariant for a missing parent, which is super confusing.
  invariant(false, 'getNodeFromInstance: Invalid argument.');
}

export function getFiberCurrentPropsFromNode(node) {
  return node[internalEventHandlersKey] || null;
}

export function updateFiberProps(node, props) {
  node[internalEventHandlersKey] = props;
}
<|endoftext|>


<commit_before>/* global Cookies */
WebApp.connectHandlers.use('/snippet/download', function(req, res) {
	var match = /^\/([^\/]+)\/(.*)/.exec(req.url);

	if (match[1]) {
		let snippet = RocketChat.models.Messages.findOneById(match[1]);
		var cookie, rawCookies, ref, token, uid;
		cookie = new Cookies();

		if ((typeof req !== 'undefined' && req !== null ? (ref = req.headers) != null ? ref.cookie : void 0 : void 0) != null) {
			rawCookies = req.headers.cookie;
		}

		if (rawCookies != null) {
			uid = cookie.get('rc_uid', rawCookies);
		}

		if (rawCookies != null) {
			token = cookie.get('rc_token', rawCookies);
		}

		if (uid == null) {
			uid = req.query.rc_uid;
			token = req.query.rc_token;
		}

		if (!(uid && token && RocketChat.models.Users.findOneByIdAndLoginToken(uid, token))) {
			res.writeHead(403);
			res.end();
			return false;
		}

		res.setHeader('Content-Disposition', `attachment; filename*=UTF-8''${encodeURIComponent(snippet.snippetName)}`);
		res.setHeader('Content-Type', 'application/octet-stream');

		// Removing the ``` contained in the msg.
		let snippetContent = snippet.msg.substr(3, snippet.msg.length - 6);
		res.setHeader('Content-Length', snippetContent.length);
		res.write(snippetContent);
		res.end();
		return;
	}

	res.writeHead(404);
	res.end();
	return;
});
<commit_msg>Snippet: Fix permissions in the download section.<commit_after>/* global Cookies */
WebApp.connectHandlers.use('/snippet/download', function(req, res) {
	var cookie, rawCookies, ref, token, uid;
	cookie = new Cookies();

	if ((typeof req !== 'undefined' && req !== null ? (ref = req.headers) != null ? ref.cookie : void 0 : void 0) != null) {
		rawCookies = req.headers.cookie;
	}

	if (rawCookies != null) {
		uid = cookie.get('rc_uid', rawCookies);
	}

	if (rawCookies != null) {
		token = cookie.get('rc_token', rawCookies);
	}

	if (uid == null) {
		uid = req.query.rc_uid;
		token = req.query.rc_token;
	}

	let user = RocketChat.models.Users.findOneByIdAndLoginToken(uid, token);

	if (!(uid && token && user)) {
		res.writeHead(403);
		res.end();
		console.log('here');
		return false;
	}
	var match = /^\/([^\/]+)\/(.*)/.exec(req.url);

	if (match[1]) {
		let snippet = RocketChat.models.Messages.findOne(
			{
				'_id': match[1],
				'snippeted': true
			}
		);
		let room = RocketChat.models.Rooms.findOne({ '_id': snippet.rid, 'usernames': { '$in': [user.username] }});
		if (room === undefined) {
			res.writeHead(403);
			res.end();
			console.log('not here');
			return false;
		}

		res.setHeader('Content-Disposition', `attachment; filename*=UTF-8''${encodeURIComponent(snippet.snippetName)}`);
		res.setHeader('Content-Type', 'application/octet-stream');

		// Removing the ``` contained in the msg.
		let snippetContent = snippet.msg.substr(3, snippet.msg.length - 6);
		res.setHeader('Content-Length', snippetContent.length);
		res.write(snippetContent);
		res.end();
		return;
	}

	res.writeHead(404);
	res.end();
	return;
});
<|endoftext|>


<commit_before>// handle form
$('#join-meeting-button').click(function (e) {
    console.log("join clicked");
    if(!validateJoin()) {
        return;
    }
    $("#join-form").submit();
//    e.preventDefault();
//    var code = $('#join-input-code').val();
//    console.log(code);
//    var firstName = $("#join-input-firstname").val();
//    var lastName = $("#join-input-lastname").val();
//    var joinInputData = {
//        "code": code,
//        "firstName": firstName,
//        "lastName": lastName
//    }
//    console.log(joinInputData);
    // $.post('/home')
});

$('#polling-submit-button').click(function (e) {
    console.log("join clicked");
    if(!validateCreate()) {
        return;
    }
    $("#polling-create-form").submit();
//    e.preventDefault();
//    var code = $('#join-input-code').val();
//    console.log(code);
//    var firstName = $("#join-input-firstname").val();
//    var lastName = $("#join-input-lastname").val();
//    var joinInputData = {
//        "code": code,
//        "firstName": firstName,
//        "lastName": lastName
//    }
//    console.log(joinInputData);
    // $.post('/home')
});

$('#leave-meeting').click(function (e) {
    console.log("leave clicked");
    $.ajax({
    url: '/',
    type: 'DELETE',
    success: function(result) {
        console.log(result);
        console.log("leave the meeting successfully");
        window.location.href = '/';
    }
    });
});

(function ($) {
    "use strict"; // Start of use strict
	/*
    // jQuery for page scrolling feature - requires jQuery Easing plugin
    $('a.page-scroll').bind('click', function (event) {
        var $anchor = $(this);
        $('html, body').stop().animate({
            scrollTop: ($($anchor.attr('href')).offset().top - 50)
        }, 1250, 'easeInOutExpo');
        event.preventDefault();
    });
    // Highlight the top nav as scrolling occurs
    $('body').scrollspy({
        target: '.navbar-fixed-top',
        offset: 51
    })
    // Closes the Responsive Menu on Menu Item Click
    $('.navbar-collapse ul li a').click(function () {
        $('.navbar-toggle:visible').click();
    });
	*/
    // Fit Text Plugin for Main Header
    $("h1").fitText(
        0.8, {
            minFontSize: '30px',
            maxFontSize: '65px'
        }
    );

    $(".create-text-sm").fitText(
        1.5, {
            minFontSize: '12px',
            maxFontSize: '30px'
        }
    );

    $(".btn-xl").fitText(
        1.5, {
            minFontSize: '11px',
            maxFontSize: '18px'
        })

    // Offset for Main Navigation
    $('#mainNav').affix({
        offset: {
            top: 100
        }
    })

    // Initialize WOW.js Scrolling Animations
    new WOW().init();

})(jQuery); // End of use strict

function pollingAdd() {
	var count = document.getElementById("polling-create-form").elements.length;
	if (count < 7) {
		var newInput = document.createElement('div');
		newInput.innerHTML ='
'
                            +'Option '+(count-1)
                          +'
'
                          +'
'
                            +'
'
                              +'<input id="polling-create-option' + (count-2) + '" name="pollingOption'+
                              (count-2) + '" type="text">'
                            +'
'
                          +'
';
		newInput.className += 'input-group text-section'
		document.getElementById("polling-create-form").appendChild(newInput);
		if (count == 6)
			$("#polling-create-add").hide();
		if (count == 4)
			$("#polling-create-minus").show();
	}
}

function pollingRemove() {
	var count = document.getElementById("polling-create-form").elements.length;
	if (count > 4) {
		$('#polling-create-form .text-section:last-child').remove();
		if (count == 5)
			$("#polling-create-minus").hide();
		if (count == 7)
			$("#polling-create-add").show();
	}
}

function validateJoin() {
    var error = "";
    var errorExist = false;
    var errorColor = '#ffff4c';
    var legalName = /^[a-zA-Z]+$/; // allow letters, numbers, and underscores
    var legalCode = /^\d+$/
    var firstname = document.getElementById("join-input-firstname");
    var lastname = document.getElementById("join-input-lastname");
    var code = document.getElementById("join-input-code");
    var errorMessage = document.getElementById("error-message");
    var errorInput = document.createElement('ul');
    //initialize color
    code.style.background = 'White';
    firstname.style.background = 'White';
    lastname.style.background = 'White';
    $('#error-message ul').remove();

    if(!(legalCode.test(code.value)) || code.value.length!=6) {
        code.style.background = errorColor;
        error += "
Please enter a 6-digit code.
";
        errorExist = true;
    }
    if (firstname.value == "") {
        firstname.style.background = errorColor;
        error += "
Please enter the firstname.
";
        errorExist = true;
    }
    else if (!legalName.test(firstname.value)) {
        firstname.style.background = errorColor;
        error += "
Please enter your correct firstname
";
        errorExist = true;
    }

    if (lastname.value == "") {
        lastname.style.background = errorColor;
        error += "
Please enter the lastname.
";
        errorExist = true;
    }
    else if (!legalName.test(lastname.value)) {
        lastname.style.background = errorColor;
        error += "
Please enter your correct lastname
";
        errorExist = true;
    }

    if(errorExist) {
        console.log(error);
        errorInput.innerHTML = error;
        errorInput.style.color = 'Red';

        errorMessage.appendChild(errorInput);
        return false;
    }
    else {
        return true;
    }
}

function validateCreate() {
    var error = "";
    var errorExist = false;
    var errorColor = '#ffff4c';

    var errorInput = document.createElement('ul');
    var errorMessage= document.getElementById("error-message");
    var title = document.getElementById("polling-create-title");
    var count = document.getElementById("polling-create-form").elements.length - 2;
    var options = [];
    for(var i=0; i<count; i++) {
        options[i] = (document.getElementById("polling-create-option"+(i)));
    }
    if(errorMessage == undefined) {
        console.log("errorMessage undefined");
    }
    //initialize background color
    for(var i=0; i<count; i++) {
        options[i].style.background = 'White';
    }
    title.style.background = 'White';
    //clear error message
    $('#error-message ul').remove();

    if(title.value=="") {
        title.style.background = errorColor;
        error += "
Please enter your question in title.
";
        errorExist = true;
    }

    for(var i=0; i<count; i++) {
        if(options[i].value=="") {
            options[i].style.background = errorColor;
            error += "
Please fill in option" + (i+1) + ".
";
            errorExist = true;
        }
    }

    if(errorExist) {
        console.log(error);
        errorInput.innerHTML = error;
        errorInput.style.color = 'Red';
        errorMessage.appendChild(errorInput);
        return false;
    }
    else {
        return true;
    }
}

<commit_msg>create front-end<commit_after>// handle form
$('#join-meeting-button').click(function (e) {
    console.log("join clicked");
    if(!validateJoin()) {
        return;
    }
    $("#join-form").submit();
//    e.preventDefault();
//    var code = $('#join-input-code').val();
//    console.log(code);
//    var firstName = $("#join-input-firstname").val();
//    var lastName = $("#join-input-lastname").val();
//    var joinInputData = {
//        "code": code,
//        "firstName": firstName,
//        "lastName": lastName
//    }
//    console.log(joinInputData);
    // $.post('/home')
});

$('#create-meeting-button').click(function (e) {
    console.log("create clicked");
    $.get('/create');
})

$('#polling-submit-button').click(function (e) {
    console.log("join clicked");
    if(!validateCreate()) {
        return;
    }
    $("#polling-create-form").submit();
//    e.preventDefault();
//    var code = $('#join-input-code').val();
//    console.log(code);
//    var firstName = $("#join-input-firstname").val();
//    var lastName = $("#join-input-lastname").val();
//    var joinInputData = {
//        "code": code,
//        "firstName": firstName,
//        "lastName": lastName
//    }
//    console.log(joinInputData);
    // $.post('/home')
});

$('#leave-meeting').click(function (e) {
    console.log("leave clicked");
    $.ajax({
    url: '/',
    type: 'DELETE',
    success: function(result) {
        console.log(result);
        console.log("leave the meeting successfully");
        window.location.href = '/';
    }
    });
});

(function ($) {
    "use strict"; // Start of use strict
	/*
    // jQuery for page scrolling feature - requires jQuery Easing plugin
    $('a.page-scroll').bind('click', function (event) {
        var $anchor = $(this);
        $('html, body').stop().animate({
            scrollTop: ($($anchor.attr('href')).offset().top - 50)
        }, 1250, 'easeInOutExpo');
        event.preventDefault();
    });
    // Highlight the top nav as scrolling occurs
    $('body').scrollspy({
        target: '.navbar-fixed-top',
        offset: 51
    })
    // Closes the Responsive Menu on Menu Item Click
    $('.navbar-collapse ul li a').click(function () {
        $('.navbar-toggle:visible').click();
    });
	*/
    // Fit Text Plugin for Main Header
    $("h1").fitText(
        0.8, {
            minFontSize: '30px',
            maxFontSize: '65px'
        }
    );

    $(".create-text-sm").fitText(
        1.5, {
            minFontSize: '12px',
            maxFontSize: '30px'
        }
    );

    $(".btn-xl").fitText(
        1.5, {
            minFontSize: '11px',
            maxFontSize: '18px'
        })

    // Offset for Main Navigation
    $('#mainNav').affix({
        offset: {
            top: 100
        }
    })

    // Initialize WOW.js Scrolling Animations
    new WOW().init();

})(jQuery); // End of use strict

function pollingAdd() {
	var count = document.getElementById("polling-create-form").elements.length;
	if (count < 7) {
		var newInput = document.createElement('div');
		newInput.innerHTML ='
'
                            +'Option '+(count-1)
                          +'
'
                          +'
'
                            +'
'
                              +'<input id="polling-create-option' + (count-2) + '" name="pollingOption'+
                              (count-2) + '" type="text">'
                            +'
'
                          +'
';
		newInput.className += 'input-group text-section'
		document.getElementById("polling-create-form").appendChild(newInput);
		if (count == 6)
			$("#polling-create-add").hide();
		if (count == 4)
			$("#polling-create-minus").show();
	}
}

function pollingRemove() {
	var count = document.getElementById("polling-create-form").elements.length;
	if (count > 4) {
		$('#polling-create-form .text-section:last-child').remove();
		if (count == 5)
			$("#polling-create-minus").hide();
		if (count == 7)
			$("#polling-create-add").show();
	}
}

function validateJoin() {
    var error = "";
    var errorExist = false;
    var errorColor = '#ffff4c';
    var legalName = /^[a-zA-Z]+$/; // allow letters, numbers, and underscores
    var legalCode = /^\d+$/
    var firstname = document.getElementById("join-input-firstname");
    var lastname = document.getElementById("join-input-lastname");
    var code = document.getElementById("join-input-code");
    var errorMessage = document.getElementById("error-message");
    var errorInput = document.createElement('ul');
    //initialize color
    code.style.background = 'White';
    firstname.style.background = 'White';
    lastname.style.background = 'White';
    $('#error-message ul').remove();

    if(!(legalCode.test(code.value)) || code.value.length!=6) {
        code.style.background = errorColor;
        error += "
Please enter a 6-digit code.
";
        errorExist = true;
    }
    if (firstname.value == "") {
        firstname.style.background = errorColor;
        error += "
Please enter the firstname.
";
        errorExist = true;
    }
    else if (!legalName.test(firstname.value)) {
        firstname.style.background = errorColor;
        error += "
Please enter your correct firstname
";
        errorExist = true;
    }

    if (lastname.value == "") {
        lastname.style.background = errorColor;
        error += "
Please enter the lastname.
";
        errorExist = true;
    }
    else if (!legalName.test(lastname.value)) {
        lastname.style.background = errorColor;
        error += "
Please enter your correct lastname
";
        errorExist = true;
    }

    if(errorExist) {
        console.log(error);
        errorInput.innerHTML = error;
        errorInput.style.color = 'Red';

        errorMessage.appendChild(errorInput);
        return false;
    }
    else {
        return true;
    }
}

function validateCreate() {
    var error = "";
    var errorExist = false;
    var errorColor = '#ffff4c';

    var errorInput = document.createElement('ul');
    var errorMessage= document.getElementById("error-message");
    var title = document.getElementById("polling-create-title");
    var count = document.getElementById("polling-create-form").elements.length - 2;
    var options = [];
    for(var i=0; i<count; i++) {
        options[i] = (document.getElementById("polling-create-option"+(i)));
    }
    if(errorMessage == undefined) {
        console.log("errorMessage undefined");
    }
    //initialize background color
    for(var i=0; i<count; i++) {
        options[i].style.background = 'White';
    }
    title.style.background = 'White';
    //clear error message
    $('#error-message ul').remove();

    if(title.value=="") {
        title.style.background = errorColor;
        error += "
Please enter your question in title.
";
        errorExist = true;
    }

    for(var i=0; i<count; i++) {
        if(options[i].value=="") {
            options[i].style.background = errorColor;
            error += "
Please fill in option" + (i+1) + ".
";
            errorExist = true;
        }
    }

    if(errorExist) {
        console.log(error);
        errorInput.innerHTML = error;
        errorInput.style.color = 'Red';
        errorMessage.appendChild(errorInput);
        return false;
    }
    else {
        return true;
    }
}

<|endoftext|>


<commit_before>$(document).ready(
        function() {

            var timer;
            var doAutoRefresh = false;

            __init();

            function __init() {
                $('#servers-add .btn-info').click(function() {
                    addServer($('#host').val(), $('#port').val());
                    $("#host,#port").val('');
                    $('#servers-add').modal('hide');
                    window.location.href = window.location.href;
                    return false;
                });
                $('#addJob').on('click', function() {
                    $('#modalAddJob').modal('toggle');
                    return false;
                });
                $('#filter input[type=checkbox]').click(function() {
                    $('table')
                            .find('[name=' + $(this).attr('name') + ']')
                            .toggle($(this).is(':checked'));
                    var names = [];
                    $('#filter input:checked').each(function() {
                        names.push($(this).attr('name'));
                    });
                    $.cookie($('#filter').data('cookie'), names, {expires: 365});
                    $('.row-full').attr('colspan', names.length);
                });

                $('#tubeSave').on('click', function() {
                    var result = addNewJob();

                    if (result == 'empty') {
                        $('#tubeSaveAlert').fadeIn('fast');
                    } else {
                        $('#modalAddJob').modal('toggle');
                    }

                    return false;
                });

                $('#autoRefresh').on('click', function() {
                    if (!$('#autoRefresh').hasClass('btn-success')) {
                        reloader();
                        $('#autoRefresh').toggleClass('btn-success');
                        $('#autoRefresh i').toggleClass('icon-white');
                    } else {
                        clearTimeout(timer);
                        doAutoRefresh = false;
                        $('#autoRefresh').toggleClass('btn-success');
                        $('#autoRefresh i').toggleClass('icon-white');
                    }

                    return false;
                });

                if (contentType == 'json') {
                    var cn = $('pre code').html();
                    var jn = formatJson(cn);
                    $('pre code').html(jn);
                }

                $('#clearTubesSelect').on('click', function() {
                    $('#clear-tubes input[type=checkbox]:regex(name,' + $("#tubeSelector").val() + ')').prop('checked', true);
                    $.cookie("tubeSelector", $("#tubeSelector").val(), {
                        expires: 365
                    });
                    $('#clearTubes').text('Clear ' + $('#clear-tubes input[type=checkbox]:checked').length + ' selected tubes');
                });

                $('#clearTubes').on('click', function() {
                    clearTubes();
                });

                $('#settings input').on('change', function() {
                    var val;
                    if ($(this).attr('type') == 'checkbox') {
                        if ($(this).is(':checked')) {
                            val = $(this).val();
                        } else {
                            val = null;
                        }
                    } else {
                        val = $(this).val();
                    }
                    if (jQuery.inArray(this.id, ['isDisabledUnserialization', 'isDisabledJsonDecode', 'isDisabledJobDataHighlight']) >= 0)
                        val = $(this).is(':checked') ? null : 1;
                    $.cookie(this.id, val, {expires: 365});
                });

                $('.addSample').on('click', function() {
                    var selectedText = "";
                    if (typeof window.getSelection != "undefined") {
                        var sel = window.getSelection();
                        if (sel.rangeCount) {
                            var container = document.createElement("div");
                            for (var i = 0, len = sel.rangeCount; i < len; ++i) {
                                container.appendChild(sel.getRangeAt(i).cloneContents());
                            }
                            selectedText = container.textContent || container.innerText;
                        }
                    } else if (typeof document.selection != "undefined") {
                        if (document.selection.type == "Text") {
                            selectedText = document.selection.createRange().htmlText;
                        }
                    }
                    $('#addsamplename').val(selectedText);
                    $('#addsamplestate').val($(this).data('state'));
                    $('#modalAddSample').modal('toggle');
                    return false;
                });

                $('#sampleSave').on('click', function() {
                    addSampleJob();
                    return false;
                });
            }

            function addServer(host, port) {
                if (host) {
                    myCoockie = $.cookie("beansServers");
                    if (myCoockie == null) {
                        server = host + ":" + port;
                    } else {
                        server = myCoockie + ";" + host + ":" + port;
                    }
                    $.cookie("beansServers", server, {
                        expires: 365
                    });
                } else {
                    alert("Some fields empty..");
                }
            }

            function addNewJob() {

                if (!$('#tubeName').val() || !$('#tubeData').val()) {
                    return 'empty';
                }

                var params = {
                    'tubeName': $('#tubeName').val(),
                    'tubeData': $('#tubeData').val(),
                    'tubePriority': $('#tubePriority').val(),
                    'tubeDelay': $('#tubeDelay').val(),
                    'tubeTtr': $('#tubeTtr').val()
                }

                $.ajax({
                    'url': url + '&action=addjob',
                    'data': params,
                    'success': function(data) {
                        var result = data.result;
                        cleanFormNewJob();
                        location.reload();
                    },
                    'type': 'POST',
                    'dataType': 'json',
                    'error': function() {
                        console.log('error ajax...');
                    }
                });
            }

            function cleanFormNewJob() {
                // $('#tubeName').val('');
                $('#tubeData').val('');
                $('#tubePriority').val('');
                $('#tubeDelay').val('');
                $('#tubeTtr').val('');
            }

            function formatJson(val) {

                var retval = '';
                var str = val;
                var pos = 0;
                var strLen = str.length;
                var indentStr = '    ';
                var newLine = "\n";
                var char = '';

                for (var i = 0; i < strLen; i++) {
                    char = str.substring(i, i + 1);
                    nextChar = str.substring(i + 1, i + 2);
                    if ((char == '}' || char == ']') && nextChar != newLine) {

                        retval = retval + newLine;
                        pos = pos - 1;
                        for (var j = 0; j < pos; j++) {
                            retval = retval + indentStr;
                        }
                    }
                    retval = retval + char;

                    if ((char == '{' || char == '[' || char == ',') && nextChar != newLine) {
                        retval = retval + newLine;
                        if (char == '{' || char == '[') {
                            pos = pos + 1;
                        }

                        for (var k = 0; k < pos; k++) {
                            retval = retval + indentStr;
                        }
                    }
                }

                return retval;

            }

            function reloader() {
                var params = {
                    'action': 'reloader',
                    'tplMain': 'ajax',
                    'tplBlock': 'allTubes',
                    'secondary': new Date().getTime()
                }
                var res;

                doAutoRefresh = true;
                $.ajax({
                    'url': url,
                    'data': params,
                    'success': function(data) {
                        if (doAutoRefresh) {
                            var ms = 500;
                            if ($.cookie('autoRefreshTimeoutMs')) {
                                ms = parseInt($.cookie('autoRefreshTimeoutMs'));
                            }
                            if (ms < 200) {
                                ms = 200;
                            }
                            // wrapping all of this to prevent last update
                            // after you turn it off
                            var html = $('#idAllTubes').html();
                            $('#idAllTubes').html(data);
                            $('#idAllTubesCopy').html(html);
                            updateTable();
                            timer = setTimeout(reloader, ms);
                        }
                    },
                    'type': 'GET',
                    'dataType': 'html',
                    'error': function() {
                        console.log('error ajax...');
                    }
                });
            }

            function updateTable() {
                var td1 = $('#idAllTubes table').find('td'), td2 = $('#idAllTubesCopy table').find('td');
                for (i = 0, il = td1.length; i < il; i++) {
                    if (typeof td2[i] === 'undefined' || typeof td1[i] === 'undefined') {                    // tube is missing
                        continue;
                    }
                    var l = td1[i].innerText || td1[i].innerHTML || td1[i].textContent;
                    var r = td2[i].innerText || td2[i].innerHTML || td2[i].textContent;
                    if (l != r) {
                        var $td1 = $(td1[i]), color = $td1.css('background-color');
                        $td1.css({
                            'background-color': '#afa'
                        }).animate({
                            'background-color': color
                        }, 500);
                    }
                }
            }

            function clearTubes() {
                if ($('#clear-tubes input[type=checkbox]:checked').length === 0) {
                    return;
                }

                $.ajax({
                    'url': url + '&action=clearTubes',
                    'data': $('#clear-tubes input[type=checkbox]:checked').serialize(),
                    'success': function(data) {
                        var result = data.result;
                        location.reload();
                    },
                    'type': 'POST',
                    'error': function() {
                        alert('error from ajax (clear might take a while, be patient)...');
                    }
                });
            }

            function addSampleJob() {
                if (!$('#addsamplename').val() || $('input[name^=tube]:checked').length < 1) {
                    $('#sampleSaveAlert span').text('Required fields are marked *');
                    $('#sampleSaveAlert').fadeIn('fast');
                    return;
                }

                $.ajax({
                    'url': url + '&action=addSample',
                    'data': $('#modalAddSample input').serialize(),
                    'success': function(data) {
                        console.log(data);
                        if (data.result) {
                            $('#modalAddSample').modal('toggle');
                        } else {
                            $('#sampleSaveAlert span').text(data.error);
                            $('#sampleSaveAlert').fadeIn('fast');
                        }
                    },
                    'type': 'POST',
                    'dataType': 'json',
                    'error': function() {
                        alert('error ajax...');
                    }
                });
            }
        }
);
<commit_msg>customer.js - formatJSON fix<commit_after>$(document).ready(
        function() {

            var timer;
            var doAutoRefresh = false;

            __init();

            function __init() {
                $('#servers-add .btn-info').click(function() {
                    addServer($('#host').val(), $('#port').val());
                    $("#host,#port").val('');
                    $('#servers-add').modal('hide');
                    window.location.href = window.location.href;
                    return false;
                });
                $('#addJob').on('click', function() {
                    $('#modalAddJob').modal('toggle');
                    return false;
                });
                $('#filter input[type=checkbox]').click(function() {
                    $('table')
                            .find('[name=' + $(this).attr('name') + ']')
                            .toggle($(this).is(':checked'));
                    var names = [];
                    $('#filter input:checked').each(function() {
                        names.push($(this).attr('name'));
                    });
                    $.cookie($('#filter').data('cookie'), names, {expires: 365});
                    $('.row-full').attr('colspan', names.length);
                });

                $('#tubeSave').on('click', function() {
                    var result = addNewJob();

                    if (result == 'empty') {
                        $('#tubeSaveAlert').fadeIn('fast');
                    } else {
                        $('#modalAddJob').modal('toggle');
                    }

                    return false;
                });

                $('#autoRefresh').on('click', function() {
                    if (!$('#autoRefresh').hasClass('btn-success')) {
                        reloader();
                        $('#autoRefresh').toggleClass('btn-success');
                        $('#autoRefresh i').toggleClass('icon-white');
                    } else {
                        clearTimeout(timer);
                        doAutoRefresh = false;
                        $('#autoRefresh').toggleClass('btn-success');
                        $('#autoRefresh i').toggleClass('icon-white');
                    }

                    return false;
                });

                if (contentType == 'json') {
                    $('pre code').each(function(index, value) {
                        var cn = $(this).html();
                        var jn = formatJson(cn);
                        $(this).html(jn);
                    });
                }

                $('#clearTubesSelect').on('click', function() {
                    $('#clear-tubes input[type=checkbox]:regex(name,' + $("#tubeSelector").val() + ')').prop('checked', true);
                    $.cookie("tubeSelector", $("#tubeSelector").val(), {
                        expires: 365
                    });
                    $('#clearTubes').text('Clear ' + $('#clear-tubes input[type=checkbox]:checked').length + ' selected tubes');
                });

                $('#clearTubes').on('click', function() {
                    clearTubes();
                });

                $('#settings input').on('change', function() {
                    var val;
                    if ($(this).attr('type') == 'checkbox') {
                        if ($(this).is(':checked')) {
                            val = $(this).val();
                        } else {
                            val = null;
                        }
                    } else {
                        val = $(this).val();
                    }
                    if (jQuery.inArray(this.id, ['isDisabledUnserialization', 'isDisabledJsonDecode', 'isDisabledJobDataHighlight']) >= 0)
                        val = $(this).is(':checked') ? null : 1;
                    $.cookie(this.id, val, {expires: 365});
                });

                $('.addSample').on('click', function() {
                    var selectedText = "";
                    if (typeof window.getSelection != "undefined") {
                        var sel = window.getSelection();
                        if (sel.rangeCount) {
                            var container = document.createElement("div");
                            for (var i = 0, len = sel.rangeCount; i < len; ++i) {
                                container.appendChild(sel.getRangeAt(i).cloneContents());
                            }
                            selectedText = container.textContent || container.innerText;
                        }
                    } else if (typeof document.selection != "undefined") {
                        if (document.selection.type == "Text") {
                            selectedText = document.selection.createRange().htmlText;
                        }
                    }
                    $('#addsamplename').val(selectedText);
                    $('#addsamplestate').val($(this).data('state'));
                    $('#modalAddSample').modal('toggle');
                    return false;
                });

                $('#sampleSave').on('click', function() {
                    addSampleJob();
                    return false;
                });
            }

            function addServer(host, port) {
                if (host) {
                    myCoockie = $.cookie("beansServers");
                    if (myCoockie == null) {
                        server = host + ":" + port;
                    } else {
                        server = myCoockie + ";" + host + ":" + port;
                    }
                    $.cookie("beansServers", server, {
                        expires: 365
                    });
                } else {
                    alert("Some fields empty..");
                }
            }

            function addNewJob() {

                if (!$('#tubeName').val() || !$('#tubeData').val()) {
                    return 'empty';
                }

                var params = {
                    'tubeName': $('#tubeName').val(),
                    'tubeData': $('#tubeData').val(),
                    'tubePriority': $('#tubePriority').val(),
                    'tubeDelay': $('#tubeDelay').val(),
                    'tubeTtr': $('#tubeTtr').val()
                }

                $.ajax({
                    'url': url + '&action=addjob',
                    'data': params,
                    'success': function(data) {
                        var result = data.result;
                        cleanFormNewJob();
                        location.reload();
                    },
                    'type': 'POST',
                    'dataType': 'json',
                    'error': function() {
                        console.log('error ajax...');
                    }
                });
            }

            function cleanFormNewJob() {
                // $('#tubeName').val('');
                $('#tubeData').val('');
                $('#tubePriority').val('');
                $('#tubeDelay').val('');
                $('#tubeTtr').val('');
            }

            function formatJson(val) {

                var retval = '';
                var str = val;
                var pos = 0;
                var strLen = str.length;
                var indentStr = '    ';
                var newLine = "\n";
                var char = '';

                for (var i = 0; i < strLen; i++) {
                    char = str.substring(i, i + 1);
                    nextChar = str.substring(i + 1, i + 2);
                    if ((char == '}' || char == ']') && nextChar != newLine) {

                        retval = retval + newLine;
                        pos = pos - 1;
                        for (var j = 0; j < pos; j++) {
                            retval = retval + indentStr;
                        }
                    }
                    retval = retval + char;

                    if ((char == '{' || char == '[' || char == ',') && nextChar != newLine) {
                        retval = retval + newLine;
                        if (char == '{' || char == '[') {
                            pos = pos + 1;
                        }

                        for (var k = 0; k < pos; k++) {
                            retval = retval + indentStr;
                        }
                    }
                }

                return retval;

            }

            function reloader() {
                var params = {
                    'action': 'reloader',
                    'tplMain': 'ajax',
                    'tplBlock': 'allTubes',
                    'secondary': new Date().getTime()
                }
                var res;

                doAutoRefresh = true;
                $.ajax({
                    'url': url,
                    'data': params,
                    'success': function(data) {
                        if (doAutoRefresh) {
                            var ms = 500;
                            if ($.cookie('autoRefreshTimeoutMs')) {
                                ms = parseInt($.cookie('autoRefreshTimeoutMs'));
                            }
                            if (ms < 200) {
                                ms = 200;
                            }
                            // wrapping all of this to prevent last update
                            // after you turn it off
                            var html = $('#idAllTubes').html();
                            $('#idAllTubes').html(data);
                            $('#idAllTubesCopy').html(html);
                            updateTable();
                            timer = setTimeout(reloader, ms);
                        }
                    },
                    'type': 'GET',
                    'dataType': 'html',
                    'error': function() {
                        console.log('error ajax...');
                    }
                });
            }

            function updateTable() {
                var td1 = $('#idAllTubes table').find('td'), td2 = $('#idAllTubesCopy table').find('td');
                for (i = 0, il = td1.length; i < il; i++) {
                    if (typeof td2[i] === 'undefined' || typeof td1[i] === 'undefined') {                    // tube is missing
                        continue;
                    }
                    var l = td1[i].innerText || td1[i].innerHTML || td1[i].textContent;
                    var r = td2[i].innerText || td2[i].innerHTML || td2[i].textContent;
                    if (l != r) {
                        var $td1 = $(td1[i]), color = $td1.css('background-color');
                        $td1.css({
                            'background-color': '#afa'
                        }).animate({
                            'background-color': color
                        }, 500);
                    }
                }
            }

            function clearTubes() {
                if ($('#clear-tubes input[type=checkbox]:checked').length === 0) {
                    return;
                }

                $.ajax({
                    'url': url + '&action=clearTubes',
                    'data': $('#clear-tubes input[type=checkbox]:checked').serialize(),
                    'success': function(data) {
                        var result = data.result;
                        location.reload();
                    },
                    'type': 'POST',
                    'error': function() {
                        alert('error from ajax (clear might take a while, be patient)...');
                    }
                });
            }

            function addSampleJob() {
                if (!$('#addsamplename').val() || $('input[name^=tube]:checked').length < 1) {
                    $('#sampleSaveAlert span').text('Required fields are marked *');
                    $('#sampleSaveAlert').fadeIn('fast');
                    return;
                }

                $.ajax({
                    'url': url + '&action=addSample',
                    'data': $('#modalAddSample input').serialize(),
                    'success': function(data) {
                        console.log(data);
                        if (data.result) {
                            $('#modalAddSample').modal('toggle');
                        } else {
                            $('#sampleSaveAlert span').text(data.error);
                            $('#sampleSaveAlert').fadeIn('fast');
                        }
                    },
                    'type': 'POST',
                    'dataType': 'json',
                    'error': function() {
                        alert('error ajax...');
                    }
                });
            }
        }
);
<|endoftext|>


<commit_before>/*
This file is part of Kronekeeper, a web based application for
recording and managing wiring frame records.

Copyright (C) 2016 NP Broadcast Limited

Kronekeeper is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

Kronekeeper is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License
along with Kronekeeper.  If not, see <http://www.gnu.org/licenses/>.

*/

define([
        'jquery',
], function (
) {
        'use strict';

	/* We want to display a rich drop-down of jumper templates, including
	 * div elements to illustrate the wire colours. A standard html <select>
	 * doesn't allow anything but text in <option> elements, so cannot be used
	 * for this. Instead we construct our own select-type dropdown based on
	 * an unordered list.
	 *
	 * Inspired by:
	 *   http://jsfiddle.net/6zcRk/ and
	 *   http://stackoverflow.com/questions/9548618/custom-drop-down-panel-with-jquery
	 *   http://www.jankoatwarpspeed.com/reinventing-a-drop-down-with-css-and-jquery/
	 */

	/* Initialises a custom drop-down select widget. Pass a jquery reference to the containing div */
	function initialise(container, options) {

		/* Options:
		 *   initial_value: Optional - selects this item from the list on initialisation
		 *   on_change: Optional callback, called when selection changes
		 */
		if(!options) {
			options = {};
		}

		var list = container.find('ul');
		var selection = container.find("div.selection");
		var selection_label = selection.find("span.option");

		selection.click(function(e) {

			if(list.is(":hidden")) {

				e.stopPropagation();

				/* If any other custom-select dropdowns are showing, hide them
				 * by triggering a click event, so the event handlers are cleaned-up
				 */
				$("div.custom-select").has("li:visible").trigger("click");

				list.show();

				/* Add event handlers */
				list.find('li').on("click", handle_select);
				$(document).on("click", handle_document_click);
				$(document).on("keydown", handle_keydown);
			}

			function hide_dropdown() {

				list.hide();

				/* Clean-up event handlers */
				list.find('li').off("click", handle_select);
				$(document).off("click", handle_document_click);
				$(document).off("keydown", handle_keydown);
			}

			function handle_keydown(e) {

				if(e.which == 27) {
					hide_dropdown();
				}
			}

			function handle_select(e) {

				e.stopPropagation();
				selection_label.html(e.currentTarget.innerHTML);
				var clicked_value = e.currentTarget.dataset.value;

				if(selection_label.data("value") != clicked_value) {
					/* Selection has changed */
					selection_label.data("value", clicked_value);
					console.log("selection changed:", clicked_value);
					if(options.on_change) {
						options.on_change(clicked_value);
					}
				}

				hide_dropdown();
			}

			function handle_document_click(e) {

				hide_dropdown();
			}

		});

		if(options.initial_value) {
			selection_label.html(
				list.find("li[data-value='" + options.initial_value + "']").first().html()
			);
		}
	}

	console.log("loaded import/kris/dropdown.js");

	/* Our Exports */
	return {
		initialise: initialise
	};
});
<commit_msg>Extend dropdown.js to allow initial value specified as data attribute<commit_after>/*
This file is part of Kronekeeper, a web based application for
recording and managing wiring frame records.

Copyright (C) 2016-2020 NP Broadcast Limited

Kronekeeper is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

Kronekeeper is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License
along with Kronekeeper.  If not, see <http://www.gnu.org/licenses/>.

*/

define([
        'jquery',
], function (
) {
        'use strict';

	/* We want to display a rich drop-down of jumper templates, including
	 * div elements to illustrate the wire colours. A standard html <select>
	 * doesn't allow anything but text in <option> elements, so cannot be used
	 * for this. Instead we construct our own select-type dropdown based on
	 * an unordered list.
	 *
	 * Inspired by:
	 *   http://jsfiddle.net/6zcRk/ and
	 *   http://stackoverflow.com/questions/9548618/custom-drop-down-panel-with-jquery
	 *   http://www.jankoatwarpspeed.com/reinventing-a-drop-down-with-css-and-jquery/
	 */

	/* Initialises a custom drop-down select widget. Pass a jquery reference to the containing div */
	function initialise(container, options) {

		/* Options:
		 *   initial_value: Optional - selects this item from the list on initialisation
		 *   on_change: Optional callback, called when selection changes
		 */
		if(!options) {
			options = {};
		}

		var list = container.find('ul');
		var selection = container.find("div.selection");
		var selection_label = selection.find("span.option");

		selection.click(function(e) {

			if(list.is(":hidden")) {

				e.stopPropagation();

				/* If any other custom-select dropdowns are showing, hide them
				 * by triggering a click event, so the event handlers are cleaned-up
				 */
				$("div.custom-select").has("li:visible").trigger("click");

				list.show();

				/* Add event handlers */
				list.find('li').on("click", handle_select);
				$(document).on("click", handle_document_click);
				$(document).on("keydown", handle_keydown);
			}

			function hide_dropdown() {

				list.hide();

				/* Clean-up event handlers */
				list.find('li').off("click", handle_select);
				$(document).off("click", handle_document_click);
				$(document).off("keydown", handle_keydown);
			}

			function handle_keydown(e) {

				if(e.which == 27) {
					hide_dropdown();
				}
			}

			function handle_select(e) {

				e.stopPropagation();
				selection_label.html(e.currentTarget.innerHTML);
				var clicked_value = e.currentTarget.dataset.value;

				if(selection_label.data("value") != clicked_value) {
					/* Selection has changed */
					selection_label.data("value", clicked_value);
					console.log("selection changed:", clicked_value);
					if(options.on_change) {
						options.on_change(clicked_value);
					}
				}

				hide_dropdown();
			}

			function handle_document_click(e) {

				hide_dropdown();
			}

		});

		/* Select initial value, if defined. Initial value passed in options takes
		 * precedence over initial value defined as container data-initial_value
		 * attribute.
		 */
		if(options.initial_value || container.data("initial_value")) {
			let initial_value = options.initial_value ?? container.data("initial_value");
			selection_label.html(
				list.find("li[data-value='" + initial_value + "']").first().html()
			);
		}
	}

	console.log("loaded import/kris/dropdown.js");

	/* Our Exports */
	return {
		initialise: initialise
	};
});
<|endoftext|>