diff --git a/build/jquery.notebook.min.css b/build/jquery.notebook.min.css index a0fb2d4..071fa61 100644 --- a/build/jquery.notebook.min.css +++ b/build/jquery.notebook.min.css @@ -1 +1 @@ -.jquery-notebook.editor{position:relative;outline:0;min-height:50px}.jquery-notebook.editor p{z-index:2;position:relative;min-height:1px}.jquery-notebook.editor p.placeholder{position:absolute;z-index:1;opacity:.5;pointer-events:none}.jquery-notebook p:first-child,.jquery-notebook p.placeholder+p{margin-top:0}.jquery-notebook.bubble{position:absolute;z-index:3;opacity:1;height:43px;left:0;top:0;opacity:0;border-radius:5px;-webkit-box-shadow:2px 2px 2px -1px rgba(0,0,0,.7),inset 0 0 1px rgba(255,255,255,.07),inset 0 0 2px rgba(255,255,255,.15000000000000002);box-shadow:2px 2px 2px -1px rgba(0,0,0,.7),inset 0 0 1px rgba(255,255,255,.07),inset 0 0 2px rgba(255,255,255,.15000000000000002);background:#323232;-webkit-transition:.5s ease-in-out;transition:.5s ease-in-out}.jquery-notebook.bubble.active{opacity:1}.jquery-notebook.bubble:after{content:'';display:block;position:absolute;left:50%;bottom:-3px;margin-left:-4px;width:8px;height:8px;-webkit-transform:rotate(45deg);-ms-transform:rotate(45deg);transform:rotate(45deg);background:#323232;-webkit-box-shadow:0 0 2px #262625;box-shadow:0 0 2px #262625}.jquery-notebook.bubble ul{padding:0;margin:0;list-style:none}.jquery-notebook.bubble ul li{display:inline}.jquery-notebook.bubble button{outline:0;border:0;background:transparent;width:41px;height:42px;font-family:FontAwesome;color:#fff;font-size:14pt;cursor:pointer;margin-top:0}.jquery-notebook.bubble button.active{color:#1ed228}.jquery-notebook.bubble button.bold:after{content:"\f032"}.jquery-notebook.bubble button.italic:after{content:"\f033"}.jquery-notebook.bubble button.underline:after{content:"\f0cd"}.jquery-notebook.bubble button.anchor:after{content:"\f0c1"}.jquery-notebook.bubble button.paste:after{content:"\f0ea"}.jquery-notebook.bubble button.h1:after{font-family:inherit;content:"h1"}.jquery-notebook.bubble button.h2:after{font-family:inherit;content:"h2"}.jquery-notebook.bubble button.ul:after{font-family:inherit;content:"\f0ca"}.jquery-notebook.bubble button.ol:after{font-family:inherit;content:"\f0cb"}.jquery-notebook .link-area{display:none}.jquery-notebook .link-area button{float:left}.jquery-notebook .link-area button:after{content:"\f00d"}.jquery-notebook input[type=text]{width:220px;height:28px;margin:6px 0 0 10px;background:0;border:0;outline:0;color:#fff;font-size:14px;float:left} \ No newline at end of file +.jquery-notebook.editor{position:relative;outline:0;min-height:50px}.jquery-notebook.editor p{z-index:2;position:relative;min-height:1px}.jquery-notebook.editor p.placeholder{position:absolute;z-index:1;opacity:.5;pointer-events:none}.jquery-notebook p:first-child,.jquery-notebook p.placeholder+p{margin-top:0}.jquery-notebook.bubble{position:absolute;z-index:3;opacity:1;height:43px;left:0;top:0;opacity:0;border-radius:5px;border:1px solid #1C1C1B;-webkit-box-shadow:0 2px 3px rgba(0,0,0,.2),inset 0 0 2px rgba(255,255,255,.2);box-shadow:0 2px 3px rgba(0,0,0,.2),inset 0 0 2px rgba(255,255,255,.2);background:#373735;background:-webkit-gradient(linear,left top,left bottom,color-stop(0%,rgba(55,55,53,1)),color-stop(100%,rgba(40,40,39,1)));background:-webkit-linear-gradient(top,rgba(55,55,53,1) 0,rgba(40,40,39,1) 100%);background:-webkit-gradient(linear,left top,left bottom,from(rgba(55,55,53,1)),to(rgba(40,40,39,1)));background:-webkit-linear-gradient(top,rgba(55,55,53,1) 0,rgba(40,40,39,1) 100%);background:linear-gradient(to bottom,rgba(55,55,53,1) 0,rgba(40,40,39,1) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#373735', endColorstr='#282827', GradientType=0);-webkit-transition:.15s ease-in-out;transition:.15s ease-in-out;-webkit-transition:.15s ease-in-out}.jquery-notebook.bubble.active{opacity:1}.jquery-notebook.bubble.jump{-webkit-transition:opacity .15s;transition:opacity .15s;-webkit-transition:opacity .15s}.jquery-notebook.bubble:after{content:'';display:block;position:absolute;left:50%;bottom:-6px;margin-left:-8px;width:16px;height:16px;-webkit-transform:rotate(45deg);-ms-transform:rotate(45deg);transform:rotate(45deg);background:#282827;-webkit-box-shadow:2px 2px 1px rgba(0,0,0,.1);box-shadow:2px 2px 1px rgba(0,0,0,.1)}.jquery-notebook.bubble ul{padding:0;margin:0;list-style:none}.jquery-notebook.bubble ul li{display:inline}.jquery-notebook.bubble button{outline:0;border:0;background:transparent;width:41px;height:42px;font-family:FontAwesome;color:#fff;font-size:14pt;cursor:pointer}.jquery-notebook.bubble button.active{color:#60D778}.jquery-notebook.bubble button.bold:after{content:"\f032"}.jquery-notebook.bubble button.italic:after{content:"\f033"}.jquery-notebook.bubble button.underline:after{content:"\f0cd"}.jquery-notebook.bubble button.anchor:after{content:"\f0c1"}.jquery-notebook.bubble button.paste:after{content:"\f0ea"}.jquery-notebook.bubble button.h1:after{font-family:inherit;content:"h1"}.jquery-notebook.bubble button.h2:after{font-family:inherit;content:"h2"}.jquery-notebook.bubble button.ul:after{font-family:inherit;content:"\f0ca"}.jquery-notebook.bubble button.ol:after{font-family:inherit;content:"\f0cb"}.jquery-notebook .link-area{display:none}.jquery-notebook .link-area button{float:left}.jquery-notebook .link-area button:after{content:"\f00d"}.jquery-notebook input[type=text]{width:220px;height:28px;margin:6px 0 0 10px;background:0;border:0;outline:0;color:#fff;font-size:14px;float:left} \ No newline at end of file diff --git a/build/jquery.notebook.min.js b/build/jquery.notebook.min.js index 62583b2..eb1906a 100644 --- a/build/jquery.notebook.min.js +++ b/build/jquery.notebook.min.js @@ -1,403 +1 @@ -! function(e, t, n) { - var o, i = function() { - var e = function(e) { - return e && "none" != e ? e.match(/(-?[0-9\.]+)/g) : [1, 0, 0, 1, 0, 0] - }, t = function(e) { - return e.css("-webkit-transform") || e.css("transform") || e.css("-moz-transform") || e.css("-o-transform") || e.css("-ms-transform") - }, n = function(n) { - var o = t(n); - return e(o) - }, o = function(e, t) { - e.css("-webkit-transform", t), e.css("-moz-transform", t), e.css("-o-transform", t), e.css("-ms-transform", t), e.css("transform", t) - }, i = function(e) { - return "matrix(" + e[0] + ", " + e[1] + ", " + e[2] + ", " + e[3] + ", " + e[4] + ", " + e[5] + ")" - }, a = function(e) { - var t = n(e); - return { - x: parseInt(t[4]), - y: parseInt(t[5]) - } - }, l = function(e, t) { - var a = n(e); - a[0] = a[3] = t; - var l = i(a); - o(e, l) - }, c = function(e, t, a) { - var l = n(e); - l[4] = t, l[5] = a; - var c = i(l); - o(e, c) - }, r = function(e, t) { - var a = n(e), - l = t * (Math.PI / 180), - c = -1 * l; - a[1] = l, a[2] = c; - var r = i(a); - o(e, r) - }; - return { - scale: l, - translate: c, - rotate: r, - getTranslate: a - } - }(), - a = "MacIntel" == n.navigator.platform, - l = 0, - c = 0, - r = { - command: !1, - shift: !1, - isSelecting: !1 - }, s = { - 66: "bold", - 73: "italic", - 85: "underline", - 112: "h1", - 113: "h2", - 122: "undo" - }, u = { - keyboard: { - isCommand: function(e, t, n) { - a && e.metaKey || !a && e.ctrlKey ? t() : n() - }, - isShift: function(e, t, n) { - e.shiftKey ? t() : n() - }, - isModifier: function(e, t) { - var n = e.which, - o = s[n]; - o && t.call(this, o) - }, - isEnter: function(e, t) { - 13 === e.which && t() - }, - isArrow: function(e, t) { - (e.which >= 37 || e.which <= 40) && t() - } - }, - html: { - addTag: function(n, o, i, a) { - var l = e(t.createElement(o)); - return l.attr("contenteditable", Boolean(a)), l.append(" "), n.append(l), i && (r.focusedElement = n.children().last(), u.cursor.set(n, 0, r.focusedElement)), l - } - }, - cursor: { - set: function(e, o, i) { - var a; - if (t.createRange) { - a = t.createRange(); - var l = n.getSelection(), - c = e.children().last(), - r = c.html().length - 1, - s = i ? i[0] : c[0], - u = "undefined" != typeof o ? o : r; - a.setStart(s, u), a.collapse(!0), l.removeAllRanges(), l.addRange(a) - } else a = t.body.createTextRange(), a.moveToElementText(i), a.collapse(!1), a.select() - } - }, - selection: { - save: function() { - if (n.getSelection) { - var e = n.getSelection(); - if (e.rangeCount > 0) return e.getRangeAt(0) - } else if (t.selection && t.selection.createRange) return t.selection.createRange(); - return null - }, - restore: function(e) { - if (e) - if (n.getSelection) { - var o = n.getSelection(); - o.removeAllRanges(), o.addRange(e) - } else t.selection && e.select && e.select() - }, - getText: function() { - var e = ""; - return n.getSelection ? e = n.getSelection().toString() : t.getSelection ? e = t.getSelection().toString() : t.selection && (e = t.selection.createRange().text), e - }, - clear: function() { - window.getSelection ? window.getSelection().empty ? window.getSelection().empty() : window.getSelection().removeAllRanges && window.getSelection().removeAllRanges() : document.selection && document.selection.empty() - }, - getContainer: function(e) { - return n.getSelection && e && e.commonAncestorContainer ? e.commonAncestorContainer : t.selection && e && e.parentElement ? e.parentElement() : null - } - }, - validation: { - isUrl: function(e) { - return /^(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$/.test(e) - } - } - }, d = { - updatePos: function(t, o) { - var a = n.getSelection(), - l = a.getRangeAt(0), - c = l.getBoundingClientRect(), - r = o.width(), - s = o.height(), - u = (t.offset().left, { - x: c.left + c.width / 2 - r / 2, - y: c.top - s - 8 + e(document).scrollTop() - }); - i.translate(o, u.x, u.y) - }, - updateState: function(e, t) { - t.find("button").removeClass("active"); - var o = n.getSelection(), - i = []; - d.checkForFormatting(o.focusNode, i); - for (var a = { - b: "bold", - i: "italic", - h1: "h1", - h2: "h2", - a: "anchor", - ul: "ul", - ol: "ol" - }, l = 0; l < i.length; l++) { - var c = i[l]; - t.find("button." + a[c]).addClass("active") - } - }, - checkForFormatting: function(e, t) { - var n = ["b", "i", "u", "h1", "h2", "ol", "ul", "li", "a"]; - ("#text" === e.nodeName || -1 != n.indexOf(e.nodeName.toLowerCase())) && ("#text" != e.nodeName && t.push(e.nodeName.toLowerCase()), d.checkForFormatting(e.parentNode, t)) - }, - buildMenu: function(t, n) { - var i = u.html.addTag(n, "ul", !1, !1); - for (var a in o.modifiers) { - var l = u.html.addTag(i, "li", !1, !1), - c = u.html.addTag(l, "button", !1, !1); - c.attr("editor-command", o.modifiers[a]), c.addClass(o.modifiers[a]) - } - n.find("button").click(function(n) { - n.preventDefault(); - var o = e(this).attr("editor-command"); - m.commands[o].call(t, n) - }); - var r = u.html.addTag(n, "div", !1, !1); - r.addClass("link-area"); - var s = u.html.addTag(r, "input", !1, !1); - s.attr({ - type: "text" - }); - var d = u.html.addTag(r, "button", !1, !1); - d.click(function(t) { - t.preventDefault(); - e(this).closest(".editor"); - e(this).closest(".link-area").hide(), e(this).closest(".bubble").find("ul").show() - }) - }, - show: function() { - var t = e(this).parent().find(".bubble"); - t.length || (t = u.html.addTag(e(this).parent(), "div", !1, !1), t.addClass("jquery-notebook bubble"), d.buildMenu(this, t)), t.show(), d.updateState(this, t), t.addClass("active"), d.updatePos(e(this), t) - }, - update: function() { - var t = e(this).parent().find(".bubble"); - d.updateState(this, t) - }, - clear: function() { - var t = e(this).parent().find(".bubble"); - t.hasClass("active") && (t.removeClass("active"), d.hideLinkInput.call(this), d.showButtons.call(this), setTimeout(function() { - t.hasClass("active") || t.hide() - }, 500)) - }, - hideButtons: function() { - e(this).parent().find(".bubble").find("ul").hide() - }, - showButtons: function() { - e(this).parent().find(".bubble").find("ul").show() - }, - showLinkInput: function(t) { - d.hideButtons.call(this); - var n = this, - o = e(this).parent().find(".bubble").find("input[type=text]"), - i = o.closest(".jquery-notebook").find("button.anchor").hasClass("active"); - o.unbind("keydown"), o.keydown(function(o) { - var a = e(this); - u.keyboard.isEnter(o, function() { - o.preventDefault(); - var e = a.val(); - u.validation.isUrl(e) ? (o.url = e, m.commands.createLink(o, t), d.clear.call(n)) : "" === e && i && (m.commands.removeLink(o, t), d.clear.call(n)) - }) - }), o.bind("paste", function() { - var t = e(this); - setTimeout(function() { - var e = t.val(); - /http:\/\/https?:\/\//.test(e) && (e = e.substring(7), t.val(e)) - }, 1) - }); - var a = "http://"; - if (i) { - var l = e(u.selection.getContainer(t)).closest("a"); - a = l.prop("href") || a - } - e(this).parent().find(".link-area").show(), o.val(a).focus() - }, - hideLinkInput: function() { - e(this).parent().find(".bubble").find(".link-area").hide() - } - }, f = { - bindEvents: function(t) { - t.keydown(h.keydown), t.keyup(h.keyup), t.focus(h.focus), t.bind("paste", m.paste), t.mousedown(h.mouseClick), t.mouseup(h.mouseUp), t.mousemove(h.mouseMove), t.blur(h.blur), e("body").mouseup(function(e) { - e.target == e.currentTarget && r.isSelecting && h.mouseUp.call(t, e) - }) - }, - setPlaceholder: function(t) { - if (/^\s*$/.test(e(this).text())) { - e(this).empty(); - var n = u.html.addTag(e(this), "p").addClass("placeholder"); - n.append(e(this).attr("editor-placeholder")), u.html.addTag(e(this), "p", "undefined" != typeof t.focus ? t.focus : !1, !0) - } else e(this).find(".placeholder").remove() - }, - removePlaceholder: function() { - e(this).find(".placeholder").remove() - }, - preserveElementFocus: function() { - var e = n.getSelection() ? n.getSelection().anchorNode : t.activeElement; - if (e) { - var o = e.parentNode, - i = o !== r.focusedElement, - a = this.children, - l = 0; - o === this && (o = e); - for (var c = 0; c < a.length; c++) - if (o === a[c]) { - l = c; - break - } - i && (r.focusedElement = o, r.focusedElementIndex = l) - } - }, - prepare: function(e, t) { - if (o = t, e.attr("editor-mode", o.mode), e.attr("editor-placeholder", o.placeholder), e.attr("contenteditable", !0), e.css("position", "relative"), e.addClass("jquery-notebook editor"), f.setPlaceholder.call(e, {}), f.preserveElementFocus.call(e), o.autoFocus === !0) { - var n = e.find("p:not(.placeholder)"); - u.cursor.set(e, 0, n) - } - } - }, h = { - keydown: function(e) { - var t = this; - r.command && 65 === e.which && setTimeout(function() { - d.show.call(t) - }, 50), u.keyboard.isCommand(e, function() { - r.command = !0 - }, function() { - r.command = !1 - }), u.keyboard.isShift(e, function() { - r.shift = !0 - }, function() { - r.shift = !1 - }), u.keyboard.isModifier.call(this, e, function(t) { - r.command && m.commands[t].call(this, e) - }), r.shift ? u.keyboard.isArrow.call(this, e, function() { - setTimeout(function() { - var e = u.selection.getText(); - "" !== e ? d.show.call(t) : d.clear.call(t) - }, 100) - }) : u.keyboard.isArrow.call(this, e, function() { - d.clear.call(t) - }), 13 === e.which && m.enterKey.call(this, e), 27 === e.which && d.clear.call(this), 86 === e.which && m.paste.call(this, e) - }, - keyup: function(t) { - u.keyboard.isCommand(t, function() { - r.command = !1 - }, function() { - r.command = !0 - }), f.preserveElementFocus.call(this), f.removePlaceholder.call(this), /^\s*$/.test(e(this).text()) && (e(this).empty(), u.html.addTag(e(this), "p", !0, !0)) - }, - focus: function() { - r.command = !1, r.shift = !1 - }, - mouseClick: function(t) { - var n = this; - if (r.isSelecting = !0, 2 === t.button) return setTimeout(function() { - d.show.call(n) - }, 50), void t.preventDefault(); - if (e(this).find(".bubble:visible").length) { - var o = e(this).find(".bubble:visible"), - i = o.offset().left, - a = o.offset().top, - s = o.width(), - u = o.height(); - if (l > i && i + s > l && c > a && a + u > c) return - } - }, - mouseUp: function(e) { - e.preventDefault(); - var t = this; - r.isSelecting = !1, setTimeout(function() { - var e = u.selection.save(); - e.collapsed ? d.clear.call(t) : d.show.call(t) - }, 50) - }, - mouseMove: function(e) { - l = e.pageX, c = e.pageY - }, - blur: function() { - f.setPlaceholder.call(this, { - focus: !1 - }) - } - }, m = { - commands: { - bold: function(e) { - e.preventDefault(), t.execCommand("bold", !1), d.update.call(this) - }, - italic: function(e) { - e.preventDefault(), t.execCommand("italic", !1), d.update.call(this) - }, - underline: function(e) { - e.preventDefault(), t.execCommand("underline", !1), d.update.call(this) - }, - anchor: function(e) { - e.preventDefault(); - var t = u.selection.save(); - d.showLinkInput.call(this, t) - }, - createLink: function(e, n) { - u.selection.restore(n), t.execCommand("createLink", !1, e.url), d.update.call(this) - }, - removeLink: function(t, n) { - var o = e(u.selection.getContainer(n)).closest("a"); - o.contents().first().unwrap() - }, - h1: function(n) { - n.preventDefault(), e(window.getSelection().anchorNode.parentNode).is("h1") ? t.execCommand("formatBlock", !1, "

") : t.execCommand("formatBlock", !1, "

"), d.update.call(this) - }, - h2: function(n) { - n.preventDefault(), e(window.getSelection().anchorNode.parentNode).is("h2") ? t.execCommand("formatBlock", !1, "

") : t.execCommand("formatBlock", !1, "

"), d.update.call(this) - }, - ul: function(e) { - e.preventDefault(), t.execCommand("insertUnorderedList", !1), d.update.call(this) - }, - ol: function(e) { - e.preventDefault(), t.execCommand("insertOrderedList", !1), d.update.call(this) - }, - undo: function(e) { - e.preventDefault(), t.execCommand("undo", !1) - } - }, - enterKey: function(t) { - return "inline" === e(this).attr("editor-mode") ? void t.preventDefault() : void 0 - }, - paste: function() { - var t = e(this); - setTimeout(function() { - t.find("*").each(function() { - var t = e(this); - e.each(this.attributes, function() { - "class" === this.name && t.hasClass("placeholder") || t.removeAttr(this.name) - }) - }) - }, 100) - } - }; - e.fn.notebook = function(t) { - return t = e.extend({}, e.fn.notebook.defaults, t), f.prepare(this, t), f.bindEvents(this), this - }, e.fn.notebook.defaults = { - autoFocus: !1, - placeholder: "Your text here...", - mode: "multiline", - modifiers: ["bold", "italic", "underline", "h1", "h2", "ol", "ul", "anchor"] - } -}(jQuery, document, window); \ No newline at end of file +!function(e,t,n){var o=function(){var e=function(e){return e&&"none"!=e?e.match(/(-?[0-9\.]+)/g):[1,0,0,1,0,0]},t=function(e){return e.css("-webkit-transform")||e.css("transform")||e.css("-moz-transform")||e.css("-o-transform")||e.css("-ms-transform")},n=function(n){var o=t(n);return e(o)},o=function(e,t){e.css("-webkit-transform",t),e.css("-moz-transform",t),e.css("-o-transform",t),e.css("-ms-transform",t),e.css("transform",t)},i=function(e){return"matrix("+e[0]+", "+e[1]+", "+e[2]+", "+e[3]+", "+e[4]+", "+e[5]+")"},a=function(e){var t=n(e);return{x:parseInt(t[4]),y:parseInt(t[5])}},l=function(e,t){var a=n(e);a[0]=a[3]=t;var l=i(a);o(e,l)},r=function(e,t,a){var l=n(e);l[4]=t,l[5]=a;var r=i(l);o(e,r)},s=function(e,t){var a=n(e),l=t*(Math.PI/180),r=-1*l;a[1]=l,a[2]=r;var s=i(a);o(e,s)};return{scale:l,translate:r,rotate:s,getTranslate:a}}(),i=function(o,i){var r=this,s=0,c=0,u={command:!1,shift:!1,isSelecting:!1};e.extend(r,{init:function(){r.element=e(o),r.options=i,r.utils=new a,r.bubble=new l(r),r.prepare(),r.bindEvents()},bindEvents:function(){r.element.keydown(r.rawEvents.keydown),r.element.keyup(r.rawEvents.keyup),r.element.focus(r.rawEvents.focus),r.element.bind("paste",r.events.paste),r.element.mousedown(r.rawEvents.mouseClick),r.element.mouseup(r.rawEvents.mouseUp),r.element.mousemove(r.rawEvents.mouseMove),r.element.blur(r.rawEvents.blur),e("body").mouseup(function(e){e.target==e.currentTarget&&u.isSelecting&&r.rawEvents.mouseUp(e)})},setPlaceholder:function(e){if(/^\s*$/.test(r.element.text())){r.element.empty();var t=r.utils.html.addTag(r.element,"p").addClass("placeholder");t.append(r.element.attr("editor-placeholder")),r.utils.html.addTag(r.element,"p","undefined"!=typeof e.focus?e.focus:!1,!0)}else r.element.find(".placeholder").remove()},removePlaceholder:function(){r.element.find(".placeholder").remove()},preserveElementFocus:function(){var e=n.getSelection()?n.getSelection().anchorNode:t.activeElement;if(e){var o=e.parentNode,i=o!==u.focusedElement,a=r.element[0].children,l=0;o===r.element[0]&&(o=e);for(var s=0;sn&&n+i>s&&c>o&&o+a>c)return}},mouseUp:function(e){e.preventDefault(),u.isSelecting=!1,setTimeout(function(){var e=r.utils.selection.save();e.collapsed?r.bubble.clear():r.bubble.show()},50)},mouseMove:function(e){s=e.pageX,c=e.pageY},blur:function(){r.setPlaceholder({focus:!1})}},events:{commands:{bold:function(e){e.preventDefault(),t.execCommand("bold",!1),r.bubble.update()},italic:function(e){e.preventDefault(),t.execCommand("italic",!1),r.bubble.update()},underline:function(e){e.preventDefault(),t.execCommand("underline",!1),r.bubble.update()},anchor:function(e){e.preventDefault();var t=r.utils.selection.save();r.bubble.showLinkInput(t)},createLink:function(e,n){r.utils.selection.restore(n),t.execCommand("createLink",!1,e.url),r.bubble.update()},removeLink:function(t,n){var o=e(r.utils.selection.getContainer(n)).closest("a");o.contents().first().unwrap()},h1:function(n){n.preventDefault(),e(window.getSelection().anchorNode.parentNode).is("h1")?t.execCommand("formatBlock",!1,"

"):t.execCommand("formatBlock",!1,"

"),r.bubble.update()},h2:function(n){n.preventDefault(),e(window.getSelection().anchorNode.parentNode).is("h2")?t.execCommand("formatBlock",!1,"

"):t.execCommand("formatBlock",!1,"

"),r.bubble.update()},ul:function(e){e.preventDefault(),t.execCommand("insertUnorderedList",!1),r.bubble.update()},ol:function(e){e.preventDefault(),t.execCommand("insertOrderedList",!1),r.bubble.update()},undo:function(e){e.preventDefault(),t.execCommand("undo",!1)}},enterKey:function(e){return"inline"===r.element.attr("editor-mode")?void e.preventDefault():void 0},paste:function(){setTimeout(function(){r.element.find("*").each(function(){var t=e(this);e.each(this.attributes,function(){"class"===this.name&&t.hasClass("placeholder")||t.removeAttr(this.name)})})},100)}}}),r.init()},a=function(){var o,i;i=this,o="MacIntel"==n.navigator.platform,e.extend(this,{keyboard:{isCommand:function(e,t,n){o&&e.metaKey||!o&&e.ctrlKey?t():n()},isShift:function(e,t,n){e.shiftKey?t():n()},isModifier:function(e,t){var n=e.which,o=modifiers[n];o&&t(o)},isEnter:function(e,t){13===e.which&&t()},isArrow:function(e,t){(e.which>=37||e.which<=40)&&t()}},html:{addTag:function(n,o,i,a){var l=e(t.createElement(o));return l.attr("contenteditable",Boolean(a)),l.append(" "),n.append(l),i&&(cache.focusedElement=n.children().last(),this.cursor.set(n,0,cache.focusedElement)),l},decode:function(t){return e("
").html(t).text()}},cursor:{set:function(e,o,i){var a;if(t.createRange){a=t.createRange();var l=n.getSelection(),r=e.children().last(),s=r.html().length-1,c=i?i[0]:r[0],u="undefined"!=typeof o?o:s;a.setStart(c,u),a.collapse(!0),l.removeAllRanges(),l.addRange(a)}else a=t.body.createTextRange(),a.moveToElementText(i),a.collapse(!1),a.select()}},selection:{save:function(){if(n.getSelection){var e=n.getSelection();if(e.rangeCount>0)return e.getRangeAt(0)}else if(t.selection&&t.selection.createRange)return t.selection.createRange();return null},restore:function(e){if(e)if(n.getSelection){var o=n.getSelection();o.removeAllRanges(),o.addRange(e)}else t.selection&&e.select&&e.select()},getText:function(){var e="";return n.getSelection?e=n.getSelection().toString():t.getSelection?e=t.getSelection().toString():t.selection&&(e=t.selection.createRange().text),e},clear:function(){window.getSelection?window.getSelection().empty?window.getSelection().empty():window.getSelection().removeAllRanges&&window.getSelection().removeAllRanges():document.selection&&document.selection.empty()},getContainer:function(e){return n.getSelection&&e&&e.commonAncestorContainer?e.commonAncestorContainer:t.selection&&e&&e.parentElement?e.parentElement():null}},validation:{isUrl:function(e){return/^(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$/.test(e)}}})},l=function(t){var i=this;e.extend(i,{isVisible:function(){return i.element.is(":visible")},updatePos:function(){var t=n.getSelection(),a=t.getRangeAt(0),l=a.getBoundingClientRect(),r=i.element.width(),s=i.element.height(),c=(i.notebook.element.offset().left,{x:l.left+l.width/2-r/2,y:l.top-s-8+e(document).scrollTop()});o.translate(i.element,c.x,c.y)},updateState:function(){i.element.find("button").removeClass("active");var e=n.getSelection(),t=[];i.checkForFormatting(e.focusNode,t);for(var o={b:"bold",i:"italic",u:"underline",h1:"h1",h2:"h2",a:"anchor",ul:"ul",ol:"ol"},a=0;a bubbleX && mouseX < bubbleX + bubbleWidth && + mouseY > bubbleY && mouseY < bubbleY + bubbleHeight) { + return; + } + } + }, + mouseUp: function(e) { + e.preventDefault(); + cache.isSelecting = false; + setTimeout(function() { + var s = self.utils.selection.save(); + if (s.collapsed) { + self.bubble.clear(); + } else { + self.bubble.show(); + } + }, 50); + }, + mouseMove: function(e) { + mouseX = e.pageX; + mouseY = e.pageY; + }, + blur: function(e) { + self.setPlaceholder({ + focus: false + }); + } + }, + events: { + commands: { + bold: function(e) { + e.preventDefault(); + d.execCommand('bold', false); + self.bubble.update(); + }, + italic: function(e) { + e.preventDefault(); + d.execCommand('italic', false); + self.bubble.update(); + }, + underline: function(e) { + e.preventDefault(); + d.execCommand('underline', false); + self.bubble.update(); + }, + anchor: function(e) { + e.preventDefault(); + var s = self.utils.selection.save(); + self.bubble.showLinkInput(s); + }, + createLink: function(e, s) { + self.utils.selection.restore(s); + d.execCommand('createLink', false, e.url); + self.bubble.update(); + }, + removeLink: function(e, s) { + var el = $(self.utils.selection.getContainer(s)).closest('a'); + el.contents().first().unwrap(); + }, + h1: function(e) { + e.preventDefault(); + if ($(window.getSelection().anchorNode.parentNode).is('h1')) { + d.execCommand('formatBlock', false, '

'); + } else { + d.execCommand('formatBlock', false, '

'); + } + self.bubble.update(); + }, + h2: function(e) { + e.preventDefault(); + if ($(window.getSelection().anchorNode.parentNode).is('h2')) { + d.execCommand('formatBlock', false, '

'); + } else { + d.execCommand('formatBlock', false, '

'); + } + self.bubble.update(); + }, + ul: function(e) { + e.preventDefault(); + d.execCommand('insertUnorderedList', false); + self.bubble.update(); + }, + ol: function(e) { + e.preventDefault(); + d.execCommand('insertOrderedList', false); + self.bubble.update(); + }, + undo: function(e) { + e.preventDefault(); + d.execCommand('undo', false); + } + }, + enterKey: function(e) { + if (self.element.attr('editor-mode') === 'inline') { + e.preventDefault(); + return; + } + }, + paste: function(e) { + setTimeout(function() { + self.element.find('*').each(function() { + var current = $(this); + $.each(this.attributes, function() { + if (this.name !== 'class' || !current.hasClass('placeholder')) { + current.removeAttr(this.name); + } + }); + }); + }, 100); + } + } + }); + self.init(); + }; + + var Utils = function() { + var isMac, self; + self = this; + isMac = w.navigator.platform == 'MacIntel'; + $.extend(this, { keyboard: { isCommand: function(e, callbackTrue, callbackFalse) { if (isMac && e.metaKey || !isMac && e.ctrlKey) { @@ -137,7 +420,7 @@ var key = e.which, cmd = modifiers[key]; if (cmd) { - callback.call(this, cmd); + callback(cmd); } }, isEnter: function(e, callback) { @@ -159,9 +442,12 @@ elem.append(newElement); if (focus) { cache.focusedElement = elem.children().last(); - utils.cursor.set(elem, 0, cache.focusedElement); + this.cursor.set(elem, 0, cache.focusedElement); } return newElement; + }, + decode: function(str) { + return $('
').html(str).text(); } }, cursor: { @@ -245,32 +531,39 @@ return (/^(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$/).test(url); } } - }, - bubble = { + }); + }; + + var notebookBubble = function(editor) { + var self = this; + $.extend(self, { /* * This is called to position the bubble above the selection. */ - updatePos: function(editor, elem) { + isVisible: function() { + return self.element.is(':visible'); + }, + updatePos: function() { var sel = w.getSelection(), range = sel.getRangeAt(0), boundary = range.getBoundingClientRect(), - bubbleWidth = elem.width(), - bubbleHeight = elem.height(), - offset = editor.offset().left, + bubbleWidth = self.element.width(), + bubbleHeight = self.element.height(), + offset = self.notebook.element.offset().left, pos = { x: (boundary.left + boundary.width / 2) - bubbleWidth / 2, y: boundary.top - bubbleHeight - 8 + $(document).scrollTop() }; - transform.translate(elem, pos.x, pos.y); + transform.translate(self.element, pos.x, pos.y); }, /* * Updates the bubble to set the active formats for the current selection. */ - updateState: function(editor, elem) { - elem.find('button').removeClass('active'); + updateState: function() { + self.element.find('button').removeClass('active'); var sel = w.getSelection(), formats = []; - bubble.checkForFormatting(sel.focusNode, formats); + self.checkForFormatting(sel.focusNode, formats); var formatDict = { 'b': 'bold', 'i': 'italic', @@ -283,7 +576,7 @@ }; for (var i = 0; i < formats.length; i++) { var format = formats[i]; - elem.find('button.' + formatDict[format]).addClass('active'); + self.element.find('button.' + formatDict[format]).addClass('active'); } }, /* @@ -297,92 +590,86 @@ if (currentNode.nodeName != '#text') { formats.push(currentNode.nodeName.toLowerCase()); } - bubble.checkForFormatting(currentNode.parentNode, formats); + self.checkForFormatting(currentNode.parentNode, formats); } }, - buildMenu: function(editor, elem) { - var ul = utils.html.addTag(elem, 'ul', false, false); - for (var cmd in options.modifiers) { - var li = utils.html.addTag(ul, 'li', false, false); - var btn = utils.html.addTag(li, 'button', false, false); - btn.attr('editor-command', options.modifiers[cmd]); - btn.addClass(options.modifiers[cmd]); + buildMenu: function() { + var ul = self.notebook.utils.html.addTag(self.element, 'ul', false, false); + for (var cmd in self.notebook.options.modifiers) { + var li = self.notebook.utils.html.addTag(ul, 'li', false, false); + var btn = self.notebook.utils.html.addTag(li, 'button', false, false); + btn.attr('editor-command', self.notebook.options.modifiers[cmd]); + btn.addClass(self.notebook.options.modifiers[cmd]); } - elem.find('button').click(function(e) { + self.element.find('button').click(function(e) { e.preventDefault(); var cmd = $(this).attr('editor-command'); - events.commands[cmd].call(editor, e); + self.notebook.events.commands[cmd](e); }); - var linkArea = utils.html.addTag(elem, 'div', false, false); + var linkArea = self.notebook.utils.html.addTag(self.element, 'div', false, false); linkArea.addClass('link-area'); - var linkInput = utils.html.addTag(linkArea, 'input', false, false); + var linkInput = self.notebook.utils.html.addTag(linkArea, 'input', false, false); linkInput.attr({ type: 'text' }); - var closeBtn = utils.html.addTag(linkArea, 'button', false, false); + var closeBtn = self.notebook.utils.html.addTag(linkArea, 'button', false, false); closeBtn.click(function(e) { e.preventDefault(); - var editor = $(this).closest('.editor'); $(this).closest('.link-area').hide(); - $(this).closest('.bubble').find('ul').show(); + self.element.find('ul').show(); }); }, + init: function(editor) { + self.notebook = editor; + + self.element = self.notebook.utils.html.addTag(self.notebook.element.parent(), 'div', false, false); + self.element.addClass('jquery-notebook bubble'); + self.buildMenu(); + }, show: function() { - var tag = $(this).parent().find('.bubble'); - if (!tag.length) { - tag = utils.html.addTag($(this).parent(), 'div', false, false); - tag.addClass('jquery-notebook bubble'); - bubble.buildMenu(this, tag); - } - tag.show(); - bubble.updateState(this, tag); - if (!tag.hasClass('active')) { - tag.addClass('jump'); - } else { - tag.removeClass('jump'); - } - bubble.updatePos($(this), tag); - tag.addClass('active'); + self.element.show(); + self.updateState(); + self.element.toggleClass('jump'); + self.updatePos(); + self.element.addClass('active'); }, update: function() { - var tag = $(this).parent().find('.bubble'); - bubble.updateState(this, tag); + self.updateState(); }, clear: function() { - var elem = $(this).parent().find('.bubble'); - if (!elem.hasClass('active')) return; - elem.removeClass('active'); - bubble.hideLinkInput.call(this); - bubble.showButtons.call(this); + if (!self.element.hasClass('active')) return; + self.element.removeClass('active'); + self.hideLinkInput(); + self.showButtons(); setTimeout(function() { - if (elem.hasClass('active')) return; - elem.hide(); + if (self.element.hasClass('active')) return; + self.element.hide(); }, 500); }, hideButtons: function() { - $(this).parent().find('.bubble').find('ul').hide(); + self.element.find('ul').hide(); }, showButtons: function() { - $(this).parent().find('.bubble').find('ul').show(); + self.element.find('ul').show(); }, showLinkInput: function(selection) { - bubble.hideButtons.call(this); - var editor = this; - var elem = $(this).parent().find('.bubble').find('input[type=text]'); - var hasLink = elem.closest('.jquery-notebook').find('button.anchor').hasClass('active'); + self.hideButtons(); + var elem, hasLink; + elem = self.element.find('input[type=text]'); + hasLink = elem.closest('.jquery-notebook').find('button.anchor').hasClass('active'); elem.unbind('keydown'); elem.keydown(function(e) { - var elem = $(this); - utils.keyboard.isEnter(e, function() { + var el = $(this); + self.notebook.utils.keyboard.isEnter(e, function() { e.preventDefault(); - var url = elem.val(); - if (utils.validation.isUrl(url)) { + var url = el.val(); + if (self.notebook.utils.validation.isUrl(url)) { e.url = url; - events.commands.createLink(e, selection); - bubble.clear.call(editor); + self.notebook.events.commands.createLink(e, selection); + self.clear(); } else if (url === '' && hasLink) { - events.commands.removeLink(e, selection); - bubble.clear.call(editor); + self.notebook.events.commands.removeLink(e, selection); + self.clear(); } }); }); @@ -398,291 +685,26 @@ }); var linkText = 'http://'; if (hasLink) { - var anchor = $(utils.selection.getContainer(selection)).closest('a'); + var anchor = $(self.notebook.utils.selection.getContainer(selection)).closest('a'); linkText = anchor.prop('href') || linkText; } - $(this).parent().find('.link-area').show(); + self.notebook.element.parent().find('.link-area').show(); elem.val(linkText).focus(); }, hideLinkInput: function() { - $(this).parent().find('.bubble').find('.link-area').hide(); + self.element.find('.link-area').hide(); } - }, - actions = { - bindEvents: function(elem) { - elem.keydown(rawEvents.keydown); - elem.keyup(rawEvents.keyup); - elem.focus(rawEvents.focus); - elem.bind('paste', events.paste); - elem.mousedown(rawEvents.mouseClick); - elem.mouseup(rawEvents.mouseUp); - elem.mousemove(rawEvents.mouseMove); - elem.blur(rawEvents.blur); - $('body').mouseup(function(e) { - if (e.target == e.currentTarget && cache.isSelecting) { - rawEvents.mouseUp.call(elem, e); - } - }); - }, - setPlaceholder: function(e) { - if (/^\s*$/.test($(this).text())) { - $(this).empty(); - var placeholder = utils.html.addTag($(this), 'p').addClass('placeholder'); - placeholder.append($(this).attr('editor-placeholder')); - utils.html.addTag($(this), 'p', typeof e.focus != 'undefined' ? e.focus : false, true); - } else { - $(this).find('.placeholder').remove(); - } - }, - removePlaceholder: function(e) { - $(this).find('.placeholder').remove(); - }, - preserveElementFocus: function() { - var anchorNode = w.getSelection() ? w.getSelection().anchorNode : d.activeElement; - if (anchorNode) { - var current = anchorNode.parentNode, - diff = current !== cache.focusedElement, - children = this.children, - elementIndex = 0; - if (current === this) { - current = anchorNode; - } - for (var i = 0; i < children.length; i++) { - if (current === children[i]) { - elementIndex = i; - break; - } - } - if (diff) { - cache.focusedElement = current; - cache.focusedElementIndex = elementIndex; - } - } - }, - prepare: function(elem, customOptions) { - options = customOptions; - elem.attr('editor-mode', options.mode); - elem.attr('editor-placeholder', options.placeholder); - elem.attr('contenteditable', true); - elem.css('position', 'relative'); - elem.addClass('jquery-notebook editor'); - actions.setPlaceholder.call(elem, {}); - actions.preserveElementFocus.call(elem); - if (options.autoFocus === true) { - var firstP = elem.find('p:not(.placeholder)'); - utils.cursor.set(elem, 0, firstP); - } - } - }, - rawEvents = { - keydown: function(e) { - var elem = this; - if (cache.command && e.which === 65) { - setTimeout(function() { - bubble.show.call(elem); - }, 50); - } - utils.keyboard.isCommand(e, function() { - cache.command = true; - }, function() { - cache.command = false; - }); - utils.keyboard.isShift(e, function() { - cache.shift = true; - }, function() { - cache.shift = false; - }); - utils.keyboard.isModifier.call(this, e, function(modifier) { - if (cache.command) { - events.commands[modifier].call(this, e); - } - }); - - if (cache.shift) { - utils.keyboard.isArrow.call(this, e, function() { - setTimeout(function() { - var txt = utils.selection.getText(); - if (txt !== '') { - bubble.show.call(elem); - } else { - bubble.clear.call(elem); - } - }, 100); - }); - } else { - utils.keyboard.isArrow.call(this, e, function() { - bubble.clear.call(elem); - }); - } + }); - if (e.which === 13) { - events.enterKey.call(this, e); - } - if (e.which === 27) { - bubble.clear.call(this); - } - if (e.which === 86) { - events.paste.call(this, e); - } - }, - keyup: function(e) { - utils.keyboard.isCommand(e, function() { - cache.command = false; - }, function() { - cache.command = true; - }); - actions.preserveElementFocus.call(this); - actions.removePlaceholder.call(this); - - /* - * This breaks the undo when the whole text is deleted but so far - * it is the only way that I fould to solve the more serious bug - * that the editor was losing the p elements after deleting the whole text - */ - if (/^\s*$/.test($(this).text())) { - $(this).empty(); - utils.html.addTag($(this), 'p', true, true); - } - }, - focus: function(e) { - cache.command = false; - cache.shift = false; - }, - mouseClick: function(e) { - var elem = this; - cache.isSelecting = true; - if (e.button === 2) { - setTimeout(function() { - bubble.show.call(elem); - }, 50); - e.preventDefault(); - return; - } - if ($(this).find('.bubble:visible').length) { - var bubbleTag = $(this).find('.bubble:visible'), - bubbleX = bubbleTag.offset().left, - bubbleY = bubbleTag.offset().top, - bubbleWidth = bubbleTag.width(), - bubbleHeight = bubbleTag.height(); - if (mouseX > bubbleX && mouseX < bubbleX + bubbleWidth && - mouseY > bubbleY && mouseY < bubbleY + bubbleHeight) { - return; - } - } - }, - mouseUp: function(e) { - e.preventDefault(); - var elem = this; - cache.isSelecting = false; - setTimeout(function() { - var s = utils.selection.save(); - if (s.collapsed) { - bubble.clear.call(elem); - } else { - bubble.show.call(elem); - } - }, 50); - }, - mouseMove: function(e) { - mouseX = e.pageX; - mouseY = e.pageY; - }, - blur: function(e) { - actions.setPlaceholder.call(this, { - focus: false - }); - } - }, - events = { - commands: { - bold: function(e) { - e.preventDefault(); - d.execCommand('bold', false); - bubble.update.call(this); - }, - italic: function(e) { - e.preventDefault(); - d.execCommand('italic', false); - bubble.update.call(this); - }, - underline: function(e) { - e.preventDefault(); - d.execCommand('underline', false); - bubble.update.call(this); - }, - anchor: function(e) { - e.preventDefault(); - var s = utils.selection.save(); - bubble.showLinkInput.call(this, s); - }, - createLink: function(e, s) { - utils.selection.restore(s); - d.execCommand('createLink', false, e.url); - bubble.update.call(this); - }, - removeLink: function(e, s) { - var el = $(utils.selection.getContainer(s)).closest('a'); - el.contents().first().unwrap(); - }, - h1: function(e) { - e.preventDefault(); - if ($(window.getSelection().anchorNode.parentNode).is('h1')) { - d.execCommand('formatBlock', false, '

'); - } else { - d.execCommand('formatBlock', false, '

'); - } - bubble.update.call(this); - }, - h2: function(e) { - e.preventDefault(); - if ($(window.getSelection().anchorNode.parentNode).is('h2')) { - d.execCommand('formatBlock', false, '

'); - } else { - d.execCommand('formatBlock', false, '

'); - } - bubble.update.call(this); - }, - ul: function(e) { - e.preventDefault(); - d.execCommand('insertUnorderedList', false); - bubble.update.call(this); - }, - ol: function(e) { - e.preventDefault(); - d.execCommand('insertOrderedList', false); - bubble.update.call(this); - }, - undo: function(e) { - e.preventDefault(); - d.execCommand('undo', false); - } - }, - enterKey: function(e) { - if ($(this).attr('editor-mode') === 'inline') { - e.preventDefault(); - return; - } - }, - paste: function(e) { - var elem = $(this); - setTimeout(function() { - elem.find('*').each(function() { - var current = $(this); - $.each(this.attributes, function() { - if (this.name !== 'class' || !current.hasClass('placeholder')) { - current.removeAttr(this.name); - } - }); - }); - }, 100); - } - }; + self.init(editor); + }; $.fn.notebook = function(options) { options = $.extend({}, $.fn.notebook.defaults, options); - actions.prepare(this, options); - actions.bindEvents(this); - return this; + + return this.each(function() { + new Notebook(this, options); + }); }; $.fn.notebook.defaults = {