All Downloads are FREE. Search and download functionalities are using the official Maven repository.

frontend.src.behave.js Maven / Gradle / Ivy

There is a newer version: 3.0.0-alpha-29
Show newest version
/* eslint-disable */
/*
 * Behave.js
 *
 * Copyright 2013, Jacob Kelley - http://jakiestfu.com/
 * Released under the MIT Licence
 * http://opensource.org/licenses/MIT
 *
 * Github:  http://github.com/jakiestfu/Behave.js/
 * Version: 1.5
 */


(function (undefined) {


    var BehaveHooks = BehaveHooks || (function () {
            var hooks = {};

            return {
                add: function (hookName, fn) {
                    if (typeof hookName == "object") {
                        var i;
                        for (i = 0; i < hookName.length; i++) {
                            var theHook = hookName[i];
                            if (!hooks[theHook]) {
                                hooks[theHook] = [];
                            }
                            hooks[theHook].push(fn);
                        }
                    } else {
                        if (!hooks[hookName]) {
                            hooks[hookName] = [];
                        }
                        hooks[hookName].push(fn);
                    }
                },
                get: function (hookName) {
                    if (hooks[hookName]) {
                        return hooks[hookName];
                    }
                }
            };

        })(),
        Behave = Behave || function (userOpts) {

            if (typeof String.prototype.repeat !== 'function') {
                String.prototype.repeat = function (times) {
                    if (times < 1) {
                        return '';
                    }
                    if (times % 2) {
                        return this.repeat(times - 1) + this;
                    }
                    var half = this.repeat(times / 2);
                    return half + half;
                };
            }

            if (typeof Array.prototype.filter !== 'function') {
                Array.prototype.filter = function (func /*, thisp */) {
                    if (this === null) {
                        throw new TypeError();
                    }

                    var t = Object(this),
                        len = t.length >>> 0;
                    if (typeof func != "function") {
                        throw new TypeError();
                    }
                    var res = [],
                        thisp = arguments[1];
                    for (var i = 0; i < len; i++) {
                        if (i in t) {
                            var val = t[i];
                            if (func.call(thisp, val, i, t)) {
                                res.push(val);
                            }
                        }
                    }
                    return res;
                };
            }

            var defaults = {
                    textarea: null,
                    replaceTab: true,
                    softTabs: true,
                    tabSize: 4,
                    autoOpen: true,
                    overwrite: true,
                    autoStrip: true,
                    autoIndent: true,
                    fence: false
                },
                tab,
                newLine,
                charSettings = {

                    keyMap: [{
                        open: "\"",
                        close: "\"",
                        canBreak: false
                    },
                        {
                            open: "'",
                            close: "'",
                            canBreak: false
                        },
                        {
                            open: "(",
                            close: ")",
                            canBreak: false
                        },
                        {
                            open: "[",
                            close: "]",
                            canBreak: true
                        },
                        {
                            open: "{",
                            close: "}",
                            canBreak: true
                        }
                    ]

                },
                utils = {

                    _callHook: function (hookName, passData) {
                        var hooks = BehaveHooks.get(hookName);
                        passData = typeof passData == "boolean" && passData === false ? false : true;

                        if (hooks) {
                            if (passData) {
                                var theEditor = defaults.textarea,
                                    textVal = theEditor.value,
                                    caretPos = utils.cursor.get(),
                                    i;

                                for (i = 0; i < hooks.length; i++) {
                                    hooks[i].call(undefined, {
                                        editor: {
                                            element: theEditor,
                                            text: textVal,
                                            levelsDeep: utils.levelsDeep()
                                        },
                                        caret: {
                                            pos: caretPos
                                        },
                                        lines: {
                                            current: utils.cursor.getLine(textVal, caretPos),
                                            total: utils.editor.getLines(textVal)
                                        }
                                    });
                                }
                            } else {
                                for (i = 0; i < hooks.length; i++) {
                                    hooks[i].call(undefined);
                                }
                            }
                        }
                    },

                    defineNewLine: function () {
                        var ta = document.createElement('textarea');
                        ta.value = "\n";

                        if (ta.value.length == 2) {
                            newLine = "\r\n";
                        } else {
                            newLine = "\n";
                        }
                    },
                    defineTabSize: function (tabSize) {
                        if (typeof defaults.textarea.style.OTabSize != "undefined") {
                            defaults.textarea.style.OTabSize = tabSize;
                            return;
                        }
                        if (typeof defaults.textarea.style.MozTabSize != "undefined") {
                            defaults.textarea.style.MozTabSize = tabSize;
                            return;
                        }
                        if (typeof defaults.textarea.style.tabSize != "undefined") {
                            defaults.textarea.style.tabSize = tabSize;

                        }
                    },
                    cursor: {
                        getLine: function (textVal, pos) {
                            return ((textVal.substring(0, pos)).split("\n")).length;
                        },
                        get: function () {

                            if (typeof document.createElement('textarea').selectionStart === "number") {
                                return defaults.textarea.selectionStart;
                            } else if (document.selection) {
                                var caretPos = 0,
                                    range = defaults.textarea.createTextRange(),
                                    rangeDupe = document.selection.createRange().duplicate(),
                                    rangeDupeBookmark = rangeDupe.getBookmark();
                                range.moveToBookmark(rangeDupeBookmark);

                                while (range.moveStart('character', -1) !== 0) {
                                    caretPos++;
                                }
                                return caretPos;
                            }
                        },
                        set: function (start, end) {
                            if (!end) {
                                end = start;
                            }
                            if (defaults.textarea.setSelectionRange) {
                                defaults.textarea.focus();
                                defaults.textarea.setSelectionRange(start, end);
                            } else if (defaults.textarea.createTextRange) {
                                var range = defaults.textarea.createTextRange();
                                range.collapse(true);
                                range.moveEnd('character', end);
                                range.moveStart('character', start);
                                range.select();
                            }
                        },
                        selection: function () {
                            var textAreaElement = defaults.textarea,
                                start = 0,
                                end = 0,
                                normalizedValue,
                                range,
                                textInputRange,
                                len,
                                endRange;

                            if (typeof textAreaElement.selectionStart == "number" && typeof textAreaElement.selectionEnd == "number") {
                                start = textAreaElement.selectionStart;
                                end = textAreaElement.selectionEnd;
                            } else {
                                range = document.selection.createRange();

                                if (range && range.parentElement() == textAreaElement) {

                                    normalizedValue = utils.editor.get();
                                    len = normalizedValue.length;

                                    textInputRange = textAreaElement.createTextRange();
                                    textInputRange.moveToBookmark(range.getBookmark());

                                    endRange = textAreaElement.createTextRange();
                                    endRange.collapse(false);

                                    if (textInputRange.compareEndPoints("StartToEnd", endRange) > -1) {
                                        start = end = len;
                                    } else {
                                        start = -textInputRange.moveStart("character", -len);
                                        start += normalizedValue.slice(0, start).split(newLine).length - 1;

                                        if (textInputRange.compareEndPoints("EndToEnd", endRange) > -1) {
                                            end = len;
                                        } else {
                                            end = -textInputRange.moveEnd("character", -len);
                                            end += normalizedValue.slice(0, end).split(newLine).length - 1;
                                        }
                                    }
                                }
                            }

                            return start == end ? false : {
                                start: start,
                                end: end
                            };
                        }
                    },
                    editor: {
                        getLines: function (textVal) {
                            return (textVal).split("\n").length;
                        },
                        get: function () {
                            return defaults.textarea.value.replace(/\r/g, '');
                        },
                        set: function (data) {
                            defaults.textarea.value = data;
                        }
                    },
                    fenceRange: function () {
                        if (typeof defaults.fence == "string") {

                            var data = utils.editor.get(),
                                pos = utils.cursor.get(),
                                hacked = 0,
                                matchedFence = data.indexOf(defaults.fence),
                                matchCase = 0;

                            while (matchedFence >= 0) {
                                matchCase++;
                                if (pos < (matchedFence + hacked)) {
                                    break;
                                }

                                hacked += matchedFence + defaults.fence.length;
                                data = data.substring(matchedFence + defaults.fence.length);
                                matchedFence = data.indexOf(defaults.fence);

                            }

                            if ((hacked) < pos && ((matchedFence + hacked) > pos) && matchCase % 2 === 0) {
                                return true;
                            }
                            return false;
                        } else {
                            return true;
                        }
                    },
                    isEven: function (_this, i) {
                        return i % 2;
                    },
                    levelsDeep: function () {
                        var pos = utils.cursor.get(),
                            val = utils.editor.get();

                        var left = val.substring(0, pos),
                            levels = 0,
                            i, j;

                        for (i = 0; i < left.length; i++) {
                            for (j = 0; j < charSettings.keyMap.length; j++) {
                                if (charSettings.keyMap[j].canBreak) {
                                    if (charSettings.keyMap[j].open == left.charAt(i)) {
                                        levels++;
                                    }

                                    if (charSettings.keyMap[j].close == left.charAt(i)) {
                                        levels--;
                                    }
                                }
                            }
                        }

                        var toDecrement = 0,
                            quoteMap = ["'", "\""];
                        for (i = 0; i < charSettings.keyMap.length; i++) {
                            if (charSettings.keyMap[i].canBreak) {
                                for (j in quoteMap) {
                                    toDecrement += left.split(quoteMap[j]).filter(utils.isEven).join('').split(charSettings.keyMap[i].open).length - 1;
                                }
                            }
                        }

                        var finalLevels = levels - toDecrement;

                        return finalLevels >= 0 ? finalLevels : 0;
                    },
                    deepExtend: function (destination, source) {
                        for (var property in source) {
                            if (source[property] && source[property].constructor &&
                                source[property].constructor === Object) {
                                destination[property] = destination[property] || {};
                                utils.deepExtend(destination[property], source[property]);
                            } else {
                                destination[property] = source[property];
                            }
                        }
                        return destination;
                    },
                    addEvent: function addEvent(element, eventName, func) {
                        if (element.addEventListener) {
                            element.addEventListener(eventName, func, false);
                        } else if (element.attachEvent) {
                            element.attachEvent("on" + eventName, func);
                        }
                    },
                    removeEvent: function addEvent(element, eventName, func) {
                        if (element.addEventListener) {
                            element.removeEventListener(eventName, func, false);
                        } else if (element.attachEvent) {
                            element.detachEvent("on" + eventName, func);
                        }
                    },

                    preventDefaultEvent: function (e) {
                        if (e.preventDefault) {
                            e.preventDefault();
                        } else {
                            e.returnValue = false;
                        }
                    }
                },
                intercept = {
                    tabKey: function (e) {

                        if (!utils.fenceRange()) {
                            return;
                        }

                        if (e.keyCode == 9) {
                            utils.preventDefaultEvent(e);

                            var toReturn = true;
                            utils._callHook('tab:before');

                            var selection = utils.cursor.selection(),
                                pos = utils.cursor.get(),
                                val = utils.editor.get();

                            if (selection) {

                                var tempStart = selection.start;
                                while (tempStart--) {
                                    if (val.charAt(tempStart) == "\n") {
                                        selection.start = tempStart + 1;
                                        break;
                                    }
                                }

                                var toIndent = val.substring(selection.start, selection.end),
                                    lines = toIndent.split("\n"),
                                    i;

                                if (e.shiftKey) {
                                    for (i = 0; i < lines.length; i++) {
                                        if (lines[i].substring(0, tab.length) == tab) {
                                            lines[i] = lines[i].substring(tab.length);
                                        }
                                    }
                                    toIndent = lines.join("\n");

                                    utils.editor.set(val.substring(0, selection.start) + toIndent + val.substring(selection.end));
                                    utils.cursor.set(selection.start, selection.start + toIndent.length);

                                } else {
                                    for (i in lines) {
                                        lines[i] = tab + lines[i];
                                    }
                                    toIndent = lines.join("\n");

                                    utils.editor.set(val.substring(0, selection.start) + toIndent + val.substring(selection.end));
                                    utils.cursor.set(selection.start, selection.start + toIndent.length);
                                }
                            } else {
                                var left = val.substring(0, pos),
                                    right = val.substring(pos),
                                    edited = left + tab + right;

                                if (e.shiftKey) {
                                    if (val.substring(pos - tab.length, pos) == tab) {
                                        edited = val.substring(0, pos - tab.length) + right;
                                        utils.editor.set(edited);
                                        utils.cursor.set(pos - tab.length);
                                    }
                                } else {
                                    utils.editor.set(edited);
                                    utils.cursor.set(pos + tab.length);
                                    toReturn = false;
                                }
                            }
                            utils._callHook('tab:after');
                        }
                        return toReturn;
                    },
                    enterKey: function (e) {

                        if (!utils.fenceRange()) {
                            return;
                        }

                        if (e.keyCode == 13) {

                            utils.preventDefaultEvent(e);
                            utils._callHook('enter:before');

                            var pos = utils.cursor.get(),
                                val = utils.editor.get(),
                                left = val.substring(0, pos),
                                right = val.substring(pos),
                                leftChar = left.charAt(left.length - 1),
                                rightChar = right.charAt(0),
                                numTabs = utils.levelsDeep(),
                                ourIndent = "",
                                closingBreak = "",
                                finalCursorPos,
                                i;
                            if (!numTabs) {
                                finalCursorPos = 1;
                            } else {
                                while (numTabs--) {
                                    ourIndent += tab;
                                }
                                ourIndent = ourIndent;
                                finalCursorPos = ourIndent.length + 1;

                                for (i = 0; i < charSettings.keyMap.length; i++) {
                                    if (charSettings.keyMap[i].open == leftChar && charSettings.keyMap[i].close == rightChar) {
                                        closingBreak = newLine;
                                    }
                                }

                            }

                            var edited = left + newLine + ourIndent + closingBreak + (ourIndent.substring(0, ourIndent.length - tab.length)) + right;
                            utils.editor.set(edited);
                            utils.cursor.set(pos + finalCursorPos);
                            utils._callHook('enter:after');
                        }
                    },
                    deleteKey: function (e) {

                        if (!utils.fenceRange()) {
                            return;
                        }

                        if (e.keyCode == 8) {
                            utils.preventDefaultEvent(e);

                            utils._callHook('delete:before');

                            var pos = utils.cursor.get(),
                                val = utils.editor.get(),
                                left = val.substring(0, pos),
                                right = val.substring(pos),
                                leftChar = left.charAt(left.length - 1),
                                rightChar = right.charAt(0),
                                i;

                            if (utils.cursor.selection() === false) {
                                for (i = 0; i < charSettings.keyMap.length; i++) {
                                    if (charSettings.keyMap[i].open == leftChar && charSettings.keyMap[i].close == rightChar) {
                                        var edited = val.substring(0, pos - 1) + val.substring(pos + 1);
                                        utils.editor.set(edited);
                                        utils.cursor.set(pos - 1);
                                        return;
                                    }
                                }
                                var edited = val.substring(0, pos - 1) + val.substring(pos);
                                utils.editor.set(edited);
                                utils.cursor.set(pos - 1);
                            } else {
                                var sel = utils.cursor.selection(),
                                    edited = val.substring(0, sel.start) + val.substring(sel.end);
                                utils.editor.set(edited);
                                utils.cursor.set(pos);
                            }

                            utils._callHook('delete:after');

                        }
                    }
                },
                charFuncs = {
                    openedChar: function (_char, e) {
                        utils.preventDefaultEvent(e);
                        utils._callHook('openChar:before');
                        var pos = utils.cursor.get(),
                            val = utils.editor.get(),
                            left = val.substring(0, pos),
                            right = val.substring(pos),
                            edited = left + _char.open + _char.close + right;

                        defaults.textarea.value = edited;
                        utils.cursor.set(pos + 1);
                        utils._callHook('openChar:after');
                    },
                    closedChar: function (_char, e) {
                        var pos = utils.cursor.get(),
                            val = utils.editor.get(),
                            toOverwrite = val.substring(pos, pos + 1);
                        if (toOverwrite == _char.close) {
                            utils.preventDefaultEvent(e);
                            utils._callHook('closeChar:before');
                            utils.cursor.set(utils.cursor.get() + 1);
                            utils._callHook('closeChar:after');
                            return true;
                        }
                        return false;
                    }
                },
                action = {
                    filter: function (e) {

                        if (!utils.fenceRange()) {
                            return;
                        }

                        var theCode = e.which || e.keyCode;

                        if (theCode == 39 || theCode == 40 && e.which === 0) {
                            return;
                        }

                        var _char = String.fromCharCode(theCode),
                            i;

                        for (i = 0; i < charSettings.keyMap.length; i++) {

                            if (charSettings.keyMap[i].close == _char) {
                                var didClose = defaults.overwrite && charFuncs.closedChar(charSettings.keyMap[i], e);

                                if (!didClose && charSettings.keyMap[i].open == _char && defaults.autoOpen) {
                                    charFuncs.openedChar(charSettings.keyMap[i], e);
                                }
                            } else if (charSettings.keyMap[i].open == _char && defaults.autoOpen) {
                                charFuncs.openedChar(charSettings.keyMap[i], e);
                            }
                        }
                    },
                    listen: function () {

                        if (defaults.replaceTab) {
                            utils.addEvent(defaults.textarea, 'keydown', intercept.tabKey);
                        }
                        if (defaults.autoIndent) {
                            utils.addEvent(defaults.textarea, 'keydown', intercept.enterKey);
                        }
                        if (defaults.autoStrip) {
                            utils.addEvent(defaults.textarea, 'keydown', intercept.deleteKey);
                        }

                        utils.addEvent(defaults.textarea, 'keypress', action.filter);

                        utils.addEvent(defaults.textarea, 'keydown', function () {
                            utils._callHook('keydown');
                        });
                        utils.addEvent(defaults.textarea, 'keyup', function () {
                            utils._callHook('keyup');
                        });
                    }
                },
                init = function (opts) {

                    if (opts.textarea) {
                        utils._callHook('init:before', false);
                        utils.deepExtend(defaults, opts);
                        utils.defineNewLine();

                        if (defaults.softTabs) {
                            tab = " ".repeat(defaults.tabSize);
                        } else {
                            tab = "\t";

                            utils.defineTabSize(defaults.tabSize);
                        }

                        action.listen();
                        utils._callHook('init:after', false);
                    }

                };

            this.destroy = function () {
                utils.removeEvent(defaults.textarea, 'keydown', intercept.tabKey);
                utils.removeEvent(defaults.textarea, 'keydown', intercept.enterKey);
                utils.removeEvent(defaults.textarea, 'keydown', intercept.deleteKey);
                utils.removeEvent(defaults.textarea, 'keypress', action.filter);
            };

            init(userOpts);

        };

    if (typeof module !== 'undefined' && module.exports) {
        module.exports = Behave;
    }

    if (typeof ender === 'undefined') {
        this.Behave = Behave;
        this.BehaveHooks = BehaveHooks;
    }

    if (typeof define === "function" && define.amd) {
        define("behave", [], function () {
            return Behave;
        });
    }

}).call(this);




© 2015 - 2024 Weber Informatics LLC | Privacy Policy