<commit_before>var HTMLCS = new function()
{
    var _standards    = {};
    var _sniffs       = [];
    var _tags         = {};
    var _standard     = null;
    var _currentSniff = null;

    var _messages     = [];
    var _msgOverrides = {};

    /*
        Message type constants.
    */
    this.ERROR   = 1;
    this.WARNING = 2;
    this.NOTICE  = 3;

    /**
     * Loads the specifid standard and run the sniffs.
     *
     * @param {string}         standard The name of the standard to load.
     * @param {string|DOMNode} An HTML string or a DOMNode.
     * @param {function}       The function that will be called when the testing is completed.
     */
    this.process = function(standard, content, callback) {
        if (!content) {
            return false;
        }

        this.loadStandard(standard, function() {
            HTMLCS.run(callback, content);
        });
    };

    /**
     * Loads the specified standard and its sniffs.
     *
     * @param {string}   standard The name of the standard to load.
     * @param {function} callback The function to call once the standard is loaded.
     *
     * @return void
     */
    this.loadStandard = function(standard, callback) {
        if (!standard) {
            return false;
        }

        _includeStandard(standard, function() {
            _standard = standard;
            callback.call(this);
        });
    };

    /**
     * Runs the sniffs for the loaded standard.
     *
     * @param {function}       callback The function to call once all sniffs are completed.
     * @param {string|DOMNode} content  An HTML string or a DOMNode.
     *
     * @return void
     */
    this.run = function(callback, content) {
        var element = null;
        if (typeof content === 'string') {
            element = document.createElement('div');
            element.innerHTML = content;
        } else {
            element = content;
        }

        if (!element) {
            callback.call(this);
            return;
        }

        callback  = callback || function() {};
        _messages = [];

        // Get all the elements in the element.
        var elements = _getAllTags(element);

        // Run the sniffs.
        _run(elements, callback);
    };

    /**
     * Adds a message.
     *
     * @param {integer} type The type of the message.
     * @param {DOMNode} element The element that the message is related to.
     * @param {string}  msg     The message string.
     * @param {string}  code    Unique code for the message.
     * @param {object}  data    Extra data to store for the message.
     */
    this.addMessage = function(type, element, msg, code, data) {
        code = _getMessageCode(code);

        _messages.push({
            type: type,
            element: element,
            msg: _msgOverrides[code] || msg,
            code: code,
            data: data
        });
    };

    /**
     * Returns all the messages for the last run.
     *
     * @return {array} Array of message objects.
     */
    this.getMessages = function() {
        return _messages;
    };

    /**
     * Runs the sniffs in the loaded standard for the specified element.
     *
     * @param {DOMNode}  element  The element to test.
     * @param {function} callback The function to call once all tests are run.
     */
    var _run = function(elements, callback) {
        if (elements.length === 0) {
            callback.call(this);
            return;
        }

        var element = elements.shift();
        var tagName = element.tagName.toLowerCase();
        if (_tags[tagName] && _tags[tagName].length > 0) {
            _processSniffs(element, _tags[tagName].concat([]), function() {
                _run(elements, callback);
            });
        } else {
            _run(elements, callback);
        }
    };

    /**
     * Process the sniffs.
     *
     * @param {DOMNode}  element  The element to test.
     * @param {array}    sniffs   Array of sniffs.
     * @param {function} callback The function to call once the processing is completed.
     */
    var _processSniffs = function(element, sniffs, callback) {
        if (sniffs.length === 0) {
            callback.call(this);
            return;
        }

        var sniff     = sniffs.shift();
        _currentSniff = sniff;

        if (sniff.useCallback === true) {
            // If the useCallback property is set to true then wait for process method
            // to call the function and then continue processing sniffs.
            sniff.process(element, function() {
                _processSniffs(element, sniffs, callback);
            });
        } else {
            // Process the sniff.
            sniff.process(element);

            // Continue processing the rest of the sniffs.
            _processSniffs(element, sniffs, callback);
        }
    };

    /**
     * Includes the specified standard file.
     *
     * @param {string}   standard The name of the standard.
     * @param {function} callback The function to call once the standard is included.
     * @param {object}   options  The options for the standard (e.g. exclude sniffs).
     */
    var _includeStandard = function(standard, callback, options) {
        if (standard.indexOf('http') !== 0) {
            // Get the include path of a local standard.
            var scripts = document.getElementsByTagName('script');
            var path    = null;

            // Loop through all the script tags that exist in the document and find the one
            // that has included this file.
            for (var i = 0; i < scripts.length; i++) {
                if (scripts[i].src) {
                    if (scripts[i].src.match(/HTMLCS\.js/)) {
                        // We have found our appropriate <script> tag that includes
                        // this file, we can extract the path.
                        path = scripts[i].src.replace(/HTMLCS\.js/,'');
                        break;
                    }
                }
            }

            standard = path + 'Standards/' + standard + '/ruleset.js';
        }//end id

        // Include the standard's ruleset JS file.
        _includeScript(standard, function() {
            // Script is included now register the standard.
            _registerStandard(standard, callback, options);
        });
    };

    /**
     * Registers the specified standard and its sniffs.
     *
     * @param {string}   standard The name of the standard.
     * @param {function} callback The function to call once the standard is registered.
     * @param {object}   options  The options for the standard (e.g. exclude sniffs).
     */
    var _registerStandard = function(standard, callback, options) {
        // Get the object name.
        var parts = standard.split('/');

        // Get the ruleset object.
        var ruleSet = window['HTMLCS_' + parts[(parts.length - 2)]];
        if (!ruleSet) {
            return false;
        }

        _standards[standard] = ruleSet;

        // Process the options.
        if (options) {
            if (options.include && options.include.length > 0) {
                // Included sniffs.
                ruleSet.sniffs = options.include;
            } else if (options.exclude) {
                // Excluded sniffs.
                for (var i = 0; i < options.exclude.length; i++) {
                    var index = ruleSet.sniffs.find(options.exclude[i]);
                    if (index >= 0) {
                        ruleSet.sniffs.splice(index, 1);
                    }
                }
            }
        }//end if

        // Register the sniffs for this standard.
        _registerSniffs(standard, ruleSet.sniffs, callback);
    };

    /**
     * Registers the sniffs for the specified standard.
     *
     * @param {string}   standard The name of the standard.
     * @param {array}    sniffs   List of sniffs to register.
     * @param {function} callback The function to call once the sniffs are registered.
     */
    var _registerSniffs = function(standard, sniffs, callback) {
        if (sniffs.length === 0) {
            callback.call(this);
            return;
        }

        // Include and register sniffs.
        var sniff = sniffs.shift();
        _loadSniffFile(standard, sniff, function() {
            _registerSniffs(standard, sniffs, callback);
        });
    };

    /**
     * Includes the sniff's JS file and registers it.
     *
     * @param {string}        standard The name of the standard.
     * @param {string|object} sniff    The sniff to register, can be a string or
     *                                 and object specifying another standard.
     * @param {function}      callback The function to call once the sniff is included and registered.
     */
    var _loadSniffFile = function(standard, sniff, callback) {
        if (typeof sniff === 'string') {
            _includeScript(_getSniffPath(standard, sniff), function() {
                _registerSniff(standard, sniff);
                callback.call(this);
            });
        } else {
            // Including a whole other standard.
            _includeStandard(sniff.standard, function() {
                if (sniff.messages) {
                    // Add message overrides.
                    for (var msg in sniff.messages) {
                        _msgOverrides[msg] = sniff.messages[msg];
                    }
                }

                callback.call(this);
            }, {
                exclude: sniff.exclude,
                include: sniff.include
            });
        }
    };

    /**
     * Registers the specified sniff.
     *
     * @param {string} standard The name of the standard.
     * @param {string} sniff    The name of the sniff.
     */
    var _registerSniff = function(standard, sniff) {
        // Get the sniff object.
        var sniffObj = _getSniff(standard, sniff);
        if (!sniffObj) {
            return false;
        }

        // Call the register method of the sniff, it should return an array of tags.
        var watchedTags = sniffObj.register();
        if (watchedTags && watchedTags.length > 0) {
            for (var i = 0; i < watchedTags.length; i++) {
                if (!_tags[watchedTags[i]]) {
                    _tags[watchedTags[i]] = [];
                }

                _tags[watchedTags[i]].push(sniffObj);
            }
        }

        _sniffs.push(sniffObj);
    };

    /**
     * Returns the path to the sniff file.
     *
     * @param {string} standard The name of the standard.
     * @param {string} sniff    The name of the sniff.
     *
     * @return {string} The path to the JS file of the sniff.
     */
    var _getSniffPath = function(standard, sniff) {
        var parts = standard.split('/');
        parts.pop();

        return parts.join('/') + '/Sniffs/' + sniff.replace('.', '/', 'g') + '.js';
    };

    /**
     * Returns the sniff object.
     *
     * @param {string} standard The name of the standard.
     * @param {string} sniff    The name of the sniff.
     *
     * @return {object} The sniff object.
     */
    var _getSniff = function(standard, sniff) {
        var name = 'HTMLCS_';
        name    += _standards[standard].name + '_Sniffs_';
        name    += sniff.split('.').join('_');

        if (!window[name]) {
            return null;
        }

        window[name]._name = sniff;
        return window[name];
    };

    /**
     * Returns the full message code.
     *
     * A full message code includes the standard name, the sniff name and the given code.
     *
     * @return {string} The full message code.
     */
    var _getMessageCode = function(code) {
        code = _standard + '.' + _currentSniff._name + '.' + code;
        return code;
    };

    /**
     * Includes the specified JS file.
     *
     * @param {string}   src      The URL to the JS file.
     * @param {function} callback The function to call once the script is loaded.
     */
    var _includeScript = function(src, callback) {
        var script    = document.createElement('script');
        script.onload = function() {
            callback.call(this);
        };

        script.src = src;
        document.head.appendChild(script);
    };

    /**
     * Returns all the child elements in the given element.
     *
     * @param {DOMNode} element The parent element.
     *
     * @return {array} Array of DOMNode.
     */
    var _getAllTags = function(element) {
        element      = element || document;
        var elements = element.getElementsByTagName('*');

        // Conver to array.
        elements = [].slice.call(elements, 0);

        return elements;
    };

};
<commit_msg>Do not load standard files multiple times when the process method is called.<commit_after>var HTMLCS = new function()
{
    var _standards    = {};
    var _sniffs       = [];
    var _tags         = {};
    var _standard     = null;
    var _currentSniff = null;

    var _messages     = [];
    var _msgOverrides = {};

    /*
        Message type constants.
    */
    this.ERROR   = 1;
    this.WARNING = 2;
    this.NOTICE  = 3;

    /**
     * Loads the specifid standard and run the sniffs.
     *
     * @param {string}         standard The name of the standard to load.
     * @param {string|DOMNode} An HTML string or a DOMNode.
     * @param {function}       The function that will be called when the testing is completed.
     */
    this.process = function(standard, content, callback) {
        if (!content) {
            return false;
        }

        if (_standards[_getStandardPath(standard)]) {
            HTMLCS.run(callback, content);
        } else {
            this.loadStandard(standard, function() {
                HTMLCS.run(callback, content);
            });
        }
    };

    /**
     * Loads the specified standard and its sniffs.
     *
     * @param {string}   standard The name of the standard to load.
     * @param {function} callback The function to call once the standard is loaded.
     *
     * @return void
     */
    this.loadStandard = function(standard, callback) {
        if (!standard) {
            return false;
        }

        _includeStandard(standard, function() {
            _standard = standard;
            callback.call(this);
        });
    };

    /**
     * Runs the sniffs for the loaded standard.
     *
     * @param {function}       callback The function to call once all sniffs are completed.
     * @param {string|DOMNode} content  An HTML string or a DOMNode.
     *
     * @return void
     */
    this.run = function(callback, content) {
        var element = null;
        if (typeof content === 'string') {
            element = document.createElement('div');
            element.innerHTML = content;
        } else {
            element = content;
        }

        if (!element) {
            callback.call(this);
            return;
        }

        callback  = callback || function() {};
        _messages = [];

        // Get all the elements in the element.
        var elements = _getAllTags(element);

        // Run the sniffs.
        _run(elements, callback);
    };

    /**
     * Adds a message.
     *
     * @param {integer} type The type of the message.
     * @param {DOMNode} element The element that the message is related to.
     * @param {string}  msg     The message string.
     * @param {string}  code    Unique code for the message.
     * @param {object}  data    Extra data to store for the message.
     */
    this.addMessage = function(type, element, msg, code, data) {
        code = _getMessageCode(code);

        _messages.push({
            type: type,
            element: element,
            msg: _msgOverrides[code] || msg,
            code: code,
            data: data
        });
    };

    /**
     * Returns all the messages for the last run.
     *
     * @return {array} Array of message objects.
     */
    this.getMessages = function() {
        return _messages;
    };

    /**
     * Runs the sniffs in the loaded standard for the specified element.
     *
     * @param {DOMNode}  element  The element to test.
     * @param {function} callback The function to call once all tests are run.
     */
    var _run = function(elements, callback) {
        if (elements.length === 0) {
            callback.call(this);
            return;
        }

        var element = elements.shift();
        var tagName = element.tagName.toLowerCase();
        if (_tags[tagName] && _tags[tagName].length > 0) {
            _processSniffs(element, _tags[tagName].concat([]), function() {
                _run(elements, callback);
            });
        } else {
            _run(elements, callback);
        }
    };

    /**
     * Process the sniffs.
     *
     * @param {DOMNode}  element  The element to test.
     * @param {array}    sniffs   Array of sniffs.
     * @param {function} callback The function to call once the processing is completed.
     */
    var _processSniffs = function(element, sniffs, callback) {
        if (sniffs.length === 0) {
            callback.call(this);
            return;
        }

        var sniff     = sniffs.shift();
        _currentSniff = sniff;

        if (sniff.useCallback === true) {
            // If the useCallback property is set to true then wait for process method
            // to call the function and then continue processing sniffs.
            sniff.process(element, function() {
                _processSniffs(element, sniffs, callback);
            });
        } else {
            // Process the sniff.
            sniff.process(element);

            // Continue processing the rest of the sniffs.
            _processSniffs(element, sniffs, callback);
        }
    };

    /**
     * Includes the specified standard file.
     *
     * @param {string}   standard The name of the standard.
     * @param {function} callback The function to call once the standard is included.
     * @param {object}   options  The options for the standard (e.g. exclude sniffs).
     */
    var _includeStandard = function(standard, callback, options) {
        if (standard.indexOf('http') !== 0) {
            standard = _getStandardPath(standard);
        }//end id

        // Include the standard's ruleset JS file.
        _includeScript(standard, function() {
            // Script is included now register the standard.
            _registerStandard(standard, callback, options);
        });
    };

    /**
     * Registers the specified standard and its sniffs.
     *
     * @param {string}   standard The name of the standard.
     * @param {function} callback The function to call once the standard is registered.
     * @param {object}   options  The options for the standard (e.g. exclude sniffs).
     */
    var _registerStandard = function(standard, callback, options) {
        // Get the object name.
        var parts = standard.split('/');

        // Get the ruleset object.
        var ruleSet = window['HTMLCS_' + parts[(parts.length - 2)]];
        if (!ruleSet) {
            return false;
        }

        _standards[standard] = ruleSet;

        // Process the options.
        if (options) {
            if (options.include && options.include.length > 0) {
                // Included sniffs.
                ruleSet.sniffs = options.include;
            } else if (options.exclude) {
                // Excluded sniffs.
                for (var i = 0; i < options.exclude.length; i++) {
                    var index = ruleSet.sniffs.find(options.exclude[i]);
                    if (index >= 0) {
                        ruleSet.sniffs.splice(index, 1);
                    }
                }
            }
        }//end if

        // Register the sniffs for this standard.
        _registerSniffs(standard, ruleSet.sniffs, callback);
    };

    /**
     * Registers the sniffs for the specified standard.
     *
     * @param {string}   standard The name of the standard.
     * @param {array}    sniffs   List of sniffs to register.
     * @param {function} callback The function to call once the sniffs are registered.
     */
    var _registerSniffs = function(standard, sniffs, callback) {
        if (sniffs.length === 0) {
            callback.call(this);
            return;
        }

        // Include and register sniffs.
        var sniff = sniffs.shift();
        _loadSniffFile(standard, sniff, function() {
            _registerSniffs(standard, sniffs, callback);
        });
    };

    /**
     * Includes the sniff's JS file and registers it.
     *
     * @param {string}        standard The name of the standard.
     * @param {string|object} sniff    The sniff to register, can be a string or
     *                                 and object specifying another standard.
     * @param {function}      callback The function to call once the sniff is included and registered.
     */
    var _loadSniffFile = function(standard, sniff, callback) {
        if (typeof sniff === 'string') {
            _includeScript(_getSniffPath(standard, sniff), function() {
                _registerSniff(standard, sniff);
                callback.call(this);
            });
        } else {
            // Including a whole other standard.
            _includeStandard(sniff.standard, function() {
                if (sniff.messages) {
                    // Add message overrides.
                    for (var msg in sniff.messages) {
                        _msgOverrides[msg] = sniff.messages[msg];
                    }
                }

                callback.call(this);
            }, {
                exclude: sniff.exclude,
                include: sniff.include
            });
        }
    };

    /**
     * Registers the specified sniff.
     *
     * @param {string} standard The name of the standard.
     * @param {string} sniff    The name of the sniff.
     */
    var _registerSniff = function(standard, sniff) {
        // Get the sniff object.
        var sniffObj = _getSniff(standard, sniff);
        if (!sniffObj) {
            return false;
        }

        // Call the register method of the sniff, it should return an array of tags.
        var watchedTags = sniffObj.register();
        if (watchedTags && watchedTags.length > 0) {
            for (var i = 0; i < watchedTags.length; i++) {
                if (!_tags[watchedTags[i]]) {
                    _tags[watchedTags[i]] = [];
                }

                _tags[watchedTags[i]].push(sniffObj);
            }
        }

        _sniffs.push(sniffObj);
    };

    /**
     * Returns the path to the sniff file.
     *
     * @param {string} standard The name of the standard.
     * @param {string} sniff    The name of the sniff.
     *
     * @return {string} The path to the JS file of the sniff.
     */
    var _getSniffPath = function(standard, sniff) {
        var parts = standard.split('/');
        parts.pop();

        return parts.join('/') + '/Sniffs/' + sniff.replace('.', '/', 'g') + '.js';
    };

    /**
     * Returns the path to a local standard.
     *
     * @param {string} standard The name of the standard.
     *
     * @return {string} The path to the local standard.
     */
    var _getStandardPath = function(standard)
    {
        // Get the include path of a local standard.
        var scripts = document.getElementsByTagName('script');
        var path    = null;

        // Loop through all the script tags that exist in the document and find the one
        // that has included this file.
        for (var i = 0; i < scripts.length; i++) {
            if (scripts[i].src) {
                if (scripts[i].src.match(/HTMLCS\.js/)) {
                    // We have found our appropriate <script> tag that includes
                    // this file, we can extract the path.
                    path = scripts[i].src.replace(/HTMLCS\.js/,'');
                    break;
                }
            }
        }

        return path + 'Standards/' + standard + '/ruleset.js';

    };

    /**
     * Returns the sniff object.
     *
     * @param {string} standard The name of the standard.
     * @param {string} sniff    The name of the sniff.
     *
     * @return {object} The sniff object.
     */
    var _getSniff = function(standard, sniff) {
        var name = 'HTMLCS_';
        name    += _standards[standard].name + '_Sniffs_';
        name    += sniff.split('.').join('_');

        if (!window[name]) {
            return null;
        }

        window[name]._name = sniff;
        return window[name];
    };

    /**
     * Returns the full message code.
     *
     * A full message code includes the standard name, the sniff name and the given code.
     *
     * @return {string} The full message code.
     */
    var _getMessageCode = function(code) {
        code = _standard + '.' + _currentSniff._name + '.' + code;
        return code;
    };

    /**
     * Includes the specified JS file.
     *
     * @param {string}   src      The URL to the JS file.
     * @param {function} callback The function to call once the script is loaded.
     */
    var _includeScript = function(src, callback) {
        var script    = document.createElement('script');
        script.onload = function() {
            callback.call(this);
        };

        script.src = src;
        document.head.appendChild(script);
    };

    /**
     * Returns all the child elements in the given element.
     *
     * @param {DOMNode} element The parent element.
     *
     * @return {array} Array of DOMNode.
     */
    var _getAllTags = function(element) {
        element      = element || document;
        var elements = element.getElementsByTagName('*');

        // Conver to array.
        elements = [].slice.call(elements, 0);

        return elements;
    };

};
<|endoftext|>


<commit_before>'use strict';

var ltx = require('ltx'),
    util = require('util'),
    winston = require('winston'),
    logger = winston.loggers.get('xepcomponent'),
    uuid = require('node-uuid'),
    XepComponent = require('./XepComponent');

var NS_MUC_UNIQUE = 'http://jabber.org/protocol/muc#unique';

/*
 * XEP-0307: Unique Room Names for Multi-User Chat
 * http://xmpp.org/extensions/xep-0307.html
 *
 */
function MucUnique() {
    XepComponent.call(this);
}
util.inherits(MucUnique, XepComponent);

MucUnique.prototype.name = 'XEP-0307: Unique Room Names for Multi-User Chat';

MucUnique.prototype.version = '0.1.0';

MucUnique.prototype.match = function (stanza) {
    logger.debug("check match");
    if (stanza.is('iq') && stanza.attrs.type === 'get' && (stanza.getChild('unique', NS_MUC_UNIQUE))) {
        logger.debug('detected muc unique request');
        return true;
    }
    return false;
};

/**
 * @description Entity Requests Unique Room Name
 * @param stanza full pubsub message stanza
 * @see http://xmpp.org/extensions/xep-0307.html
 *
 * <iq from='crone1@shakespeare.lit/desktop'
 *     id='unique1'
 *     to='chat.shakespeare.lit'
 *     type='get'>
 *   <unique xmlns='http://jabber.org/protocol/muc#unique'/>
 * </iq>
 *
 * <iq from='chat.shakespeare.lit'
 *     id='unique1'
 *     to='crone1@shakespeare.lit/desktop'
 *     type='result'>
 *   <unique xmlns='http://jabber.org/protocol/muc#unique'>
 *     6d9423a55f499b29ad20bf7b2bdea4f4b885ead1
 *   </unique>
 * </iq>
 */
MucUnique.prototype.handle = function (stanza) {
    // stanza is already verified

    var msg = new ltx.Element('iq', {
        from: stanza.attrs.to,
        to: stanza.attrs.from,
        id: stanza.attrs.id,
        type: 'result'
    });
    var id = uuid.v4().toString();

    // TODO verify the id does not exist in our database
    msg.c('unique', {xmlns : NS_MUC_UNIQUE }).t(id);

    this.send(msg);
};

module.exports = MucUnique;<commit_msg>update logger message in muc unique<commit_after>'use strict';

var ltx = require('ltx'),
    util = require('util'),
    winston = require('winston'),
    logger = winston.loggers.get('xepcomponent'),
    uuid = require('node-uuid'),
    XepComponent = require('./XepComponent');

var NS_MUC_UNIQUE = 'http://jabber.org/protocol/muc#unique';

/*
 * XEP-0307: Unique Room Names for Multi-User Chat
 * http://xmpp.org/extensions/xep-0307.html
 *
 */
function MucUnique() {
    XepComponent.call(this);
}
util.inherits(MucUnique, XepComponent);

MucUnique.prototype.name = 'XEP-0307: Unique Room Names for Multi-User Chat';

MucUnique.prototype.version = '0.1.0';

MucUnique.prototype.match = function (stanza) {
    if (stanza.is('iq') && stanza.attrs.type === 'get' && (stanza.getChild('unique', NS_MUC_UNIQUE))) {
        logger.debug('detected XEP-0307 request');
        return true;
    }
    return false;
};

/**
 * @description Entity Requests Unique Room Name
 * @param stanza full pubsub message stanza
 * @see http://xmpp.org/extensions/xep-0307.html
 *
 * <iq from='crone1@shakespeare.lit/desktop'
 *     id='unique1'
 *     to='chat.shakespeare.lit'
 *     type='get'>
 *   <unique xmlns='http://jabber.org/protocol/muc#unique'/>
 * </iq>
 *
 * <iq from='chat.shakespeare.lit'
 *     id='unique1'
 *     to='crone1@shakespeare.lit/desktop'
 *     type='result'>
 *   <unique xmlns='http://jabber.org/protocol/muc#unique'>
 *     6d9423a55f499b29ad20bf7b2bdea4f4b885ead1
 *   </unique>
 * </iq>
 */
MucUnique.prototype.handle = function (stanza) {
    // stanza is already verified

    var msg = new ltx.Element('iq', {
        from: stanza.attrs.to,
        to: stanza.attrs.from,
        id: stanza.attrs.id,
        type: 'result'
    });
    var id = uuid.v4().toString();

    // TODO verify the id does not exist in our database
    msg.c('unique', {xmlns : NS_MUC_UNIQUE }).t(id);

    this.send(msg);
};

module.exports = MucUnique;<|endoftext|>


<commit_before>/*
Name:             bolcom.js
Description:      Module for node.js to access Bol.com Open API service
Author:           Franklin (https://fvdm.com)
Source:           https://github.com/fvdm/nodejs-bolcom
License:          Unlicense
*/

const { doRequest } = require ('httpreq');

module.exports = class BolcomAPI {

  constructor ({
    apikey,
    sessionId = null,
    timeout = 5000,
  }) {
    this._config = {
      apikey,
      sessionId,
      timeout,
    };
  }

  /**
   * Clean up product URLs
   *
   * @param   {object}  product  Product to clean
   * @return  {object}           Cleaned product
   */

  async cleanProductUrls (product) {
    let urls = {};
    let url;

    for (let i = 0; i < product.urls.length; i++) {
      url = product.urls[i];
      urls[url.key] = url;
    }

    product.urls = urls;
    return product;
  }

  /**
   * Clean up product images
   *
   * @param   {object}  product  Product to clean
   * @return  {object}           Cleaned product
   */

  async cleanProductImages (product) {
    let imgs = {};
    let image;

    for (let i = 0; i < product.images.length; i++) {
      image = product.images[i];
      imgs[image.key] = product.images[i];
    }

    product.images = imgs;
    return product;
  }

  /**
   * Clean up product attributeGroups
   *
   * @param   {object}  product  Product to clean
   * @return  {object}           Cleaned product
   */

  async cleanProductAttrGroups (product) {
    let groups = {};
    let group;
    let attrib;

      if (product.attributeGroups) {
        for (let i = 0; i < product.attributeGroups.length; i++) {
          group = product.attributeGroups[i];
          groups[group.title] = {
            title: group.title,
          };

          if (group.attributes) {
            groups[group.title].attributes = {};

            for (let a = 0; a < group.attributes.length; a++) {
              attrib = group.attributes[a];
              groups[group.title].attributes[attrib.key] = attrib;
            }
          }
        }

        product.attributeGroups = groups;
      }

    return product;
  }

  /**
   * Clean up product data
   *
   * @param   {object}  product  Object to clean
   * @return  {object}           Cleaned object
   */

  async cleanProduct (product) {
    return cleanProductUrls (product)
      .then (cleanProductImages)
      .then (cleanProductAttrGroups)
    ;
  }

  /**
   * Communication with API
   *
   * @param     {string}    cat       api.bol.com/:CAT/v4/method
   * @param     {string}    method    api.bol.com/cat/v4/:METHOD
   * @param     {object}    [params]  Request paramaters
   *
   * @return    {Promise<object>}
   */

  async _talk (cat, method, params = {}) {
    const options = {
      url: `https://api.bol.com/${cat}/v4/${method}`,
      method: 'GET',
      timeout: this._config.timeout,
      parameters: params,
      headers: {
        'User-Agent': 'bolcom.js (https://www.npmjs.com/package/bolcom)',
      },
    };

    options.parameters.apikey = this._config.apikey;
    options.parameters.format = 'json';

    // check session ID
    if (this._config.sessionId) {
      options.headers['X-OpenAPI-Session-ID'] = this._config.sessionId;
    }

    // process response
    return doRequest (options)
      .then (res => res.body)
      .then (JSON.parse)
    ;
  }

  /**
   * Method: utils.ping
   *
   * @return    {Promise<object>}
   */

  async methodUtilsPing () {
    return this._talk ('utils', 'ping');
  }

  /**
   * Method: account.sessions
   *
   * @return    {Promise<object>}
   */

  async methodAccountSessions () {
    return this._talk ('accounts', 'sessions');
  }

  /**
   * Generic catalog request handler
   *
   * @param     {string}    name      Catalog method name
   * @param     {object}    props     Request parameters
   *
   * @return    {Promise<object>}
   */

  async _catalogTalk (name, props) {
    const data = await this._talk ('catalog', name, props);

    if (data.products && Array.isArray (data.products)) {
        for (let i = 0; i < data.products.length; i++) {
          data.products[i] = cleanProduct (data.products[i]);
        }
      }

      return data;
    }
  }

  /**
   * Method: catalog.search
   *
   * @param     {object}    props     Method parameters
   *
   * @return    {Promise<object>}
   */

  async methodCatalogSearch (props) {
    return this._catalogTalk ('search', props);
  }

  /**
   * Method: catalog.lists
   *
   * @param     {object}    props     Method parameters
   *
   * @return    {Promise<object>}
   */

  async methodCatalogLists (props) {
    return this._catalogTalk ('lists', props);
  }

  /**
   * Method: catalog.products
   *
   * @param     {string}    productId  Product ID
   * @param     {object}    [props]    Method parameters
   *
   * @return    {Promise<object>}
   */

  async methodCatalogProducts (productId, props) {
    return this._catalogTalk (`products/${productId}`, props);
  }

  /**
   * Method: catalog.offers
   *
   * @param     {string}    productId  Product ID
   * @param     {object}    [props]    Method parameters
   *
   * @return    {Promise<object>}
   */

  async methodCatalogOffers (productId, props) {
    const data = await this._talk ('catalog', `offers/${productId}`, props);

    if (data.offerData) {
      data = data.offerData;
    }

    return data;
  }

  /**
   * Method: catalog.recommendations
   *
   * @return    {Promise<object>}
   *
   * @param     {string}    productId  Product ID
   * @param     {object}    [props]    Method parameters
   */

  async methodCatalogRecommendations (productId, props) {
    return this._catalogTalk (`recommendations/${productId}`, props);
  }

  /**
   * Method: catalog.relatedproducts
   *
   * @return    {Promise<object>}
   *
   * @param     {string}    productId  Product ID
   * @param     {object}    [props]    Method parameters
   */

  async methodCatalogRelatedProducts (productId, props) {
    let data = await this._talk ('catalog', `relatedproducts/${productId}`, props);
    let tmp = {};
    let tmp2 = {};

    if (data.productFamilies) {
      data = data.productFamilies;

      if (!Array.isArray (data) && !data.length && !data[0].key) {
        return data;
      }

      for (let i = 0; i < data.length; i++) {
        tmp[data[i].key] = data[i];

        if (Array.isArray (data[i].productFamilyMembers)) {
          tmp2 = {};

          for (let m = 0; m < data[i].productFamilyMembers.length; m++) {
            tmp2[data[i].productFamilyMembers[m].label] = data[i].productFamilyMembers[m];
          }

          tmp[data[i].key].productFamilyMembers = tmp2;
        }

        data = tmp;
      }

      return data;
    }
  }

  /**
   * Method: account.wishlists
   *
   * @return    {Promise<object>}
   */

  async methodAccountWishlists () {
    return this._talk ('accounts', 'wishlists');
  }

};
<commit_msg>Fix: Syntax errors and whitespace<commit_after>/*
Name:             bolcom.js
Description:      Module for node.js to access Bol.com Open API service
Author:           Franklin (https://fvdm.com)
Source:           https://github.com/fvdm/nodejs-bolcom
License:          Unlicense
*/

const { doRequest } = require ('httpreq');

module.exports = class BolcomAPI {

  constructor ({
    apikey,
    sessionId = null,
    timeout = 5000,
  }) {
    this._config = {
      apikey,
      sessionId,
      timeout,
    };
  }

  /**
   * Clean up product URLs
   *
   * @param   {object}  product  Product to clean
   * @return  {object}           Cleaned product
   */

  async cleanProductUrls (product) {
    let urls = {};
    let url;

    for (let i = 0; i < product.urls.length; i++) {
      url = product.urls[i];
      urls[url.key] = url;
    }

    product.urls = urls;
    return product;
  }

  /**
   * Clean up product images
   *
   * @param   {object}  product  Product to clean
   * @return  {object}           Cleaned product
   */

  async cleanProductImages (product) {
    let imgs = {};
    let image;

    for (let i = 0; i < product.images.length; i++) {
      image = product.images[i];
      imgs[image.key] = product.images[i];
    }

    product.images = imgs;
    return product;
  }

  /**
   * Clean up product attributeGroups
   *
   * @param   {object}  product  Product to clean
   * @return  {object}           Cleaned product
   */

  async cleanProductAttrGroups (product) {
    let groups = {};
    let group;
    let attrib;

    if (product.attributeGroups) {
      for (let i = 0; i < product.attributeGroups.length; i++) {
        group = product.attributeGroups[i];
        groups[group.title] = {
          title: group.title,
        };

        if (group.attributes) {
          groups[group.title].attributes = {};

          for (let a = 0; a < group.attributes.length; a++) {
            attrib = group.attributes[a];
            groups[group.title].attributes[attrib.key] = attrib;
          }
        }
      }

      product.attributeGroups = groups;
    }

    return product;
  }

  /**
   * Clean up product data
   *
   * @param   {object}  product  Object to clean
   * @return  {object}           Cleaned object
   */

  async cleanProduct (product) {
    return cleanProductUrls (product)
      .then (cleanProductImages)
      .then (cleanProductAttrGroups)
    ;
  }

  /**
   * Communication with API
   *
   * @param     {string}    cat       api.bol.com/:CAT/v4/method
   * @param     {string}    method    api.bol.com/cat/v4/:METHOD
   * @param     {object}    [params]  Request paramaters
   *
   * @return    {Promise<object>}
   */

  async _talk (cat, method, params = {}) {
    const options = {
      url: `https://api.bol.com/${cat}/v4/${method}`,
      method: 'GET',
      timeout: this._config.timeout,
      parameters: params,
      headers: {
        'User-Agent': 'bolcom.js (https://www.npmjs.com/package/bolcom)',
      },
    };

    options.parameters.apikey = this._config.apikey;
    options.parameters.format = 'json';

    // check session ID
    if (this._config.sessionId) {
      options.headers['X-OpenAPI-Session-ID'] = this._config.sessionId;
    }

    // process response
    return doRequest (options)
      .then (res => res.body)
      .then (JSON.parse)
    ;
  }

  /**
   * Method: utils.ping
   *
   * @return    {Promise<object>}
   */

  async methodUtilsPing () {
    return this._talk ('utils', 'ping');
  }

  /**
   * Method: account.sessions
   *
   * @return    {Promise<object>}
   */

  async methodAccountSessions () {
    return this._talk ('accounts', 'sessions');
  }

  /**
   * Generic catalog request handler
   *
   * @param     {string}    name      Catalog method name
   * @param     {object}    props     Request parameters
   *
   * @return    {Promise<object>}
   */

  async _catalogTalk (name, props) {
    const data = await this._talk ('catalog', name, props);

    if (data.products && Array.isArray (data.products)) {
      for (let i = 0; i < data.products.length; i++) {
        data.products[i] = cleanProduct (data.products[i]);
      }

      return data;
    }
  }

  /**
   * Method: catalog.search
   *
   * @param     {object}    props     Method parameters
   *
   * @return    {Promise<object>}
   */

  async methodCatalogSearch (props) {
    return this._catalogTalk ('search', props);
  }

  /**
   * Method: catalog.lists
   *
   * @param     {object}    props     Method parameters
   *
   * @return    {Promise<object>}
   */

  async methodCatalogLists (props) {
    return this._catalogTalk ('lists', props);
  }

  /**
   * Method: catalog.products
   *
   * @param     {string}    productId  Product ID
   * @param     {object}    [props]    Method parameters
   *
   * @return    {Promise<object>}
   */

  async methodCatalogProducts (productId, props) {
    return this._catalogTalk (`products/${productId}`, props);
  }

  /**
   * Method: catalog.offers
   *
   * @param     {string}    productId  Product ID
   * @param     {object}    [props]    Method parameters
   *
   * @return    {Promise<object>}
   */

  async methodCatalogOffers (productId, props) {
    const data = await this._talk ('catalog', `offers/${productId}`, props);

    if (data.offerData) {
      data = data.offerData;
    }

    return data;
  }

  /**
   * Method: catalog.recommendations
   *
   * @return    {Promise<object>}
   *
   * @param     {string}    productId  Product ID
   * @param     {object}    [props]    Method parameters
   */

  async methodCatalogRecommendations (productId, props) {
    return this._catalogTalk (`recommendations/${productId}`, props);
  }

  /**
   * Method: catalog.relatedproducts
   *
   * @return    {Promise<object>}
   *
   * @param     {string}    productId  Product ID
   * @param     {object}    [props]    Method parameters
   */

  async methodCatalogRelatedProducts (productId, props) {
    let data = await this._talk ('catalog', `relatedproducts/${productId}`, props);
    let tmp = {};
    let tmp2 = {};

    if (data.productFamilies) {
      data = data.productFamilies;

      if (!Array.isArray (data) && !data.length && !data[0].key) {
        return data;
      }

      for (let i = 0; i < data.length; i++) {
        tmp[data[i].key] = data[i];

        if (Array.isArray (data[i].productFamilyMembers)) {
          tmp2 = {};

          for (let m = 0; m < data[i].productFamilyMembers.length; m++) {
            tmp2[data[i].productFamilyMembers[m].label] = data[i].productFamilyMembers[m];
          }

          tmp[data[i].key].productFamilyMembers = tmp2;
        }

        data = tmp;
      }

      return data;
    }
  }

  /**
   * Method: account.wishlists
   *
   * @return    {Promise<object>}
   */

  async methodAccountWishlists () {
    return this._talk ('accounts', 'wishlists');
  }

};
<|endoftext|>


<commit_before>
$(document).ready(function(){
	// Initialisation de Particles JS
	particlesJS.load('particles-js', 'assets/particles.json');

	// Affichage du titre de la popup d'introduction (Typed.js)
	$("#typed_title").typed({
		strings:["Qu'est ce que la smart city ?"],
		typeSpeed:30,
		callback:function(){
			$('.typed-cursor').hide();
		}
	});

	// Bouton passer (passe la popup d'introduction)
	$('.overlay .overlay_content .skip').click(function(event){
		event.preventDefault();
		$('.overlay').hide();
	});
};

// sound text
var soundAntiquite = new Howl({
      src: ['assets/audio/Antiquite.wav']});
var soundCollabHumain = new Howl({
      src: ['assets/audio/Appli_collab_humain.wav']});
var soundCollabTech = new Howl({
      src: ['assets/audio/Appli_collab_tech.wav']});
var soundFerme = new Howl({
      src: ['assets/audio/Fermes_urbaines.wav']});
var soundMurVege = new Howl({
      src: ['assets/audio/Mur_vegetal.wav']});
var soundPanneauSol = new Howl({
      src: ['assets/audio/Panneau_sol-pho.wav']});
var soundSingapour = new Howl({
      src: ['assets/audio/Singapour.wav']});
var soundVauban = new Howl({
      src: ['assets/audio/Vauban.wav']});
var soundWifiLib = new Howl({
      src: ['assets/audio/WifiLib.wav']});

var soundBruitagesClap = new Howl({
      src: ['assets/Bruitages/claphyblab.mp3']});
var soundBruitagesButton = new Howl({
      src: ['assets/Bruitages/buttonhyblab.mp3']});
var soundBruitagesDeZoom = new Howl({
      src: ['assets/Bruitages/hyplabdezoom.mp3']});
var soundBruitagesZoom = new Howl({
      src: ['assets/Bruitages/hyplabzoom.mp3']});

// Gestion de la date (ODOMETER) au survol d'un point
// au survol de n'importe quel élément ".point" QUI POSSEDE UNE ID -> on refresh l'odomètre (années)
var anneeEnCours = -2121;
var d = new Date();
var n = d.getTime();
function intervalSoundClap(annee){
	if(anneeEnCours != annee){
		d = new Date();
		var time2 = d.getTime();
		if(time2 -n >2000){
			soundBruitagesClap.play();
			n = time2;
		}
	}
};
//TODO changement de couleur? taille ? pour l'intractiviter
$('.point').hover(function(event){
	var annee = 0;
	switch(event.target.id){
		case "p1":
		annee = -312;
		intervalSoundClap(annee);
		anneeEnCours = annee;
			break;
		case "p2":
			annee = 1954;
			intervalSoundClap(annee);
			anneeEnCours = annee;
			break;
		case "p3":
			annee = 1986;
			intervalSoundClap(annee);
			anneeEnCours = annee;
			break;
		case "p4":
			annee = 2000;
			intervalSoundClap(annee);
			anneeEnCours = annee;
			break;
		case "p5":
			annee = 2012;
			intervalSoundClap(annee);
			anneeEnCours = annee;
			break;
		case "p6":
			annee = 0;
			intervalSoundClap(annee);
			anneeEnCours = annee;
			break;
		case "p7":
			annee = 0;
			intervalSoundClap(annee);
			anneeEnCours = annee;
			break;
		case "p8":
			annee = 0;
			intervalSoundClap(annee);
			anneeEnCours = annee;
			break;
		case "p9":
			annee = 0;
			intervalSoundClap(annee);
			anneeEnCours = annee;
			break;
		case "p10":
			annee = 0;
			intervalSoundClap(annee);
			anneeEnCours = annee;
			break;
		case "p11":
			annee = 0;
			intervalSoundClap(annee);
			anneeEnCours = annee;
			break;
		case "p12":
			annee = 0;
			intervalSoundClap(annee);
			anneeEnCours = annee;
			break;
	}
	$('.odometer').html(annee);
});

// Variable qui permet de savoir si on est zoomés ou pas (et donc d'activer le dézoom au clic à la place du zoom)
var areWeZoomed = false;
var animPola1;
var animPola2;
var animPola3;

$('.point').click(function(event){
<<<<<<< HEAD
	if(!areWeZoomed){
=======

	if(!areWeZoomed){
	soundBruitagesZoom.play();
>>>>>>> c9c34cb22185cec6a0166d408d62f00a28576153
		$(this).removeClass('pulsating');
		zoom.to({
			element:document.querySelector('#' + event.target.id)
		});
		areWeZoomed = true;
	}
	$(this).toggleClass('selectedZoomTarget');
	new Promise(resolve => {
		animPola1 = setTimeout(() => {
			resolve($(this).find('.pola1').toggleClass('polaAnimer'));
		}, 1500);
	});
	new Promise(resolve => {
		animPola2 = setTimeout(() => {
			resolve($(this).find('.pola2').toggleClass('polaAnimer'));
			resolve($(this).find('.play').toggleClass('polaAnimer'));
		}, 3500);
	});
	new Promise(resolve => {
		animPola3 = setTimeout(() => {
			resolve($(this).find('.pola3').toggleClass('polaAnimer'));
		}, 7000);
	});
});

/* Gestion de la fonction de zoom arrière (unzoom) */
$("body *:not(body .point)").click(function(event){
	console.log("click");
	if(areWeZoomed){
		clearTimeout(animPola1);
		clearTimeout(animPola2);
		clearTimeout(animPola3);
		$('.pola1').removeClass('polaAnimer');
		$('.pola2').removeClass('polaAnimer');
		$('.pola3').removeClass('polaAnimer');
		zoom.out();
		areWeZoomed = false;
	}
});
<commit_msg>error syntax<commit_after>
$(document).ready(function(){
	// Initialisation de Particles JS
	particlesJS.load('particles-js', 'assets/particles.json');

	// Affichage du titre de la popup d'introduction (Typed.js)
	$("#typed_title").typed({
		strings:["Qu'est ce que la smart city ?"],
		typeSpeed:30,
		callback:function(){
			$('.typed-cursor').hide();
		}
	});

	// Bouton passer (passe la popup d'introduction)
	$('.overlay .overlay_content .skip').click(function(event){
		event.preventDefault();
		$('.overlay').hide();
	});
});

// sound text
var soundAntiquite = new Howl({
      src: ['assets/audio/Antiquite.wav']});
var soundCollabHumain = new Howl({
      src: ['assets/audio/Appli_collab_humain.wav']});
var soundCollabTech = new Howl({
      src: ['assets/audio/Appli_collab_tech.wav']});
var soundFerme = new Howl({
      src: ['assets/audio/Fermes_urbaines.wav']});
var soundMurVege = new Howl({
      src: ['assets/audio/Mur_vegetal.wav']});
var soundPanneauSol = new Howl({
      src: ['assets/audio/Panneau_sol-pho.wav']});
var soundSingapour = new Howl({
      src: ['assets/audio/Singapour.wav']});
var soundVauban = new Howl({
      src: ['assets/audio/Vauban.wav']});
var soundWifiLib = new Howl({
      src: ['assets/audio/WifiLib.wav']});

var soundBruitagesClap = new Howl({
      src: ['assets/Bruitages/claphyblab.mp3']});
var soundBruitagesButton = new Howl({
      src: ['assets/Bruitages/buttonhyblab.mp3']});
var soundBruitagesDeZoom = new Howl({
      src: ['assets/Bruitages/hyplabdezoom.mp3']});
var soundBruitagesZoom = new Howl({
      src: ['assets/Bruitages/hyplabzoom.mp3']});

// Gestion de la date (ODOMETER) au survol d'un point
// au survol de n'importe quel élément ".point" QUI POSSEDE UNE ID -> on refresh l'odomètre (années)
var anneeEnCours = -2121;
var d = new Date();
var n = d.getTime();
function intervalSoundClap(annee){
	if(anneeEnCours != annee){
		d = new Date();
		var time2 = d.getTime();
		if(time2 -n >2000){
			soundBruitagesClap.play();
			n = time2;
		}
	}
};
//TODO changement de couleur? taille ? pour l'intractiviter
$('.point').hover(function(event){
	var annee = 0;
	switch(event.target.id){
		case "p1":
		annee = -312;
		intervalSoundClap(annee);
		anneeEnCours = annee;
			break;
		case "p2":
			annee = 1954;
			intervalSoundClap(annee);
			anneeEnCours = annee;
			break;
		case "p3":
			annee = 1986;
			intervalSoundClap(annee);
			anneeEnCours = annee;
			break;
		case "p4":
			annee = 2000;
			intervalSoundClap(annee);
			anneeEnCours = annee;
			break;
		case "p5":
			annee = 2012;
			intervalSoundClap(annee);
			anneeEnCours = annee;
			break;
		case "p6":
			annee = 0;
			intervalSoundClap(annee);
			anneeEnCours = annee;
			break;
		case "p7":
			annee = 0;
			intervalSoundClap(annee);
			anneeEnCours = annee;
			break;
		case "p8":
			annee = 0;
			intervalSoundClap(annee);
			anneeEnCours = annee;
			break;
		case "p9":
			annee = 0;
			intervalSoundClap(annee);
			anneeEnCours = annee;
			break;
		case "p10":
			annee = 0;
			intervalSoundClap(annee);
			anneeEnCours = annee;
			break;
		case "p11":
			annee = 0;
			intervalSoundClap(annee);
			anneeEnCours = annee;
			break;
		case "p12":
			annee = 0;
			intervalSoundClap(annee);
			anneeEnCours = annee;
			break;
	}
	$('.odometer').html(annee);
});

// Variable qui permet de savoir si on est zoomés ou pas (et donc d'activer le dézoom au clic à la place du zoom)
var areWeZoomed = false;
var animPola1;
var animPola2;
var animPola3;

$('.point').click(function(event){
	if(!areWeZoomed){
	soundBruitagesZoom.play();
		$(this).removeClass('pulsating');
		zoom.to({
			element:document.querySelector('#' + event.target.id)
		});
		areWeZoomed = true;
	}
	$(this).toggleClass('selectedZoomTarget');
	new Promise(resolve => {
		animPola1 = setTimeout(() => {
			resolve($(this).find('.pola1').toggleClass('polaAnimer'));
		}, 1500);
	});
	new Promise(resolve => {
		animPola2 = setTimeout(() => {
			resolve($(this).find('.pola2').toggleClass('polaAnimer'));
			resolve($(this).find('.play').toggleClass('polaAnimer'));
		}, 3500);
	});
	new Promise(resolve => {
		animPola3 = setTimeout(() => {
			resolve($(this).find('.pola3').toggleClass('polaAnimer'));
		}, 7000);
	});
});

/* Gestion de la fonction de zoom arrière (unzoom) */
$("body *:not(body .point)").click(function(event){
	console.log("click");
	if(areWeZoomed){
		clearTimeout(animPola1);
		clearTimeout(animPola2);
		clearTimeout(animPola3);
		$('.pola1').removeClass('polaAnimer');
		$('.pola2').removeClass('polaAnimer');
		$('.pola3').removeClass('polaAnimer');
		zoom.out();
		areWeZoomed = false;
	}
});
<|endoftext|>


<commit_before>/*doc
---
title: Dropdowns
name: dropdown_react
categories:
- react_components_dropdowns
- react_all
---

npm install pui-react-dropdowns --save

npm install babel-loader svg-react-loader --save-dev

## Props

Property         | Required | Type                             | Default | Description
-----------------|----------|----------------------------------|---------|------------
border           | no       | Boolean                          |         | If true, adds a border between menu items
buttonClassName  | no       | String                           |         | Classname to add to the button
closeOnMenuClick | no       | Boolean                          | true    | If false, do not close the menu when clicking in the dropdown menu
disableScrim     | no       | Boolean                          | false   | If true, do not close the menu when clicking outside the dropdown
dropCaret        | no       | Boolean                          | true    | If false, do not render the caret in the dropdown toggle
flat             | no       | Boolean                          |         | If true, dropdown toggle has no borders and is transparent
link             | no       | Boolean                          |         | If true, color the dropdown toggle like a link
menuCaret        | no       | Boolean                          |         | If true, render a caret in the menu pointing at the toggle
onEntered        | no       | Function                         |         | Callback that fires after opening the dropdown
onExited         | no       | Function                         |         | Callback that fires after closing the dropdown
split            | no       | Boolean                          |         | If true, separates the button text from the toggle
title            | no       | Node                             |         | The button contents
toggle           | no       | Node                             |         | The toggle contents
menuAlign        | no       | oneOf(['none', 'left', 'right']) | 'none'  | Sets the alignment of the menu with the button
scroll           | no       | Boolean                          | false   | Enables scrolling in the dropdown menu when enabled

(The extra loaders are for the [Iconography](/react_base_iconography.html) component.)

Import the subcomponents:

```
import {Dropdown, DropdownItem} from 'pui-react-dropdowns';
```

## Basic Dropdown

This is the basic dropdown. It has an attached menu that extends from the bottom.

```react_example
<Dropdown title='Basic DropDown'>
  <DropdownItem href="#">lorem ipsum</DropdownItem>
  <DropdownItem href="#">lorem ipsum</DropdownItem>
  <DropdownItem href="#">lorem ipsum</DropdownItem>
</Dropdown>
```

## Float Dropdown Menu:

The float dropdown menu is spaced 2px below the toggle. It can also be pinned to the left or right for content that
exceeds the parent dropdown width.

```react_example
<div className="form-group" style={{display: 'flex'}}>
 <Dropdown title='Float DropDown Menu' menuCaret style={{marginRight: 32}}>
  <DropdownItem href="#">lorem ipsum</DropdownItem>
  <DropdownItem href="#">lorem ipsum</DropdownItem>
  <DropdownItem href="#">lorem ipsum</DropdownItem>
 </Dropdown>

 <Dropdown title='Pinned Left' menuCaret menuAlign='left' style={{marginRight: 32}}>
 <DropdownItem href="#">Note that this option exceeds the width of the parent dropdown toggle</DropdownItem>
 <DropdownItem href="#">lorem ipsum</DropdownItem>
 <DropdownItem href="#">lorem ipsum</DropdownItem>
 </Dropdown>

 <Dropdown title='Pinned Right' menuCaret menuAlign='right'>
 <DropdownItem href="#">lorem ipsum</DropdownItem>
 <DropdownItem href="#">lorem ipsum</DropdownItem>
 <DropdownItem href="#">lorem ipsum</DropdownItem>
 </Dropdown>
</div>
```

## Float Scroll Menu:

Lists that are indeterminately long can utilize the float scroll menu. The size is
fixed so you'll have to customize the fixed height to achieve your desired results.

```react_example
<Dropdown title='Float Scroll Menu' scroll menuCaret>
  <DropdownItem href="#">lorem ipsum</DropdownItem>
  <DropdownItem href="#">lorem ipsum</DropdownItem>
  <DropdownItem href="#">lorem ipsum</DropdownItem>
  <DropdownItem href="#">lorem ipsum</DropdownItem>
  <DropdownItem href="#">lorem ipsum</DropdownItem>
  <DropdownItem href="#">lorem ipsum</DropdownItem>
  <DropdownItem href="#">lorem ipsum</DropdownItem>
  <DropdownItem href="#">lorem ipsum</DropdownItem>
  <DropdownItem href="#">lorem ipsum</DropdownItem>
  <DropdownItem href="#">lorem ipsum</DropdownItem>
</Dropdown>
```

## Split Dropdown:

Action with additional actions hidden in a dropdown. Only appropriate as a float menu.

```react_example
<Dropdown title='Split Dropdown' split>
  <DropdownItem href="#">lorem ipsum</DropdownItem>
  <DropdownItem href="#">lorem ipsum</DropdownItem>
  <DropdownItem href="#">lorem ipsum</DropdownItem>
</Dropdown>
```

## Flat Button Dropdown:

Dropdown with the flat button styling.

```react_example
<Dropdown title='Flat Button DropDown' flat>
  <DropdownItem href="#">lorem ipsum</DropdownItem>
  <DropdownItem href="#">lorem ipsum</DropdownItem>
  <DropdownItem href="#">lorem ipsum</DropdownItem>
</Dropdown>
```

## Link Dropdown:

Dropdown with the link styling, retains dropdown padding.

```react_example
<Dropdown title='Link DropDown' link>
  <DropdownItem href="#">lorem ipsum</DropdownItem>
  <DropdownItem href="#">lorem ipsum</DropdownItem>
  <DropdownItem href="#">lorem ipsum</DropdownItem>
</Dropdown>
```

## Icon Dropdown (dropdown with icon toggle):

A dropdown with an icon toggle can be styled like a basic dropdown or a flat button.

### Basic Icon
```react_example
<Dropdown toggle={<Icon src='chevron_down'/>}>
  <DropdownItem href="#">lorem ipsum</DropdownItem>
  <DropdownItem href="#">lorem ipsum</DropdownItem>
  <DropdownItem href="#">lorem ipsum</DropdownItem>
</Dropdown>
```

### Flat Icon
```react_example
<Dropdown toggle={<Icon src='chevron_down'/>} flat>
  <DropdownItem href="#">lorem ipsum</DropdownItem>
  <DropdownItem href="#">lorem ipsum</DropdownItem>
  <DropdownItem href="#">lorem ipsum</DropdownItem>
</Dropdown>
```
*/
<commit_msg>feat(dropdown) remove icon dropdown from React docs<commit_after>/*doc
---
title: Dropdowns
name: dropdown_react
categories:
- react_components_dropdowns
- react_all
---

npm install pui-react-dropdowns --save

npm install babel-loader svg-react-loader --save-dev

## Props

Property         | Required | Type                             | Default | Description
-----------------|----------|----------------------------------|---------|------------
border           | no       | Boolean                          |         | If true, adds a border between menu items
buttonClassName  | no       | String                           |         | Classname to add to the button
closeOnMenuClick | no       | Boolean                          | true    | If false, do not close the menu when clicking in the dropdown menu
disableScrim     | no       | Boolean                          | false   | If true, do not close the menu when clicking outside the dropdown
dropCaret        | no       | Boolean                          | true    | If false, do not render the caret in the dropdown toggle
flat             | no       | Boolean                          |         | If true, dropdown toggle has no borders and is transparent
link             | no       | Boolean                          |         | If true, color the dropdown toggle like a link
menuCaret        | no       | Boolean                          |         | If true, render a caret in the menu pointing at the toggle
onEntered        | no       | Function                         |         | Callback that fires after opening the dropdown
onExited         | no       | Function                         |         | Callback that fires after closing the dropdown
split            | no       | Boolean                          |         | If true, separates the button text from the toggle
title            | no       | Node                             |         | The button contents
toggle           | no       | Node                             |         | The toggle contents
menuAlign        | no       | oneOf(['none', 'left', 'right']) | 'none'  | Sets the alignment of the menu with the button
scroll           | no       | Boolean                          | false   | Enables scrolling in the dropdown menu when enabled

(The extra loaders are for the [Iconography](/react_base_iconography.html) component.)

Import the subcomponents:

```
import {Dropdown, DropdownItem} from 'pui-react-dropdowns';
```

## Basic Dropdown

This is the basic dropdown. It has an attached menu that extends from the bottom.

```react_example
<Dropdown title='Basic DropDown'>
  <DropdownItem href="#">lorem ipsum</DropdownItem>
  <DropdownItem href="#">lorem ipsum</DropdownItem>
  <DropdownItem href="#">lorem ipsum</DropdownItem>
</Dropdown>
```

## Float Dropdown Menu:

The float dropdown menu is spaced 2px below the toggle. It can also be pinned to the left or right for content that
exceeds the parent dropdown width.

```react_example
<div className="form-group" style={{display: 'flex'}}>
 <Dropdown title='Float DropDown Menu' menuCaret style={{marginRight: 32}}>
  <DropdownItem href="#">lorem ipsum</DropdownItem>
  <DropdownItem href="#">lorem ipsum</DropdownItem>
  <DropdownItem href="#">lorem ipsum</DropdownItem>
 </Dropdown>

 <Dropdown title='Pinned Left' menuCaret menuAlign='left' style={{marginRight: 32}}>
 <DropdownItem href="#">Note that this option exceeds the width of the parent dropdown toggle</DropdownItem>
 <DropdownItem href="#">lorem ipsum</DropdownItem>
 <DropdownItem href="#">lorem ipsum</DropdownItem>
 </Dropdown>

 <Dropdown title='Pinned Right' menuCaret menuAlign='right'>
 <DropdownItem href="#">lorem ipsum</DropdownItem>
 <DropdownItem href="#">lorem ipsum</DropdownItem>
 <DropdownItem href="#">lorem ipsum</DropdownItem>
 </Dropdown>
</div>
```

## Float Scroll Menu:

Lists that are indeterminately long can utilize the float scroll menu. The size is
fixed so you'll have to customize the fixed height to achieve your desired results.

```react_example
<Dropdown title='Float Scroll Menu' scroll menuCaret>
  <DropdownItem href="#">lorem ipsum</DropdownItem>
  <DropdownItem href="#">lorem ipsum</DropdownItem>
  <DropdownItem href="#">lorem ipsum</DropdownItem>
  <DropdownItem href="#">lorem ipsum</DropdownItem>
  <DropdownItem href="#">lorem ipsum</DropdownItem>
  <DropdownItem href="#">lorem ipsum</DropdownItem>
  <DropdownItem href="#">lorem ipsum</DropdownItem>
  <DropdownItem href="#">lorem ipsum</DropdownItem>
  <DropdownItem href="#">lorem ipsum</DropdownItem>
  <DropdownItem href="#">lorem ipsum</DropdownItem>
</Dropdown>
```

## Split Dropdown:

Action with additional actions hidden in a dropdown. Only appropriate as a float menu.

```react_example
<Dropdown title='Split Dropdown' split>
  <DropdownItem href="#">lorem ipsum</DropdownItem>
  <DropdownItem href="#">lorem ipsum</DropdownItem>
  <DropdownItem href="#">lorem ipsum</DropdownItem>
</Dropdown>
```

## Flat Button Dropdown:

Dropdown with the flat button styling.

```react_example
<Dropdown title='Flat Button DropDown' flat>
  <DropdownItem href="#">lorem ipsum</DropdownItem>
  <DropdownItem href="#">lorem ipsum</DropdownItem>
  <DropdownItem href="#">lorem ipsum</DropdownItem>
</Dropdown>
```

## Link Dropdown:

Dropdown with the link styling, retains dropdown padding.

```react_example
<Dropdown title='Link DropDown' link>
  <DropdownItem href="#">lorem ipsum</DropdownItem>
  <DropdownItem href="#">lorem ipsum</DropdownItem>
  <DropdownItem href="#">lorem ipsum</DropdownItem>
</Dropdown>
```
*/
<|endoftext|>


<commit_before>/**
 * brightwheel
 *
 * Copyright © 2016 Allen Smith <loranallensmith@github.com>. All rights reserved.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE.txt file in the root directory of this source tree.
 */

import { expect } from 'chai';
import TextArea from '../src/textarea';

describe('TextArea', () => {

  describe('render', () => {

    it('Should render the correct element', () => {
      let myText = new TextArea({}, []);
      expect(myText.virtualElement.tagName).to.equal('TEXTAREA')
    });

    it('Should have the correct default classes', () => {
      let myText = new TextArea({}, []);
      expect(myText.virtualElement.properties.className).to.include('form-control');
    });

    it('Should support multiple classes', () => {
      let myText = new TextArea({ classNames: ['extra-class', 'another-class'] }, []);
      expect(myText.virtualElement.properties.className).to.include('another-class');
      expect(myText.virtualElement.properties.className).to.include('extra-class');
    });

    it('Should render the correct rows and cols', () => {
      let myText = new TextArea({ type: 'text', rows: 10, cols: 20}, []);
      expect(myText.virtualElement.properties).to.contain.keys({ type: 'text', rows: 10, cols: 20 });
    });

    it('Should render the name', () => {
      let myText = new TextArea({ name: 'my-input'}, []);
      expect(myText.virtualElement.properties).to.contain.keys({ name: 'my-input' });
    });

    it('Should render the text', () => {
      let myText = new TextArea({ text: 'Text content'}, []);
      expect(myText.virtualElement.children[0].text).to.equal('Text content');
    });

  });

});
<commit_msg>Remove test for rows and columns<commit_after>/**
 * brightwheel
 *
 * Copyright © 2016 Allen Smith <loranallensmith@github.com>. All rights reserved.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE.txt file in the root directory of this source tree.
 */

import { expect } from 'chai';
import TextArea from '../src/textarea';

describe('TextArea', () => {

  describe('render', () => {

    it('Should render the correct element', () => {
      let myText = new TextArea({}, []);
      expect(myText.virtualElement.tagName).to.equal('TEXTAREA')
    });

    it('Should have the correct default classes', () => {
      let myText = new TextArea({}, []);
      expect(myText.virtualElement.properties.className).to.include('form-control');
    });

    it('Should support multiple classes', () => {
      let myText = new TextArea({ classNames: ['extra-class', 'another-class'] }, []);
      expect(myText.virtualElement.properties.className).to.include('another-class');
      expect(myText.virtualElement.properties.className).to.include('extra-class');
    });

    it('Should render the name', () => {
      let myText = new TextArea({ name: 'my-input'}, []);
      expect(myText.virtualElement.properties).to.contain.keys({ name: 'my-input' });
    });

    it('Should render the text', () => {
      let myText = new TextArea({ text: 'Text content'}, []);
      expect(myText.virtualElement.children[0].text).to.equal('Text content');
    });

  });

});
<|endoftext|>


<commit_before>/*global describe,it*/

var unexpected = require('unexpected');
    unicodeRegExp = require('../lib/unicodeRegExp');

describe('unicodeRegExp', function () {
    describe('#removeCharacterFromCharacterClassRegExp()', function () {
        var expect = unexpected.clone();

        expect.addAssertion('[not] to be rewritten to', function (value) {
            this.assert(unicodeRegExp.removeCharacterFromCharacterClassRegExp(this.obj[0], this.obj[1]), 'to equal', value);
        });

        it('should handle an empty character class', function () {
            expect([new RegExp('[]'), 'a'], 'to be rewritten to', new RegExp("[]"));
        });

        it('should remove the only char', function () {
            expect([/[a]/, 'a'], 'to be rewritten to', new RegExp("[]"));
        });

        it('should remove the only char in \\u... syntax', function () {
            expect([/[\u0061]/, 'a'], 'to be rewritten to', new RegExp("[]"));
        });

        it('should remove single matching char, \\u syntax', function () {
            expect([/[\u0061]/, 'a'], 'to be rewritten to', new RegExp("[]"));
        });

        it('should remove single matching char, \\x syntax', function () {
            expect([/[\x61]/, 'a'], 'to be rewritten to', new RegExp("[]"));
        });

        it('should remove single non-matching char', function () {
            expect([/[a]/, 'b'], 'to be rewritten to', /[a]/);
        });

        it('should remove single non-matching char, \\x syntax', function () {
            expect([/[\x61]/, 'b'], 'to be rewritten to', /[a]/);
        });

        it('should remove multiple chars, remove first', function () {
            expect([/[abc]/, 'a'], 'to be rewritten to', /[bc]/);
        });

        it('should remove multiple chars, remove first, \\u syntax', function () {
            expect([/[\u0061\u0062\u0063]/, 'a'], 'to be rewritten to', /[bc]/);
        });

        it('should remove multiple chars, remove first, \\x syntax', function () {
            expect([/[\x61\x62\x63]/, 'a'], 'to be rewritten to', /[bc]/);
        });

        it('should remove multiple chars, remove second', function () {
            expect([/[abc]/, 'b'], 'to be rewritten to', /[ac]/);
        });

        it('should remove multiple chars, remove second, \\u syntax', function () {
            expect([/[\u0061\u0062\u0063]/, 'b'], 'to be rewritten to', /[ac]/);
        });

        it('should remove multiple chars, remove second, \\x syntax', function () {
            expect([/[\x61\x62\x63]/, 'b'], 'to be rewritten to', /[ac]/);
        });

        it('should remove single range, remove first char', function () {
            expect([/[a-z]/, 'a'], 'to be rewritten to', /[b-z]/);
        });

        it('should remove single range, remove first char, \\u syntax', function () {
            expect([/[\u0061-\u007a]/, 'a'], 'to be rewritten to', /[b-z]/);
        });

        it('should remove single range, remove first char, \\x syntax', function () {
            expect([/[\x61-\x7a]/, 'a'], 'to be rewritten to', /[b-z]/);
        });

        it('should remove single range, remove second char', function () {
            expect([/[a-z]/, 'b'], 'to be rewritten to', /[ac-z]/);
        });

        it('should remove single range, remove second char, \\u syntax', function () {
            expect([/[\u0061-\u007a]/, 'b'], 'to be rewritten to', /[ac-z]/);
        });

        it('should remove single range, remove second char, \\x syntax', function () {
            expect([/[\x61-\x7a]/, 'b'], 'to be rewritten to', /[ac-z]/);
        });

        it('should remove single range, remove last char but one', function () {
            expect([/[a-z]/, 'y'], 'to be rewritten to', /[a-xz]/);
        });

        it('should remove single range, remove last char but one, \\u syntax', function () {
            expect([/[\u0061-\u007a]/, 'y'], 'to be rewritten to', /[a-xz]/);
        });

        it('should remove single range, remove last char but one, \\x syntax', function () {
            expect([/[\x61-\x7a]/, 'y'], 'to be rewritten to', /[a-xz]/);
        });

        it('should remove single range, remove last char', function () {
            expect([/[a-z]/, 'z'], 'to be rewritten to', /[a-y]/);
        });

        it('should remove single range, remove last char, \\u syntax', function () {
            expect([/[\u0061-\u007a]/, 'z'], 'to be rewritten to', /[a-y]/);
        });

        it('should remove single range, remove last char, \\x syntax', function () {
            expect([/[\x61-\x7a]/, 'z'], 'to be rewritten to', /[a-y]/);
        });

        it('should remove multiple ranges, remove first char', function () {
            expect([/[0-9a-z]/, 'a'], 'to be rewritten to', /[0-9b-z]/);
        });

        it('should remove multiple ranges, remove second char', function () {
            expect([/[0-9a-z]/, 'b'], 'to be rewritten to', /[0-9ac-z]/);
        });

        it('should remove multiple ranges, remove last char but one', function () {
            expect([/[0-9a-z]/, 'y'], 'to be rewritten to', /[0-9a-xz]/);
        });

        it('should remove multiple ranges, remove last char', function () {
            expect([/[0-9a-z]/, 'z'], 'to be rewritten to', /[0-9a-y]/)
        });
    });
});
<commit_msg>Added a couple of very basic tests of the regexps.<commit_after>/*global describe,it*/

var unexpected = require('unexpected');
    unicodeRegExp = require('../lib/unicodeRegExp');

describe('unicodeRegExp', function () {
    var expect = unexpected.clone();

    expect.addAssertion('[not] to match all characters in', function (value) {
        for (var i = 0 ; i < value.length ; i += 1) {
            this.assert(this.obj.test(value.charAt(i)));
        }
    });

    describe('.letter', function () {
        it('should accept all Danish characters', function () {
            expect(unicodeRegExp.letter, 'to match all characters in', 'abcdefghijklmnopqrstuvwxyzæøå');
        });

        it('should reject numbers', function () {
            expect(unicodeRegExp.letter, 'not to match all characters in', '123456789');
        });
    });

    describe('.number', function () {
        it('should accept all Arabic numbers', function () {
            expect(unicodeRegExp.number, 'to match all characters in', '123456789');
        });

        it('should reject all Danish characters', function () {
            expect(unicodeRegExp.number, 'not to match all characters in', 'abcdefghijklmnopqrstuvwxyzæøå');
        });
    });

    describe('#removeCharacterFromCharacterClassRegExp()', function () {
        expect.addAssertion('[not] to be rewritten to', function (value) {
            this.assert(unicodeRegExp.removeCharacterFromCharacterClassRegExp(this.obj[0], this.obj[1]), 'to equal', value);
        });

        it('should handle an empty character class', function () {
            expect([new RegExp('[]'), 'a'], 'to be rewritten to', new RegExp("[]"));
        });

        it('should remove the only char', function () {
            expect([/[a]/, 'a'], 'to be rewritten to', new RegExp("[]"));
        });

        it('should remove the only char in \\u... syntax', function () {
            expect([/[\u0061]/, 'a'], 'to be rewritten to', new RegExp("[]"));
        });

        it('should remove single matching char, \\u syntax', function () {
            expect([/[\u0061]/, 'a'], 'to be rewritten to', new RegExp("[]"));
        });

        it('should remove single matching char, \\x syntax', function () {
            expect([/[\x61]/, 'a'], 'to be rewritten to', new RegExp("[]"));
        });

        it('should remove single non-matching char', function () {
            expect([/[a]/, 'b'], 'to be rewritten to', /[a]/);
        });

        it('should remove single non-matching char, \\x syntax', function () {
            expect([/[\x61]/, 'b'], 'to be rewritten to', /[a]/);
        });

        it('should remove multiple chars, remove first', function () {
            expect([/[abc]/, 'a'], 'to be rewritten to', /[bc]/);
        });

        it('should remove multiple chars, remove first, \\u syntax', function () {
            expect([/[\u0061\u0062\u0063]/, 'a'], 'to be rewritten to', /[bc]/);
        });

        it('should remove multiple chars, remove first, \\x syntax', function () {
            expect([/[\x61\x62\x63]/, 'a'], 'to be rewritten to', /[bc]/);
        });

        it('should remove multiple chars, remove second', function () {
            expect([/[abc]/, 'b'], 'to be rewritten to', /[ac]/);
        });

        it('should remove multiple chars, remove second, \\u syntax', function () {
            expect([/[\u0061\u0062\u0063]/, 'b'], 'to be rewritten to', /[ac]/);
        });

        it('should remove multiple chars, remove second, \\x syntax', function () {
            expect([/[\x61\x62\x63]/, 'b'], 'to be rewritten to', /[ac]/);
        });

        it('should remove single range, remove first char', function () {
            expect([/[a-z]/, 'a'], 'to be rewritten to', /[b-z]/);
        });

        it('should remove single range, remove first char, \\u syntax', function () {
            expect([/[\u0061-\u007a]/, 'a'], 'to be rewritten to', /[b-z]/);
        });

        it('should remove single range, remove first char, \\x syntax', function () {
            expect([/[\x61-\x7a]/, 'a'], 'to be rewritten to', /[b-z]/);
        });

        it('should remove single range, remove second char', function () {
            expect([/[a-z]/, 'b'], 'to be rewritten to', /[ac-z]/);
        });

        it('should remove single range, remove second char, \\u syntax', function () {
            expect([/[\u0061-\u007a]/, 'b'], 'to be rewritten to', /[ac-z]/);
        });

        it('should remove single range, remove second char, \\x syntax', function () {
            expect([/[\x61-\x7a]/, 'b'], 'to be rewritten to', /[ac-z]/);
        });

        it('should remove single range, remove last char but one', function () {
            expect([/[a-z]/, 'y'], 'to be rewritten to', /[a-xz]/);
        });

        it('should remove single range, remove last char but one, \\u syntax', function () {
            expect([/[\u0061-\u007a]/, 'y'], 'to be rewritten to', /[a-xz]/);
        });

        it('should remove single range, remove last char but one, \\x syntax', function () {
            expect([/[\x61-\x7a]/, 'y'], 'to be rewritten to', /[a-xz]/);
        });

        it('should remove single range, remove last char', function () {
            expect([/[a-z]/, 'z'], 'to be rewritten to', /[a-y]/);
        });

        it('should remove single range, remove last char, \\u syntax', function () {
            expect([/[\u0061-\u007a]/, 'z'], 'to be rewritten to', /[a-y]/);
        });

        it('should remove single range, remove last char, \\x syntax', function () {
            expect([/[\x61-\x7a]/, 'z'], 'to be rewritten to', /[a-y]/);
        });

        it('should remove multiple ranges, remove first char', function () {
            expect([/[0-9a-z]/, 'a'], 'to be rewritten to', /[0-9b-z]/);
        });

        it('should remove multiple ranges, remove second char', function () {
            expect([/[0-9a-z]/, 'b'], 'to be rewritten to', /[0-9ac-z]/);
        });

        it('should remove multiple ranges, remove last char but one', function () {
            expect([/[0-9a-z]/, 'y'], 'to be rewritten to', /[0-9a-xz]/);
        });

        it('should remove multiple ranges, remove last char', function () {
            expect([/[0-9a-z]/, 'z'], 'to be rewritten to', /[0-9a-y]/)
        });
    });
});
<|endoftext|>


<commit_before>var methodsArray = [save, selectLabel, panTool];

function save() {
    alert("Impement save");
}

function panTool() {
    alert("Implement pan tool");
}

function selectLabel() {
    alert("Implement select label");
}

function render(dom) {
    methodsArray.forEach((method) => {
        console.log(method.name)
    dom
        .getElementsByClassName(method.name)[0]
        .addEventListener('click', method);
})
    ;
}

// Uncomment before the deployment in Yandex.Toloka
/*
 exports.Task = extend(TolokaHandlebarsTask, function (options) {
 TolokaHandlebarsTask.call(this, options);
 }, {

 // Add listener to each button based on its class on start
 // appropriate class for each button should be added in html
 onRender: function() { render(this.getDOMElement()); },
 onDestroy: function () {
 //

 }
 });
 */

function extend(ParentClass, constructorFunction, prototypeHash) {
    constructorFunction = constructorFunction || function () {
        };
    prototypeHash = prototypeHash || {};
    if (ParentClass) {
        constructorFunction.prototype = Object.create(ParentClass.prototype);
    }
    for (var i in prototypeHash) {
        constructorFunction.prototype[i] = prototypeHash[i];
    }
    return constructorFunction;
}

// request data from JSON file
function loadJSON(callback) {
    var xobj = new XMLHttpRequest();
    xobj.overrideMimeType("application/json");
    xobj.open('GET', 'https://rawgit.com/innosoft-pro/label-them/LT-116/front/json/classesandparameters.json', true);
    xobj.onreadystatechange = function () {
        if (xobj.readyState == 4 && xobj.status == "200") {

            // .open will NOT return a value but simply returns undefined in async mode so use a callback
            callback(xobj.responseText);

        }
    };
    xobj.send(null);
}

// Generate HTML code for classes and parameters described in json/classesandparameters.json
// Adds this HTML code to div with id="classes-and-parameters" in main.html
function generateHTMLCodeForClassesAndParameters(dom) {
    // Call to function with anonymous callback
    loadJSON(function (response) {
        jsonresponse = JSON.parse(response);

        var html = [];

        var generalClassesNameTemplate = [];
        var classes = [];
        var parameters = [];

        generalClassesNameTemplate.push('
');
        generalClassesNameTemplate.push(jsonresponse.generalClassesName);
        generalClassesNameTemplate.push(' Type');
        generalClassesNameTemplate.push('
');
        generalClassesNameTemplate = generalClassesNameTemplate.join("");

        classes.push("
");
        classes.push("<button class=\"btn btn-default dropdown-toggle\" type=\"button\" ");
        classes.push("id=\"dropdownMenu-Classes\" ");
        classes.push("data-toggle=\"dropdown\" aria-haspopup=\"true\" aria-expanded=\"true\">");
        classes.push(jsonresponse.generalClassesName);
        classes.push(' Type');
        classes.push("");
        classes.push("</button>");
        classes.push("
");

        jsonresponse.classes.forEach(function (obj) {
            classes.push("
");
            classes.push(obj);
            classes.push("
");
        });

        classes.push("
");
        classes.push("
");
        classes = classes.join("");

        if (jsonresponse.parameters !== null) {
            var dropdownMenusCount = 0;
            var inputGroupsCount = 0;
            parameters.push('<form>');
            jsonresponse.parameters.forEach(function (obj) {
                if (obj.type === "checkbox") {
                    parameters.push("
");
                    parameters.push("<input type=\"checkbox\" value=\"\">");
                    parameters.push(obj.name);
                    parameters.push("");
                    parameters.push("
");
                } else if (obj.type === "input-group") {
                    inputGroupsCount++;
                    parameters.push("
");
                    parameters.push("");
                    parameters.push(obj.placeholder);
                    parameters.push("");
                    parameters.push("<input type=\"text\" class=\"form-control\" placeholder=\"");
                    parameters.push(obj.name);
                    parameters.push("\" aria-describedby=\"basic-addon");
                    parameters.push(inputGroupsCount);
                    parameters.push("\">");
                    parameters.push("
");
                } else if (obj.type === "dropdown-menu") {
                    dropdownMenusCount++;
                    parameters.push('
');
                    parameters.push(obj.name);
                    parameters.push('
');
                    parameters.push("
");
                    parameters.push("<button class=\"btn btn-default dropdown-toggle\" type=\"button\" ");
                    parameters.push("id=\"dropdownMenu-parameters");
                    parameters.push(dropdownMenusCount);
                    parameters.push("\" ");
                    parameters.push("data-toggle=\"dropdown\" aria-haspopup=\"true\" aria-expanded=\"true\">");
                    parameters.push(obj.name);
                    parameters.push("");
                    parameters.push("</button>");
                    parameters.push("
");

                    obj.menuItems.forEach(function (obj2) {
                        parameters.push("
");
                        parameters.push(obj2);
                        parameters.push("
");
                    });

                    parameters.push("
");
                    parameters.push("
");
                }
            });
            parameters.push('</form>');
            parameters = parameters.join("");
        }

        html.push(generalClassesNameTemplate);
        html.push(classes);
        html.push(parameters);

        html = html.join("");

        dom.getElementById('classes-and-parameters').innerHTML += html;
    });
}<commit_msg>LT-65 fixed no-use-before-define issue<commit_after>function save() {
    alert("Impement save");
}

function panTool() {
    alert("Implement pan tool");
}

function selectLabel() {
    alert("Implement select label");
}

var methodsArray = [save, selectLabel, panTool];

function render(dom) {
    methodsArray.forEach((method) => {
        console.log(method.name)
    dom
        .getElementsByClassName(method.name)[0]
        .addEventListener('click', method);
})
    ;
}

// Uncomment before the deployment in Yandex.Toloka
/*
 exports.Task = extend(TolokaHandlebarsTask, function (options) {
 TolokaHandlebarsTask.call(this, options);
 }, {

 // Add listener to each button based on its class on start
 // appropriate class for each button should be added in html
 onRender: function() { render(this.getDOMElement()); },
 onDestroy: function () {
 //

 }
 });
 */

function extend(ParentClass, constructorFunction, prototypeHash) {
    constructorFunction = constructorFunction || function () {
        };
    prototypeHash = prototypeHash || {};
    if (ParentClass) {
        constructorFunction.prototype = Object.create(ParentClass.prototype);
    }
    for (var i in prototypeHash) {
        constructorFunction.prototype[i] = prototypeHash[i];
    }
    return constructorFunction;
}

// request data from JSON file
function loadJSON(callback) {
    var xobj = new XMLHttpRequest();
    xobj.overrideMimeType("application/json");
    xobj.open('GET', 'https://rawgit.com/innosoft-pro/label-them/LT-116/front/json/classesandparameters.json', true);
    xobj.onreadystatechange = function () {
        if (xobj.readyState == 4 && xobj.status == "200") {

            // .open will NOT return a value but simply returns undefined in async mode so use a callback
            callback(xobj.responseText);

        }
    };
    xobj.send(null);
}

// Generate HTML code for classes and parameters described in json/classesandparameters.json
// Adds this HTML code to div with id="classes-and-parameters" in main.html
function generateHTMLCodeForClassesAndParameters(dom) {
    // Call to function with anonymous callback
    loadJSON(function (response) {
        jsonresponse = JSON.parse(response);

        var html = [];

        var generalClassesNameTemplate = [];
        var classes = [];
        var parameters = [];

        generalClassesNameTemplate.push('
');
        generalClassesNameTemplate.push(jsonresponse.generalClassesName);
        generalClassesNameTemplate.push(' Type');
        generalClassesNameTemplate.push('
');
        generalClassesNameTemplate = generalClassesNameTemplate.join("");

        classes.push("
");
        classes.push("<button class=\"btn btn-default dropdown-toggle\" type=\"button\" ");
        classes.push("id=\"dropdownMenu-Classes\" ");
        classes.push("data-toggle=\"dropdown\" aria-haspopup=\"true\" aria-expanded=\"true\">");
        classes.push(jsonresponse.generalClassesName);
        classes.push(' Type');
        classes.push("");
        classes.push("</button>");
        classes.push("
");

        jsonresponse.classes.forEach(function (obj) {
            classes.push("
");
            classes.push(obj);
            classes.push("
");
        });

        classes.push("
");
        classes.push("
");
        classes = classes.join("");

        if (jsonresponse.parameters !== null) {
            var dropdownMenusCount = 0;
            var inputGroupsCount = 0;
            parameters.push('<form>');
            jsonresponse.parameters.forEach(function (obj) {
                if (obj.type === "checkbox") {
                    parameters.push("
");
                    parameters.push("<input type=\"checkbox\" value=\"\">");
                    parameters.push(obj.name);
                    parameters.push("");
                    parameters.push("
");
                } else if (obj.type === "input-group") {
                    inputGroupsCount++;
                    parameters.push("
");
                    parameters.push("");
                    parameters.push(obj.placeholder);
                    parameters.push("");
                    parameters.push("<input type=\"text\" class=\"form-control\" placeholder=\"");
                    parameters.push(obj.name);
                    parameters.push("\" aria-describedby=\"basic-addon");
                    parameters.push(inputGroupsCount);
                    parameters.push("\">");
                    parameters.push("
");
                } else if (obj.type === "dropdown-menu") {
                    dropdownMenusCount++;
                    parameters.push('
');
                    parameters.push(obj.name);
                    parameters.push('
');
                    parameters.push("
");
                    parameters.push("<button class=\"btn btn-default dropdown-toggle\" type=\"button\" ");
                    parameters.push("id=\"dropdownMenu-parameters");
                    parameters.push(dropdownMenusCount);
                    parameters.push("\" ");
                    parameters.push("data-toggle=\"dropdown\" aria-haspopup=\"true\" aria-expanded=\"true\">");
                    parameters.push(obj.name);
                    parameters.push("");
                    parameters.push("</button>");
                    parameters.push("
");

                    obj.menuItems.forEach(function (obj2) {
                        parameters.push("
");
                        parameters.push(obj2);
                        parameters.push("
");
                    });

                    parameters.push("
");
                    parameters.push("
");
                }
            });
            parameters.push('</form>');
            parameters = parameters.join("");
        }

        html.push(generalClassesNameTemplate);
        html.push(classes);
        html.push(parameters);

        html = html.join("");

        dom.getElementById('classes-and-parameters').innerHTML += html;
    });
}<|endoftext|>