Valider 0ef7e66f rédigé par marcimat's avatar marcimat
Parcourir les fichiers

Ticket #12: Éviter un recalcul si on modifie le formulaire de configuration de Bigup.

Changement de stratégie assez important pour le coup, et notamment pour séparer un peu certaines fonctions JS
qui pourraient être génériques dans SPIP.

A) On sépare le JS de bigup pour clarifier et minimiser la partie compilée par SPIP :

1) le fichier bigup.utils.js déclare des fonctions génériques, notamment
un objet `Traductions` qu’on instancie dans une variable globale `Trads`.
Cet objet permet d’obtenir, à partir d’un nom de clé et module, une traduction qui y aurait été déclaré.
Note: ça ne gère pas de langue actuellement, en supposant que le texte contenu est dans la langue de l’utilisateur,
mais on pourrait éventuellement être plus précis dans le futur.
Trads dispose de fonctions tel que `Trads.traduire('module:cle')` ou `Trads.singulier_ou_pluriel(nb, 'module:singulier', 'module:pluriel')`,
dont la signature est comme on l’imagine, l’équivalent de ces fonctions en PHP.
On déclare d’ailleurs une fonction _T() alias de Trads.traduire(), qui est utilisée dans bigup.js ensuite.

2) le fichier bigup.trads.js.html déclare les traductions de bigup (et aussi 'unites') à l’objet Trads, dans une certaine langue.

3) bigup.js déclare la classe Bigup et quelques fonctions pour bigup, mais n’instancie pas la classe.

4) bigup.loader.js instancie où on le souhaite le script bigup, en l’occurrence, comme avant, sur tout input file
ayant la classe .bigup, dans un formulaire SPIP.

5) on déclare la configuration JS de bigup directement dans le pipeline insert_head, de sorte qu’elle ne soit pas en cache.
Et on adapte les chargements des pipelines en conséquence.
parent 3d49a283
Chargement en cours
Chargement en cours
Chargement en cours
Chargement en cours
+43 −6
Numéro de ligne d'origine Numéro de ligne de diff Ligne de diff
@@ -20,23 +20,60 @@ if (!defined('_ECRIRE_INC_VERSION')) return;
**/
function bigup_jquery_plugins($scripts) {
	if (test_espace_prive() or lire_config('bigup/charger_public', false)) {
		$scripts[] = 'javascript/bigup.utils.js';
		$scripts[] = produire_fond_statique('javascript/bigup.trads.js', array(
			'lang' => $GLOBALS['spip_lang'],
		));
		$scripts[] = 'lib/flow/flow.js';
		$scripts[] = produire_fond_statique('javascript/bigup.js');
		$scripts[] = 'javascript/bigup.js';
		$scripts[] = 'javascript/bigup.loader.js';
	}
	return $scripts;
}

/**
 * Charger des styles CSS
 * Charger des JS dans l’espace public
 *
 * @pipeline insert_head_css
 * @param string $flux Code html des styles CSS à charger
 * @return string Code html complété
 **/
function bigup_insert_head($flux) {
	if (lire_config('bigup/charger_public', false)) {
		$flux = bigup_header_prive($flux);
	}
	return $flux;
}

/**
 * Charger des JS dans l’espace prive
 *
 * @pipeline insert_head_css
 * @param string $flux Code html des styles CSS à charger
 * @return string Code html complété
 **/
function bigup_header_prive($flux) {
	$maxFileSize = intval(lire_config('bigup/max_file_size', 0));
	$flux .= <<<EOS
<script type='text/javascript'>
jQuery.bigup_config = {
	maxFileSize: $maxFileSize
}
</script>
EOS;
	return $flux;
}

/**
 * Charger des styles CSS dans l’espace public
 *
 * @pipeline insert_head_css
 * @param string $flux Code html des styles CSS à charger
 * @return string Code html complété
**/
function bigup_insert_head_css($flux) {
	if (test_espace_prive() or lire_config('bigup/charger_public', false)) {
		$flux .= '<link rel="stylesheet" href="' . produire_fond_statique('css/vignettes.css') . '" type="text/css" />' . "\n";
		$flux .= '<link rel="stylesheet" href="' . timestamp(find_in_path('css/bigup.css')) . '" type="text/css" />' . "\n";
	if (lire_config('bigup/charger_public', false)) {
		$flux = bigup_header_prive_css($flux);
	}
	return $flux;
}
@@ -48,7 +85,7 @@ function bigup_insert_head_css($flux) {
 * @param string $flux Code html des styles CSS à charger
 * @return string Code html complété
**/
function bigup_header_prive($flux) {
function bigup_header_prive_css($flux) {
	$flux .= '<link rel="stylesheet" href="' . produire_fond_statique('css/vignettes.css') . '" type="text/css" />' . "\n";
	$flux .= '<link rel="stylesheet" href="' . timestamp(find_in_path('css/bigup.css')) . '" type="text/css" />' . "\n";
	return $flux;
+26 −139
Numéro de ligne d'origine Numéro de ligne de diff Ligne de diff
#HTTP_HEADER{Content-Type: text/javascript}
[(#REM)<script>]

jQuery(function($){
	var formulaires_avec_bigup = function() {
		// trouver les input qui envoient des fichiers
		$(".formulaire_spip form input[type=file].bigup").bigup();
	}
	formulaires_avec_bigup();
	onAjaxLoad(formulaires_avec_bigup);
});


/**
 * Pour un input de type file sélectionné,
 * gère l'upload du ou des fichiers, via html5 et flow.js
@@ -54,9 +41,9 @@ $.fn.bigup = function(options, callbacks) {
		}

		// config globale de bigup.
		var conf = {
			maxFileSize: [(#CONFIG{bigup/max_file_size, 0})]
		}
		var conf = $.extend(true, {
			maxFileSize: 0
		}, $.bigup_config || {});

		var bigup = new Bigup(
			{
@@ -64,7 +51,7 @@ $.fn.bigup = function(options, callbacks) {
				input: $input,
				formulaire_action: $form.find('input[name=formulaire_action]').val(),
				formulaire_action_args: $form.find('input[name=formulaire_action_args]').val(),
				token: $input.data('token'),
				token: $input.data('token')
			},
			{
				contraintes: {
@@ -93,6 +80,8 @@ $.fn.bigup = function(options, callbacks) {
 * Bigup gère les fichiers des input concernés (avec Flow.js)
 * et leur communication avec SPIP
 *
 * Nécessite un accès à Trads.
 *
 * @param [params]
 * @param {jquery} [params.form]
 * @param {jquery} [params.input]
@@ -116,17 +105,13 @@ function Bigup(params, opts, callbacks) {
	this.formulaire_action_args = params.formulaire_action_args;
	this.token = params.token;

	this.target = this.enlever_ancre(this.form.attr('action'));
	this.target = $.enlever_ancre(this.form.attr('action'));
	this.name = this.input.attr('name');
	this.class_name = this.nom2classe(this.name);
	this.class_name = $.nom2classe(this.name);
	this.multiple  = this.input.prop('multiple');

	this.textes = {
		erreur_de_transfert: "<:bigup:erreur_de_transfert|attribut_html:>",
		erreur_taille_max: "<:bigup:erreur_taille_max|attribut_html:>",
		erreur_type_fichier: "<:bigup:erreur_type_fichier|attribut_html:>",
		erreur_probleme_survenu: "<:bigup:probleme_survenu|attribut_html:>"
	};
	// a améliorer...
	this.textes = params.trads;

	this.zones = {
		depot: null,
@@ -142,8 +127,8 @@ function Bigup(params, opts, callbacks) {
		options: {
			// previsualisation des images
			previsualisation: {
				activer: this.input.data("previsualiser") ? true : false,
				fileSizeMax: 10, // 10 Mb
				activer: !!this.input.data("previsualiser"),
				fileSizeMax: 10 // 10 Mb
			}
		},
		templates: {
@@ -152,12 +137,13 @@ function Bigup(params, opts, callbacks) {
				depot: function (name, multiple) {
					var template =
						'\n<div class="dropfile dropfile_' + name + '" style="display:none;">'
						+ '\n\t<span class="dropfilebutton bigup-btn btn btn-default"><:bigup:televerser|texte_script:></span>'
						+ '\n\t<span class="dropfileor"><:bigup:ou|texte_script:></span>'
						+ '\n\t<span class="dropfilebutton bigup-btn btn btn-default">'
						+ _T('bigup:televerser')
						+ '</span>'
						+ '\n\t<span class="dropfileor">' + _T('bigup:ou') + '</span>'
						+ '\n\t<span class="dropfiletext">'
						+ '\n\t\t' + (multiple
							? '<:bigup:deposer_vos_fichiers_ici|texte_script:>'
							: '<:bigup:deposer_votre_fichier_ici|texte_script:>' )
						+ '\n\t\t'
						+ Trads.singulier_ou_pluriel(!multiple, 'bigup:deposer_votre_fichier_ici', 'bigup:deposer_vos_fichiers_ici')
						+ '\n\t</:span:>'
						+ '\n</div>\n';
					return template;
@@ -172,7 +158,6 @@ function Bigup(params, opts, callbacks) {
			fichier: function(file) {
				// retouver l'extension
				var extension = $.trouver_extension(file.name);
				var t_annuler = "<:bouton_annuler|texte_script:>";

				var template =
					'\n<div class="fichier">'
@@ -183,7 +168,7 @@ function Bigup(params, opts, callbacks) {
					+ '\n\t\t\t<span class="size">' + $.taille_en_octets(file.size) + '</span>'
					+ '\n\t\t</div>'
					+ '\n\t\t<div class="actions">'
					+ '\n\t\t\t<span class="bigup-btn btn btn-default cancel" onClick="$.bigup_enlever_fichier(this); return false;">' + t_annuler + '</span>'
					+ '\n\t\t\t<span class="bigup-btn btn btn-default cancel" onClick="$.bigup_enlever_fichier(this); return false;">' + _T("bigup:bouton_annuler") + '</span>'
					+ '\n\t\t</div>'
					+ '\n\t</div>'
					+ '\n</div>\n';
@@ -232,51 +217,6 @@ function Bigup(params, opts, callbacks) {

Bigup.prototype = {

	/**
	 * Traduction d'un code de langue
	 */
	_T: function(code, couples) {
		var texte = this.textes[code];
		console.log(code, texte, this.textes);
		if (!texte) { return ''; }
		$.each(couples, function(cle, val) {
			texte = texte.replace('@' + cle + '@', val);
		});
		return texte;
	},

	/**
	 * retourne le texte singulier si nb vaut 1, sinon le texte pluriel.
	 */
	singulier_ou_pluriel: function(nb, texte_singulier, texte_pluriel) {
		nb == 1
			? this._T(texte_singulier)
			: this._T(texte_pluriel, {nb: nb});
	},

	/**
	 * Enlève une ancre d'une URL
	 * @param string $url
	 */
	enlever_ancre: function(url) {
		p = url.indexOf('#');
		if (p!=-1) {
			ancre = url.substring(p);
			url = url.substring(0,p);
		}
		return url;
	},

	/**
	 * Transforme un name en classe
	 * @see saisie_nom2classe() en PHP.
	 * @param string name
	 * @return string
	 */
	nom2classe: function(nom) {
		return nom.replace(/\/|\\[|&#91/g, '_').replace(/\]|&#93/g, '');
	},

	/**
	 * Redéfinir des options
	 * @param object options Options à modifier
@@ -318,9 +258,10 @@ Bigup.prototype = {
	 * @param string fichien DOM de l'emplacement de présentation du fichier
	 */
	ajouter_bouton_enlever: function(fichier) {
		var t_enlever = "<:bigup:bouton_enlever|texte_script:>";
		var js = "$.bigup_enlever_fichier(this); return true;";
		var inserer = '<span class="bigup-btn btn btn-default" onClick="' + js + '">' + t_enlever + '</span>';
		var inserer = '<span class="bigup-btn btn btn-default" onClick="' + js + '">'
			+ _T('bigup:bouton_enlever')
			+ '</span>';
		$(fichier).find('.actions').append(inserer);
		return this;
	},
@@ -397,7 +338,7 @@ Bigup.prototype = {
		this.flow.on('fileError', function(file, message, chunk){
			console.warn("error", file, message, chunk);
			me.progress.retirer(file.emplacement.find("progress"));
			me.presenter_erreur(file.emplacement, me._T('erreur_de_transfert'));
			me.presenter_erreur(file.emplacement, _T('bigup:erreur_de_transfert'));
		});
	},

@@ -484,14 +425,14 @@ Bigup.prototype = {
		if (this.opts.contraintes.maxFileSize) {
			var taille = this.opts.contraintes.maxFileSize * 1024 * 1024;
			if (file.size > taille) {
				file.erreur = this._T('erreur_taille_max', {taille: $.taille_en_octets(taille)});
				file.erreur = _T('bigup:erreur_taille_max', {taille: $.taille_en_octets(taille)});
				return false;
			}
		}
		if (this.opts.contraintes.accept) {
			var accept = this.opts.contraintes.accept;
			if (accept && !this.valider_fichier(file.file, accept)) {
				file.erreur = this._T('erreur_type_fichier');
				file.erreur = _T('bigup:erreur_type_fichier');
				return false;
			}
		}
@@ -600,7 +541,7 @@ Bigup.prototype = {
			});
		})
		.fail(function() {
			me.presenter_erreur(emplacement, me._T('erreur_probleme_survenu'));
			me.presenter_erreur(emplacement, _T('bigup:erreur_probleme_survenu'));
		});
	},

@@ -818,57 +759,3 @@ $.bigup_enlever_fichier = function(me) {
};

/**
 * Retrouve (et corrige) une extension dans un nom de fichier
 * @param string name Nom d'un fichier
 * @return string Extension du fichier
 */
$.trouver_extension = function(name) {
	// retouver l'extension
	var re = /(?:\.([^.]+))?$/;
	var extension = re.exec(name)[1];
	extension = extension.toLowerCase();

	// cf corriger_extension() dans plugin medias.
	switch (extension) {
		case 'htm':
			extension='html';
			break;
		case 'jpeg':
			extension='jpg';
			break;
		case 'tiff':
			extension='tif';
			break;
		case 'aif':
			extension='aiff';
			break;
		case 'mpeg':
			extension='mpg';
			break;
	}
	return extension;
};


/**
 * Calcule une taille en octets humainement lisible
 * @param int taille Taille en octets
 * @return string
 */
$.taille_en_octets = function(taille) {
	var ko = 1024;
	var t_octets = "<:taille_octets|texte_script:>";
	var t_ko     = "<:taille_ko|texte_script:>";
	var t_mo     = "<:taille_mo|texte_script:>";
	var t_go     = "<:taille_go|texte_script:>";
	if (taille < ko) {
		return t_octets.replace('@taille@', taille);
	} else if (taille < ko * ko) {
		return t_ko.replace('@taille@', Math.round(taille/ko * 10) / 10);
	} else if (taille < ko * ko * ko) {
		return t_mo.replace('@taille@', Math.round(taille/ko/ko * 10) / 10);
	} else {
		return t_go.replace('@taille@', Math.round(taille/ko/ko/ko * 10) / 10);
	}
};
 No newline at end of file
+8 −0
Numéro de ligne d'origine Numéro de ligne de diff Ligne de diff
jQuery(function($){
	var formulaires_avec_bigup = function() {
		// trouver les input qui envoient des fichiers
		$(".formulaire_spip form input[type=file].bigup").bigup();
	}
	formulaires_avec_bigup();
	onAjaxLoad(formulaires_avec_bigup);
});
 No newline at end of file
+38 −0
Numéro de ligne d'origine Numéro de ligne de diff Ligne de diff
#HTTP_HEADER{Content-Type: text/javascript; charset=utf-8}
#HTTP_HEADER{Vary: Accept-Encoding}
[(#REM)<script>]

/**
 * Déclarations d’unités, sert entre autre pour $.taille_en_octets
 */
Trads.set('unites', {
	taille_octets: "<:taille_octets|texte_script:>",
	taille_ko: "<:taille_ko|texte_script:>",
	taille_mo: "<:taille_mo|texte_script:>",
	taille_go: "<:taille_go|texte_script:>"
});

/**
 * Chaines de langue de Bigup
 */
Trads.set('bigup', {
	// B
	bouton_annuler: "<:bigup:bouton_annuler|texte_script:>",
	bouton_enlever: "<:bigup:bouton_enlever|texte_script:>",

	// D
	deposer_vos_fichiers_ici: "<:bigup:deposer_vos_fichiers_ici|texte_script:>",
	deposer_votre_fichier_ici: "<:bigup:deposer_votre_fichier_ici|texte_script:>",

	// E
	erreur_de_transfert: "<:bigup:erreur_de_transfert|texte_script:>",
	erreur_taille_max: "<:bigup:erreur_taille_max|texte_script:>",
	erreur_type_fichier: "<:bigup:erreur_type_fichier|texte_script:>",
	erreur_probleme_survenu: "<:bigup:erreur_probleme_survenu|texte_script:>",

	// O
	ou: "<:bigup:ou|texte_script:>",

	// T
	televerser: "<:bigup:televerser|texte_script:>"
});
 No newline at end of file
+154 −0
Numéro de ligne d'origine Numéro de ligne de diff Ligne de diff
/**
 * Déclaration de fonctions utilitaires,
 * indépendances de Bigup.
 *
 * - Gestion de clés de traductions en JS
 * - Reprise de fonctions PHP de SPIP en JS
 */

/** Alias pour avoir une fonction _T utilisable en js */
function _T(code, contexte) {
	return Trads.traduire(code, contexte);
}

/**
 * Gestion de traductions.
 *
 * Actuellement on ne déclare pas de langue, considérant
 * que les traductions ajoutées sont dans la langue de l’utilisateur.
 */
function Traductions() {
	this.modules = {};
};

Traductions.prototype = {

	set: function(module, couples_cle_traduction) {
		this.modules[module] = $.extend(this.modules[module] || {}, couples_cle_traduction);
	},

	get: function(module, code, contexte) {
		if (typeof this.modules[module] === 'undefined') {
			return '';
		}
		if (typeof this.modules[module][code] === 'undefined') {
			return '';
		}
		var texte = this.modules[module][code];
		$.each(contexte, function(cle, val) {
			texte = texte.replace('@' + cle + '@', val);
		});
		return texte;
	},

	/**
	 * Traduction d'un code de langue
	 *
	 * trads.traduire('bigup:supprimer_fichier');
	 * trads.traduire('bigup:supprimer_fichier', {fichier: 'nom.jpg'});
	 */
	traduire: function(code, contexte) {
		var desc = this.trouver_module_et_code(code);
		return this.get(desc.module, desc.code, contexte) || code;
	},

	/** Retrouve le nom du module et la clé d’un code de langue 'module:cle_de_langue' */
	trouver_module_et_code: function(code) {
		var list = code.split(':', 2);
		var module = list.shift();
		var cle = list.shift();
		if (cle) {
			return { module:module, code:cle };
		}
		return { module: 'spip', cle: module};
	},

	/**
	 * retourne le texte singulier si nb vaut 1, sinon le texte pluriel.
	 */
	singulier_ou_pluriel: function(nb, code_singulier, code_pluriel) {
		return parseInt(nb, 10) === 1
			? this.traduire(code_singulier)
			: this.traduire(code_pluriel, {nb: nb});
	}
};


// Déclarons un spécimen de traduction global.
Trads = new Traductions();


/**
 * Enlève une ancre d'une URL
 * @param string $url
 */
$.enlever_ancre = function(url) {
	var p = url.indexOf('#');
	if (p !== -1) {
		// var ancre = url.substring(p);
		url = url.substring(0,p);
	}
	return url;
};

/**
 * Transforme un name en classe
 * @see saisie_nom2classe() en PHP.
 * @param string name
 * @return string
 */
$.nom2classe = function(nom) {
	return nom.replace(/\/|\[|&#91/g, '_').replace(/\]|&#93/g, '');
};

/**
 * Calcule une taille en octets humainement lisible
 * @param int taille Taille en octets
 * @return string
 */
$.taille_en_octets = function(taille) {
	var ko = 1024;
	if (taille < ko) {
		return _T('unites:taille_octets', {taille: taille});
	} else if (taille < ko * ko) {
		return _T('unites:taille_ko', {taille: Math.round(taille/ko * 10) / 10});
	} else if (taille < ko * ko * ko) {
		return _T('unites:taille_mo', {taille: Math.round(taille/ko/ko * 10) / 10});
	} else {
		return _T('unites:taille_go', {taille: Math.round(taille/ko/ko/ko * 10) / 10});
	}
};


/**
 * Retrouve (et corrige) une extension dans un nom de fichier
 * @param string name Nom d'un fichier
 * @return string Extension du fichier
 */
$.trouver_extension = function(name) {
	// retouver l'extension
	var re = /(?:\.([^.]+))?$/;
	var extension = re.exec(name)[1];
	extension = extension.toLowerCase();

	// cf corriger_extension() dans plugin medias.
	switch (extension) {
		case 'htm':
			extension='html';
			break;
		case 'jpeg':
			extension='jpg';
			break;
		case 'tiff':
			extension='tif';
			break;
		case 'aif':
			extension='aiff';
			break;
		case 'mpeg':
			extension='mpg';
			break;
	}
	return extension;
};
Chargement en cours