r75195 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r75194‎ | r75195 | r75196 >
Date:15:43, 22 October 2010
Author:yaron
Status:deferred
Tags:
Comment:
Removed nearly all of the Javascript, except for the FCKeditor-related Javascript - it's now in SemanticForms.js
Modified paths:
  • /trunk/extensions/SemanticForms/includes/SF_FormUtils.php (modified) (history)

Diff [purge]

Index: trunk/extensions/SemanticForms/includes/SF_FormUtils.php
@@ -9,412 +9,33 @@
1010 */
1111
1212 class SFFormUtils {
 13+ static function setGlobalJSVariables( &$vars ) {
 14+ global $sfgAdderButtons, $sfgRemoverButtons;
 15+ global $sfgAutocompleteMappings, $sfgAutocompleteDataTypes, $sfgAutocompleteValues;
 16+ global $sfgAutocompleteOnAllChars, $sfgComboBoxInputs, $sfgAutogrowInputs;
 17+ global $sfgJSValidationCalls, $sfgShowOnSelectCalls;
1318
14 - /**
15 - * All the Javascript calls to validate both the type of each
16 - * form field and their presence, for mandatory fields
17 - */
18 - static function validationJavascript() {
19 - global $sfgJSValidationCalls;
20 -
21 - $form_errors_header = Xml::escapeJsString( wfMsg( 'sf_formerrors_header' ) );
22 - $blank_error_str = Xml::escapeJsString( wfMsg( 'sf_blank_error' ) );
23 - $bad_url_error_str = Xml::escapeJsString( wfMsg( 'sf_bad_url_error' ) );
24 - $bad_email_error_str = Xml::escapeJsString( wfMsg( 'sf_bad_email_error' ) );
25 - $bad_number_error_str = Xml::escapeJsString( wfMsg( 'sf_bad_number_error' ) );
26 - $bad_integer_error_str = Xml::escapeJsString( wfMsg( 'sf_bad_integer_error' ) );
27 - $bad_date_error_str = Xml::escapeJsString( wfMsg( 'sf_bad_date_error' ) );
28 -
29 - $javascript_text = <<<END
30 -
31 -function validate_mandatory_field(field_id, info_id) {
32 - var field = document.getElementById(field_id);
33 - // if there's nothing at that field ID, ignore it - it's probably
34 - // a hidden field
35 - if (field == null) {
 19+ $vars['sfgRemoveText'] = wfMsg( 'sf_formedit_remove' );
 20+ $vars['sfgAdderButtons'] = $sfgAdderButtons;
 21+ $vars['sfgRemoverButtons'] = $sfgRemoverButtons;
 22+ $vars['autocompleteOnAllChars'] = $sfgAutocompleteOnAllChars;
 23+ $vars['sfgAutocompleteMappings'] = $sfgAutocompleteMappings;
 24+ $vars['sfgAutocompleteValues'] = $sfgAutocompleteValues;
 25+ $vars['sfgAutocompleteDataTypes'] = $sfgAutocompleteDataTypes;
 26+ $vars['sfgComboBoxInputs'] = $sfgComboBoxInputs;
 27+ $vars['sfgAutogrowInputs'] = $sfgAutogrowInputs;
 28+ $vars['sfgFormErrorsHeader'] = Xml::escapeJsString( wfMsg( 'sf_formerrors_header' ) );
 29+ $vars['sfgBlankErrorStr'] = Xml::escapeJsString( wfMsg( 'sf_blank_error' ) );
 30+ $vars['sfgBadURLErrorStr'] = Xml::escapeJsString( wfMsg( 'sf_bad_url_error' ) );
 31+ $vars['sfgBadEmailErrorStr'] = Xml::escapeJsString( wfMsg( 'sf_bad_email_error' ) );
 32+ $vars['sfgBadNumberErrorStr'] = Xml::escapeJsString( wfMsg( 'sf_bad_number_error' ) );
 33+ $vars['sfgBadIntegerErrorStr'] = Xml::escapeJsString( wfMsg( 'sf_bad_integer_error' ) );
 34+ $vars['sfgBadDateErrorStr'] = Xml::escapeJsString( wfMsg( 'sf_bad_date_error' ) );
 35+ $vars['sfgJSValidationCalls'] = $sfgJSValidationCalls;
 36+ $vars['sfgShowOnSelectCalls'] = $sfgShowOnSelectCalls;
3637 return true;
3738 }
38 - if (field.value.replace(/\s+/, '') == '') {
39 - var info_span = document.getElementById(info_id);
40 - if ( info_span == null ) {
41 - alert ("no info span found at " + info_id + "!");
42 - } else {
43 - info_span.innerHTML = "$blank_error_str";
44 - }
45 - return false;
46 - } else {
47 - return true;
48 - }
49 -}
5039
51 -// special handling for radiobuttons, because what's being checked
52 -// is the first radiobutton, which has value of "None"
53 -function validate_mandatory_radiobutton(none_button_id, info_id) {
54 - none_button = document.getElementById(none_button_id);
55 - if (none_button && none_button.checked) {
56 - info_span = document.getElementById(info_id);
57 - info_span.innerHTML = "$blank_error_str";
58 - return false;
59 - } else {
60 - return true;
61 - }
62 -}
63 -
64 -function validate_mandatory_combobox(field_id, info_id) {
65 - var field = jQuery('input#' + field_id);
66 - // if there's nothing at that field ID, ignore it - it's probably
67 - // a hidden field
68 - if (field == null) {
69 - return true;
70 - }
71 - // FIXME
72 - // field.val() unfortunately doesn't work in IE - it just returns
73 - // "undefined". For now, if that happens, just exit
74 - var value = field.val();
75 - if (value == undefined) {
76 - alert(field.html());
77 - return true;
78 - }
79 - if (value.replace(/\s+/, '') == '') {
80 - var info_span = document.getElementById(info_id);
81 - info_span.innerHTML = "$blank_error_str";
82 - return false;
83 - } else {
84 - return true;
85 - }
86 -}
87 -
88 -function validate_mandatory_checkboxes(field_id, info_id) {
89 - // get all checkboxes - the "field_id" in this case is the span
90 - // surrounding all the checkboxes
91 - var checkboxes = jQuery('span#' + field_id + " > span > input");
92 - var all_unchecked = true;
93 - for (var i = 0; i < checkboxes.length; i++) {
94 - if (checkboxes[i].checked) {
95 - all_unchecked = false;
96 - }
97 - }
98 - if (all_unchecked) {
99 - info_span = document.getElementById(info_id);
100 - info_span.innerHTML = "$blank_error_str";
101 - return false;
102 - } else {
103 - return true;
104 - }
105 -}
106 -
107 -// validate a mandatory field that exists across multiple instances of
108 -// a template - we have to find each one, matching on the pattern of its
109 -// ID, and validate it
110 -function validate_multiple_mandatory_fields(field_num) {
111 - var num_errors = 0;
112 - elems = document.getElementsByTagName("*");
113 - var field_pattern = new RegExp('input_(.*)_' + field_num);
114 - for (var i = 0; i < elems.length; i++) {
115 - id = elems[i].id;
116 - if (matches = field_pattern.exec(id)) {
117 - instance_num = matches[1];
118 - var input_name = "input_" + instance_num + "_" + field_num;
119 - var info_name = "info_" + instance_num + "_" + field_num;
120 - if (! validate_mandatory_field(input_name, info_name)) {
121 - num_errors += 1;
122 - }
123 - }
124 - }
125 - return (num_errors == 0);
126 -}
127 -
128 -function validate_field_type(field_id, type, info_id) {
129 - field = document.getElementById(field_id);
130 - if (type != 'date' && field.value == '') {
131 - return true;
132 - } else {
133 - if (type == 'URL') {
134 - // code borrowed from http://snippets.dzone.com/posts/show/452
135 - var url_regexp = /(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/;
136 - if (url_regexp.test(field.value)) {
137 - return true;
138 - } else {
139 - info_span = document.getElementById(info_id);
140 - info_span.innerHTML = "$bad_url_error_str";
141 - return false;
142 - }
143 - } else if (type == 'email') {
144 - // code borrowed from http://javascript.internet.com/forms/email-validation---basic.html
145 - var email_regexp = /^\s*\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,6})+\s*$/;
146 - if (email_regexp.test(field.value)) {
147 - return true;
148 - } else {
149 - info_span = document.getElementById(info_id);
150 - info_span.innerHTML = "$bad_email_error_str";
151 - return false;
152 - }
153 - } else if (type == 'number') {
154 - if (field.value.match(/^\s*\-?[\d\.,]+\s*$/)) {
155 - return true;
156 - } else {
157 - info_span = document.getElementById(info_id);
158 - info_span.innerHTML = "$bad_number_error_str";
159 - return false;
160 - }
161 - } else if (type == 'date') {
162 - // validate only if day and year fields are both filled in
163 - day_field = document.getElementById(field_id + "_day");
164 - year_field = document.getElementById(field_id + "_year");
165 - if (day_field.value == '' || year_field.value == '') {
166 - return true;
167 - } else if (day_field.value.match(/^\d+$/) &&
168 - day_field.value <= 31) {
169 - // no year validation, since it can also include
170 - // 'BC' and possibly other non-number strings
171 - return true;
172 - } else {
173 - info_span = document.getElementById(info_id);
174 - info_span.innerHTML = "$bad_date_error_str";
175 - return false;
176 - }
177 - } else {
178 - return true;
179 - }
180 - }
181 -}
182 -
183 -// same as validate_multiple_mandatory_fields(), but for type validation
184 -function validate_type_of_multiple_fields(field_num, type) {
185 - var num_errors = 0;
186 - elems = document.getElementsByTagName("*");
187 - var field_pattern = new RegExp('input_(.*)_' + field_num);
188 - for (var i = 0; i < elems.length; i++) {
189 - id = elems[i].id;
190 - if (matches = field_pattern.exec(id)) {
191 - instance_num = matches[1];
192 - var input_name = "input_" + instance_num + "_" + field_num;
193 - var info_name = "info_" + instance_num + "_" + field_num;
194 - if (! validate_field_type(input_name, type, info_name)) {
195 - num_errors += 1;
196 - }
197 - }
198 - }
199 - return (num_errors == 0);
200 -}
201 -
202 -
203 -function validate_all() {
204 - var num_errors = 0;
205 -
206 -END;
207 - foreach ( $sfgJSValidationCalls as $function_call ) {
208 - $javascript_text .= " if (! $function_call) num_errors += 1;\n";
209 - }
210 - $javascript_text .= <<<END
211 - if (num_errors > 0) {
212 - // add error header, if it's not there already
213 - if (! document.getElementById("form_error_header")) {
214 - var errorMsg = document.createElement('div');
215 - errorMsg.innerHTML = "<div id=\"form_error_header\" class=\"warningMessage\" style=\"font-size: medium\">$form_errors_header</div>";
216 - document.getElementById("contentSub").appendChild(errorMsg);
217 - }
218 - scroll(0, 0);
219 - }
220 - return (num_errors == 0);
221 -}
222 -
223 -END;
224 - return $javascript_text;
225 - }
226 -
227 - static function instancesJavascript() {
228 - $remove_text = wfMsg( 'sf_formedit_remove' );
229 - $javascript_text = <<<END
230 -
231 -var num_elements = 0;
232 -
233 -function addInstance(starter_div_id, main_div_id, tab_index)
234 -{
235 - var starter_div = document.getElementById(starter_div_id);
236 - var main_div = document.getElementById(main_div_id);
237 - num_elements++;
238 -
239 - //Create the new instance
240 - var new_div = starter_div.cloneNode(true);
241 - var div_id = 'div_gen_' + num_elements;
242 - new_div.className = 'multipleTemplate';
243 - new_div.id = div_id;
244 - new_div.style.display = 'block';
245 -
246 - // make internal ID unique for the relevant divs and spans, and replace
247 - // the [num] index in the element names with an actual unique index
248 - var children = new_div.getElementsByTagName('*');
249 - // this array is needed to counteract an IE bug
250 - var orig_children = starter_div.getElementsByTagName('*');
251 - var fancybox_ids = new Array();
252 - var x;
253 - for (x = 0; x < children.length; x++) {
254 - if (children[x].name)
255 - children[x].name = children[x].name.replace(/\[num\]/g, '[' + num_elements + ']');
256 - if (children[x].id)
257 - children[x].id = children[x].id
258 - .replace(/input_/g, 'input_' + num_elements + '_')
259 - .replace(/info_/g, 'info_' + num_elements + '_')
260 - .replace(/div_/g, 'div_' + num_elements + '_');
261 - if (children[x].href)
262 - children[x].href = children[x].href
263 - .replace(/input_/g, 'input_' + num_elements + '_');
264 - if (children[x].id.match("^fancybox")) {
265 - fancybox_ids.push(children[x].id);
266 - }
267 -
268 - // for dropdowns, copy over selectedIndex from original div,
269 - // to get around a bug in IE
270 - if (children[x].type == 'select-one') {
271 - children[x].selectedIndex = orig_children[x].selectedIndex;
272 - }
273 - }
274 - if (children[x]) {
275 - //We clone the last object
276 - if (children[x].href) {
277 - children[x].href = children[x].href
278 - .replace(/input_/g, 'input_' + num_elements + '_')
279 - .replace(/info_/g, 'info_' + num_elements + '_')
280 - .replace(/div_/g, 'div_' + num_elements + '_');
281 - }
282 - }
283 - // Since we clone the first object and we have uploadable field
284 - // we must replace the input_ in order to let the printer return
285 - // the value into the right field
286 - //Create remove button
287 - var remove_button = document.createElement('input');
288 - remove_button.type = 'button';
289 - remove_button.value = "$remove_text";
290 - remove_button.tabIndex = tab_index;
291 - remove_button.onclick = removeInstanceEventHandler(div_id);
292 - new_div.appendChild(remove_button);
293 -
294 - //Add the new instance
295 - main_div.appendChild(new_div);
296 - attachAutocompleteToAllFields(new_div);
297 -
298 - // For each 'upload file' link in this latest instance,
299 - // add a call to fancybox()
300 - for (x = 0; x < fancybox_ids.length; x++) {
301 - jQuery("#" + fancybox_ids[x]).fancybox({
302 - 'width' : '75%',
303 - 'height' : '75%',
304 - 'autoScale' : false,
305 - 'transitionIn' : 'none',
306 - 'transitionOut' : 'none',
307 - 'type' : 'iframe',
308 - 'overlayColor' : '#222',
309 - 'overlayOpacity' : '0.8'
310 - });
311 - }
312 -}
313 -
314 -function removeInstanceEventHandler(this_div_id)
315 -{
316 - return function() {
317 - removeInstance(this_div_id);
318 - };
319 -}
320 -
321 -function removeInstance(div_id) {
322 - var olddiv = document.getElementById(div_id);
323 - var parent = olddiv.parentNode;
324 - parent.removeChild(olddiv);
325 -}
326 -
327 -END;
328 - return $javascript_text;
329 - }
330 -
331 - static function autocompletionJavascript() {
332 - global $wgScriptPath, $wgOut, $smwgScriptPath, $smwgJQueryIncluded;
333 - global $sfgAutocompleteOnAllChars;
334 -
335 - if ( !$smwgJQueryIncluded ) {
336 - $wgOut->addScriptFile( "$smwgScriptPath/libs/jquery-1.4.2.min.js" );
337 - $smwgJQueryIncluded = true;
338 - }
339 -
340 - // set a Javascript variable so that the matcher knows
341 - // whether to match on characters anywhere within each string,
342 - // or just (as is the default) the beginning of each word
343 - if ( $sfgAutocompleteOnAllChars ) {
344 - $autocompleteOnAllCharsStr = 'true';
345 - } else {
346 - $autocompleteOnAllCharsStr = 'false';
347 - }
348 -
349 - $javascript_text = <<<END
350 -var autocompleteOnAllChars = $autocompleteOnAllCharsStr;
351 -var autocompletemappings = new Array();
352 -var autocompletestrings = new Array();
353 -var autocompletedatatypes = new Array();
354 -
355 -//Activate autocomplete functionality for every field on the document
356 -function attachAutocompleteToAllDocumentFields()
357 -{
358 - var forms = document.getElementsByTagName("form");
359 - var x;
360 - for (x = 0; x < forms.length; x++) {
361 - if (forms[x].name == "createbox") {
362 - attachAutocompleteToAllFields(forms[x]);
363 - }
364 - }
365 -}
366 -
367 -//Activate autocomplete functionality for every field under the specified element
368 -function attachAutocompleteToAllFields(base)
369 -{
370 - var inputs = base.getElementsByTagName("input");
371 - var y;
372 - for (y = 0; y < inputs.length; y++) {
373 - attachAutocompleteToField(inputs[y].id);
374 - }
375 - // don't forget the textareas
376 - inputs = base.getElementsByTagName("textarea");
377 - for (y = 0; y < inputs.length; y++) {
378 - attachAutocompleteToField(inputs[y].id);
379 - }
380 -}
381 -
382 -//Activate autocomplete functionality for the specified field
383 -function attachAutocompleteToField(input_id)
384 -{
385 - //Check input id for the proper format, to ensure this is for SF
386 - if (input_id.substr(0,6) == 'input_')
387 - {
388 - //Extract the field ID number from the input field
389 - var field_num = parseInt(input_id.substring(input_id.lastIndexOf('_') + 1, input_id.length),10);
390 - //Add the autocomplete string, if a mapping exists.
391 - var field_string = autocompletemappings[field_num];
392 - if (field_string) {
393 - var div_id = input_id.replace(/input_/g, 'div_');
394 - var field_values = new Array();
395 - field_values = field_string.split(',');
396 - var delimiter = null;
397 - var data_source = field_values[0];
398 - if (field_values[1] == 'list') {
399 - delimiter = ",";
400 - if (field_values[2] != null) {
401 - delimiter = field_values[2];
402 - }
403 - }
404 - if (autocompletestrings[field_string] != null) {
405 - sf_autocomplete(input_id, div_id, autocompletestrings[field_string], null, null, delimiter, data_source);
406 - } else {
407 - sf_autocomplete(input_id, div_id, null, "{$wgScriptPath}/api.php", autocompletedatatypes[field_string], delimiter, data_source);
408 - }
409 - }
410 - }
411 -}
412 -
413 -jQuery.event.add(window, "load", attachAutocompleteToAllDocumentFields);
414 -
415 -END;
416 - return $javascript_text;
417 - }
418 -
41940 static function hiddenFieldHTML( $input_name, $cur_value ) {
42041 $input = self::buttonHTML( array(
42142 'type' => 'hidden',
@@ -456,21 +77,6 @@
45778 return $additional_template_text;
45879 }
45980
460 - /**
461 - * Helper function, for versions of MediaWiki that don't have
462 - * Xml::expandAttributes (i.e., before 1.13)
463 - */
464 - static function expandAttributes( $attribs ) {
465 - if ( method_exists( 'Xml', 'expandAttributes' ) ) {
466 - return Xml::expandAttributes( $attribs );
467 - } else {
468 - $out = '';
469 - foreach ( $attribs as $name => $val )
470 - $out .= " {$name}=\"" . Sanitizer::encodeAttribute( $val ) . '"';
471 - return $out;
472 - }
473 - }
474 -
47581 static function summaryInputHTML( $is_disabled, $label = null, $attr = array() ) {
47682 global $sfgTabIndex;
47783
@@ -478,7 +84,7 @@
47985 if ( $label == null )
48086 $label = wfMsg( 'summary' );
48187 $disabled_text = ( $is_disabled ) ? " disabled" : "";
482 - $attr = self::expandAttributes( $attr );
 88+ $attr = Xml::expandAttributes( $attr );
48389 $text = <<<END
48490 <span id='wpSummaryLabel'><label for='wpSummary'>$label</label></span>
48591 <input tabindex="$sfgTabIndex" type='text' value="" name='wpSummary' id='wpSummary' maxlength='200' size='60'$disabled_text$attr/>
@@ -496,7 +102,7 @@
497103 $label = wfMsgExt( 'minoredit', array( 'parseinline' ) );
498104 $accesskey = wfMsg( 'accesskey-minoredit' );
499105 $tooltip = wfMsg( 'tooltip-minoredit' );
500 - $attr = self::expandAttributes( $attr );
 106+ $attr = Xml::expandAttributes( $attr );
501107 $text = <<<END
502108 <input tabindex="$sfgTabIndex" type="checkbox" value="" name="wpMinoredit" accesskey="$accesskey" id="wpMinoredit"$disabled_text$attr/>
503109 <label for="wpMinoredit" title="$tooltip">$label</label>
@@ -527,7 +133,7 @@
528134 $label = wfMsgExt( 'watchthis', array( 'parseinline' ) );
529135 $accesskey = htmlspecialchars( wfMsg( 'accesskey-watch' ) );
530136 $tooltip = htmlspecialchars( wfMsg( 'tooltip-watch' ) );
531 - $attr = self::expandAttributes( $attr );
 137+ $attr = Xml::expandAttributes( $attr );
532138 $text = <<<END
533139 <input tabindex="$sfgTabIndex" type="checkbox" name="wpWatchthis" accesskey="$accesskey" id='wpWatchthis'$checked_text$disabled_text$attr/>
534140 <label for="wpWatchthis" title="$tooltip">$label</label>

Status & tagging log