Yaron Koren has submitted this change and it was merged.

Change subject: Fix jshint errors, Also run npm and composer tests
......................................................................


Fix jshint errors, Also run npm and composer tests

Add support for running npm and composer tests.

Running jshint, jsonlint tests through npm.

Running phplint through composer test.

This patches includes big and minor changes such as formatting, fixing the 
configs that were undefined.

These changes are done in order for the tests to pass.

Bumped mw version required to 1.27.

Change-Id: I5e01223da5a882591e8028a8bb608a07ac543dfd
---
M .gitignore
M .jshintignore
M .jshintrc
A Gruntfile.js
M SemanticForms.php
M composer.json
M extension.json
M includes/SF_Utils.php
M libs/SF_CreateClass.js
M libs/SF_CreateForm.js
M libs/SF_CreateProperty.js
M libs/SF_CreateTemplate.js
M libs/SF_PageSchemas.js
M libs/SF_dynatree.js
M libs/SF_imagePreview.js
M libs/SF_popupform.js
M libs/SF_wikieditor.js
M libs/SemanticForms.js
M libs/ext.sf.js
M libs/ext.sf.select2.base.js
M libs/ext.sf.select2.combobox.js
M libs/ext.sf.select2.tokens.js
A package.json
23 files changed, 1,017 insertions(+), 928 deletions(-)

Approvals:
  Yaron Koren: Checked; Looks good to me, approved
  jenkins-bot: Verified



diff --git a/.gitignore b/.gitignore
index a901587..f5a6251 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,3 @@
-.svn
 *~
 *.kate-swp
 .*.swp
@@ -7,5 +6,6 @@
 composer.phar
 
 .idea/
+node_modules/
 vendor/
-extensions/
\ No newline at end of file
+extensions/
diff --git a/.jshintignore b/.jshintignore
index a93e887..10f6214 100644
--- a/.jshintignore
+++ b/.jshintignore
@@ -1 +1,7 @@
-libs
+libs/jquery.browser.js
+libs/jquery.dynatree.js
+libs/jquery.fancybox.js
+libs/select2.js
+libs/SF_maps.js
+node_modules/
+vendor/
diff --git a/.jshintrc b/.jshintrc
index 80b00ba..795e82d 100644
--- a/.jshintrc
+++ b/.jshintrc
@@ -1,14 +1,4 @@
 {
-       "predef": [
-               "mediaWiki",
-               "jQuery",
-               "semanticforms",
-               "mw",
-               "$",
-               "sf",
-               "ext"
-       ],
-
        "bitwise": true,
        "camelcase": false,
        "curly": true,
@@ -32,10 +22,20 @@
        "multistr": true,
 
        "browser": true,
+       "jquery": true,
 
        "nomen": false,
        "onevar": false,
 
        "scripturl": false,
-       "supernew": false
+       "supernew": false,
+
+       "globals": {
+               "mediaWiki": false,
+               "semanticforms": false,
+               "sf": false,
+               "ext": false,
+               "google": true,
+               "OpenLayers": true
+       }
 }
diff --git a/Gruntfile.js b/Gruntfile.js
new file mode 100644
index 0000000..c679ec7
--- /dev/null
+++ b/Gruntfile.js
@@ -0,0 +1,36 @@
+/*jshint node:true */
+module.exports = function ( grunt ) {
+       grunt.loadNpmTasks( 'grunt-contrib-jshint' );
+       grunt.loadNpmTasks( 'grunt-jsonlint' );
+       // grunt.loadNpmTasks( 'grunt-banana-checker' );
+
+       grunt.initConfig( {
+               jshint: {
+                       options: {
+                               jshintrc: true
+                       },
+                       all: [
+                               '**/*.js',
+                               '!node_modules/**',
+                               '!libs/OpenLayers/**',
+                               '!libs/jquery.browser.js',
+                               '!libs/jquery.dynatree.js',
+                               '!libs/jquery.fancybox.js',
+                               '!libs/select2.js',
+                               '!libs/SF_maps.js'
+                       ]
+               },
+               // banana: {
+                       // all: 'i18n/'
+               // },
+               jsonlint: {
+                       all: [
+                               '**/*.json',
+                               '!node_modules/**'
+                       ]
+               }
+       } );
+
+       grunt.registerTask( 'test', [ 'jshint', 'jsonlint' /* 'banana' */ ] );
+       grunt.registerTask( 'default', 'test' );
+};
diff --git a/SemanticForms.php b/SemanticForms.php
index 06521e3..9f2ddc5 100644
--- a/SemanticForms.php
+++ b/SemanticForms.php
@@ -41,9 +41,9 @@
 // In some versions of MW 1.25, there's a bug in which global variables
 // set in LocalSettings.php do not override the settings in
 // extension.json. For simplicity's sake, don't load extensions unless we're
-// at version 1.26 or higher.
+// at version 1.27 or higher.
 //if ( function_exists( 'wfLoadExtension' ) ) {
-if ( version_compare( $GLOBALS['wgVersion'], '1.26c', '>' ) ) {
+if ( version_compare( $GLOBALS['wgVersion'], '1.27c', '>' ) ) {
        if ( function_exists( 'wfLoadExtension' ) ) {
                wfLoadExtension( 'SemanticForms' );
                // Keep i18n globals so mergeMessageFileList.php doesn't break
@@ -363,9 +363,6 @@
                        'sf-select2-input-too-short',
                        'sf-select2-selection-too-big',
                ),
-       ),
-       'ext.semanticforms.maps' => $sfgResourceTemplate + array(
-               'scripts' => 'libs/SF_maps.js',
        ),
        'ext.semanticforms' => $sfgResourceTemplate + array(
                'scripts' => array(
diff --git a/composer.json b/composer.json
index d565619..758e5a9 100644
--- a/composer.json
+++ b/composer.json
@@ -30,5 +30,13 @@
                "branch-alias": {
                        "dev-master": "2.8.x-dev"
                }
+       },
+       "require-dev": {
+               "jakub-onderka/php-parallel-lint": "0.9.2"
+       },
+       "scripts": {
+               "test": [
+                       "parallel-lint . --exclude vendor"
+               ]
        }
 }
diff --git a/extension.json b/extension.json
index 8663f3e..aac7755 100644
--- a/extension.json
+++ b/extension.json
@@ -14,8 +14,8 @@
        "ExtensionFunctions": [
                "SFUtils::initialize"
        ],
-       "requires": {
-               "MediaWiki": ">= 1.26.0"
+       "require": {
+               "MediaWiki": ">= 1.27.0"
        },
        "GroupPermissions": {
                "*": {
@@ -262,11 +262,6 @@
                                "sf-select2-searching",
                                "sf-select2-input-too-short",
                                "sf-select2-selection-too-big"
-                       ]
-               },
-               "ext.semanticforms.maps": {
-                       "scripts": [
-                               "libs/SF_maps.js"
                        ]
                },
                "ext.semanticforms": {
diff --git a/includes/SF_Utils.php b/includes/SF_Utils.php
index 5462858..3589755 100644
--- a/includes/SF_Utils.php
+++ b/includes/SF_Utils.php
@@ -1345,18 +1345,26 @@
                if ( class_exists( 'WikiEditorHooks' ) ) {
                        $resourceLoader->register( array(
                                'ext.semanticforms.wikieditor' => array(
-                                       'localBasePath' => __DIR__ . '/..',
+                                       'localBasePath' => __DIR__,
                                        'remoteExtPath' => 'SemanticForms',
-                                       'scripts' => 'libs/SF_wikieditor.js',
-                                       'styles' => 'skins/SF_wikieditor.css',
+                                       'scripts' => 
'/../libs/SF_wikieditor.js',
+                                       'styles' => 
'/../skins/SF_wikieditor.css',
                                        'dependencies' => array(
                                                'ext.semanticforms.main',
-                                               'jquery.wikiEditor',
+                                               'jquery.wikiEditor'
                                        )
                                ),
                        ) );
                }
 
+               $resourceLoader->register( array(
+                       'ext.semanticforms.maps' => array(
+                               'localBasePath' => __DIR__,
+                               'remoteExtPath' => 'SemanticForms',
+                               'scripts' => '/../libs/SF_maps.js',
+                       ),
+               ) );
+
                return true;
        }
 
diff --git a/libs/SF_CreateClass.js b/libs/SF_CreateClass.js
index 50d6117..2402f13 100644
--- a/libs/SF_CreateClass.js
+++ b/libs/SF_CreateClass.js
@@ -1,8 +1,8 @@
 var rowNum = mediaWiki.config.get( '$numStartingRows');
 function createClassAddRow() {
        rowNum++;
-       newRow = jQuery('#starterRow').clone().css('display', '');
-       newHTML = newRow.html().replace(/starter/g, rowNum);
+       var newRow = jQuery('#starterRow').clone().css('display', '');
+       var newHTML = newRow.html().replace(/starter/g, rowNum);
        newRow.html(newHTML);
        jQuery('#mainTable').append(newRow);
 }
diff --git a/libs/SF_CreateForm.js b/libs/SF_CreateForm.js
index d0f794f..5486c6e 100644
--- a/libs/SF_CreateForm.js
+++ b/libs/SF_CreateForm.js
@@ -1,5 +1,5 @@
 jQuery.fn.displayInputParams = function () {
-       inputParamsDiv = this.closest( '.formField' ).find( '.otherInputParams' 
);
+       var inputParamsDiv = this.closest( '.formField' ).find( 
'.otherInputParams' );
        jQuery.ajax( {
                url: mediaWiki.config.get( 'wgCreateFormUrl' ),
                context: document.body,
@@ -14,7 +14,7 @@
                jQuery( this ).displayInputParams();
        } );
        jQuery( '#addsection' ).click( function( event ) {
-               if( jQuery( '#sectionname' ).val() == '' ) {
+               if( jQuery( '#sectionname' ).val() === '' ) {
                        event.preventDefault();
                        jQuery( '#section_error' ).remove();
                        jQuery( '<div/>' ).append( '<span class="error" 
id="section_error">' + mediaWiki.msg( 'sf_blank_error' ) + '</span>' 
).appendTo( '#sectionerror' );
@@ -23,5 +23,5 @@
 } );
 
 jQuery( "input,select" ).keypress( function ( event ) {
-       return event.keyCode != 13;
+       return event.keyCode !== 13;
 } );
diff --git a/libs/SF_CreateProperty.js b/libs/SF_CreateProperty.js
index 97eee53..b2bf507 100644
--- a/libs/SF_CreateProperty.js
+++ b/libs/SF_CreateProperty.js
@@ -1,6 +1,6 @@
 function toggleDefaultForm(property_type) {
        var default_form_div = document.getElementById("default_form_div");
-       if ( property_type == mediaWiki.config.get( 'wgPageTypeLabel' ) ) {
+       if ( property_type === mediaWiki.config.get( 'wgPageTypeLabel' ) ) {
                default_form_div.style.display = "";
        } else {
                default_form_div.style.display = "none";
@@ -11,10 +11,10 @@
        var allowed_values_div = document.getElementById("allowed_values");
        // Page, String (or Text, for SMW 1.9+), Number, Email - is that a
        // reasonable set of types for which enumerations should be allowed?
-       if ( property_type == mediaWiki.config.get( 'wgPageTypeLabel' ) ||
-               property_type == mediaWiki.config.get( 'wgStringTypeLabel' ) ||
-               property_type == mediaWiki.config.get( 'wgNumberTypeLabel' ) ||
-               property_type == mediaWiki.config.get( 'wgEmailTypeLabel' ) ) {
+       if ( property_type === mediaWiki.config.get( 'wgPageTypeLabel' ) ||
+               property_type === mediaWiki.config.get( 'wgStringTypeLabel' ) ||
+               property_type === mediaWiki.config.get( 'wgNumberTypeLabel' ) ||
+               property_type === mediaWiki.config.get( 'wgEmailTypeLabel' ) ) {
                allowed_values_div.style.display = "";
        } else {
                allowed_values_div.style.display = "none";
diff --git a/libs/SF_CreateTemplate.js b/libs/SF_CreateTemplate.js
index 737ba7b..c1de746 100644
--- a/libs/SF_CreateTemplate.js
+++ b/libs/SF_CreateTemplate.js
@@ -1,8 +1,8 @@
 var fieldNum = 1;
 function createTemplateAddField() {
        fieldNum++;
-       newField = jQuery( '#starterField' ).clone().css( 'display', '' 
).removeAttr( 'id' );
-       newHTML = newField.html().replace(/starter/g, fieldNum);
+       var newField = jQuery( '#starterField' ).clone().css( 'display', '' 
).removeAttr( 'id' );
+       var newHTML = newField.html().replace(/starter/g, fieldNum);
        newField.html( newHTML );
        newField.find( ".deleteField" ).click( function () {
                // Remove the encompassing div for this instance.
@@ -20,7 +20,7 @@
 }
 
 function validateCreateTemplateForm() {
-       templateName = jQuery( '#template_name' ).val();
+       var templateName = jQuery( '#template_name' ).val();
        if ( templateName === '' ) {
                scroll( 0, 0 );
                jQuery( '#template_name_p' ).append( '<span class="error">' + 
mediaWiki.msg( 'sf_blank_error' ) + '</span>' );
diff --git a/libs/SF_PageSchemas.js b/libs/SF_PageSchemas.js
index 6030e41..b5e3d6b 100644
--- a/libs/SF_PageSchemas.js
+++ b/libs/SF_PageSchemas.js
@@ -7,7 +7,7 @@
                jQuery('#sf-edit-title').css('display', 'none');
        }
        return this;
-}
+};
 
 jQuery( document ).ready( function () {
        jQuery('#sf-two-step-process')
diff --git a/libs/SF_dynatree.js b/libs/SF_dynatree.js
index 00786a0..dcf9f8b 100644
--- a/libs/SF_dynatree.js
+++ b/libs/SF_dynatree.js
@@ -40,10 +40,10 @@
                        selectMode: selectMode,
                        onClick: function (dtNode, event) {
                                var targetType = 
dtNode.getEventTargetType(event);
-                               if ( targetType == "expander" ) {
+                               if ( targetType === "expander" ) {
                                        dtNode.toggleExpand();
-                               } else if ( targetType == "checkbox" ||
-                                          targetType == "title" ) {
+                               } else if ( targetType === "checkbox" ||
+                                          targetType === "title" ) {
                                        dtNode.toggleSelect();
                                }
 
@@ -77,4 +77,4 @@
 
        };
 
-} )( jQuery, mediaWiki, sf );
+}( jQuery, mediaWiki, sf ) );
diff --git a/libs/SF_imagePreview.js b/libs/SF_imagePreview.js
index c1f3aff..aaa7ef7 100644
--- a/libs/SF_imagePreview.js
+++ b/libs/SF_imagePreview.js
@@ -5,7 +5,7 @@
  * @author Jeroen De Dauw <jeroendedauw at gmail dot com>
  */
 
-(function( $ ) {
+( function ( $, mw ) {
        var _this = this;
 
        this.getPreviewImage = function( args, callback ) {
@@ -63,4 +63,4 @@
                        $input.change( showPreview );
                } );
        } );
-})( jQuery );
+}( jQuery, mediaWiki ) );
diff --git a/libs/SF_popupform.js b/libs/SF_popupform.js
index 02b0e58..e720fbe 100644
--- a/libs/SF_popupform.js
+++ b/libs/SF_popupform.js
@@ -27,14 +27,14 @@
                return ext.popupform.handlePopupFormInput( this.getAttribute( 
'action' ), this );
        });
 
-});
+} );
 
 // create ext if it does not exist yet
 if ( typeof( window.ext ) === "undefined" ) {
        window.ext = {};
 }
 
-window.ext.popupform = new function() {
+window.ext.popupform = ( function () {
        var wrapper;
        var background;
        var container;
@@ -53,84 +53,296 @@
 
        var padding = 20;
 
-       function handlePopupFormInput( ptarget, elem ) {
-               showForm();
-
-               iframe.one( 'load', function(){
-                       // attach event handler to iframe
-                       iframe.bind( 'load', handleLoadFrame );
-                       return false;
-               });
-
-               elem.target = 'popupform-iframe' + instance;
-               return true;
-       }
-
-       function handlePopupFormLink( ptarget, elem ) {
-               showForm();
-
-               // store initial readystate
-               var readystate = iframe.contents()[0].readyState;
-
-               // set up timer for waiting on the document in the iframe to be 
dom-ready
-               // this sucks, but there is no other way to catch that event
-               // onload is already too late
-               timer = setInterval(function(){
-                       // if the readystate changed
-                       if ( readystate !== iframe.contents()[0].readyState ) {
-                               // store new readystate
-                               readystate = iframe.contents()[0].readyState;
-
-                               // if dom is built but document not yet 
displayed
-                               if ( readystate === 'interactive' || readystate 
=== 'complete' ) {
-                                       needsRender = false; // flag that 
rendering is already done
-                                       handleLoadFrame();
-                               }
+       function fadeOut(elem, callback ) {
+               // no fading for broken browsers
+               if ( brokenBrowser ){
+                       elem.hide();
+                       if ( callback ) {
+                               callback();
                        }
-               }, 100 );
-
-               // fallback in case we did not catch the dom-ready state
-               iframe.on('load', function( event ){
-                       if ( needsRender ) { // rendering not already done?
-                               handleLoadFrame( event );
-                       }
-                       needsRender = true;
-               });
-
-               if ( elem.tagName == 'FORM' ) {
-                       elem.target = 'popupform-iframe' + instance;
-                       return true;
                } else {
-                       var delim = ptarget.indexOf( '?' );
-                       var form = document.createElement("form");
-
-                       form.target = 'popupform-iframe' + instance;
-
-                       // Do we have parameters?
-                       if ( delim > 0 ) {
-                               form.action = ptarget.substr( 0, delim );
-                               var params = String( ptarget.substr( delim + 1 
) ).split("&");
-                               for ( var i = 0; i < params.length; ++i ) {
-
-                                       var input = 
document.createElement("input");
-                                       var param = String( params[i] 
).split('=');
-                                       input.type = 'hidden';
-                                       input.name = decodeURIComponent( 
param[0] );
-                                       input.value = decodeURIComponent( 
param[1] );
-                                       form.appendChild( input );
-                               }
+                       // what an ugly hack
+                       if ( elem === waitIndicator ) {
+                               elem.fadeOut( 200, callback );
                        } else {
-                               form.action = ptarget;
+                               elem.fadeOut( callback );
                        }
-
-                       
document.getElementsByTagName('body')[0].appendChild(form);
-                       form.submit();
-                       
document.getElementsByTagName('body')[0].removeChild(form);
-
-                       return false;
                }
        }
 
+       function adjustFrameSize( animate ) {
+               // set some inputs
+               var oldFrameW = container.width();
+               var oldFrameH = container.height();
+               var oldContW = content.width();
+               var oldContH = content.height();
+
+               var availW = Math.floor( jQuery(window).width() * 0.8 );
+               var availH = Math.floor( jQuery(window).height() * 0.8 );
+
+               var emergencyW = Math.floor( jQuery(window).width() * 0.85 );
+               var emergencyH = Math.floor( jQuery(window).height() * 0.85 );
+
+               // FIXME: these might not be the true values
+               var scrollW = 25;
+               var scrollH = 25;
+
+
+               // find the dimensions of the document
+
+               var body = content.closest('body');
+               var html = body.parent();
+
+               var scrollTgt = html;
+
+               if ( jQuery.browser.webkit || jQuery.browser.safari ) {
+                       scrollTgt = body;
+               }
+
+               var scrollTop = scrollTgt.scrollTop();
+               var scrollLeft = scrollTgt.scrollLeft();
+
+               content
+               .css('position', 'absolute')
+               .width( 'auto' )
+               .height( 'auto' );
+
+               // set max dimensions for layout of content
+               iframe
+               .width( emergencyW )
+               .height( emergencyH );
+
+               // get dimension values
+               var docW = content.width();
+               var docH = content.height();
+
+               // set old dimensions for layout of content
+               iframe
+               .width( '100%' )
+               .height( '100%' );
+
+               content
+               .css('position', 'relative')
+               .width( oldContW )
+               .height( oldContH );
+
+               if ( jQuery.browser.msie ) {
+                       docW += 20;
+                       docH += 20;
+               }
+
+               var docpW = docW + 2 * padding;
+               var docpH = docH + 2 * padding;
+
+               // Flags
+
+               var needsHScroll = docpW > emergencyW || ( docpW > emergencyW - 
scrollW && docpH > emergencyH );
+               var needsVScroll = docpH > emergencyH || ( docpH > emergencyH - 
scrollH && docpW > emergencyW );
+
+               var needsWStretch =
+               ( docpW > availW && docpW <= emergencyW ) && ( docpH <= 
emergencyH ) ||
+               ( docpW > availW - scrollW && docpW <= emergencyW - scrollW ) 
&& ( docpH > emergencyH );
+
+               var needsHStretch =
+               ( docpH > availH && docpH <= emergencyH ) && ( docpW <= 
emergencyW ) ||
+               ( docpH > availH - scrollH && docpH <= emergencyH - scrollH ) 
&& ( docpW > emergencyW );
+
+               // Outputs
+
+               var frameW;
+               var frameH;
+
+               var contW;
+               var contH;
+
+               if ( needsWStretch ) {
+                       contW = docW;
+                       frameW = docpW;
+               } else if ( docpW > availW ) { // form does not even fit with 
stretching
+                       contW = docW;
+                       frameW = availW;
+               } else {
+                       //contW = Math.max( Math.min( 1.5 * docW, availW ), 
availW / 2 );
+                       contW = docW;
+                       frameW = docpW;
+               }
+
+               if ( needsVScroll ){
+                       frameW += scrollW;
+               } else {
+                       scrollTop = 0;
+               }
+
+               if ( needsHStretch ) {
+                       contH = docH;
+                       frameH = docpH;
+               } else if ( docpH > availH ) { // form does not even fit with 
stretching
+                       contH = docH;
+                       frameH = availH;
+               } else {
+                       //contH = Math.min( 1.1 * docH, availH);
+                       contH = docH;
+                       frameH = docpH;
+               }
+
+               if ( needsHScroll ){
+                       frameH += scrollH;
+               } else {
+                       scrollLeft = 0;
+               }
+
+               if ( frameW !== oldFrameW || frameH !== oldFrameH ) {
+
+                       if ( jQuery.browser.safari ) {
+                               html[0].style.overflow="hidden";
+                       } else {
+                               iframe[0].style.overflow="hidden";
+                       }
+
+                       if ( animate ) {
+                               content
+                               .width ( 'auto' )
+                               .height ( 'auto' );
+
+                               container.animate({
+                                       width: frameW,
+                                       height: frameH,
+                                       top: Math.floor(( - frameH ) / 2),
+                                       left: Math.floor(( - frameW ) / 2)
+                               }, {
+                                       duration: 500,
+                                       complete: function() {
+
+                                               if ( jQuery.browser.safari ) {
+                                                       
html[0].style.overflow="visible";
+                                               } else if ( jQuery.browser.msie 
) {
+                                                       
iframe[0].style.overflow="auto";
+                                               } else {
+                                                       
iframe[0].style.overflow="visible";
+                                               }
+
+                                               if ( jQuery.browser.mozilla ) {
+                                                       content
+                                                       .width ( contW )
+                                                       .height ( contH );
+                                               } else {
+                                                       content
+                                                       .width ( 'auto' )
+                                                       .height ( 'auto' );
+                                               }
+                                       }
+                               });
+
+                       } else {
+                               container
+                               .width( frameW )
+                               .height ( frameH );
+
+                               container[0].style.top = (Math.floor(( - frameH 
) / 2)) + "px";
+                               container[0].style.left = (Math.floor(( - 
frameW ) / 2)) + "px";
+
+
+                               setTimeout(function(){
+
+                                               if ( jQuery.browser.safari ) {
+                                                       
html[0].style.overflow="visible";
+                                               } else if ( jQuery.browser.msie 
) {
+                                                       
iframe[0].style.overflow="auto";
+                                               } else {
+                                                       
iframe[0].style.overflow="visible";
+                                               }
+
+                               }, 100);
+
+                               if ( jQuery.browser.mozilla ) {
+                                       content
+                                       .width ( contW )
+                                       .height ( contH );
+                               } else {
+                                       content
+                                       .width ( 'auto' )
+                                       .height ( 'auto' );
+                               }
+
+                       }
+               } else {
+                       content
+                       .width ( 'auto' )
+                       .height ( 'auto' );
+
+                       if ( jQuery.browser.safari ) { // Google chrome needs a 
kick
+
+                               // turn scrollbars off and on again to really 
only show them when needed
+                                       html[0].style.overflow="hidden";
+
+                                       setTimeout(function(){
+                                               
html[0].style.overflow="visible";
+                               }, 1);
+                       }
+               }
+
+               scrollTgt
+               .css('overflow', 'auto')
+               .scrollTop(Math.min(scrollTop, docpH - frameH))
+               .scrollLeft(scrollLeft);
+
+               if ( jQuery.browser.mozilla ) {
+                       body
+                       .css('overflow', 'auto');
+               }
+
+               return true;
+       }
+
+       function handleCloseFrame( event ){
+               jQuery(window).unbind( "resize", adjustFrameSize );
+               clearTimeout(timer);
+
+               fadeOut( container, function(){
+                       background.fadeOut( function(){
+                               wrapper.remove();
+                       });
+               });
+               return false;
+       }
+
+       function fadeIn(elem, callback ) {
+               // no fading for broken browsers
+               if ( brokenBrowser ){
+
+                       elem.show();
+                       if ( callback ) {
+                               callback();
+                       }
+               } else {
+                       // what an ugly hack
+                       if ( elem === waitIndicator ) {
+                               elem.fadeIn( 200, callback );
+                       } else {
+                               elem.fadeIn( callback );
+                       }
+               }
+       }
+
+       function fadeTo(elem, time, target, callback) {
+               // no fading for broken browsers
+               if ( brokenBrowser ){
+
+                       if (target > 0) {
+                               elem[0].style.visibility = "visible";
+                       } else {
+                               elem[0].style.visibility = "hidden";
+                       }
+
+                       if ( callback ) {
+                               callback();
+                       }
+
+               } else {
+                       elem.fadeTo(time, target, callback);
+               }
+       }
+       
        function showForm() {
                instance++;
 
@@ -202,6 +414,107 @@
 
                // attach event handler to close button
                closeBtn.click( handleCloseFrame );
+       }
+
+       function handleSubmitData( event, returnedData, textStatus, 
XMLHttpRequest ){
+               fadeOut( container, function() {
+                       fadeIn( waitIndicator );
+               });
+
+               var form = jQuery( event.target );
+               var formdata = form.serialize() + "&wpSave=" + 
escape(form.find("#wpSave").attr("value"));
+               
+               function handleInnerSubmit() {
+                       // find form in fake edit page
+                       var innerform = jQuery("<div>" + returnedData + 
"</div>").find("form");
+
+                       // check if we got an error page
+                       if ( innerform.length === 0 ) {
+
+                               form.unbind( event );
+
+                               var iframe = container.find("iframe");
+                               var doc = iframe[0].contentWindow || 
iframe[0].contentDocument;
+                               if (doc.document) {
+                                       doc = doc.document;
+                               }
+
+                               doc.open();
+                               doc.write(returnedData);
+                               doc.close();
+
+                               return false;
+                       }
+
+                       // Send the form data off, we do not care for the 
returned data
+                       var innerformdata = innerform.serialize();
+                       jQuery.post( innerform.attr("action"), innerformdata );
+
+                       // build new url for outer page (we have to ask for a 
purge)
+
+                       var url = location.href;
+
+                       // does a querystring exist?
+                       var start = url.indexOf("action=");
+
+                       if ( start >= 0 ) {
+
+                               var stop = url.indexOf("&", start);
+
+                               if ( stop >= 0 ) {
+                                       url = url.substr( 0, start - 1 ) + 
url.substr(stop + 1);
+                               } else {
+                                       url = url.substr( 0, start - 1 );
+                               }
+
+                       }
+
+                       form = jQuery('<form action="' + url + '" 
method="POST"><input type="hidden" name="action" value="purge"></form>')
+                       .appendTo('body');
+
+                       form
+                       .submit();
+
+                       fadeOut( container, function(){
+                               fadeIn( waitIndicator );
+                       });
+
+                       return false;
+               }
+
+               // Send form data off. SF will send back a fake edit page
+               //
+               // Normally we should check this.action first and only if it is 
empty
+               // revert to this.ownerDocument.URL. Tough luck, IE does not 
return an
+               // empty action but fills in some bogus
+               jQuery.post( event.target.ownerDocument.URL , formdata, 
handleInnerSubmit);
+
+               return false;
+       }
+
+       function closeFrameAndFollowLink( link ){
+               clearTimeout(timer);
+
+               fadeOut( container, function(){
+                       fadeIn ( waitIndicator );
+                       window.location.href = link;
+               });
+       }
+
+       // Saw it on 
http://robertnyman.com/2006/04/24/get-the-rendered-style-of-an-element
+       // and liked it
+       function getStyle(oElm, strCssRule){
+               var strValue = "";
+               if(document.defaultView && 
document.defaultView.getComputedStyle){
+                       strValue = document.defaultView.getComputedStyle(oElm, 
"").getPropertyValue(strCssRule);
+               }
+               else if(oElm.currentStyle){
+                       strCssRule = strCssRule.replace(/\-(\w)/g, function 
(strMatch, p1){
+                               return p1.toUpperCase();
+                       });
+                       strValue = oElm.currentStyle[strCssRule];
+               }
+               return strValue;
        }
 
        function handleLoadFrame() {
@@ -284,7 +597,7 @@
                                var elem = jQuery(this);
 
                                // TODO: Does this really help?
-                               if ( getStyle(this, "display") != "none" && ! (
+                               if ( getStyle(this, "display") !== "none" && ! (
                                                ( this.offsetLeft + 
elem.outerWidth(true) < 0 ) ||              // left of document
                                                ( this.offsetTop + 
elem.outerHeight(true) < 0 )  || // above document
                                                ( this.offsetLeft > 100000 ) || 
        // right of document
@@ -423,402 +736,89 @@
 
                // finally show the frame, but only if it is not already visible
                if ( ! containerAlreadyVisible ) {
-                               fadeOut ( waitIndicator, function(){
+                               fadeOut ( waitIndicator, function () {
                                fadeTo( container, 400, 1 );
-                       });
+                       } );
                }
 
                return false;
        }
 
-       function handleSubmitData( event ){
-               fadeOut( container, function() {
-                       fadeIn( waitIndicator );
+       function handlePopupFormInput( ptarget, elem ) {
+               showForm();
+
+               iframe.one( 'load', function(){
+                       // attach event handler to iframe
+                       iframe.bind( 'load', handleLoadFrame );
+                       return false;
                });
 
-               var form = jQuery( event.target );
-               var formdata = form.serialize() + "&wpSave=" + 
escape(form.find("#wpSave").attr("value"));
-
-               // Send form data off. SF will send back a fake edit page
-               //
-               // Normally we should check this.action first and only if it is 
empty
-               // revert to this.ownerDocument.URL. Tough luck, IE does not 
return an
-               // empty action but fills in some bogus
-               jQuery.post( event.target.ownerDocument.URL , formdata, 
handleInnerSubmit);
-
-               return false;
-
-               function handleInnerSubmit ( returnedData, textStatus, 
XMLHttpRequest ) {
-                       // find form in fake edit page
-                       var innerform = jQuery("<div>" + returnedData + 
"</div>").find("form");
-
-                       // check if we got an error page
-                       if ( innerform.length === 0 ) {
-
-                               form.unbind( event );
-
-                               var iframe = container.find("iframe");
-                               var doc = iframe[0].contentWindow || 
iframe[0].contentDocument;
-                               if (doc.document) {
-                                       doc = doc.document;
-                               }
-
-                               doc.open();
-                               doc.write(returnedData);
-                               doc.close();
-
-                               return false;
-                       }
-
-                       // Send the form data off, we do not care for the 
returned data
-                       var innerformdata = innerform.serialize();
-                       jQuery.post( innerform.attr("action"), innerformdata );
-
-                       // build new url for outer page (we have to ask for a 
purge)
-
-                       var url = location.href;
-
-                       // does a querystring exist?
-                       var start = url.indexOf("action=");
-
-                       if ( start >= 0 ) {
-
-                               var stop = url.indexOf("&", start);
-
-                               if ( stop >= 0 ) {
-                                       url = url.substr( 0, start - 1 ) + 
url.substr(stop + 1);
-                               } else {
-                                       url = url.substr( 0, start - 1 );
-                               }
-
-                       }
-
-                       form = jQuery('<form action="' + url + '" 
method="POST"><input type="hidden" name="action" value="purge"></form>')
-                       .appendTo('body');
-
-                       form
-                       .submit();
-
-                       fadeOut( container, function(){
-                               fadeIn( waitIndicator );
-                       });
-
-                       return false;
-               }
-       }
-
-       function adjustFrameSize( animate ) {
-               // set some inputs
-               var oldFrameW = container.width();
-               var oldFrameH = container.height();
-               var oldContW = content.width();
-               var oldContH = content.height();
-
-               var availW = Math.floor( jQuery(window).width() * 0.8 );
-               var availH = Math.floor( jQuery(window).height() * 0.8 );
-
-               var emergencyW = Math.floor( jQuery(window).width() * 0.85 );
-               var emergencyH = Math.floor( jQuery(window).height() * 0.85 );
-
-               // FIXME: these might not be the true values
-               var scrollW = 25;
-               var scrollH = 25;
-
-
-               // find the dimensions of the document
-
-               var body = content.closest('body');
-               var html = body.parent();
-
-               var scrollTgt = html;
-
-               if ( jQuery.browser.webkit || jQuery.browser.safari ) {
-                       scrollTgt = body;
-               }
-
-               var scrollTop = scrollTgt.scrollTop();
-               var scrollLeft = scrollTgt.scrollLeft();
-
-               content
-               .css('position', 'absolute')
-               .width( 'auto' )
-               .height( 'auto' );
-
-               // set max dimensions for layout of content
-               iframe
-               .width( emergencyW )
-               .height( emergencyH );
-
-               // get dimension values
-               var docW = content.width();
-               var docH = content.height();
-
-               // set old dimensions for layout of content
-               iframe
-               .width( '100%' )
-               .height( '100%' );
-
-               content
-               .css('position', 'relative')
-               .width( oldContW )
-               .height( oldContH );
-
-               if ( jQuery.browser.msie ) {
-                       docW += 20;
-                       docH += 20;
-               }
-
-               var docpW = docW + 2 * padding;
-               var docpH = docH + 2 * padding;
-
-               // Flags
-
-               var needsHScroll = docpW > emergencyW || ( docpW > emergencyW - 
scrollW && docpH > emergencyH );
-               var needsVScroll = docpH > emergencyH || ( docpH > emergencyH - 
scrollH && docpW > emergencyW );
-
-               var needsWStretch =
-               ( docpW > availW && docpW <= emergencyW ) && ( docpH <= 
emergencyH ) ||
-               ( docpW > availW - scrollW && docpW <= emergencyW - scrollW ) 
&& ( docpH > emergencyH );
-
-               var needsHStretch =
-               ( docpH > availH && docpH <= emergencyH ) && ( docpW <= 
emergencyW ) ||
-               ( docpH > availH - scrollH && docpH <= emergencyH - scrollH ) 
&& ( docpW > emergencyW );
-
-               // Outputs
-
-               var frameW;
-               var frameH;
-
-               var contW;
-               var contH;
-
-               if ( needsWStretch ) {
-                       contW = docW;
-                       frameW = docpW;
-               } else if ( docpW > availW ) { // form does not even fit with 
stretching
-                       contW = docW;
-                       frameW = availW;
-               } else {
-                       //contW = Math.max( Math.min( 1.5 * docW, availW ), 
availW / 2 );
-                       contW = docW;
-                       frameW = docpW;
-               }
-
-               if ( needsVScroll ){
-                       frameW += scrollW;
-               } else {
-                       scrollTop = 0;
-               }
-
-               if ( needsHStretch ) {
-                       contH = docH;
-                       frameH = docpH;
-               } else if ( docpH > availH ) { // form does not even fit with 
stretching
-                       contH = docH;
-                       frameH = availH;
-               } else {
-                       //contH = Math.min( 1.1 * docH, availH);
-                       contH = docH;
-                       frameH = docpH;
-               }
-
-               if ( needsHScroll ){
-                       frameH += scrollH;
-               } else {
-                       scrollLeft = 0;
-               }
-
-               if ( frameW != oldFrameW || frameH != oldFrameH ) {
-
-                       if ( jQuery.browser.safari ) {
-                               html[0].style.overflow="hidden";
-                       } else {
-                               iframe[0].style.overflow="hidden";
-                       }
-
-                       if ( animate ) {
-                               content
-                               .width ( 'auto' )
-                               .height ( 'auto' );
-
-                               container.animate({
-                                       width: frameW,
-                                       height: frameH,
-                                       top: Math.floor(( - frameH ) / 2),
-                                       left: Math.floor(( - frameW ) / 2)
-                               }, {
-                                       duration: 500,
-                                       complete: function() {
-
-                                               if ( jQuery.browser.safari ) {
-                                                       
html[0].style.overflow="visible";
-                                               } else if ( jQuery.browser.msie 
) {
-                                                       
iframe[0].style.overflow="auto";
-                                               } else {
-                                                       
iframe[0].style.overflow="visible";
-                                               }
-
-                                               if ( jQuery.browser.mozilla ) {
-                                                       content
-                                                       .width ( contW )
-                                                       .height ( contH );
-                                               } else {
-                                                       content
-                                                       .width ( 'auto' )
-                                                       .height ( 'auto' );
-                                               }
-                                       }
-                               });
-
-                       } else {
-                               container
-                               .width( frameW )
-                               .height ( frameH );
-
-                               container[0].style.top = (Math.floor(( - frameH 
) / 2)) + "px";
-                               container[0].style.left = (Math.floor(( - 
frameW ) / 2)) + "px";
-
-
-                               setTimeout(function(){
-
-                                               if ( jQuery.browser.safari ) {
-                                                       
html[0].style.overflow="visible";
-                                               } else if ( jQuery.browser.msie 
) {
-                                                       
iframe[0].style.overflow="auto";
-                                               } else {
-                                                       
iframe[0].style.overflow="visible";
-                                               }
-
-                               }, 100);
-
-                               if ( jQuery.browser.mozilla ) {
-                                       content
-                                       .width ( contW )
-                                       .height ( contH );
-                               } else {
-                                       content
-                                       .width ( 'auto' )
-                                       .height ( 'auto' );
-                               }
-
-                       }
-               } else {
-                       content
-                       .width ( 'auto' )
-                       .height ( 'auto' );
-
-                       if ( jQuery.browser.safari ) { // Google chrome needs a 
kick
-
-                               // turn scrollbars off and on again to really 
only show them when needed
-                                       html[0].style.overflow="hidden";
-
-                                       setTimeout(function(){
-                                               
html[0].style.overflow="visible";
-                               }, 1);
-                       }
-               }
-
-               scrollTgt
-               .css('overflow', 'auto')
-               .scrollTop(Math.min(scrollTop, docpH - frameH))
-               .scrollLeft(scrollLeft);
-
-               if ( jQuery.browser.mozilla ) {
-                       body
-                       .css('overflow', 'auto');
-               }
-
+               elem.target = 'popupform-iframe' + instance;
                return true;
        }
 
-       function closeFrameAndFollowLink( link ){
-               clearTimeout(timer);
+       function handlePopupFormLink( ptarget, elem ) {
+               showForm();
 
-               fadeOut( container, function(){
-                       fadeIn ( waitIndicator );
-                       window.location.href = link;
+               // store initial readystate
+               var readystate = iframe.contents()[0].readyState;
+
+               // set up timer for waiting on the document in the iframe to be 
dom-ready
+               // this sucks, but there is no other way to catch that event
+               // onload is already too late
+               timer = setInterval(function(){
+                       // if the readystate changed
+                       if ( readystate !== iframe.contents()[0].readyState ) {
+                               // store new readystate
+                               readystate = iframe.contents()[0].readyState;
+
+                               // if dom is built but document not yet 
displayed
+                               if ( readystate === 'interactive' || readystate 
=== 'complete' ) {
+                                       needsRender = false; // flag that 
rendering is already done
+                                       handleLoadFrame();
+                               }
+                       }
+               }, 100 );
+
+               // fallback in case we did not catch the dom-ready state
+               iframe.on('load', function( event ){
+                       if ( needsRender ) { // rendering not already done?
+                               handleLoadFrame( event );
+                       }
+                       needsRender = true;
                });
-       }
 
-       function handleCloseFrame( event ){
-               jQuery(window).unbind( "resize", adjustFrameSize );
-               clearTimeout(timer);
-
-               fadeOut( container, function(){
-                       background.fadeOut( function(){
-                               wrapper.remove();
-                       });
-               });
-               return false;
-       }
-
-       // Saw it on 
http://robertnyman.com/2006/04/24/get-the-rendered-style-of-an-element
-       // and liked it
-       function getStyle(oElm, strCssRule){
-               var strValue = "";
-               if(document.defaultView && 
document.defaultView.getComputedStyle){
-                       strValue = document.defaultView.getComputedStyle(oElm, 
"").getPropertyValue(strCssRule);
-               }
-               else if(oElm.currentStyle){
-                       strCssRule = strCssRule.replace(/\-(\w)/g, function 
(strMatch, p1){
-                               return p1.toUpperCase();
-                       });
-                       strValue = oElm.currentStyle[strCssRule];
-               }
-               return strValue;
-       }
-
-       function fadeIn(elem, callback ) {
-               // no fading for broken browsers
-               if ( brokenBrowser ){
-
-                       elem.show();
-                       if ( callback ) {
-                               callback();
-                       }
+               if ( elem.tagName === 'FORM' ) {
+                       elem.target = 'popupform-iframe' + instance;
+                       return true;
                } else {
-                       // what an ugly hack
-                       if ( elem === waitIndicator ) {
-                               elem.fadeIn( 200, callback );
+                       var delim = ptarget.indexOf( '?' );
+                       var form = document.createElement("form");
+
+                       form.target = 'popupform-iframe' + instance;
+
+                       // Do we have parameters?
+                       if ( delim > 0 ) {
+                               form.action = ptarget.substr( 0, delim );
+                               var params = String( ptarget.substr( delim + 1 
) ).split("&");
+                               for ( var i = 0; i < params.length; ++i ) {
+
+                                       var input = 
document.createElement("input");
+                                       var param = String( params[i] 
).split('=');
+                                       input.type = 'hidden';
+                                       input.name = decodeURIComponent( 
param[0] );
+                                       input.value = decodeURIComponent( 
param[1] );
+                                       form.appendChild( input );
+                               }
                        } else {
-                               elem.fadeIn( callback );
-                       }
-               }
-       }
-
-       function fadeOut(elem, callback ) {
-               // no fading for broken browsers
-               if ( brokenBrowser ){
-                       elem.hide();
-                       if ( callback ) {
-                               callback();
-                       }
-               } else {
-                       // what an ugly hack
-                       if ( elem === waitIndicator ) {
-                               elem.fadeOut( 200, callback );
-                       } else {
-                               elem.fadeOut( callback );
-                       }
-               }
-       }
-
-       function fadeTo(elem, time, target, callback) {
-               // no fading for broken browsers
-               if ( brokenBrowser ){
-
-                       if (target > 0) {
-                               elem[0].style.visibility = "visible";
-                       } else {
-                               elem[0].style.visibility = "hidden";
+                               form.action = ptarget;
                        }
 
-                       if ( callback ) {
-                               callback();
-                       }
+                       
document.getElementsByTagName('body')[0].appendChild(form);
+                       form.submit();
+                       
document.getElementsByTagName('body')[0].removeChild(form);
 
-               } else {
-                       elem.fadeTo(time, target, callback);
+                       return false;
                }
        }
 
@@ -826,4 +826,4 @@
        this.handlePopupFormInput = handlePopupFormInput;
        this.handlePopupFormLink = handlePopupFormLink;
        this.adjustFrameSize = adjustFrameSize;
-}();
\ No newline at end of file
+}() );
diff --git a/libs/SF_wikieditor.js b/libs/SF_wikieditor.js
index 8527081..a965b68 100644
--- a/libs/SF_wikieditor.js
+++ b/libs/SF_wikieditor.js
@@ -1,20 +1,22 @@
 // create ext if it does not exist yet
 /*global wgWikiEditorEnabledModules*/
-if ( window.ext == null || typeof( window.ext ) === "undefined" ) {
+if ( window.ext === null || typeof( window.ext ) === "undefined" ) {
        window.ext = {};
 }
+
+( function ( $, mw ) {
 
 window.ext.wikieditor = {
        // initialize the wikieditor on the specified element
        init : function init ( input_id, params ) {
-               jQuery( function() {
-               if ( window.mediaWiki ) {
-                               var input = jQuery( '#' + input_id );
+               $( function() {
+                       if ( mw ) {
+                               var input = $( '#' + input_id );
 
                                // load toolbar
-                               mediaWiki.loader.using( 
['jquery.wikiEditor.toolbar', 'jquery.wikiEditor.toolbar.config'] , function(){
-                                       if ( jQuery.wikiEditor.isSupported( 
jQuery.wikiEditor.modules.toolbar ) ) {
-                                               input.wikiEditor( 'addModule', 
jQuery.wikiEditor.modules.toolbar.config.getDefaultConfig() );
+                               mw.loader.using( ['jquery.wikiEditor.toolbar', 
'jquery.wikiEditor.toolbar.config'] , function() {
+                                       if ( $.wikiEditor.isSupported( 
$.wikiEditor.modules.toolbar ) ) {
+                                               input.wikiEditor( 'addModule', 
$.wikiEditor.modules.toolbar.config.getDefaultConfig() );
 
                                                // hide sig if required
                                                if ( wgWikiEditorEnabledModules 
&& wgWikiEditorEnabledModules.hidesig === true ) {
@@ -29,14 +31,15 @@
                                });
 
                                // load dialogs
-                               mediaWiki.loader.using( 
['jquery.wikiEditor.dialogs', 'jquery.wikiEditor.dialogs.config'] , function(){
-                                       if ( jQuery.wikiEditor.isSupported( 
jQuery.wikiEditor.modules.dialogs ) ) {
-                                               
jQuery.wikiEditor.modules.dialogs.config.replaceIcons( input );
+                               mw.loader.using( ['jquery.wikiEditor.dialogs', 
'jquery.wikiEditor.dialogs.config'] , function(){
+                                       if ( $.wikiEditor.isSupported( 
$.wikiEditor.modules.dialogs ) ) {
+                                               
$.wikiEditor.modules.dialogs.config.replaceIcons( input );
                                                input.wikiEditor( 'addModule', 
$.wikiEditor.modules.dialogs.config.getDefaultConfig() );
 
                                        }
                                });
                        }
-               });
+               } );
        }
 };
+}( jQuery, mediaWiki ) );
diff --git a/libs/SemanticForms.js b/libs/SemanticForms.js
index 02c3866..523a9fa 100644
--- a/libs/SemanticForms.js
+++ b/libs/SemanticForms.js
@@ -10,214 +10,215 @@
  * @author Harold Solbrig
  * @author Eugene Mednikov
  */
- /*global sfgShowOnSelect, sfgFieldProperties, sfgCargoFields, validateAll, 
alert, sf*/
+/*global sfgShowOnSelect, sfgFieldProperties, sfgCargoFields, validateAll, 
alert, sf*/
 
 // Activate autocomplete functionality for the specified field
-(function(jQuery) {
+( function ( $, mw ) {
 
-       /* extending jQuery functions for custom highlighting */
-       jQuery.ui.autocomplete.prototype._renderItem = function( ul, item) {
+/* extending jQuery functions for custom highlighting */
+$.ui.autocomplete.prototype._renderItem = function( ul, item) {
 
-               var delim = this.element.context.delimiter;
-               var term;
-               if ( delim === null ) {
-                       term = this.term;
-               } else {
-                       term = this.term.split( delim ).pop();
-               }
-               var re = new RegExp("(?![^&;]+;)(?!<[^<>]*)(" + 
term.replace(/([\^\$\(\)\[\]\{\}\*\.\+\?\|\\])/gi, "\\$1") + 
")(?![^<>]*>)(?![^&;]+;)", "gi");
-               var loc = item.label.search(re);
-               var t;
-               if (loc >= 0) {
-                       t = item.label.substr(0, loc) + '<strong>' + 
item.label.substr(loc, term.length) + '</strong>' + item.label.substr(loc + 
term.length);
-               } else {
-                       t = item.label;
-               }
-               return jQuery( "<li></li>" )
-                       .data( "item.autocomplete", item )
-                       .append( " <a>" + t + "</a>" )
-                       .appendTo( ul );
-       };
-
-  jQuery.fn.attachAutocomplete = function() {
-    return this.each(function() {
-       // Get all the necessary values from the input's "autocompletesettings"
-       // attribute. This should probably be done as three separate attributes,
-       // instead.
-       var field_string = jQuery(this).attr("autocompletesettings");
-
-       if ( typeof field_string === 'undefined' ) {
-               return;
+       var delim = this.element.context.delimiter;
+       var term;
+       if ( delim === null ) {
+               term = this.term;
+       } else {
+               term = this.term.split( delim ).pop();
        }
-
-       var field_values = field_string.split(',');
-       var delimiter = null;
-       var data_source = field_values[0];
-       if (field_values[1] == 'list') {
-               delimiter = ",";
-               if (field_values[2] !== null && field_values[2] !== '' && 
field_values[2] !== undefined) {
-                       delimiter = field_values[2];
-               }
+       var re = new RegExp("(?![^&;]+;)(?!<[^<>]*)(" + 
term.replace(/([\^\$\(\)\[\]\{\}\*\.\+\?\|\\])/gi, "\\$1") + 
")(?![^<>]*>)(?![^&;]+;)", "gi");
+       var loc = item.label.search(re);
+       var t;
+       if (loc >= 0) {
+               t = item.label.substr(0, loc) + '<strong>' + 
item.label.substr(loc, term.length) + '</strong>' + item.label.substr(loc + 
term.length);
+       } else {
+               t = item.label;
        }
+       return $( "<li></li>" )
+               .data( "item.autocomplete", item )
+               .append( " <a>" + t + "</a>" )
+               .appendTo( ul );
+};
 
-       // Modify the delimiter. If it's "\n", change it to an actual
-       // newline - otherwise, add a space to the end.
-       // This doesn't cover the case of a delimiter that's a newline
-       // plus something else, like ".\n" or "\n\n", but as far as we
-       // know no one has yet needed that.
-       if ( delimiter !== null && delimiter !== '' && delimiter !== undefined 
) {
-               if ( delimiter == "\\n" ) {
-                       delimiter = "\n";
-               } else {
-                       delimiter += " ";
+$.fn.attachAutocomplete = function() {
+       return this.each(function() {
+               // Get all the necessary values from the input's 
"autocompletesettings"
+               // attribute. This should probably be done as three separate 
attributes,
+               // instead.
+               var field_string = $(this).attr("autocompletesettings");
+
+               if ( typeof field_string === 'undefined' ) {
+                       return;
+
                }
-       }
-       // Store this value within the object, so that it can be used
-       // during highlighting of the search term as well.
-       this.delimiter = delimiter;
 
-       /* extending jquery functions */
-       jQuery.extend( jQuery.ui.autocomplete, {
-           filter: function(array, term) {
-               var sfgAutocompleteOnAllChars = mediaWiki.config.get( 
'sfgAutocompleteOnAllChars' );
-               var matcher;
-    if ( sfgAutocompleteOnAllChars ) {
-                       matcher = new 
RegExp(jQuery.ui.autocomplete.escapeRegex(term), "i" );
-               } else {
-                       matcher = new RegExp("\\b" + 
jQuery.ui.autocomplete.escapeRegex(term), "i" );
-               }
-               return jQuery.grep( array, function(value) {
-                       return matcher.test( value.label || value.value || 
value );
-               });
-           }
-       });
-
-   var values = jQuery(this).data('autocompletevalues');
-    if ( !values ) {
-       var sfgAutocompleteValues = mediaWiki.config.get( 
'sfgAutocompleteValues' );
-       values = sfgAutocompleteValues[field_string];
-    }
-    var split = function (val) {
-               return val.split(delimiter);
-       };
-       var extractLast = function (term) {
-               return split(term).pop();
-       };
-    if (values !== null && values !== undefined) {
-       // Local autocompletion
-
-       if (delimiter !== null && delimiter !== undefined) {
-               // Autocomplete for multiple values
-
-               var thisInput = jQuery(this);
-
-               jQuery(this).autocomplete({
-                       minLength: 0,
-                       source: function(request, response) {
-                               // We need to re-get the set of values, since
-                               // the "values" variable gets overwritten.
-                               values = thisInput.data( 'autocompletevalues' );
-                               if ( !values ) {
-                                       values = 
sfgAutocompleteValues[field_string];
-                               }
-                               response(jQuery.ui.autocomplete.filter(values, 
extractLast(request.term)));
-                       },
-                       focus: function() {
-                               // prevent value inserted on focus
-                               return false;
-                       },
-                       select: function(event, ui) {
-                               var terms = split( this.value );
-                               // remove the current input
-                               terms.pop();
-                               // add the selected item
-                               terms.push( ui.item.value );
-                               // add placeholder to get the comma-and-space 
at the end
-                               terms.push("");
-                               this.value = terms.join(delimiter);
-                               return false;
+               var field_values = field_string.split(',');
+               var delimiter = null;
+               var data_source = field_values[0];
+               if (field_values[1] === 'list') {
+                       delimiter = ",";
+                       if (field_values[2] !== null && field_values[2] !== '' 
&& field_values[2] !== undefined) {
+                               delimiter = field_values[2];
                        }
-               });
+               }
 
-        } else {
-               // Autocomplete for a single value
-                jQuery(this).autocomplete({
-                       source:values
-               });
-        }
-    } else {
-       // Remote autocompletion.
-       var myServer = mediaWiki.util.wikiScript( 'api' );
-       var data_type = jQuery(this).attr("autocompletedatatype");
-       myServer += "?action=sfautocomplete&format=json&" + data_type + "=" + 
data_source;
+               // Modify the delimiter. If it's "\n", change it to an actual
+               // newline - otherwise, add a space to the end.
+               // This doesn't cover the case of a delimiter that's a newline
+               // plus something else, like ".\n" or "\n\n", but as far as we
+               // know no one has yet needed that.
+               if ( delimiter !== null && delimiter !== '' && delimiter !== 
undefined ) {
+                       if ( delimiter === "\\n" ) {
+                               delimiter = "\n";
+                       } else {
+                               delimiter += " ";
+                       }
+               }
+               // Store this value within the object, so that it can be used
+               // during highlighting of the search term as well.
+               this.delimiter = delimiter;
 
-       if (delimiter !== null && delimiter !== undefined) {
-               jQuery(this).autocomplete({
-                       source: function(request, response) {
-                               jQuery.getJSON(myServer, {
-                                       substr: extractLast(request.term)
-                               }, function( data ) {
-                                       
response(jQuery.map(data.sfautocomplete, function(item) {
-                                               return {
-                                                       value: item.title
-                                               };
-                                       }));
-                               });
-                       },
-                       search: function() {
-                               // custom minLength
-                               var term = extractLast(this.value);
-                               if (term.length < 1) {
-                                       return false;
+               /* extending jQuery functions */
+               $.extend( $.ui.autocomplete, {
+                       filter: function(array, term) {
+                               var sfgAutocompleteOnAllChars = mw.config.get( 
'sfgAutocompleteOnAllChars' );
+                               var matcher;
+                               if ( sfgAutocompleteOnAllChars ) {
+                                       matcher = new 
RegExp($.ui.autocomplete.escapeRegex(term), "i" );
+                               } else {
+                                       matcher = new RegExp("\\b" + 
$.ui.autocomplete.escapeRegex(term), "i" );
                                }
-                       },
-                       focus: function() {
-                               // prevent value inserted on focus
-                               return false;
-                       },
-                       select: function(event, ui) {
-                               var terms = split( this.value );
-                               // remove the current input
-                               terms.pop();
-                               // add the selected item
-                               terms.push( ui.item.value );
-                               // add placeholder to get the comma-and-space 
at the end
-                               terms.push("");
-                               this.value = terms.join(delimiter);
-                               return false;
+                               return $.grep( array, function(value) {
+                                       return matcher.test( value.label || 
value.value || value );
+                               });
                        }
                } );
-       } else {
-               jQuery(this).autocomplete({
-                       minLength: 1,
-                       source: function(request, response) {
-                               jQuery.ajax({
-                                       url: myServer,
-                                       dataType: "json",
-                                       data: {
-                                               substr:request.term
+
+               var values = $(this).data('autocompletevalues');
+               if ( !values ) {
+                       var sfgAutocompleteValues = mw.config.get( 
'sfgAutocompleteValues' );
+                       values = sfgAutocompleteValues[field_string];
+               }
+               var split = function (val) {
+                       return val.split(delimiter);
+               };
+               var extractLast = function (term) {
+                       return split(term).pop();
+               };
+               if (values !== null && values !== undefined) {
+                       // Local autocompletion
+
+                       if (delimiter !== null && delimiter !== undefined) {
+                               // Autocomplete for multiple values
+
+                               var thisInput = $(this);
+
+                               $(this).autocomplete({
+                                       minLength: 0,
+                                       source: function(request, response) {
+                                               // We need to re-get the set of 
values, since
+                                               // the "values" variable gets 
overwritten.
+                                               values = thisInput.data( 
'autocompletevalues' );
+                                               if ( !values ) {
+                                                       values = 
sfgAutocompleteValues[field_string];
+                                               }
+                                               
response($.ui.autocomplete.filter(values, extractLast(request.term)));
                                        },
-                                       success: function( data ) {
-                                               
response(jQuery.map(data.sfautocomplete, function(item) {
-                                                       return {
-                                                               value: 
item.title
-                                                       };
-                                               }));
+                                       focus: function() {
+                                               // prevent value inserted on 
focus
+                                               return false;
+                                       },
+                                       select: function(event, ui) {
+                                               var terms = split( this.value );
+                                               // remove the current input
+                                               terms.pop();
+                                               // add the selected item
+                                               terms.push( ui.item.value );
+                                               // add placeholder to get the 
comma-and-space at the end
+                                               terms.push("");
+                                               this.value = 
terms.join(delimiter);
+                                               return false;
                                        }
                                });
-                       },
-                       open: function() {
-                               
jQuery(this).removeClass("ui-corner-all").addClass("ui-corner-top");
-                       },
-                       close: function() {
-                               
jQuery(this).removeClass("ui-corner-top").addClass("ui-corner-all");
+
+                       } else {
+                               // Autocomplete for a single value
+                               $(this).autocomplete({
+                                       source:values
+                               });
                        }
-               } );
-       }
-    }
-   });
-  };
-})( jQuery );
+               } else {
+                       // Remote autocompletion.
+                       var myServer = mw.util.wikiScript( 'api' );
+                       var data_type = $(this).attr("autocompletedatatype");
+                       myServer += "?action=sfautocomplete&format=json&" + 
data_type + "=" + data_source;
+
+                       if (delimiter !== null && delimiter !== undefined) {
+                               $(this).autocomplete({
+                                       source: function(request, response) {
+                                               $.getJSON(myServer, {
+                                                       substr: 
extractLast(request.term)
+                                               }, function( data ) {
+                                                       
response($.map(data.sfautocomplete, function(item) {
+                                                               return {
+                                                                       value: 
item.title
+                                                               };
+                                                       }));
+                                               });
+                                       },
+                                       search: function() {
+                                               // custom minLength
+                                               var term = 
extractLast(this.value);
+                                               if (term.length < 1) {
+                                                       return false;
+                                               }
+                                       },
+                                       focus: function() {
+                                               // prevent value inserted on 
focus
+                                               return false;
+                                       },
+                                       select: function(event, ui) {
+                                               var terms = split( this.value );
+                                               // remove the current input
+                                               terms.pop();
+                                               // add the selected item
+                                               terms.push( ui.item.value );
+                                               // add placeholder to get the 
comma-and-space at the end
+                                               terms.push("");
+                                               this.value = 
terms.join(delimiter);
+                                               return false;
+                                       }
+                               } );
+                       } else {
+                               $(this).autocomplete({
+                                       minLength: 1,
+                                       source: function(request, response) {
+                                               $.ajax({
+                                                       url: myServer,
+                                                       dataType: "json",
+                                                       data: {
+                                                               
substr:request.term
+                                                       },
+                                                       success: function( data 
) {
+                                                               
response($.map(data.sfautocomplete, function(item) {
+                                                                       return {
+                                                                               
value: item.title
+                                                                       };
+                                                               }));
+                                                       }
+                                               });
+                                       },
+                                       open: function() {
+                                               
$(this).removeClass("ui-corner-all").addClass("ui-corner-top");
+                                       },
+                                       close: function() {
+                                               
$(this).removeClass("ui-corner-top").addClass("ui-corner-all");
+                                       }
+                               } );
+                       }
+               }
+       });
+};
+
 
 
 /*
@@ -228,7 +229,7 @@
 // Initialize data object to hold initialization and validation data
 function setupSF() {
 
-       jQuery("#sfForm").data("SemanticForms",{
+       $("#sfForm").data("SemanticForms",{
                initFunctions : [],
                validationFunctions : []
        });
@@ -244,17 +245,17 @@
 //
 // @param valfunction The validation functions. Must take a string (the 
input's id) and an object as parameters
 // @param param The parameter object given to the validation function
-jQuery.fn.SemanticForms_registerInputValidation = function(valfunction, param) 
{
+$.fn.SemanticForms_registerInputValidation = function(valfunction, param) {
 
        if ( ! this.attr("id") ) {
                return this;
        }
 
-       if ( ! jQuery("#sfForm").data("SemanticForms") ) {
+       if ( ! $("#sfForm").data("SemanticForms") ) {
                setupSF();
        }
 
-       jQuery("#sfForm").data("SemanticForms").validationFunctions.push({
+       $("#sfForm").data("SemanticForms").validationFunctions.push({
                input : this.attr("id"),
                valfunction : valfunction,
                parameters : param
@@ -274,7 +275,7 @@
 // @param initFunction The initialization function. Must take a string (the 
input's id) and an object as parameters
 // @param param The parameter object given to the initialization function
 // @param noexecute If set, the initialization method will not be executed here
-jQuery.fn.SemanticForms_registerInputInit = function( initFunction, param, 
noexecute ) {
+$.fn.SemanticForms_registerInputInit = function( initFunction, param, 
noexecute ) {
 
        // return if element has no id
        if ( ! this.attr("id") ) {
@@ -282,18 +283,18 @@
        }
 
        // setup data structure if necessary
-       if ( ! jQuery("#sfForm").data("SemanticForms") ) {
+       if ( ! $("#sfForm").data("SemanticForms") ) {
                setupSF();
        }
 
        // if no initialization function for this input was registered yet,
        // create entry
-       if ( ! 
jQuery("#sfForm").data("SemanticForms").initFunctions[this.attr("id")] ) {
-               
jQuery("#sfForm").data("SemanticForms").initFunctions[this.attr("id")] = [];
+       if ( ! 
$("#sfForm").data("SemanticForms").initFunctions[this.attr("id")] ) {
+               
$("#sfForm").data("SemanticForms").initFunctions[this.attr("id")] = [];
        }
 
        // record initialization function
-       
jQuery("#sfForm").data("SemanticForms").initFunctions[this.attr("id")].push({
+       $("#sfForm").data("SemanticForms").initFunctions[this.attr("id")].push({
                initFunction : initFunction,
                parameters : param
        });
@@ -303,22 +304,22 @@
        if ( this.closest(".multipleTemplateStarter").length === 0 && 
!noexecute) {
                var input = this;
                // ensure initFunction is only exectued after doc structure is 
complete
-               jQuery(function() {initFunction ( input.attr("id"), param );});
+               $(function() {initFunction ( input.attr("id"), param );});
        }
 
        return this;
 };
 
 // Unregister all validation methods for the element referenced by /this/
-jQuery.fn.SemanticForms_unregisterInputValidation = function() {
+$.fn.SemanticForms_unregisterInputValidation = function() {
 
-       var sfdata = jQuery("#sfForm").data("SemanticForms");
+       var sfdata = $("#sfForm").data("SemanticForms");
 
        if ( this.attr("id") && sfdata ) {
                // delete every validation method for this input
                for ( var i = 0; i < sfdata.validationFunctions.length; i++ ) {
                        if ( typeof sfdata.validationFunctions[i] !== 
'undefined' &&
-                               sfdata.validationFunctions[i].input == 
this.attr("id") ) {
+                               sfdata.validationFunctions[i].input === 
this.attr("id") ) {
                                delete sfdata.validationFunctions[i];
                        }
                }
@@ -328,10 +329,10 @@
 };
 
 // Unregister all initialization methods for the element referenced by /this/
-jQuery.fn.SemanticForms_unregisterInputInit = function() {
+$.fn.SemanticForms_unregisterInputInit = function() {
 
-       if ( this.attr("id") && jQuery("#sfForm").data("SemanticForms") ) {
-               delete 
jQuery("#sfForm").data("SemanticForms").initFunctions[this.attr("id")];
+       if ( this.attr("id") && $("#sfForm").data("SemanticForms") ) {
+               delete 
$("#sfForm").data("SemanticForms").initFunctions[this.attr("id")];
        }
 
        return this;
@@ -343,10 +344,11 @@
 
 // Display a div that would otherwise be hidden by "show on select".
 function showDiv(div_id, instanceWrapperDiv, speed) {
-       if ( instanceWrapperDiv != null ) {
-               var elem = jQuery('[data-origID="' + div_id + '"]', 
instanceWrapperDiv);
+       var elem;
+       if ( instanceWrapperDiv !== null ) {
+               elem = $('[data-origID="' + div_id + '"]', instanceWrapperDiv);
        } else {
-               var elem = jQuery('#' + div_id);
+               elem = $('#' + div_id);
        }
 
        elem
@@ -358,10 +360,10 @@
        .removeClass('disabledBySF');
 
        elem.each( function() {
-               if ( jQuery(this).css('display') == 'none' ) {
+               if ( $(this).css('display') === 'none' ) {
 
-                       jQuery(this).slideDown(speed, function() {
-                               jQuery(this).fadeTo(speed,1);
+                       $(this).slideDown(speed, function() {
+                               $(this).fadeTo(speed,1);
                        });
 
                }
@@ -371,6 +373,7 @@
 // Hide a div due to "show on select". The CSS class is there so that SF can
 // ignore the div's contents when the form is submitted.
 function hideDiv(div_id, instanceWrapperDiv, speed) {
+       var elem;
        // IDs can't contain spaces, and jQuery won't work with such IDs - if
        // this one has a space, display an alert.
        if ( div_id.indexOf( ' ' ) > -1 ) {
@@ -379,23 +382,23 @@
                alert( "Warning: this form has \"show on select\" pointing to 
an invalid element ID (\"" + div_id + "\") - IDs in HTML cannot contain 
spaces." );
        }
 
-       if ( instanceWrapperDiv != null ) {
-               var elem = instanceWrapperDiv.find('[data-origID=' + div_id + 
']');
+       if ( instanceWrapperDiv !== null ) {
+               elem = instanceWrapperDiv.find('[data-origID=' + div_id + ']');
        } else {
-               var elem = jQuery('#' + div_id);
+               elem = $('#' + div_id);
        }
        elem.find("span, div").addClass('hiddenBySF');
 
        elem.each( function() {
-               if ( jQuery(this).css('display') != 'none' ) {
+               if ( $(this).css('display') !== 'none' ) {
 
                        // if 'display' is not 'hidden', but the element is 
hidden otherwise
                        // (e.g. by having height = 0), just hide it, else 
animate the hiding
-                       if ( jQuery(this).is(':hidden') ) {
-                               jQuery(this).hide();
+                       if ( $(this).is(':hidden') ) {
+                               $(this).hide();
                        } else {
-                       jQuery(this).fadeTo(speed, 0, function() {
-                               jQuery(this).slideUp(speed);
+                       $(this).fadeTo(speed, 0, function() {
+                               $(this).slideUp(speed);
                        });
                        }
                }
@@ -408,8 +411,8 @@
        for ( var i = 0; i < options.length; i++ ) {
                // If it's a listbox and the user has selected more than one
                // value, it'll be an array - handle either case.
-               if ((jQuery.isArray(inputVal) && jQuery.inArray(options[i], 
inputVal) >= 0) ||
-                   (!jQuery.isArray(inputVal) && (inputVal == options[i]))) {
+               if (($.isArray(inputVal) && $.inArray(options[i], inputVal) >= 
0) ||
+                       (!$.isArray(inputVal) && (inputVal === options[i]))) {
                        showDiv( div_id, instanceWrapperDiv, initPage ? 0 : 
'fast' );
                        return;
                }
@@ -418,16 +421,17 @@
 }
 
 // Used for handling 'show on select' for the 'dropdown' and 'listbox' inputs.
-jQuery.fn.showIfSelected = function(initPage) {
-       var inputVal = this.val();
-       var sfgShowOnSelect = mediaWiki.config.get( 'sfgShowOnSelect' );
+$.fn.showIfSelected = function(initPage) {
+       var inputVal = this.val(),
+               sfgShowOnSelect = mw.config.get( 'sfgShowOnSelect' ),
+               showOnSelectVals,
+               instanceWrapperDiv = this.closest('.multipleTemplateInstance');
 
-       var instanceWrapperDiv = this.closest('.multipleTemplateInstance');
        if ( instanceWrapperDiv.length === 0 ) {
                instanceWrapperDiv = null;
-               var showOnSelectVals = sfgShowOnSelect[this.attr("id")];
+               showOnSelectVals = sfgShowOnSelect[this.attr("id")];
        } else {
-               var showOnSelectVals = 
sfgShowOnSelect[this.attr("data-origID")];
+               showOnSelectVals = sfgShowOnSelect[this.attr("data-origID")];
        }
 
        if ( showOnSelectVals !== undefined ) {
@@ -443,9 +447,9 @@
 
 // Show this div if any of the relevant selections are checked -
 // otherwise, hide it.
-jQuery.fn.showDivIfChecked = function(options, div_id, instanceWrapperDiv, 
initPage ) {
+$.fn.showDivIfChecked = function(options, div_id, instanceWrapperDiv, initPage 
) {
        for ( var i = 0; i < options.length; i++ ) {
-               if (jQuery(this).find('[value="' + options[i] + 
'"]').is(":checked")) {
+               if ($(this).find('[value="' + options[i] + 
'"]').is(":checked")) {
                        showDiv(div_id, instanceWrapperDiv, initPage ? 0 : 
'fast' );
                        return this;
                }
@@ -457,19 +461,21 @@
 
 // Used for handling 'show on select' for the 'checkboxes' and 'radiobutton'
 // inputs.
-jQuery.fn.showIfChecked = function(initPage) {
-       var sfgShowOnSelect = mediaWiki.config.get( 'sfgShowOnSelect' );
+$.fn.showIfChecked = function(initPage) {
+       var sfgShowOnSelect = mw.config.get( 'sfgShowOnSelect' ),
+               showOnSelectVals,
+               i;
 
        var instanceWrapperDiv = this.closest('.multipleTemplateInstance');
        if ( instanceWrapperDiv.length === 0 ) {
                instanceWrapperDiv = null;
-               var showOnSelectVals = sfgShowOnSelect[this.attr("id")];
+               showOnSelectVals = sfgShowOnSelect[this.attr("id")];
        } else {
-               var showOnSelectVals = 
sfgShowOnSelect[this.attr("data-origID")];
+               showOnSelectVals = sfgShowOnSelect[this.attr("data-origID")];
        }
 
        if ( showOnSelectVals !== undefined ) {
-               for ( var i = 0; i < showOnSelectVals.length; i++ ) {
+               for ( i = 0; i < showOnSelectVals.length; i++ ) {
                        var options = showOnSelectVals[i][0];
                        var div_id = showOnSelectVals[i][1];
                        this.showDivIfChecked(options, div_id, 
instanceWrapperDiv, initPage );
@@ -480,20 +486,23 @@
 };
 
 // Used for handling 'show on select' for the 'checkbox' input.
-jQuery.fn.showIfCheckedCheckbox = function(partOfMultiple, initPage) {
-       var sfgShowOnSelect = mediaWiki.config.get( 'sfgShowOnSelect' );
+$.fn.showIfCheckedCheckbox = function( partOfMultiple, initPage ) {
+       var sfgShowOnSelect = mw.config.get( 'sfgShowOnSelect' ),
+               divIDs,
+               instanceWrapperDiv,
+               i;
 
        if (partOfMultiple) {
-               var divIDs = sfgShowOnSelect[this.attr("data-origID")];
-               var instanceWrapperDiv = 
this.closest(".multipleTemplateInstance");
+               divIDs = sfgShowOnSelect[this.attr("data-origID")];
+               instanceWrapperDiv = this.closest(".multipleTemplateInstance");
        } else {
-               var divIDs = sfgShowOnSelect[this.attr("id")];
-               var instanceWrapperDiv = null;
+               divIDs = sfgShowOnSelect[this.attr("id")];
+               instanceWrapperDiv = null;
        }
 
-       for ( var i = 0; i < divIDs.length; i++ ) {
+       for ( i = 0; i < divIDs.length; i++ ) {
                var divID = divIDs[i];
-               if (jQuery(this).is(":checked")) {
+               if ($(this).is(":checked")) {
                        showDiv(divID, instanceWrapperDiv, initPage ? 0 : 
'fast' );
                } else {
                        hideDiv(divID, instanceWrapperDiv, initPage ? 0 : 
'fast' );
@@ -508,19 +517,19 @@
  */
 
 // Set the error message for an input.
-jQuery.fn.setErrorMessage = function(msg, val) {
+$.fn.setErrorMessage = function(msg, val) {
        var container = this.find('.sfErrorMessages');
-       container.html($('<div>').addClass( 'errorMessage' ).text( 
mediaWiki.msg( msg, val ) ));
+       container.html($('<div>').addClass( 'errorMessage' ).text( mw.msg( msg, 
val ) ));
 };
 
 // Append an error message to the end of an input.
-jQuery.fn.addErrorMessage = function(msg, val) {
+$.fn.addErrorMessage = function(msg, val) {
        this.find('input').addClass('inputError');
        this.find('select2-container').addClass('inputError');
-       this.append($('<div>').addClass( 'errorMessage' ).text( mediaWiki.msg( 
msg, val ) ));
+       this.append($('<div>').addClass( 'errorMessage' ).text( mw.msg( msg, 
val ) ));
 };
 
-jQuery.fn.isAtMaxInstances = function() {
+$.fn.isAtMaxInstances = function() {
        var numInstances = this.find("div.multipleTemplateInstance").length;
        var maximumInstances = this.attr("maximumInstances");
        if ( numInstances >= maximumInstances ) {
@@ -530,7 +539,7 @@
        return false;
 };
 
-jQuery.fn.validateNumInstances = function() {
+$.fn.validateNumInstances = function() {
        var minimumInstances = this.attr("minimumInstances");
        var maximumInstances = this.attr("maximumInstances");
        var numInstances = this.find("div.multipleTemplateInstance").length;
@@ -545,12 +554,12 @@
        }
 };
 
-jQuery.fn.validateMandatoryField = function() {
+$.fn.validateMandatoryField = function() {
        var fieldVal = this.find(".mandatoryField").val();
   var isEmpty;
        if (fieldVal === null) {
                isEmpty = true;
-       } else if (jQuery.isArray(fieldVal)) {
+       } else if ($.isArray(fieldVal)) {
                isEmpty = (fieldVal.length === 0);
        } else {
                isEmpty = (fieldVal.replace(/\s+/, '') === '');
@@ -563,7 +572,7 @@
        }
 };
 
-jQuery.fn.validateUniqueField = function() {
+$.fn.validateUniqueField = function() {
 
        var UNDEFINED = "undefined";
        var field = this.find(".uniqueField");
@@ -579,22 +588,25 @@
        }
 
        var categoryFieldName = field.prop("id") + "_unique_for_category";
-       var categoryField = jQuery("[name=" + categoryFieldName + "]");
+       var categoryField = $("[name=" + categoryFieldName + "]");
        var category = categoryField.val();
 
        var namespaceFieldName = field.prop("id") + "_unique_for_namespace";
-       var namespaceField = jQuery("[name=" + namespaceFieldName + "]");
+       var namespaceField = $("[name=" + namespaceFieldName + "]");
        var namespace = namespaceField.val();
 
-       var url = mediaWiki.config.get( 'wgScriptPath' ) + 
"/api.php?format=json&action=";
+       var url = mw.config.get( 'wgScriptPath' ) + 
"/api.php?format=json&action=";
+
+       var query,
+               isNotUnique;
 
        // SMW
-       var propertyFieldName = field.prop("id") + "_unique_property";
-       var propertyField = jQuery("[name=" + propertyFieldName + "]");
-       var property = propertyField.val();
+       var propertyFieldName = field.prop("id") + "_unique_property",
+               propertyField = $("[name=" + propertyFieldName + "]"),
+               property = propertyField.val();
        if (typeof property !== UNDEFINED && property.replace(/\s+/, '') !== 
'') {
 
-               var query = "[[" + property + "::" + fieldVal + "]]";
+               query = "[[" + property + "::" + fieldVal + "]]";
 
                if (typeof category !== UNDEFINED &&
                        category.replace(/\s+/, '') !== '') {
@@ -610,7 +622,7 @@
                }
 
                var conceptFieldName = field.prop("id") + "_unique_for_concept";
-               var conceptField = jQuery("[name=" + conceptFieldName + "]");
+               var conceptField = $("[name=" + conceptFieldName + "]");
                var concept = conceptField.val();
                if (typeof concept !== UNDEFINED &&
                        concept.replace(/\s+/, '') !== '') {
@@ -621,8 +633,8 @@
                query = encodeURIComponent(query);
 
                url += "ask&query=" + query;
-               var isNotUnique = true;
-               jQuery.ajax({
+               isNotUnique = true;
+               $.ajax({
                        url: url,
                        dataType: 'json',
                        async: false,
@@ -642,16 +654,16 @@
 
        // Cargo
        var cargoTableFieldName = field.prop("id") + "_unique_cargo_table";
-       var cargoTableField = jQuery("[name=" + cargoTableFieldName + "]");
+       var cargoTableField = $("[name=" + cargoTableFieldName + "]");
        var cargoTable = cargoTableField.val();
        var cargoFieldFieldName = field.prop("id") + "_unique_cargo_field";
-       var cargoFieldField = jQuery("[name=" + cargoFieldFieldName + "]");
+       var cargoFieldField = $("[name=" + cargoFieldFieldName + "]");
        var cargoField = cargoFieldField.val();
        if (typeof cargoTable !== UNDEFINED && cargoTable.replace(/\s+/, '') 
!== ''
                && typeof cargoField !== UNDEFINED
                && cargoField.replace(/\s+/, '') !== '') {
 
-               var query = "&where=" + cargoField + "+=+'" + fieldVal + "'";
+               query = "&where=" + cargoField + "+=+'" + fieldVal + "'";
 
                if (typeof category !== UNDEFINED &&
                        category.replace(/\s+/, '') !== '') {
@@ -663,7 +675,7 @@
                if (typeof namespace !== UNDEFINED) {
                        query += "+AND+_pageNamespace=";
                        if (namespace.replace(/\s+/, '') !== '') {
-                               var ns = 
mediaWiki.config.get('wgNamespaceIds')[namespace.toLowerCase()];
+                               var ns = 
mw.config.get('wgNamespaceIds')[namespace.toLowerCase()];
                                if (typeof ns !== UNDEFINED) {
                                        query +=  ns;
                                }
@@ -676,8 +688,8 @@
 
                url += "cargoquery&tables=" + cargoTable + "&fields=" + 
cargoField +
                        query;
-               var isNotUnique = true;
-               jQuery.ajax({
+               isNotUnique = true;
+               $.ajax({
                        url: url,
                        dataType: 'json',
                        async: false,
@@ -699,7 +711,7 @@
 
 };
 
-jQuery.fn.validateMandatoryComboBox = function() {
+$.fn.validateMandatoryComboBox = function() {
        var combobox = this.find( "input.sfComboBox" );
        if (combobox.val() === '') {
                this.addErrorMessage( 'sf_blank_error' );
@@ -709,10 +721,10 @@
        }
 };
 
-jQuery.fn.validateMandatoryDateField = function() {
+$.fn.validateMandatoryDateField = function() {
        if (this.find(".dayInput").val() === '' ||
-           this.find(".monthInput").val() === '' ||
-           this.find(".yearInput").val() === '') {
+               this.find(".monthInput").val() === '' ||
+               this.find(".yearInput").val() === '') {
                this.addErrorMessage( 'sf_blank_error' );
                return false;
        } else {
@@ -722,7 +734,7 @@
 
 // Special handling for radiobuttons, because what's being checked
 // is the first radiobutton, which has an empty value.
-jQuery.fn.validateMandatoryRadioButton = function() {
+$.fn.validateMandatoryRadioButton = function() {
        if (this.find("[value='']").is(':checked')) {
                this.addErrorMessage( 'sf_blank_error' );
                return false;
@@ -731,7 +743,7 @@
        }
 };
 
-jQuery.fn.validateMandatoryCheckboxes = function() {
+$.fn.validateMandatoryCheckboxes = function() {
        // Get the number of checked checkboxes within this span - must
        // be at least one.
        var numChecked = this.find("input:checked").size();
@@ -747,7 +759,7 @@
  * Type-based validation
  */
 
-jQuery.fn.validateURLField = function() {
+$.fn.validateURLField = function() {
        var fieldVal = this.find("input").val();
        // code borrowed from http://snippets.dzone.com/posts/show/452
        var url_regexp = 
/(ftp|http|https|rtsp|news):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/;
@@ -759,7 +771,7 @@
        }
 };
 
-jQuery.fn.validateEmailField = function() {
+$.fn.validateEmailField = function() {
        var fieldVal = this.find("input").val();
        // code borrowed from 
http://javascript.internet.com/forms/email-validation---basic.html
        var email_regexp = 
/^\s*\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,6})+\s*$/;
@@ -771,7 +783,7 @@
        }
 };
 
-jQuery.fn.validateNumberField = function() {
+$.fn.validateNumberField = function() {
        var fieldVal = this.find("input").val();
        // Handle "E notation"/scientific notation ("1.2e-3") in addition
        // to regular numbers
@@ -784,7 +796,7 @@
        }
 };
 
-jQuery.fn.validateDateField = function() {
+$.fn.validateDateField = function() {
        // validate only if day and year fields are both filled in
        var dayVal = this.find(".dayInput").val();
        var yearVal = this.find(".yearInput").val();
@@ -802,19 +814,24 @@
 
 // Standalone pipes are not allowed, because they mess up the template
 // parsing; unless they're part of a call to a template or a parser function.
-jQuery.fn.checkForPipes = function() {
+$.fn.checkForPipes = function() {
        var fieldVal = this.find("input, textarea").val();
        // We need to check for a few different things because this is
        // called for a variety of different input types.
-       if ( fieldVal == undefined || fieldVal == '' ) {
+       if ( fieldVal === undefined || fieldVal === '' ) {
                fieldVal = this.text();
        }
-       if ( fieldVal == undefined || fieldVal == '' ) {
+       if ( fieldVal === undefined || fieldVal === '' ) {
                return true;
        }
        if ( fieldVal.indexOf( '|' ) < 0 ) {
                return true;
        }
+
+       var nextPipe,
+               curIndex,
+               nextDoubleBracketsStart,
+               nextDoubleBracketsEnd;
 
        // There's at least one pipe - here's where the real work begins.
        // We do a mini-parsing of the string to try to make sure that every
@@ -850,86 +867,86 @@
 
        // We'll never get here, but let's have this line anyway.
        return true;
-}
+};
 
 window.validateAll = function () {
 
        // Hook that fires on form submission, before the validation.
-       mediaWiki.hook('sf.formValidationBefore').fire();
+       mw.hook('sf.formValidationBefore').fire();
 
        var num_errors = 0;
 
        // Remove all old error messages.
-       jQuery(".errorMessage").remove();
+       $(".errorMessage").remove();
 
        // Make sure all inputs are ignored in the "starter" instance
        // of any multiple-instance template.
-       jQuery(".multipleTemplateStarter").find("span, 
div").addClass("hiddenBySF");
+       $(".multipleTemplateStarter").find("span, div").addClass("hiddenBySF");
 
-       jQuery(".multipleTemplateList").each( function() {
-               if (! jQuery(this).validateNumInstances() ) {
+       $(".multipleTemplateList").each( function() {
+               if (! $(this).validateNumInstances() ) {
                        num_errors += 1;
                }
        });
 
-       jQuery("span.inputSpan.mandatoryFieldSpan").not(".hiddenBySF").each( 
function() {
-               if (! jQuery(this).validateMandatoryField() ) {
+       $("span.inputSpan.mandatoryFieldSpan").not(".hiddenBySF").each( 
function() {
+               if (! $(this).validateMandatoryField() ) {
                        num_errors += 1;
                }
        });
-       jQuery("div.ui-widget.mandatory").not(".hiddenBySF").each( function() {
-               if (! jQuery(this).validateMandatoryComboBox() ) {
+       $("div.ui-widget.mandatory").not(".hiddenBySF").each( function() {
+               if (! $(this).validateMandatoryComboBox() ) {
                        num_errors += 1;
                }
        });
-       jQuery("span.dateInput.mandatoryFieldSpan").not(".hiddenBySF").each( 
function() {
-               if (! jQuery(this).validateMandatoryDateField() ) {
+       $("span.dateInput.mandatoryFieldSpan").not(".hiddenBySF").each( 
function() {
+               if (! $(this).validateMandatoryDateField() ) {
                        num_errors += 1;
                }
        });
-       
jQuery("span.radioButtonSpan.mandatoryFieldSpan").not(".hiddenBySF").each( 
function() {
-               if (! jQuery(this).validateMandatoryRadioButton() ) {
+       $("span.radioButtonSpan.mandatoryFieldSpan").not(".hiddenBySF").each( 
function() {
+               if (! $(this).validateMandatoryRadioButton() ) {
                        num_errors += 1;
                }
        });
-       
jQuery("span.checkboxesSpan.mandatoryFieldSpan").not(".hiddenBySF").each( 
function() {
-               if (! jQuery(this).validateMandatoryCheckboxes() ) {
+       $("span.checkboxesSpan.mandatoryFieldSpan").not(".hiddenBySF").each( 
function() {
+               if (! $(this).validateMandatoryCheckboxes() ) {
                        num_errors += 1;
                }
        });
-       jQuery("span.inputSpan.uniqueFieldSpan").not(".hiddenBySF").each( 
function() {
-               if (! jQuery(this).validateUniqueField() ) {
+       $("span.inputSpan.uniqueFieldSpan").not(".hiddenBySF").each( function() 
{
+               if (! $(this).validateUniqueField() ) {
                        num_errors += 1;
                }
        });
-       jQuery("span.inputSpan, div.sfComboBox").not(".hiddenBySF, .freeText, 
.pageSection").each( function() {
-               if (! jQuery(this).checkForPipes() ) {
+       $("span.inputSpan, div.sfComboBox").not(".hiddenBySF, .freeText, 
.pageSection").each( function() {
+               if (! $(this).checkForPipes() ) {
                        num_errors += 1;
                }
        });
-       jQuery("span.URLInput").not(".hiddenBySF").each( function() {
-               if (! jQuery(this).validateURLField() ) {
+       $("span.URLInput").not(".hiddenBySF").each( function() {
+               if (! $(this).validateURLField() ) {
                        num_errors += 1;
                }
        });
-       jQuery("span.emailInput").not(".hiddenBySF").each( function() {
-               if (! jQuery(this).validateEmailField() ) {
+       $("span.emailInput").not(".hiddenBySF").each( function() {
+               if (! $(this).validateEmailField() ) {
                        num_errors += 1;
                }
        });
-       jQuery("span.numberInput").not(".hiddenBySF").each( function() {
-               if (! jQuery(this).validateNumberField() ) {
+       $("span.numberInput").not(".hiddenBySF").each( function() {
+               if (! $(this).validateNumberField() ) {
                        num_errors += 1;
                }
        });
-       jQuery("span.dateInput").not(".hiddenBySF").each( function() {
-               if (! jQuery(this).validateDateField() ) {
+       $("span.dateInput").not(".hiddenBySF").each( function() {
+               if (! $(this).validateDateField() ) {
                        num_errors += 1;
                }
        });
 
        // call registered validation functions
-       var sfdata = jQuery("#sfForm").data('SemanticForms');
+       var sfdata = $("#sfForm").data('SemanticForms');
 
        if ( sfdata && sfdata.validationFunctions.length > 0 ) { // found data 
object?
 
@@ -938,8 +955,8 @@
 
                        // if input is not part of multipleTemplateStarter
                        if ( typeof sfdata.validationFunctions[i] !== 
'undefined' &&
-                               jQuery("#" + 
sfdata.validationFunctions[i].input).closest(".multipleTemplateStarter").length 
=== 0 &&
-                               jQuery("#" + 
sfdata.validationFunctions[i].input).closest(".hiddenBySF").length === 0 ) {
+                               $("#" + 
sfdata.validationFunctions[i].input).closest(".multipleTemplateStarter").length 
=== 0 &&
+                               $("#" + 
sfdata.validationFunctions[i].input).closest(".hiddenBySF").length === 0 ) {
 
                                if (! sfdata.validationFunctions[i].valfunction(
                                                
sfdata.validationFunctions[i].input,
@@ -953,8 +970,8 @@
 
        if (num_errors > 0) {
                // add error header, if it's not there already
-               if (jQuery("#form_error_header").size() === 0) {
-                       jQuery("#contentSub").append('<div 
id="form_error_header" class="errorbox" style="font-size: medium"><img src="' + 
mediaWiki.config.get( 'sfgScriptPath' ) + '/skins/MW-Icon-AlertMark.png" 
/>&nbsp;' + mediaWiki.message( 'sf_formerrors_header' ).escaped() + '</div><br 
clear="both" />');
+               if ($("#form_error_header").size() === 0) {
+                       $("#contentSub").append('<div id="form_error_header" 
class="errorbox" style="font-size: medium"><img src="' + mw.config.get( 
'sfgScriptPath' ) + '/skins/MW-Icon-AlertMark.png" />&nbsp;' + mw.message( 
'sf_formerrors_header' ).escaped() + '</div><br clear="both" />');
                }
                scroll(0, 0);
        } else {
@@ -962,24 +979,25 @@
                // because they're part of the "starter" div for
                // multiple-instance templates, so that they aren't
                // submitted by the form.
-               jQuery('.hiddenBySF').find("input, select, 
textarea").not(':disabled')
+               $('.hiddenBySF').find("input, select, 
textarea").not(':disabled')
                .prop('disabled', true)
                .addClass('disabledBySF');
                //remove error box if it exists because there are no errors in 
the form now
-               jQuery("#contentSub").find(".errorbox").remove();
+               $("#contentSub").find(".errorbox").remove();
        }
 
        // Hook that fires on form submission, after the validation.
-       mediaWiki.hook('sf.formValidationAfter').fire();
+       mw.hook('sf.formValidationAfter').fire();
 
        return (num_errors === 0);
 };
 
+var num_elements = 0;
+
 /**
  * Functions for multiple-instance templates.
  */
-
-jQuery.fn.addInstance = function( addAboveCurInstance ) {
+$.fn.addInstance = function( addAboveCurInstance ) {
        var wrapper = this.closest(".multipleTemplateWrapper");
        var multipleTemplateList = wrapper.find('.multipleTemplateList');
 
@@ -1002,7 +1020,7 @@
                .removeAttr("id")
                .fadeTo(0,0)
                .slideDown('fast', function() {
-                       jQuery(this).fadeTo('fast', 1);
+                       $(this).fadeTo('fast', 1);
                });
 
        // Add on a new attribute, "data-origID", representing the ID of all
@@ -1028,7 +1046,7 @@
                        // chance of name collision with another field
                        if (this.name) {
                                var old_name = this.name.replace(/\[num\]/g, 
'');
-                               jQuery(this).attr('origName', old_name);
+                               $(this).attr('origName', old_name);
                                this.name = this.name.replace(/\[num\]/g, '[' + 
num_elements + 'b]');
                        }
 
@@ -1039,16 +1057,16 @@
                                this.id = this.id.replace(/input_/g, 'input_' + 
num_elements + '_');
 
                                // TODO: Data in sfgShowOnSelect should 
probably be stored in
-                               //  jQuery("#sfForm").data('SemanticForms')
+                               //  $("#sfForm").data('SemanticForms')
                                if ( sfgShowOnSelect[ old_id ] ) {
                                        sfgShowOnSelect[ this.id ] = 
sfgShowOnSelect[ old_id ];
                                }
 
                                // register initialization and validation 
methods for new inputs
 
-                               var sfdata = 
jQuery("#sfForm").data('SemanticForms');
+                               var sfdata = $("#sfForm").data('SemanticForms');
                                if ( sfdata ) { // found data object?
-          var i;
+                 var i;
                                        if ( sfdata.initFunctions[old_id] ) {
 
                                                // For every initialization 
method for
@@ -1056,7 +1074,7 @@
                                                // method for the new input.
                                                for ( i = 0; i < 
sfdata.initFunctions[old_id].length; i++ ) {
 
-                                                       
jQuery(this).SemanticForms_registerInputInit(
+                                                       
$(this).SemanticForms_registerInputInit(
                                                                
sfdata.initFunctions[old_id][i].initFunction,
                                                                
sfdata.initFunctions[old_id][i].parameters,
                                                                true //do not 
yet execute
@@ -1070,9 +1088,9 @@
                                        for ( i = 0; i < 
sfdata.validationFunctions.length; i++ ) {
 
                                                if ( typeof 
sfdata.validationFunctions[i] !== 'undefined' &&
-                                                       
sfdata.validationFunctions[i].input == old_id ) {
+                                                       
sfdata.validationFunctions[i].input === old_id ) {
 
-                                                       
jQuery(this).SemanticForms_registerInputValidation(
+                                                       
$(this).SemanticForms_registerInputValidation(
                                                                
sfdata.validationFunctions[i].valfunction,
                                                                
sfdata.validationFunctions[i].parameters
                                                                );
@@ -1108,7 +1126,7 @@
 
                        if (this.id) {
 
-                               var sfdata = 
jQuery("#sfForm").data('SemanticForms');
+                               var sfdata = $("#sfForm").data('SemanticForms');
                                if ( sfdata ) {
 
                                        // have to store data array: the id 
attribute
@@ -1132,16 +1150,16 @@
 
        // Hook that fires each time a new template instance is added.
        // The first parameter is a jQuery selection of the newly created 
instance div.
-       mediaWiki.hook('sf.addTemplateInstance').fire(new_div);
+       mw.hook('sf.addTemplateInstance').fire(new_div);
 };
 
 // The first argument is needed, even though it's an attribute of the element
 // on which this function is called, because it's the 'name' attribute for
 // regular inputs, and the 'origName' attribute for inputs in multiple-instance
 // templates.
-jQuery.fn.setDependentAutocompletion = function( dependentField, baseField, 
baseValue ) {
+$.fn.setDependentAutocompletion = function( dependentField, baseField, 
baseValue ) {
        // Get data from either Cargo or Semantic MediaWiki.
-       var myServer = mediaWiki.config.get( 'wgScriptPath' ) + "/api.php";
+       var myServer = mw.config.get( 'wgScriptPath' ) + "/api.php";
        myServer += "?action=sfautocomplete&format=json";
        if ( sfgCargoFields.hasOwnProperty( dependentField ) ) {
                var cargoTableAndFieldStr = sfgCargoFields[dependentField];
@@ -1159,8 +1177,8 @@
                myServer += "&property=" + propName + "&baseprop=" + baseProp + 
"&basevalue=" + baseValue;
        }
        var dependentValues = [];
-       var thisInput = jQuery(this);
-       // We use jQuery.ajax() here instead of jQuery.getJSON() so that the
+       var thisInput = $(this);
+       // We use $.ajax() here instead of $.getJSON() so that the
        // 'async' parameter can be set. That, in turn, is set because
        // if the 2nd, "dependent" field is a combo box, it can have weird
        // behavior: clicking on the down arrow for the combo box leads to a
@@ -1173,13 +1191,13 @@
        // @TODO - handle this the right way, by having special behavior for
        // the dropdown - it should get delayed until the values are
        // calculated, then appear.
-       jQuery.ajax({
+       $.ajax({
                url: myServer,
                dataType: 'json',
                async: false,
                success: function(data) {
                        var realData = data.sfautocomplete;
-                       jQuery.each(realData, function(key, val) {
+                       $.each(realData, function(key, val) {
                                dependentValues.push(val.title);
                        });
                        thisInput.data('autocompletevalues', dependentValues);
@@ -1192,24 +1210,24 @@
  * Called on a 'base' field (e.g., for a country) - sets the autocompletion
  * for its 'dependent' field (e.g., for a city).
  */
-jQuery.fn.setAutocompleteForDependentField = function( partOfMultiple ) {
-       var curValue = jQuery(this).val();
+$.fn.setAutocompleteForDependentField = function( partOfMultiple ) {
+       var curValue = $(this).val();
        if ( curValue === null ) { return this; }
 
        var nameAttr = partOfMultiple ? 'origName' : 'name';
-       var name = jQuery(this).attr(nameAttr);
-       var sfgDependentFields = mediaWiki.config.get( 'sfgDependentFields' );
+       var name = $(this).attr(nameAttr);
+       var sfgDependentFields = mw.config.get( 'sfgDependentFields' );
        var dependent_on_me = [];
        for ( var i = 0; i < sfgDependentFields.length; i++ ) {
                var dependentFieldPair = sfgDependentFields[i];
-               if ( dependentFieldPair[0] == name ) {
+               if ( dependentFieldPair[0] === name ) {
                        dependent_on_me.push(dependentFieldPair[1]);
                }
        }
-       dependent_on_me = jQuery.unique(dependent_on_me);
+       dependent_on_me = $.unique(dependent_on_me);
 
        var self = this;
-       jQuery.each( dependent_on_me, function() {
+       $.each( dependent_on_me, function() {
                var element, cmbox, tokens,
                        dependentField = this;
 
@@ -1240,28 +1258,28 @@
  * called for either the entire HTML body, or for a div representing an
  * instance of a multiple-instance template.
  */
-jQuery.fn.initializeJSElements = function( partOfMultiple ) {
+$.fn.initializeJSElements = function( partOfMultiple ) {
        this.find(".sfShowIfSelected").each( function() {
-               jQuery(this)
+               $(this)
                .showIfSelected(true)
                .change( function() {
-                       jQuery(this).showIfSelected(false);
+                       $(this).showIfSelected(false);
                });
        });
 
        this.find(".sfShowIfChecked").each( function() {
-               jQuery(this)
+               $(this)
                .showIfChecked(true)
                .click( function() {
-                       jQuery(this).showIfChecked(false);
+                       $(this).showIfChecked(false);
                });
        });
 
        this.find(".sfShowIfCheckedCheckbox").each( function() {
-               jQuery(this)
+               $(this)
                .showIfCheckedCheckbox(partOfMultiple, true)
                .click( function() {
-                       jQuery(this).showIfCheckedCheckbox(partOfMultiple, 
false);
+                       $(this).showIfCheckedCheckbox(partOfMultiple, false);
                });
        });
 
@@ -1269,18 +1287,18 @@
        this.find(".removeButton").click( function() {
 
                // Unregister initialization and validation for deleted inputs
-               jQuery(this).parentsUntil( '.multipleTemplateInstance' 
).last().parent().find("input, select, textarea").each(
+               $(this).parentsUntil( '.multipleTemplateInstance' 
).last().parent().find("input, select, textarea").each(
                        function() {
-                               
jQuery(this).SemanticForms_unregisterInputInit();
-                               
jQuery(this).SemanticForms_unregisterInputValidation();
+                               $(this).SemanticForms_unregisterInputInit();
+                               
$(this).SemanticForms_unregisterInputValidation();
                        }
                );
 
                // Remove the encompassing div for this instance.
-               jQuery(this).closest(".multipleTemplateInstance")
+               $(this).closest(".multipleTemplateInstance")
                .fadeTo('fast', 0, function() {
-                       jQuery(this).slideUp('fast', function() {
-                               jQuery(this).remove();
+                       $(this).slideUp('fast', function() {
+                               $(this).remove();
                        });
                });
                return false;
@@ -1289,7 +1307,7 @@
        // ...and the new adder
        if ( partOfMultiple ) {
                this.find('.addAboveButton').click( function() {
-                       jQuery(this).addInstance( true );
+                       $(this).addInstance( true );
                        return false; // needed to disable <a> behavior
                });
        }
@@ -1323,10 +1341,10 @@
        // "dependent fields" information from a global variable to a
        // per-input HTML attribute.
        this.find('input, select').each( function() {
-               jQuery(this)
+               $(this)
                .setAutocompleteForDependentField( partOfMultiple )
                .blur( function() {
-                       jQuery(this).setAutocompleteForDependentField( 
partOfMultiple );
+                       $(this).setAutocompleteForDependentField( 
partOfMultiple );
                });
        });
        // The 'blur' event doesn't get triggered for radio buttons for
@@ -1335,58 +1353,65 @@
        // @TODO - blur() shuldn't be called at all for radio buttons.
        this.find('input:radio')
                .change( function() {
-                       jQuery(this).setAutocompleteForDependentField( 
partOfMultiple );
+                       $(this).setAutocompleteForDependentField( 
partOfMultiple );
                });
 
        this.find(".sfTreeInput").not(".multipleTemplateStarter 
.sfTreeInput").each( function() {
-               jQuery(this).applyDynatree();
+               $(this).applyDynatree();
        });
 
 };
 
-var num_elements = 0;
-
 // Once the document has finished loading, set up everything!
-jQuery(document).ready( function() {
+$(document).ready( function() {
+       var i,
+               inputID,
+               validationFunctionData;
+
        // Initialize inputs created by #forminput.
-       if ( jQuery('.sfFormInput').length > 0 ) {
-               jQuery('.autocompleteInput').attachAutocomplete();
+       if ( $('.sfFormInput').length > 0 ) {
+               $('.autocompleteInput').attachAutocomplete();
        }
 
        // Exit now if a Semantic Forms form is not present.
-       if ( jQuery('#sfForm').length == 0 ) {
+       if ( $('#sfForm').length === 0 ) {
                return;
        }
 
        // register init functions
-       initFunctionData = mw.config.get( 'ext.sf.initFunctionData' );
-       for ( var inputID in initFunctionData ) {
-               for ( var i in initFunctionData[inputID] ) {
-                       jQuery( '#' + inputID 
).SemanticForms_registerInputInit( window[initFunctionData[ inputID ][ i ][ 
'name' ]], initFunctionData[ inputID ][ i ][ 'param' ] );
+       var initFunctionData = mw.config.get( 'ext.sf.initFunctionData' );
+       for ( inputID in initFunctionData ) {
+               for ( i in initFunctionData[inputID] ) {
+                       /*jshint -W069 */
+                       $( '#' + inputID ).SemanticForms_registerInputInit( 
window[initFunctionData[ inputID ][ i ][ 'name' ]], initFunctionData[ inputID 
][ i ][ 'param' ] );
+                       /*jshint +W069 */
                }
        }
 
        // register validation functions
        validationFunctionData = mw.config.get( 'ext.sf.validationFunctionData' 
);
-       for ( var inputID in validationFunctionData ) {
-               for ( var i in validationFunctionData[inputID] ) {
-                       jQuery( '#' + inputID 
).SemanticForms_registerInputValidation( window[validationFunctionData[ inputID 
][ i ][ 'name' ]], validationFunctionData[ inputID ][ i ][ 'param' ] );
+       for ( inputID in validationFunctionData ) {
+               for ( i in validationFunctionData[inputID] ) {
+                       /*jshint -W069 */
+                       $( '#' + inputID 
).SemanticForms_registerInputValidation( window[validationFunctionData[ inputID 
][ i ][ 'name' ]], validationFunctionData[ inputID ][ i ][ 'param' ] );
+                       /*jshint +W069 */
                }
        }
 
-       jQuery('body').initializeJSElements(false);
+       $( 'body' ).initializeJSElements(false);
 
-       jQuery('.multipleTemplateInstance').initializeJSElements(true);
-       jQuery('.multipleTemplateAdder').click( function() {
-               jQuery(this).addInstance( false );
+       $('.multipleTemplateInstance').initializeJSElements(true);
+       $('.multipleTemplateAdder').click( function() {
+               $(this).addInstance( false );
        });
-       jQuery('.multipleTemplateList').sortable({
+       $('.multipleTemplateList').sortable({
                axis: 'y',
                handle: '.instanceRearranger'
        });
 
        // If the form is submitted, validate everything!
-       jQuery('#sfForm').submit( function() {
+       $('#sfForm').submit( function() {
                return validateAll();
        } );
 });
+}( jQuery, mediaWiki ) );
diff --git a/libs/ext.sf.js b/libs/ext.sf.js
index 7c251c8..19775cd 100644
--- a/libs/ext.sf.js
+++ b/libs/ext.sf.js
@@ -9,7 +9,7 @@
 *
 */
 
-var sf = ( function ( $, undefined ) {
+window.sf = ( function ( $, undefined ) {
        'use strict';
        /**
         *
@@ -23,7 +23,7 @@
        return {
 
        };
-} )( jQuery );
+}( jQuery ) );
 
 // Assigning namespace.
 window.sf = window.semanticforms = sf;
diff --git a/libs/ext.sf.select2.base.js b/libs/ext.sf.select2.base.js
index 9cf6174..ff522ac 100644
--- a/libs/ext.sf.select2.base.js
+++ b/libs/ext.sf.select2.base.js
@@ -1,16 +1,16 @@
 /*
-* ext.sf.select2.base.js
-*
-* Base class to handle autocomplete
-* for various input types using Select2 JS library
-*
-* @file
-*
-*
-* @licence GNU GPL v2+
-* @author Jatin Mehta
-*
-*/
+ * ext.sf.select2.base.js
+ *
+ * Base class to handle autocomplete
+ * for various input types using Select2 JS library
+ *
+ * @file
+ *
+ *
+ * @licence GNU GPL v2+
+ * @author Jatin Mehta
+ *
+ */
 
 ( function ( $, mw, sf ) {
        'use strict';
@@ -122,8 +122,8 @@
                        var sfgDependentFields = mw.config.get( 
'sfgDependentFields' );
                        for ( var i = 0; i < sfgDependentFields.length; i++ ) {
                                var dependentFieldPair = sfgDependentFields[i];
-                               if ( dependentFieldPair[1] == name ) {
-                                        return dependentFieldPair[0];
+                               if ( dependentFieldPair[1] === name ) {
+                                       return dependentFieldPair[0];
                                }
                        }
                        return null;
@@ -145,7 +145,7 @@
                        var sfgDependentFields = mw.config.get( 
'sfgDependentFields' );
                        for ( var i = 0; i < sfgDependentFields.length; i++ ) {
                                var dependentFieldPair = sfgDependentFields[i];
-                               if ( dependentFieldPair[0] == name ) {
+                               if ( dependentFieldPair[0] === name ) {
                                        
dependent_on_me.push(dependentFieldPair[1]);
                                }
                        }
@@ -252,11 +252,11 @@
                        var start = 
no_diac_text.toUpperCase().indexOf(term.toUpperCase());
                        if (start !== 0 && !mw.config.get( 
'sfgAutocompleteOnAllChars' )) {
                                start = no_diac_text.toUpperCase().indexOf(" " 
+ term.toUpperCase());
-                               if ( start != -1 ) {
+                               if ( start !== -1 ) {
                                        start = start + 1;
                                }
                        }
-                       if ( start != -1 ) {
+                       if ( start !== -1 ) {
                                markup += text.substr(0, start) +
                                '<span class="select2-match">' +
                                text.substr(start,term.length) +
diff --git a/libs/ext.sf.select2.combobox.js b/libs/ext.sf.select2.combobox.js
index c634532..f300440 100644
--- a/libs/ext.sf.select2.combobox.js
+++ b/libs/ext.sf.select2.combobox.js
@@ -53,7 +53,7 @@
                        opts.formatInputTooShort = mw.msg( 
"sf-select2-input-too-short", opts.minimumInputLength );
                        opts.formatSelection = this.formatSelection;
                        opts.escapeMarkup = function (m) { return m; };
-               } else if ( input_tagname == "INPUT" ) {
+               } else if ( input_tagname === "INPUT" ) {
                        opts.data = this.getData( 
autocomplete_opts.autocompletesettings );
                }
                var sfgAutocompleteOnAllChars = mw.config.get( 
'sfgAutocompleteOnAllChars' );
@@ -62,7 +62,7 @@
                                var no_diac_text = 
sf.select2.base.prototype.removeDiacritics( text );
                                var position = 
no_diac_text.toUpperCase().indexOf(term.toUpperCase());
                                var position_with_space = 
no_diac_text.toUpperCase().indexOf(" " + term.toUpperCase());
-                               if ( (position != -1 && position === 0 ) ||  
position_with_space != -1 ) {
+                               if ( (position !== -1 && position === 0 ) ||  
position_with_space !== -1 ) {
                                        return true;
                                } else {
                                        return false;
@@ -73,10 +73,10 @@
                opts.formatSearching = mw.msg( "sf-select2-searching" );
                opts.formatNoMatches = mw.msg( "sf-select2-no-matches" );
                opts.placeholder = $(input_id).attr( "placeholder" );
-               if ( $(input_id).attr( "existingvaluesonly" ) !== "true" && 
input_tagname == "INPUT" ) {
+               if ( $(input_id).attr( "existingvaluesonly" ) !== "true" && 
input_tagname === "INPUT" ) {
                        opts.createSearchChoice = function( term, data ) { if ( 
$(data).filter(function() { return this.text.localeCompare( term )===0; 
}).length===0 ) {return { id:term, text:term };} };
                }
-               if ( $(input_id).val() !== "" && input_tagname == "INPUT" ) {
+               if ( $(input_id).val() !== "" && input_tagname === "INPUT" ) {
                        opts.initSelection = function ( element, callback ) { 
var data = {id: element.val(), text: element.val()}; callback(data); };
                }
                opts.allowClear = true;
@@ -103,7 +103,7 @@
                var dep_on = this.dependentOn();
                var i, data;
                if ( dep_on === null ) {
-                       if ( autocompletesettings == 'external data' ) {
+                       if ( autocompletesettings === 'external data' ) {
                                var name = 
$(input_id).attr(this.nameAttr($(input_id)));
                                var sfgEDSettings = mw.config.get( 
'sfgEDSettings' );
                                var edgValues = mw.config.get( 'edgValues' );
@@ -161,7 +161,7 @@
                        my_server += "?action=sfautocomplete&format=json";
                        // URL depends on whether Cargo or Semantic MediaWiki
                        // is being used.
-                       if ( dep_field_opts.prop.indexOf('|') == -1 ) {
+                       if ( dep_field_opts.prop.indexOf('|') === -1 ) {
                                // SMW
                                my_server += "&property=" + dep_field_opts.prop 
+ "&baseprop=" + dep_field_opts.base_prop + "&basevalue=" + 
dep_field_opts.base_value;
                        } else {
@@ -208,7 +208,7 @@
                var data_source = 
autocomplete_opts.autocompletesettings.split(',')[0];
                var my_server = mw.util.wikiScript( 'api' );
                var autocomplete_type = autocomplete_opts.autocompletedatatype;
-               if ( autocomplete_type == 'cargo field' ) {
+               if ( autocomplete_type === 'cargo field' ) {
                        var table_and_field = data_source.split('|');
                        my_server += 
"?action=sfautocomplete&format=json&cargo_table=" + table_and_field[0] + 
"&cargo_field=" + table_and_field[1];
                } else {
@@ -280,11 +280,11 @@
                var cmbox = new sf.select2.combobox();
                var tokens = new sf.select2.tokens();
 
-               if ( class_name.indexOf( 'sfComboBox' ) != -1 ) {
+               if ( class_name.indexOf( 'sfComboBox' ) !== -1 ) {
                        cmbox.refresh(dependent_field);
-               } else  if ( class_name.indexOf( 'sfTokens' ) != -1 ) {
+               } else if ( class_name.indexOf( 'sfTokens' ) !== -1 ) {
                        tokens.refresh(dependent_field);
-               } else if ( class_name.indexOf( 'createboxInput' ) != -1 ) {
+               } else if ( class_name.indexOf( 'createboxInput' ) !== -1 ) {
                        var name_attr = cmbox.nameAttr($(dependent_on));
                        var field_name = $(dependent_field).attr(name_attr),
                        base_field_name = $(dependent_on).attr(name_attr),
diff --git a/libs/ext.sf.select2.tokens.js b/libs/ext.sf.select2.tokens.js
index 30da75a..03302da 100644
--- a/libs/ext.sf.select2.tokens.js
+++ b/libs/ext.sf.select2.tokens.js
@@ -69,7 +69,7 @@
                        opts.formatInputTooShort = "";
                        opts.formatSelection = this.formatSelection;
                        opts.escapeMarkup = function (m) { return m; };
-               } else if ( input_tagname == "INPUT" ) {
+               } else if ( input_tagname === "INPUT" ) {
                        opts.data = this.getData( 
autocomplete_opts.autocompletesettings );
                }
                var sfgAutocompleteOnAllChars = mw.config.get( 
'sfgAutocompleteOnAllChars' );
@@ -78,7 +78,7 @@
                                var no_diac_text = 
sf.select2.base.prototype.removeDiacritics( text );
                                var position = 
no_diac_text.toUpperCase().indexOf(term.toUpperCase());
                                var position_with_space = 
no_diac_text.toUpperCase().indexOf(" " + term.toUpperCase());
-                               if ( (position != -1 && position === 0 ) ||  
position_with_space != -1 ) {
+                               if ( (position !== -1 && position === 0 ) ||  
position_with_space !== -1 ) {
                                        return true;
                                } else {
                                        return false;
@@ -89,10 +89,10 @@
                opts.formatSearching = mw.msg( "sf-select2-searching" );
                opts.formatNoMatches = "";
                opts.placeholder = $(input_id).attr( "placeholder" );
-               if ( $(input_id).attr( "existingvaluesonly" ) !== "true" && 
input_tagname == "INPUT" ) {
+               if ( $(input_id).attr( "existingvaluesonly" ) !== "true" && 
input_tagname === "INPUT" ) {
                        opts.createSearchChoice = function( term, data ) { if ( 
$(data).filter(function() { return this.text.localeCompare( term )===0; 
}).length===0 ) {return { id:term, text:term };} };
                }
-               if ( $(input_id).val() !== "" && input_tagname == "INPUT" ) {
+               if ( $(input_id).val() !== "" && input_tagname === "INPUT" ) {
                        opts.initSelection = function ( element, callback ) {
                                var data = [];
                                var delim = self.getDelimiter($(input_id));
@@ -124,7 +124,7 @@
                        opts.formatSelectionTooBig = mw.msg( 
"sf-select2-selection-too-big", maxvalues );
                }
                opts.adaptContainerCssClass = function( clazz ) {
-                       if (clazz == "mandatoryField") {
+                       if (clazz === "mandatoryField") {
                                return "";
                        } else {
                                return clazz;
@@ -146,7 +146,7 @@
                var data;
                var dep_on = this.dependentOn();
                if ( dep_on === null ) {
-                       if ( autocompletesettings == 'external data' ) {
+                       if ( autocompletesettings === 'external data' ) {
                                var name = 
$(input_id).attr(this.nameAttr($(input_id)));
                                var sfgEDSettings = mw.config.get( 
'sfgEDSettings' );
                                var edgValues = mw.config.get( 'edgValues' );
@@ -233,7 +233,7 @@
                var data_source = 
autocomplete_opts.autocompletesettings.split(',')[0];
                var my_server = mw.util.wikiScript( 'api' );
                var autocomplete_type = autocomplete_opts.autocompletedatatype;
-               if ( autocomplete_type == 'cargo field' ) {
+               if ( autocomplete_type === 'cargo field' ) {
                        var table_and_field = data_source.split('|');
                        my_server += 
"?action=sfautocomplete&format=json&cargo_table=" + table_and_field[0] + 
"&cargo_field=" + table_and_field[1] + "&field_is_array=true";
                } else {
@@ -294,7 +294,7 @@
        tokens_proto.getDelimiter = function ( element ) {
                var field_values = element.attr('autocompletesettings').split( 
',' );
                var delimiter = ",";
-               if (field_values[1] == 'list' && field_values[2] !== undefined 
&& field_values[2] != "")  {
+               if (field_values[1] === 'list' && field_values[2] !== undefined 
&& field_values[2] !== "")  {
                                delimiter = field_values[2];
                }
 
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..5cea0c8
--- /dev/null
+++ b/package.json
@@ -0,0 +1,11 @@
+{
+  "scripts": {
+    "test": "grunt test"
+  },
+  "devDependencies": {
+    "grunt": "0.4.5",
+    "grunt-cli": "0.1.13",
+    "grunt-contrib-jshint": "0.12.0",
+    "grunt-jsonlint": "1.0.7"
+  }
+}

-- 
To view, visit https://gerrit.wikimedia.org/r/258678
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: I5e01223da5a882591e8028a8bb608a07ac543dfd
Gerrit-PatchSet: 66
Gerrit-Project: mediawiki/extensions/SemanticForms
Gerrit-Branch: master
Gerrit-Owner: Paladox <thomasmulhall...@yahoo.com>
Gerrit-Reviewer: Jforrester <jforres...@wikimedia.org>
Gerrit-Reviewer: Legoktm <legoktm.wikipe...@gmail.com>
Gerrit-Reviewer: Paladox <thomasmulhall...@yahoo.com>
Gerrit-Reviewer: TheDJ <hartman.w...@gmail.com>
Gerrit-Reviewer: Yaron Koren <yaro...@gmail.com>
Gerrit-Reviewer: jenkins-bot <>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to