rendered paste body// ----------------------------------------------------------------------------// markItUp! Universal MarkUp Engine, JQuery plugin// v 1.1.5// Dual licensed under the MIT and GPL licenses.// ----------------------------------------------------------------------------// Copyright (C) 2007-2008 Jay Salvat// http://markitup.jaysalvat.com/// ----------------------------------------------------------------------------// Permission is hereby granted, free of charge, to any person obtaining a copy// of this software and associated documentation files (the "Software"), to deal// in the Software without restriction, including without limitation the rights// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell// copies of the Software, and to permit persons to whom the Software is// furnished to do so, subject to the following conditions:// // The above copyright notice and this permission notice shall be included in// all copies or substantial portions of the Software.// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN// THE SOFTWARE.// ----------------------------------------------------------------------------(function($) { $.fn.markup = function(settings, extraSettings) { var options, miu, ctrlKey, shiftKey, altKey; ctrlKey = shiftKey = altKey = false; miu = { save: function(markup) { data = EncodeURL(markup.textarea.value); ok = confirm("Save your work?"); if (!ok) { return false; } $.post("/ajax/rants/save.php", "data="+data, function(response) { if(response === "MIU:OK") { alert("Saved!"); } } ); }, load: function(markup) { $.get("/ajax/rants/load.php", function(response) { if(response === "MIU:EMPTY") { alert("Nothing to load"); } else { ok = confirm("Load the previously saved content?"); if (!ok) { return false; } markup.textarea.value = response; } } ); } }; options = { id: '', nameSpace: '', root: '', previewInWindow: '', // 'width=800, height=600, resizable=yes, scrollbars=yes' previewAutoRefresh: true, previewPosition: 'after', previewTemplatePath: '/ajax/rants/preview.php', previewParserPath: '/ajax/rants/preview.php', previewParserVar: 'data', resizeHandle: true, beforeInsert: '', afterInsert: '', realcontent: false, onEnter: {}, onShiftEnter: {keepDefault:false, replaceWith:'<br />\n'}, onCtrlEnter: {keepDefault:false, openWith:'\n<p>', closeWith:'</p>\n'}, onTab: {keepDefault:false, openWith:' '}, markupSet: [ /* Html {name:'Bold', key:'B', className:'bold', openWith:'(!(<strong>|!|<b>)!)', closeWith:'(!(</strong>|!|</b>)!)' }, {name:'Italic', key:'I', className:'italic', openWith:'(!(<em>|!|<i>)!)', closeWith:'(!(</em>|!|</i>)!)' }, {name:'Underline', key:'U', className:'underline', openWith:'(!(<ins>|!|<u>)!)', closeWith:'(!(</ins>|!|</u>)!)'}, {name:'Strike Through', key:'S', className:'strike', openWith:'<del>', closeWith:'</del>' }, {name:'Paragraph', className:'paragraph', openWith:'<p(!( class="[![Class]!]")!)>', closeWith:'</p>' }, {separator:'---------------' }, {name:'Picture', key:'P', className:'picture', replaceWith:'<img src="[![Source:!:http://]!]" alt="[![Alternative text]!]" />' }, {name:'Link', key:'L', className:'link', openWith:'<a href="[![Link:!:http://]!]"(!( title="[![Title]!]")!)>', closeWith:'</a>', placeHolder:'Your text to link...' }, {separator:'---------------' }, {name:'Bulleted List', className:'list-bullet', openWith:'<ul>\n', closeWith:'</ul>\n' }, {name:'Numeric List', className:'list-numeric', openWith:'<ol>\n', closeWith:'</ol>\n' }, {name:'List Item', className:'list-item', openWith:'<li>', closeWith:'</li>' }, {separator:'---------------' }, {name:'Quotes', className:'quotes', openWith:'<blockquote>', closeWith:'</blockquote>'}, {name:'Code', className:'code', openWith:'<code>', closeWith:'</code>'}, {separator:'---------------' }, {name:'Heading 1', key:'1', className:'h1', openWith:'<h1(!( class="[![Class]!]")!)>', closeWith:'</h1>', placeHolder:'Your title here...' }, {name:'Heading 2', key:'2', className:'h2', openWith:'<h2(!( class="[![Class]!]")!)>', closeWith:'</h2>', placeHolder:'Your title here...' }, {name:'Heading 3', key:'3', className:'h3', openWith:'<h3(!( class="[![Class]!]")!)>', closeWith:'</h3>', placeHolder:'Your title here...' }, {name:'Heading 4', key:'4', className:'h4', openWith:'<h4(!( class="[![Class]!]")!)>', closeWith:'</h4>', placeHolder:'Your title here...' }, {name:'Heading 5', key:'5', className:'h5', openWith:'<h5(!( class="[![Class]!]")!)>', closeWith:'</h5>', placeHolder:'Your title here...' }, {name:'Heading 6', key:'6', className:'h6', openWith:'<h6(!( class="[![Class]!]")!)>', closeWith:'</h6>', placeHolder:'Your title here...' }, {separator:'---------------' }, */ {name:'Bold', key:'B', className:'bold', openWith:'(!([strong]|!|[b])!)', closeWith:'(!([/strong]|!|[/b])!)' }, {name:'Italic', key:'I', className:'italic', openWith:'(!([em]|!|[i])!)', closeWith:'(!([/em]|!|[/i])!)' }, {name:'Underline', key:'U', className:'underline', openWith:'(!([ins]|!|[u])!)', closeWith:'(!([/ins]|!|[/u])!)'}, {name:'Strike Through', key:'T', className:'strike', openWith:'[s]', closeWith:'[s]' }, {separator:'---------------' }, {name:'Picture', key:'P', className:'picture', replaceWith:'[img][![Url]!][/img]'}, {name:'Link', key:'L', className:'link', openWith:'[url=[![Url]!]]', closeWith:'[/url]', placeHolder:'Your text to link here...'}, {separator:'---------------' }, {name:'Size', className:'size', openWith:'[size=[![Text size (%)]!]]', closeWith:'[/size]', dropMenu :[ {name:'Big', openWith:'[size=200]', closeWith:'[/size]' }, {name:'Normal', openWith:'[size=100]', closeWith:'[/size]' }, {name:'Small', openWith:'[size=50]', closeWith:'[/size]' } ]}, {separator:'---------------' }, {name:'Bulleted List', className:'list-bullet', openWith:'[list]\n', closeWith:'\n[/list]' }, {name:'Numeric List', className:'list-numeric', openWith:'[list=[![Starting number]!]]', closeWith:'\n[/list]' }, {name:'List Item', key: 'E', className:'list-item', openWith:'[*]' }, {separator:'---------------' }, {name:'Quotes', className:'quotes', openWith:'[quote]', closeWith:'[/quote]'}, {name:'Code', className:'code', openWith:'[code]', closeWith:'[/code]'}, {separator:'---------------' }, {name:'Heading 1', key:'1', className:'h1', openWith:'[h1(!( class="[![Class]!]")!)]', closeWith:'[/h1]', placeHolder:'Your title here...' }, {name:'Heading 2', key:'2', className:'h2', openWith:'[h2(!( class="[![Class]!]")!)]', closeWith:'[/h2]', placeHolder:'Your title here...' }, {name:'Heading 3', key:'3', className:'h3', openWith:'[h3(!( class="[![Class]!]")!)]', closeWith:'[/h3]', placeHolder:'Your title here...' }, {name:'Heading 4', key:'4', className:'h4', openWith:'[h4(!( class="[![Class]!]")!)]', closeWith:'[/h4]', placeHolder:'Your title here...' }, {name:'Heading 5', key:'5', className:'h5', openWith:'[h5(!( class="[![Class]!]")!)]', closeWith:'[/h5]', placeHolder:'Your title here...' }, {name:'Heading 6', key:'6', className:'h6', openWith:'[h6(!( class="[![Class]!]")!)]', closeWith:'[/h6]', placeHolder:'Your title here...' }, {separator:'---------------' }, {name:'Clear Markup', className:'clean', replaceWith:function(markup) { return markup.selection.replace(/\[(.*?)\]/g, "") } }, {name:'Preview', className:'preview', call:'preview' }, {separator:'---------------' }, {name:'Save', key: 'S', className:'disk-save', beforeInsert:function(markup) { miu.save(markup) } }, {name:'Load', className:'disk-load', beforeInsert:function(markup) { miu.load(markup) } } ] }; $.extend(options, settings, extraSettings); // compute markItUp! path if (!options.root) { $('script').each(function(a, tag) { miuScript = $(tag).get(0).src.match(/(.*)jquery\.markitup(\.pack)?\.js$/); if (miuScript !== null) { options.root = miuScript[1]; } }); } return this.each(function() { var $$, textarea, levels, scrollPosition, caretPosition, caretOffset, clicked, hash, header, footer, previewWindow, template, iFrame, abort; $$ = $(this); textarea = this; levels = []; abort = false; scrollPosition = caretPosition = 0; caretOffset = -1; options.previewParserPath = localize(options.previewParserPath); options.previewTemplatePath = localize(options.previewTemplatePath); // apply the computed path to ~/ function localize(data, inText) { if (inText) { return data.replace(/("|')~\//g, "$1"+options.root); } return data.replace(/^~\//, options.root); } // init and build editor function init() { id = ''; nameSpace = ''; if (options.id) { id = ' id="'+options.id+'"'; } else if ($$.attr("id")) { id = ' id="markup'+($$.attr("id").substr(0, 1).toUpperCase())+($$.attr("id").substr(1))+'"'; } if (options.nameSpace) { nameSpace = ' class="'+options.nameSpace+'"'; } $$.wrap('<div'+nameSpace+'></div>'); $$.wrap('<div'+id+' class="markup"></div>'); $$.wrap('<div class="markupContainer"></div>'); $$.addClass("markupEditor"); // add the header before the textarea header = $('<div class="markupHeader"></div>').insertBefore($$); $(dropMenus(options.markupSet)).appendTo(header); // add the footer after the textarea footer = $('<div class="markupFooter"></div>').insertAfter($$); // add the resize handle after textarea if (options.resizeHandle === true && $.browser.safari !== true) { resizeHandle = $('<div class="markupResizeHandle"></div>') .insertAfter($$) .bind("mousedown", function(e) { var h = $$.height(), y = e.clientY, mouseMove, mouseUp; mouseMove = function(e) { $$.css("height", Math.max(20, e.clientY+h-y)+"px"); return false; }; mouseUp = function(e) { $("html").unbind("mousemove", mouseMove).unbind("mouseup", mouseUp); return false; }; $("html").bind("mousemove", mouseMove).bind("mouseup", mouseUp); }); footer.append(resizeHandle); } // listen key events $$.keydown(keyPressed).keyup(keyPressed); // bind an event to catch external calls $$.bind("insertion", function(e, settings) { if (settings.target !== false) { get(); } if (textarea === $.markItUp.focused) { markup(settings); } }); if(options.realcontent) $$.val($(options.realcontent).html()); // remember the last focus $$.focus(function() { $.markItUp.focused = this; }); } // recursively build header with dropMenus from markupset function dropMenus(markupSet) { var ul = $('<ul></ul>'), i = 0; $('li:hover > ul', ul).css('display', 'block'); $.each(markupSet, function() { var button = this, t = '', title, li, j; title = (button.key) ? (button.name||'')+' [Ctrl+'+button.key+']' : (button.name||''); key = (button.key) ? 'accesskey="'+button.key+'"' : ''; if (button.separator) { li = $('<li class="markupSeparator">'+(button.separator||'')+'</li>').appendTo(ul); } else { i++; for (j = levels.length -1; j >= 0; j--) { t += levels[j]+"-"; } li = $('<li class="markupButton markupButton'+t+(i)+' '+(button.className||'')+'"><a href="" '+key+' title="'+title+'">'+(button.name||'')+'</a></li>') .bind("contextmenu", function() { // prevent contextmenu on mac and allow ctrl+click return false; }).click(function() { return false; }).mouseup(function() { if (button.call) { eval(button.call)(); } markup(button); return false; }).hover(function() { $('> ul', this).show(); $(document).one('click', function() { // close dropmenu if click outside $('ul ul', header).hide(); } ); }, function() { $('> ul', this).hide(); } ).appendTo(ul); if (button.dropMenu) { levels.push(i); $(li).addClass('markupDropMenu').append(dropMenus(button.dropMenu)); } } }); levels.pop(); return ul; } // markItUp! markups function magicMarkups(string) { if (string) { string = string.toString(); string = string.replace(/\(\!\(([\s\S]*?)\)\!\)/g, function(x, a) { var b = a.split('|!|'); if (altKey === true) { return (b[1] !== undefined) ? b[1] : b[0]; } else { return (b[1] === undefined) ? "" : b[0]; } } ); // [![prompt]!], [![prompt:!:value]!] string = string.replace(/\[\!\[([\s\S]*?)\]\!\]/g, function(x, a) { var b = a.split(':!:'); if (abort === true) { return false; } value = prompt(b[0], (b[1]) ? b[1] : ''); if (value === null) { abort = true; } return value; } ); return string; } return ""; } // prepare action function prepare(action) { if ($.isFunction(action)) { action = action(hash); } return magicMarkups(action); } // build block to insert function build(string) { openWith = prepare(clicked.openWith); placeHolder = prepare(clicked.placeHolder); replaceWith = prepare(clicked.replaceWith); closeWith = prepare(clicked.closeWith); if (replaceWith !== "") { block = openWith + replaceWith + closeWith; } else if (selection === '' && placeHolder !== '') { block = openWith + placeHolder + closeWith; } else { block = openWith + (string||selection) + closeWith; } return { block:block, openWith:openWith, replaceWith:replaceWith, placeHolder:placeHolder, closeWith:closeWith }; } // define markup to insert function markup(button) { var len, j, n, i; hash = clicked = button; get(); $.extend(hash, { line:"", root:options.root, textarea:textarea, selection:(selection||''), caretPosition:caretPosition, ctrlKey:ctrlKey, shiftKey:shiftKey, altKey:altKey } ); // callbacks before insertion prepare(options.beforeInsert); prepare(clicked.beforeInsert); if (ctrlKey === true && shiftKey === true) { prepare(clicked.beforeMultiInsert); } $.extend(hash, { line:1 }); if (ctrlKey === true && shiftKey === true) { lines = selection.split(/\r?\n/); for (j = 0, n = lines.length, i = 0; i < n; i++) { if ($.trim(lines[i]) !== '') { $.extend(hash, { line:++j, selection:lines[i] } ); lines[i] = build(lines[i]).block; } else { lines[i] = ""; } } string = { block:lines.join('\n')}; start = caretPosition; len = string.block.length + (($.browser.opera) ? n : 0); } else if (ctrlKey === true) { string = build(selection); start = caretPosition + string.openWith.length; len = string.block.length - string.openWith.length - string.closeWith.length; len -= fixIeBug(string.block); } else if (shiftKey === true) { string = build(selection); start = caretPosition; len = string.block.length; len -= fixIeBug(string.block); } else { string = build(selection); start = caretPosition + string.block.length ; len = 0; start -= fixIeBug(string.block); } if ((selection === '' && string.replaceWith === '')) { caretOffset += fixOperaBug(string.block); start = caretPosition + string.openWith.length; len = string.block.length - string.openWith.length - string.closeWith.length; caretOffset = $$.val().substring(caretPosition, $$.val().length).length; caretOffset -= fixOperaBug($$.val().substring(0, caretPosition)); } $.extend(hash, { caretPosition:caretPosition, scrollPosition:scrollPosition } ); if (string.block !== selection && abort === false) { insert(string.block); set(start, len); } else { caretOffset = -1; } get(); $.extend(hash, { line:'', selection:selection }); // callbacks after insertion if (ctrlKey === true && shiftKey === true) { prepare(clicked.afterMultiInsert); } prepare(clicked.afterInsert); prepare(options.afterInsert); // refresh preview if opened if (previewWindow && options.previewAutoRefresh) { refreshPreview(); } // reinit keyevent shiftKey = altKey = ctrlKey = abort = false; } // Substract linefeed in Opera function fixOperaBug(string) { if ($.browser.opera) { return string.length - string.replace(/\n*/g, '').length; } return 0; } // Substract linefeed in IE function fixIeBug(string) { if ($.browser.msie) { return string.length - string.replace(/\r*/g, '').length; } return 0; } // add markup function insert(block) { if (document.selection) { var newSelection = document.selection.createRange(); newSelection.text = block; } else { $$.val($$.val().substring(0, caretPosition) + block + $$.val().substring(caretPosition + selection.length, $$.val().length)); } } // set a selection function set(start, len) { if (textarea.createTextRange){ // quick fix to make it work on Opera 9.5 if ($.browser.opera && $.browser.version >= 9.5 && len == 0) { return false; } range = textarea.createTextRange(); range.collapse(true); range.moveStart('character', start); range.moveEnd('character', len); range.select(); } else if (textarea.setSelectionRange ){ textarea.setSelectionRange(start, start + len); } textarea.scrollTop = scrollPosition; textarea.focus(); } // get the selection function get() { textarea.focus(); scrollPosition = textarea.scrollTop; if (document.selection) { selection = document.selection.createRange().text; if ($.browser.msie) { // ie var range = document.selection.createRange(), rangeCopy = range.duplicate(); rangeCopy.moveToElementText(textarea); caretPosition = -1; while(rangeCopy.inRange(range)) { // fix most of the ie bugs with linefeeds... rangeCopy.moveStart('character'); caretPosition ++; } } else { // opera caretPosition = textarea.selectionStart; } } else { // gecko caretPosition = textarea.selectionStart; selection = $$.val().substring(caretPosition, textarea.selectionEnd); } return selection; } // open preview window function preview() { if (!previewWindow || previewWindow.closed) { if (options.previewInWindow) { previewWindow = window.open('', 'preview', options.previewInWindow); } else { iFrame = $('<iframe class="markupPreviewFrame"></iframe>'); if (options.previewPosition == 'after') { iFrame.insertAfter(footer); } else { iFrame.insertBefore(header); } previewWindow = iFrame[iFrame.length-1].contentWindow || frame[iFrame.length-1]; } } else if (altKey === true) { if (iFrame) { iFrame.remove(); } previewWindow.close(); previewWindow = iFrame = false; } if (!options.previewAutoRefresh) { refreshPreview(); } } // refresh Preview window function refreshPreview() { if (previewWindow.document) { try { sp = previewWindow.document.documentElement.scrollTop } catch(e) { sp = 0; } previewWindow.document.open(); previewWindow.document.write(renderPreview()); previewWindow.document.close(); previewWindow.document.documentElement.scrollTop = sp; } if (options.previewInWindow) { previewWindow.focus(); } } function renderPreview() { if (options.previewParserPath !== '') { $.ajax( { type: 'POST', async: false, url: options.previewParserPath, data: options.previewParserVar+'='+encodeURIComponent($$.val())+'&title='+$('#title').val(), success: function(data) { phtml = localize(data, 1); } } ); } else { if (!template) { $.ajax( { async: false, url: options.previewTemplatePath, success: function(data) { template = localize(data, 1); } } ); } phtml = template.replace(/<!-- content -->/g, $$.val()); } return phtml; } // set keys pressed function keyPressed(e) { shiftKey = e.shiftKey; altKey = e.altKey; ctrlKey = (!(e.altKey && e.ctrlKey)) ? e.ctrlKey : false; if (e.type === 'keydown') { if (ctrlKey === true) { li = $("a[accesskey="+String.fromCharCode(e.keyCode)+"]", header).parent('li'); if (li.length !== 0) { ctrlKey = false; li.triggerHandler('mouseup'); return false; } } if (e.keyCode === 13 || e.keyCode === 10) { // Enter key if (ctrlKey === true) { // Enter + Ctrl ctrlKey = false; markup(options.onCtrlEnter); return options.onCtrlEnter.keepDefault; } else if (shiftKey === true) { // Enter + Shift shiftKey = false; markup(options.onShiftEnter); return options.onShiftEnter.keepDefault; } else { // only Enter markup(options.onEnter); return options.onEnter.keepDefault; } } if (e.keyCode === 9) { // Tab key if (shiftKey == true || ctrlKey == true || altKey == true) { // Thx Dr Floob. return false; } if (caretOffset !== -1) { get(); caretOffset = $$.val().length - caretOffset; set(caretOffset, 0); caretOffset = -1; return false; } else { markup(options.onTab); return options.onTab.keepDefault; } } }else{ shiftKey = altKey = ctrlKey = false; } } init(); }); }; $.fn.markupRemove = function() { return this.each(function() { $$ = $(this).unbind().removeClass('markupEditor'); $$.parent('div').parent('div.markup').parent('div').replaceWith($$); } ); }; $.markup = function(settings) { var options = { target:false }; $.extend(options, settings); if (options.target) { return $(options.target).each(function() { $(this).focus(); $(this).trigger('insertion', [options]); }); } else { $('textarea').trigger('insertion', [options]); } };})(jQuery);