/* * 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){ 'use strict'; var BehaveHooks = BehaveHooks || (function(){ var hooks = {}; return { add: function(hookName, fn){ if(typeof hookName == "object"){ var i; for(i=0; i>> 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 -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=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