X-Git-Url: http://git.cyclocoop.org/?p=lhc%2Fweb%2Fclavette_www.git;a=blobdiff_plain;f=www%2Fplugins%2Fcrayons%2Fjs%2Fcrayons.js;fp=www%2Fplugins%2Fcrayons%2Fjs%2Fcrayons.js;h=00300b502a638104efda93977a346aaa4863cee0;hp=0000000000000000000000000000000000000000;hb=39f8b2ffa1fd0a3c67d6c74ed0fee9af296ccbb8;hpb=65eb21b34b55f850024ccda121bb96c73be4309f diff --git a/www/plugins/crayons/js/crayons.js b/www/plugins/crayons/js/crayons.js new file mode 100644 index 0000000..00300b5 --- /dev/null +++ b/www/plugins/crayons/js/crayons.js @@ -0,0 +1,575 @@ +(function($){ +/* + * crayons.js (c) Fil, toggg, 2006-2013 -- licence GPL + */ + +// le prototype configuration de Crayons +$.prototype.cfgCrayons = function (options) { + this.url_crayons_html = '?action=crayons_html'; + this.img = { + 'searching':{'txt':'En attente du serveur ...'}, + 'edit':{'txt':'Editer'}, + 'img-changed':{'txt':'Deja modifie'} + }; + this.txt = { + }; + for (opt in options) { + this[opt] = options[opt]; + } +}; + +$.prototype.cfgCrayons.prototype.mkimg = function(what, extra) { + var txt = this.img[what] ? this.img[what].txt : this.img['crayon'].txt; + return ''; +}; + +$.prototype.cfgCrayons.prototype.iconclick = function(c, type) { + + // le + qui passe en prive pour editer tout si classe type--id + var link = c.match(/\b(\w+)--(\d+)\b/); + link = link ? + '' + this.mkimg('edit', ' (' + link[1] + ' ' + link[2] + ')') + '' : ''; + + // on recherche une class du type type-champ-id + // comme article-texte-10 pour le texte de l'article 10 + // ou meta-valeur-meta + var cray = + c.match(/\b\w+-(\w+)-\d(?:-\w+)+\b/) // numeros_lien-type-2-3-article (table-champ-cles) + || c.match(/\b\w+-(\w+)-\d+\b/) // article-texte-10 (inclu dans le precedent, mais bon) + || c.match(/\b\meta-valeur-(\w+)\b/) // meta-valeur-xx + ; + + var boite = !cray ? '' : this.mkimg(type, ' (' + cray[1] + ')'); + + return "" + boite + + this.mkimg('img-changed', cray ? ' (' + cray[1] + ')': '') + + link +""; +}; + +function entity2unicode(txt) +{ + var reg = txt.split(/&#(\d+);/i); + for (var i = 1; i < reg.length; i+=2) { + reg[i] = String.fromCharCode(parseInt(reg[i])); + } + return reg.join(''); +}; + +function uniAlert(txt) +{ + alert(entity2unicode(txt)); +}; + +function uniConfirm(txt) +{ + return confirm(entity2unicode(txt)); +}; + +// donne le crayon d'un element +$.fn.crayon = function(){ + if (this.length) + return $( + $.map(this, function(a){ + return '#'+($(a).find('.crayon-icones').attr('rel')); + }) + .join(',')); + else + return $([]); +}; + +// ouvre un crayon +$.fn.opencrayon = function(evt, percent) { + if (evt && evt.stopPropagation) { + evt.stopPropagation(); + } + return this + .each(function(){ + // verifier que je suis un crayon + if (!$(this).is('.crayon')) + return; + + // voir si je dispose deja du crayon comme voisin + if ($(this).is('.crayon-has')) { + $(this) + .css('visibility','hidden') + .crayon() + .show(); + } + // sinon charger le formulaire + else { + // sauf si je suis deja en train de le charger (lock) + if ($(this).find("em.crayon-searching").length) { + return; + } + $(this) + .find('>span.crayon-icones span') + .append(configCrayons.mkimg('searching')); // icone d'attente + var me=this; + var offset = $(this).offset(); + var params = { + 'top': offset.top, + 'left': offset.left, + 'w': $(this).width(), + 'h': $(this).height(), + 'ww': (window.innerWidth ? window.innerWidth : (document.documentElement.clientWidth ? document.documentElement.clientWidth : document.body.offsetWidth)), + 'wh': (window.innerHeight ? window.innerHeight : (document.documentElement.clientHeight ? document.documentElement.clientHeight : document.body.offsetHeight)), + 'em': $(this).px('fontSize'), // eviter un bug MSIE sur fontSize + 'class': me.className, + 'color': $(this).css('color'), + 'font-size': $(this).px('fontSize'), + 'font-family': $(this).css('fontFamily'), + 'font-weight': $(this).css('fontWeight'), + 'line-height': $(this).css('lineHeight'), + 'min-height': $(this).css('lineHeight'), + 'text-align': $(this).css('textAlign'), + 'background-color': $(this).css('backgroundColor'), + 'self': configCrayons.self + }; + if (me.type) params.type = me.type; + if (params['background-color'] == 'transparent' + || params['background-color'] == 'rgba(0, 0, 0, 0)') { + $(me).parents() + .each(function(){ + var bg = $(this).css('backgroundColor'); + if (bg != 'transparent' + && (params['background-color'] == 'transparent' + || params['background-color'] == 'rgba(0, 0, 0, 0)')) + params['background-color'] = bg; + }); + } + $.post(configCrayons.url_crayons_html, + params, + function (c) { + try { + c = $.parseJSON(c); + } catch(e) { + c = {'$erreur': 'erreur de communication :' + ' ' + e.message, '$html':''}; + } + $(me) + .find("em.crayon-searching") + .remove(); + if (c.$erreur) { + uniAlert(c.$erreur); + return false; + } + id_crayon++; + + var position = 'absolute'; + $(me).parents().each(function(){ + if($(this).css("position") == "fixed") + position = 'fixed'; + }); + + $(me) + .css('visibility','hidden') + .addClass('crayon-has') + .find('>.crayon-icones') + .attr('rel','crayon_'+id_crayon); + if ($.browser.msie) $(me).css({'zoom':1}); + var pos = $(me).offset(); + $('
') + .css({ + 'position':position, + 'top':pos['top']-1, + 'left':pos['left']-1 + }) + .appendTo('body') + .html(c.$html); + $(me) + .activatecrayon(percent); + // Si le crayon a une taille mini qui le fait deborder + // a droite de l'ecran, recadrer vers la gauche + var diff = $('#crayon_'+id_crayon).offset().left + $('#crayon_'+id_crayon).width() - $(window).width(); + if (diff>0) { + $('#crayon_'+id_crayon) + .css({'left': parseInt(pos['left'])-diff}); + } + } + ); + } + }); +}; + +// annule le crayon ouvert (fonction destructive) +$.fn.cancelcrayon = function() { + this + .filter('.crayon-has') + .css('visibility','visible') + .removeClass('crayon-has') + .removeClass('crayon-changed') + .crayon() + .remove(); + return this; +}; + +// masque le crayon ouvert +$.fn.hidecrayon = function() { + this + .filter('.crayon-has') + .css('visibility','visible') + .crayon() + .hide() + .removeClass('crayon-hover'); + return this; +}; + +// active un crayon qui vient d'etre charge +$.fn.activatecrayon = function(percent) { + var focus = false; + this + .crayon() + .click(function(e){ + e.stopPropagation(); + }); + this + .each(function(){ + var me = $(this); + var crayon = $(this).crayon(); + crayon + .find('form') + .append( + $('') + .attr('value',configCrayons.self) + ) + .ajaxForm({ + "dataType":"json", + "error": function(d) { + uniAlert('erreur de communication'); + crayon + .empty() + .append( + $('
') + .html(d.responseText || d.error || 'erreur inconnue') + ) + .css({ + background: 'white', + color: 'black', + width: '480px', + border: 'red solid 2px', + padding: '10px'} + ); + }, + "success": function(d) { + // parfois le JSON n'est pas renvoye sous forme d'objet + // mais d'une chaine encadree de
...
+ if (typeof d == "string") { + try { + d = $.parseJSON(d.replace(/^
/,'').replace(/<[/]pre>$/,''));
+					} catch(e) {
+						d = {'$erreur': 'erreur de communication :' + '  ' + e.message, '$html':''};
+					}
+				}
+				me
+				.find("em.crayon-searching")
+					.remove();
+
+				//Remise a zero des warnings invalides (unwrap)
+				crayon
+				.find("span.crayon-invalide p")
+					  .remove();
+				crayon
+				.find("span.crayon-invalide")
+					  .each(function(){
+					      $(this).replaceWith( this.childNodes );
+						}
+					    );
+
+				if(d.$invalides) {
+					for (invalide in d.$invalides) {
+						//Affichage des warnings invalides
+						d.$invalides[invalide]['retour']?retour=d.$invalides[invalide]['retour']:retour='';
+						d.$invalides[invalide]['msg']?msg=d.$invalides[invalide]['msg']:msg='';
+						crayon
+						    .find("*[name='content_"+invalide+"']")
+							.wrap("")
+						    .parent()
+						    .append("

" + + retour + + " " + + msg + + "

" + ); + } + + } + + if (d.$erreur > '') { + if (d.$annuler) { + if (d.$erreur > ' ') { + uniAlert(d.$erreur); + } + me + .cancelcrayon(); + } else { + uniAlert(d.$erreur+'\n'+configCrayons.txt.error); + } + } + + if (d.erreur > '' || d.$invalides) { + crayon + .find('form') + .css('opacity', 1.0) + .find(".crayon-boutons,.resizehandle") + .show() + .end() + .find('.crayon-searching') + .remove(); + return false; + } + // Desactive celui pour qui on vient de recevoir les nouvelles donnees + $(me) + .cancelcrayon(); + // Insere les donnees dans *tous* les elements ayant le meme code + var tous = $( + '.crayon.crayon-autorise.' + + me[0].className.match(/crayon ([^ ]+)/)[1] + ) + .html( + d[$('input.crayon-id', crayon).val()] + ) + .iconecrayon(); + // Declencher le onAjaxLoad normal de SPIP + if (typeof jQuery.spip == 'object' && typeof jQuery.spip.triggerAjaxLoad == 'function') { + jQuery.spip.triggerAjaxLoad(tous.get()); + } + // SPIP 2.x + else if (typeof triggerAjaxLoad == 'function') { + triggerAjaxLoad(tous.get()); + } + }}) + .bind('form-submit-validate',function(form,a, e, options, veto){ + if(!veto.veto) + crayon + .find('form') + .css('opacity', 0.5) + .after(configCrayons.mkimg('searching')) // icone d'attente + .find(".crayon-boutons,.resizehandle") + .hide(); + }) + // keyup pour les input et textarea ... + .keyup(function(e){ + crayon + .find(".crayon-boutons") + .show(); + me + .addClass('crayon-changed'); + e.cancelBubble = true; // ne pas remonter l'evenement vers la page + }) + // ... change pour les select : ici on submit direct, pourquoi pas + .change(function(e){ + crayon + .find(".crayon-boutons") + .show(); + me + .addClass('crayon-changed'); + e.cancelBubble = true; + }) + .keypress(function(e){ + e.cancelBubble = true; + }) + // focus par defaut (crayons sans textarea/text, mais uniquement menus ou fichiers) + .find('input:visible:not(:disabled):not([readonly]):first').focus().end() + .find("textarea.crayon-active,input.crayon-active[type=text]") + .each(function(n){ + // focus pour commencer a taper son texte directement dans le champ + // sur le premier textarea non readonly ni disabled + // on essaie de positionner la selection (la saisie) au niveau du clic + // ne pas le faire sur un input de [type=file] + if (n==0) { + if(!$(this).is(':disabled, [readonly]')){ + this.focus(); + focus = true; + } + // premiere approximation, en fonction de la hauteur du clic + var position = parseInt(percent * this.textLength); + this.selectionStart=position; + this.selectionEnd=position; + }else if(!focus && !$(this).is(':disabled, [readonly]')) + this.focus(); + }) + .end() + .keydown(function(e){ + if(!e.charCode && e.keyCode == 119 /* F8, windows */) { + crayon + .find("form.formulaire_crayon") + .submit(); + } + if (e.keyCode == 27) { /* esc */ + me + .cancelcrayon(); + } + }) + .keypress(function(e){ + // Clavier pour sauver + if ( + (e.ctrlKey && ( + /* ctrl-s ou ctrl-maj-S, firefox */ + ((e.charCode||e.keyCode) == 115) || ((e.charCode||e.keyCode) == 83)) + /* ctrl-s, safari */ + || (e.charCode==19 && e.keyCode==19) + ) || + ( + e.shiftKey && (e.keyCode == 13) /* shift-return */ + ) + ) { + crayon + .find("form.formulaire_crayon") + .submit(); + } + var maxh = this.className.match(/\bmaxheight(\d+)?\b/); + if (maxh) { + maxh = maxh[1] ? parseInt(maxh[1]) : 200; + maxh = this.scrollHeight < maxh ? this.scrollHeight : maxh; + if (maxh > this.clientHeight) { + $(this).css('height', maxh + 'px'); + } + } + }) + .find(".crayon-submit") + .click(function(e){ + e.stopPropagation(); + $(this) + .parents("form:eq(0)") + .submit(); + }) + .end() + .find(".crayon-cancel") + .click(function(e){ + e.stopPropagation(); + me + .cancelcrayon(); + }) + .end() + // decaler verticalement si la fenetre d'edition n'est pas visible + .each(function(){ + var offset = $(this).offset(); + var hauteur = parseInt($(this).css('height')); + var scrolltop = $(window).scrollTop(); + var h = $(window).height(); + if (offset['top'] - 5 <= scrolltop) + $(window).scrollTop(offset['top'] - 5); + else if (offset['top'] + hauteur - h + 20 > scrolltop) + $(window).scrollTop(offset['top'] + hauteur - h + 30); + // Si c'est textarea, on essaie de caler verticalement son contenu + // et on lui ajoute un resizehandle + $("textarea", this) + .each(function(){ + if (percent && this.scrollHeight > hauteur) { + this.scrollTop = this.scrollHeight * percent - hauteur; + } + }) + .resizehandle() + // decaler les boutons qui suivent un resizer de 16px vers le haut + .next('.resizehandle') + .next('.crayon-boutons') + .addClass('resizehandle_boutons'); + }) + .end(); + // Declencher le onAjaxLoad normal de SPIP + // (apres donc le chargement de la page de saisie (controleur)) + if (typeof jQuery.spip == 'object' && typeof jQuery.spip.triggerAjaxLoad == 'function') { + jQuery.spip.triggerAjaxLoad(crayon.get()); + } + // SPIP 2.x + else if (typeof triggerAjaxLoad == 'function') { + triggerAjaxLoad(crayon.get()); + } + }); +}; + +// insere les icones et le type de crayon (optionnel) dans l'element +$.fn.iconecrayon = function(){ + return this.each(function() { + var ctype = this.className.match(/\b[^-]type_(\w+)\b/); + type = (ctype) ? ctype[1] : 'crayon'; + if (ctype) this.type = type; // Affecte son type a l'objet crayon + $(this).prepend(configCrayons.iconclick(this.className, type)) + .find('.crayon-' + type + ', .crayon-img-changed') // le crayon a clicker lui-meme et sa memoire + .click(function(e){ + $(this).parents('.crayon:eq(0)').opencrayon(e); + }); + }); +}; + +// initialise les crayons +$.fn.initcrayon = function(){ + var editme = function(e){ + timeme=null; + $(this).opencrayon(e, + // calcul du "percent" du click par rapport a la hauteur totale du div + ((e.pageY ? e.pageY : e.clientY) - document.body.scrollTop - this.offsetTop) + / this.clientHeight); + }; + var timeme; + this + .addClass('crayon-autorise') + .dblclick(editme) + .bind("touchstart",function(e){var me=this;timeme=setTimeout(function(){editme.apply(me,[e]);},800);}) + .bind("touchend",function(e){if (timeme) {clearTimeout(timeme);timeme=null;}}) + .iconecrayon() + .hover( // :hover pour MSIE + function(){ + $(this) + .addClass('crayon-hover') + .find('>span.crayon-icones') + .find('>span>em.crayon-' + (this.type||'crayon') + ',>span>em.crayon-edit') + .show();//'visibility','visible'); + },function(){ + $(this) + .removeClass('crayon-hover') + .find('>span.crayon-icones') + .find('>span>em.crayon-' + (this.type||'crayon') + ',>span>em.crayon-edit') + .hide();//('visibility','hidden'); + } + ); + return this; +}; + +// demarrage +$.fn.crayonsstart = function() { + if (!configCrayons.droits) return; + id_crayon = 0; // global + + // sortie, demander pour sauvegarde si oubli + if (configCrayons.txt.sauvegarder) { + $(window).unload(function(e) { + var chg = $(".crayon-changed"); + if (chg.length && uniConfirm(configCrayons.txt.sauvegarder)) { + chg.crayon().find('form').submit(); + } + }); + } + + // demarrer les crayons + if ((typeof crayons_init_dynamique == 'undefined') || (crayons_init_dynamique==false)) { + + // compat jQuery 1.9 + if (typeof $.fn.live == 'undefined') { + $.fn.live = function( types, data, fn ) { + $( this.context ).on( types, this.selector, data, fn ); + return this; + }; + } + $('.crayon:not(.crayon-init)') + .live('mouseover touchstart', function(e) { + $(this) + .addClass('crayon-init') + .filter(configCrayons.droits) + .initcrayon() + .trigger('mouseover'); + if (e.type=='touchstart') + $(this).trigger('touchstart'); + }); + } + + // un clic en dehors ferme tous les crayons ouverts ? + if (configCrayons.cfg.clickhide) + $("html") + .click(function(){ + $('.crayon-has') + .hidecrayon(); + }); +}; + +})(jQuery);