// ----------------------------------------------------------------------------
// markItUp! Universal MarkUp Engine, JQuery plugin
-// v 1.1.12
+// v 1.1.14 ( c014800b - 02/06/2014 )
// Dual licensed under the MIT and GPL licenses.
// ----------------------------------------------------------------------------
-// Copyright (C) 2007-2011 Jay Salvat
+// Copyright (C) 2007-2012 Jay Salvat
// http://markitup.jaysalvat.com/
// ----------------------------------------------------------------------------
// Permission is hereby granted, free of charge, to any person obtaining a copy
// ----------------------------------------------------------------------------
/*
- * Le code original de markitup 1.1.12
+ * Le code original de markitup 1.1.14
* a ete modifie pour prendre en compte
*
* 1) la langue utilisee dans les textarea :
* 3) eviter a Opera de gerer les evenements apres tabulation ou entree...
* il ne sait pas gerer (v11.51)
*
- *
+ * 4) ajout d'un <em> supplémentaire sur le html des boutons de la barre d'outil, pour des histoires de sprites
*/
;(function($) {
$.fn.markItUp = function(settings, extraSettings) {
- var options, ctrlKey, shiftKey, altKey;
- ctrlKey = shiftKey = altKey = false;
+ var method, params, options, ctrlKey, shiftKey, altKey; ctrlKey = shiftKey = altKey = false;
+ markitup_prompt = false; // variable volontairement globale
+
+ if (typeof settings == 'string') {
+ method = settings;
+ params = extraSettings;
+ }
options = { id: '',
nameSpace: '',
root: '',
lang: '',
+ previewHandler: false,
previewInWindow: '', // 'width=800, height=600, resizable=yes, scrollbars=yes'
+ previewInElement: '',
previewAutoRefresh: true,
previewPosition: 'after',
previewTemplatePath: '~/templates/preview.html',
previewParser: false,
previewParserPath: '',
previewParserVar: 'data',
+ previewParserAjaxType: 'POST',
resizeHandle: true,
beforeInsert: '',
afterInsert: '',
});
}
+ // Quick patch to keep compatibility with jQuery 1.9
+ var uaMatch = function(ua) {
+ ua = ua.toLowerCase();
+
+ var match = /(chrome)[ \/]([\w.]+)/.exec(ua) ||
+ /(webkit)[ \/]([\w.]+)/.exec(ua) ||
+ /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) ||
+ /(msie) ([\w.]+)/.exec(ua) ||
+ ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) ||
+ [];
+
+ return {
+ browser: match[ 1 ] || "",
+ version: match[ 2 ] || "0"
+ };
+ };
+ var matched = uaMatch( navigator.userAgent );
+ var browser = {};
+
+ if (matched.browser) {
+ browser[matched.browser] = true;
+ browser.version = matched.version;
+ }
+ if (browser.chrome) {
+ browser.webkit = true;
+ } else if (browser.webkit) {
+ browser.safari = true;
+ }
+
return this.each(function() {
var $$, textarea, levels, scrollPosition, caretPosition,
clicked, hash, header, footer, previewWindow, template, iFrame, abort,
options.previewParserPath = localize(options.previewParserPath);
options.previewTemplatePath = localize(options.previewTemplatePath);
+ if (method) {
+ switch(method) {
+ case 'remove':
+ remove();
+ break;
+ case 'insert':
+ markup(params);
+ break;
+ default:
+ $.error('Method ' + method + ' does not exist on jQuery.markItUp');
+ }
+ return;
+ }
+
// apply the computed path to ~/
function localize(data, inText) {
if (inText) {
$(dropMenus(options.markupSet)).appendTo(header);
// remove empty dropMenu
$(header).find("li.markItUpDropMenu ul:empty").parent().remove();
-
+
// add the footer after the textarea
footer = $('<div class="markItUpFooter"></div>').insertAfter($$);
// add the resize handle after textarea
-
- if (options.resizeHandle === true && $.browser.safari !== true) {
+ if (options.resizeHandle === true && browser.safari !== true) {
resizeHandle = $('<div class="markItUpResizeHandle"></div>')
.insertAfter($$)
- .bind("mousedown", function(e) {
+ .on("mousedown.markItUp", 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);
+ $("html").off("mousemove.markItUp", mouseMove).off("mouseup.markItUp", mouseUp);
return false;
};
- $("html").bind("mousemove", mouseMove).bind("mouseup", mouseUp);
+ $("html").on("mousemove.markItUp", mouseMove).on("mouseup.markItUp", mouseUp);
});
footer.append(resizeHandle);
}
// listen key events
- $$.keydown(keyPressed).keyup(keyPressed);
+ $$.on('keydown.markItUp', keyPressed).on('keyup', keyPressed);
// bind an event to catch external calls
- $$.bind("insertion", function(e, settings) {
+ $$.on("insertion.markItUp", function(e, settings) {
if (settings.target !== false) {
get();
}
});
// remember the last focus
- $$.focus(function() {
+ $$.on('focus.markItUp', function() {
$.markItUp.focused = this;
});
+
+ if (options.previewInElement) {
+ refreshPreview();
+ }
}
// recursively build header with dropMenus from markupset
// pas de langue ou dans la langue ; et uniquement si langue autorisee
if ((!lang || !button.lang || ($.inArray(lang, button.lang) != -1))
&& (!button.lang_not || ($.inArray(lang, button.lang_not) == -1))) {
- title = (button.key) ? (button.name||'')+' [Ctrl+'+button.key+']' : (button.name||'');
+ button.title ? title = (button.key) ? (button.title||'')+' [Ctrl+'+button.key+']' : (button.title||'') : title = (button.key) ? (button.name||'')+' [Ctrl+'+button.key+']' : (button.name||'');
key = (button.key) ? 'accesskey="'+button.key+'"' : '';
if (button.separator) {
li = $('<li class="markItUpSeparator">'+(button.separator||'')+'</li>').appendTo(ul);
for (j = levels.length -1; j >= 0; j--) {
t += levels[j]+"-";
}
- li = $('<li class="markItUpButton markItUpButton'+t+(i)+' '+(button.className||'')+'"><a href="" '+key+' title="'+title+'"><em>'+(button.name||'')+'</em></a></li>')
- .bind("contextmenu", function() { // prevent contextmenu on mac and allow ctrl+click
+ li = $('<li class="markItUpButton markItUpButton'+t+(i)+' '+(button.className||'')+'"><a href="#" '+key+' title="'+title+'"><em>'+(button.name||'')+'</em></a></li>')
+ .on("contextmenu.markItUp", function() { // prevent contextmenu on mac and allow ctrl+click
return false;
- }).click(function() {
- return false;
- }).bind("focusin", function(){
+ }).on('click.markItUp', function(e) {
+ e.preventDefault();
+ }).on("focusin.markItUp", function(){
$$.focus();
- }).mouseup(function() {
+ }).on('mouseup', function(e) {
if (button.call) {
- eval(button.call)();
+ eval(button.call)(e); // Pass the mouseup event to custom delegate
}
setTimeout(function() { markup(button) },1);
return false;
- }).hover(function() {
+ }).on('mouseenter.markItUp', function() {
$('> ul', this).show();
$(document).one('click', function() { // close dropmenu if click outside
$('ul ul', header).hide();
}
);
- }, function() {
+ }).on('mouseleave.markItUp', function() {
$('> ul', this).hide();
- }
- ).appendTo(ul);
+ }).appendTo(ul);
if (button.dropMenu) {
levels.push(i);
$(li).addClass('markItUpDropMenu').append(dropMenus(button.dropMenu));
if (abort === true) {
return false;
}
+
+ // On prévient qu'un prompt s'ouvre
+ markitup_prompt = true;
+
value = prompt(b[0], (b[1]) ? b[1] : '');
if (value === null) {
abort = true;
}
+
+ // On attend un peu avant de dire que le prompt est fermé
+ // pour ne pas que ça soit pris en compte en même temps que la fermeture du prompt
+ setTimeout(function(){markitup_prompt = false;}, 500);
+
return value;
}
);
var openBlockWith = prepare(clicked.openBlockWith);
var closeBlockWith = prepare(clicked.closeBlockWith);
var multiline = clicked.multiline;
-
+
if (replaceWith !== "") {
block = openWith + replaceWith + closeWith;
} else if (selection === '' && placeHolder !== '') {
} else if (multiline === true) {
string = string || selection;
- var lines = selection.split(/\r?\n/), blocks = [];
-
- for (var l=0; l < lines.length; l++) {
+ var lines = [string], blocks = [];
+
+ if (multiline === true) {
+ lines = string.split(/\r?\n/);
+ }
+
+ for (var l = 0; l < lines.length; l++) {
line = lines[l];
var trailingSpaces;
if (trailingSpaces = line.match(/ *$/)) {
blocks.push(openWith + line + closeWith);
}
}
-
+
block = blocks.join("\n");
} else {
block = openWith + (string || selection) + closeWith;
}
block = openBlockWith + block + closeBlockWith;
-
+
return { block:block,
+ openBlockWith:openBlockWith,
openWith:openWith,
replaceWith:replaceWith,
placeHolder:placeHolder,
- closeWith:closeWith
+ closeWith:closeWith,
+ closeBlockWith:closeBlockWith
};
}
function selectWord(){
selectionBeforeAfter(/\s|[.,;:!¡?¿()]/);
- selectionSave();
+ selectionSave();
}
function selectLine(){
selectionBeforeAfter(/\r?\n/);
- selectionSave();
- }
-
+ selectionSave();
+ }
+
function selectionRemoveLast(pattern){
// Remove space by default
if (!pattern) pattern = /\s/;
set(caretPosition, selection.length-1);
get();
$.extend(hash, { caretPosition:caretPosition, scrollPosition:scrollPosition } );
- }
+ }
}
-
+
function selectionBeforeAfter(pattern) {
if (!pattern) pattern = /\s/;
sautAvantIE = sautApresIE = 0;
- if ($.browser.msie) {
+ if (browser.msie) {
// calcul du nombre reel de caracteres pour le substr()
// IE ne compte pas les sauts de lignes pour definir les selections
// mais les compte dans la fonction length()
before = textarea.value.substring(0, caretPosition);
after = textarea.value.substring(caretPosition + selection.length - fixIeBug(selection));
}
-
+
before = before.split(pattern);
after = after.split(pattern);
// ajouter ce fichu saut de ligne pour IE
if (sautAvantIE) before.push("");
if (sautApresIE) after.unshift("");
-
+
}
-
+
function selectionSave(){
nb_before = before ? before[before.length-1].length : 0;
nb_after = after ? after[0].length : 0;
get();
$.extend(hash, { selection:selection, caretPosition:caretPosition, scrollPosition:scrollPosition } );
}
-
+
// define markup to insert
function markup(button) {
var len, j, n, i;
altKey:altKey
}
);
-
+
// corrections des selections pour que
// - soit le curseur ne change pas
// - soit on prend le mot complet (si pas de selection)
// win/ff add space on double click ? (hum, seems strange)
selectionRemoveLast(/\s/);
}
- }
+ }
if (button.selectionType == "line") {
selectLine();
}
// c'est extremement vilain a chaque saut de ligne
// des qu'il y a un texte volumineux.
// on dit tant pis pour lui.
- if (!$.browser.msie) {
+ if (!browser.msie) {
selectionBeforeAfter(/\r?\n/);
before_last = before[before.length-1];
after = '';
prepare(clicked.beforeInsert);
if ((ctrlKey === true && shiftKey === true) || button.multiline === true) {
prepare(clicked.beforeMultiInsert);
- }
+ }
$.extend(hash, { line:1 });
if ((ctrlKey === true && shiftKey === true) || button.forceMultiline === true) {
lines[i] = "";
}
}
+
string = { block:lines.join('\n')};
start = caretPosition;
- len = string.block.length + (($.browser.opera) ? n-1 : 0);
+ len = string.block.length + ((browser.opera) ? n-1 : 0);
} else if (ctrlKey === true) {
string = build(selection);
start = caretPosition + string.openWith.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;
+
+ start = caretPosition + string.openBlockWith.length + string.openWith.length;
+ len = string.block.length - string.openBlockWith.length - string.openWith.length - string.closeWith.length - string.closeBlockWith.length;
caretOffset = $$.val().substring(caretPosition, $$.val().length).length;
caretOffset -= fixOperaBug($$.val().substring(0, caretPosition));
if (previewWindow && options.previewAutoRefresh) {
refreshPreview();
}
-
+
// reinit keyevent
shiftKey = altKey = ctrlKey = abort = false;
-
}
// Substract linefeed in Opera
function fixOperaBug(string) {
- if ($.browser.opera) {
+ if (browser.opera) {
return string.length - string.replace(/\n*/g, '').length;
}
return 0;
}
// Substract linefeed in IE
function fixIeBug(string) {
- if ($.browser.msie) {
+ if (browser.msie) {
return string.length - string.replace(/\r*/g, '').length;
}
return 0;
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) {
+ if (browser.opera && browser.version >= 9.5 && len == 0) {
return false;
}
range = textarea.createTextRange();
scrollPosition = textarea.scrollTop;
if (document.selection) {
selection = document.selection.createRange().text;
- if ($.browser.msie) { // ie
+ if (browser.msie) { // ie
var range = document.selection.createRange(), rangeCopy = range.duplicate();
rangeCopy.moveToElementText(textarea);
caretPosition = -1;
}
} else { // gecko & webkit
caretPosition = textarea.selectionStart;
+
selection = textarea.value.substring(caretPosition, textarea.selectionEnd);
-
}
return selection;
}
// open preview window
function preview() {
- if (!previewWindow || previewWindow.closed) {
+ if (typeof options.previewHandler === 'function') {
+ previewWindow = true;
+ } else if (options.previewInElement) {
+ previewWindow = $(options.previewInElement);
+ } else if (!previewWindow || previewWindow.closed) {
if (options.previewInWindow) {
previewWindow = window.open('', 'preview', options.previewInWindow);
$(window).unload(function() {
iFrame.insertAfter(footer);
} else {
iFrame.insertBefore(header);
- }
+ }
previewWindow = iFrame[iFrame.length - 1].contentWindow || frame[iFrame.length - 1];
}
} else if (altKey === true) {
// refresh Preview window
function refreshPreview() {
- renderPreview();
+ renderPreview();
}
function renderPreview() {
var phtml;
- if (options.previewParser && typeof options.previewParser === 'function') {
+ if (options.previewHandler && typeof options.previewHandler === 'function') {
+ options.previewHandler( $$.val() );
+ } else if (options.previewParser && typeof options.previewParser === 'function') {
var data = options.previewParser( $$.val() );
- writeInPreview( localize(data, 1) );
+ writeInPreview(localize(data, 1) );
} else if (options.previewParserPath !== '') {
$.ajax({
- type: 'POST',
+ type: options.previewParserAjaxType,
dataType: 'text',
global: false,
url: options.previewParserPath,
});
} else {
if (!template) {
- $.ajax( {
+ $.ajax({
url: options.previewTemplatePath,
dataType: 'text',
global: false,
}
return false;
}
-
+
function writeInPreview(data) {
- if (previewWindow.document) {
+ if (options.previewInElement) {
+ $(options.previewInElement).html(data);
+ } else if (previewWindow && previewWindow.document) {
try {
sp = previewWindow.document.documentElement.scrollTop
} catch(e) {
previewWindow.document.documentElement.scrollTop = sp;
}
}
-
+
// set keys pressed
- function keyPressed(e) {
+ function keyPressed(e) {
shiftKey = e.shiftKey;
altKey = e.altKey;
ctrlKey = (!(e.altKey && e.ctrlKey)) ? (e.ctrlKey || e.metaKey) : false;
if (e.type === 'keydown') {
if (ctrlKey === true) {
- li = $('a[accesskey="'+String.fromCharCode(e.keyCode)+'"]', header).parent('li');
+ li = $('a[accesskey="'+((e.keyCode == 13) ? '\\n' : String.fromCharCode(e.keyCode))+'"]', header).parent('li');
if (li.length !== 0) {
ctrlKey = false;
setTimeout(function() {
// si opera, on s'embete pas, il cree plus de problemes qu'autre chose
// car il ne prend pas en compte l'arret de ces evenements
- if (!$.browser.opera) {
+ if (!browser.opera) {
if (e.keyCode === 13 || e.keyCode === 10) { // Enter key
if (ctrlKey === true) { // Enter + Ctrl
ctrlKey = false;
if (shiftKey == true || ctrlKey == true || altKey == true) {
// permettre un retour a l'action naturelle
// du navigateur via shift+tab
- return true;
+ return false;
}
if (caretOffset !== -1) {
get();
}
}
+ function remove() {
+ $$.off(".markItUp").removeClass('markItUpEditor');
+ $$.parent('div').parent('div.markItUp').parent('div').replaceWith($$);
+
+ var relativeRef = $$.parent('div').parent('div.markItUp').parent('div');
+ if (relativeRef.length) {
+ relativeRef.replaceWith($$);
+ }
+
+ $$.data('markItUp', null);
+ }
+
init();
});
};
$.fn.markItUpRemove = function() {
return this.each(function() {
- var $$ = $(this).unbind().removeClass('markItUpEditor');
- $$.parent('div').parent('div.markItUp').parent('div').replaceWith($$);
+ $(this).markItUp('remove');
}
);
};
$('textarea').trigger('insertion', [options]);
}
};
-
+
})(jQuery);