(function($){ /* * crayons.js (c) Fil, toggg, 2006-2019 -- 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(); } if (evt) { evt.preventDefault(); } return this .each(function(){ var $me = $(this); // verifier que je suis un crayon if (!$me.is('.crayon')) return; // voir si je dispose deja du crayon comme voisin if ($me.is('.crayon-has')) { $me .css('visibility','hidden') .crayon() .show(); } // sinon charger le formulaire else { // sauf si je suis deja en train de le charger (lock) if ($me.is('.crayon-loading')) { return; } $me .addClass('crayon-loading') .find('>span.crayon-icones span') .append(configCrayons.mkimg('searching')); // icone d'attente var me=this; var offset = $me.offset(); var bgcolor = $me.css('backgroundColor'); var params = { 'top': offset.top, 'left': offset.left, 'w': $me.width(), 'h': $me.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': $me.css('fontSize'), // Bug de jquery resolu : http://bugs.jquery.com/ticket/760 'class': this.className, 'color': $me.css('color'), 'font-size': $me.css('fontSize'), 'font-family': $me.css('fontFamily'), 'font-weight': $me.css('fontWeight'), 'line-height': $me.css('lineHeight'), 'min-height': $me.css('lineHeight'), 'text-align': $me.css('textAlign'), 'background-color': $me.css('backgroundColor'), 'self': configCrayons.self }; if (this.type) params.type = this.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 .removeClass('crayon-loading') .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); // Detection IE sur sa capacite a gerer zoom : // http://www.sitepoint.com/detect-css3-property-browser-support/ if (document.createElement("detect").style.zoom === "") { $me.css({'zoom':1}); } var pos = $me.offset(); var styles = { 'position':position, 'top':pos['top']-1, 'left':pos['left']-1 }; var zindex = $me.zindexcrayon(); if (zindex) { styles['z-index'] = zindex + 1; } $('
') .css(styles) .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}); } } ); } }); }; // trouver le zindex des crayons en remontant les parents // pour voir si un z-index est imposé quelque part $.fn.zindexcrayon = function() { var zindex=0; this.parents().each(function(){ var thiszindex = parseInt(jQuery(this).css('z-index')); if (thiszindex && thiszindex>zindex) { zindex = thiszindex; } }); return zindex; } // 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; }; $.fn.restorecrayon = function(showButtons) { this .removeClass('crayon-loading') .find("em.crayon-searching") .remove(); if (showButtons) { this .find(".crayon-boutons,.resizehandle") .show() } 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 .restorecrayon(true) .prepend( $('
') .html(d.responseText || d.statusText || 'erreur inconnue') ) ; }, "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.restorecrayon(false);

				//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 (var invalide in d.$invalides) {
						var retour, msg;
						//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.restorecrayon(true); 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(); // Invalider des préchargements ajax if (typeof jQuery.spip == 'object' && typeof jQuery.spip.preloaded_urls == 'object') { jQuery.spip.preloaded_urls = {}; } // Declencher le onAjaxLoad normal de SPIP if (typeof jQuery.spip == 'object' && typeof jQuery.spip.triggerAjaxLoad == 'function') { jQuery.spip.triggerAjaxLoad(tous.get()); } }}) .bind('form-submit-validate',function(form,a, e, options, veto){ if(!veto.veto) crayon .addClass('crayon-loading') .find('form') .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){ 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'); } } e.cancelBubble = true; }) // focus par defaut (crayons sans textarea/text, mais uniquement menus ou fichiers) .find('select:visible:not(:disabled):not([readonly]):first').focus().end() .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){ // Clavier pour sauver if ( (!e.charCode && e.keyCode == 119 /* F8, windows */) || (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 */ ) ) { e.preventDefault(); // Lorsque l'on utilise ctrl+s, on n'ouvre pas la fenêtre de sauvegarde crayon .find("form.formulaire_crayon") .submit(); } if (e.keyCode == 27) { /* esc */ me .cancelcrayon(); } }) .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()); } }); }; // 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/); var 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' + (configCrayons.cfg.yellow_fade ? ' crayon-fade' : '')) .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)) { $(function(){ $('body') .on('mouseover touchstart', '.crayon:not(.crayon-init)', function(e) { //console.log('over'); //console.log(this); $(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);