[SPIP] ~2.1.12 -->2.1.25
[velocampus/web/www.git] / www / prive / javascript / multilang.js
1 /*
2 * multilang
3 *
4 * Copyright (c) 2006-2014 Renato Formato (rformato@gmail.com)
5 * Licensed under the GPL License:
6 * http://www.gnu.org/licenses/gpl.html
7 *
8 */
9
10 var multilang_containers={}, //menu containers
11 forms_fields={},
12 multilang_forms, //forms to be processed (jQuery object)
13 multilang_menu_lang; //template of the menu (jQuery object)
14 /*
15 (?:\[([a-z_]+)\]|^[\s\n]*)
16 [lang] or white space
17
18 ((?:.|\n)*?)
19 all chars not greedy
20
21 (?=\[[a-z_]+\]|$)
22 [lang] or end string
23 */
24 var match_multi = /(?:\[([a-z_]+)\]|^[\s\n]*)((?:.|\n|\s)*?)(?=\[[a-z_]+\]|$)/ig;
25 var multilang_css_link,
26 multilang_css_cur_link={},
27 multilang_root, //root of the search (jQuery object)
28 multilang_fields_selector,
29 multilang_menu_selector,
30 multilang_forms_selector; //selector of the forms to be processed (string)
31 multilang_css_link = {"cursor":"pointer","margin":"2px 5px","float":"left"};
32 $.extend(multilang_css_cur_link,multilang_css_link,{fontWeight:"bold"});
33
34 /* options is a hash having the following values:
35 * - fields (mandatory): a jQuery selector to set the fields that have to be internationalized.
36 * - page (optional): a string to be searched in the current url. if found the plugin is applied.
37 * - root (optional): the root element of all processing. Default value is 'document'. To speed up search
38 * - forms (optional): a jQuery selector to set the forms that have to be internationalized. Default value is 'form'.
39 * - main_menu (optional): a jQuery selector to set the container for the main menu to control all the selected forms.
40 * - form_menu (optional): a jQuery selector to set the container for the form menus.
41 */
42 function multilang_init_lang(options) {
43 //Detect if we're on the right page and if multilinguism is activated. If not return.
44 if((options.page && window.location.search.indexOf(options.page)==-1) || multilang_avail_langs.length<=1) return;
45 //set the root element of all processing
46 var root = options.root || document;
47 multilang_root = $(root);
48 //set the main menu element
49 multilang_containers = options.main_menu ? $(options.main_menu,multilang_root) : $([]);
50 //create menu lang template
51 multilang_menu_lang =$("<div>");
52 $.each(multilang_avail_langs,function() {
53 multilang_menu_lang.append($("<a>").html("["+this+"]").css(this==multilang_def_lang?multilang_css_cur_link:multilang_css_link)[0]);
54 });
55 //store all the internationalized forms
56 multilang_forms_selector = options.forms || "form";
57 multilang_forms = $(multilang_forms_selector,multilang_root);
58 //create menu lang for the global form
59 if(multilang_containers.size()) forms_make_menu_lang(multilang_containers);
60 //init fields
61 multilang_fields_selector = options.fields;
62 multilang_menu_selector = options.form_menu;
63 forms_init_multi();
64 }
65
66 function forms_make_menu_lang(container,target) {
67 target = target || multilang_forms;
68 $(multilang_menu_lang).clone().find("a").click(function() {forms_change_lang(this,container,target)}).end().
69 append("<div style='clear:left'></div>").appendTo(container);
70 }
71
72 function forms_change_lang(el,container,target) {
73 var lang = el.innerHTML;
74 container = container || multilang_containers;
75 //update lang menu with current selection
76 container.find("a").each(function(){
77 $(this).css("fontWeight",lang==this.innerHTML?"bold":"normal");
78 }).end();
79 lang = lang.slice(1,-1);
80 //store the fields inputs for later use (usefull for select)
81 var target_id = target!=multilang_forms?jQuery.data(target[0]):"undefined";
82 if(!forms_fields[target_id]) forms_fields[target_id] = $(multilang_fields_selector,target);
83 //save the current values
84 forms_fields[target_id].each(function(){
85 forms_save_lang(this,this.form.form_lang);
86 });
87 //change current lang
88 target.each(function(){this.form_lang = lang});
89 //reinit fields to current lang
90 forms_fields[target_id].each(function(){forms_set_lang(this,lang)});
91 }
92
93 function forms_init_multi(options) {
94 var target = options?options.target:null;
95 var init_forms;
96 //Update the list of form if this is an update
97 if(target) {
98 //Verify the target is really a form to be internationalized (in case of an ajax request fired by onAjaxLoad)
99 if(target==document) return;
100 init_forms = $(target).find('form').in_set($(multilang_forms_selector,multilang_root));
101 if(!init_forms.length) return;
102 multilang_forms.add(init_forms.each(forms_attach_submit).get());
103 } else {
104 //attach multi processing to submit event
105 init_forms = multilang_forms;
106 multilang_forms.each(forms_attach_submit);
107 }
108 forms_fields = {};
109 forms_fields["undefined"] = $(multilang_fields_selector,multilang_forms);
110 //init the value of the field to current lang
111 //add a container for the language menu inside the form
112 init_forms.each(function() {
113 this.form_lang = multilang_def_lang;
114 var container = multilang_menu_selector ? $(multilang_menu_selector,this) : $(this);
115 container.prepend("<div class='menu_lang'>");
116 });
117 $(multilang_fields_selector,init_forms).each(function(){
118 forms_init_field(this,this.form.form_lang);
119 });
120 //create menu for each form. The menu is just before the form
121 $("div.menu_lang",init_forms).empty().each(function() {
122 //store all form containers to allow menu lang update on each container
123 //when it is triggered by global menu
124 multilang_containers.add(this);
125 forms_make_menu_lang($(this),$(this).parents("form"));
126 });
127 }
128
129 function forms_attach_submit() {
130 var oldsubmit = this.onsubmit;
131 this.onsubmit = "";
132 if(oldsubmit) $(this).submit(function(){forms_multi_submit.apply(this);return oldsubmit.apply(this);})
133 else $(this).submit(forms_multi_submit);
134 }
135
136 function forms_init_field(el,lang) {
137 //Retrieves the following data
138 //1)the title element of the field
139 //2)boolean multi = the fields has a multi value
140 //3)various lang string
141 //if already inited just return
142 if(el.field_lang) return;
143 var langs;
144 var m = el.value.match(/(\d+\.\s+)?<multi>((?:.|\n|\s)*?)<\/multi>/);
145 el.field_lang = {};
146 el.field_pre_lang = ""; //this is the 01. part of the string, the will be put outside the <multi>
147 el.titre_el = $("#titre_"+el.id);
148 if(m!=null) {
149 el.field_pre_lang = m[1] || "";
150 el.multi = true;
151 match_multi.lastIndex=0;
152 while((langs=match_multi.exec(m[2]))!=null) {
153 var text = langs[2].match(/^(\d+\.\s+)((?:.|\n|\s)*)/), value;
154 if(text!=null) {
155 value = text[2];
156 el.field_pre_lang = text[1] || "";
157 } else {
158 value = langs[2];
159 }
160 el.field_lang[langs[1]||multilang_def_lang] = value;
161 }
162 //Put the current lang string only in the field
163 forms_set_lang(el,lang);
164 } else {
165 el.multi = false;
166 el.field_lang[lang] = el.value;
167 }
168 }
169
170 function forms_set_lang(el,lang) {
171 //if current lang is not setted use default lang value
172 if(el.field_lang[lang]==undefined)
173 el.field_lang[lang] = el.field_lang[multilang_def_lang];
174 el.value = el.field_pre_lang+(el.field_lang[lang]==undefined?"":el.field_lang[lang]); //show the common part (01. ) before the value
175 el.titre_el.html(el.value);
176 }
177
178 function forms_save_lang(el,lang) {
179 //if the lang value is equal to the def lang do nothing
180 //else save value but if the field is not empty, delete lang value
181 var m = el.value.match(/^(\d+\.\s+)((?:.|\n|\s)*)/);
182 if(m!=null) {
183 el.field_pre_lang = m[1];
184 el.value = m[2];
185 }
186 if(el.field_lang[multilang_def_lang]!=el.value) {
187 if(!el.value) {
188 delete el.field_lang[lang];
189 return;
190 }
191 el.multi = true;
192 el.field_lang[lang] = el.value;
193 }
194 }
195
196 //This func receives the form that is going to be submitted
197 function forms_multi_submit(params) {
198 if(multilang_avail_langs.length<=1) return;
199 var form = this;
200 //remove the current form from the list of forms
201 multilang_forms.not(this);
202 //remove the current menu lang container from the list
203 multilang_containers.not("div.menu_lang",$(this));
204 //build the input values
205 $(multilang_fields_selector,this).each(function(){
206 //save data before submit
207 forms_save_lang(this,form.form_lang || multilang_def_lang);
208 //build the string value
209 var def_value = this.field_lang[multilang_def_lang];
210 if(!this.multi) this.value = this.field_pre_lang+(def_value==undefined?"":def_value);
211 else {
212 var value="",count=0;
213 $.each(this.field_lang,function(name){
214 //save default lang value and other lang values if different from
215 //the default one
216 if(this!=def_value || name==multilang_def_lang) {
217 value += "["+name+"]"+this;
218 count++;
219 }
220 });
221 this.value = this.field_pre_lang+(count!=1?"<multi>"+value+"</multi>":value.replace(/^\[[a-z_]+\]/,''));
222 }
223 });
224 //save back the params
225 if(params) $.extend(params,$(form).formToArray(false));
226 }
227
228 jQuery.fn.in_set = function(set) {
229 var elements = this.get();
230 var result = $.grep(set,function(i){
231 var found = false;
232 $.each(elements,function(){
233 if(this==i) found=true;
234 })
235 return found;
236 });
237 return jQuery(result);
238 }