|
3 | 3 | // v 1.1.x
|
4 | 4 | // Dual licensed under the MIT and GPL licenses.
|
5 | 5 | // ----------------------------------------------------------------------------
|
6 |
| -// Copyright (C) 2007-2011 Jay Salvat |
| 6 | +// Copyright (C) 2007-2012 Jay Salvat |
7 | 7 | // http://markitup.jaysalvat.com/
|
8 | 8 | // ----------------------------------------------------------------------------
|
9 | 9 | // Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
26 | 26 | // ----------------------------------------------------------------------------
|
27 | 27 | (function($) {
|
28 | 28 | $.fn.markItUp = function(settings, extraSettings) {
|
29 |
| - var options, ctrlKey, shiftKey, altKey; |
30 |
| - ctrlKey = shiftKey = altKey = false; |
31 |
| - |
| 29 | + var method, params, options, ctrlKey, shiftKey, altKey; ctrlKey = shiftKey = altKey = false; |
| 30 | + |
| 31 | + if (typeof settings == 'string') { |
| 32 | + method = settings; |
| 33 | + params = extraSettings; |
| 34 | + } |
| 35 | + |
32 | 36 | options = { id: '',
|
33 | 37 | nameSpace: '',
|
34 | 38 | root: '',
|
| 39 | + previewHandler: false, |
35 | 40 | previewInWindow: '', // 'width=800, height=600, resizable=yes, scrollbars=yes'
|
| 41 | + previewInElement: '', |
36 | 42 | previewAutoRefresh: true,
|
37 | 43 | previewPosition: 'after',
|
38 | 44 | previewTemplatePath: '~/templates/preview.html',
|
39 | 45 | previewParser: false,
|
40 | 46 | previewParserPath: '',
|
41 | 47 | previewParserVar: 'data',
|
| 48 | + previewParserAjaxType: 'POST', |
42 | 49 | resizeHandle: true,
|
43 | 50 | beforeInsert: '',
|
44 | 51 | afterInsert: '',
|
|
53 | 60 | // compute markItUp! path
|
54 | 61 | if (!options.root) {
|
55 | 62 | $('script').each(function(a, tag) {
|
56 |
| - miuScript = $(tag).get(0).src.match(/(.*)jquery\.markitup(\.pack)?\.js$/); |
| 63 | + var miuScript = $(tag).get(0).src.match(/(.*)jquery\.markitup(\.pack)?\.js$/); |
57 | 64 | if (miuScript !== null) {
|
58 | 65 | options.root = miuScript[1];
|
59 | 66 | }
|
60 | 67 | });
|
61 | 68 | }
|
62 | 69 |
|
| 70 | + // Quick patch to keep compatibility with jQuery 1.9 |
| 71 | + var uaMatch = function(ua) { |
| 72 | + ua = ua.toLowerCase(); |
| 73 | + |
| 74 | + var match = /(chrome)[ \/]([\w.]+)/.exec(ua) || |
| 75 | + /(webkit)[ \/]([\w.]+)/.exec(ua) || |
| 76 | + /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || |
| 77 | + /(msie) ([\w.]+)/.exec(ua) || |
| 78 | + ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || |
| 79 | + []; |
| 80 | + |
| 81 | + return { |
| 82 | + browser: match[ 1 ] || "", |
| 83 | + version: match[ 2 ] || "0" |
| 84 | + }; |
| 85 | + }; |
| 86 | + var matched = uaMatch( navigator.userAgent ); |
| 87 | + var browser = {}; |
| 88 | + |
| 89 | + if (matched.browser) { |
| 90 | + browser[matched.browser] = true; |
| 91 | + browser.version = matched.version; |
| 92 | + } |
| 93 | + if (browser.chrome) { |
| 94 | + browser.webkit = true; |
| 95 | + } else if (browser.webkit) { |
| 96 | + browser.safari = true; |
| 97 | + } |
| 98 | + |
63 | 99 | return this.each(function() {
|
64 | 100 | var $$, textarea, levels, scrollPosition, caretPosition, caretOffset,
|
65 | 101 | clicked, hash, header, footer, previewWindow, template, iFrame, abort;
|
|
73 | 109 | options.previewParserPath = localize(options.previewParserPath);
|
74 | 110 | options.previewTemplatePath = localize(options.previewTemplatePath);
|
75 | 111 |
|
| 112 | + if (method) { |
| 113 | + switch(method) { |
| 114 | + case 'remove': |
| 115 | + remove(); |
| 116 | + break; |
| 117 | + case 'insert': |
| 118 | + markup(params); |
| 119 | + break; |
| 120 | + default: |
| 121 | + $.error('Method ' + method + ' does not exist on jQuery.markItUp'); |
| 122 | + } |
| 123 | + return; |
| 124 | + } |
| 125 | + |
76 | 126 | // apply the computed path to ~/
|
77 | 127 | function localize(data, inText) {
|
78 | 128 | if (inText) {
|
|
106 | 156 | footer = $('<div class="markItUpFooter"></div>').insertAfter($$);
|
107 | 157 |
|
108 | 158 | // add the resize handle after textarea
|
109 |
| - if (options.resizeHandle === true && $.browser.safari !== true) { |
| 159 | + if (options.resizeHandle === true && browser.safari !== true) { |
110 | 160 | resizeHandle = $('<div class="markItUpResizeHandle"></div>')
|
111 | 161 | .insertAfter($$)
|
112 |
| - .bind("mousedown", function(e) { |
| 162 | + .bind("mousedown.markItUp", function(e) { |
113 | 163 | var h = $$.height(), y = e.clientY, mouseMove, mouseUp;
|
114 | 164 | mouseMove = function(e) {
|
115 | 165 | $$.css("height", Math.max(20, e.clientY+h-y)+"px");
|
116 | 166 | return false;
|
117 | 167 | };
|
118 | 168 | mouseUp = function(e) {
|
119 |
| - $("html").unbind("mousemove", mouseMove).unbind("mouseup", mouseUp); |
| 169 | + $("html").unbind("mousemove.markItUp", mouseMove).unbind("mouseup.markItUp", mouseUp); |
120 | 170 | return false;
|
121 | 171 | };
|
122 |
| - $("html").bind("mousemove", mouseMove).bind("mouseup", mouseUp); |
| 172 | + $("html").bind("mousemove.markItUp", mouseMove).bind("mouseup.markItUp", mouseUp); |
123 | 173 | });
|
124 | 174 | footer.append(resizeHandle);
|
125 | 175 | }
|
126 | 176 |
|
127 | 177 | // listen key events
|
128 |
| - $$.keydown(keyPressed).keyup(keyPressed); |
| 178 | + $$.bind('keydown.markItUp', keyPressed).bind('keyup', keyPressed); |
129 | 179 |
|
130 | 180 | // bind an event to catch external calls
|
131 |
| - $$.bind("insertion", function(e, settings) { |
| 181 | + $$.bind("insertion.markItUp", function(e, settings) { |
132 | 182 | if (settings.target !== false) {
|
133 | 183 | get();
|
134 | 184 | }
|
|
138 | 188 | });
|
139 | 189 |
|
140 | 190 | // remember the last focus
|
141 |
| - $$.focus(function() { |
| 191 | + $$.bind('focus.markItUp', function() { |
142 | 192 | $.markItUp.focused = this;
|
143 | 193 | });
|
| 194 | + |
| 195 | + if (options.previewInElement) { |
| 196 | + refreshPreview(); |
| 197 | + } |
144 | 198 | }
|
145 | 199 |
|
146 | 200 | // recursively build header with dropMenus from markupset
|
|
149 | 203 | $('li:hover > ul', ul).css('display', 'block');
|
150 | 204 | $.each(markupSet, function() {
|
151 | 205 | var button = this, t = '', title, li, j;
|
152 |
| - title = (button.key) ? (button.name||'')+' [Ctrl+'+button.key+']' : (button.name||''); |
| 206 | + button.title ? title = (button.key) ? (button.title||'')+' [Ctrl+'+button.key+']' : (button.title||'') : title = (button.key) ? (button.name||'')+' [Ctrl+'+button.key+']' : (button.name||''); |
153 | 207 | key = (button.key) ? 'accesskey="'+button.key+'"' : '';
|
154 | 208 | if (button.separator) {
|
155 | 209 | li = $('<li class="markItUpSeparator">'+(button.separator||'')+'</li>').appendTo(ul);
|
|
158 | 212 | for (j = levels.length -1; j >= 0; j--) {
|
159 | 213 | t += levels[j]+"-";
|
160 | 214 | }
|
161 |
| - li = $('<li class="markItUpButton markItUpButton'+t+(i)+' '+(button.className||'')+'"><a href="" '+key+' title="'+title+'">'+(button.name||'')+'</a></li>') |
162 |
| - .bind("contextmenu", function() { // prevent contextmenu on mac and allow ctrl+click |
| 215 | + li = $('<li class="markItUpButton markItUpButton'+t+(i)+' '+(button.className||'')+'"><a href="#" '+key+' title="'+title+'">'+(button.name||'')+'</a></li>') |
| 216 | + .bind("contextmenu.markItUp", function() { // prevent contextmenu on mac and allow ctrl+click |
163 | 217 | return false;
|
164 |
| - }).click(function() { |
165 |
| - return false; |
166 |
| - }).bind("focusin", function(){ |
| 218 | + }).bind('click.markItUp', function(e) { |
| 219 | + e.preventDefault(); |
| 220 | + }).bind("focusin.markItUp", function(){ |
167 | 221 | $$.focus();
|
168 |
| - }).mouseup(function() { |
| 222 | + }).bind('mouseup', function(e) { |
169 | 223 | if (button.call) {
|
170 |
| - eval(button.call)(); |
| 224 | + eval(button.call)(e); // Pass the mouseup event to custom delegate |
171 | 225 | }
|
172 | 226 | setTimeout(function() { markup(button) },1);
|
173 | 227 | return false;
|
174 |
| - }).hover(function() { |
| 228 | + }).bind('mouseenter.markItUp', function() { |
175 | 229 | $('> ul', this).show();
|
176 | 230 | $(document).one('click', function() { // close dropmenu if click outside
|
177 | 231 | $('ul ul', header).hide();
|
178 | 232 | }
|
179 | 233 | );
|
180 |
| - }, function() { |
| 234 | + }).bind('mouseleave.markItUp', function() { |
181 | 235 | $('> ul', this).hide();
|
182 |
| - } |
183 |
| - ).appendTo(ul); |
| 236 | + }).appendTo(ul); |
184 | 237 | if (button.dropMenu) {
|
185 | 238 | levels.push(i);
|
186 | 239 | $(li).addClass('markItUpDropMenu').append(dropMenus(button.dropMenu));
|
|
249 | 302 | } else {
|
250 | 303 | string = string || selection;
|
251 | 304 |
|
252 |
| - var lines = selection.split(/\r?\n/), blocks = []; |
| 305 | + var lines = [string], blocks = []; |
| 306 | + |
| 307 | + if (multiline === true) { |
| 308 | + lines = string.split(/\r?\n/); |
| 309 | + } |
253 | 310 |
|
254 |
| - for (var l=0; l < lines.length; l++) { |
| 311 | + for (var l = 0; l < lines.length; l++) { |
255 | 312 | line = lines[l];
|
256 | 313 | var trailingSpaces;
|
257 | 314 | if (trailingSpaces = line.match(/ *$/)) {
|
|
267 | 324 | block = openBlockWith + block + closeBlockWith;
|
268 | 325 |
|
269 | 326 | return { block:block,
|
| 327 | + openBlockWith:openBlockWith, |
270 | 328 | openWith:openWith,
|
271 | 329 | replaceWith:replaceWith,
|
272 | 330 | placeHolder:placeHolder,
|
273 |
| - closeWith:closeWith |
| 331 | + closeWith:closeWith, |
| 332 | + closeBlockWith:closeBlockWith |
274 | 333 | };
|
275 | 334 | }
|
276 | 335 |
|
|
307 | 366 | lines[i] = "";
|
308 | 367 | }
|
309 | 368 | }
|
| 369 | + |
310 | 370 | string = { block:lines.join('\n')};
|
311 | 371 | start = caretPosition;
|
312 |
| - len = string.block.length + (($.browser.opera) ? n-1 : 0); |
| 372 | + len = string.block.length + ((browser.opera) ? n-1 : 0); |
313 | 373 | } else if (ctrlKey === true) {
|
314 | 374 | string = build(selection);
|
315 | 375 | start = caretPosition + string.openWith.length;
|
|
330 | 390 | if ((selection === '' && string.replaceWith === '')) {
|
331 | 391 | caretOffset += fixOperaBug(string.block);
|
332 | 392 |
|
333 |
| - start = caretPosition + string.openWith.length; |
334 |
| - len = string.block.length - string.openWith.length - string.closeWith.length; |
| 393 | + start = caretPosition + string.openBlockWith.length + string.openWith.length; |
| 394 | + len = string.block.length - string.openBlockWith.length - string.openWith.length - string.closeWith.length - string.closeBlockWith.length; |
335 | 395 |
|
336 | 396 | caretOffset = $$.val().substring(caretPosition, $$.val().length).length;
|
337 | 397 | caretOffset -= fixOperaBug($$.val().substring(0, caretPosition));
|
|
359 | 419 | if (previewWindow && options.previewAutoRefresh) {
|
360 | 420 | refreshPreview();
|
361 | 421 | }
|
| 422 | + |
| 423 | + // Triggers an input event to allow other scripts to react. |
| 424 | + textarea.dispatchEvent(new Event('input')); |
362 | 425 |
|
363 | 426 | // reinit keyevent
|
364 | 427 | shiftKey = altKey = ctrlKey = abort = false;
|
365 | 428 | }
|
366 | 429 |
|
367 | 430 | // Substract linefeed in Opera
|
368 | 431 | function fixOperaBug(string) {
|
369 |
| - if ($.browser.opera) { |
| 432 | + if (browser.opera) { |
370 | 433 | return string.length - string.replace(/\n*/g, '').length;
|
371 | 434 | }
|
372 | 435 | return 0;
|
373 | 436 | }
|
374 | 437 | // Substract linefeed in IE
|
375 | 438 | function fixIeBug(string) {
|
376 |
| - if ($.browser.msie) { |
| 439 | + if (browser.msie) { |
377 | 440 | return string.length - string.replace(/\r*/g, '').length;
|
378 | 441 | }
|
379 | 442 | return 0;
|
|
393 | 456 | function set(start, len) {
|
394 | 457 | if (textarea.createTextRange){
|
395 | 458 | // quick fix to make it work on Opera 9.5
|
396 |
| - if ($.browser.opera && $.browser.version >= 9.5 && len == 0) { |
| 459 | + if (browser.opera && browser.version >= 9.5 && len == 0) { |
397 | 460 | return false;
|
398 | 461 | }
|
399 | 462 | range = textarea.createTextRange();
|
|
415 | 478 | scrollPosition = textarea.scrollTop;
|
416 | 479 | if (document.selection) {
|
417 | 480 | selection = document.selection.createRange().text;
|
418 |
| - if ($.browser.msie) { // ie |
| 481 | + if (browser.msie) { // ie |
419 | 482 | var range = document.selection.createRange(), rangeCopy = range.duplicate();
|
420 | 483 | rangeCopy.moveToElementText(textarea);
|
421 | 484 | caretPosition = -1;
|
|
436 | 499 |
|
437 | 500 | // open preview window
|
438 | 501 | function preview() {
|
439 |
| - if (!previewWindow || previewWindow.closed) { |
| 502 | + if (typeof options.previewHandler === 'function') { |
| 503 | + previewWindow = true; |
| 504 | + } else if (options.previewInElement) { |
| 505 | + previewWindow = $(options.previewInElement); |
| 506 | + } else if (!previewWindow || previewWindow.closed) { |
440 | 507 | if (options.previewInWindow) {
|
441 | 508 | previewWindow = window.open('', 'preview', options.previewInWindow);
|
442 | 509 | $(window).unload(function() {
|
|
472 | 539 | renderPreview();
|
473 | 540 | }
|
474 | 541 |
|
475 |
| - function renderPreview() { |
| 542 | + function renderPreview() { |
476 | 543 | var phtml;
|
| 544 | + var parsedData = $$.val(); |
477 | 545 | if (options.previewParser && typeof options.previewParser === 'function') {
|
478 |
| - var data = options.previewParser( $$.val() ); |
479 |
| - writeInPreview( localize(data, 1) ); |
| 546 | + parsedData = options.previewParser(parsedData); |
| 547 | + } |
| 548 | + if (options.previewHandler && typeof options.previewHandler === 'function') { |
| 549 | + options.previewHandler(parsedData); |
480 | 550 | } else if (options.previewParserPath !== '') {
|
481 | 551 | $.ajax({
|
482 |
| - type: 'POST', |
| 552 | + type: options.previewParserAjaxType, |
483 | 553 | dataType: 'text',
|
484 | 554 | global: false,
|
485 | 555 | url: options.previewParserPath,
|
486 |
| - data: options.previewParserVar+'='+encodeURIComponent($$.val()), |
| 556 | + data: options.previewParserVar+'='+encodeURIComponent(parsedData), |
487 | 557 | success: function(data) {
|
488 | 558 | writeInPreview( localize(data, 1) );
|
489 | 559 | }
|
|
495 | 565 | dataType: 'text',
|
496 | 566 | global: false,
|
497 | 567 | success: function(data) {
|
498 |
| - writeInPreview( localize(data, 1).replace(/<!-- content -->/g, $$.val()) ); |
| 568 | + writeInPreview( localize(data, 1).replace(/<!-- content -->/g, parsedData) ); |
499 | 569 | }
|
500 | 570 | });
|
501 | 571 | }
|
|
504 | 574 | }
|
505 | 575 |
|
506 | 576 | function writeInPreview(data) {
|
507 |
| - if (previewWindow.document) { |
| 577 | + if (options.previewInElement) { |
| 578 | + $(options.previewInElement).html(data); |
| 579 | + } else if (previewWindow && previewWindow.document) { |
508 | 580 | try {
|
509 | 581 | sp = previewWindow.document.documentElement.scrollTop
|
510 | 582 | } catch(e) {
|
|
525 | 597 |
|
526 | 598 | if (e.type === 'keydown') {
|
527 | 599 | if (ctrlKey === true) {
|
528 |
| - li = $('a[accesskey="'+String.fromCharCode(e.keyCode)+'"]', header).parent('li'); |
| 600 | + li = $('a[accesskey="'+((e.keyCode == 13) ? '\\n' : String.fromCharCode(e.keyCode))+'"]', header).parent('li'); |
529 | 601 | if (li.length !== 0) {
|
530 | 602 | ctrlKey = false;
|
531 | 603 | setTimeout(function() {
|
|
566 | 638 | }
|
567 | 639 | }
|
568 | 640 |
|
| 641 | + function remove() { |
| 642 | + $$.unbind(".markItUp").removeClass('markItUpEditor'); |
| 643 | + $$.parent('div').parent('div.markItUp').parent('div').replaceWith($$); |
| 644 | + |
| 645 | + var relativeRef = $$.parent('div').parent('div.markItUp').parent('div'); |
| 646 | + if (relativeRef.length) { |
| 647 | + relativeRef.replaceWith($$); |
| 648 | + } |
| 649 | + |
| 650 | + $$.data('markItUp', null); |
| 651 | + } |
| 652 | + |
569 | 653 | init();
|
570 | 654 | });
|
571 | 655 | };
|
572 | 656 |
|
573 | 657 | $.fn.markItUpRemove = function() {
|
574 | 658 | return this.each(function() {
|
575 |
| - var $$ = $(this).unbind().removeClass('markItUpEditor'); |
576 |
| - $$.parent('div').parent('div.markItUp').parent('div').replaceWith($$); |
| 659 | + $(this).markItUp('remove'); |
577 | 660 | }
|
578 | 661 | );
|
579 | 662 | };
|
|
0 commit comments