<commit_before>/*
Input Mask plugin for jquery
http://github.com/RobinHerbots/jquery.inputmask
Copyright (c) 2010 Robin Herbots
Licensed under the MIT license (http://www.opensource.org/licenses/mit-license.php)
Version: 0.0.8

This plugin is based on the masked input plugin written by Josh Bush (digitalbush.com)
*/

(function($) {

    $.fn.inputmask = function(fn, options) {
        //options default
        var defaults = {
            placeholder: "_",
            mask: null,
            onComplete: null,
            repeat: 0, //repetitions of the mask
            greedy: true, //true: allocated buffer for all mask repetitions - false: allocate only if needed
            definitions: {
                '9': {
                    "validator": "[0-9]",
                    "cardinality": 1,
                    'prevalidator': null
                },
                'a': {
                    "validator": "[A-Za-z]",
                    "cardinality": 1,
                    "prevalidator": null
                },
                '*': {
                    "validator": "[A-Za-z0-9]",
                    "cardinality": 1,
                    "prevalidator": null
                },
                'd': { //day
                    "validator": "0[1-9]|[12][0-9]|3[01]",
                    "cardinality": 2,
                    "prevalidator": [{ "validator": "[0-3]", "cardinality": 1}]
                },
                'm': { //month
                    "validator": "0[1-9]|1[012]",
                    "cardinality": 2,
                    "prevalidator": [{ "validator": "[01]", "cardinality": 1}]
                },
                'y': { //year
                    "validator": "(19|20)\\d\\d",
                    "cardinality": 4,
                    "prevalidator": [
                        { "validator": "[12]", "cardinality": 1 },
                        { "validator": "(19|20)", "cardinality": 2 },
                        { "validator": "(19|20)\\d", "cardinality": 3 }
                        ]
                }
            },
            keyCode: { ALT: 18, BACKSPACE: 8, CAPS_LOCK: 20, COMMA: 188, COMMAND: 91, COMMAND_LEFT: 91, COMMAND_RIGHT: 93, CONTROL: 17, DELETE: 46, DOWN: 40, END: 35, ENTER: 13, ESCAPE: 27, HOME: 36, INSERT: 45, LEFT: 37, MENU: 93, NUMPAD_ADD: 107, NUMPAD_DECIMAL: 110, NUMPAD_DIVIDE: 111, NUMPAD_ENTER: 108,
                NUMPAD_MULTIPLY: 106, NUMPAD_SUBTRACT: 109, PAGE_DOWN: 34, PAGE_UP: 33, PERIOD: 190, RIGHT: 39, SHIFT: 16, SPACE: 32, TAB: 9, UP: 38, WINDOWS: 91
            }
        };

        var opts = $.extend({}, defaults, options);

        if (typeof fn == "string") {
            if (fn == 'mask') {
                //init buffer
                var _buffer = getMaskTemplate();
                var pasteEventName = $.browser.msie ? 'paste' : 'input';
                var iPhone = (window.orientation != undefined);
                var tests = getTestingChain();

                return this.each(function() {
                    mask($(this));
                });
            } else if (fn == 'unmaskedvalue') {
                var el = $(this);
                var tests = el.data('tests');
                var _buffer = el.data('_buffer');
                return unmaskedvalue(el);
            } else if (fn == 'setvalue') {
                var el = $(this);
                var tests = el.data('tests');
                var _buffer = el.data('_buffer');
                setvalue(el, options); //options in this case the value
            }
            else { //maybe fn is a mask so we try
                //set mask
                opts.mask = fn;

                //init buffer
                var _buffer = getMaskTemplate();
                var pasteEventName = $.browser.msie ? 'paste' : 'input';
                var iPhone = (window.orientation != undefined);
                var tests = getTestingChain();

                return this.each(function() {
                    mask($(this));
                });
            }
        } if (typeof fn == "object") {
            opts = $.extend({}, defaults, fn);

            //init buffer
            var _buffer = getMaskTemplate();
            var pasteEventName = $.browser.msie ? 'paste' : 'input';
            var iPhone = (window.orientation != undefined);
            var tests = getTestingChain();

            return this.each(function() {
                mask($(this));
            });
        }

        //helper functions
        function getMaskTemplate() {
            var singleMask = $.map(opts.mask.split(""), function(element, index) {
                var outElem = [];
                var maskdef = opts.definitions[element];
                if (maskdef) {
                    for (i = 0; i < maskdef.cardinality; i++) {
                        outElem.push(opts.placeholder);
                    }
                } else outElem.push(element);

                return outElem;
            });

            //allocate repetitions
            var repeatedMask = singleMask.slice();
            for (var i = 0; i < opts.repeat && opts.greedy; i++) {
                repeatedMask = repeatedMask.concat(singleMask.slice());
            }
            return repeatedMask;
        }

        function getTestingChain() {
            return $.map(opts.mask.split(""), function(element, index) {
                var outElem = [];
                var maskdef = opts.definitions[element];
                if (maskdef) {
                    for (i = 1; i < maskdef.cardinality; i++) {
                        var prevalidator = maskdef.prevalidator[i - 1];
                        outElem.push([new RegExp(prevalidator.validator), prevalidator.cardinality]);
                    }
                    outElem.push([new RegExp(maskdef.validator), maskdef.cardinality]);
                } else outElem.push(null);

                return outElem;
            });
        }

        function isValid(pos, c, buffer) {
            var testPos = determineTestPosition(pos);

            var loopend = 0;
            if (c) { loopend = 1; ; }

            var chrs = '';
            for (var i = tests[testPos][1]; i > loopend; i--) {
                chrs += getBufferElement(buffer, testPos - (i - 1));
            }

            if (c) { chrs += c; }

            return tests[testPos][0].test(chrs);
        }

        function isMask(pos) {
            return tests[determineTestPosition(pos)];
        }

        function determineTestPosition(pos) {
            return pos % tests.length;
        }

        function getMaskLength() {
            var calculatedLength = _buffer.length;
            if (!opts.greedy) {
                calculatedLength += (_buffer.length * opts.repeat)
            }
            return calculatedLength;
        }

        function seekNext(pos) {
            while (++pos <= getMaskLength() && !isMask(pos));
            return pos;
        }
        //these are needed to handle the non-greedy mask repetitions
        function setBufferElement(buffer, position, element) {
            while (buffer.length <= position && buffer.length < getMaskLength()) {
                $.merge(buffer, _buffer);
            }
            buffer[position] = element;
        }
        function getBufferElement(buffer, position) {
            while (buffer.length <= position && buffer.length < getMaskLength()) {
                $.merge(buffer, _buffer);
            }
            return buffer[position];
        }

        function writeBuffer(input, buffer) { return input.val(buffer.join('')).val(); };
        function clearBuffer(buffer, start, end) {
            for (var i = start; i < end && i < getMaskLength(); i++) {
                setBufferElement(buffer, i, getBufferElement(_buffer.slice(), i));
            }
        };

        function checkVal(input, buffer, clearInvalid) {
            var inputValue = input.val().replace(new RegExp(_buffer.join('') + "$"), "");
            clearBuffer(buffer, 0, buffer.length);
            buffer.length = _buffer.length; //reset the buffer to its original size
            var lastMatch = -1;
            for (var i = 0; i < inputValue.length; i++) {
                for (var pos = lastMatch + 1; pos < getMaskLength(); pos++) {
                    if (isMask(pos)) {
                        if (isValid(pos, inputValue.charAt(i), buffer)) {
                            setBufferElement(buffer, pos, inputValue.charAt(i));
                            lastMatch = pos;
                        } else {
                            setBufferElement(buffer, pos, opts.placeholder);
                        }
                        break;
                    } else {   //nonmask
                        lastMatch++;
                    }
                }
            }
            if (clearInvalid) {
                writeBuffer(input, buffer);
            }
            return seekNext(lastMatch);
        }

        //functionality fn
        function setvalue(el, value) {
            el.val(value);
            if (tests) {
                var buffer = _buffer.slice();
                checkVal(el, buffer, true);
            }
        }

        function unmaskedvalue(el) {

            if (tests) {
                var buffer = _buffer.slice();
                checkVal(el, buffer, true);
                return $.map(el.val().split(""), function(element, index) {
                    return isMask(index) && element != getBufferElement(_buffer, index) ? element : null;
                }).join('');
            }
            else {
                return el.val();
            }
        }

        function mask(el) {
            var input = $(el);
            //store tests & original buffer in the input element - used to get the unmasked value
            input.data('tests', tests);
            input.data('_buffer', _buffer);

            //init buffer
            var buffer = _buffer.slice();
            var undoBuffer = input.val();
            var ignore = false;              //Variable for ignoring control keys

            //bind events
            if (!input.attr("readonly")) {
                input.bind("focus", function() {
                    input.addClass('focus');
                    undoBuffer = input.val();
                    var pos = checkVal(input, buffer, true);
                    setTimeout(function() {
                        if (pos >= _buffer.length)
                            caret(input, 0, pos);
                        else
                            caret(input, pos);
                    }, 0);
                }).bind("mouseenter", function() {
                    if (!input.hasClass('focus') && input.val().length == 0) {
                        buffer = _buffer.slice();
                        writeBuffer(input, buffer);
                    }
                }).bind("blur", function() {
                    input.removeClass('focus');
                    checkVal(input, buffer);
                    writeBuffer(input, buffer);
                    if (input.val() == _buffer.join('')) {
                        input.val('');
                    } else {
                        if (input.val() != undoBuffer)
                            input.change();
                    }
                }).bind("mouseleave", function() {
                    if (!input.hasClass('focus') && input.val() == _buffer.join(''))
                        input.val('');
                }).bind("keydown", keydownEvent
                ).bind("keypress", keypressEvent
                ).bind(pasteEventName, function() {
                    setTimeout(function() { caret(input, checkVal(input, buffer, true)); }, 0);
                });

            }

            checkVal(input, buffer);

            //private functions
            function shiftL(pos) {
                while (!isMask(pos) && --pos >= 0);
                for (var i = pos; i < getMaskLength(); i++) {
                    if (isMask(i)) {
                        setBufferElement(buffer, i, opts.placeholder);
                        var j = seekNext(i);
                        if (j < getMaskLength() && isValid(i, getBufferElement(buffer, j), buffer)) {
                            setBufferElement(buffer, i, getBufferElement(buffer, j));
                        } else
                            break;
                    }
                }
                writeBuffer(input, buffer);
                caret(input, pos);
            };

            function shiftR(pos) {
                for (var i = pos, c = opts.placeholder; i < getMaskLength(); i++) {
                    if (isMask(i)) {
                        var j = seekNext(i);
                        var t = getBufferElement(buffer, i);
                        setBufferElement(buffer, i, c);
                        if (j < getMaskLength() && isValid(j, t, buffer))
                            c = t;
                        else
                            break;
                    }
                }
            };

            function caret(input, begin, end) {
                if (input.length == 0) return;
                if (typeof begin == 'number') {
                    end = (typeof end == 'number') ? end : begin;
                    return input.each(function() {
                        if (this.setSelectionRange) {
                            this.focus();
                            this.setSelectionRange(begin, end);
                        } else if (this.createTextRange) {
                            var range = this.createTextRange();
                            range.collapse(true);
                            range.moveEnd('character', end);
                            range.moveStart('character', begin);
                            range.select();
                        }
                    });
                } else {
                    if (input[0].setSelectionRange) {
                        begin = input[0].selectionStart;
                        end = input[0].selectionEnd;
                    } else if (document.selection && document.selection.createRange) {
                        var range = document.selection.createRange();
                        begin = 0 - range.duplicate().moveStart('character', -100000);
                        end = begin + range.text.length;
                    }
                    return { begin: begin, end: end };
                }
            };

            function keydownEvent(e) {
                var pos = caret($(this));
                var k = e.keyCode;
                ignore = (k < 16 || (k > 16 && k < 32) || (k > 32 && k < 41));

                //delete selection before proceeding
                if ((pos.begin - pos.end) != 0 && (!ignore || k == opts.keyCode.BACKSPACE || k == opts.keyCode.DELETE))
                    clearBuffer(buffer, pos.begin, pos.end);

                //backspace, delete, and escape get special treatment
                if (k == opts.keyCode.BACKSPACE || k == opts.keyCode.DELETE || (iPhone && k == 127)) {//backspace/delete
                    shiftL(pos.begin + (k == opts.keyCode.DELETE ? 0 : -1));
                    return false;
                } else if (k == opts.keyCode.ESCAPE) {//escape
                    input.val(undoBuffer);
                    caret(input, 0, checkVal(input, buffer));
                    return false;
                }
            }

            function keypressEvent(e) {
                if (ignore) {
                    ignore = false;
                    //Fixes Mac FF bug on backspace
                    return (e.keyCode == opts.keyCode.BACKSPACE) ? false : null;
                }
                e = e || window.event;
                var k = e.charCode || e.keyCode || e.which;
                var pos = caret($(this));

                if (e.ctrlKey || e.altKey || e.metaKey) {//Ignore
                    return true;
                } else if ((k >= 32 && k <= 125) || k > 186) {//typeable characters
                    var p = seekNext(pos.begin - 1);
                    if (p < getMaskLength()) {
                        var c = String.fromCharCode(k);
                        if (isValid(p, c, buffer)) {
                            shiftR(p);
                            setBufferElement(buffer, p, c);
                            writeBuffer(input, buffer);
                            var next = seekNext(p);
                            caret($(this), next);
                            if (opts.onComplete && next == getMaskLength())
                                opts.onComplete.call(input);
                        }
                    }
                }
                return false;
            }

        }
    };

})(jQuery);<commit_msg>Make defaults configurable<commit_after>/*
Input Mask plugin for jquery
http://github.com/RobinHerbots/jquery.inputmask
Copyright (c) 2010 Robin Herbots
Licensed under the MIT license (http://www.opensource.org/licenses/mit-license.php)
Version: 0.0.9

This plugin is based on the masked input plugin written by Josh Bush (digitalbush.com)
*/

(function($) {
    $.inputmask = {
        //options default
        defaults: {
            placeholder: "_",
            mask: null,
            onComplete: null,
            repeat: 0, //repetitions of the mask
            greedy: true, //true: allocated buffer for all mask repetitions - false: allocate only if needed
            definitions: {
                '9': {
                    "validator": "[0-9]",
                    "cardinality": 1,
                    'prevalidator': null
                },
                'a': {
                    "validator": "[A-Za-z]",
                    "cardinality": 1,
                    "prevalidator": null
                },
                '*': {
                    "validator": "[A-Za-z0-9]",
                    "cardinality": 1,
                    "prevalidator": null
                },
                'd': { //day
                    "validator": "0[1-9]|[12][0-9]|3[01]",
                    "cardinality": 2,
                    "prevalidator": [{ "validator": "[0-3]", "cardinality": 1}]
                },
                'm': { //month
                    "validator": "0[1-9]|1[012]",
                    "cardinality": 2,
                    "prevalidator": [{ "validator": "[01]", "cardinality": 1}]
                },
                'y': { //year
                    "validator": "(19|20)\\d\\d",
                    "cardinality": 4,
                    "prevalidator": [
                        { "validator": "[12]", "cardinality": 1 },
                        { "validator": "(19|20)", "cardinality": 2 },
                        { "validator": "(19|20)\\d", "cardinality": 3 }
                        ]
                }
            },
            keyCode: { ALT: 18, BACKSPACE: 8, CAPS_LOCK: 20, COMMA: 188, COMMAND: 91, COMMAND_LEFT: 91, COMMAND_RIGHT: 93, CONTROL: 17, DELETE: 46, DOWN: 40, END: 35, ENTER: 13, ESCAPE: 27, HOME: 36, INSERT: 45, LEFT: 37, MENU: 93, NUMPAD_ADD: 107, NUMPAD_DECIMAL: 110, NUMPAD_DIVIDE: 111, NUMPAD_ENTER: 108,
                NUMPAD_MULTIPLY: 106, NUMPAD_SUBTRACT: 109, PAGE_DOWN: 34, PAGE_UP: 33, PERIOD: 190, RIGHT: 39, SHIFT: 16, SPACE: 32, TAB: 9, UP: 38, WINDOWS: 91
            }
        }
    };

    $.fn.inputmask = function(fn, options) {
        var opts = $.extend({}, $.inputmask.defaults, options);

        if (typeof fn == "string") {
            if (fn == 'mask') {
                //init buffer
                var _buffer = getMaskTemplate();
                var pasteEventName = $.browser.msie ? 'paste' : 'input';
                var iPhone = (window.orientation != undefined);
                var tests = getTestingChain();

                return this.each(function() {
                    mask($(this));
                });
            } else if (fn == 'unmaskedvalue') {
                var el = $(this);
                var tests = el.data('tests');
                var _buffer = el.data('_buffer');
                return unmaskedvalue(el);
            } else if (fn == 'setvalue') {
                var el = $(this);
                var tests = el.data('tests');
                var _buffer = el.data('_buffer');
                setvalue(el, options); //options in this case the value
            }
            else { //maybe fn is a mask so we try
                //set mask
                opts.mask = fn;

                //init buffer
                var _buffer = getMaskTemplate();
                var pasteEventName = $.browser.msie ? 'paste' : 'input';
                var iPhone = (window.orientation != undefined);
                var tests = getTestingChain();

                return this.each(function() {
                    mask($(this));
                });
            }
        } if (typeof fn == "object") {
            opts = $.extend({}, defaults, fn);

            //init buffer
            var _buffer = getMaskTemplate();
            var pasteEventName = $.browser.msie ? 'paste' : 'input';
            var iPhone = (window.orientation != undefined);
            var tests = getTestingChain();

            return this.each(function() {
                mask($(this));
            });
        }

        //helper functions
        function getMaskTemplate() {
            var singleMask = $.map(opts.mask.split(""), function(element, index) {
                var outElem = [];
                var maskdef = opts.definitions[element];
                if (maskdef) {
                    for (i = 0; i < maskdef.cardinality; i++) {
                        outElem.push(opts.placeholder);
                    }
                } else outElem.push(element);

                return outElem;
            });

            //allocate repetitions
            var repeatedMask = singleMask.slice();
            for (var i = 0; i < opts.repeat && opts.greedy; i++) {
                repeatedMask = repeatedMask.concat(singleMask.slice());
            }
            return repeatedMask;
        }

        function getTestingChain() {
            return $.map(opts.mask.split(""), function(element, index) {
                var outElem = [];
                var maskdef = opts.definitions[element];
                if (maskdef) {
                    for (i = 1; i < maskdef.cardinality; i++) {
                        var prevalidator = maskdef.prevalidator[i - 1];
                        outElem.push([new RegExp(prevalidator.validator), prevalidator.cardinality]);
                    }
                    outElem.push([new RegExp(maskdef.validator), maskdef.cardinality]);
                } else outElem.push(null);

                return outElem;
            });
        }

        function isValid(pos, c, buffer) {
            var testPos = determineTestPosition(pos);

            var loopend = 0;
            if (c) { loopend = 1; ; }

            var chrs = '';
            for (var i = tests[testPos][1]; i > loopend; i--) {
                chrs += getBufferElement(buffer, testPos - (i - 1));
            }

            if (c) { chrs += c; }

            return tests[testPos][0].test(chrs);
        }

        function isMask(pos) {
            return tests[determineTestPosition(pos)];
        }

        function determineTestPosition(pos) {
            return pos % tests.length;
        }

        function getMaskLength() {
            var calculatedLength = _buffer.length;
            if (!opts.greedy) {
                calculatedLength += (_buffer.length * opts.repeat)
            }
            return calculatedLength;
        }

        function seekNext(pos) {
            while (++pos <= getMaskLength() && !isMask(pos));
            return pos;
        }
        //these are needed to handle the non-greedy mask repetitions
        function setBufferElement(buffer, position, element) {
            while (buffer.length <= position && buffer.length < getMaskLength()) {
                $.merge(buffer, _buffer);
            }
            buffer[position] = element;
        }
        function getBufferElement(buffer, position) {
            while (buffer.length <= position && buffer.length < getMaskLength()) {
                $.merge(buffer, _buffer);
            }
            return buffer[position];
        }

        function writeBuffer(input, buffer) { return input.val(buffer.join('')).val(); };
        function clearBuffer(buffer, start, end) {
            for (var i = start; i < end && i < getMaskLength(); i++) {
                setBufferElement(buffer, i, getBufferElement(_buffer.slice(), i));
            }
        };

        function checkVal(input, buffer, clearInvalid) {
            var inputValue = input.val().replace(new RegExp(_buffer.join('') + "$"), "");
            clearBuffer(buffer, 0, buffer.length);
            buffer.length = _buffer.length; //reset the buffer to its original size
            var lastMatch = -1;
            for (var i = 0; i < inputValue.length; i++) {
                for (var pos = lastMatch + 1; pos < getMaskLength(); pos++) {
                    if (isMask(pos)) {
                        if (isValid(pos, inputValue.charAt(i), buffer)) {
                            setBufferElement(buffer, pos, inputValue.charAt(i));
                            lastMatch = pos;
                        } else {
                            setBufferElement(buffer, pos, opts.placeholder);
                        }
                        break;
                    } else {   //nonmask
                        lastMatch++;
                    }
                }
            }
            if (clearInvalid) {
                writeBuffer(input, buffer);
            }
            return seekNext(lastMatch);
        }

        //functionality fn
        function setvalue(el, value) {
            el.val(value);
            if (tests) {
                var buffer = _buffer.slice();
                checkVal(el, buffer, true);
            }
        }

        function unmaskedvalue(el) {

            if (tests) {
                var buffer = _buffer.slice();
                checkVal(el, buffer, true);
                return $.map(el.val().split(""), function(element, index) {
                    return isMask(index) && element != getBufferElement(_buffer, index) ? element : null;
                }).join('');
            }
            else {
                return el.val();
            }
        }

        function mask(el) {
            var input = $(el);
            //store tests & original buffer in the input element - used to get the unmasked value
            input.data('tests', tests);
            input.data('_buffer', _buffer);

            //init buffer
            var buffer = _buffer.slice();
            var undoBuffer = input.val();
            var ignore = false;              //Variable for ignoring control keys

            //bind events
            if (!input.attr("readonly")) {
                input.bind("focus", function() {
                    input.addClass('focus');
                    undoBuffer = input.val();
                    var pos = checkVal(input, buffer, true);
                    setTimeout(function() {
                        if (pos >= _buffer.length)
                            caret(input, 0, pos);
                        else
                            caret(input, pos);
                    }, 0);
                }).bind("mouseenter", function() {
                    if (!input.hasClass('focus') && input.val().length == 0) {
                        buffer = _buffer.slice();
                        writeBuffer(input, buffer);
                    }
                }).bind("blur", function() {
                    input.removeClass('focus');
                    checkVal(input, buffer);
                    writeBuffer(input, buffer);
                    if (input.val() == _buffer.join('')) {
                        input.val('');
                    } else {
                        if (input.val() != undoBuffer)
                            input.change();
                    }
                }).bind("mouseleave", function() {
                    if (!input.hasClass('focus') && input.val() == _buffer.join(''))
                        input.val('');
                }).bind("keydown", keydownEvent
                ).bind("keypress", keypressEvent
                ).bind(pasteEventName, function() {
                    setTimeout(function() { caret(input, checkVal(input, buffer, true)); }, 0);
                });

            }

            checkVal(input, buffer);

            //private functions
            function shiftL(pos) {
                while (!isMask(pos) && --pos >= 0);
                for (var i = pos; i < getMaskLength(); i++) {
                    if (isMask(i)) {
                        setBufferElement(buffer, i, opts.placeholder);
                        var j = seekNext(i);
                        if (j < getMaskLength() && isValid(i, getBufferElement(buffer, j), buffer)) {
                            setBufferElement(buffer, i, getBufferElement(buffer, j));
                        } else
                            break;
                    }
                }
                writeBuffer(input, buffer);
                caret(input, pos);
            };

            function shiftR(pos) {
                for (var i = pos, c = opts.placeholder; i < getMaskLength(); i++) {
                    if (isMask(i)) {
                        var j = seekNext(i);
                        var t = getBufferElement(buffer, i);
                        setBufferElement(buffer, i, c);
                        if (j < getMaskLength() && isValid(j, t, buffer))
                            c = t;
                        else
                            break;
                    }
                }
            };

            function caret(input, begin, end) {
                if (input.length == 0) return;
                if (typeof begin == 'number') {
                    end = (typeof end == 'number') ? end : begin;
                    return input.each(function() {
                        if (this.setSelectionRange) {
                            this.focus();
                            this.setSelectionRange(begin, end);
                        } else if (this.createTextRange) {
                            var range = this.createTextRange();
                            range.collapse(true);
                            range.moveEnd('character', end);
                            range.moveStart('character', begin);
                            range.select();
                        }
                    });
                } else {
                    if (input[0].setSelectionRange) {
                        begin = input[0].selectionStart;
                        end = input[0].selectionEnd;
                    } else if (document.selection && document.selection.createRange) {
                        var range = document.selection.createRange();
                        begin = 0 - range.duplicate().moveStart('character', -100000);
                        end = begin + range.text.length;
                    }
                    return { begin: begin, end: end };
                }
            };

            function keydownEvent(e) {
                var pos = caret($(this));
                var k = e.keyCode;
                ignore = (k < 16 || (k > 16 && k < 32) || (k > 32 && k < 41));

                //delete selection before proceeding
                if ((pos.begin - pos.end) != 0 && (!ignore || k == opts.keyCode.BACKSPACE || k == opts.keyCode.DELETE))
                    clearBuffer(buffer, pos.begin, pos.end);

                //backspace, delete, and escape get special treatment
                if (k == opts.keyCode.BACKSPACE || k == opts.keyCode.DELETE || (iPhone && k == 127)) {//backspace/delete
                    shiftL(pos.begin + (k == opts.keyCode.DELETE ? 0 : -1));
                    return false;
                } else if (k == opts.keyCode.ESCAPE) {//escape
                    input.val(undoBuffer);
                    caret(input, 0, checkVal(input, buffer));
                    return false;
                }
            }

            function keypressEvent(e) {
                if (ignore) {
                    ignore = false;
                    //Fixes Mac FF bug on backspace
                    return (e.keyCode == opts.keyCode.BACKSPACE) ? false : null;
                }
                e = e || window.event;
                var k = e.charCode || e.keyCode || e.which;
                var pos = caret($(this));

                if (e.ctrlKey || e.altKey || e.metaKey) {//Ignore
                    return true;
                } else if ((k >= 32 && k <= 125) || k > 186) {//typeable characters
                    var p = seekNext(pos.begin - 1);
                    if (p < getMaskLength()) {
                        var c = String.fromCharCode(k);
                        if (isValid(p, c, buffer)) {
                            shiftR(p);
                            setBufferElement(buffer, p, c);
                            writeBuffer(input, buffer);
                            var next = seekNext(p);
                            caret($(this), next);
                            if (opts.onComplete && next == getMaskLength())
                                opts.onComplete.call(input);
                        }
                    }
                }
                return false;
            }

        }
    };

})(jQuery);<|endoftext|>


<commit_before>/*
 * client.js: Base client from which all AWS clients inherit from
 *
 * (C) 2012 Nodejitsu Inc.
 *
 */

var utile = require('utile'),
    request = require('request'),
    base = require('../core/base');

var Client = exports.Client = function (options) {
  base.Client.call(this, options);

  options = options || {};

  // Allow overriding serversUrl in child classes
  this.provider   = 'amazon';
  this.securityGroup = options.securityGroup;
  this.securityGroupId = options.securityGroupId;
  this.version = options.version || '2012-04-01';
  this.protocol = options.protocol || 'https://';
  this.serversUrl = options.serversUrl
    || this.serversUrl
    || 'ec2.amazonaws.com';

  if (!this.before) {
    this.before = [];
  }
};

utile.inherits(Client, base.Client);

Client.prototype._toArray = function toArray(obj) {
  if (typeof obj === 'undefined') {
    return [];
  }

  return Array.isArray(obj) ? obj : [obj];
};

Client.prototype.failCodes = {
  400: 'Bad Request',
  401: 'Unauthorized',
  403: 'Resize not allowed',
  404: 'Item not found',
  409: 'Build in progress',
  413: 'Over Limit',
  415: 'Bad Media Type',
  500: 'Fault',
  503: 'Service Unavailable'
};

Client.prototype.successCodes = {
  200: 'OK',
  201: 'Created',
  202: 'Accepted',
  203: 'Non-authoritative information',
  204: 'No content'
};
<commit_msg>[aws] support either key or accessKey<commit_after>/*
 * client.js: Base client from which all AWS clients inherit from
 *
 * (C) 2012 Nodejitsu Inc.
 *
 */

var utile = require('utile'),
    request = require('request'),
    base = require('../core/base');

var Client = exports.Client = function (options) {
  base.Client.call(this, options);

  options = options || {};

  // Allow overriding serversUrl in child classes
  this.provider   = 'amazon';
  this.securityGroup = options.securityGroup;
  this.securityGroupId = options.securityGroupId;
  this.version = options.version || '2012-04-01';
  this.protocol = options.protocol || 'https://';
  this.serversUrl = options.serversUrl
    || this.serversUrl
    || 'ec2.amazonaws.com';

  // support either key/accessKey syntax
  this.config.key = this.config.key || options.accessKey;
  this.config.keyId = this.config.keyId || options.accessKeyId;

  if (!this.before) {
    this.before = [];
  }
};

utile.inherits(Client, base.Client);

Client.prototype._toArray = function toArray(obj) {
  if (typeof obj === 'undefined') {
    return [];
  }

  return Array.isArray(obj) ? obj : [obj];
};

Client.prototype.failCodes = {
  400: 'Bad Request',
  401: 'Unauthorized',
  403: 'Resize not allowed',
  404: 'Item not found',
  409: 'Build in progress',
  413: 'Over Limit',
  415: 'Bad Media Type',
  500: 'Fault',
  503: 'Service Unavailable'
};

Client.prototype.successCodes = {
  200: 'OK',
  201: 'Created',
  202: 'Accepted',
  203: 'Non-authoritative information',
  204: 'No content'
};
<|endoftext|>


<commit_before>(function(angular) {

    angular.module('ng-polymer-elements', [])
    .constant('$ngPolymerMappings', {
    		mmDropdown: {
    			ngModel: {
    				primitive: 'value'
    			}
    		},
    		mmInput: {
    			ngModel: {
    				primitive: 'value'
    			}
    		}
    	})
    	.config(['$compileProvider', '$injector', function($compileProvider, $injector) {

    		'use strict';

    		// Each mapping is an object where the key is the directive/custom element
    	    // name in camel case and the value is an object where the keys are the
    	    // AngularJS attributes in camel case and the values are objects where the
    	    // key is the type which can be 'primitive', 'object', 'array' or 'event'
    	    // and the value is the name of the attribute in the web component.

    	    var inputMappings = {
    	        ngModel: {
    	            primitive: 'value'
    	        },
    	        ngDisabled: {
    	        	primitive: 'disabled'
    	        }
    	    };

    	    var selectorMappings = {
    	    	ngModel: {
    	    		primitive: 'selected'
    	    	}
    	    };

    	    var checkMappings = {
    	    	ngModel: {
    	    		primitive: 'checked'
    	    	},
    	        ngDisabled: {
    	        	primitive: 'disabled'
    	        }
    	    };

    	    var openableMappings = {
    	    	ngOpened: {
    	    		primitive: 'opened'
    	    	}
    	    };

    	    var allMappings = {
    	        paperInput: inputMappings,
    	        paperRadioGroup: selectorMappings,
    	        paperTabs: selectorMappings,
    	        coreSelector: selectorMappings,
    	        coreMenu: selectorMappings,
    	        paperCheckbox: checkMappings,
    	        paperToggleButton: checkMappings,
    	        coreOverlay: openableMappings,
    	        paperDialog: openableMappings,
    	        paperActionDialog: openableMappings,
    	        paperToast: openableMappings,
    	        paperSlider: inputMappings,
    	        coreList: {
    	            ngModel: {
    	                array: 'data'
    	            },
    	            ngTap: {
    	                event: 'core-activate'
    	            }
    	        }
    	    };

    		// Extension point for overriding mappings

    		if($injector.has('$ngPolymerMappings')) {
    			var extendedMappings = $injector.get('$ngPolymerMappings');
    			angular.extend(allMappings, extendedMappings);
    		}

		    // A directive is created for each web component according to the mappings

		    Object.keys(allMappings).forEach(function(tag) {
		        var mappings = allMappings[tag];

		        $compileProvider.directive(tag, ['$parse', '$window', function($parse, $window) {

		            var scopeDefinition = {};

		            var keys = Object.keys(mappings);

		            keys.forEach(function(attr) {

		                var conf = mappings[attr];

		                if(conf.primitive || conf.object || conf.array) {
		                    scopeDefinition[attr] = '=';
		                } else if(!conf.event) {
		                    throw 'Invalid mapping for ' + attr +
		                    ' - must contain primitive | object | array | event';
		                }
		            });

		            return {
		                restrict: 'E',
		                scope: scopeDefinition,

		                link: function (scope, element, attrs) {

		                    var el = element[0];

		                    keys.forEach(function(attr) {

		                    	// Don't create bindings for non-existent attributes
		                    	if(!attrs[attr]) {
		                    		return;
		                    	}

		                        var conf = mappings[attr];

		                        if(conf.event) {

		                        	var fn = $parse(attrs[attr]);

		                            el.addEventListener(conf.event, function (e) {
		                            	scope.$apply(function() {
		                            		fn(scope.$parent, {$event: e});
		                            	});

		                            });

		                        } else {

		                            var propertyName =
		                            	conf.primitive || conf.object || conf.array;

		                            if(conf.object) {
		                                el[propertyName] = {};
		                            } else if(conf.array) {
		                                el[propertyName] = [];
		                            }

		                            // Copy the scope property value to the web
		                            // component's value

		                            var handler = function(value) {
		                                if(conf.primitive) {
		                            		el[propertyName] = value;
		                                } else {
		                                    angular.copy(value, el[propertyName]);
		                                }
		                            };

		                            scope.$watch(attr, handler, true);

		                            handler(scope[attr]);

		                            // Copy the web component's value to the scope
		                            // property value

		                            var observer = new PathObserver(el, propertyName);

		                            observer.open(function (value) {
		                                scope.$apply(function () {
		                                    if(conf.primitive) {
		                                        scope[attr] = value;
		                                    } else {
		                                        angular.copy(value, scope[attr]);
		                                    }
		                                });
		                            });

		                        }

		                    });
		                }

		            };
		        }]);
		    });

    	}]);

})(angular);
<commit_msg>adds ngChange to mmDropdown and mmInput<commit_after>(function(angular) {

    angular.module('ng-polymer-elements', [])
    .constant('$ngPolymerMappings', {
    		mmDropdown: {
    			ngModel: {
    				primitive: 'value'
    			},
    			ngChange: {
    				event: 'changed'
    			}
    		},
    		mmInput: {
    			ngModel: {
    				primitive: 'value'
    			},
    			ngChange: {
    				event: 'changed'
    			}
    		}
    	})
    	.config(['$compileProvider', '$injector', function($compileProvider, $injector) {

    		'use strict';

    		// Each mapping is an object where the key is the directive/custom element
    	    // name in camel case and the value is an object where the keys are the
    	    // AngularJS attributes in camel case and the values are objects where the
    	    // key is the type which can be 'primitive', 'object', 'array' or 'event'
    	    // and the value is the name of the attribute in the web component.

    	    var inputMappings = {
    	        ngModel: {
    	            primitive: 'value'
    	        },
    	        ngDisabled: {
    	        	primitive: 'disabled'
    	        }
    	    };

    	    var selectorMappings = {
    	    	ngModel: {
    	    		primitive: 'selected'
    	    	}
    	    };

    	    var checkMappings = {
    	    	ngModel: {
    	    		primitive: 'checked'
    	    	},
    	        ngDisabled: {
    	        	primitive: 'disabled'
    	        }
    	    };

    	    var openableMappings = {
    	    	ngOpened: {
    	    		primitive: 'opened'
    	    	}
    	    };

    	    var allMappings = {
    	        paperInput: inputMappings,
    	        paperRadioGroup: selectorMappings,
    	        paperTabs: selectorMappings,
    	        coreSelector: selectorMappings,
    	        coreMenu: selectorMappings,
    	        paperCheckbox: checkMappings,
    	        paperToggleButton: checkMappings,
    	        coreOverlay: openableMappings,
    	        paperDialog: openableMappings,
    	        paperActionDialog: openableMappings,
    	        paperToast: openableMappings,
    	        paperSlider: inputMappings,
    	        coreList: {
    	            ngModel: {
    	                array: 'data'
    	            },
    	            ngTap: {
    	                event: 'core-activate'
    	            }
    	        }
    	    };

    		// Extension point for overriding mappings

    		if($injector.has('$ngPolymerMappings')) {
    			var extendedMappings = $injector.get('$ngPolymerMappings');
    			angular.extend(allMappings, extendedMappings);
    		}

		    // A directive is created for each web component according to the mappings

		    Object.keys(allMappings).forEach(function(tag) {
		        var mappings = allMappings[tag];

		        $compileProvider.directive(tag, ['$parse', '$window', function($parse, $window) {

		            var scopeDefinition = {};

		            var keys = Object.keys(mappings);

		            keys.forEach(function(attr) {

		                var conf = mappings[attr];

		                if(conf.primitive || conf.object || conf.array) {
		                    scopeDefinition[attr] = '=';
		                } else if(!conf.event) {
		                    throw 'Invalid mapping for ' + attr +
		                    ' - must contain primitive | object | array | event';
		                }
		            });

		            return {
		                restrict: 'E',
		                scope: scopeDefinition,

		                link: function (scope, element, attrs) {

		                    var el = element[0];

		                    keys.forEach(function(attr) {

		                    	// Don't create bindings for non-existent attributes
		                    	if(!attrs[attr]) {
		                    		return;
		                    	}

		                        var conf = mappings[attr];

		                        if(conf.event) {

		                        	var fn = $parse(attrs[attr]);

		                            el.addEventListener(conf.event, function (e) {
		                            	scope.$apply(function() {
		                            		fn(scope.$parent, {$event: e});
		                            	});

		                            });

		                        } else {

		                            var propertyName =
		                            	conf.primitive || conf.object || conf.array;

		                            if(conf.object) {
		                                el[propertyName] = {};
		                            } else if(conf.array) {
		                                el[propertyName] = [];
		                            }

		                            // Copy the scope property value to the web
		                            // component's value

		                            var handler = function(value) {
		                                if(conf.primitive) {
		                            		el[propertyName] = value;
		                                } else {
		                                    angular.copy(value, el[propertyName]);
		                                }
		                            };

		                            scope.$watch(attr, handler, true);

		                            handler(scope[attr]);

		                            // Copy the web component's value to the scope
		                            // property value

		                            var observer = new PathObserver(el, propertyName);

		                            observer.open(function (value) {
		                                scope.$apply(function () {
		                                    if(conf.primitive) {
		                                        scope[attr] = value;
		                                    } else {
		                                        angular.copy(value, scope[attr]);
		                                    }
		                                });
		                            });

		                        }

		                    });
		                }

		            };
		        }]);
		    });

    	}]);

})(angular);
<|endoftext|>


<commit_before>/*jslint browser: true, nomen: true */

(function (flow, $, _, ace, Backbone, Blob, d3, FileReader, girder, tangelo, URL) {
    "use strict";

   // The view for selecting, running, and editing analyses
    flow.AnalysisManagementView = Backbone.View.extend({
        formats: [
            'table:rows',
            'table:r.dataframe',
            'table:csv',
            'table:tsv',
            'tree:nested',
            'tree:r.apetree',
            'string:text',
            'number:number',
            'image:png.base64',
            'r:object'
        ],

        events: {
            'click #show-script': function () {
                var hide = d3.select("#show-script").classed("active");
                flow.setDisplay(hide ? "vis" : "editor");
                this.editor.resize();
                d3.select("#show-script-icon").classed("glyphicon-eye-open", hide);
                d3.select("#show-script-icon").classed("glyphicon-eye-close", !hide);
                d3.select("#show-script-text").text(hide ? "Show script" : "Hide script");
                if (this.analysis.get('collection').get('_accessLevel') > 0) {
                    d3.select("#edit").classed("hidden", hide);
                    d3.selectAll(".edit-controls").classed("hidden", !d3.select("#edit").classed("active") || hide);
                }
            },

            'click #edit': function () {
                var edit = d3.select("#edit").classed("active");
                this.editor.setReadOnly(edit);
                this.editor.renderer.$cursorLayer.element.style.opacity = edit ? 0 : 1;
                d3.selectAll(".edit-controls").classed("hidden", edit);
            },

            'change #mode': function () {
                if (this.analysis) {
                    this.analysis.get('meta').analysis.mode = $("#mode").val();
                    this.editor.getSession().setMode("ace/mode/" + this.analysis.get('meta').analysis.mode);
                }
            },

            'click #save': function () {
                if (this.analysis) {
                    this.analysis.get('meta').analysis.script = this.editor.getValue();
                    d3.json(girder.apiRoot + '/item/' + this.analysis.id + '/metadata').send('put', JSON.stringify(this.analysis.get('meta')), function () {
                        // Trigger recreating the analysis UI
                        $("#analysis").change();
                    });
                }
            },

            'change #analysis': function () {
                this.changeAnalysis(this.analyses.get($("#analysis").val()));
            },

            'click #setup': function () {
                if (this.analysis) {
                    this.analysisSetupView.model = this.analysis;
                    this.analysisSetupView.render();
                }
            },

            'click #analysis-new': function () {
                var analysis = {
                    name: $("#analysis-name").val(),
                    inputs: [],
                    outputs: [],
                    mode: "python",
                    script: ""
                };
                this.createAnalysis(analysis);
            },

            'click #analysis-download': function () {
                var blob = new Blob([JSON.stringify(this.analysis.get('meta').analysis, null, "    ")]),
                    filename = this.analysis.get('meta').analysis.name + '.json',
                    anchor = $('');
                anchor[0].click();
            },

            'change #analysis-files': function () {
                var files = $('#analysis-files')[0].files;
                _.each(files, function (file) {
                    this.upload(file);
                }, this);
            },

            'click #analysis-upload': function () {
                $('#analysis-files').click();
            }

        },

        initialize: function (settings) {
            this.analysis = null;
            this.datasets = settings.datasets;
            this.analysisSetupView = new flow.AnalysisSetupView({
                el: $('#analysis-setup-dialog'),
                model: this.analysis,
                datasets: this.datasets
            });

            this.editor = ace.edit("editor");
            this.editor.setTheme("ace/theme/chrome");
            this.editor.setHighlightActiveLine(false);
            this.editor.setHighlightGutterLine(false);
            this.editor.setShowPrintMargin(false);
            this.editor.setReadOnly(true);
            this.editor.setFontSize(14);
            this.editor.renderer.$cursorLayer.element.style.opacity = 0;

            this.analyses = settings.analyses;
            this.analysesView = new flow.ItemsView({el: this.$('#analysis'), itemView: flow.ItemOptionView, collection: this.analyses});
            this.analysesView.render();

            // Once the first analysis is added, make it the active analysis
            this.analyses.on('add', _.bind(function (item) {
                if (!this.analysis) {
                    this.changeAnalysis(item);
                }
            }, this));

            flow.events.on('flow:change-save-location', this.saveLocationChange, this);
        },

        changeAnalysis: function (analysis) {
            this.analysis = analysis;
            if (this.analysis) {
                this.editor.setValue(this.analysis.get('meta').analysis.script);
                this.editor.clearSelection();
                this.editor.getSession().setMode("ace/mode/" + this.analysis.get('meta').analysis.mode);
                this.setupVariableEditor('input-edit-', this.analysis.get('meta').analysis.inputs);
                this.setupVariableEditor('output-edit-', this.analysis.get('meta').analysis.outputs);
                this.$('#mode').val(this.analysis.get('meta').analysis.mode);
            } else {
                this.editor.setValue('');
                this.setupVariableEditor('input-edit-', []);
            }
        },

        upload: function (file) {
            var reader = new FileReader();

            reader.onload = _.bind(function (e) {
                this.createAnalysis(JSON.parse(e.target.result));
            }, this);

            reader.readAsText(file);
        },

        createAnalysis: function (analysis) {
            d3.json(girder.apiRoot + '/item/?name=' + encodeURIComponent(analysis.name) + '&folderId=' + flow.saveLocation.get('analysisFolder')).post(_.bind(function (error, result) {
                var analysisUri = girder.apiRoot + '/item/' + result._id;
                d3.json(analysisUri + '/metadata').send('put', JSON.stringify({analysis: analysis}), _.bind(function (error, result) {
                    var model = new Backbone.Model(result);
                    model.id = model.get('_id');
                    this.analyses.add(model);
                    $("#analysis").val(model.cid);
                    $("#analysis").change();
                    $("#analysis-name").val("");
                }, this));
            }, this));
        },

        saveLocationChange: function () {
            this.$('#new-analysis-form').toggleClass('hidden', flow.saveLocation === null);
        },

        setupVariableEditor: function(idPrefix, parameters) {
            var add = $("#" + idPrefix + "add"),
                name = $("#" + idPrefix + "name"),
                remove = $("#" + idPrefix + "remove"),
                format = $("#" + idPrefix + "format"),
                domain = $("#" + idPrefix + "domain"),
                select = $("#" + idPrefix + "select"),
                defaultValue = $("#" + idPrefix + "default"),
                parameterMap = {};

            parameters.forEach(function (d) {
                parameterMap[d.name] = d;
            });

            d3.select(format.get(0)).selectAll("option")
                .data(this.formats, function (d) { return d; })
                .enter().append("option")
                .text(function (d) { return d; })
                .attr("value", function (d) { return d; });

            function update() {
                var options = d3.select(select.get(0)).selectAll("option")
                    .data(parameters, function (d) { return d.name; });
                options.enter().append("option")
                    .text(function (d) { return d.name; })
                    .attr("value", function (d) { return d.name; });
                options.exit().remove();
            }

            add.off("click");
            add.click(function () {
                var param = {name: name.val(), type: "table", format: "rows"};
                parameters.push(param);
                parameterMap[param.name] = param;
                update();
                select.val(param.name);
                select.change();
                name.val("");
            });

            select.off("change");
            select.change(function () {
                var param = parameterMap[select.val()];
                if (param) {
                    format.val(param.type + ":" + param.format);
                    format.change();
                    if (param.domain) {
                        if (tangelo.isArray(param.domain)) {
                            domain.val(param.domain.join(","));
                        } else {
                            domain.val(JSON.stringify(param.domain));
                        }
                    } else {
                        domain.val("");
                    }
                    if (defaultValue && param["default"]) {
                        defaultValue.val(param["default"].data);
                    } else {
                        defaultValue.val("");
                    }
                }
            });

            format.off("change");
            format.change(function () {
                var param = parameterMap[select.val()],
                    parts = format.val().split(":");
                if (param) {
                    param.type = parts[0];
                    param.format = parts[1];
                }
                d3.select(domain.get(0)).classed("hidden", format.val() !== "string:text");
            });

            domain.off("focusout");
            domain.focusout(function () {
                var param = parameterMap[select.val()];
                if (param) {
                    if (domain.val() !== "") {
                        if (domain.val()[0] === "{") {
                            param.domain = JSON.parse(domain.val());
                        } else {
                            param.domain = domain.val().split(",");
                        }
                    } else {
                        delete param.domain;
                    }
                }
            });

            remove.off("click");
            remove.click(function () {
                var param = parameterMap[select.val()], index;
                if (param) {
                    index = parameters.indexOf(param);
                    parameters.splice(index, 1);
                    delete parameterMap[param.name];
                    update();
                    select.change();
                }
            });

            if (defaultValue) {
                defaultValue.remove("focusout");
                defaultValue.focusout(function () {
                    var param = parameterMap[select.val()];
                    if (param) {
                        if (defaultValue.val() !== "") {
                            if (param.type === "string") {
                                param['default'] = {format: "text", data: defaultValue.val()};
                            } else if (param.type === "number") {
                                param['default'] = {format: "number", data: parseFloat(defaultValue.val())};
                            }
                        } else {
                            delete param['default'];
                        }
                    }
                });
            }

            d3.select(select.get(0)).selectAll("option").remove();
            update();
            select.change();
        }
    });

}(window.flow, window.$, window._, window.ace, window.Backbone, window.Blob, window.d3, window.FileReader, window.girder, window.tangelo, window.URL));
<commit_msg>Trim comma-separated list parts in string domain<commit_after>/*jslint browser: true, nomen: true */

(function (flow, $, _, ace, Backbone, Blob, d3, FileReader, girder, tangelo, URL) {
    "use strict";

   // The view for selecting, running, and editing analyses
    flow.AnalysisManagementView = Backbone.View.extend({
        formats: [
            'table:rows',
            'table:r.dataframe',
            'table:csv',
            'table:tsv',
            'tree:nested',
            'tree:r.apetree',
            'string:text',
            'number:number',
            'image:png.base64',
            'r:object'
        ],

        events: {
            'click #show-script': function () {
                var hide = d3.select("#show-script").classed("active");
                flow.setDisplay(hide ? "vis" : "editor");
                this.editor.resize();
                d3.select("#show-script-icon").classed("glyphicon-eye-open", hide);
                d3.select("#show-script-icon").classed("glyphicon-eye-close", !hide);
                d3.select("#show-script-text").text(hide ? "Show script" : "Hide script");
                if (this.analysis.get('collection').get('_accessLevel') > 0) {
                    d3.select("#edit").classed("hidden", hide);
                    d3.selectAll(".edit-controls").classed("hidden", !d3.select("#edit").classed("active") || hide);
                }
            },

            'click #edit': function () {
                var edit = d3.select("#edit").classed("active");
                this.editor.setReadOnly(edit);
                this.editor.renderer.$cursorLayer.element.style.opacity = edit ? 0 : 1;
                d3.selectAll(".edit-controls").classed("hidden", edit);
            },

            'change #mode': function () {
                if (this.analysis) {
                    this.analysis.get('meta').analysis.mode = $("#mode").val();
                    this.editor.getSession().setMode("ace/mode/" + this.analysis.get('meta').analysis.mode);
                }
            },

            'click #save': function () {
                if (this.analysis) {
                    this.analysis.get('meta').analysis.script = this.editor.getValue();
                    d3.json(girder.apiRoot + '/item/' + this.analysis.id + '/metadata').send('put', JSON.stringify(this.analysis.get('meta')), function () {
                        // Trigger recreating the analysis UI
                        $("#analysis").change();
                    });
                }
            },

            'change #analysis': function () {
                this.changeAnalysis(this.analyses.get($("#analysis").val()));
            },

            'click #setup': function () {
                if (this.analysis) {
                    this.analysisSetupView.model = this.analysis;
                    this.analysisSetupView.render();
                }
            },

            'click #analysis-new': function () {
                var analysis = {
                    name: $("#analysis-name").val(),
                    inputs: [],
                    outputs: [],
                    mode: "python",
                    script: ""
                };
                this.createAnalysis(analysis);
            },

            'click #analysis-download': function () {
                var blob = new Blob([JSON.stringify(this.analysis.get('meta').analysis, null, "    ")]),
                    filename = this.analysis.get('meta').analysis.name + '.json',
                    anchor = $('');
                anchor[0].click();
            },

            'change #analysis-files': function () {
                var files = $('#analysis-files')[0].files;
                _.each(files, function (file) {
                    this.upload(file);
                }, this);
            },

            'click #analysis-upload': function () {
                $('#analysis-files').click();
            }

        },

        initialize: function (settings) {
            this.analysis = null;
            this.datasets = settings.datasets;
            this.analysisSetupView = new flow.AnalysisSetupView({
                el: $('#analysis-setup-dialog'),
                model: this.analysis,
                datasets: this.datasets
            });

            this.editor = ace.edit("editor");
            this.editor.setTheme("ace/theme/chrome");
            this.editor.setHighlightActiveLine(false);
            this.editor.setHighlightGutterLine(false);
            this.editor.setShowPrintMargin(false);
            this.editor.setReadOnly(true);
            this.editor.setFontSize(14);
            this.editor.renderer.$cursorLayer.element.style.opacity = 0;

            this.analyses = settings.analyses;
            this.analysesView = new flow.ItemsView({el: this.$('#analysis'), itemView: flow.ItemOptionView, collection: this.analyses});
            this.analysesView.render();

            // Once the first analysis is added, make it the active analysis
            this.analyses.on('add', _.bind(function (item) {
                if (!this.analysis) {
                    this.changeAnalysis(item);
                }
            }, this));

            flow.events.on('flow:change-save-location', this.saveLocationChange, this);
        },

        changeAnalysis: function (analysis) {
            this.analysis = analysis;
            if (this.analysis) {
                this.editor.setValue(this.analysis.get('meta').analysis.script);
                this.editor.clearSelection();
                this.editor.getSession().setMode("ace/mode/" + this.analysis.get('meta').analysis.mode);
                this.setupVariableEditor('input-edit-', this.analysis.get('meta').analysis.inputs);
                this.setupVariableEditor('output-edit-', this.analysis.get('meta').analysis.outputs);
                this.$('#mode').val(this.analysis.get('meta').analysis.mode);
            } else {
                this.editor.setValue('');
                this.setupVariableEditor('input-edit-', []);
            }
        },

        upload: function (file) {
            var reader = new FileReader();

            reader.onload = _.bind(function (e) {
                this.createAnalysis(JSON.parse(e.target.result));
            }, this);

            reader.readAsText(file);
        },

        createAnalysis: function (analysis) {
            d3.json(girder.apiRoot + '/item/?name=' + encodeURIComponent(analysis.name) + '&folderId=' + flow.saveLocation.get('analysisFolder')).post(_.bind(function (error, result) {
                var analysisUri = girder.apiRoot + '/item/' + result._id;
                d3.json(analysisUri + '/metadata').send('put', JSON.stringify({analysis: analysis}), _.bind(function (error, result) {
                    var model = new Backbone.Model(result);
                    model.id = model.get('_id');
                    this.analyses.add(model);
                    $("#analysis").val(model.cid);
                    $("#analysis").change();
                    $("#analysis-name").val("");
                }, this));
            }, this));
        },

        saveLocationChange: function () {
            this.$('#new-analysis-form').toggleClass('hidden', flow.saveLocation === null);
        },

        setupVariableEditor: function(idPrefix, parameters) {
            var add = $("#" + idPrefix + "add"),
                name = $("#" + idPrefix + "name"),
                remove = $("#" + idPrefix + "remove"),
                format = $("#" + idPrefix + "format"),
                domain = $("#" + idPrefix + "domain"),
                select = $("#" + idPrefix + "select"),
                defaultValue = $("#" + idPrefix + "default"),
                parameterMap = {};

            parameters.forEach(function (d) {
                parameterMap[d.name] = d;
            });

            d3.select(format.get(0)).selectAll("option")
                .data(this.formats, function (d) { return d; })
                .enter().append("option")
                .text(function (d) { return d; })
                .attr("value", function (d) { return d; });

            function update() {
                var options = d3.select(select.get(0)).selectAll("option")
                    .data(parameters, function (d) { return d.name; });
                options.enter().append("option")
                    .text(function (d) { return d.name; })
                    .attr("value", function (d) { return d.name; });
                options.exit().remove();
            }

            add.off("click");
            add.click(function () {
                var param = {name: name.val(), type: "table", format: "rows"};
                parameters.push(param);
                parameterMap[param.name] = param;
                update();
                select.val(param.name);
                select.change();
                name.val("");
            });

            select.off("change");
            select.change(function () {
                var param = parameterMap[select.val()];
                if (param) {
                    format.val(param.type + ":" + param.format);
                    format.change();
                    if (param.domain) {
                        if (tangelo.isArray(param.domain)) {
                            domain.val(param.domain.join(","));
                        } else {
                            domain.val(JSON.stringify(param.domain));
                        }
                    } else {
                        domain.val("");
                    }
                    if (defaultValue && param["default"]) {
                        defaultValue.val(param["default"].data);
                    } else {
                        defaultValue.val("");
                    }
                }
            });

            format.off("change");
            format.change(function () {
                var param = parameterMap[select.val()],
                    parts = format.val().split(":");
                if (param) {
                    param.type = parts[0];
                    param.format = parts[1];
                }
                d3.select(domain.get(0)).classed("hidden", format.val() !== "string:text");
            });

            domain.off("focusout");
            domain.focusout(function () {
                var param = parameterMap[select.val()], i;
                if (param) {
                    if (domain.val() !== "") {
                        if (domain.val()[0] === "{") {
                            param.domain = JSON.parse(domain.val());
                        } else {
                            param.domain = domain.val().split(",");
                            for (i = 0; i < param.domain.length; i += 1) {
                                param.domain[i] = param.domain[i].trim();
                            }
                        }
                    } else {
                        delete param.domain;
                    }
                }
            });

            remove.off("click");
            remove.click(function () {
                var param = parameterMap[select.val()], index;
                if (param) {
                    index = parameters.indexOf(param);
                    parameters.splice(index, 1);
                    delete parameterMap[param.name];
                    update();
                    select.change();
                }
            });

            if (defaultValue) {
                defaultValue.remove("focusout");
                defaultValue.focusout(function () {
                    var param = parameterMap[select.val()];
                    if (param) {
                        if (defaultValue.val() !== "") {
                            if (param.type === "string") {
                                param['default'] = {format: "text", data: defaultValue.val()};
                            } else if (param.type === "number") {
                                param['default'] = {format: "number", data: parseFloat(defaultValue.val())};
                            }
                        } else {
                            delete param['default'];
                        }
                    }
                });
            }

            d3.select(select.get(0)).selectAll("option").remove();
            update();
            select.change();
        }
    });

}(window.flow, window.$, window._, window.ace, window.Backbone, window.Blob, window.d3, window.FileReader, window.girder, window.tangelo, window.URL));
<|endoftext|>


<commit_before>var $ = require('jQuery');
var onReady = require('kwf/on-ready');
var kwfExtend = require('kwf/extend');

var HistoryStateAbstract = function() {
    this.disabled = false; //functionality can be disabled, so it behaves like a browser that doesn't support history states
    this.currentState = {};
};
HistoryStateAbstract.prototype = {
    /**
     * Number of entries in the history of the current page
     **/
    entries: 0,
    pushState: function() {},
    updateState: function() {},
    /**
     * Replace the current state, don't use is possible as it will do a new page request in non-html5-browsers
     **/
    replaceState: function() {},

    on: function(event, cb, scope) {
        if (typeof scope != 'undefined') cb = cb.bind(scope);
        $(window).on('kwf-history-state-'+event, cb);
    }
};

var HistoryStateHtml5 = function() {
    HistoryStateHtml5.superclass.constructor.call(this);
    $(window).on('popstate', (function(event) {
        if (this.disabled) return;
        this.entries--;
        if (event.originalEvent.state) {
            this.currentState = event.originalEvent.state;
        } else {
            this.currentState = {};
        }

        //only when state cromes from "us" react on it
        //works around safari bug which fires popstate on load
        if (this.currentState['kwfUp-kwfHistoryState']) {
            $(window).trigger('kwf-history-state-popstate');
        }
    }).bind(this));
};
kwfExtend(HistoryStateHtml5, HistoryStateAbstract, {
    pushState: function(title, href) {
        if (this.disabled) return;
        this.currentState['kwfUp-kwfHistoryState'] = true;
        window.history.pushState(this.currentState, title, href);
        this.entries++;
    },
    updateState: function() {
        if (this.disabled) return;
          this.currentState['kwfUp-kwfHistoryState'] = true;
        window.history.replaceState(this.currentState, document.title, window.location.href);
    },
    replaceState: function(title, href) {
        if (this.disabled) return;
          this.currentState['kwfUp-kwfHistoryState'] = true;
        window.history.replaceState(this.currentState, title, href);
    }
});

// Fallback for <IE10
// always triggers a page load
var HistoryStateFallback = kwfExtend(HistoryStateAbstract, {
    pushState: function(title, href) {
        if (this.disabled) return;
        location.href = href; //this will trigger a page load
    },
    replaceState: function(title, href) {
        if (this.disabled) return;
        location.replace(href); //this will trigger a page load
    }
});
if (window.history.pushState) {
    module.exports = new HistoryStateHtml5();
} else {
    module.exports = new HistoryStateFallback();
}
<commit_msg>HistoryState Bugfix: updateState on load<commit_after>var $ = require('jQuery');
var onReady = require('kwf/on-ready');
var kwfExtend = require('kwf/extend');

var HistoryStateAbstract = function() {
    this.disabled = false; //functionality can be disabled, so it behaves like a browser that doesn't support history states
    this.currentState = {};
};
HistoryStateAbstract.prototype = {
    /**
     * Number of entries in the history of the current page
     **/
    entries: 0,
    pushState: function() {},
    updateState: function() {},
    /**
     * Replace the current state, don't use is possible as it will do a new page request in non-html5-browsers
     **/
    replaceState: function() {},

    on: function(event, cb, scope) {
        if (typeof scope != 'undefined') cb = cb.bind(scope);
        $(window).on('kwf-history-state-'+event, cb);
    }
};

var HistoryStateHtml5 = function() {
    HistoryStateHtml5.superclass.constructor.call(this);
    $(window).on('popstate', (function(event) {
        if (this.disabled) return;
        this.entries--;
        if (event.originalEvent.state) {
            this.currentState = event.originalEvent.state;
        } else {
            this.currentState = {};
        }

        //only when state cromes from "us" react on it
        //works around safari bug which fires popstate on load
        if (this.currentState['kwfUp-kwfHistoryState']) {
            $(window).trigger('kwf-history-state-popstate');
        }
    }).bind(this));

    if (!window.history.state) {
        this.updateState();
    }
};
kwfExtend(HistoryStateHtml5, HistoryStateAbstract, {
    pushState: function(title, href) {
        if (this.disabled) return;
        this.currentState['kwfUp-kwfHistoryState'] = true;
        window.history.pushState(this.currentState, title, href);
        this.entries++;
    },
    updateState: function() {
        if (this.disabled) return;
        this.currentState['kwfUp-kwfHistoryState'] = true;
        window.history.replaceState(this.currentState, document.title, window.location.href);
    },
    replaceState: function(title, href) {
        if (this.disabled) return;
        this.currentState['kwfUp-kwfHistoryState'] = true;
        window.history.replaceState(this.currentState, title, href);
    }
});

// Fallback for <IE10
// always triggers a page load
var HistoryStateFallback = kwfExtend(HistoryStateAbstract, {
    pushState: function(title, href) {
        if (this.disabled) return;
        location.href = href; //this will trigger a page load
    },
    replaceState: function(title, href) {
        if (this.disabled) return;
        location.replace(href); //this will trigger a page load
    }
});
if (window.history.pushState) {
    module.exports = new HistoryStateHtml5();
} else {
    module.exports = new HistoryStateFallback();
}
<|endoftext|>


<commit_before>'use strict';
const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;
const ClientPasswordStrategy = require('passport-oauth2-client-password').Strategy;
const BearerStrategy = require('passport-http-bearer').Strategy;

const config = require('../../config');
const jwtPolicy = require('../jwt').policy;
const services = require('../../services/index');
const authService = services.auth;

/**
 * LocalStrategy
 *
 * This strategy is used to authenticate users based on a username and password.
 * Anytime a request is made to authorize an application, we must ensure that
 * a user is logged in before asking them to approve the request.
 */

passport.use(new LocalStrategy({ passReqToCallback: true }, authenticateLocal));

passport.serializeUser((user, done) => done(null, user.id));

passport.deserializeUser((id, done) => {
  return authService.validateConsumer(id)
    .then(consumer => {
      if (!consumer) return done(null, false);
      return done(null, consumer);
    })
    .catch(err => done(err));
});

/**
 * BasicStrategy & ClientPasswordStrategy
 *
 * These strategies are used to authenticate registered OAuth clients. They are
 * employed to protect the `token` endpoint, which consumers use to obtain
 * access tokens. The OAuth 2.0 specification suggests that clients use the
 * HTTP Basic scheme to authenticate. Use of the client password strategy
 * allows clients to send the same credentials in the request body (as opposed
 * to the `Authorization` header). While this approach is not recommended by
 * the specification, in practice it is quite common.
 */

passport.use(new ClientPasswordStrategy({ passReqToCallback: true }, authenticateBasic));

/**
 * BearerStrategy
 *
 * This strategy is used to authenticate either users or clients based on an access token
 * (aka a bearer token). If a user, they must have previously authorized a client
 * application, which is issued an access token to make requests on behalf of
 * the authorizing user.
 */

passport.use(new BearerStrategy({ passReqToCallback: true }, authenticateToken));

function authenticateToken (req, accessToken, done) {
  let endpointScopes;
  if (req.egContext.apiEndpoint && req.egContext.apiEndpoint.scopes) {
    endpointScopes = req.egContext.apiEndpoint.scopes;
  }

  let token, consumer;

  return authService.authenticateToken(accessToken)
    .then(res => {
      if (!res) {
        return done(null, false);
      }

      token = res.token;
      consumer = res.consumer;

      return authService.authorizeToken(accessToken, 'oauth2', endpointScopes)
        .then(authorized => {
          if (!authorized) {
            return done(null, false);
          }
          delete req.headers.authorization;
          delete token.tokenDecrypted;
          consumer.token = token;

          if (!token.authenticatedUserId) {
            return done(null, consumer);
          }

          return authService.validateConsumer(token.authenticatedUserId)
            .then(user => {
              if (!user) {
                return done(null, false);
              }
              consumer.token = token;
              return done(null, consumer);
            });
        });
    });
}

function authenticateBasic (req, clientId, clientSecret, done) {
  let credentialType, endpointScopes, requestedScopes;

  if (req.egContext && req.egContext.apiEndpoint && req.egContext.apiEndpoint.scopes) {
    endpointScopes = req.egContext.apiEndpoint.scopes;
    credentialType = 'basic-auth';
  } else {
    credentialType = 'oauth2';
    if (req.query.scope) {
      requestedScopes = req.query.scope.split(' ');
    } else if (req.body.scope) {
      requestedScopes = req.body.scope.split(' ');
    }
  }

  return authService.authenticateCredential(clientId, clientSecret, credentialType)
    .then(consumer => {
      if (!consumer) {
        return done(null, false);
      }

      return authService.authorizeCredential(clientId, credentialType, endpointScopes || requestedScopes)
        .then(authorized => {
          if (!authorized) {
            return done(null, false);
          }

          consumer.authorizedScopes = endpointScopes;

          return done(null, consumer);
        });
    })
    .catch(err => done(err));
}

function authenticateLocal (req, clientId, clientSecret, done) {
  const credentialType = 'basic-auth';

  return authService.authenticateCredential(clientId, clientSecret, credentialType)
    .then(consumer => {
      if (!consumer) {
        return done(null, false);
      }

      return authService.authorizeCredential(clientId, credentialType)
        .then(authorized => {
          if (!authorized) {
            return done(null, false);
          }

          delete req.headers['authorization'];
          return done(null, consumer);
        });
    })
    .catch(err => done(err));
}

module.exports = function (actionParams) {
  if (config.systemConfig.accessTokens.tokenType === 'jwt') {
    return jwtPolicy({ ...actionParams.jwt, getCommonAuthCallback: actionParams.getCommonAuthCallback });
  }

  return function (req, res, next) {
    actionParams.session = false;
    passport.authenticate('bearer', actionParams, actionParams.getCommonAuthCallback(req, res, next))(req, res, next);
  };
};
<commit_msg>Circumnavigate nyc problem<commit_after>'use strict';
const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;
const ClientPasswordStrategy = require('passport-oauth2-client-password').Strategy;
const BearerStrategy = require('passport-http-bearer').Strategy;

const config = require('../../config');
const jwtPolicy = require('../jwt').policy;
const services = require('../../services/index');
const authService = services.auth;

/**
 * LocalStrategy
 *
 * This strategy is used to authenticate users based on a username and password.
 * Anytime a request is made to authorize an application, we must ensure that
 * a user is logged in before asking them to approve the request.
 */

passport.use(new LocalStrategy({ passReqToCallback: true }, authenticateLocal));

passport.serializeUser((user, done) => done(null, user.id));

passport.deserializeUser((id, done) => {
  return authService.validateConsumer(id)
    .then(consumer => {
      if (!consumer) return done(null, false);
      return done(null, consumer);
    })
    .catch(err => done(err));
});

/**
 * BasicStrategy & ClientPasswordStrategy
 *
 * These strategies are used to authenticate registered OAuth clients. They are
 * employed to protect the `token` endpoint, which consumers use to obtain
 * access tokens. The OAuth 2.0 specification suggests that clients use the
 * HTTP Basic scheme to authenticate. Use of the client password strategy
 * allows clients to send the same credentials in the request body (as opposed
 * to the `Authorization` header). While this approach is not recommended by
 * the specification, in practice it is quite common.
 */

passport.use(new ClientPasswordStrategy({ passReqToCallback: true }, authenticateBasic));

/**
 * BearerStrategy
 *
 * This strategy is used to authenticate either users or clients based on an access token
 * (aka a bearer token). If a user, they must have previously authorized a client
 * application, which is issued an access token to make requests on behalf of
 * the authorizing user.
 */

passport.use(new BearerStrategy({ passReqToCallback: true }, authenticateToken));

function authenticateToken (req, accessToken, done) {
  let endpointScopes;
  if (req.egContext.apiEndpoint && req.egContext.apiEndpoint.scopes) {
    endpointScopes = req.egContext.apiEndpoint.scopes;
  }

  let token, consumer;

  return authService.authenticateToken(accessToken)
    .then(res => {
      if (!res) {
        return done(null, false);
      }

      token = res.token;
      consumer = res.consumer;

      return authService.authorizeToken(accessToken, 'oauth2', endpointScopes)
        .then(authorized => {
          if (!authorized) {
            return done(null, false);
          }
          delete req.headers.authorization;
          delete token.tokenDecrypted;
          consumer.token = token;

          if (!token.authenticatedUserId) {
            return done(null, consumer);
          }

          return authService.validateConsumer(token.authenticatedUserId)
            .then(user => {
              if (!user) {
                return done(null, false);
              }
              consumer.token = token;
              return done(null, consumer);
            });
        });
    });
}

function authenticateBasic (req, clientId, clientSecret, done) {
  let credentialType, endpointScopes, requestedScopes;

  if (req.egContext && req.egContext.apiEndpoint && req.egContext.apiEndpoint.scopes) {
    endpointScopes = req.egContext.apiEndpoint.scopes;
    credentialType = 'basic-auth';
  } else {
    credentialType = 'oauth2';
    if (req.query.scope) {
      requestedScopes = req.query.scope.split(' ');
    } else if (req.body.scope) {
      requestedScopes = req.body.scope.split(' ');
    }
  }

  return authService.authenticateCredential(clientId, clientSecret, credentialType)
    .then(consumer => {
      if (!consumer) {
        return done(null, false);
      }

      return authService.authorizeCredential(clientId, credentialType, endpointScopes || requestedScopes)
        .then(authorized => {
          if (!authorized) {
            return done(null, false);
          }

          consumer.authorizedScopes = endpointScopes;

          return done(null, consumer);
        });
    })
    .catch(err => done(err));
}

function authenticateLocal (req, clientId, clientSecret, done) {
  const credentialType = 'basic-auth';

  return authService.authenticateCredential(clientId, clientSecret, credentialType)
    .then(consumer => {
      if (!consumer) {
        return done(null, false);
      }

      return authService.authorizeCredential(clientId, credentialType)
        .then(authorized => {
          if (!authorized) {
            return done(null, false);
          }

          delete req.headers['authorization'];
          return done(null, consumer);
        });
    })
    .catch(err => done(err));
}

module.exports = function (actionParams) {
  if (config.systemConfig.accessTokens.tokenType === 'jwt') {
    const params = Object.assign({ getCommonAuthCallback: actionParams.getCommonAuthCallback }, actionParams.jwt);
    return jwtPolicy(params);
  }

  return function (req, res, next) {
    actionParams.session = false;
    passport.authenticate('bearer', actionParams, actionParams.getCommonAuthCallback(req, res, next))(req, res, next);
  };
};
<|endoftext|>