diff --git a/.jshintignore b/.jshintignore index 66a218b5..b97a47d3 100644 --- a/.jshintignore +++ b/.jshintignore @@ -1,2 +1,4 @@ # upstream lib from Google modules/contentCollector.js +# messy +modules/jquery.wikiEditor.iframe.js diff --git a/.jshintrc b/.jshintrc index 64cd5087..5d335e32 100644 --- a/.jshintrc +++ b/.jshintrc @@ -1,9 +1,33 @@ { + /* Common */ + + // Enforcing + "camelcase": true, + "curly": true, + "eqeqeq": true, + "immed": true, + "latedef": true, + "newcap": true, + "noarg": true, + "noempty": true, + "nonew": true, + "quotmark": "single", + "trailing": true, + "undef": true, + "unused": true, + // Legacy + "onevar": true, + + /* Local */ + + // Relaxing + "loopfunc": true, + "multistr": true, + // Environment + "browser": true, + "predef": [ "mediaWiki", "jQuery" - ], - "browser": true, - "smarttabs": true, - "multistr": true + ] } diff --git a/modules/ext.wikiEditor.templateEditor.js b/modules/ext.wikiEditor.templateEditor.js index 61b88f9f..660a14fb 100644 --- a/modules/ext.wikiEditor.templateEditor.js +++ b/modules/ext.wikiEditor.templateEditor.js @@ -1,11 +1,13 @@ /* * JavaScript for WikiEditor Template Editor */ -jQuery( document ).ready( function ( $ ) { - // Disable in template namespace - if ( mw.config.get( 'wgNamespaceNumber' ) === 10 ) { - return true; - } - // Add template editor module - $( 'textarea#wpTextbox1' ).wikiEditor( 'addModule', 'templateEditor' ); -}); +( function ( mw, $ ) { + $( document ).ready( function () { + // Disable in template namespace + if ( mw.config.get( 'wgNamespaceNumber' ) === 10 ) { + return true; + } + // Add template editor module + $( 'textarea#wpTextbox1' ).wikiEditor( 'addModule', 'templateEditor' ); + } ); +}( mediaWiki, jQuery ) ); diff --git a/modules/ext.wikiEditor.tests.toolbar.js b/modules/ext.wikiEditor.tests.toolbar.js index d4ffe5ae..7ed765e9 100644 --- a/modules/ext.wikiEditor.tests.toolbar.js +++ b/modules/ext.wikiEditor.tests.toolbar.js @@ -4,7 +4,7 @@ var textareaId = '#wpTextbox1'; var wikiEditorTests = { // Add emoticons section - add_sections_toolbar: { + 'add_sections_toolbar': { call: 'addToToolbar', data: { 'sections': { @@ -159,8 +159,8 @@ var wikiEditorTests = { data: { section: 'info', page: 'removeme' - }, - test: '*[rel=info].section *[rel=removeme].page', + }, + test: '*[rel=info].section *[rel=removeme].page', pre: 1, post: 0 }, @@ -171,8 +171,8 @@ var wikiEditorTests = { section: 'info', page: 'emoticons', 'character': ':))' - }, - test: '*[rel=info].section *[rel=emoticons].page *[rel=":))"]', + }, + test: '*[rel=info].section *[rel=emoticons].page *[rel=":))"]', pre: 1, post: 0 }, @@ -211,7 +211,7 @@ jQuery(document).ready( function ( $ ) { return false; } - var test, pre, post, + var test, pre, post, i, messages = [ 'Running tests for wikiEditor API' ], $target = $( textareaId ), $ui = $target.data( 'wikiEditor-context' ).$ui, @@ -234,13 +234,13 @@ jQuery(document).ready( function ( $ ) { } if ( window.console ) { - for ( var i = 0; i < messages.length; i++ ) { + for ( i = 0; i < messages.length; i++ ) { window.console.log( messages[i] ); } } $(this) - .attr( 'title', messages.join( " | " ) ) + .attr( 'title', messages.join( ' | ' ) ) .text( passes + ' / ' + tests + ' were successful' ) .css( 'backgroundColor', passes < tests ? 'red' : 'green' ) .data( 'testDone', 'true' ) diff --git a/modules/jquery.wikiEditor.dialogs.config.js b/modules/jquery.wikiEditor.dialogs.config.js index 0d769164..f37d004e 100644 --- a/modules/jquery.wikiEditor.dialogs.config.js +++ b/modules/jquery.wikiEditor.dialogs.config.js @@ -1,6 +1,8 @@ /** * Configuration of Dialog module for wikiEditor */ +/*jshint curly:false, noarg:false, quotmark:false, onevar:false */ +/*global alert */ ( function ( $, mw ) { $.wikiEditor.modules.dialogs.config = { @@ -226,7 +228,7 @@ $.wikiEditor.modules.dialogs.config = { ); } $( '#wikieditor-toolbar-link-type-int, #wikieditor-toolbar-link-type-ext' ).click( function () { - if ( $( '#wikieditor-toolbar-link-type-ext' ).is( ':checked' ) ) { + if ( $( '#wikieditor-toolbar-link-type-ext' ).prop( 'checked' ) ) { // Abort previous request var request = $( '#wikieditor-toolbar-link-int-target-status' ).data( 'request' ); if ( request ) { @@ -234,8 +236,9 @@ $.wikiEditor.modules.dialogs.config = { } updateWidget( 'external' ); } - if ( $( '#wikieditor-toolbar-link-type-int' ).is( ':checked' ) ) + if ( $( '#wikieditor-toolbar-link-type-int' ).prop( 'checked' ) ) { updateExistence( true ); + } }); // Set labels of tabs based on rel values $(this).find( '[rel]' ).each( function () { @@ -250,12 +253,12 @@ $.wikiEditor.modules.dialogs.config = { .data( 'tooltip', mw.msg( 'wikieditor-toolbar-tool-link-int-text-tooltip' ) ); $( '#wikieditor-toolbar-link-int-target, #wikieditor-toolbar-link-int-text' ) .each( function () { - var tooltip = mw.msg( $( this ).attr( 'id' ) + '-tooltip' ); - if ( $( this ).val() === '' ) + if ( $( this ).val() === '' ) { $( this ) .addClass( 'wikieditor-toolbar-dialog-hint' ) .val( $( this ).data( 'tooltip' ) ) .data( 'tooltip-mode', true ); + } } ) .focus( function () { if ( $( this ).val() === $( this ).data( 'tooltip' ) ) { @@ -295,26 +298,30 @@ $.wikiEditor.modules.dialogs.config = { $( '#wikieditor-toolbar-link-type-int' ).prop( 'checked', true ); updateExistence(); } - if ( $( '#wikieditor-toolbar-link-int-text' ).data( 'untouched' ) ) + /*jshint eqeqeq:false */ + if ( $( '#wikieditor-toolbar-link-int-text' ).data( 'untouched' ) ) { if ( $( '#wikieditor-toolbar-link-int-target' ).val() == - $( '#wikieditor-toolbar-link-int-target' ).data( 'tooltip' ) ) { - $( '#wikieditor-toolbar-link-int-text' ) - .addClass( 'wikieditor-toolbar-dialog-hint' ) - .val( $( '#wikieditor-toolbar-link-int-text' ).data( 'tooltip' ) ) - .change(); - } else { - $( '#wikieditor-toolbar-link-int-text' ) - .val( $( '#wikieditor-toolbar-link-int-target' ).val() ) - .change(); - } + $( '#wikieditor-toolbar-link-int-target' ).data( 'tooltip' ) + ) { + $( '#wikieditor-toolbar-link-int-text' ) + .addClass( 'wikieditor-toolbar-dialog-hint' ) + .val( $( '#wikieditor-toolbar-link-int-text' ).data( 'tooltip' ) ) + .change(); + } else { + $( '#wikieditor-toolbar-link-int-text' ) + .val( $( '#wikieditor-toolbar-link-int-target' ).val() ) + .change(); + } + } }, 0 ); }); $( '#wikieditor-toolbar-link-int-text' ).bind( 'change keydown paste cut', function () { var oldVal = $(this).val(); var that = this; setTimeout( function () { - if ( $(that).val() !== oldVal ) + if ( $(that).val() !== oldVal ) { $(that).data( 'untouched', false ); + } }, 0 ); }); // Add images to the page existence widget, which will be shown mutually exclusively to communicate if @@ -379,7 +386,7 @@ $.wikiEditor.modules.dialogs.config = { // Title suggestions $( '#wikieditor-toolbar-link-int-target' ).data( 'suggcache', {} ).suggestions( { - fetch: function ( query ) { + fetch: function () { var that = this; var title = $(this).val(); @@ -608,7 +615,7 @@ $.wikiEditor.modules.dialogs.config = { // Execute the action associated with the first button // when the user presses Enter $(this).closest( '.ui-dialog' ).keypress( function ( e ) { - if ( ( e.keyCode || e.which ) == 13 ) { + if ( ( e.keyCode || e.which ) === 13 ) { var button = $(this).data( 'dialogaction' ) || $(this).find( 'button:first' ); button.click(); e.preventDefault(); @@ -706,7 +713,7 @@ $.wikiEditor.modules.dialogs.config = { // Execute the action associated with the first button // when the user presses Enter $( this ).closest( '.ui-dialog' ).keypress( function ( e ) { - if ( ( e.keyCode || e.which ) == 13 ) { + if ( ( e.keyCode || e.which ) === 13 ) { var button = $( this ).data( 'dialogaction' ) || $( this ).find( 'button:first' ); button.click(); e.preventDefault(); @@ -978,7 +985,7 @@ $.wikiEditor.modules.dialogs.config = { var hiddenHTML = $( '.wikieditor-toolbar-table-preview-hidden' ).html(); $( '.wikieditor-toolbar-table-preview-header' ).html( hiddenHTML ); $( '.wikieditor-toolbar-table-preview-hidden' ).html( headerHTML ); - if ( typeof jQuery.fn.tablesorter == 'function' ) { + if ( typeof jQuery.fn.tablesorter === 'function' ) { $( '#wikieditor-toolbar-table-preview, #wikieditor-toolbar-table-preview2' ) .filter( '.sortable' ) .tablesorter(); @@ -1070,7 +1077,7 @@ $.wikiEditor.modules.dialogs.config = { // Execute the action associated with the first button // when the user presses Enter $(this).closest( '.ui-dialog' ).keypress( function ( e ) { - if ( ( e.keyCode || e.which ) == 13 ) { + if ( ( e.keyCode || e.which ) === 13 ) { var button = $(this).data( 'dialogaction' ) || $(this).find( 'button:first' ); button.click(); e.preventDefault(); @@ -1202,7 +1209,7 @@ $.wikiEditor.modules.dialogs.config = { if ( !match ) { $( '#wikieditor-toolbar-replace-nomatch' ).show(); - } else if ( mode == 'replaceAll' ) { + } else if ( mode === 'replaceAll' ) { // Instead of using repetitive .match() calls, we use one .match() call with /g // and indexOf() followed by substr() to find the offsets. This is actually // faster because our indexOf+substr loop is faster than a match loop, and the @@ -1237,7 +1244,7 @@ $.wikiEditor.modules.dialogs.config = { $(this).data( 'offset', 0 ); } else { - if ( mode == 'replace' ) { + if ( mode === 'replace' ) { var actualReplacement; if (isRegex) { @@ -1330,7 +1337,7 @@ $.wikiEditor.modules.dialogs.config = { // Execute the action associated with the first button // when the user presses Enter $(this).closest( '.ui-dialog' ).keypress( function ( e ) { - if ( ( e.keyCode || e.which ) == 13 ) { + if ( ( e.keyCode || e.which ) === 13 ) { var button = $(this).data( 'dialogaction' ) || $(this).find( 'button:first' ); button.click(); e.preventDefault(); @@ -1350,12 +1357,12 @@ $.wikiEditor.modules.dialogs.config = { $( textbox ) .bind( 'keypress.srdialog', function ( e ) { - if ( e.which == 13 ) { + if ( e.which === 13 ) { // Enter var button = dialog.data( 'dialogaction' ) || dialog.find( 'button:first' ); button.click(); e.preventDefault(); - } else if ( e.which == 27 ) { + } else if ( e.which === 27 ) { // Escape $(that).dialog( 'close' ); } diff --git a/modules/jquery.wikiEditor.dialogs.js b/modules/jquery.wikiEditor.dialogs.js index f6d86d78..6d92966f 100644 --- a/modules/jquery.wikiEditor.dialogs.js +++ b/modules/jquery.wikiEditor.dialogs.js @@ -42,8 +42,8 @@ $.wikiEditor.modules.dialogs = { }, openDialog: function ( context, module ) { if ( module in $.wikiEditor.modules.dialogs.modules ) { - var mod = $.wikiEditor.modules.dialogs.modules[module]; - var $dialog = $( '#' + mod.id ); + var mod = $.wikiEditor.modules.dialogs.modules[module], + $dialog = $( '#' + mod.id ); if ( $dialog.length === 0 ) { $.wikiEditor.modules.dialogs.fn.reallyCreate( context, mod, module ); $dialog = $( '#' + mod.id ); @@ -82,7 +82,7 @@ $.wikiEditor.modules.dialogs = { module = config[mod]; // Only create the dialog if it's supported, isn't filtered and doesn't exist yet filtered = false; - if ( typeof module.filters != 'undefined' ) { + if ( typeof module.filters !== 'undefined' ) { for ( i = 0; i < module.filters.length; i++ ) { if ( $( module.filters[i] ).length === 0 ) { filtered = true; @@ -92,7 +92,7 @@ $.wikiEditor.modules.dialogs = { } // If the dialog already exists, but for another textarea, simply remove it $existingDialog = $( '#' + module.id ); - if ( $existingDialog.length > 0 && $existingDialog.data( 'context' ).$textarea != context.$textarea ) { + if ( $existingDialog.length > 0 && $existingDialog.data( 'context' ).$textarea !== context.$textarea ) { $existingDialog.remove(); } // Re-select from the DOM, we might have removed the dialog just now @@ -119,13 +119,13 @@ $.wikiEditor.modules.dialogs = { * @param {String} name Dialog name (key in $.wikiEditor.modules.dialogs.modules) */ reallyCreate: function ( context, module, name ) { - var msg, + var msg, dialogDiv, configuration = module.dialog; // Add some stuff to configuration configuration.bgiframe = true; configuration.autoOpen = false; // By default our dialogs are modal, unless explicitely defined in their specific configuration. - if( typeof configuration.modal == "undefined" ) { + if( typeof configuration.modal === 'undefined' ) { configuration.modal = true; } configuration.title = $.wikiEditor.autoMsg( module, 'title' ); @@ -138,7 +138,7 @@ $.wikiEditor.modules.dialogs = { } configuration.buttons = configuration.newButtons; // Create the dialog
- var dialogDiv = $( '
' ) + dialogDiv = $( '
' ) .attr( 'id', module.id ) .html( module.html ) .data( 'context', context ) @@ -171,26 +171,28 @@ $.wikiEditor.modules.dialogs = { * NOTE: This function assumes $.ui.dialog has already been loaded */ resize: function () { - var wrapper = $(this).closest( '.ui-dialog' ); - var oldWidth = wrapper.width(); - // Make sure elements don't wrapped so we get an accurate idea of whether they really fit. Also temporarily show - // hidden elements. Work around jQuery bug where
inside a dialog is both - // :visible and :hidden - var oldHidden = $(this).find( '*' ).not( ':visible' ); + var oldWS, thisWidth, wrapperWidth, + wrapper = $(this).closest( '.ui-dialog' ), + oldWidth = wrapper.width(), + // Make sure elements don't wrapped so we get an accurate idea of whether they really fit. Also temporarily show + // hidden elements. Work around jQuery bug where
inside a dialog is both + // :visible and :hidden + oldHidden = $(this).find( '*' ).not( ':visible' ); + // Save the style attributes of the hidden elements to restore them later. Calling hide() after show() messes up // for elements hidden with a class oldHidden.each( function () { $(this).data( 'oldstyle', $(this).attr( 'style' ) ); }); oldHidden.show(); - var oldWS = $(this).css( 'white-space' ); + oldWS = $(this).css( 'white-space' ); $(this).css( 'white-space', 'nowrap' ); if ( wrapper.width() <= $(this).get(0).scrollWidth ) { - var thisWidth = $(this).data( 'thisWidth' ) ? $(this).data( 'thisWidth' ) : 0; + thisWidth = $(this).data( 'thisWidth' ) ? $(this).data( 'thisWidth' ) : 0; thisWidth = Math.max( $(this).get(0).width, thisWidth ); $(this).width( thisWidth ); $(this).data( 'thisWidth', thisWidth ); - var wrapperWidth = $(this).data( 'wrapperWidth' ) ? $(this).data( 'wrapperWidth' ) : 0; + wrapperWidth = $(this).data( 'wrapperWidth' ) ? $(this).data( 'wrapperWidth' ) : 0; wrapperWidth = Math.max( wrapper.get(0).scrollWidth, wrapperWidth ); wrapper.width( wrapperWidth ); $(this).data( 'wrapperWidth', wrapperWidth ); diff --git a/modules/jquery.wikiEditor.highlight.js b/modules/jquery.wikiEditor.highlight.js index 9d964fa7..f646e456 100644 --- a/modules/jquery.wikiEditor.highlight.js +++ b/modules/jquery.wikiEditor.highlight.js @@ -20,13 +20,21 @@ $.wikiEditor.modules.highlight = { * Internally used event handlers */ evt: { + /** + * @param context + * @param event + */ delayedChange: function ( context, event ) { - if ( event.data.scope == 'realchange' ) { + if ( event.data.scope === 'realchange' ) { $.wikiEditor.modules.highlight.fn.scan( context ); $.wikiEditor.modules.highlight.fn.mark( context, event.data.scope ); } }, - ready: function ( context, event ) { + /** + * @param context + * @param event + */ + ready: function ( context ) { $.wikiEditor.modules.highlight.fn.scan( context ); $.wikiEditor.modules.highlight.fn.mark( context, 'ready' ); } @@ -39,19 +47,22 @@ $.wikiEditor.modules.highlight = { /** * Creates a highlight module within a wikiEditor * + * @param context * @param config Configuration object to create module from */ - create: function ( context, config ) { + create: function ( context ) { context.modules.highlight.markersStr = ''; }, /** * Scans text division for tokens * + * @param context * @param division */ - scan: function ( context, division ) { + scan: function ( context ) { var tokenArray, text, module, exp, - left, right, match; + left, right, match, + regex, label, markAfter, offset; /*jshint eqnull: true */ // Remove all existing tokens @@ -65,11 +76,11 @@ $.wikiEditor.modules.highlight = { if ( module in $.wikiEditor.modules && 'exp' in $.wikiEditor.modules[module] ) { for ( exp in $.wikiEditor.modules[module].exp ) { // Prepare configuration - var regex = $.wikiEditor.modules[module].exp[exp].regex; - var label = $.wikiEditor.modules[module].exp[exp].label; - var markAfter = $.wikiEditor.modules[module].exp[exp].markAfter || false; + regex = $.wikiEditor.modules[module].exp[exp].regex; + label = $.wikiEditor.modules[module].exp[exp].label; + markAfter = $.wikiEditor.modules[module].exp[exp].markAfter || false; // Search for tokens - var offset = 0; + offset = 0; while ( ( match = text.substr( offset ).match( regex ) ) != null ) { right = ( left = offset + match.index ) + match[0].length; tokenArray[tokenArray.length] = { @@ -95,16 +106,19 @@ $.wikiEditor.modules.highlight = { /** * Marks up text with HTML * + * @param context * @param division * @param tokens */ // FIXME: What do division and tokens do? // TODO: Document the scan() and mark() APIs somewhere - mark: function ( context, division, tokens ) { - var i, subtracted, oldLength, j, o; + mark: function ( context, division ) { + /*jshint eqeqeq:false, onevar:false */ + var i, subtracted, oldLength, j, o, + markers; // Reset markers - var markers = []; + markers = []; // Recycle markers that will be skipped in this run if ( context.modules.highlight.markers && division !== '' ) { @@ -353,8 +367,9 @@ $.wikiEditor.modules.highlight = { // Don't remove these either return true; } - if ( marker && typeof marker.beforeUnwrap === 'function' ) + if ( marker && typeof marker.beforeUnwrap === 'function' ) { marker.beforeUnwrap( this ); + } if ( ( marker && marker.anchor === 'tag' ) || $(this).is( 'p' ) ) { // Remove all classes $(this).removeAttr( 'class' ); diff --git a/modules/jquery.wikiEditor.iframe.js b/modules/jquery.wikiEditor.iframe.js index 4e01a64a..cb21debc 100644 --- a/modules/jquery.wikiEditor.iframe.js +++ b/modules/jquery.wikiEditor.iframe.js @@ -1,6 +1,6 @@ /* IFrame extension for wikiEditor */ - -( function ( $ ) { $.wikiEditor.extensions.iframe = function( context ) { +/*jshint onevar:false, boss:true */ +( function ( $ ) { $.wikiEditor.extensions.iframe = function ( context ) { /* * Event Handlers @@ -14,18 +14,18 @@ context.evt = $.extend( context.evt, { * function is to both classify the scope of changes as 'division' or 'character' and to prevent further * processing of events which did not actually change the content of the iframe. */ - 'keydown': function( event ) { + keydown: function ( event ) { switch ( event.which ) { case 90: // z case 89: // y - if ( event.which == 89 && !$.browser.msie ) { + if ( event.which === 89 && !$.browser.msie ) { // only handle y events for IE return true; } else if ( ( event.ctrlKey || event.metaKey ) && context.history.length ) { // HistoryPosition is a negative number between -1 and -context.history.length, in other words // it's the number of steps backwards from the latest state. var newPosition; - if ( event.shiftKey || event.which == 89 ) { + if ( event.shiftKey || event.which === 89 ) { // Redo newPosition = context.historyPosition + 1; } else { @@ -35,7 +35,7 @@ context.evt = $.extend( context.evt, { // Only act if we are switching to a valid state if ( newPosition >= ( context.history.length * -1 ) && newPosition < 0 ) { // Make sure we run the history storing code before we make this change - context.fn.updateHistory( context.oldDelayedHTML != context.$content.html() ); + context.fn.updateHistory( context.oldDelayedHTML !== context.$content.html() ); context.oldDelayedHistoryPosition = context.historyPosition; context.historyPosition = newPosition; // Change state @@ -65,8 +65,8 @@ context.evt = $.extend( context.evt, { var $tabindexList = $( '[tabindex]:visible' ).sort( function( a, b ) { return a.tabIndex - b.tabIndex; } ); - for( var i=0; i < $tabindexList.length; i++ ) { - if( $tabindexList.eq( i ).attr( 'id' ) == context.$iframe.attr( 'id' ) ) { + for ( var i=0; i < $tabindexList.length; i++ ) { + if ( $tabindexList.eq( i ).attr( 'id' ) === context.$iframe.attr( 'id' ) ) { $tabindexList.get( i + 1 ).focus(); break; } @@ -74,48 +74,48 @@ context.evt = $.extend( context.evt, { return false; } break; - case 86: //v - if ( event.ctrlKey && $.browser.msie && 'paste' in context.evt ) { - //paste, intercepted for IE - context.evt.paste( event ); - } - break; + case 86: //v + if ( event.ctrlKey && $.browser.msie && 'paste' in context.evt ) { + //paste, intercepted for IE + context.evt.paste( event ); + } + break; } return true; }, - 'change': function( event ) { + change: function ( event ) { event.data.scope = 'division'; var newHTML = context.$content.html(); - if ( context.oldHTML != newHTML ) { + if ( context.oldHTML !== newHTML ) { context.fn.purgeOffsets(); context.oldHTML = newHTML; event.data.scope = 'realchange'; } // Never let the body be totally empty - if ( context.$content.children().length == 0 ) { + if ( context.$content.children().length === 0 ) { context.$content.append( '

' ); } return true; }, - 'delayedChange': function( event ) { + delayedChange: function ( event ) { event.data.scope = 'division'; var newHTML = context.$content.html(); - if ( context.oldDelayedHTML != newHTML ) { + if ( context.oldDelayedHTML !== newHTML ) { context.oldDelayedHTML = newHTML; event.data.scope = 'realchange'; // Surround by

if it does not already have it var cursorPos = context.fn.getCaretPosition(); var t = context.fn.getOffset( cursorPos[0] ); - if ( ! $.browser.msie && t && t.node.nodeName == '#text' && t.node.parentNode.nodeName.toLowerCase() == 'body' ) { - $( t.node ).wrap( "

" ); + if ( ! $.browser.msie && t && t.node.nodeName === '#text' && t.node.parentNode.nodeName.toLowerCase() === 'body' ) { + $( t.node ).wrap( '

' ); context.fn.purgeOffsets(); context.fn.setSelection( { start: cursorPos[0], end: cursorPos[1] } ); } } - context.fn.updateHistory( event.data.scope == 'realchange' ); + context.fn.updateHistory( event.data.scope === 'realchange' ); return true; }, - 'cut': function( event ) { + cut: function ( event ) { setTimeout( function() { context.$content.find( 'br' ).each( function() { if ( $(this).parent().is( 'body' ) ) { @@ -125,7 +125,7 @@ context.evt = $.extend( context.evt, { }, 100 ); return true; }, - 'paste': function( event ) { + paste: function ( event ) { // Save the cursor position to restore it after all this voodoo var cursorPos = context.fn.getCaretPosition(); var oldLength = context.fn.getContents().length; @@ -138,6 +138,7 @@ context.evt = $.extend( context.evt, { } setTimeout( function() { + /*jshint eqnull:true */ // Kill stuff we know we don't want context.$content.find( 'script,style,img,input,select,textarea,hr,button,link,meta' ).remove(); var nodeToDelete = []; @@ -152,30 +153,31 @@ context.evt = $.extend( context.evt, { } if ( elementAtCursor == null || elementAtCursor.node == null ) { context.$content.prepend( '

' ); - firstDirtyNode = context.$content.children()[0]; + firstDirtyNode = context.$content.children()[0]; } else { firstDirtyNode = elementAtCursor.node; } - //this is ugly but seems like the best way to handle the case where we select and replace all editor contents + // This is ugly but seems like the best way to handle the case where we select and replace all editor contents try { + /*jshint expr:true */ firstDirtyNode.parentNode; } catch ( err ) { context.$content.prepend( '

' ); - firstDirtyNode = context.$content.children()[0]; + firstDirtyNode = context.$content.children()[0]; } while ( firstDirtyNode != null ) { //we're going to replace the contents of the entire parent node. - while ( firstDirtyNode.parentNode && firstDirtyNode.parentNode.nodeName != 'BODY' - && ! $( firstDirtyNode ).hasClass( 'wikiEditor' ) - ) { + while ( firstDirtyNode.parentNode && firstDirtyNode.parentNode.nodeName !== 'BODY' && + !$( firstDirtyNode ).hasClass( 'wikiEditor' ) + ) { firstDirtyNode = firstDirtyNode.parentNode; } //go back till we find the first pasted node - while ( firstDirtyNode.previousSibling != null - && ! $( firstDirtyNode.previousSibling ).hasClass( 'wikiEditor' ) - ) { + while ( firstDirtyNode.previousSibling != null && + !$( firstDirtyNode.previousSibling ).hasClass( 'wikiEditor' ) + ) { if ( $( firstDirtyNode.previousSibling ).hasClass( '#comment' ) ) { $( firstDirtyNode ).remove(); @@ -185,9 +187,9 @@ context.evt = $.extend( context.evt, { } if ( firstDirtyNode.previousSibling != null ) { - $lastDirtyNode = $( firstDirtyNode.previousSibling ); + $lastDirtyNode = $( firstDirtyNode.previousSibling ); } else { - $lastDirtyNode = $( firstDirtyNode ); + $lastDirtyNode = $( firstDirtyNode ); } var cc = makeContentCollector( $.browser, null ); @@ -218,7 +220,7 @@ context.evt = $.extend( context.evt, { } - if( !pastedPretty && $.browser.msie && i == 0 ) { + if ( !pastedPretty && $.browser.msie && i === 0 ) { continue; } $newElement = $( '

' ); @@ -241,7 +243,7 @@ context.evt = $.extend( context.evt, { //anything without wikiEditor class was pasted. $selection = context.$content.find( ':not(.wikiEditor)' ); - if ( $selection.length == 0 ) { + if ( $selection.length === 0 ) { break; } else { firstDirtyNode = $selection.eq( 0 )[0]; @@ -260,7 +262,7 @@ context.evt = $.extend( context.evt, { }, 0 ); return true; }, - 'ready': function( event ) { + ready: function ( event ) { // Initialize our history queue if ( context.$content ) { context.history.push( { 'html': context.$content.html(), 'sel': context.fn.getCaretPosition() } ); @@ -275,7 +277,7 @@ context.evt = $.extend( context.evt, { * Internally used functions */ context.fn = $.extend( context.fn, { - 'highlightLine': function( $element, mode ) { + highlightLine: function ( highlightLine ) { if ( !$element.is( 'p' ) ) { $element = $element.closest( 'p' ); } @@ -283,7 +285,7 @@ context.fn = $.extend( context.fn, { setTimeout( function() { $element.animate( { 'backgroundColor': 'white' }, 'slow' ); }, 100 ); setTimeout( function() { $element.css( 'backgroundColor', 'white' ); }, 1000 ); }, - 'htmlToText': function( html ) { + htmlToText: function ( htmlToText ) { // This function is slow for large inputs, so aggressively cache input/output pairs if ( html in context.htmlToTextMap ) { return context.htmlToTextMap[html]; @@ -294,15 +296,15 @@ context.fn = $.extend( context.fn, { // IE does overzealous whitespace collapsing for $( '
' ).html( html );
 		// We also do 
and easy cases for

conversion here, complicated cases are handled later html = html - .replace( /\r?\n/g, "" ) // IE7 inserts newlines before block elements - .replace( / /g, " " ) // We inserted these to prevent IE from collapsing spaces - .replace( /\]*\>\<\/p\>/gi, '

' ) // Remove trailing
from

- .replace( /\<\/p\>\s*\]*\>/gi, "\n" ) // Easy case for

conversion - .replace( /\]*\>/gi, "\n" ) //
conversion - .replace( /\<\/p\>(\n*)\]*\>/gi, "$1\n" ) + .replace( /\r?\n/g, '' ) // IE7 inserts newlines before block elements + .replace( / /g, ' ' ) // We inserted these to prevent IE from collapsing spaces + .replace( /]*\><\/p\>/gi, '

' ) // Remove trailing
from

+ .replace( /<\/p\>\s*]*\>/gi, '\n' ) // Easy case for

conversion + .replace( /]*\>/gi, '\n' ) //
conversion + .replace( /<\/p\>(\n*)]*\>/gi, '$1\n' ) // Un-nest

tags - .replace( /\]*\>]*\>/gi, '

' ) - .replace( /\<\/p\><\/p\>/gi, '

' ); + .replace( /]*\>]*\>/gi, '

' ) + .replace( /<\/p\><\/p\>/gi, '

' ); // Save leading and trailing whitespace now and restore it later. IE eats it all, and even Firefox // won't leave everything alone var leading = html.match( /^\s*/ )[0]; @@ -311,8 +313,8 @@ context.fn = $.extend( context.fn, { var $pre = $( '
' + html + '
' ); $pre.find( '.wikiEditor-noinclude' ).each( function() { $( this ).remove(); } ); // Convert tabs,

s and
s back - $pre.find( '.wikiEditor-tab' ).each( function() { $( this ).text( "\t" ); } ); - $pre.find( 'br' ).each( function() { $( this ).replaceWith( "\n" ); } ); + $pre.find( '.wikiEditor-tab' ).each( function() { $( this ).text( '\t' ); } ); + $pre.find( 'br' ).each( function() { $( this ).replaceWith( '\n' ); } ); // Converting

s is wrong if there's nothing before them, so check that. // .find( '* + p' ) isn't good enough because textnodes aren't considered $pre.find( 'p' ).each( function() { @@ -323,21 +325,21 @@ context.fn = $.extend( context.fn, { // Check for preceding text var t = new context.fn.rawTraverser( this.firstChild, this, $pre.get( 0 ), true ).prev(); - while ( t && t.node.nodeName != '#text' && t.node.nodeName != 'BR' && t.node.nodeName != 'P' ) { + while ( t && t.node.nodeName !== '#text' && t.node.nodeName !== 'BR' && t.node.nodeName !== 'P' ) { t = t.prev(); } if ( t ) { - text = "\n" + text; + text = '\n' + text; } // Check for following text t = new context.fn.rawTraverser( this.lastChild, this, $pre.get( 0 ), true ).next(); - while ( t && t.node.nodeName != '#text' && t.node.nodeName != 'BR' && t.node.nodeName != 'P' ) { + while ( t && t.node.nodeName !== '#text' && t.node.nodeName !== 'BR' && t.node.nodeName !== 'P' ) { t = t.next(); } - if ( t && !t.inP && t.node.nodeName == '#text' && t.node.nodeValue.charAt( 0 ) != '\n' - && t.node.nodeValue.charAt( 0 ) != '\r' ) { - text += "\n"; + if ( t && !t.inP && t.node.nodeName === '#text' && t.node.nodeValue.charAt( 0 ) !== '\n' && + t.node.nodeValue.charAt( 0 ) !== '\r' ) { + text += '\n'; } $( this ).text( text ); } ); @@ -357,8 +359,8 @@ context.fn = $.extend( context.fn, { * @param strict If true, the element the selection starts in cannot match (default: false) * @return jQuery object or null if unknown */ - 'beforeSelection': function( classname, strict ) { - if ( typeof classname == 'undefined' ) { + beforeSelection: function ( beforeSelection ) { + if ( typeof classname === 'undefined' ) { classname = ''; } var e = null, offset = null; @@ -381,7 +383,7 @@ context.fn = $.extend( context.fn, { // When the cursor is on an empty line, Opera gives us a bogus range object with // startContainer=endContainer=body and startOffset=endOffset=1 var body = context.$iframe[0].contentWindow.document.body; - if ( $.browser.opera && e == body && offset == 1 ) { + if ( $.browser.opera && e === body && offset === 1 ) { return null; } } @@ -400,14 +402,14 @@ context.fn = $.extend( context.fn, { return null; } var seekPos = context.fn.htmlToText( range2.htmlText ).length; - var offset = context.fn.getOffset( seekPos ); + offset = context.fn.getOffset( seekPos ); e = offset ? offset.node : null; offset = offset ? offset.offset : null; if ( !e ) { return null; } } - if ( e.nodeName != '#text' ) { + if ( e.nodeName !== '#text' ) { // The selection is not in a textnode, but between two non-text nodes // (usually inside the between two
s). Go to the rightmost // child of the node just before the selection @@ -425,7 +427,7 @@ context.fn = $.extend( context.fn, { // constructor thousands of times is very inefficient var classStr = ' ' + classname + ' '; while ( e ) { - if ( !strict && ( !classname || ( ' ' + e.className + ' ' ).indexOf( classStr ) != -1 ) ) { + if ( !strict && ( !classname || ( ' ' + e.className + ' ' ).indexOf( classStr ) !== -1 ) ) { return $( e ); } var next = e.previousSibling; @@ -440,7 +442,7 @@ context.fn = $.extend( context.fn, { /** * Object used by traverser(). Don't use this unless you know what you're doing */ - 'rawTraverser': function( node, inP, ancestor, skipNoinclude ) { + rawTraverser: function ( rawTraverser ) { this.node = node; this.inP = inP; this.ancestor = ancestor; @@ -450,16 +452,16 @@ context.fn = $.extend( context.fn, { var nextInP = this.inP; while ( p && !p.nextSibling ) { p = p.parentNode; - if ( p == this.ancestor ) { + if ( p === this.ancestor ) { // We're back at the ancestor, stop here p = null; } - if ( p && p.nodeName == "P" ) { + if ( p && p.nodeName === 'P' ) { nextInP = null; } } p = p ? p.nextSibling : null; - if ( p && p.nodeName == "P" ) { + if ( p && p.nodeName === 'P' ) { nextInP = p; } do { @@ -467,13 +469,13 @@ context.fn = $.extend( context.fn, { // Don't use $( p ).hasClass( 'wikiEditor-noinclude' ) because // $() is slow in a tight loop if ( this.skipNoinclude ) { - while ( p && ( ' ' + p.className + ' ' ).indexOf( ' wikiEditor-noinclude ' ) != -1 ) { + while ( p && ( ' ' + p.className + ' ' ).indexOf( ' wikiEditor-noinclude ' ) !== -1 ) { p = p.nextSibling; } } if ( p && p.firstChild ) { p = p.firstChild; - if ( p.nodeName == "P" ) { + if ( p.nodeName === 'P' ) { nextInP = p; } } @@ -487,16 +489,16 @@ context.fn = $.extend( context.fn, { var prevInP = this.inP; while ( p && !p.previousSibling ) { p = p.parentNode; - if ( p == this.ancestor ) { + if ( p === this.ancestor ) { // We're back at the ancestor, stop here p = null; } - if ( p && p.nodeName == "P" ) { + if ( p && p.nodeName === 'P' ) { prevInP = null; } } p = p ? p.previousSibling : null; - if ( p && p.nodeName == "P" ) { + if ( p && p.nodeName === 'P' ) { prevInP = p; } do { @@ -510,7 +512,7 @@ context.fn = $.extend( context.fn, { } if ( p && p.lastChild ) { p = p.lastChild; - if ( p.nodeName == "P" ) { + if ( p.nodeName == 'P' ) { prevInP = p; } } @@ -528,11 +530,11 @@ context.fn = $.extend( context.fn, { * @return Traverser object, use .next() or .prev() to get a traverser object referring to the * previous/next node */ - 'traverser': function( start ) { + traverser: function ( traverser ) { // Find the leftmost leaf node in the tree var startNode = start.jquery ? start.get( 0 ) : start; var node = startNode; - var inP = node.nodeName == "P" ? node : null; + var inP = node.nodeName == 'P' ? node : null; do { // Filter nodes with the wikiEditor-noinclude class // Don't use $( p ).hasClass( 'wikiEditor-noinclude' ) because @@ -542,14 +544,14 @@ context.fn = $.extend( context.fn, { } if ( node && node.firstChild ) { node = node.firstChild; - if ( node.nodeName == "P" ) { + if ( node.nodeName == 'P' ) { inP = node; } } } while ( node && node.firstChild ); return new context.fn.rawTraverser( node, inP, startNode, true ); }, - 'getOffset': function( offset ) { + getOffset: function ( getOffset ) { if ( !context.offsets ) { context.fn.refreshOffsets(); } @@ -578,21 +580,21 @@ context.fn = $.extend( context.fn, { 'lastTextNode': base.lastTextNode }; }, - 'purgeOffsets': function() { + purgeOffsets: function () { context.offsets = null; }, - 'refreshOffsets': function() { + refreshOffsets: function () { context.offsets = [ ]; var t = context.fn.traverser( context.$content ); var pos = 0, lastTextNode = null; while ( t ) { - if ( t.node.nodeName != '#text' && t.node.nodeName != 'BR' ) { + if ( t.node.nodeName !== '#text' && t.node.nodeName !== 'BR' ) { t = t.next(); continue; } - var nextPos = t.node.nodeName == '#text' ? pos + t.node.nodeValue.length : pos + 1; + var nextPos = t.node.nodeName === '#text' ? pos + t.node.nodeValue.length : pos + 1; var nextT = t.next(); - var leavingP = t.node.nodeName == '#text' && t.inP && nextT && ( !nextT.inP || nextT.inP != t.inP ); + var leavingP = t.node.nodeName === '#text' && t.inP && nextT && ( !nextT.inP || nextT.inP !== t.inP ); context.offsets[pos] = { 'node': t.node, 'offset': 0, @@ -610,27 +612,27 @@ context.fn = $.extend( context.fn, { }; } pos = nextPos + ( leavingP ? 1 : 0 ); - if ( t.node.nodeName == '#text' ) { + if ( t.node.nodeName === '#text' ) { lastTextNode = t.node; } t = nextT; } }, - 'saveCursorAndScrollTop': function() { + saveCursorAndScrollTop: function () { // Stub out textarea behavior return; }, - 'restoreCursorAndScrollTop': function() { + restoreCursorAndScrollTop: function () { // Stub out textarea behavior return; }, - 'saveSelection': function() { + saveSelection: function () { if ( $.client.profile().name === 'msie' ) { context.$iframe[0].contentWindow.focus(); context.savedSelection = context.$iframe[0].contentWindow.document.selection.createRange(); } }, - 'restoreSelection': function() { + restoreSelection: function () { if ( $.client.profile().name === 'msie' && context.savedSelection !== null ) { context.$iframe[0].contentWindow.focus(); context.savedSelection.select(); @@ -643,7 +645,7 @@ context.fn = $.extend( context.fn, { * @param htmlChange pass true or false to inidicate if there was a text change that should potentially * be given a new history state. */ - 'updateHistory': function( htmlChange ) { + updateHistory: function ( updateHistory ) { var newHTML = context.$content.html(); var newSel = context.fn.getCaretPosition(); // Was text changed? Was it because of a REDO or UNDO action? @@ -675,7 +677,7 @@ context.fn = $.extend( context.fn, { /** * Sets up the iframe in place of the textarea to allow more advanced operations */ - 'setupIframe': function() { + setupIframe: function () { context.$iframe = $( '' ) .attr( { 'frameBorder': 0, @@ -834,7 +836,7 @@ context.fn = $.extend( context.fn, { * equivilant functionality to the otherwise textarea-based functionality. */ - 'getElementAtCursor': function() { + getElementAtCursor: function () { if ( context.$iframe[0].contentWindow.getSelection ) { // Firefox and Opera var selection = context.$iframe[0].contentWindow.getSelection(); @@ -855,7 +857,7 @@ context.fn = $.extend( context.fn, { /** * Gets the complete contents of the iframe (in plain text, not HTML) */ - 'getContents': function() { + getContents: function () { // For

, .html() returns

 

in IE // This seems to convince IE while not affecting display if ( !context.$content ) { @@ -880,7 +882,7 @@ context.fn = $.extend( context.fn, { * Gets the currently selected text in the content * DO NOT CALL THIS DIRECTLY, use $.textSelection( 'functionname', options ) instead */ - 'getSelection': function() { + getSelection: function () { var retval; if ( context.$iframe[0].contentWindow.getSelection ) { // Firefox and Opera @@ -915,7 +917,7 @@ context.fn = $.extend( context.fn, { * selection is empty. * DO NOT CALL THIS DIRECTLY, use $.textSelection( 'functionname', options ) instead */ - 'encapsulateSelection': function( options ) { + encapsulateSelection: function ( encapsulateSelection ) { var selText = $(this).textSelection( 'getSelection' ); var selTextArr; var collapseToEnd = false; @@ -1127,7 +1129,7 @@ context.fn = $.extend( context.fn, { * Gets the position (in resolution of bytes not nessecarily characters) in a textarea * DO NOT CALL THIS DIRECTLY, use $.textSelection( 'functionname', options ) instead */ - 'getCaretPosition': function( options ) { + getCaretPosition: function ( getCaretPosition ) { var startPos = null, endPos = null; if ( context.$iframe[0].contentWindow.getSelection ) { var selection = context.$iframe[0].contentWindow.getSelection(); @@ -1264,7 +1266,7 @@ context.fn = $.extend( context.fn, { * @param startContainer Element in iframe to start selection in. If not set, start is a character offset * @param endContainer Element in iframe to end selection in. If not set, end is a character offset */ - 'setSelection': function( options ) { + setSelection: function ( setSelection ) { var sc = options.startContainer, ec = options.endContainer; sc = sc && sc.jquery ? sc[0] : sc; ec = ec && ec.jquery ? ec[0] : ec; @@ -1351,7 +1353,7 @@ context.fn = $.extend( context.fn, { * Scroll a textarea to the current cursor position. You can set the cursor position with setSelection() * DO NOT CALL THIS DIRECTLY, use $.textSelection( 'functionname', options ) instead */ - 'scrollToCaretPosition': function( options ) { + scrollToCaretPosition: function ( scrollToCaretPosition ) { context.fn.scrollToTop( context.fn.getElementAtCursor(), true ); }, /** @@ -1361,7 +1363,7 @@ context.fn = $.extend( context.fn, { * @param $element jQuery object containing an element in the iframe * @param force If true, scroll the element even if it's already visible */ - 'scrollToTop': function( $element, force ) { + scrollToTop: function ( scrollToTop ) { var html = context.$content.closest( 'html' ), body = context.$content.closest( 'body' ), parentHtml = $( 'html' ), diff --git a/modules/jquery.wikiEditor.js b/modules/jquery.wikiEditor.js index def8b69e..460203ff 100644 --- a/modules/jquery.wikiEditor.js +++ b/modules/jquery.wikiEditor.js @@ -8,7 +8,8 @@ * $( 'textarea#wpTextbox1' ).wikiEditor( 'addModule', 'toolbar', { ... config ... } ); * */ -( function ( $ ) { +/*jshint onevar:false, boss:true */ +( function ( $, mw ) { /** * Global static object for wikiEditor that provides generally useful functionality to all modules and contexts. @@ -113,7 +114,7 @@ $.wikiEditor = { isRequired: function ( module, requirement ) { if ( typeof module.req !== 'undefined' ) { for ( var req in module.req ) { - if ( module.req[req] == requirement ) { + if ( module.req[req] === requirement ) { return true; } } @@ -132,9 +133,10 @@ $.wikiEditor = { * with the key 'bar'. */ autoMsg: function ( object, property ) { + var i, p; // Accept array of possible properties, of which the first one found will be used - if ( typeof property == 'object' ) { - for ( var i in property ) { + if ( typeof property === 'object' ) { + for ( i in property ) { if ( property[i] in object || property[i] + 'Msg' in object ) { property = property[i]; break; @@ -144,11 +146,11 @@ $.wikiEditor = { if ( property in object ) { return object[property]; } else if ( property + 'Msg' in object ) { - var p = object[property + 'Msg']; + p = object[property + 'Msg']; if ( $.isArray( p ) && p.length >= 2 ) { - return mediaWiki.message.apply( mediaWiki.message, p ).plain(); + return mw.message.apply( mw.message, p ).plain(); } else { - return mediaWiki.message( p ).plain(); + return mw.message( p ).plain(); } } else { return ''; @@ -181,7 +183,7 @@ $.wikiEditor = { var src = $.wikiEditor.autoLang( icon, lang ); path = path || $.wikiEditor.imgPath; // Prepend path if src is not absolute - if ( src.substr( 0, 7 ) != 'http://' && src.substr( 0, 8 ) != 'https://' && src[0] != '/' ) { + if ( src.substr( 0, 7 ) !== 'http://' && src.substr( 0, 8 ) !== 'https://' && src[0] !== '/' ) { src = path + src; } return src + '?' + mw.loader.version( 'jquery.wikiEditor' ); @@ -197,9 +199,9 @@ $.wikiEditor = { */ autoIconOrOffset: function ( icon, offset, path, lang ) { lang = lang || mw.config.get( 'wgUserLanguage' ); - if ( typeof offset == 'object' && lang in offset ) { + if ( typeof offset === 'object' && lang in offset ) { return offset[lang]; - } else if ( typeof icon == 'object' && lang in icon ) { + } else if ( typeof icon === 'object' && lang in icon ) { return $.wikiEditor.autoIcon( icon, undefined, lang ); } else { return $.wikiEditor.autoLang( offset, lang ); @@ -223,7 +225,7 @@ if ( !$.wikiEditor.isSupported() ) { // where we left off var context = $(this).data( 'wikiEditor-context' ); // On first call, we need to set things up, but on all following calls we can skip right to the API handling -if ( !context || typeof context == 'undefined' ) { +if ( !context || typeof context === 'undefined' ) { // Star filling the context with useful data - any jQuery selections, as usual should be named with a preceding $ context = { @@ -276,14 +278,14 @@ if ( !context || typeof context == 'undefined' ) { 'addModule': function ( context, data ) { var module, call, modules = {}; - if ( typeof data == 'string' ) { + if ( typeof data === 'string' ) { modules[data] = {}; - } else if ( typeof data == 'object' ) { + } else if ( typeof data === 'object' ) { modules = data; } for ( module in modules ) { // Check for the existance of an available / supported module with a matching name and a create function - if ( typeof module == 'string' && typeof $.wikiEditor.modules[module] !== 'undefined' && + if ( typeof module === 'string' && typeof $.wikiEditor.modules[module] !== 'undefined' && $.wikiEditor.isSupported( $.wikiEditor.modules[module] ) ) { // Extend the context's core API with this module's own API calls @@ -326,11 +328,11 @@ if ( !context || typeof context == 'undefined' ) { */ trigger: function ( name, event ) { // Event is an optional argument, but from here on out, at least the type field should be dependable - if ( typeof event == 'undefined' ) { + if ( typeof event === 'undefined' ) { event = { 'type': 'custom' }; } // Ensure there's a place for extra information to live - if ( typeof event.data == 'undefined' ) { + if ( typeof event.data === 'undefined' ) { event.data = {}; } @@ -393,7 +395,7 @@ if ( !context || typeof context == 'undefined' ) { // Return the newly appended tab return $( '
' ) .attr( 'rel', 'wikiEditor-ui-view-' + options.name ) - .addClass( context.view == options.name ? 'current' : null ) + .addClass( context.view === options.name ? 'current' : null ) .append( $( '' ) .attr( 'href', '#' ) .mousedown( function () { @@ -406,7 +408,7 @@ if ( !context || typeof context == 'undefined' ) { context.$tabs.find( 'div' ).removeClass( 'current' ); $(this).parent().addClass( 'current' ); $(this).blur(); - if ( 'init' in options && typeof options.init == 'function' ) { + if ( 'init' in options && typeof options.init === 'function' ) { options.init( context ); } event.preventDefault(); @@ -539,9 +541,9 @@ if ( !context || typeof context == 'undefined' ) { var args = $.makeArray( arguments ); // Dynamically setup core extensions for modules that are required -if ( args[0] == 'addModule' && typeof args[1] !== 'undefined' ) { +if ( args[0] === 'addModule' && typeof args[1] !== 'undefined' ) { var modules = args[1]; - if ( typeof modules !== "object" ) { + if ( typeof modules !== 'object' ) { modules = {}; modules[args[1]] = ''; } @@ -577,4 +579,4 @@ return $(this).data( 'wikiEditor-context', context ); }; -}( jQuery ) ); +}( jQuery, mediaWiki ) ); diff --git a/modules/jquery.wikiEditor.preview.js b/modules/jquery.wikiEditor.preview.js index 39907364..372d2e8e 100644 --- a/modules/jquery.wikiEditor.preview.js +++ b/modules/jquery.wikiEditor.preview.js @@ -1,6 +1,6 @@ /* Preview module for wikiEditor */ ( function ( $, mw ) { - +/*jshint onevar:false */ $.wikiEditor.modules.preview = { /** @@ -32,7 +32,7 @@ fn: { * @param context Context object of editor to create module in * @param config Configuration object to create module from */ - create: function ( context, config ) { + create: function ( context ) { if ( 'initialized' in context.modules.preview ) { return; } @@ -65,9 +65,9 @@ fn: { }, function ( data ) { if ( - typeof data.parse == 'undefined' || - typeof data.parse.text == 'undefined' || - typeof data.parse.text['*'] == 'undefined' + typeof data.parse === 'undefined' || + typeof data.parse.text === 'undefined' || + typeof data.parse.text['*'] === 'undefined' ) { return; } @@ -89,7 +89,7 @@ fn: { // Gets the latest copy of the wikitext var wikitext = context.$textarea.textSelection( 'getContents' ); // Aborts when nothing has changed since the last time - if ( context.modules.preview.changesText == wikitext ) { + if ( context.modules.preview.changesText === wikitext ) { return; } context.$changesTab.find( 'table.diff tbody' ).empty(); @@ -115,8 +115,9 @@ fn: { rvprop: '' }; var section = $( '[name="wpSection"]' ).val(); - if ( section !== '' ) + if ( section !== '' ) { postdata2.rvsection = section; + } $.post( mw.util.wikiScript( 'api' ), postdata2, function ( data ) { // Add diff CSS diff --git a/modules/jquery.wikiEditor.previewDialog.js b/modules/jquery.wikiEditor.previewDialog.js index 2e3cc2a8..5381e605 100644 --- a/modules/jquery.wikiEditor.previewDialog.js +++ b/modules/jquery.wikiEditor.previewDialog.js @@ -1,5 +1,6 @@ /* Publish module for wikiEditor */ -( function ( $ ) { $.wikiEditor.modules.previewDialog = { +/*jshint onevar:false */ +( function ( $, mw ) { $.wikiEditor.modules.previewDialog = { /** * Compatability map @@ -29,7 +30,7 @@ fn: { * @param context Context object of editor to create module in * @param config Configuration object to create module from */ - create: function( context, config ) { + create: function( context ) { // Build the dialog behind the Publish button var dialogID = 'wikiEditor-' + context.instance + '-preview-dialog'; $.wikiEditor.modules.dialogs.fn.create( @@ -78,7 +79,7 @@ fn: { .css( 'top', '25px' ); // $dialog.dialog( 'option', 'width', $( 'body' ).width() - 300 ); // Aborts when nothing has changed since the last preview - if ( context.modules.preview.previewText == wikitext ) { + if ( context.modules.preview.previewText === wikitext ) { return; } @@ -96,9 +97,9 @@ fn: { }, function( data ) { if ( - typeof data.parse == 'undefined' || - typeof data.parse.text == 'undefined' || - typeof data.parse.text['*'] == 'undefined' + typeof data.parse === 'undefined' || + typeof data.parse.text === 'undefined' || + typeof data.parse.text['*'] === 'undefined' ) { return; } @@ -128,4 +129,4 @@ fn: { } } -}; } )( jQuery ); +}; } )( jQuery, mediaWiki ); diff --git a/modules/jquery.wikiEditor.publish.js b/modules/jquery.wikiEditor.publish.js index b61140dc..058fa1b3 100644 --- a/modules/jquery.wikiEditor.publish.js +++ b/modules/jquery.wikiEditor.publish.js @@ -1,4 +1,5 @@ /* Publish module for wikiEditor */ +/*jshint onevar:false */ ( function ( $ ) { $.wikiEditor.modules.publish = { @@ -31,7 +32,7 @@ fn: { * @param context Context object of editor to create module in * @param config Configuration object to create module from */ - create: function ( context, config ) { + create: function ( context ) { // Build the dialog behind the Publish button var dialogID = 'wikiEditor-' + context.instance + '-dialog'; $.wikiEditor.modules.dialogs.fn.create( @@ -89,16 +90,18 @@ fn: { ); /* END OF REALLY DIRTY HACK */ - if ( $( '#wpMinoredit' ).length === 0 ) + if ( $( '#wpMinoredit' ).length === 0 ) { $( '#wikiEditor-' + context.instance + '-dialog-minor' ).hide(); - else if ( $( '#wpMinoredit' ).is( ':checked' ) ) + } else if ( $( '#wpMinoredit' ).prop( 'checked' ) ) { $( '#wikiEditor-' + context.instance + '-dialog-minor' ) .prop( 'checked', true ); - if ( $( '#wpWatchthis' ).length === 0 ) + } + if ( $( '#wpWatchthis' ).length === 0 ) { $( '#wikiEditor-' + context.instance + '-dialog-watch' ).hide(); - else if ( $( '#wpWatchthis' ).is( ':checked' ) ) + } else if ( $( '#wpWatchthis' ).prop( 'checked' ) ) { $( '#wikiEditor-' + context.instance + '-dialog-watch' ) .prop( 'checked', true ); + } $(this).find( 'form' ).submit( function ( e ) { $(this).closest( '.ui-dialog' ).find( 'button:first' ).click(); diff --git a/modules/jquery.wikiEditor.templateEditor.js b/modules/jquery.wikiEditor.templateEditor.js index f296f5e9..3cbd5ba5 100644 --- a/modules/jquery.wikiEditor.templateEditor.js +++ b/modules/jquery.wikiEditor.templateEditor.js @@ -1,4 +1,5 @@ /* TemplateEditor module for wikiEditor */ +/*jshint quotmark:false, onevar:false */ ( function ( $ ) { $.wikiEditor.modules.templateEditor = { /** * Name mappings, dirty hack which will be removed once "TemplateInfo" extension is more fully supported @@ -37,9 +38,13 @@ */ evt: { - mark: function( context, event ) { + /** + * @param context + * @param event + */ + mark: function( context ) { // The markers returned by this function are skipped on realchange, so don't regenerate them in that case - if ( context.modules.highlight.currentScope == 'realchange' ) { + if ( context.modules.highlight.currentScope === 'realchange' ) { return; } @@ -47,10 +52,9 @@ evt: { var markers = context.modules.highlight.markers; var tokenArray = context.modules.highlight.tokenArray; // Collect matching level 0 template call boundaries from the tokenArray - var level = 0; var tokenIndex = 0; while ( tokenIndex < tokenArray.length ){ - while ( tokenIndex < tokenArray.length && tokenArray[tokenIndex].label != 'TEMPLATE_BEGIN' ) { + while ( tokenIndex < tokenArray.length && tokenArray[tokenIndex].label !== 'TEMPLATE_BEGIN' ) { tokenIndex++; } //open template @@ -58,19 +62,18 @@ evt: { var beginIndex = tokenIndex; var endIndex = -1; //no match found var openTemplates = 1; - var templatesMatched = false; - while ( tokenIndex < tokenArray.length - 1 && endIndex == -1 ) { + while ( tokenIndex < tokenArray.length - 1 && endIndex === -1 ) { tokenIndex++; - if ( tokenArray[tokenIndex].label == 'TEMPLATE_BEGIN' ) { + if ( tokenArray[tokenIndex].label === 'TEMPLATE_BEGIN' ) { openTemplates++; - } else if ( tokenArray[tokenIndex].label == 'TEMPLATE_END' ) { + } else if ( tokenArray[tokenIndex].label === 'TEMPLATE_END' ) { openTemplates--; - if ( openTemplates == 0 ) { + if ( openTemplates === 0 ) { endIndex = tokenIndex; } //we can stop looping } }//while finding template ending - if ( endIndex != -1 ) { + if ( endIndex !== -1 ) { markers.push( { start: tokenArray[beginIndex].offset, end: tokenArray[endIndex].offset, @@ -92,7 +95,7 @@ evt: { } }, onSkip: function( node ) { - if ( $( node ).html() == $( node ).data( 'oldHTML' ) ) { + if ( $( node ).html() === $( node ).data( 'oldHTML' ) ) { // No change return; } @@ -104,7 +107,7 @@ evt: { if ( $( node ).parent().hasClass( 'wikiEditor-template' ) ) { var $label = $( node ).parent().find( '.wikiEditor-template-label' ); var displayName = $.wikiEditor.modules.templateEditor.fn.getTemplateDisplayName( model ); - if ( $label.text() != displayName ) { + if ( $label.text() !== displayName ) { $label.text( displayName ); } } @@ -119,7 +122,7 @@ evt: { $.wikiEditor.modules.templateEditor.fn.bindTemplateEvents( $( node ) ); } }, - getAnchor: function( ca1, ca2 ) { + getAnchor: function( ca1 ) { return $( ca1.parentNode ).is( 'span.wikiEditor-template-text' ) ? ca1.parentNode : null; }, @@ -142,7 +145,9 @@ evt: { var $evtElem = event.jQueryNode; if ( $evtElem.hasClass( 'wikiEditor-template-label' ) ) { // Allow anything if the command or control key are depressed - if ( event.ctrlKey || event.metaKey ) return true; + if ( event.ctrlKey || event.metaKey ) { + return true; + } switch ( event.which ) { case 13: // Enter $evtElem.click(); @@ -177,14 +182,22 @@ evt: { } } }, - keyup: function( context, event ) { + /** + * @param context + * @param event + */ + keyup: function( context ) { // Rest our ignoreKeypress variable if it's set to true if ( context.$iframe.data( 'ignoreKeypress' ) ) { context.$iframe.data( 'ignoreKeypress', false ); } return true; }, - keypress: function( context, event ) { + /** + * @param context + * @param event + */ + keypress: function( context ) { // If this event is from a keydown event which we want to block, ignore it return ( context.$iframe.data( 'ignoreKeypress' ) ? false : true ); } @@ -210,7 +223,7 @@ fn: { * @param context Context object of editor to create module in * @param config Configuration object to create module from */ - create: function( context, config ) { + create: function( context ) { // Initialize module within the context context.modules.templateEditor = {}; }, @@ -220,8 +233,7 @@ fn: { */ wrapTemplate: function( $wrapper ) { var model = $wrapper.data( 'model' ); - var context = $wrapper.data( 'marker' ).context; - var $template = $wrapper + $wrapper .wrap( '' ) .addClass( 'wikiEditor-template-text wikiEditor-template-text-shrunken' ) .parent() @@ -249,7 +261,7 @@ fn: { bindTemplateEvents: function( $wrapper ) { var $template = $wrapper.parent( '.wikiEditor-template' ); - if ( typeof ( opera ) == "undefined" ) { + if ( typeof opera === 'undefined' ) { $template.parent().attr('contentEditable', 'false'); } @@ -274,7 +286,7 @@ fn: { * Toggle the visisbilty of the wikitext for a given template * @param $wrapper The origianl wrapper we want expand/collapse */ - toggleWikiTextEditor: function( $wrapper ) { + toggleWikiTextEditor: function( $wrapper ) { var context = $wrapper.data( 'marker' ).context; var $template = $wrapper.parent( '.wikiEditor-template' ); context.fn.purgeOffsets(); @@ -285,11 +297,11 @@ fn: { var $templateText = $template.find( '.wikiEditor-template-text' ); $templateText.toggleClass( 'wikiEditor-template-text-shrunken' ); $templateText.toggleClass( 'wikiEditor-template-text-visible' ); - if( $templateText.hasClass('wikiEditor-template-text-shrunken') ){ + if ( $templateText.hasClass('wikiEditor-template-text-shrunken') ){ //we just closed the template // Update the model if we need to - if ( $templateText.html() != $templateText.data( 'oldHTML' ) ) { + if ( $templateText.html() !== $templateText.data( 'oldHTML' ) ) { var templateModel = $.wikiEditor.modules.templateEditor.fn.updateModel( $templateText ); //this is the only place the template name can be changed; keep the template name in sync @@ -350,7 +362,7 @@ fn: { var $templateText = $templateDiv.children( '.wikiEditor-template-text' ); var templateModel = $templateText.data( 'model' ); // Update the model if we need to - if ( $templateText.html() != $templateText.data( 'oldHTML' ) ) { + if ( $templateText.html() !== $templateText.data( 'oldHTML' ) ) { templateModel = $.wikiEditor.modules.templateEditor.fn.updateModel( $templateText ); } @@ -362,11 +374,11 @@ fn: { var $rows = $fields.find( '.wikiEditor-template-dialog-field-wrapper' ); for ( var paramIndex in params ) { var param = params[paramIndex]; - if ( typeof param.name == 'undefined' ) { + if ( typeof param.name === 'undefined' ) { // param is the template name, skip it continue; } - var paramText = typeof param == 'string' ? + var paramText = typeof param === 'string' ? param.name.replace( /[\_\-]/g, ' ' ) : param.name; var paramVal = templateModel.getValue( param.name ); @@ -397,11 +409,13 @@ fn: { .data( 'expanded', false ) .bind( 'cut paste keypress click change', function( e ) { // If this was fired by a tab keypress, let it go - if ( e.keyCode == '9' ) return true; + if ( e.keyCode === 9 || e.keyCode === '9' ) { + return true; + } var $this = $( this ); setTimeout( function() { var expanded = $this.data( 'expanded' ); - if ( $this.val().indexOf( '\n' ) != -1 || $this.val().length > 24 ) { + if ( $this.val().indexOf( '\n' ) !== -1 || $this.val().length > 24 ) { if ( !expanded ) { $this.animate( { 'height': '4.5em' }, 'fast' ); $this.data( 'expanded', true ); @@ -455,7 +469,7 @@ fn: { updateModel: function( $templateText, model ) { var context = $templateText.data( 'marker' ).context; var text; - if ( typeof model == 'undefined' ) { + if ( typeof model === 'undefined' ) { text = context.fn.htmlToText( $templateText.html() ); } else { text = model.getText(); @@ -464,7 +478,7 @@ fn: { $templateText.text( text ); $templateText.html( $templateText.html().replace( /\n/g, '
' ) ); $templateText.data( 'oldHTML', $templateText.html() ); - if ( typeof model == 'undefined' ) { + if ( typeof model === 'undefined' ) { model = new $.wikiEditor.modules.templateEditor.fn.model( text ); $templateText.data( 'model', model ); } @@ -476,9 +490,9 @@ fn: { */ getTemplateDisplayName: function ( model ) { var tName = model.getName(); - if( model.getValue( 'name' ) != '' ) { + if( model.getValue( 'name' ) !== '' ) { return tName + ': ' + model.getValue( 'name' ); - } else if( model.getValue( 'Name' ) != '' ) { + } else if( model.getValue( 'Name' ) !== '' ) { return tName + ': ' + model.getValue( 'Name' ); } else if( tName.toLowerCase() in $.wikiEditor.modules.templateEditor.nameMappings ) { return tName + ': ' + model.getValue( $.wikiEditor.modules.templateEditor.nameMappings[tName.toLowerCase()] ); @@ -541,27 +555,28 @@ fn: { var retVal; if ( isNaN( name ) ) { // It's a string! - if ( typeof paramsByName[name] == 'undefined' ) { + if ( typeof paramsByName[name] === 'undefined' ) { // Does not exist - return ""; + return ''; } rangeIndex = paramsByName[name]; } else { // It's a number! - rangeIndex = parseInt( name ); + rangeIndex = parseInt( name, 10 ); } - if ( typeof params[rangeIndex] == 'undefined' ) { + if ( typeof params[rangeIndex] === 'undefined' ) { // Does not exist - return ""; + return ''; } valueRange = ranges[params[rangeIndex].valueIndex]; - if ( typeof valueRange.newVal == 'undefined' || original ) { + if ( typeof valueRange.newVal === 'undefined' || original ) { // Value unchanged, return original wikitext retVal = wikitext.substring( valueRange.begin, valueRange.end ); } else { // New value exists, return new value retVal = valueRange.newVal; } + /*jshint eqnull:true */ if ( value != null ) { ranges[params[rangeIndex].valueIndex].newVal = value; } @@ -574,7 +589,7 @@ fn: { * Get template name */ this.getName = function() { - if( typeof ranges[templateNameIndex].newVal == 'undefined' ) { + if( typeof ranges[templateNameIndex].newVal === 'undefined' ) { return wikitext.substring( ranges[templateNameIndex].begin, ranges[templateNameIndex].end ); } else { return ranges[templateNameIndex].newVal; @@ -635,9 +650,9 @@ fn: { * Get modified template text */ this.getText = function() { - newText = ""; - for ( i = 0 ; i < ranges.length; i++ ) { - if( typeof ranges[i].newVal == 'undefined' ) { + var newText = ""; + for ( var i = 0 ; i < ranges.length; i++ ) { + if( typeof ranges[i].newVal === 'undefined' ) { newText += wikitext.substring( ranges[i].begin, ranges[i].end ); } else { newText += ranges[i].newVal; @@ -659,7 +674,7 @@ fn: { var adjustment = 0; for (var i = 0 ; i < ranges.length; i++ ) { ranges[i].begin += adjustment; - if( typeof ranges[i].adjust != 'undefined' ) { + if ( typeof ranges[i].adjust !== 'undefined' ) { adjustment += ranges[i].adjust(); // NOTE: adjust should be a function that has the information necessary to calculate the length of // this 'segment' @@ -680,15 +695,16 @@ fn: { // Get rid of first {{ with whitespace var sanatizedStr = wikitext.replace( /{{/, " " ); // Replace end - endBraces = sanatizedStr.match( /}}\s*$/ ); + var endBraces = sanatizedStr.match( /}}\s*$/ ); if ( endBraces ) { sanatizedStr = sanatizedStr.substring( 0, endBraces.index ) + " " + sanatizedStr.substring( endBraces.index + 2 ); } + var startIndex, endIndex, sanatizedSegment, openBraces, brace; //treat HTML comments like whitespace - while ( sanatizedStr.indexOf( '') + 3; if( endIndex < 3 ){ @@ -700,26 +716,26 @@ fn: { } // Match the open braces we just found with equivalent closing braces note, works for any level of braces - while ( sanatizedStr.indexOf( '{{' ) != -1 ) { + while ( sanatizedStr.indexOf( '{{' ) !== -1 ) { startIndex = sanatizedStr.indexOf( '{{' ) + 1; openBraces = 2; endIndex = startIndex; while ( (openBraces > 0) && (endIndex < sanatizedStr.length) ) { - var brace = sanatizedStr[++endIndex]; - openBraces += brace == '}' ? -1 : brace == '{' ? 1 : 0; + brace = sanatizedStr[++endIndex]; + openBraces += brace === '}' ? -1 : brace === '{' ? 1 : 0; } sanatizedSegment = sanatizedStr.substring( startIndex,endIndex ).replace( /[{}|=]/g , 'X' ); sanatizedStr = sanatizedStr.substring( 0, startIndex ) + sanatizedSegment + sanatizedStr.substring( endIndex ); } //links, images, etc, which also can nest - while ( sanatizedStr.indexOf( '[[' ) != -1 ) { + while ( sanatizedStr.indexOf( '[[' ) !== -1 ) { startIndex = sanatizedStr.indexOf( '[[' ) + 1; openBraces = 2; endIndex = startIndex; while ( (openBraces > 0) && (endIndex < sanatizedStr.length) ) { - var brace = sanatizedStr[++endIndex]; - openBraces += brace == ']' ? -1 : brace == '[' ? 1 : 0; + brace = sanatizedStr[++endIndex]; + openBraces += brace === ']' ? -1 : brace === '[' ? 1 : 0; } sanatizedSegment = sanatizedStr.substring( startIndex,endIndex ).replace( /[\[\]|=]/g , 'X' ); sanatizedStr = @@ -733,14 +749,16 @@ fn: { var params = []; var templateNameIndex = 0; var doneParsing = false; - oldDivider = 0; - divider = sanatizedStr.indexOf( '|', oldDivider ); - if ( divider == -1 ) { + var oldDivider = 0; + var divider = sanatizedStr.indexOf( '|', oldDivider ); + if ( divider === -1 ) { divider = sanatizedStr.length; doneParsing = true; collapsible = false; //zero params } - nameMatch = sanatizedStr.substring( 0, divider ).match( /[^\s]/ ); + var nameMatch = sanatizedStr.substring( 0, divider ).match( /[^\s]/ ); + var nameEndMatch; + /*jshint eqnull:true */ if ( nameMatch != null ) { ranges.push( new Range( 0 ,nameMatch.index ) ); //whitespace and squiggles upto the name nameEndMatch = sanatizedStr.substring( 0 , divider ).match( /[^\s]\s*$/ ); //last nonwhitespace character @@ -758,18 +776,21 @@ fn: { * Start looping over params */ var currentParamNumber = 0; + var currentField, currentValue, valueBeginIndex, valueBegin, valueEnd; + var nameIndex, equalsIndex, valueIndex; + var currentName, nameBegin, nameBeginIndex, nameEnd, nameEndIndex; var valueEndIndex = ranges[templateNameIndex].end; var paramsByName = []; while ( !doneParsing ) { currentParamNumber++; oldDivider = divider; divider = sanatizedStr.indexOf( '|', oldDivider + 1 ); - if ( divider == -1 ) { + if ( divider === -1 ) { divider = sanatizedStr.length; doneParsing = true; } currentField = sanatizedStr.substring( oldDivider+1, divider ); - if ( currentField.indexOf( '=' ) == -1 ) { + if ( currentField.indexOf( '=' ) === -1 ) { // anonymous field, gets a number //default values, since we'll allow empty values diff --git a/modules/jquery.wikiEditor.templates.js b/modules/jquery.wikiEditor.templates.js index e4237814..b0462563 100644 --- a/modules/jquery.wikiEditor.templates.js +++ b/modules/jquery.wikiEditor.templates.js @@ -1,22 +1,23 @@ /* Templates Module for wikiEditor */ +/*jshint onevar:false */ ( function ( $ ) { $.wikiEditor.modules.templates = { /** * Core Requirements */ -'req': [ 'iframe' ], +req: [ 'iframe' ], /** * Object Templates */ -'tpl': { - 'marker': { - 'type': 'template', - 'anchor': 'wrap', - 'skipDivision': 'realchange', - 'afterWrap': function( node ) { +tpl: { + marker: { + type: 'template', + anchor: 'wrap', + skipDivision: 'realchange', + afterWrap: function ( node ) { $( node ).addClass( 'wikiEditor-template' ); }, - 'getAnchor': function( ca1, ca2 ) { + getAnchor: function ( ca1 ) { return $( ca1.parentNode ).is( '.wikiEditor-template' ) ? ca1.parentNode : null; } } @@ -24,10 +25,14 @@ /** * Event handlers */ -'evt': { - 'mark': function( context, event ) { +evt: { + /** + * @param context + * @param event + */ + mark: function ( context ) { // The markers returned by this function are skipped on realchange, so don't regenerate them in that case - if ( context.modules.highlight.currentScope == 'realchange' ) { + if ( context.modules.highlight.currentScope === 'realchange' ) { return; } // Get references to the markers and tokens from the current context @@ -36,14 +41,14 @@ // Use depth-tracking to extract top-level templates from tokens var depth = 0, bias, start; for ( var i in tokens ) { - depth += ( bias = tokens[i].label == 'TEMPLATE_BEGIN' ? 1 : ( tokens[i].label == 'TEMPLATE_END' ? -1 : 0 ) ); - if ( bias > 0 && depth == 1 ) { + depth += ( bias = tokens[i].label === 'TEMPLATE_BEGIN' ? 1 : ( tokens[i].label === 'TEMPLATE_END' ? -1 : 0 ) ); + if ( bias > 0 && depth === 1 ) { // Top-level opening - use offset as start start = tokens[i].offset; - } else if ( bias < 0 && depth == 0 ) { + } else if ( bias < 0 && depth === 0 ) { // Top-level closing - use offset as end markers[markers.length] = $.extend( - { 'context': context, 'start': start, 'end': tokens[i].offset }, + { context: context, start: start, end: tokens[i].offset }, $.wikiEditor.modules.templates.tpl.marker ); } @@ -53,15 +58,19 @@ } } }, -'exp': [ - { 'regex': /{{/, 'label': "TEMPLATE_BEGIN" }, - { 'regex': /}}/, 'label': "TEMPLATE_END", 'markAfter': true } +exp: [ + { regex: /{{/, label: 'TEMPLATE_BEGIN' }, + { regex: /}}/, label: 'TEMPLATE_END', markAfter: true } ], /** * Internally used functions */ -'fn': { - 'create': function( context, config ) { +fn: { + /** + * @param context + * @param config + */ + create: function () { // Do some stuff here... } } diff --git a/modules/jquery.wikiEditor.toc.js b/modules/jquery.wikiEditor.toc.js index 361d078b..3f186db6 100644 --- a/modules/jquery.wikiEditor.toc.js +++ b/modules/jquery.wikiEditor.toc.js @@ -1,31 +1,32 @@ /* TOC Module for wikiEditor */ -( function ( $ ) { $.wikiEditor.modules.toc = { +/*jshint onevar:false */ +( function ( $, mw ) { $.wikiEditor.modules.toc = { /** * Compatability map */ -'browsers': { +browsers: { // Left-to-right languages - 'ltr': { - 'msie': [['>=', 7]], - 'firefox': [['>=', 3]], - 'opera': [['>=', 10]], - 'safari': [['>=', 4]], - 'chrome': [['>=', 4]] + ltr: { + msie: [['>=', 7]], + firefox: [['>=', 3]], + opera: [['>=', 10]], + safari: [['>=', 4]], + chrome: [['>=', 4]] }, // Right-to-left languages - 'rtl': { - 'msie': [['>=', 8]], - 'firefox': [['>=', 3]], - 'opera': [['>=', 10]], - 'safari': [['>=', 4]], - 'chrome': [['>=', 4]] + rtl: { + msie: [['>=', 8]], + firefox: [['>=', 3]], + opera: [['>=', 10]], + safari: [['>=', 4]], + chrome: [['>=', 4]] } }, /** * Core Requirements */ -'req': [ 'iframe' ], +req: [ 'iframe' ], /** * Configuration */ @@ -51,10 +52,18 @@ api: { * Event handlers */ evt: { - change: function( context, event ) { + /** + * @param context + * @param event + */ + change: function( context ) { $.wikiEditor.modules.toc.fn.update( context ); }, - ready: function( context, event ) { + /** + * @param context + * @param event + */ + ready: function( context ) { // Add the TOC to the document $.wikiEditor.modules.toc.fn.build( context ); if ( !context.$content ) { @@ -68,28 +77,32 @@ evt: { $.wikiEditor.modules.toc.fn.improveUI(); $.wikiEditor.modules.toc.evt.resize( context ); }, - resize: function( context, event ) { + /** + * @param context + * @param event + */ + resize: function( context ) { var availableWidth = context.$wikitext.width() - parseFloat( $.wikiEditor.modules.toc.cfg.textMinimumWidth ), totalMinWidth = parseFloat( $.wikiEditor.modules.toc.cfg.minimumWidth ) + parseFloat( $.wikiEditor.modules.toc.cfg.textMinimumWidth ); context.$ui.find( '.wikiEditor-ui-right' ) .resizable( 'option', 'maxWidth', availableWidth ); - if ( context.modules.toc.$toc.data( 'positionMode' ) != 'disabled' && + if ( context.modules.toc.$toc.data( 'positionMode' ) !== 'disabled' && context.$wikitext.width() < totalMinWidth ) { $.wikiEditor.modules.toc.fn.disable( context ); - } else if ( context.modules.toc.$toc.data( 'positionMode' ) == 'disabled' && + } else if ( context.modules.toc.$toc.data( 'positionMode' ) === 'disabled' && context.$wikitext.width() > totalMinWidth ) { $.wikiEditor.modules.toc.fn.enable( context ); - } else if ( context.modules.toc.$toc.data( 'positionMode' ) == 'regular' && + } else if ( context.modules.toc.$toc.data( 'positionMode' ) === 'regular' && context.$ui.find( '.wikiEditor-ui-right' ).width() > availableWidth ) { //switch mode $.wikiEditor.modules.toc.fn.switchLayout( context ); - } else if ( context.modules.toc.$toc.data( 'positionMode' ) == 'goofy' && + } else if ( context.modules.toc.$toc.data( 'positionMode' ) === 'goofy' && context.modules.toc.$toc.data( 'previousWidth' ) < context.$wikitext.width() ) { //switch mode $.wikiEditor.modules.toc.fn.switchLayout( context ); } - if ( context.modules.toc.$toc.data( 'positionMode' ) == 'goofy' ) { + if ( context.modules.toc.$toc.data( 'positionMode' ) === 'goofy' ) { context.modules.toc.$toc.find( 'div' ).autoEllipsis( { 'position': 'right', 'tooltip': true, 'restoreText': true } ); @@ -105,14 +118,18 @@ evt: { // store the width of the view for comparison on next resize context.modules.toc.$toc.data( 'previousWidth', context.$wikitext.width() ); }, - mark: function( context, event ) { + /** + * @param context + * @param event + */ + mark: function( context ) { var hash = ''; var markers = context.modules.highlight.markers; var tokenArray = context.modules.highlight.tokenArray; var outline = context.data.outline = []; var h = 0; for ( var i = 0; i < tokenArray.length; i++ ) { - if ( tokenArray[i].label != 'TOC_HEADER' ) { + if ( tokenArray[i].label !== 'TOC_HEADER' ) { continue; } h++; @@ -134,14 +151,14 @@ evt: { }, onSkip: function( node ) { var marker = $( node ).data( 'marker' ); - if ( $( node ).data( 'section' ) != marker.index ) { + if ( $( node ).data( 'section' ) !== marker.index ) { $( node ) .removeClass( 'wikiEditor-toc-section-' + $( node ).data( 'section' ) ) .addClass( 'wikiEditor-toc-section-' + marker.index ) .data( 'section', marker.index ); } }, - getAnchor: function( ca1, ca2 ) { + getAnchor: function( ca1 ) { return $( ca1.parentNode ).is( '.wikiEditor-toc-header' ) ? ca1.parentNode : null; } @@ -154,7 +171,7 @@ evt: { } ); } // Only update the TOC if it's been changed - we do this by comparing a hash of the headings this time to last - if ( typeof context.modules.toc.lastHash == 'undefined' || context.modules.toc.lastHash !== hash ) { + if ( typeof context.modules.toc.lastHash === 'undefined' || context.modules.toc.lastHash !== hash ) { $.wikiEditor.modules.toc.fn.build( context ); $.wikiEditor.modules.toc.fn.update( context ); // Remember the changed version @@ -175,13 +192,13 @@ fn: { * @param {Object} context Context object of editor to create module in * @param {Object} config Configuration object to create module from */ - create: function( context, config ) { + create: function( context ) { if ( '$toc' in context.modules.toc ) { return; } $.wikiEditor.modules.toc.cfg.rtl = $( 'body' ).is( '.rtl' ); $.wikiEditor.modules.toc.cfg.flexProperty = $.wikiEditor.modules.toc.cfg.rtl ? 'marginLeft' : 'marginRight'; - var height = context.$ui.find( '.wikiEditor-ui-left' ).height(); + context.$ui.find( '.wikiEditor-ui-left' ).height(); context.modules.toc.$toc = $( '
' ) .addClass( 'wikiEditor-ui-toc' ) .data( 'context', context ) @@ -196,14 +213,14 @@ fn: { }, redraw: function( context, fixedWidth ) { fixedWidth = parseFloat( fixedWidth ); - if( context.modules.toc.$toc.data( 'positionMode' ) == 'regular' ) { + if ( context.modules.toc.$toc.data( 'positionMode' ) === 'regular' ) { context.$ui.find( '.wikiEditor-ui-right' ) .css( 'width', fixedWidth + 'px' ); context.$ui.find( '.wikiEditor-ui-left' ) .css( $.wikiEditor.modules.toc.cfg.flexProperty, ( -1 * fixedWidth ) + 'px' ) .children() .css( $.wikiEditor.modules.toc.cfg.flexProperty, fixedWidth + 'px' ); - } else if( context.modules.toc.$toc.data( 'positionMode' ) == 'goofy' ) { + } else if( context.modules.toc.$toc.data( 'positionMode' ) === 'goofy' ) { context.$ui.find( '.wikiEditor-ui-left' ) .css( 'width', fixedWidth ); context.$ui.find( '.wikiEditor-ui-right' ) @@ -212,10 +229,10 @@ fn: { } }, switchLayout: function( context ) { - var width, - height = context.$ui.find( '.wikiEditor-ui-right' ).height(); - if ( context.modules.toc.$toc.data( 'positionMode' ) == 'regular' - && !context.modules.toc.$toc.data( 'collapsed' ) + var width; + context.$ui.find( '.wikiEditor-ui-right' ).height(); + if ( context.modules.toc.$toc.data( 'positionMode' ) === 'regular' && + !context.modules.toc.$toc.data( 'collapsed' ) ) { // store position mode context.modules.toc.$toc.data( 'positionMode', 'goofy' ); @@ -237,7 +254,7 @@ fn: { 'left' : $.wikiEditor.modules.toc.cfg.rtl ? 0 : 'auto' } ); context.$wikitext .css( 'position', 'relative' ); - } else if ( context.modules.toc.$toc.data( 'positionMode' ) == 'goofy' ) { + } else if ( context.modules.toc.$toc.data( 'positionMode' ) === 'goofy' ) { // store position mode context.modules.toc.$toc.data( 'positionMode', 'regular' ); // set width @@ -260,7 +277,7 @@ fn: { if ( context.modules.toc.$toc.data( 'collapsed' ) ) { context.$ui.find( '.wikiEditor-ui-toc-expandControl' ).hide(); } else { - if( context.modules.toc.$toc.data( 'positionMode' ) == 'goofy' ) { + if( context.modules.toc.$toc.data( 'positionMode' ) === 'goofy' ) { $.wikiEditor.modules.toc.fn.switchLayout( context ); } context.$ui.find( '.wikiEditor-ui-right' ).hide(); @@ -296,7 +313,7 @@ fn: { * * @param {Object} context */ - update: function( context ) { + update: function () { //temporarily commenting this out because it is causing all kinds of cursor //and text jumping issues in IE. WIll get back to this --pdhanda /* @@ -333,10 +350,10 @@ fn: { * * @param {Object} event Event object with context as data */ - collapse: function( event ) { + collapse: function () { var $this = $( this ), context = $this.data( 'context' ); - if( context.modules.toc.$toc.data( 'positionMode' ) == 'goofy' ) { + if ( context.modules.toc.$toc.data( 'positionMode' ) === 'goofy' ) { $.wikiEditor.modules.toc.fn.switchLayout( context ); } var pT = $this.parent().position().top - 1; @@ -366,7 +383,7 @@ fn: { // Let the UI know things have moved around context.fn.trigger( 'tocCollapse' ); context.fn.trigger( 'resize' ); - } ); + } ); $.cookie( 'wikiEditor-' + context.instance + '-toc-width', 0 ); return false; @@ -377,15 +394,19 @@ fn: { * * @param {Object} event Event object with context as data */ - expand: function( event ) { + expand: function () { var $this = $( this ), context = $this.data( 'context' ), openWidth = parseFloat( context.modules.toc.$toc.data( 'openWidth' ) ), availableSpace = context.$wikitext.width() - parseFloat( $.wikiEditor.modules.toc.cfg.textMinimumWidth ); - if ( availableSpace < $.wikiEditor.modules.toc.cfg.textMinmumWidth ) return false; + if ( availableSpace < $.wikiEditor.modules.toc.cfg.textMinmumWidth ) { + return false; + } context.modules.toc.$toc.data( 'collapsed', false ); // check if we've got enough room to open to our stored width - if ( availableSpace < openWidth ) openWidth = availableSpace; + if ( availableSpace < openWidth ) { + openWidth = availableSpace; + } context.$ui.find( '.wikiEditor-ui-toc-expandControl' ).hide(); var leftParam = {}, leftChildParam = {}; leftParam[ $.wikiEditor.modules.toc.cfg.flexProperty ] = parseFloat( openWidth ) * -1; @@ -407,7 +428,7 @@ fn: { 'top': 'auto' } ); context.fn.trigger( 'tocExpand' ); context.fn.trigger( 'resize' ); - } ); + } ); $.cookie( 'wikiEditor-' + context.instance + '-toc-width', context.modules.toc.$toc.data( 'openWidth' ) ); return false; @@ -432,7 +453,7 @@ fn: { } var sections = []; for ( var i = offset; i < outline.length; i++ ) { - if ( outline[i].nLevel == level ) { + if ( outline[i].nLevel === level ) { var sub = buildStructure( outline, i + 1, level + 1 ); if ( sub.length ) { outline[i].sections = sub; @@ -462,8 +483,9 @@ fn: { .click( function( event ) { var wrapper = context.$content.find( '.wikiEditor-toc-section-' + $( this ).data( 'index' ) ); - if ( wrapper.length === 0 ) + if ( wrapper.length === 0 ) { wrapper = context.$content; + } context.fn.scrollToTop( wrapper, true ); context.$textarea.textSelection( 'setSelection', { 'start': 0, @@ -481,8 +503,9 @@ fn: { event.preventDefault(); } ) .text( structure[i].text ); - if ( structure[i].text === '' ) + if ( structure[i].text === '' ) { div.html( ' ' ); + } var item = $( '
  • ' ).append( div ); if ( structure[i].sections !== undefined ) { item.append( buildList( structure[i].sections ) ); @@ -546,7 +569,7 @@ fn: { .data( 'wikiEditor-ui-left', context.$ui.find( '.wikiEditor-ui-left' ) ) .resizable( { handles: 'w,e', preventPositionLeftChange: true, minWidth: parseFloat( $.wikiEditor.modules.toc.cfg.minimumWidth ), - start: function( e, ui ) { + start: function () { var $this = $( this ); // Toss a transparent cover over our iframe $( '
    ' ) @@ -562,7 +585,7 @@ fn: { .appendTo( context.$ui.find( '.wikiEditor-ui-left' ) ); $this.resizable( 'option', 'maxWidth', $this.parent().width() - parseFloat( $.wikiEditor.modules.toc.cfg.textMinimumWidth ) ); - if(context.modules.toc.$toc.data( 'positionMode' ) == 'goofy' ) { + if ( context.modules.toc.$toc.data( 'positionMode' ) === 'goofy' ) { $.wikiEditor.modules.toc.fn.switchLayout( context ); } }, @@ -596,7 +619,7 @@ fn: { var handle = $.wikiEditor.modules.toc.cfg.rtl ? 'w' : 'e'; context.$ui.find( '.ui-resizable-' + handle ) .removeClass( 'ui-resizable-' + handle ) - .addClass( 'ui-resizable-' + ( handle == 'w' ? 'e' : 'w' ) ) + .addClass( 'ui-resizable-' + ( handle === 'w' ? 'e' : 'w' ) ) .addClass( 'wikiEditor-ui-toc-resize-grip' ); // Bind collapse and expand event handlers to the TOC context.modules.toc.$toc @@ -604,12 +627,13 @@ fn: { .bind( 'expand.wikiEditor-toc', $.wikiEditor.modules.toc.fn.expand ); context.modules.toc.$toc.data( 'openWidth', $.wikiEditor.modules.toc.cfg.defaultWidth ); // If the toc-width cookie is set, reset the widths based upon that - if ( $.cookie( 'wikiEditor-' + context.instance + '-toc-width' ) == 0 ) { + if ( $.cookie( 'wikiEditor-' + context.instance + '-toc-width' ) === 0 ) { context.modules.toc.$toc.trigger( 'collapse.wikiEditor-toc', { data: context } ); } else if ( $.cookie( 'wikiEditor-' + context.instance + '-toc-width' ) > 0 ) { var initialWidth = $.cookie( 'wikiEditor-' + context.instance + '-toc-width' ); - if( initialWidth < parseFloat( $.wikiEditor.modules.toc.cfg.minimumWidth ) ) + if ( initialWidth < parseFloat( $.wikiEditor.modules.toc.cfg.minimumWidth ) ) { initialWidth = parseFloat( $.wikiEditor.modules.toc.cfg.minimumWidth ) + 1; + } context.modules.toc.$toc.data( 'openWidth', initialWidth + 'px' ); $.wikiEditor.modules.toc.fn.redraw( context, initialWidth ); } @@ -664,7 +688,7 @@ fn: { * Extending resizable to allow west resizing without altering the left position attribute */ $.ui.plugin.add( 'resizable', 'preventPositionLeftChange', { - resize: function( event, ui ) { + resize: function () { $( this ).data( 'resizable' ).position.left = 0; } } ); @@ -673,4 +697,4 @@ fn: { }; -} ) ( jQuery ); +} )( jQuery, mediaWiki ); diff --git a/modules/jquery.wikiEditor.toolbar.config.js b/modules/jquery.wikiEditor.toolbar.config.js index 15914f44..780eb2c3 100644 --- a/modules/jquery.wikiEditor.toolbar.config.js +++ b/modules/jquery.wikiEditor.toolbar.config.js @@ -1,7 +1,8 @@ /** * Configuration of Toolbar module for wikiEditor */ -( function ( $ ) { $.wikiEditor.modules.toolbar.config = { +/*jshint camelcase:false, quotmark:false */ +( function ( $, mw ) { $.wikiEditor.modules.toolbar.config = { getDefaultConfig: function() { var fileNamespace = mw.config.get( 'wgFormattedNamespaces' )[6]; @@ -1452,4 +1453,4 @@ getDefaultConfig: function() { } }; } -}; } ) ( jQuery ); +}; } ) ( jQuery, mediaWiki ); diff --git a/modules/jquery.wikiEditor.toolbar.js b/modules/jquery.wikiEditor.toolbar.js index e1bc6f15..71592b53 100644 --- a/modules/jquery.wikiEditor.toolbar.js +++ b/modules/jquery.wikiEditor.toolbar.js @@ -1,6 +1,7 @@ /** * Toolbar module for wikiEditor */ +/*jshint onevar:false */ ( function ( mw, $ ) { $.wikiEditor.modules.toolbar = { /** @@ -17,7 +18,7 @@ api : { var $sections = context.modules.toolbar.$toolbar.find( 'div.sections' ), $tabs = context.modules.toolbar.$toolbar.find( 'div.tabs' ); for ( var section in data[type] ) { - if ( section == 'main' ) { + if ( section === 'main' ) { // Section context.modules.toolbar.$toolbar.prepend( $.wikiEditor.modules.toolbar.fn.buildSection( @@ -145,28 +146,28 @@ api : { } }, removeFromToolbar : function( context, data ) { - if ( typeof data.section == 'string' ) { + if ( typeof data.section === 'string' ) { // Section var tab = 'div.tabs span[rel="' + data.section + '"].tab'; var target = 'div[rel="' + data.section + '"].section'; var group = null; - if ( typeof data.group == 'string' ) { + if ( typeof data.group === 'string' ) { // Toolbar group target += ' div[rel="' + data.group + '"].group'; - if ( typeof data.tool == 'string' ) { + if ( typeof data.tool === 'string' ) { // Save for later checking if empty group = target; // Tool target += ' a[rel="' + data.tool + '"].tool'; } - } else if ( typeof data.page == 'string' ) { + } else if ( typeof data.page === 'string' ) { // Booklet page var index = target + ' div.index div[rel="' + data.page + '"]'; target += ' div.pages div[rel="' + data.page + '"].page'; - if ( typeof data.character == 'string' ) { + if ( typeof data.character === 'string' ) { // Character target += ' span[rel="' + data.character + '"]'; - } else if ( typeof data.row == 'number' ) { + } else if ( typeof data.row === 'number' ) { // Table row target += ' table tr:not(:has(th)):eq(' + data.row + ')'; } else { @@ -198,7 +199,11 @@ api : { * Event handlers */ evt: { - resize: function( context, event ) { + /** + * @param context + * @param event + */ + resize: function( context ) { context.$ui.find( '.sections' ).height( context.$ui.find( '.sections .section-visible' ).outerHeight() ); }, tocCollapse: function( context, event ) { @@ -235,7 +240,7 @@ fn: { * @param {Object} action * @param {Object} source */ - doAction : function( context, action, source ) { + doAction : function( context, action ) { switch ( action.type ) { case 'replace': case 'encapsulate': @@ -244,7 +249,7 @@ fn: { 'peri' : $.wikiEditor.autoMsg( action.options, 'peri' ), 'post' : $.wikiEditor.autoMsg( action.options, 'post' ) }; - var replace = action.type == 'replace'; + var replace = action.type === 'replace'; if ( 'regex' in action.options && 'regexReplace' in action.options ) { var selection = context.$textarea.textSelection( 'getSelection' ); if ( selection !== '' && selection.match( action.options.regex ) ) { @@ -263,7 +268,7 @@ fn: { } break; case 'callback': - if ( typeof action.execute == 'function' ) { + if ( typeof action.execute === 'function' ) { action.execute( context ); } break; @@ -287,7 +292,7 @@ fn: { if ( tool ) { // Consider a group with only hidden tools empty as well // .is( ':visible' ) always returns false because tool is not attached to the DOM yet - empty = empty && tool.css( 'display' ) == 'none'; + empty = empty && tool.css( 'display' ) === 'none'; $group.append( tool ); } } @@ -447,7 +452,7 @@ fn: { } ); }, buildPage : function( context, id, page ) { - var html; + var html, i; var $page = $( '
    ' ).attr( { 'class' : 'page page-' + id, 'rel' : id @@ -461,7 +466,7 @@ fn: { html += $.wikiEditor.modules.toolbar.fn.buildHeading( context, page.headings ); } if ( 'rows' in page ) { - for ( var i = 0; i < page.rows.length; i++ ) { + for ( i = 0; i < page.rows.length; i++ ) { html += $.wikiEditor.modules.toolbar.fn.buildRow( context, page.rows[i] ); } } @@ -484,7 +489,7 @@ fn: { } if ( 'characters' in page ) { html = ''; - for ( var i = 0; i < page.characters.length; i++ ) { + for ( i = 0; i < page.characters.length; i++ ) { html += $.wikiEditor.modules.toolbar.fn.buildCharacter( page.characters[i], actions ); } $characters @@ -527,7 +532,7 @@ fn: { return html + ''; }, buildCharacter : function( character, actions ) { - if ( typeof character == 'string' ) { + if ( typeof character === 'string' ) { character = { 'label' : character, 'action' : { @@ -564,8 +569,9 @@ fn: { return mw.html.element( 'span', { 'rel': character.label }, character.label ); } } - mw.log( "A character for the toolbar was undefined. This is not supposed to happen. Double check the config." ); - return ""; // bug 31673; also an additional fix for bug 24208... + mw.log( 'A character for the toolbar was undefined. This is not supposed to happen. Double check the config.' ); + // bug 31673; also an additional fix for bug 24208... + return ''; }, buildTab : function( context, id, section ) { var selected = $.cookie( 'wikiEditor-' + context.instance + '-toolbar-section' ); @@ -575,7 +581,7 @@ fn: { } var $link = $( '' ) - .addClass( selected == id ? 'current' : null ) + .addClass( selected === id ? 'current' : null ) .attr( { href: '#', role: 'button', @@ -584,7 +590,7 @@ fn: { } ) .text( $.wikiEditor.autoMsg( section, 'label' ) ) .data( 'context', context ) - .mouseup( function( e ) { + .mouseup( function () { $(this).blur(); } ) .mousedown( function( e ) { @@ -604,7 +610,7 @@ fn: { var $sections = $(this).data( 'context' ).$ui.find( '.sections' ); var $section = $(this).data( 'context' ).$ui.find( '.section-' + $(this).parent().attr( 'rel' ) ); - var show = $section.css( 'display' ) == 'none'; + var show = $section.css( 'display' ) === 'none'; $section.parent().find( '.section-visible' ) .css( 'position', 'absolute' ) .attr( 'aria-expanded', 'false' ) @@ -668,7 +674,7 @@ fn: { id: 'wikiEditor-section-' + id } ); var selected = $.cookie( 'wikiEditor-' + context.instance + '-toolbar-section' ); - var show = selected == id; + var show = selected === id; if ( section.deferLoad !== undefined && section.deferLoad && id !== 'main' && !show ) { // This class shows the spinner and serves as a marker for the click handler in buildTab() @@ -724,6 +730,7 @@ fn: { } }, updateBookletSelection : function( context, id, $pages, $index ) { + /*jshint eqnull:true */ var cookie = 'wikiEditor-' + context.instance + '-booklet-' + id + '-page'; var selected = $.cookie( cookie ); // Re-save cookie @@ -747,7 +754,7 @@ fn: { context.modules.toolbar.$toolbar.append( $( '
    ' ).css( 'clear', 'both' ) ); var sectionQueue = []; for ( var section in config ) { - if ( section == 'main' ) { + if ( section === 'main' ) { context.modules.toolbar.$toolbar.prepend( $.wikiEditor.modules.toolbar.fn.buildSection( context, section, config[section] ) );