r59204 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r59203‎ | r59204 | r59205 >
Date:18:53, 18 November 2009
Author:catrope
Status:deferred
Tags:
Comment:
wmf-deployment: Merging usability changes from trunk
* CollapsibleTabs up to r58969
* ClickTracking up to r58205
* Individual UsabilityInitiative revisions:
** r57482: New toolbar icons
** r57677: Icon update
** r57743: CollapsibleTabs update
** r57833: NTOC style change to match booklets
** r57836: Click handlers on mousedown instead of click
** r57904: Add CollapsibleTabs plugin to combined JS
** r57906: NTOC bugfix for headers like "===="
** r57916: white-space: nowrap; on Vector tabs for better animation
** r57918: CollapsibleTabs bugfix for inconsistent buffer space
** r57921: Fix up r57918
** r58069: Add indent icon
** r58070: Add indent button to toolbar
** r58096: NTOC bugfix for highlighting confusion
** r58156: Update indent icon
** r58170: Remove trailing comma that broke IE
** r58173: Remove overflow:hidden; from toolbar sections
** r58174: Fix up r58173
** r58198: Header dropdown cleverness, link dialog and SimpleSearch bugfixes
** r58219: Fix watch/unwatch border
** r58229: Make toolbar resize more gracefully
** r58253: Toolbar regression from r57836
** r58310: Search&replace multiline regex bugfix
** r58374: NTOC bugfix for empty headers
** r58425: Link dialog bugfix for IE/Opera
** r58426: NTOC style fix
** r58427: Dialogs bugfix
** r58441: NTOC ellipsing bugfix
** r58448: Fix regression from r57836
** r58449: Unfocus tabs on mouseup
** r58451: Fix for indent icon
** r58873 (partially): Header dropdown whitespace tolerance
** r58923: Header dropdown fix
** r58926: Double line in toolbar fix
** r58953: Toolbar fixes for IE
** r58973, r58974: Fixes for r58953
** r59048: ClickTracking fix
** r59146 (partial): OptIn bugfix
** r59185: IE fixes (from acaifix branch)
** r59191: Another IE fix (from acaifix)
Modified paths:
  • /branches/wmf-deployment/extensions/UsabilityInitiative (modified) (history)
  • /branches/wmf-deployment/extensions/UsabilityInitiative/ClickTracking (modified) (history)
  • /branches/wmf-deployment/extensions/UsabilityInitiative/ClickTracking/ApiClickTracking.php (modified) (history)
  • /branches/wmf-deployment/extensions/UsabilityInitiative/ClickTracking/ApiSpecialClickTracking.php (modified) (history)
  • /branches/wmf-deployment/extensions/UsabilityInitiative/ClickTracking/ClickTracking.hooks.php (modified) (history)
  • /branches/wmf-deployment/extensions/UsabilityInitiative/ClickTracking/ClickTracking.i18n.php (modified) (history)
  • /branches/wmf-deployment/extensions/UsabilityInitiative/ClickTracking/ClickTracking.js (modified) (history)
  • /branches/wmf-deployment/extensions/UsabilityInitiative/ClickTracking/ClickTracking.php (modified) (history)
  • /branches/wmf-deployment/extensions/UsabilityInitiative/ClickTracking/SpecialClickTracking.css (modified) (history)
  • /branches/wmf-deployment/extensions/UsabilityInitiative/ClickTracking/SpecialClickTracking.js (modified) (history)
  • /branches/wmf-deployment/extensions/UsabilityInitiative/ClickTracking/SpecialClickTracking.php (modified) (history)
  • /branches/wmf-deployment/extensions/UsabilityInitiative/CollapsibleTabs (added) (history)
  • /branches/wmf-deployment/extensions/UsabilityInitiative/CollapsibleTabs/CollapsibleTabs.js (modified) (history)
  • /branches/wmf-deployment/extensions/UsabilityInitiative/EditToolbar/EditToolbar.hooks.php (modified) (history)
  • /branches/wmf-deployment/extensions/UsabilityInitiative/EditToolbar/EditToolbar.i18n.php (modified) (history)
  • /branches/wmf-deployment/extensions/UsabilityInitiative/EditToolbar/EditToolbar.js (modified) (history)
  • /branches/wmf-deployment/extensions/UsabilityInitiative/EditToolbar/EditToolbar.php (modified) (history)
  • /branches/wmf-deployment/extensions/UsabilityInitiative/Makefile (modified) (history)
  • /branches/wmf-deployment/extensions/UsabilityInitiative/NavigableTOC/NavigableTOC.php (modified) (history)
  • /branches/wmf-deployment/extensions/UsabilityInitiative/OptIn (modified) (history)
  • /branches/wmf-deployment/extensions/UsabilityInitiative/OptIn/SpecialOptIn.php (modified) (history)
  • /branches/wmf-deployment/extensions/UsabilityInitiative/UsabilityInitiative.hooks.php (modified) (history)
  • /branches/wmf-deployment/extensions/UsabilityInitiative/css/combined.css (modified) (history)
  • /branches/wmf-deployment/extensions/UsabilityInitiative/css/combined.min.css (modified) (history)
  • /branches/wmf-deployment/extensions/UsabilityInitiative/css/wikiEditor.toc.css (modified) (history)
  • /branches/wmf-deployment/extensions/UsabilityInitiative/css/wikiEditor.toolbar.css (modified) (history)
  • /branches/wmf-deployment/extensions/UsabilityInitiative/images/wikiEditor/toolbar/format-big.png (modified) (history)
  • /branches/wmf-deployment/extensions/UsabilityInitiative/images/wikiEditor/toolbar/format-bold.png (modified) (history)
  • /branches/wmf-deployment/extensions/UsabilityInitiative/images/wikiEditor/toolbar/format-indent.png (added) (history)
  • /branches/wmf-deployment/extensions/UsabilityInitiative/images/wikiEditor/toolbar/format-italic.png (modified) (history)
  • /branches/wmf-deployment/extensions/UsabilityInitiative/images/wikiEditor/toolbar/format-small.png (modified) (history)
  • /branches/wmf-deployment/extensions/UsabilityInitiative/images/wikiEditor/toolbar/format-subscript.png (modified) (history)
  • /branches/wmf-deployment/extensions/UsabilityInitiative/images/wikiEditor/toolbar/format-superscript.png (modified) (history)
  • /branches/wmf-deployment/extensions/UsabilityInitiative/images/wikiEditor/toolbar/indent.png (deleted) (history)
  • /branches/wmf-deployment/extensions/UsabilityInitiative/images/wikiEditor/toolbar/png24/format-big.png (modified) (history)
  • /branches/wmf-deployment/extensions/UsabilityInitiative/images/wikiEditor/toolbar/png24/format-bold.png (modified) (history)
  • /branches/wmf-deployment/extensions/UsabilityInitiative/images/wikiEditor/toolbar/png24/format-italic.png (modified) (history)
  • /branches/wmf-deployment/extensions/UsabilityInitiative/images/wikiEditor/toolbar/png24/format-small.png (modified) (history)
  • /branches/wmf-deployment/extensions/UsabilityInitiative/images/wikiEditor/toolbar/png24/format-subscript.png (modified) (history)
  • /branches/wmf-deployment/extensions/UsabilityInitiative/images/wikiEditor/toolbar/png24/format-superscript.png (modified) (history)
  • /branches/wmf-deployment/extensions/UsabilityInitiative/images/wikiEditor/toolbar/png24/insert-newline.png (modified) (history)
  • /branches/wmf-deployment/extensions/UsabilityInitiative/js/plugins.combined.js (modified) (history)
  • /branches/wmf-deployment/extensions/UsabilityInitiative/js/plugins.combined.min.js (modified) (history)
  • /branches/wmf-deployment/extensions/UsabilityInitiative/js/plugins/jquery.autoEllipse.js (modified) (history)
  • /branches/wmf-deployment/extensions/UsabilityInitiative/js/plugins/jquery.collapsibleTabs.js (added) (history)
  • /branches/wmf-deployment/extensions/UsabilityInitiative/js/plugins/jquery.suggestions.js (modified) (history)
  • /branches/wmf-deployment/extensions/UsabilityInitiative/js/plugins/jquery.textSelection.js (modified) (history)
  • /branches/wmf-deployment/extensions/UsabilityInitiative/js/plugins/jquery.wikiEditor.js (modified) (history)
  • /branches/wmf-deployment/extensions/UsabilityInitiative/js/plugins/jquery.wikiEditor.toc.js (modified) (history)
  • /branches/wmf-deployment/extensions/UsabilityInitiative/js/plugins/jquery.wikiEditor.toolbar.js (modified) (history)

Diff [purge]

Index: branches/wmf-deployment/extensions/UsabilityInitiative/js/plugins/jquery.suggestions.js
@@ -163,7 +163,7 @@
164164 * @param updateTextbox If true, put the suggestion in the textbox
165165 */
166166 highlight: function( context, result, updateTextbox ) {
167 - var selected = context.data.$container.find( '.suggestions-result-current' )
 167+ var selected = context.data.$container.find( '.suggestions-result-current' );
168168 if ( !result.get || selected.get( 0 ) != result.get( 0 ) ) {
169169 if ( result == 'prev' ) {
170170 result = selected.prev();
@@ -232,6 +232,12 @@
233233 case 13:
234234 context.data.$container.hide();
235235 preventDefault = wasVisible;
 236+ if ( typeof context.config.result.select == 'function' ) {
 237+ context.config.result.select.call(
 238+ context.data.$container.find( '.suggestions-result-current' ),
 239+ context.data.$textbox
 240+ );
 241+ }
236242 break;
237243 default:
238244 $.suggestions.update( context, true );
Index: branches/wmf-deployment/extensions/UsabilityInitiative/js/plugins/jquery.textSelection.js
@@ -3,12 +3,17 @@
44 */
55 ( function( $ ) { $.fn.extend( {
66
 7+/**
 8+ * Get the currently selected text in this textarea. Will focus the textarea
 9+ * in some browsers (IE/Opera)
 10+ */
711 getSelection: function() {
812 var e = this.jquery ? this[0] : this;
913 var retval = '';
1014 if ( e.style.display == 'none' ) {
1115 // Do nothing
1216 } else if ( document.selection && document.selection.createRange ) {
 17+ e.focus();
1318 var range = document.selection.createRange();
1419 retval = range.text;
1520 } else if ( e.selectionStart || e.selectionStart == '0' ) {
@@ -46,13 +51,12 @@
4752 post += ' ';
4853 }
4954 }
50 - var selText = $(this).getSelection();
 55+ var selText = $(this).focus().getSelection();
5156 var isSample = false;
5257 if ( this.style.display == 'none' ) {
5358 // Do nothing
5459 } else if ( this.selectionStart || this.selectionStart == '0' ) {
5560 // Mozilla/Opera
56 - $(this).focus();
5761 var startPos = this.selectionStart;
5862 var endPos = this.selectionEnd;
5963 checkSelectedText();
@@ -77,9 +81,10 @@
7882 this.selectionStart = startPos + pre.length + selText.length + post.length;
7983 this.selectionEnd = this.selectionStart;
8084 }
 85+ // Scroll the textarea to the inserted text
 86+ $(this).scrollToCaretPosition();
8187 } else if ( document.selection && document.selection.createRange ) {
8288 // IE
83 - $(this).focus();
8489 var range = document.selection.createRange();
8590 if ( ownline && range.moveStart ) {
8691 var range2 = document.selection.createRange();
@@ -104,8 +109,6 @@
105110 }
106111 range.select();
107112 }
108 - // Scroll the textarea to the inserted text
109 - $(this).scrollToCaretPosition();
110113 $(this).trigger( 'encapsulateSelection', [ pre, peri, post, ownline, replace ] );
111114 });
112115 },
@@ -118,11 +121,18 @@
119122 * Get the position (in resolution of bytes not nessecarily characters)
120123 * in a textarea
121124 */
122 - getCaretPosition: function( startAndEnd ) {
 125+ getCaretPosition: function( startAndEnd, restoreFocus ) {
123126 function getCaret( e ) {
124127 var caretPos = 0, endPos = 0;
125128 if ( $.browser.msie ) {
126129 // IE Support
 130+ // Focus the textarea for this
 131+ // If another element currently has focus, restore it
 132+ var oldFocus = false;
 133+ if ( restoreFocus )
 134+ oldFocus = document.selection.createRange().parentElement;
 135+ e.focus();
 136+
127137 var postFinished = false;
128138 var periFinished = false;
129139 var postFinished = false;
@@ -191,6 +201,9 @@
192202 } while ( ( !postFinished || !periFinished || !postFinished ) );
193203 caretPos = rawPreText.replace( /\r\n/g, "\n" ).length;
194204 endPos = caretPos + rawPeriText.replace( /\r\n/g, "\n" ).length;
 205+ // Restore focus
 206+ if ( oldFocus && oldFocus.focus )
 207+ oldFocus.focus();
195208 } else if ( e.selectionStart || e.selectionStart == '0' ) {
196209 // Firefox support
197210 caretPos = e.selectionStart;
@@ -219,8 +232,12 @@
220233 var selection = document.body.createTextRange();
221234 selection.moveToElementText( this );
222235 var length = selection.text.length;
 236+ if ( start > length || end > length )
 237+ // Faulty data, ignore
 238+ return;
 239+ selection.collapse();
 240+ selection.moveEnd( 'character', end );
223241 selection.moveStart( 'character', start );
224 - selection.moveEnd( 'character', -length + end );
225242 selection.select();
226243 }
227244 });
@@ -316,4 +333,4 @@
317334 } );
318335 }
319336
320 -} ); } )( jQuery );
\ No newline at end of file
 337+} ); } )( jQuery );
Index: branches/wmf-deployment/extensions/UsabilityInitiative/js/plugins/jquery.wikiEditor.js
@@ -170,10 +170,11 @@
171171 $(this).setSelection( pos[0], pos[1] );
172172 $(this).data( 'wikiEditor-cursor', false );
173173 })
174 - .blur( function() {
175 - $(this).data( 'wikiEditor-cursor', $(this).getCaretPosition( true ) );
176 - });
 174+ .delayedBind( 100, 'keyup mouseup', function() {
 175+ $(this).data( 'wikiEditor-cursor', $(this).getCaretPosition( true ) );
177176
 177+ } );
 178+
178179 // Create a set of standard methods for internal and external use
179180 context.api = {
180181 /**
@@ -237,4 +238,4 @@
238239 // Store the context for next time, and support chaining
239240 return $(this).data( 'wikiEditor-context', context );
240241
241 -};})(jQuery);
\ No newline at end of file
 242+};})(jQuery);
Index: branches/wmf-deployment/extensions/UsabilityInitiative/js/plugins/jquery.wikiEditor.toolbar.js
@@ -222,6 +222,14 @@
223223 parts[part] = ( action.options[part] || '' )
224224 }
225225 }
 226+ if ( 'regex' in action.options && 'regexReplace' in action.options ) {
 227+ var selection = context.$textarea.getSelection();
 228+ if ( selection != '' && selection.match( action.options.regex ) ) {
 229+ parts.peri = selection.replace( action.options.regex,
 230+ action.options.regexReplace );
 231+ parts.pre = parts.post = '';
 232+ }
 233+ }
226234 context.$textarea.encapsulateSelection(
227235 parts.pre, parts.peri, parts.post, action.options.ownline, action.type == 'replace'
228236 );
@@ -243,12 +251,18 @@
244252 if ( label ) {
245253 $group.append( '<div class="label">' + label + '</div>' )
246254 }
 255+
 256+ var empty = true;
247257 if ( 'tools' in group ) {
248258 for ( tool in group.tools ) {
249 - $group.append( $.wikiEditor.modules.toolbar.fn.buildTool( context, tool, group.tools[tool] ) );
 259+ var tool = $.wikiEditor.modules.toolbar.fn.buildTool( context, tool, group.tools[tool] );
 260+ if ( tool ) {
 261+ empty = false;
 262+ $group.append( tool );
 263+ }
250264 }
251265 }
252 - return $group;
 266+ return empty ? null : $group;
253267 },
254268 buildTool : function( context, id, tool ) {
255269 if ( 'filters' in tool ) {
@@ -326,25 +340,23 @@
327341 .text( label )
328342 .attr( 'rel', id )
329343 .data( 'context', context )
330 - .click(
331 - function() {
332 -
333 - $(this).parent().parent().find( '.page' ).hide();
334 - $(this).parent().parent().find( '.page-' + $(this).attr( 'rel' ) ).show();
335 - $(this).siblings().removeClass( 'current' );
336 - $(this).addClass( 'current' );
337 - var section = $(this).parent().parent().attr( 'rel' );
338 -
339 - //click tracking
340 - if($.trackAction != undefined){
341 - $.trackAction(section + '.' + $(this).attr('rel'));
342 - }
343 -
344 - $.cookie(
345 - 'wikiEditor-' + $(this).data( 'context' ).instance + '-booklet-' + section + '-page',
346 - $(this).attr( 'rel' )
347 - );
348 - } );
 344+ .bind( 'mousedown', function() {
 345+ $(this).parent().parent().find( '.page' ).hide();
 346+ $(this).parent().parent().find( '.page-' + $(this).attr( 'rel' ) ).show();
 347+ $(this).siblings().removeClass( 'current' );
 348+ $(this).addClass( 'current' );
 349+ var section = $(this).parent().parent().attr( 'rel' );
 350+
 351+ //click tracking
 352+ if($.trackAction != undefined){
 353+ $.trackAction(section + '.' + $(this).attr('rel'));
 354+ }
 355+
 356+ $.cookie(
 357+ 'wikiEditor-' + $(this).data( 'context' ).instance + '-booklet-' + section + '-page',
 358+ $(this).attr( 'rel' )
 359+ );
 360+ } );
349361 },
350362 buildPage : function( context, id, page ) {
351363 var $page = $( '<div />' ).attr( {
@@ -451,22 +463,30 @@
452464 .attr( 'href', '#' )
453465 .text( $.wikiEditor.autoMsg( section, 'label' ) )
454466 .data( 'context', context )
455 - .click( function() {
 467+ .bind( 'mouseup', function( e ) {
 468+ $(this).blur();
 469+ } )
 470+ .bind( 'click', function( e ) {
456471 var $sections = $(this).data( 'context' ).$ui.find( '.sections' );
457472 var $section =
458473 $(this).data( 'context' ).$ui.find( '.section-' + $(this).parent().attr( 'rel' ) );
459 - $(this).blur();
460474 var show = $section.css( 'display' ) == 'none';
461475 $previousSections = $section.parent().find( '.section:visible' );
462476 $previousSections.css( 'position', 'absolute' );
463477 $previousSections.fadeOut( 'fast', function() { $(this).css( 'position', 'relative' ); } );
464478 $(this).parent().parent().find( 'a' ).removeClass( 'current' );
 479+ $sections.css('overflow', 'hidden');
465480 if ( show ) {
466481 $section.fadeIn( 'fast' );
467 - $sections.animate( { 'height': $section.outerHeight() }, 'fast' );
 482+ $sections.animate( { 'height': $section.outerHeight() }, $section.outerHeight() * 2, function() {
 483+ $(this).css('overflow', 'visible').css('height', 'auto');
 484+ } );
468485 $(this).addClass( 'current' );
469486 } else {
470 - $sections.animate( { 'height': 0 } );
 487+ $sections.css('height', $section.outerHeight() )
 488+ .animate( { 'height': 0 }, $section.outerHeight() * 2, function() {
 489+ $(this).css('overflow', 'visible');
 490+ } );
471491 }
472492 // Click tracking
473493 if($.trackAction != undefined){
@@ -567,7 +587,7 @@
568588 s.$sections.append( $.wikiEditor.modules.toolbar.fn.buildSection( s.context, s.id, s.config ) );
569589 var $section = s.$sections.find( '.section:visible' );
570590 if ( $section.size() ) {
571 - $sections.animate( { 'height': $section.outerHeight() }, 'fast' );
 591+ $sections.animate( { 'height': $section.outerHeight() }, $section.outerHeight() * 2 );
572592 }
573593 }
574594 } );
Property changes on: branches/wmf-deployment/extensions/UsabilityInitiative/js/plugins/jquery.wikiEditor.toolbar.js
___________________________________________________________________
Modified: svn:mergeinfo
575595 Merged /trunk/extensions/UsabilityInitiative/js/plugins/jquery.wikiEditor.toolbar.js:r58923,58926,58953,58973-58974,59202
576596 Merged /branches/usability/acaifix/js/plugins/jquery.wikiEditor.toolbar.js:r58541-59203
Index: branches/wmf-deployment/extensions/UsabilityInitiative/js/plugins/jquery.wikiEditor.toc.js
@@ -1,6 +1,4 @@
2 -/**
3 - * TOC Module for wikiEditor
4 - */
 2+/* TOC Module for wikiEditor */
53 ( function( $ ) { $.wikiEditor.modules.toc = {
64
75 /**
@@ -41,7 +39,7 @@
4240 // Add the TOC to the document
4341 $.wikiEditor.modules.toc.fn.build( context, config );
4442 context.$textarea
45 - .delayedBind( 1000, 'keyup encapsulateSelection change',
 43+ .delayedBind( 250, 'mouseup scrollToPosition focus keyup encapsulateSelection change',
4644 function( event ) {
4745 var context = $(this).data( 'wikiEditor-context' );
4846 $(this).eachAsync( {
@@ -53,25 +51,16 @@
5452 } );
5553 }
5654 )
57 - .bind( 'mouseup scrollToPosition focus keyup encapsulateSelection change',
58 - function( event ) {
59 - var context = $(this).data( 'wikiEditor-context' );
60 - $(this).eachAsync( {
61 - bulk: 0,
62 - loop: function() {
63 - $.wikiEditor.modules.toc.fn.update( context );
64 - }
65 - } );
66 - }
67 - )
6855 .blur( function() {
6956 var context = $(this).data( 'wikiEditor-context' );
 57+ context.$textarea.delayedBindCancel( 250,
 58+ 'mouseup scrollToPosition focus keyup encapsulateSelection change' );
7059 $.wikiEditor.modules.toc.fn.unhighlight( context );
7160 });
7261 },
7362
7463 unhighlight: function( context ) {
75 - context.modules.$toc.find( 'a' ).removeClass( 'currentSelection' );
 64+ context.modules.$toc.find( 'div' ).removeClass( 'current' );
7665 },
7766 /**
7867 * Highlight the section the cursor is currently within
@@ -95,8 +84,8 @@
9685 }
9786 section = Math.max( 0, section );
9887 }
99 - var sectionLink = context.modules.$toc.find( 'a.section-' + section );
100 - sectionLink.addClass( 'currentSelection' );
 88+ var sectionLink = context.modules.$toc.find( 'div.section-' + section );
 89+ sectionLink.addClass( 'current' );
10190
10291 // Scroll the highlighted link into view if necessary
10392 var relTop = sectionLink.offset().top - context.modules.$toc.offset().top;
@@ -145,26 +134,26 @@
146135 * @param {Object} structure Structured outline
147136 */
148137 function buildList( structure ) {
149 - var list = $( '<ul />' );
 138+ var list = $( '<ul></ul>' );
150139 for ( i in structure ) {
151 - var item = $( '<li />' )
152 - .append(
153 - $( '<a />' )
154 - .attr( 'href', '#' )
155 - .addClass( 'section-' + structure[i].index )
156 - .data( 'textbox', context.$textarea )
157 - .data( 'position', structure[i].position )
158 - .click( function( event ) {
159 - $(this).data( 'textbox' )
160 - .focus()
161 - .setSelection( $(this).data( 'position' ) )
162 - .scrollToCaretPosition( true );
163 - if ( typeof $.trackAction != 'undefined' )
164 - $.trackAction( 'ntoc.heading' );
165 - event.preventDefault();
166 - } )
167 - .text( structure[i].text )
168 - );
 140+ var div = $( '<div></div>' )
 141+ .attr( 'href', '#' )
 142+ .addClass( 'section-' + structure[i].index )
 143+ .data( 'textbox', context.$textarea )
 144+ .data( 'position', structure[i].position )
 145+ .bind( 'mousedown', function( event ) {
 146+ $(this).data( 'textbox' )
 147+ .focus()
 148+ .setSelection( $(this).data( 'position' ) )
 149+ .scrollToCaretPosition( true );
 150+ if ( typeof $.trackAction != 'undefined' )
 151+ $.trackAction( 'ntoc.heading' );
 152+ event.preventDefault();
 153+ } )
 154+ .text( structure[i].text );
 155+ if ( structure[i].text == '' )
 156+ div.html( '&nbsp;' );
 157+ var item = $( '<li></li>' ).append( div );
169158 if ( structure[i].sections !== undefined ) {
170159 item.append( buildList( structure[i].sections ) );
171160 }
@@ -175,7 +164,7 @@
176165 // Build outline from wikitext
177166 var outline = [];
178167 var wikitext = $.wikiEditor.fixOperaBrokenness( context.$textarea.val() );
179 - var headings = wikitext.match( /^={1,6}.+={1,6}\s*$/gm );
 168+ var headings = wikitext.match( /^={1,6}[^=\n][^\n]*={1,6}\s*$/gm );
180169 var offset = 0;
181170 headings = $.makeArray( headings );
182171 for ( var h = 0; h < headings.length; h++ ) {
@@ -235,18 +224,11 @@
236225 // Recursively build the structure and add special item for
237226 // section 0, if needed
238227 var structure = buildStructure( outline );
239 - if ( $( 'input[name=wpSection]' ).val() == '' )
 228+ if ( $( 'input[name=wpSection]' ).val() == '' ) {
240229 structure.unshift( { 'text': wgPageName.replace(/_/g, ' '), 'level': 1, 'index': 0, 'position': 0 } );
 230+ }
241231 context.modules.$toc.html( buildList( structure ) );
242 -
243 - context.modules.$toc.find( 'ul' ).css( 'width', '10em' );
244 -
245 - var links = context.modules.$toc.find( 'ul a' );
246 - // Highlighted links are wider; autoEllipse links in
247 - // highlighted state
248 - links.addClass( 'currentSelection' );
249 - links.autoEllipse( { 'position': 'right', 'tooltip': true } );
250 - links.removeClass( 'currentSelection' );
 232+ context.modules.$toc.find( 'div' ).autoEllipse( { 'position': 'right', 'tooltip': true } );
251233 // Cache the outline for later use
252234 context.data.outline = outline;
253235 }
Index: branches/wmf-deployment/extensions/UsabilityInitiative/js/plugins/jquery.collapsibleTabs.js
@@ -0,0 +1,94 @@
 2+( function( $ ) {
 3+
 4+$.fn.collapsibleTabs = function( $$options ) {
 5+ // return if the function is called on an empty jquery object
 6+ if( !this.length ) return this;
 7+ //merge options into the defaults
 8+ var $settings = $.extend( {}, $.collapsibleTabs.defaults, $$options );
 9+
 10+ this.each( function() {
 11+ var $this = $( this );
 12+ // add the element to our array of collapsible managers
 13+ $.collapsibleTabs.instances = ( $.collapsibleTabs.instances.length == 0 ? $this : $.collapsibleTabs.instances.add( $this ) );
 14+ // attach the settings to the elements
 15+ $this.data( 'collapsibleTabsSettings', $settings );
 16+ // attach data to our collapsible elements
 17+ $this.children( $settings.collapsible ).each(function() {
 18+ var $collapsible = $(this);
 19+ $collapsible.data('collapsibleTabsSettings', {
 20+ 'expandedContainer': $settings.expandedContainer,
 21+ 'collapsedContainer': $settings.collapsedContainer,
 22+ 'expandedWidth': $collapsible.width(),
 23+ 'prevElement': $collapsible.prev()
 24+ });
 25+ } );
 26+ } );
 27+
 28+ // if we haven't already bound our resize hanlder, bind it now
 29+ if(!$.collapsibleTabs.boundEvent) $(window).delayedBind('500','resize', function(){ $.collapsibleTabs.handleResize(); });
 30+ // call our resize handler to setup the page
 31+ $.collapsibleTabs.handleResize();
 32+ return this;
 33+};
 34+
 35+$.collapsibleTabs = {
 36+ instances: [],
 37+ boundEvent: null,
 38+ defaults: {
 39+ expandedContainer: '#p-views ul',
 40+ collapsedContainer: '#p-cactions ul',
 41+ collapsible: 'li.collapsible',
 42+ shifting: false,
 43+ expandCondition: function(eleWidth) {
 44+ return ( $('#left-navigation').position().left + $('#left-navigation').width())
 45+ < ($('#right-navigation').position().left - eleWidth);
 46+ },
 47+ collapseCondition: function() {
 48+ return ( $('#left-navigation').position().left + $('#left-navigation').width())
 49+ > $('#right-navigation').position().left;
 50+ }
 51+ },
 52+ handleResize: function(e){
 53+ $.collapsibleTabs.instances.each(function() {
 54+ var $this = $(this), data = $this.data('collapsibleTabsSettings');
 55+ if(data.shifting) return;
 56+
 57+ // if the two navigations are colliding
 58+ if( $this.children(data.collapsible).length > 0 && data.collapseCondition() ) {
 59+
 60+ $this.trigger("beforeTabCollapse");
 61+ // move the element to the dropdown menu
 62+ $.collapsibleTabs.moveToCollapsed($this.children(data.collapsible+':last'));
 63+ }
 64+
 65+ // if there are still moveable items in the dropdown menu,
 66+ // and there is sufficient space to place them in the tab container
 67+ if($(data.collapsedContainer + ' ' + data.collapsible ).length > 0
 68+ && data.expandCondition( $(data.collapsedContainer).children(
 69+ data.collapsible+":first").data('collapsibleTabsSettings').expandedWidth)) {
 70+ //move the element from the dropdown to the tab
 71+ $this.trigger("beforeTabExpand");
 72+ $.collapsibleTabs.moveToExpanded( data.collapsedContainer + " " + data.collapsible + ':first' );
 73+ }
 74+ });
 75+ },
 76+ moveToCollapsed: function( ele ) {
 77+ var $moving = $(ele);
 78+ var data = $moving.data('collapsibleTabsSettings');
 79+ $(data.expandedContainer).data('collapsibleTabsSettings').shifting = true;
 80+ $moving.remove().prependTo(data.collapsedContainer).data('collapsibleTabsSettings', data);
 81+ $(data.expandedContainer).data('collapsibleTabsSettings').shifting = false;
 82+ $.collapsibleTabs.handleResize();
 83+ },
 84+ moveToExpanded: function( ele ) {
 85+ var $moving = $(ele);
 86+ var data = $moving.data('collapsibleTabsSettings');
 87+ $(data.expandedContainer).data('collapsibleTabsSettings').shifting = true;
 88+ // remove this element from where it's at and put it in the dropdown menu
 89+ $moving.remove().insertAfter(data.prevElement).data('collapsibleTabsSettings', data);
 90+ $(data.expandedContainer).data('collapsibleTabsSettings').shifting = false;
 91+ $.collapsibleTabs.handleResize();
 92+ }
 93+};
 94+
 95+} )( jQuery );
\ No newline at end of file
Property changes on: branches/wmf-deployment/extensions/UsabilityInitiative/js/plugins/jquery.collapsibleTabs.js
___________________________________________________________________
Added: svn:eol-style
196 + native
Index: branches/wmf-deployment/extensions/UsabilityInitiative/js/plugins/jquery.autoEllipse.js
@@ -12,30 +12,28 @@
1313 var text = $(this).text();
1414 var $text = $( '<span />' ).text( text ).css( 'whiteSpace', 'nowrap' );
1515 $(this).empty().append( $text );
16 - if ( $text.outerWidth() > $(this).innerWidth() ) {
 16+ if ( $text.width() > $(this).width() ) {
1717 switch ( options.position ) {
1818 case 'right':
19 - // Use binary search-like technique for
20 - // efficiency
 19+ // Use binary search-like technique for efficiency
2120 var l = 0, r = text.length;
22 - var ow, iw;
2321 do {
2422 var m = Math.ceil( ( l + r ) / 2 );
2523 $text.text( text.substr( 0, m ) + '...' );
26 - ow = $text.outerWidth();
27 - iw = $(this).innerWidth();
28 - if ( ow > iw )
 24+ if ( $text.width() > $(this).width() ) {
2925 // Text is too long
3026 r = m - 1;
31 - else
 27+ } else {
3228 l = m;
 29+ }
3330 } while ( l < r );
 31+ $text.text( text.substr( 0, l ) + '...' );
3432 break;
3533 case 'center':
3634 // TODO: Use binary search like for 'right'
3735 var i = [Math.round( text.length / 2 ), Math.round( text.length / 2 )];
3836 var side = 1; // Begin with making the end shorter
39 - while ( $text.outerWidth() > ( $(this).innerWidth() ) && i[0] > 0 ) {
 37+ while ( $text.outerWidth() > ( $(this).width() ) && i[0] > 0 ) {
4038 $text.text( text.substr( 0, i[0] ) + '...' + text.substr( i[1] ) );
4139 // Alternate between trimming the end and begining
4240 if ( side == 0 ) {
@@ -52,7 +50,7 @@
5351 case 'left':
5452 // TODO: Use binary search like for 'right'
5553 var r = 0;
56 - while ( $text.outerWidth() > $(this).innerWidth() && r < text.length ) {
 54+ while ( $text.outerWidth() > $(this).width() && r < text.length ) {
5755 $text.text( '...' + text.substr( r ) );
5856 r++;
5957 }
Index: branches/wmf-deployment/extensions/UsabilityInitiative/js/plugins.combined.js
@@ -90,30 +90,28 @@
9191 var text = $(this).text();
9292 var $text = $( '<span />' ).text( text ).css( 'whiteSpace', 'nowrap' );
9393 $(this).empty().append( $text );
94 - if ( $text.outerWidth() > $(this).innerWidth() ) {
 94+ if ( $text.width() > $(this).width() ) {
9595 switch ( options.position ) {
9696 case 'right':
97 - // Use binary search-like technique for
98 - // efficiency
 97+ // Use binary search-like technique for efficiency
9998 var l = 0, r = text.length;
100 - var ow, iw;
10199 do {
102100 var m = Math.ceil( ( l + r ) / 2 );
103101 $text.text( text.substr( 0, m ) + '...' );
104 - ow = $text.outerWidth();
105 - iw = $(this).innerWidth();
106 - if ( ow > iw )
 102+ if ( $text.width() > $(this).width() ) {
107103 // Text is too long
108104 r = m - 1;
109 - else
 105+ } else {
110106 l = m;
 107+ }
111108 } while ( l < r );
 109+ $text.text( text.substr( 0, l ) + '...' );
112110 break;
113111 case 'center':
114112 // TODO: Use binary search like for 'right'
115113 var i = [Math.round( text.length / 2 ), Math.round( text.length / 2 )];
116114 var side = 1; // Begin with making the end shorter
117 - while ( $text.outerWidth() > ( $(this).innerWidth() ) && i[0] > 0 ) {
 115+ while ( $text.outerWidth() > ( $(this).width() ) && i[0] > 0 ) {
118116 $text.text( text.substr( 0, i[0] ) + '...' + text.substr( i[1] ) );
119117 // Alternate between trimming the end and begining
120118 if ( side == 0 ) {
@@ -130,7 +128,7 @@
131129 case 'left':
132130 // TODO: Use binary search like for 'right'
133131 var r = 0;
134 - while ( $text.outerWidth() > $(this).innerWidth() && r < text.length ) {
 132+ while ( $text.outerWidth() > $(this).width() && r < text.length ) {
135133 $text.text( '...' + text.substr( r ) );
136134 r++;
137135 }
@@ -574,7 +572,7 @@
575573 * @param updateTextbox If true, put the suggestion in the textbox
576574 */
577575 highlight: function( context, result, updateTextbox ) {
578 - var selected = context.data.$container.find( '.suggestions-result-current' )
 576+ var selected = context.data.$container.find( '.suggestions-result-current' );
579577 if ( !result.get || selected.get( 0 ) != result.get( 0 ) ) {
580578 if ( result == 'prev' ) {
581579 result = selected.prev();
@@ -643,6 +641,12 @@
644642 case 13:
645643 context.data.$container.hide();
646644 preventDefault = wasVisible;
 645+ if ( typeof context.config.result.select == 'function' ) {
 646+ context.config.result.select.call(
 647+ context.data.$container.find( '.suggestions-result-current' ),
 648+ context.data.$textbox
 649+ );
 650+ }
647651 break;
648652 default:
649653 $.suggestions.update( context, true );
@@ -827,12 +831,17 @@
828832 */
829833 ( function( $ ) { $.fn.extend( {
830834
 835+/**
 836+ * Get the currently selected text in this textarea. Will focus the textarea
 837+ * in some browsers (IE/Opera)
 838+ */
831839 getSelection: function() {
832840 var e = this.jquery ? this[0] : this;
833841 var retval = '';
834842 if ( e.style.display == 'none' ) {
835843 // Do nothing
836844 } else if ( document.selection && document.selection.createRange ) {
 845+ e.focus();
837846 var range = document.selection.createRange();
838847 retval = range.text;
839848 } else if ( e.selectionStart || e.selectionStart == '0' ) {
@@ -870,13 +879,12 @@
871880 post += ' ';
872881 }
873882 }
874 - var selText = $(this).getSelection();
 883+ var selText = $(this).focus().getSelection();
875884 var isSample = false;
876885 if ( this.style.display == 'none' ) {
877886 // Do nothing
878887 } else if ( this.selectionStart || this.selectionStart == '0' ) {
879888 // Mozilla/Opera
880 - $(this).focus();
881889 var startPos = this.selectionStart;
882890 var endPos = this.selectionEnd;
883891 checkSelectedText();
@@ -901,9 +909,10 @@
902910 this.selectionStart = startPos + pre.length + selText.length + post.length;
903911 this.selectionEnd = this.selectionStart;
904912 }
 913+ // Scroll the textarea to the inserted text
 914+ $(this).scrollToCaretPosition();
905915 } else if ( document.selection && document.selection.createRange ) {
906916 // IE
907 - $(this).focus();
908917 var range = document.selection.createRange();
909918 if ( ownline && range.moveStart ) {
910919 var range2 = document.selection.createRange();
@@ -928,8 +937,6 @@
929938 }
930939 range.select();
931940 }
932 - // Scroll the textarea to the inserted text
933 - $(this).scrollToCaretPosition();
934941 $(this).trigger( 'encapsulateSelection', [ pre, peri, post, ownline, replace ] );
935942 });
936943 },
@@ -942,11 +949,18 @@
943950 * Get the position (in resolution of bytes not nessecarily characters)
944951 * in a textarea
945952 */
946 - getCaretPosition: function( startAndEnd ) {
 953+ getCaretPosition: function( startAndEnd, restoreFocus ) {
947954 function getCaret( e ) {
948955 var caretPos = 0, endPos = 0;
949956 if ( $.browser.msie ) {
950957 // IE Support
 958+ // Focus the textarea for this
 959+ // If another element currently has focus, restore it
 960+ var oldFocus = false;
 961+ if ( restoreFocus )
 962+ oldFocus = document.selection.createRange().parentElement;
 963+ e.focus();
 964+
951965 var postFinished = false;
952966 var periFinished = false;
953967 var postFinished = false;
@@ -1015,6 +1029,9 @@
10161030 } while ( ( !postFinished || !periFinished || !postFinished ) );
10171031 caretPos = rawPreText.replace( /\r\n/g, "\n" ).length;
10181032 endPos = caretPos + rawPeriText.replace( /\r\n/g, "\n" ).length;
 1033+ // Restore focus
 1034+ if ( oldFocus && oldFocus.focus )
 1035+ oldFocus.focus();
10191036 } else if ( e.selectionStart || e.selectionStart == '0' ) {
10201037 // Firefox support
10211038 caretPos = e.selectionStart;
@@ -1043,8 +1060,12 @@
10441061 var selection = document.body.createTextRange();
10451062 selection.moveToElementText( this );
10461063 var length = selection.text.length;
 1064+ if ( start > length || end > length )
 1065+ // Faulty data, ignore
 1066+ return;
 1067+ selection.collapse();
 1068+ selection.moveEnd( 'character', end );
10471069 selection.moveStart( 'character', start );
1048 - selection.moveEnd( 'character', -length + end );
10491070 selection.select();
10501071 }
10511072 });
@@ -1140,7 +1161,8 @@
11411162 } );
11421163 }
11431164
1144 -} ); } )( jQuery );/**
 1165+} ); } )( jQuery );
 1166+/**
11451167 * This plugin provides a way to build a user interface around a textarea. You
11461168 * can build the UI from a confguration..
11471169 * $j( 'div#edittoolbar' ).wikiEditor(
@@ -1312,10 +1334,11 @@
13131335 $(this).setSelection( pos[0], pos[1] );
13141336 $(this).data( 'wikiEditor-cursor', false );
13151337 })
1316 - .blur( function() {
1317 - $(this).data( 'wikiEditor-cursor', $(this).getCaretPosition( true ) );
1318 - });
 1338+ .delayedBind( 100, 'keyup mouseup', function() {
 1339+ $(this).data( 'wikiEditor-cursor', $(this).getCaretPosition( true ) );
13191340
 1341+ } );
 1342+
13201343 // Create a set of standard methods for internal and external use
13211344 context.api = {
13221345 /**
@@ -1379,7 +1402,8 @@
13801403 // Store the context for next time, and support chaining
13811404 return $(this).data( 'wikiEditor-context', context );
13821405
1383 -};})(jQuery);/**
 1406+};})(jQuery);
 1407+/**
13841408 * Extend the RegExp object with an escaping function
13851409 * From http://simonwillison.net/2006/Jan/20/escape/
13861410 */
@@ -1745,6 +1769,14 @@
17461770 parts[part] = ( action.options[part] || '' )
17471771 }
17481772 }
 1773+ if ( 'regex' in action.options && 'regexReplace' in action.options ) {
 1774+ var selection = context.$textarea.getSelection();
 1775+ if ( selection != '' && selection.match( action.options.regex ) ) {
 1776+ parts.peri = selection.replace( action.options.regex,
 1777+ action.options.regexReplace );
 1778+ parts.pre = parts.post = '';
 1779+ }
 1780+ }
17491781 context.$textarea.encapsulateSelection(
17501782 parts.pre, parts.peri, parts.post, action.options.ownline, action.type == 'replace'
17511783 );
@@ -1766,12 +1798,18 @@
17671799 if ( label ) {
17681800 $group.append( '<div class="label">' + label + '</div>' )
17691801 }
 1802+
 1803+ var empty = true;
17701804 if ( 'tools' in group ) {
17711805 for ( tool in group.tools ) {
1772 - $group.append( $.wikiEditor.modules.toolbar.fn.buildTool( context, tool, group.tools[tool] ) );
 1806+ var tool = $.wikiEditor.modules.toolbar.fn.buildTool( context, tool, group.tools[tool] );
 1807+ if ( tool ) {
 1808+ empty = false;
 1809+ $group.append( tool );
 1810+ }
17731811 }
17741812 }
1775 - return $group;
 1813+ return empty ? null : $group;
17761814 },
17771815 buildTool : function( context, id, tool ) {
17781816 if ( 'filters' in tool ) {
@@ -1849,25 +1887,23 @@
18501888 .text( label )
18511889 .attr( 'rel', id )
18521890 .data( 'context', context )
1853 - .click(
1854 - function() {
1855 -
1856 - $(this).parent().parent().find( '.page' ).hide();
1857 - $(this).parent().parent().find( '.page-' + $(this).attr( 'rel' ) ).show();
1858 - $(this).siblings().removeClass( 'current' );
1859 - $(this).addClass( 'current' );
1860 - var section = $(this).parent().parent().attr( 'rel' );
1861 -
1862 - //click tracking
1863 - if($.trackAction != undefined){
1864 - $.trackAction(section + '.' + $(this).attr('rel'));
1865 - }
1866 -
1867 - $.cookie(
1868 - 'wikiEditor-' + $(this).data( 'context' ).instance + '-booklet-' + section + '-page',
1869 - $(this).attr( 'rel' )
1870 - );
1871 - } );
 1891+ .bind( 'mousedown', function() {
 1892+ $(this).parent().parent().find( '.page' ).hide();
 1893+ $(this).parent().parent().find( '.page-' + $(this).attr( 'rel' ) ).show();
 1894+ $(this).siblings().removeClass( 'current' );
 1895+ $(this).addClass( 'current' );
 1896+ var section = $(this).parent().parent().attr( 'rel' );
 1897+
 1898+ //click tracking
 1899+ if($.trackAction != undefined){
 1900+ $.trackAction(section + '.' + $(this).attr('rel'));
 1901+ }
 1902+
 1903+ $.cookie(
 1904+ 'wikiEditor-' + $(this).data( 'context' ).instance + '-booklet-' + section + '-page',
 1905+ $(this).attr( 'rel' )
 1906+ );
 1907+ } );
18721908 },
18731909 buildPage : function( context, id, page ) {
18741910 var $page = $( '<div />' ).attr( {
@@ -1974,22 +2010,30 @@
19752011 .attr( 'href', '#' )
19762012 .text( $.wikiEditor.autoMsg( section, 'label' ) )
19772013 .data( 'context', context )
1978 - .click( function() {
 2014+ .bind( 'mouseup', function( e ) {
 2015+ $(this).blur();
 2016+ } )
 2017+ .bind( 'click', function( e ) {
19792018 var $sections = $(this).data( 'context' ).$ui.find( '.sections' );
19802019 var $section =
19812020 $(this).data( 'context' ).$ui.find( '.section-' + $(this).parent().attr( 'rel' ) );
1982 - $(this).blur();
19832021 var show = $section.css( 'display' ) == 'none';
19842022 $previousSections = $section.parent().find( '.section:visible' );
19852023 $previousSections.css( 'position', 'absolute' );
19862024 $previousSections.fadeOut( 'fast', function() { $(this).css( 'position', 'relative' ); } );
19872025 $(this).parent().parent().find( 'a' ).removeClass( 'current' );
 2026+ $sections.css('overflow', 'hidden');
19882027 if ( show ) {
19892028 $section.fadeIn( 'fast' );
1990 - $sections.animate( { 'height': $section.outerHeight() }, 'fast' );
 2029+ $sections.animate( { 'height': $section.outerHeight() }, $section.outerHeight() * 2, function() {
 2030+ $(this).css('overflow', 'visible').css('height', 'auto');
 2031+ } );
19912032 $(this).addClass( 'current' );
19922033 } else {
1993 - $sections.animate( { 'height': 0 } );
 2034+ $sections.css('height', $section.outerHeight() )
 2035+ .animate( { 'height': 0 }, $section.outerHeight() * 2, function() {
 2036+ $(this).css('overflow', 'visible');
 2037+ } );
19942038 }
19952039 // Click tracking
19962040 if($.trackAction != undefined){
@@ -2090,7 +2134,7 @@
20912135 s.$sections.append( $.wikiEditor.modules.toolbar.fn.buildSection( s.context, s.id, s.config ) );
20922136 var $section = s.$sections.find( '.section:visible' );
20932137 if ( $section.size() ) {
2094 - $sections.animate( { 'height': $section.outerHeight() }, 'fast' );
 2138+ $sections.animate( { 'height': $section.outerHeight() }, $section.outerHeight() * 2 );
20952139 }
20962140 }
20972141 } );
@@ -2098,9 +2142,7 @@
20992143 }
21002144
21012145 }; } )( jQuery );
2102 -/**
2103 - * TOC Module for wikiEditor
2104 - */
 2146+/* TOC Module for wikiEditor */
21052147 ( function( $ ) { $.wikiEditor.modules.toc = {
21062148
21072149 /**
@@ -2141,7 +2183,7 @@
21422184 // Add the TOC to the document
21432185 $.wikiEditor.modules.toc.fn.build( context, config );
21442186 context.$textarea
2145 - .delayedBind( 1000, 'keyup encapsulateSelection change',
 2187+ .delayedBind( 250, 'mouseup scrollToPosition focus keyup encapsulateSelection change',
21462188 function( event ) {
21472189 var context = $(this).data( 'wikiEditor-context' );
21482190 $(this).eachAsync( {
@@ -2153,25 +2195,16 @@
21542196 } );
21552197 }
21562198 )
2157 - .bind( 'mouseup scrollToPosition focus keyup encapsulateSelection change',
2158 - function( event ) {
2159 - var context = $(this).data( 'wikiEditor-context' );
2160 - $(this).eachAsync( {
2161 - bulk: 0,
2162 - loop: function() {
2163 - $.wikiEditor.modules.toc.fn.update( context );
2164 - }
2165 - } );
2166 - }
2167 - )
21682199 .blur( function() {
21692200 var context = $(this).data( 'wikiEditor-context' );
 2201+ context.$textarea.delayedBindCancel( 250,
 2202+ 'mouseup scrollToPosition focus keyup encapsulateSelection change' );
21702203 $.wikiEditor.modules.toc.fn.unhighlight( context );
21712204 });
21722205 },
21732206
21742207 unhighlight: function( context ) {
2175 - context.modules.$toc.find( 'a' ).removeClass( 'currentSelection' );
 2208+ context.modules.$toc.find( 'div' ).removeClass( 'current' );
21762209 },
21772210 /**
21782211 * Highlight the section the cursor is currently within
@@ -2195,8 +2228,8 @@
21962229 }
21972230 section = Math.max( 0, section );
21982231 }
2199 - var sectionLink = context.modules.$toc.find( 'a.section-' + section );
2200 - sectionLink.addClass( 'currentSelection' );
 2232+ var sectionLink = context.modules.$toc.find( 'div.section-' + section );
 2233+ sectionLink.addClass( 'current' );
22012234
22022235 // Scroll the highlighted link into view if necessary
22032236 var relTop = sectionLink.offset().top - context.modules.$toc.offset().top;
@@ -2245,26 +2278,26 @@
22462279 * @param {Object} structure Structured outline
22472280 */
22482281 function buildList( structure ) {
2249 - var list = $( '<ul />' );
 2282+ var list = $( '<ul></ul>' );
22502283 for ( i in structure ) {
2251 - var item = $( '<li />' )
2252 - .append(
2253 - $( '<a />' )
2254 - .attr( 'href', '#' )
2255 - .addClass( 'section-' + structure[i].index )
2256 - .data( 'textbox', context.$textarea )
2257 - .data( 'position', structure[i].position )
2258 - .click( function( event ) {
2259 - $(this).data( 'textbox' )
2260 - .focus()
2261 - .setSelection( $(this).data( 'position' ) )
2262 - .scrollToCaretPosition( true );
2263 - if ( typeof $.trackAction != 'undefined' )
2264 - $.trackAction( 'ntoc.heading' );
2265 - event.preventDefault();
2266 - } )
2267 - .text( structure[i].text )
2268 - );
 2284+ var div = $( '<div></div>' )
 2285+ .attr( 'href', '#' )
 2286+ .addClass( 'section-' + structure[i].index )
 2287+ .data( 'textbox', context.$textarea )
 2288+ .data( 'position', structure[i].position )
 2289+ .bind( 'mousedown', function( event ) {
 2290+ $(this).data( 'textbox' )
 2291+ .focus()
 2292+ .setSelection( $(this).data( 'position' ) )
 2293+ .scrollToCaretPosition( true );
 2294+ if ( typeof $.trackAction != 'undefined' )
 2295+ $.trackAction( 'ntoc.heading' );
 2296+ event.preventDefault();
 2297+ } )
 2298+ .text( structure[i].text );
 2299+ if ( structure[i].text == '' )
 2300+ div.html( '&nbsp;' );
 2301+ var item = $( '<li></li>' ).append( div );
22692302 if ( structure[i].sections !== undefined ) {
22702303 item.append( buildList( structure[i].sections ) );
22712304 }
@@ -2275,7 +2308,7 @@
22762309 // Build outline from wikitext
22772310 var outline = [];
22782311 var wikitext = $.wikiEditor.fixOperaBrokenness( context.$textarea.val() );
2279 - var headings = wikitext.match( /^={1,6}.+={1,6}\s*$/gm );
 2312+ var headings = wikitext.match( /^={1,6}[^=\n][^\n]*={1,6}\s*$/gm );
22802313 var offset = 0;
22812314 headings = $.makeArray( headings );
22822315 for ( var h = 0; h < headings.length; h++ ) {
@@ -2335,18 +2368,11 @@
23362369 // Recursively build the structure and add special item for
23372370 // section 0, if needed
23382371 var structure = buildStructure( outline );
2339 - if ( $( 'input[name=wpSection]' ).val() == '' )
 2372+ if ( $( 'input[name=wpSection]' ).val() == '' ) {
23402373 structure.unshift( { 'text': wgPageName.replace(/_/g, ' '), 'level': 1, 'index': 0, 'position': 0 } );
 2374+ }
23412375 context.modules.$toc.html( buildList( structure ) );
2342 -
2343 - context.modules.$toc.find( 'ul' ).css( 'width', '10em' );
2344 -
2345 - var links = context.modules.$toc.find( 'ul a' );
2346 - // Highlighted links are wider; autoEllipse links in
2347 - // highlighted state
2348 - links.addClass( 'currentSelection' );
2349 - links.autoEllipse( { 'position': 'right', 'tooltip': true } );
2350 - links.removeClass( 'currentSelection' );
 2376+ context.modules.$toc.find( 'div' ).autoEllipse( { 'position': 'right', 'tooltip': true } );
23512377 // Cache the outline for later use
23522378 context.data.outline = outline;
23532379 }
Index: branches/wmf-deployment/extensions/UsabilityInitiative/js/plugins.combined.min.js
@@ -11,10 +11,8 @@
1212 {var i=0,l=array.length,loop=opts.loop||function(){};$.whileAsync($.extend(opts,{test:function(){return i<l;},loop:function()
1313 {var val=array[i];return loop.call(val,i++,val);}}));}
1414 $.fn.eachAsync=function(opts)
15 -{$.eachAsync(this,opts);return this;}})(jQuery);(function($){$.fn.autoEllipse=function(options){$(this).each(function(){options=$.extend({'position':'center','tooltip':false},options);var text=$(this).text();var $text=$('<span />').text(text).css('whiteSpace','nowrap');$(this).empty().append($text);if($text.outerWidth()>$(this).innerWidth()){switch(options.position){case'right':var l=0,r=text.length;var ow,iw;do{var m=Math.ceil((l+r)/2);$text.text(text.substr(0,m)+'...');ow=$text.outerWidth();iw=$(this).innerWidth();if(ow>iw)
16 -r=m-1;else
17 -l=m;}while(l<r);break;case'center':var i=[Math.round(text.length/2),Math.round(text.length/2)];var side=1;while($text.outerWidth()>($(this).innerWidth())&&i[0]>0){$text.text(text.substr(0,i[0])+'...'+text.substr(i[1]));if(side==0){i[0]--;side=1;}else{i[1]++;side=0;}}
18 -break;case'left':var r=0;while($text.outerWidth()>$(this).innerWidth()&&r<text.length){$text.text('...'+text.substr(r));r++;}
 15+{$.eachAsync(this,opts);return this;}})(jQuery);(function($){$.fn.autoEllipse=function(options){$(this).each(function(){options=$.extend({'position':'center','tooltip':false},options);var text=$(this).text();var $text=$('<span />').text(text).css('whiteSpace','nowrap');$(this).empty().append($text);if($text.width()>$(this).width()){switch(options.position){case'right':var l=0,r=text.length;do{var m=Math.ceil((l+r)/2);$text.text(text.substr(0,m)+'...');if($text.width()>$(this).width()){r=m-1;}else{l=m;}}while(l<r);$text.text(text.substr(0,l)+'...');break;case'center':var i=[Math.round(text.length/2),Math.round(text.length/2)];var side=1;while($text.outerWidth()>($(this).width())&&i[0]>0){$text.text(text.substr(0,i[0])+'...'+text.substr(i[1]));if(side==0){i[0]--;side=1;}else{i[1]++;side=0;}}
 16+break;case'left':var r=0;while($text.outerWidth()>$(this).width()&&r<text.length){$text.text('...'+text.substr(r));r++;}
1917 break;}
2018 if(options.tooltip)
2119 $text.attr('title',text);}});};})(jQuery);(function($){$.browserTest=function(a,z){var u='unknown',x='X',m=function(r,h){for(var i=0;i<h.length;i=i+1){r=r.replace(h[i][0],h[i][1]);}
@@ -35,15 +33,15 @@
3634 if(context.data.timerID!=null){clearTimeout(context.data.timerID);}
3735 if(delayed){context.data.timerID=setTimeout(maybeFetch,context.config.delay);}else{maybeFetch();}
3836 $.suggestions.special(context);},special:function(context){if(typeof context.config.special.render=='function'){setTimeout(function(){$special=context.data.$container.find('.suggestions-special');context.config.special.render.call($special,context.data.$textbox.val());},1);}},configure:function(context,property,value){switch(property){case'fetch':case'cancel':case'special':case'result':case'$region':context.config[property]=value;break;case'suggestions':context.config[property]=value;if(typeof context.data!=='undefined'){if(context.config.suggestions.length==0){context.data.$container.hide();}else{context.data.$container.show();context.data.$container.css({'top':context.config.$region.offset().top+context.config.$region.outerHeight(),'bottom':'auto','width':context.config.$region.outerWidth(),'height':'auto','left':context.config.$region.offset().left,'right':'auto'});var $results=context.data.$container.children('.suggestions-results');$results.empty();for(var i=0;i<context.config.suggestions.length;i++){$result=$('<div />').addClass('suggestions-result').attr('rel',i).data('text',context.config.suggestions[i]).appendTo($results);if(typeof context.config.result.render=='function'){context.config.result.render.call($result,context.config.suggestions[i]);}else{$result.text(context.config.suggestions[i]).autoEllipse();}}}}
39 -break;case'maxRows':context.config[property]=Math.max(1,Math.min(100,value));break;case'delay':context.config[property]=Math.max(0,Math.min(12000,value));break;case'submitOnClick':context.config[property]=value?true:false;break;}},highlight:function(context,result,updateTextbox){var selected=context.data.$container.find('.suggestions-result-current')
40 -if(!result.get||selected.get(0)!=result.get(0)){if(result=='prev'){result=selected.prev();}else if(result=='next'){if(selected.size()==0)
 37+break;case'maxRows':context.config[property]=Math.max(1,Math.min(100,value));break;case'delay':context.config[property]=Math.max(0,Math.min(12000,value));break;case'submitOnClick':context.config[property]=value?true:false;break;}},highlight:function(context,result,updateTextbox){var selected=context.data.$container.find('.suggestions-result-current');if(!result.get||selected.get(0)!=result.get(0)){if(result=='prev'){result=selected.prev();}else if(result=='next'){if(selected.size()==0)
4138 result=context.data.$container.find('.suggestions-results div:first');else{result=selected.next();if(result.size()==0)
4239 result=selected;}}
4340 selected.removeClass('suggestions-result-current');result.addClass('suggestions-result-current');}
4441 if(updateTextbox){if(result.size()==0){$.suggestions.restore(context);}else{context.data.$textbox.val(result.data('text'));context.data.$textbox.change();}}
4542 $.suggestions.special(context);},keypress:function(e,context,key){var wasVisible=context.data.$container.is(':visible');var preventDefault=false;switch(key){case 40:if(wasVisible){$.suggestions.highlight(context,'next',true);}else{$.suggestions.update(context,false);}
4643 context.data.$textbox.trigger('change');preventDefault=true;break;case 38:if(wasVisible){$.suggestions.highlight(context,'prev',true);}
47 -context.data.$textbox.trigger('change');preventDefault=wasVisible;break;case 27:context.data.$container.hide();$.suggestions.restore(context);$.suggestions.cancel(context);context.data.$textbox.trigger('change');preventDefault=wasVisible;break;case 13:context.data.$container.hide();preventDefault=wasVisible;break;default:$.suggestions.update(context,true);break;}
 44+context.data.$textbox.trigger('change');preventDefault=wasVisible;break;case 27:context.data.$container.hide();$.suggestions.restore(context);$.suggestions.cancel(context);context.data.$textbox.trigger('change');preventDefault=wasVisible;break;case 13:context.data.$container.hide();preventDefault=wasVisible;if(typeof context.config.result.select=='function'){context.config.result.select.call(context.data.$container.find('.suggestions-result-current'),context.data.$textbox);}
 45+break;default:$.suggestions.update(context,true);break;}
4846 if(preventDefault){e.preventDefault();e.stopImmediatePropagation();}}};$.fn.suggestions=function(){var returnValue=null;var args=arguments;$(this).each(function(){var context=$(this).data('suggestions-context');if(typeof context=='undefined'){context={config:{'fetch':function(){},'cancel':function(){},'special':{},'result':{},'$region':$(this),'suggestions':[],'maxRows':7,'delay':1200,'submitOnClick':false}};}
4947 if(args.length>0){if(typeof args[0]=='object'){for(key in args[0]){$.suggestions.configure(context,key,args[0][key]);}}else if(typeof args[0]=='string'){if(args.length>1){$.suggestions.configure(context,args[0],args[1]);}else if(returnValue==null){returnValue=(args[0]in context.config?undefined:context.config[args[0]]);}}}
5048 if(typeof context.data=='undefined'){context.data={'timerID':null,'prevText':null,'visibleResults':0,'mouseDownOn':$([]),'$textbox':$(this)};context.data.$container=$('<div />').css({'top':Math.round(context.data.$textbox.offset().top+context.data.$textbox.outerHeight()),'left':Math.round(context.data.$textbox.offset().left),'width':context.data.$textbox.outerWidth(),'display':'none'}).mouseover(function(e){$.suggestions.highlight(context,$(e.target).closest('.suggestions-results div'),false);}).addClass('suggestions').append($('<div />').addClass('suggestions-results').mousedown(function(e){context.data.mouseDownOn=$(e.target).closest('.suggestions-results div');}).mouseup(function(e){var $result=$(e.target).closest('.suggestions-results div');var $other=context.data.mouseDownOn;context.data.mouseDownOn=$([]);if($result.get(0)!=$other.get(0)){return;}
@@ -52,24 +50,28 @@
5351 context.data.$container.hide();if(typeof context.config.special.select=='function'){context.config.special.select.call($special,context.data.$textbox);}
5452 context.data.$textbox.focus();})).appendTo($('body'));$(this).attr('autocomplete','off').keydown(function(e){context.data.keypressed=(e.keyCode==undefined)?e.which:e.keyCode;context.data.keypressedCount=0;switch(context.data.keypressed){case 40:e.preventDefault();e.stopImmediatePropagation();break;case 38:case 27:case 13:if(context.data.$container.is(':visible')){e.preventDefault();e.stopImmediatePropagation();}}}).keypress(function(e){context.data.keypressedCount++;$.suggestions.keypress(e,context,context.data.keypressed);}).keyup(function(e){if(context.data.keypressedCount==0){$.suggestions.keypress(e,context,context.data.keypressed);}}).blur(function(){if(context.data.mouseDownOn.size()>0){return;}
5553 context.data.$container.hide();$.suggestions.cancel(context);});}
56 -$(this).data('suggestions-context',context);});return returnValue!==null?returnValue:$(this);};})(jQuery);(function($){$.fn.extend({getSelection:function(){var e=this.jquery?this[0]:this;var retval='';if(e.style.display=='none'){}else if(document.selection&&document.selection.createRange){var range=document.selection.createRange();retval=range.text;}else if(e.selectionStart||e.selectionStart=='0'){retval=e.value.substring(e.selectionStart,e.selectionEnd);}
 54+$(this).data('suggestions-context',context);});return returnValue!==null?returnValue:$(this);};})(jQuery);(function($){$.fn.extend({getSelection:function(){var e=this.jquery?this[0]:this;var retval='';if(e.style.display=='none'){}else if(document.selection&&document.selection.createRange){e.focus();var range=document.selection.createRange();retval=range.text;}else if(e.selectionStart||e.selectionStart=='0'){retval=e.value.substring(e.selectionStart,e.selectionEnd);}
5755 return retval;},encapsulateSelection:function(pre,peri,post,ownline,replace){return this.each(function(){function checkSelectedText(){if(!selText){selText=peri;isSample=true;}else if(replace){selText=peri;}else if(selText.charAt(selText.length-1)==' '){selText=selText.substring(0,selText.length-1);post+=' ';}}
58 -var selText=$(this).getSelection();var isSample=false;if(this.style.display=='none'){}else if(this.selectionStart||this.selectionStart=='0'){$(this).focus();var startPos=this.selectionStart;var endPos=this.selectionEnd;checkSelectedText();if(ownline){if(startPos!=0&&this.value.charAt(startPos-1)!="\n"){pre="\n"+pre;}
 56+var selText=$(this).focus().getSelection();var isSample=false;if(this.style.display=='none'){}else if(this.selectionStart||this.selectionStart=='0'){var startPos=this.selectionStart;var endPos=this.selectionEnd;checkSelectedText();if(ownline){if(startPos!=0&&this.value.charAt(startPos-1)!="\n"){pre="\n"+pre;}
5957 if(this.value.charAt(endPos)!="\n"){post+="\n";}}
6058 this.value=this.value.substring(0,startPos)+pre+selText+post+this.value.substring(endPos,this.value.length);if(window.opera){pre=pre.replace(/\r?\n/g,"\r\n");selText=selText.replace(/\r?\n/g,"\r\n");post=post.replace(/\r?\n/g,"\r\n");}
61 -if(isSample){this.selectionStart=startPos+pre.length;this.selectionEnd=startPos+pre.length+selText.length;}else{this.selectionStart=startPos+pre.length+selText.length+post.length;this.selectionEnd=this.selectionStart;}}else if(document.selection&&document.selection.createRange){$(this).focus();var range=document.selection.createRange();if(ownline&&range.moveStart){var range2=document.selection.createRange();range2.collapse();range2.moveStart('character',-1);if(range2.text!="\r"&&range2.text!="\n"&&range2.text!=""){pre="\n"+pre;}
 59+if(isSample){this.selectionStart=startPos+pre.length;this.selectionEnd=startPos+pre.length+selText.length;}else{this.selectionStart=startPos+pre.length+selText.length+post.length;this.selectionEnd=this.selectionStart;}
 60+$(this).scrollToCaretPosition();}else if(document.selection&&document.selection.createRange){var range=document.selection.createRange();if(ownline&&range.moveStart){var range2=document.selection.createRange();range2.collapse();range2.moveStart('character',-1);if(range2.text!="\r"&&range2.text!="\n"&&range2.text!=""){pre="\n"+pre;}
6261 var range3=document.selection.createRange();range3.collapse(false);range3.moveEnd('character',1);if(range3.text!="\r"&&range3.text!="\n"&&range3.text!=""){post+="\n";}}
6362 checkSelectedText();range.text=pre+selText+post;if(isSample&&range.moveStart){range.moveStart('character',-post.length-selText.length);range.moveEnd('character',-post.length);}
6463 range.select();}
65 -$(this).scrollToCaretPosition();$(this).trigger('encapsulateSelection',[pre,peri,post,ownline,replace]);});},getCaretPosition:function(startAndEnd){function getCaret(e){var caretPos=0,endPos=0;if($.browser.msie){var postFinished=false;var periFinished=false;var postFinished=false;var preText,rawPreText,periText;var rawPeriText,postText,rawPostText;var periRange=document.selection.createRange().duplicate();var preRange=document.body.createTextRange();preRange.moveToElementText(e);preRange.setEndPoint("EndToStart",periRange);var postRange=document.body.createTextRange();postRange.moveToElementText(e);postRange.setEndPoint("StartToEnd",periRange);preText=rawPreText=preRange.text;periText=rawPeriText=periRange.text;postText=rawPostText=postRange.text;do{if(!postFinished){if(preRange.compareEndPoints("StartToEnd",preRange)==0){postFinished=true;}else{preRange.moveEnd("character",-1)
 64+$(this).trigger('encapsulateSelection',[pre,peri,post,ownline,replace]);});},getCaretPosition:function(startAndEnd,restoreFocus){function getCaret(e){var caretPos=0,endPos=0;if($.browser.msie){var oldFocus=false;if(restoreFocus)
 65+oldFocus=document.selection.createRange().parentElement;e.focus();var postFinished=false;var periFinished=false;var postFinished=false;var preText,rawPreText,periText;var rawPeriText,postText,rawPostText;var periRange=document.selection.createRange().duplicate();var preRange=document.body.createTextRange();preRange.moveToElementText(e);preRange.setEndPoint("EndToStart",periRange);var postRange=document.body.createTextRange();postRange.moveToElementText(e);postRange.setEndPoint("StartToEnd",periRange);preText=rawPreText=preRange.text;periText=rawPeriText=periRange.text;postText=rawPostText=postRange.text;do{if(!postFinished){if(preRange.compareEndPoints("StartToEnd",preRange)==0){postFinished=true;}else{preRange.moveEnd("character",-1)
6666 if(preRange.text==preText){rawPreText+="\r\n";}else{postFinished=true;}}}
6767 if(!periFinished){if(periRange.compareEndPoints("StartToEnd",periRange)==0){periFinished=true;}else{periRange.moveEnd("character",-1)
6868 if(periRange.text==periText){rawPeriText+="\r\n";}else{periFinished=true;}}}
6969 if(!postFinished){if(postRange.compareEndPoints("StartToEnd",postRange)==0){postFinished=true;}else{postRange.moveEnd("character",-1)
70 -if(postRange.text==postText){rawPostText+="\r\n";}else{postFinished=true;}}}}while((!postFinished||!periFinished||!postFinished));caretPos=rawPreText.replace(/\r\n/g,"\n").length;endPos=caretPos+rawPeriText.replace(/\r\n/g,"\n").length;}else if(e.selectionStart||e.selectionStart=='0'){caretPos=e.selectionStart;endPos=e.selectionEnd;}
 70+if(postRange.text==postText){rawPostText+="\r\n";}else{postFinished=true;}}}}while((!postFinished||!periFinished||!postFinished));caretPos=rawPreText.replace(/\r\n/g,"\n").length;endPos=caretPos+rawPeriText.replace(/\r\n/g,"\n").length;if(oldFocus&&oldFocus.focus)
 71+oldFocus.focus();}else if(e.selectionStart||e.selectionStart=='0'){caretPos=e.selectionStart;endPos=e.selectionEnd;}
7172 return startAndEnd?[caretPos,endPos]:caretPos;}
7273 return getCaret(this.get(0));},setSelection:function(start,end){if(typeof end=='undefined')
73 -end=start;return this.each(function(){if(this.selectionStart||this.selectionStart=='0'){if(start>this.selectionEnd){this.selectionEnd=end;this.selectionStart=start;}else{this.selectionStart=start;this.selectionEnd=end;}}else if(document.body.createTextRange){var selection=document.body.createTextRange();selection.moveToElementText(this);var length=selection.text.length;selection.moveStart('character',start);selection.moveEnd('character',-length+end);selection.select();}});},scrollToCaretPosition:function(force){function getLineLength(e){return Math.floor(e.scrollWidth/($.os.name=='linux'?7:8));}
 74+end=start;return this.each(function(){if(this.selectionStart||this.selectionStart=='0'){if(start>this.selectionEnd){this.selectionEnd=end;this.selectionStart=start;}else{this.selectionStart=start;this.selectionEnd=end;}}else if(document.body.createTextRange){var selection=document.body.createTextRange();selection.moveToElementText(this);var length=selection.text.length;if(start>length||end>length)
 75+return;selection.collapse();selection.moveEnd('character',end);selection.moveStart('character',start);selection.select();}});},scrollToCaretPosition:function(force){function getLineLength(e){return Math.floor(e.scrollWidth/($.os.name=='linux'?7:8));}
7476 function getCaretScrollPosition(e){var text=e.value.replace(/\r/g,"");var caret=$(e).getCaretPosition();var lineLength=getLineLength(e);var row=0;var charInLine=0;var lastSpaceInLine=0;for(i=0;i<caret;i++){charInLine++;if(text.charAt(i)==" "){lastSpaceInLine=charInLine;}else if(text.charAt(i)=="\n"){lastSpaceInLine=0;charInLine=0;row++;}
7577 if(charInLine>lineLength){if(lastSpaceInLine>0){charInLine=charInLine-lastSpaceInLine;lastSpaceInLine=0;row++;}}}
7678 var nextSpace=0;for(j=caret;j<caret+lineLength;j++){if(text.charAt(j)==" "||text.charAt(j)=="\n"||caret==text.length){nextSpace=j;break;}}
@@ -86,7 +88,7 @@
8789 $.isOperaBroken=true;div.remove();}
8890 if($.isOperaBroken)
8991 s=s.replace(/\n/g,"\r\n");return s;};$.fn.wikiEditor=function(){var context=$(this).data('wikiEditor-context');if(typeof context=='undefined'){var instance=$.wikiEditor.instances.length;context={'$textarea':$(this),'modules':{},'data':{},'instance':instance};$.wikiEditor.instances[instance]=$(this);$(this).wrap($('<div></div>').addClass('wikiEditor-ui').attr('id','wikiEditor-ui')).wrap($('<div></div>').addClass('wikiEditor-ui-bottom').attr('id','wikiEditor-ui-bottom')).wrap($('<div></div>').addClass('wikiEditor-ui-text').attr('id','wikiEditor-ui-text'));context.$ui=$(this).parent().parent().parent();context.$ui.after($('<div style="clear:both;"></div>'));context.$ui.prepend($('<div></div>').addClass('wikiEditor-ui-top').attr('id','wikiEditor-ui-top'));$(this).focus(function(){var pos=$(this).data('wikiEditor-cursor');if(pos)
90 -$(this).setSelection(pos[0],pos[1]);$(this).data('wikiEditor-cursor',false);}).blur(function(){$(this).data('wikiEditor-cursor',$(this).getCaretPosition(true));});context.api={addModule:function(context,data){function callModuleApi(module,call,data){if(module in $.wikiEditor.modules&&'fn'in $.wikiEditor.modules[module]&&call in $.wikiEditor.modules[module].fn){$.wikiEditor.modules[module].fn[call](context,data);}}
 92+$(this).setSelection(pos[0],pos[1]);$(this).data('wikiEditor-cursor',false);}).delayedBind(100,'keyup mouseup',function(){$(this).data('wikiEditor-cursor',$(this).getCaretPosition(true));});context.api={addModule:function(context,data){function callModuleApi(module,call,data){if(module in $.wikiEditor.modules&&'fn'in $.wikiEditor.modules[module]&&call in $.wikiEditor.modules[module].fn){$.wikiEditor.modules[module].fn[call](context,data);}}
9193 if(typeof data=='string'){callModuleApi(data,'create',{});}else if(typeof data=='object'){for(module in data){if(typeof module=='string'){callModuleApi(module,'create',data[module]);}}}}};for(module in $.wikiEditor.modules){if('api'in $.wikiEditor.modules[module]){for(call in $.wikiEditor.modules[module].api){if(!(call in context.api)){context.api[call]=$.wikiEditor.modules[module].api[call];}}}}}
9294 if(arguments.length>0&&typeof arguments[0]=='object'){context.api.addModule(context,arguments[0]);}else{arguments=$.makeArray(arguments);if(arguments.length>0){var call=arguments.shift();if(call in context.api){context.api[call](context,arguments[0]==undefined?{}:arguments[0]);}}}
9395 return $(this).data('wikiEditor-context',context);};})(jQuery);RegExp.escape=function(s){return s.replace(/([.*+?^${}()|\/\\[\]])/g,'\\$1');};(function($){$.wikiEditor.modules.dialogs={api:{addDialog:function(context,data){$.wikiEditor.modules.dialogs.fn.create(context,{'modules':data})},openDialog:function(context,data){if(data.dialog in $.wikiEditor.modules.dialogs.modules){$('#'+$.wikiEditor.modules.dialogs.modules[data.dialog].id).dialog('open');}},closeDialog:function(context,data){if(data.dialog in $.wikiEditor.modules.dialogs.modules){$('#'+$.wikiEditor.modules.dialogs.modules[data.dialog].id).dialog('close');}}},fn:{create:function(context,config){for(module in config){$.wikiEditor.modules.dialogs.modules[module]=config[module];}
@@ -113,14 +115,15 @@
114116 step=step.parent();}
115117 rels.reverse();var id=rels.join('.');$.trackAction(id);}
116118 switch(action.type){case'replace':case'encapsulate':var parts={'pre':'','peri':'','post':''};for(part in parts){if(part+'Msg'in action.options){parts[part]=gM(action.options[part+'Msg'],(action.options[part]||null));}else{parts[part]=(action.options[part]||'')}}
 119+if('regex'in action.options&&'regexReplace'in action.options){var selection=context.$textarea.getSelection();if(selection!=''&&selection.match(action.options.regex)){parts.peri=selection.replace(action.options.regex,action.options.regexReplace);parts.pre=parts.post='';}}
117120 context.$textarea.encapsulateSelection(parts.pre,parts.peri,parts.post,action.options.ownline,action.type=='replace');break;case'callback':if(typeof action.execute=='function'){action.execute(context);}
118121 break;case'dialog':context.$textarea.wikiEditor('openDialog',{'dialog':action.module});break;default:break;}},buildGroup:function(context,id,group){var $group=$('<div />').attr({'class':'group group-'+id,'rel':id});var label=$.wikiEditor.autoMsg(group,'label');if(label){$group.append('<div class="label">'+label+'</div>')}
119 -if('tools'in group){for(tool in group.tools){$group.append($.wikiEditor.modules.toolbar.fn.buildTool(context,tool,group.tools[tool]));}}
120 -return $group;},buildTool:function(context,id,tool){if('filters'in tool){for(filter in tool.filters){if($(tool.filters[filter]).size()==0){return null;}}}
 122+var empty=true;if('tools'in group){for(tool in group.tools){var tool=$.wikiEditor.modules.toolbar.fn.buildTool(context,tool,group.tools[tool]);if(tool){empty=false;$group.append(tool);}}}
 123+return empty?null:$group;},buildTool:function(context,id,tool){if('filters'in tool){for(filter in tool.filters){if($(tool.filters[filter]).size()==0){return null;}}}
121124 var label=$.wikiEditor.autoMsg(tool,'label');switch(tool.type){case'button':var src=tool.icon;if(src.indexOf('http://')!==0&&src.indexOf('https://')!==0){src=$.wikiEditor.imgPath+'toolbar/'+src;}
122125 $button=$('<img />').attr({'src':src,'width':22,'height':22,'alt':label,'title':label,'rel':id,'class':'tool tool-button'});if('action'in tool){$button.data('action',tool.action).data('context',context).click(function(){$.wikiEditor.modules.toolbar.fn.doAction($(this).data('context'),$(this).data('action'),$(this));return false;});}
123126 return $button;case'select':var $select=$('<div />').attr({'rel':id,'class':'tool tool-select'}).click(function(){var $options=$(this).find('.options');$options.animate({'opacity':'toggle'},'fast');});$options=$('<div />').addClass('options');if('list'in tool){for(option in tool.list){var optionLabel=$.wikiEditor.autoMsg(tool.list[option],'label');$options.append($('<a />').data('action',tool.list[option].action).data('context',context).click(function(){$.wikiEditor.modules.toolbar.fn.doAction($(this).data('context'),$(this).data('action'),$(this));}).text(optionLabel).addClass('option').attr('rel',option));}}
124 -$select.append($('<div />').addClass('menu').append($options));$select.append($('<div />').addClass('label').text(label));return $select;default:return null;}},buildBookmark:function(context,id,page){var label=$.wikiEditor.autoMsg(page,'label');return $('<div />').text(label).attr('rel',id).data('context',context).click(function(){$(this).parent().parent().find('.page').hide();$(this).parent().parent().find('.page-'+$(this).attr('rel')).show();$(this).siblings().removeClass('current');$(this).addClass('current');var section=$(this).parent().parent().attr('rel');if($.trackAction!=undefined){$.trackAction(section+'.'+$(this).attr('rel'));}
 127+$select.append($('<div />').addClass('menu').append($options));$select.append($('<div />').addClass('label').text(label));return $select;default:return null;}},buildBookmark:function(context,id,page){var label=$.wikiEditor.autoMsg(page,'label');return $('<div />').text(label).attr('rel',id).data('context',context).bind('mousedown',function(){$(this).parent().parent().find('.page').hide();$(this).parent().parent().find('.page-'+$(this).attr('rel')).show();$(this).siblings().removeClass('current');$(this).addClass('current');var section=$(this).parent().parent().attr('rel');if($.trackAction!=undefined){$.trackAction(section+'.'+$(this).attr('rel'));}
125128 $.cookie('wikiEditor-'+$(this).data('context').instance+'-booklet-'+section+'-page',$(this).attr('rel'));});},buildPage:function(context,id,page){var $page=$('<div />').attr({'class':'page page-'+id,'rel':id});switch(page.layout){case'table':$page.addClass('page-table');var html='<table cellpadding=0 cellspacing=0 '+'border=0 width="100%" class="table table-"'+id+'">';if('headings'in page){html+=$.wikiEditor.modules.toolbar.fn.buildHeading(context,page.headings)}
126129 if('rows'in page){for(row in page.rows){html+=$.wikiEditor.modules.toolbar.fn.buildRow(context,page.rows[row])}}
127130 $page.html(html);break;case'characters':$page.addClass('page-characters');$characters=$('<div />').data('context',context).data('actions',{});var actions=$characters.data('actions');if('language'in page){$characters.attr('lang',page.language);}
@@ -132,7 +135,7 @@
133136 return html;},buildRow:function(context,row){var html='<tr>';for(cell in row){html+='<td class="cell cell-'+cell+'" valign="top"><span>'+
134137 $.wikiEditor.autoMsg(row[cell],['html','text'])+'</span></td>';}
135138 html+='</tr>';return html;},buildCharacter:function(character,actions){if(typeof character=='string'){character={'label':character,'action':{'type':'encapsulate','options':{'pre':character}}};}else if(0 in character&&1 in character){character={'label':character[0],'action':{'type':'encapsulate','options':{'pre':character[1]}}};}
136 -if('action'in character&&'label'in character){actions[character.label]=character.action;return'<a rel="'+character.label+'" href="#">'+character.label+'</a>';}},buildTab:function(context,id,section){var selected=$.cookie('wikiEditor-'+context.instance+'-toolbar-section');return $('<span />').attr({'class':'tab tab-'+id,'rel':id}).append($('<a />').addClass(selected==id?'current':null).attr('href','#').text($.wikiEditor.autoMsg(section,'label')).data('context',context).click(function(){var $sections=$(this).data('context').$ui.find('.sections');var $section=$(this).data('context').$ui.find('.section-'+$(this).parent().attr('rel'));$(this).blur();var show=$section.css('display')=='none';$previousSections=$section.parent().find('.section:visible');$previousSections.css('position','absolute');$previousSections.fadeOut('fast',function(){$(this).css('position','relative');});$(this).parent().parent().find('a').removeClass('current');if(show){$section.fadeIn('fast');$sections.animate({'height':$section.outerHeight()},'fast');$(this).addClass('current');}else{$sections.animate({'height':0});}
 139+if('action'in character&&'label'in character){actions[character.label]=character.action;return'<a rel="'+character.label+'" href="#">'+character.label+'</a>';}},buildTab:function(context,id,section){var selected=$.cookie('wikiEditor-'+context.instance+'-toolbar-section');return $('<span />').attr({'class':'tab tab-'+id,'rel':id}).append($('<a />').addClass(selected==id?'current':null).attr('href','#').text($.wikiEditor.autoMsg(section,'label')).data('context',context).bind('mouseup',function(e){$(this).blur();}).bind('click',function(e){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';$previousSections=$section.parent().find('.section:visible');$previousSections.css('position','absolute');$previousSections.fadeOut('fast',function(){$(this).css('position','relative');});$(this).parent().parent().find('a').removeClass('current');$sections.css('overflow','hidden');if(show){$section.fadeIn('fast');$sections.animate({'height':$section.outerHeight()},$section.outerHeight()*2,function(){$(this).css('overflow','visible').css('height','auto');});$(this).addClass('current');}else{$sections.css('height',$section.outerHeight()).animate({'height':0},$section.outerHeight()*2,function(){$(this).css('overflow','visible');});}
137140 if($.trackAction!=undefined){$.trackAction($section.attr('rel')+'.'+(show?'show':'hide'));}
138141 $.cookie('wikiEditor-'+$(this).data('context').instance+'-toolbar-section',show?$section.attr('rel'):null);return false;}));},buildSection:function(context,id,section){context.$textarea.trigger('wikiEditor-toolbar-buildSection-'+id,[section]);var selected=$.cookie('wikiEditor-'+context.instance+'-toolbar-section');var $section;switch(section.type){case'toolbar':var $section=$('<div />').attr({'class':'toolbar section section-'+id,'rel':id});if('groups'in section){for(group in section.groups){$section.append($.wikiEditor.modules.toolbar.fn.buildGroup(context,group,section.groups[group]));}}
139142 break;case'booklet':var $pages=$('<div />').addClass('pages');var $index=$('<div />').addClass('index');if('pages'in section){for(page in section.pages){$pages.append($.wikiEditor.modules.toolbar.fn.buildPage(context,page,section.pages[page]));$index.append($.wikiEditor.modules.toolbar.fn.buildBookmark(context,page,section.pages[page]));}}
@@ -140,20 +143,21 @@
141144 if($section!==null&&id!=='main'){var show=selected==id;$section.css('display',show?'block':'none');}
142145 return $section;},updateBookletSelection:function(context,id,$pages,$index){var cookie='wikiEditor-'+context.instance+'-booklet-'+id+'-page';var selected=$.cookie(cookie);var $selectedIndex=$index.find('*[rel='+selected+']');if($selectedIndex.size()==0){selected=$index.children().eq(0).attr('rel');$.cookie(cookie,selected);}
143146 $pages.children().hide();$pages.find('*[rel='+selected+']').show();$index.children().removeClass('current');$selectedIndex.addClass('current');},build:function(context,config){var $tabs=$('<div />').addClass('tabs').appendTo(context.modules.$toolbar);var $sections=$('<div />').addClass('sections').appendTo(context.modules.$toolbar);context.modules.$toolbar.append($('<div />').css('clear','both'));var sectionQueue=[];for(section in config){if(section=='main'){context.modules.$toolbar.prepend($.wikiEditor.modules.toolbar.fn.buildSection(context,section,config[section]));}else{sectionQueue.push({'$sections':$sections,'context':context,'id':section,'config':config[section]});$tabs.append($.wikiEditor.modules.toolbar.fn.buildTab(context,section,config[section]));}}
144 -$.eachAsync(sectionQueue,{'bulk':0,'end':function(){$('body').css('position','static');$('body').css('position','relative');},'loop':function(i,s){s.$sections.append($.wikiEditor.modules.toolbar.fn.buildSection(s.context,s.id,s.config));var $section=s.$sections.find('.section:visible');if($section.size()){$sections.animate({'height':$section.outerHeight()},'fast');}}});}}};})(jQuery);(function($){$.wikiEditor.modules.toc={api:{},fn:{create:function(context,config){if('$toc'in context.modules){return;}
 147+$.eachAsync(sectionQueue,{'bulk':0,'end':function(){$('body').css('position','static');$('body').css('position','relative');},'loop':function(i,s){s.$sections.append($.wikiEditor.modules.toolbar.fn.buildSection(s.context,s.id,s.config));var $section=s.$sections.find('.section:visible');if($section.size()){$sections.animate({'height':$section.outerHeight()},$section.outerHeight()*2);}}});}}};})(jQuery);(function($){$.wikiEditor.modules.toc={api:{},fn:{create:function(context,config){if('$toc'in context.modules){return;}
145148 context.modules.$toc=$('<div />').addClass('wikiEditor-ui-toc').attr('id','wikiEditor-ui-toc');var height=context.$ui.find('.wikiEditor-ui-bottom').height()
146 -context.$ui.find('.wikiEditor-ui-bottom').append(context.modules.$toc);context.modules.$toc.height(context.$ui.find('.wikiEditor-ui-bottom').height());context.modules.$toc.css({'width':'12em','marginTop':-(height)});context.$ui.find('.wikiEditor-ui-text').css(($('body.rtl').size()?'marginLeft':'marginRight'),'12em');$.wikiEditor.modules.toc.fn.build(context,config);context.$textarea.delayedBind(1000,'keyup encapsulateSelection change',function(event){var context=$(this).data('wikiEditor-context');$(this).eachAsync({bulk:0,loop:function(){$.wikiEditor.modules.toc.fn.build(context);$.wikiEditor.modules.toc.fn.update(context);}});}).bind('mouseup scrollToPosition focus keyup encapsulateSelection change',function(event){var context=$(this).data('wikiEditor-context');$(this).eachAsync({bulk:0,loop:function(){$.wikiEditor.modules.toc.fn.update(context);}});}).blur(function(){var context=$(this).data('wikiEditor-context');$.wikiEditor.modules.toc.fn.unhighlight(context);});},unhighlight:function(context){context.modules.$toc.find('a').removeClass('currentSelection');},update:function(context){$.wikiEditor.modules.toc.fn.unhighlight(context);var position=context.$textarea.getCaretPosition();var section=0;if(context.data.outline.length>0){if(!(position<context.data.outline[0].position-1)){while(section<context.data.outline.length&&context.data.outline[section].position-1<position){section++;}
 149+context.$ui.find('.wikiEditor-ui-bottom').append(context.modules.$toc);context.modules.$toc.height(context.$ui.find('.wikiEditor-ui-bottom').height());context.modules.$toc.css({'width':'12em','marginTop':-(height)});context.$ui.find('.wikiEditor-ui-text').css(($('body.rtl').size()?'marginLeft':'marginRight'),'12em');$.wikiEditor.modules.toc.fn.build(context,config);context.$textarea.delayedBind(250,'mouseup scrollToPosition focus keyup encapsulateSelection change',function(event){var context=$(this).data('wikiEditor-context');$(this).eachAsync({bulk:0,loop:function(){$.wikiEditor.modules.toc.fn.build(context);$.wikiEditor.modules.toc.fn.update(context);}});}).blur(function(){var context=$(this).data('wikiEditor-context');context.$textarea.delayedBindCancel(250,'mouseup scrollToPosition focus keyup encapsulateSelection change');$.wikiEditor.modules.toc.fn.unhighlight(context);});},unhighlight:function(context){context.modules.$toc.find('div').removeClass('current');},update:function(context){$.wikiEditor.modules.toc.fn.unhighlight(context);var position=context.$textarea.getCaretPosition();var section=0;if(context.data.outline.length>0){if(!(position<context.data.outline[0].position-1)){while(section<context.data.outline.length&&context.data.outline[section].position-1<position){section++;}
147150 section=Math.max(0,section);}
148 -var sectionLink=context.modules.$toc.find('a.section-'+section);sectionLink.addClass('currentSelection');var relTop=sectionLink.offset().top-context.modules.$toc.offset().top;var scrollTop=context.modules.$toc.scrollTop();var divHeight=context.modules.$toc.height();var sectionHeight=sectionLink.height();if(relTop<0)
 151+var sectionLink=context.modules.$toc.find('div.section-'+section);sectionLink.addClass('current');var relTop=sectionLink.offset().top-context.modules.$toc.offset().top;var scrollTop=context.modules.$toc.scrollTop();var divHeight=context.modules.$toc.height();var sectionHeight=sectionLink.height();if(relTop<0)
149152 context.modules.$toc.scrollTop(scrollTop+relTop);else if(relTop+sectionHeight>divHeight)
150153 context.modules.$toc.scrollTop(scrollTop+relTop+sectionHeight-divHeight);}},build:function(context){function buildStructure(outline,offset,level){if(offset==undefined)offset=0;if(level==undefined)level=1;var sections=[];for(var i=offset;i<outline.length;i++){if(outline[i].nLevel==level){var sub=buildStructure(outline,i+1,level+1);if(sub.length){outline[i].sections=sub;}
151154 sections[sections.length]=outline[i];}else if(outline[i].nLevel<level){break;}}
152155 return sections;}
153 -function buildList(structure){var list=$('<ul />');for(i in structure){var item=$('<li />').append($('<a />').attr('href','#').addClass('section-'+structure[i].index).data('textbox',context.$textarea).data('position',structure[i].position).click(function(event){$(this).data('textbox').focus().setSelection($(this).data('position')).scrollToCaretPosition(true);if(typeof $.trackAction!='undefined')
154 -$.trackAction('ntoc.heading');event.preventDefault();}).text(structure[i].text));if(structure[i].sections!==undefined){item.append(buildList(structure[i].sections));}
 156+function buildList(structure){var list=$('<ul></ul>');for(i in structure){var div=$('<div></div>').attr('href','#').addClass('section-'+structure[i].index).data('textbox',context.$textarea).data('position',structure[i].position).bind('mousedown',function(event){$(this).data('textbox').focus().setSelection($(this).data('position')).scrollToCaretPosition(true);if(typeof $.trackAction!='undefined')
 157+$.trackAction('ntoc.heading');event.preventDefault();}).text(structure[i].text);if(structure[i].text=='')
 158+div.html('&nbsp;');var item=$('<li></li>').append(div);if(structure[i].sections!==undefined){item.append(buildList(structure[i].sections));}
155159 list.append(item);}
156160 return list;}
157 -var outline=[];var wikitext=$.wikiEditor.fixOperaBrokenness(context.$textarea.val());var headings=wikitext.match(/^={1,6}.+={1,6}\s*$/gm);var offset=0;headings=$.makeArray(headings);for(var h=0;h<headings.length;h++){text=$.trim(headings[h]);var position=wikitext.indexOf(text,offset);if(position>=offset){offset=position+text.length;}else if(position==-1){continue;}
 161+var outline=[];var wikitext=$.wikiEditor.fixOperaBrokenness(context.$textarea.val());var headings=wikitext.match(/^={1,6}[^=\n][^\n]*={1,6}\s*$/gm);var offset=0;headings=$.makeArray(headings);for(var h=0;h<headings.length;h++){text=$.trim(headings[h]);var position=wikitext.indexOf(text,offset);if(position>=offset){offset=position+text.length;}else if(position==-1){continue;}
158162 var startLevel=0;for(var c=0;c<text.length;c++){if(text.charAt(c)=='='){startLevel++;}else{break;}}
159163 var endLevel=0;for(var c=text.length-1;c>=0;c--){if(text.charAt(c)=='='){endLevel++;}else{break;}}
160164 var level=Math.min(startLevel,endLevel);text=$.trim(text.substr(level,text.length-(level*2)));outline[h]={'text':text,'position':position,'level':level,'index':h+1};}
@@ -161,5 +165,5 @@
162166 else if(outline[i].level<lastLevel){nLevel-=Math.max(1,lastLevel-outline[i].level);}
163167 if(nLevel<=0){nLevel=1;}
164168 outline[i].nLevel=nLevel;lastLevel=outline[i].level;}
165 -var structure=buildStructure(outline);if($('input[name=wpSection]').val()=='')
166 -structure.unshift({'text':wgPageName.replace(/_/g,' '),'level':1,'index':0,'position':0});context.modules.$toc.html(buildList(structure));context.modules.$toc.find('ul').css('width','10em');var links=context.modules.$toc.find('ul a');links.addClass('currentSelection');links.autoEllipse({'position':'right','tooltip':true});links.removeClass('currentSelection');context.data.outline=outline;}}};})(jQuery);
\ No newline at end of file
 169+var structure=buildStructure(outline);if($('input[name=wpSection]').val()==''){structure.unshift({'text':wgPageName.replace(/_/g,' '),'level':1,'index':0,'position':0});}
 170+context.modules.$toc.html(buildList(structure));context.modules.$toc.find('div').autoEllipse({'position':'right','tooltip':true});context.data.outline=outline;}}};})(jQuery);
\ No newline at end of file
Index: branches/wmf-deployment/extensions/UsabilityInitiative/Makefile
@@ -4,30 +4,34 @@
55 # For more info on JSMin, see: http://www.crockford.com/javascript/jsmin.html
66 #
77
8 -CSS := css/suggestions.css\
9 - css/wikiEditor.css\
10 - css/wikiEditor.dialogs.css\
11 - css/wikiEditor.toc.css\
12 - css/wikiEditor.toolbar.css
 8+CSS := \
 9+ css/suggestions.css\
 10+ css/wikiEditor.css\
 11+ css/wikiEditor.dialogs.css\
 12+ css/wikiEditor.toc.css\
 13+ css/wikiEditor.toolbar.css
1314
14 -JS2 := js/js2/jquery-1.3.2.js\
15 - js/js2/jquery-ui-1.7.2.js\
16 - js/js2/js2.js
 15+JS2 := \
 16+ js/js2/jquery-1.3.2.js\
 17+ js/js2/jquery-ui-1.7.2.js\
 18+ js/js2/js2.js
1719
18 -PLUGINS := js/plugins/jquery.async.js\
19 - js/plugins/jquery.autoEllipse.js\
20 - js/plugins/jquery.browser.js\
21 - js/plugins/jquery.cookie.js\
22 - js/plugins/jquery.delayedBind.js\
23 - js/plugins/jquery.namespaceSelect.js\
24 - js/plugins/jquery.suggestions.js\
25 - js/plugins/jquery.textSelection.js\
26 - js/plugins/jquery.wikiEditor.js\
27 - js/plugins/jquery.wikiEditor.dialogs.js\
28 - js/plugins/jquery.wikiEditor.toolbar.js\
29 - js/plugins/jquery.wikiEditor.toc.js
 20+PLUGINS := \
 21+ js/plugins/jquery.async.js\
 22+ js/plugins/jquery.autoEllipse.js\
 23+ js/plugins/jquery.browser.js\
 24+ js/plugins/jquery.cookie.js\
 25+ js/plugins/jquery.delayedBind.js\
 26+ js/plugins/jquery.namespaceSelect.js\
 27+ js/plugins/jquery.suggestions.js\
 28+ js/plugins/jquery.textSelection.js\
 29+ js/plugins/jquery.wikiEditor.js\
 30+ js/plugins/jquery.wikiEditor.dialogs.js\
 31+ js/plugins/jquery.wikiEditor.toolbar.js\
 32+ js/plugins/jquery.wikiEditor.toc.js
3033
31 -all: css/combined.css\
 34+all: \
 35+ css/combined.css\
3236 css/combined.min.css\
3337 js/js2.combined.js\
3438 js/js2.combined.min.js\
@@ -43,17 +47,25 @@
4448 js/plugins.combined.js: $(PLUGINS)
4549 cat $(PLUGINS) > js/plugins.combined.js
4650
47 -js/js2.combined.min.js : js/js2.combined.js
48 - jsmin < js/js2.combined.js > js/js2.combined.min.js
 51+js/js2.combined.min.js : js/js2.combined.js jsmin
 52+ if [ -e ./jsmin ]; then ./jsmin < js/js2.combined.js > js/js2.combined.min.js;\
 53+ else jsmin < js/js2.combined.js > js/js2.combined.min.js; fi
4954
50 -js/plugins.combined.min.js : js/plugins.combined.js
51 - jsmin < js/plugins.combined.js > js/plugins.combined.min.js
 55+js/plugins.combined.min.js : js/plugins.combined.js jsmin
 56+ if [ -e ./jsmin ]; then ./jsmin < js/plugins.combined.js > js/plugins.combined.min.js;\
 57+ else jsmin < js/plugins.combined.js > js/plugins.combined.min.js; fi
5258
5359 css/combined.min.css : css/combined.css
54 - cat css/combined.css |\
55 - sed -e 's/^[ ]*//g; s/[ ]*$$//g; s/\([:{;,]\) /\1/g; s/ {/{/g; s/\/\*.*\*\///g; /^$$/d'\
 60+ cat css/combined.css | sed -e 's/^[ ]*//g; s/[ ]*$$//g; s/\([:{;,]\) /\1/g; s/ {/{/g; s/\/\*.*\*\///g; /^$$/d'\
5661 > css/combined.min.css
5762
 63+jsmin:
 64+ type -P jsmin &>/dev/null || ( wget http://www.crockford.com/javascript/jsmin.c; gcc jsmin.c -o jsmin )
 65+
 66+distclean: clean
 67+ rm -rf jsmin
 68+ rm -rf jsmin.c
 69+
5870 clean:
5971 rm -f js/js2.combined.*
6072 rm -f js/plugins.combined.*
Index: branches/wmf-deployment/extensions/UsabilityInitiative/css/combined.css
@@ -126,36 +126,59 @@
127127 }
128128 .wikiEditor-ui-toc ul {
129129 padding: 0;
130 - margin: 0.5em 1em;
 130+ margin: 0;
131131 list-style: none;
132132 /* IE needs to be told in great detail how to act, or it misbehaves */
133133 list-style-image: none;
134134 list-style-position: outside;
135135 list-style-type: none;
 136+ width: 100%;
136137 }
 138+.wikiEditor-ui-toc li {
 139+ padding: 0;
 140+ margin: 0;
 141+}
137142 .wikiEditor-ui-toc ul ul {
138143 padding: 0;
139144 margin: 0;
140 - margin-left: 0.75em;
141145 margin-bottom: 0 !important;
142146 margin-top: 0 !important;
143147 list-style: none;
144148 }
145 -body.rtl .wikiEditor-ui-toc ul ul {
146 - margin-left: 0;
147 - margin-right: 0.75em;
148 -}
149 -.wikiEditor-ui-toc ul li a {
 149+.wikiEditor-ui-toc ul li div {
150150 display: block;
151151 font-size: 0.9em;
 152+ padding: 0.125em;
 153+ padding-left: 1em;
 154+ cursor: pointer;
 155+ color: #0645ad;
152156 }
153 -.wikiEditor-ui-toc ul li a.currentSelection {
154 - font-weight: bold;
 157+.wikiEditor-ui-toc ul ul li div {
 158+ padding-left: 2em;
155159 }
156 -.wikiEditor-ui-toc ul li a.section-0 {
 160+.wikiEditor-ui-toc ul ul ul li div {
 161+ padding-left: 3em;
 162+}
 163+.wikiEditor-ui-toc ul ul ul ul li div {
 164+ padding-left: 4em;
 165+}
 166+.wikiEditor-ui-toc ul ul ul ul ul li div {
 167+ padding-left: 5em;
 168+}
 169+.wikiEditor-ui-toc ul ul ul ul ul ul li div {
 170+ padding-left: 6em;
 171+}
 172+.wikiEditor-ui-toc ul li div.current {
 173+ background-color: #FAFAFA;
 174+ color: #333333;
 175+}
 176+.wikiEditor-ui-toc ul li div.section-0 {
157177 font-size: 1em;
 178+ padding-top: 0.5em;
 179+ padding-bottom: 0.5em;
158180 border-bottom: solid 1px #DDDDDD;
159 -}/* wikiEditor toolbar module */
 181+}
 182+/* wikiEditor toolbar module */
160183
161184 .wikiEditor-ui-toolbar {
162185 position: relative;
@@ -168,7 +191,6 @@
169192 width: 100%;
170193 clear: both;
171194 height: 0;
172 - overflow: hidden;
173195 }
174196 body.rtl .wikiEditor-ui-toolbar .sections {
175197 float: right;
Index: branches/wmf-deployment/extensions/UsabilityInitiative/css/combined.min.css
@@ -114,33 +114,55 @@
115115 }
116116 .wikiEditor-ui-toc ul{
117117 padding:0;
118 -margin:0.5em 1em;
 118+margin:0;
119119 list-style:none;
120120 list-style-image:none;
121121 list-style-position:outside;
122122 list-style-type:none;
 123+width:100%;
123124 }
 125+.wikiEditor-ui-toc li{
 126+padding:0;
 127+margin:0;
 128+}
124129 .wikiEditor-ui-toc ul ul{
125130 padding:0;
126131 margin:0;
127 -margin-left:0.75em;
128132 margin-bottom:0 !important;
129133 margin-top:0 !important;
130134 list-style:none;
131135 }
132 -body.rtl .wikiEditor-ui-toc ul ul{
133 -margin-left:0;
134 -margin-right:0.75em;
135 -}
136 -.wikiEditor-ui-toc ul li a{
 136+.wikiEditor-ui-toc ul li div{
137137 display:block;
138138 font-size:0.9em;
 139+padding:0.125em;
 140+padding-left:1em;
 141+cursor:pointer;
 142+color:#0645ad;
139143 }
140 -.wikiEditor-ui-toc ul li a.currentSelection{
141 -font-weight:bold;
 144+.wikiEditor-ui-toc ul ul li div{
 145+padding-left:2em;
142146 }
143 -.wikiEditor-ui-toc ul li a.section-0{
 147+.wikiEditor-ui-toc ul ul ul li div{
 148+padding-left:3em;
 149+}
 150+.wikiEditor-ui-toc ul ul ul ul li div{
 151+padding-left:4em;
 152+}
 153+.wikiEditor-ui-toc ul ul ul ul ul li div{
 154+padding-left:5em;
 155+}
 156+.wikiEditor-ui-toc ul ul ul ul ul ul li div{
 157+padding-left:6em;
 158+}
 159+.wikiEditor-ui-toc ul li div.current{
 160+background-color:#FAFAFA;
 161+color:#333333;
 162+}
 163+.wikiEditor-ui-toc ul li div.section-0{
144164 font-size:1em;
 165+padding-top:0.5em;
 166+padding-bottom:0.5em;
145167 border-bottom:solid 1px #DDDDDD;
146168 }
147169 .wikiEditor-ui-toolbar{
@@ -152,7 +174,6 @@
153175 width:100%;
154176 clear:both;
155177 height:0;
156 -overflow:hidden;
157178 }
158179 body.rtl .wikiEditor-ui-toolbar .sections{
159180 float:right;
@@ -459,4 +480,4 @@
460481 background-color:white;
461482 text-decoration:none;
462483 border-color:#a8d7f9;
463 -}
 484+}
\ No newline at end of file
Index: branches/wmf-deployment/extensions/UsabilityInitiative/css/wikiEditor.toolbar.css
@@ -11,7 +11,6 @@
1212 width: 100%;
1313 clear: both;
1414 height: 0;
15 - overflow: hidden;
1615 }
1716 body.rtl .wikiEditor-ui-toolbar .sections {
1817 float: right;
Index: branches/wmf-deployment/extensions/UsabilityInitiative/css/wikiEditor.toc.css
@@ -21,33 +21,55 @@
2222 }
2323 .wikiEditor-ui-toc ul {
2424 padding: 0;
25 - margin: 0.5em 1em;
 25+ margin: 0;
2626 list-style: none;
2727 /* IE needs to be told in great detail how to act, or it misbehaves */
2828 list-style-image: none;
2929 list-style-position: outside;
3030 list-style-type: none;
 31+ width: 100%;
3132 }
 33+.wikiEditor-ui-toc li {
 34+ padding: 0;
 35+ margin: 0;
 36+}
3237 .wikiEditor-ui-toc ul ul {
3338 padding: 0;
3439 margin: 0;
35 - margin-left: 0.75em;
3640 margin-bottom: 0 !important;
3741 margin-top: 0 !important;
3842 list-style: none;
3943 }
40 -body.rtl .wikiEditor-ui-toc ul ul {
41 - margin-left: 0;
42 - margin-right: 0.75em;
43 -}
44 -.wikiEditor-ui-toc ul li a {
 44+.wikiEditor-ui-toc ul li div {
4545 display: block;
4646 font-size: 0.9em;
 47+ padding: 0.125em;
 48+ padding-left: 1em;
 49+ cursor: pointer;
 50+ color: #0645ad;
4751 }
48 -.wikiEditor-ui-toc ul li a.currentSelection {
49 - font-weight: bold;
 52+.wikiEditor-ui-toc ul ul li div {
 53+ padding-left: 2em;
5054 }
51 -.wikiEditor-ui-toc ul li a.section-0 {
 55+.wikiEditor-ui-toc ul ul ul li div {
 56+ padding-left: 3em;
 57+}
 58+.wikiEditor-ui-toc ul ul ul ul li div {
 59+ padding-left: 4em;
 60+}
 61+.wikiEditor-ui-toc ul ul ul ul ul li div {
 62+ padding-left: 5em;
 63+}
 64+.wikiEditor-ui-toc ul ul ul ul ul ul li div {
 65+ padding-left: 6em;
 66+}
 67+.wikiEditor-ui-toc ul li div.current {
 68+ background-color: #FAFAFA;
 69+ color: #333333;
 70+}
 71+.wikiEditor-ui-toc ul li div.section-0 {
5272 font-size: 1em;
 73+ padding-top: 0.5em;
 74+ padding-bottom: 0.5em;
5375 border-bottom: solid 1px #DDDDDD;
54 -}
\ No newline at end of file
 76+}
Index: branches/wmf-deployment/extensions/UsabilityInitiative/OptIn/SpecialOptIn.php
@@ -66,6 +66,12 @@
6767
6868 $par = $wgRequest->getVal( 'from', $par );
6969 $this->mOriginTitle = Title::newFromText( $par );
 70+
 71+ // Verify that $this->mOriginTitle is not Special:Userlogout
 72+ if ( $this->mOriginTitle && $this->mOriginTitle->getNamespace() == NS_SPECIAL &&
 73+ SpecialPage::resolveAlias( $this->mOriginTitle->getText() ) == 'Userlogout' ) {
 74+ $this->mOriginTitle = null;
 75+ }
7076 if ( $this->mOriginTitle ) {
7177 $this->mOrigin = $this->mOriginTitle->getPrefixedDBKey();
7278 $this->mOriginQuery = $wgRequest->getVal( 'fromquery' );
@@ -93,17 +99,17 @@
94100 }
95101 else
96102 {
97 - if ( $wgRequest->getVal( 'opt' ) == 'in' )
98 - // Just opted in
 103+ if ( $wgRequest->getVal( 'opt' ) == 'in' && $wgUser->isLoggedIn() )
 104+ // Will be opted in in this request
99105 $wgOut->setPageTitle( wfMsg( 'optin-title-justoptedin' ) );
100106 else
101107 // About to opt in
102108 $wgOut->setPageTitle( wfMsg( 'optin-title-optedout' ) );
103109 }
104110
105 - if ( $wgRequest->getCheck( 'opt' ) ) {
 111+ if ( $wgRequest->getCheck( 'opt' ) && $wgUser->isLoggedIn() ) {
106112 if ( $wgRequest->getVal( 'opt' ) === 'in' ) {
107 - if ( self::checkToken() ) {
 113+ if ( self::checkToken() && !self::isOptedIn( $wgUser ) ) {
108114 self::optIn( $wgUser );
109115 $wgOut->addWikiMsg( 'optin-success-in' );
110116
@@ -117,21 +123,28 @@
118124 array( 'type' => $wgJsMimeType ),
119125 'js2AddOnloadHook( function() { $j.post( "' . $url . '", optInGetPOSTData() ); } );'
120126 ) );
 127+ } else if ( self::isOptedIn( $wgUser ) ) {
 128+ // User is already opted in but
 129+ // reloaded the page or tried to opt in
 130+ // again. Fake success
 131+ $wgOut->addWikiMsg( 'optin-success-in' );
121132 } else
 133+ // Token didn't match
122134 $this->showForm( self::isOptedIn( $wgUser ) ?
123135 'out' : 'in' );
124 - } else if ( $wgRequest->getVal( 'opt' ) == 'feedback' ) {
 136+ } else if ( $wgRequest->getVal( 'opt' ) == 'feedback' && self::isOptedIn( $wgUser ) ) {
125137 if ( $wgRequest->wasPosted() ) {
126138 $this->saveSurvey( $wgOptInFeedBackSurvey,
127139 'feedback' );
128140 $wgOut->addWikiMsg( 'optin-success-feedback' );
129141 } else
130142 $this->showForm( 'feedback' );
131 - } else if ( $wgRequest->getVal( 'opt' ) == 'browser' ) {
 143+ } else if ( $wgRequest->getVal( 'opt' ) == 'browser' && self::isOptedIn( $wgUser ) ) {
132144 $this->saveSurvey( $wgOptInBrowserSurvey, 'in' );
133145 $wgOut->disable();
134146 } else {
135 - if ( self::checkToken() ) {
 147+ // Opt out
 148+ if ( self::checkToken() && self::isOptedIn( $wgUser ) ) {
136149 self::optOut( $wgUser );
137150 $this->saveSurvey( $wgOptInSurvey, 'out' );
138151 $wgOut->addWikiMsg( 'optin-success-out' );
Property changes on: branches/wmf-deployment/extensions/UsabilityInitiative/OptIn/SpecialOptIn.php
___________________________________________________________________
Modified: svn:mergeinfo
139152 Merged /trunk/extensions/UsabilityInitiative/OptIn/SpecialOptIn.php:r58926,58973-58974,59146,59202
140153 Merged /branches/usability/acaifix/OptIn/SpecialOptIn.php:r58541-59203
Property changes on: branches/wmf-deployment/extensions/UsabilityInitiative/OptIn
___________________________________________________________________
Added: svn:mergeinfo
141154 Merged /branches/REL1_15/phase3/extensions/UsabilityInitiative/OptIn:r51646
142155 Merged /trunk/extensions/UsabilityInitiative/OptIn:r56151-57234,58926,58973-58974,59146,59202
143156 Merged /branches/usability/acaifix/OptIn:r59192-59203
144157 Merged /trunk/phase3/extensions/UsabilityInitiative/OptIn:r56213,56215-56216,56218,56325,56334-56336,56338,56340,56343,56345,56347,56350,57154-57447
Index: branches/wmf-deployment/extensions/UsabilityInitiative/NavigableTOC/NavigableTOC.php
@@ -27,7 +27,7 @@
2828 $wgNavigableTOCUserEnable = true;
2929
3030 // Bump the version number every time you change any of the .css/.js files
31 -$wgNavigableTOCStyleVersion = 3;
 31+$wgNavigableTOCStyleVersion = 6;
3232
3333 /* Setup */
3434
Index: branches/wmf-deployment/extensions/UsabilityInitiative/CollapsibleTabs/CollapsibleTabs.php
@@ -0,0 +1,41 @@
 2+<?php
 3+/**
 4+ * Usability Initiative CollapsibleTabs extension
 5+ *
 6+ * @file
 7+ * @ingroup Extensions
 8+ *
 9+ * This file contains the include file for the CollapsibleTabs portion of the
 10+ * UsabilityInitiative extension of MediaWiki.
 11+ *
 12+ * Usage: Include the following line in your LocalSettings.php
 13+ * require_once( "$IP/extensions/UsabilityInitiative/CollapsibleTabs/CollapsibleTabs.php" );
 14+ *
 15+ * @author Adam Miller <amiller@wikimedia.org>
 16+ * @license GPL v2 or later
 17+ * @version 0.0.7
 18+ */
 19+
 20+/* Configuration */
 21+// Bump the version number every time you change any of the .css/.js files
 22+$wgCollapsibleTabsStyleVersion = 9;
 23+
 24+/* Setup */
 25+
 26+// Credits
 27+$wgExtensionCredits['other'][] = array(
 28+ 'path' => __FILE__,
 29+ 'name' => 'CollapsibleTabs',
 30+ 'author' => 'Adam Miller',
 31+ 'version' => '0.0.7',
 32+ 'url' => 'http://www.mediawiki.org/wiki/Extension:CollapsibleTabs',
 33+ 'descriptionmsg' => 'collapsibletabs-desc',
 34+);
 35+// Includes parent extension
 36+require_once( dirname( dirname( __FILE__ ) ) . "/UsabilityInitiative.php" );
 37+
 38+// Adds Autoload Classes
 39+$wgAutoloadClasses['CollapsibleTabsHooks'] =
 40+ dirname( __FILE__ ) . '/CollapsibleTabs.hooks.php';
 41+
 42+$wgHooks['AjaxAddScript'][] = 'CollapsibleTabsHooks::initialize';
Property changes on: branches/wmf-deployment/extensions/UsabilityInitiative/CollapsibleTabs/CollapsibleTabs.php
___________________________________________________________________
Added: svn:eol-style
143 + native
Index: branches/wmf-deployment/extensions/UsabilityInitiative/CollapsibleTabs/CollapsibleTabs.hooks.php
@@ -0,0 +1,25 @@
 2+<?php
 3+/**
 4+ * Hooks for Usability Initiative Collapsing Tabs extension
 5+ *
 6+ * @file
 7+ * @ingroup Extensions
 8+ */
 9+
 10+class CollapsibleTabsHooks {
 11+
 12+ /* Static Functions */
 13+
 14+ /**
 15+ * intialize hook
 16+ */
 17+ public static function initialize( $out ) {
 18+ global $wgCollapsibleTabsStyleVersion;
 19+ UsabilityInitiativeHooks::initialize();
 20+ UsabilityInitiativeHooks::addScript(
 21+ 'CollapsibleTabs/CollapsibleTabs.js', $wgCollapsibleTabsStyleVersion
 22+ );
 23+ return true;
 24+ }
 25+
 26+}
Property changes on: branches/wmf-deployment/extensions/UsabilityInitiative/CollapsibleTabs/CollapsibleTabs.hooks.php
___________________________________________________________________
Added: svn:eol-style
127 + native
Index: branches/wmf-deployment/extensions/UsabilityInitiative/CollapsibleTabs/CollapsibleTabs.js
@@ -0,0 +1,72 @@
 2+js2AddOnloadHook( function() {
 3+
 4+ var rtl = $j( 'body.rtl' ).size() ? true : false;
 5+
 6+ //Overloading the moveToCollapsed function to animate the transition
 7+ $j.collapsibleTabs.moveToCollapsed = function( ele ) {
 8+ var $moving = $j(ele);
 9+ $j($moving.data('collapsibleTabsSettings').expandedContainer).data('collapsibleTabsSettings').shifting = true;
 10+ var data = $moving.data('collapsibleTabsSettings');
 11+ // Remove the element from where it's at and put it in the dropdown menu
 12+ var target = $moving.data('collapsibleTabsSettings').collapsedContainer;
 13+ $moving.css("position", "relative").css( ( rtl ? 'left' : 'right'), 0 );
 14+ $moving.animate({width: '1px'},"normal",function(){
 15+ $j(this).hide();
 16+ // add the placeholder
 17+ $j('<span class="placeholder" style="display:none;"></span>').insertAfter(this);
 18+ $j(this).remove().prependTo(target).data('collapsibleTabsSettings', data);
 19+ $j(this).attr('style', 'display:list-item;');
 20+ $j($j(ele).data('collapsibleTabsSettings').expandedContainer).data('collapsibleTabsSettings').shifting = false;
 21+ $j.collapsibleTabs.handleResize();
 22+ });
 23+ };
 24+
 25+ // Overloading the moveToExpanded function to animate the transition
 26+ $j.collapsibleTabs.moveToExpanded = function( ele ) {
 27+ var $moving = $j(ele);
 28+ $j($moving.data('collapsibleTabsSettings').expandedContainer).data('collapsibleTabsSettings').shifting = true;
 29+ var data = $moving.data('collapsibleTabsSettings');
 30+ // grab the next appearing placeholder so we can use it for replacing
 31+ var $target = $j($moving.data('collapsibleTabsSettings').expandedContainer).find('span.placeholder:first');
 32+ var expandedWidth = $moving.data('collapsibleTabsSettings').expandedWidth;
 33+ $moving.css("position", "relative").css( ( rtl ? 'right' : 'left'), 0 ).css('width','1px');
 34+ $target.replaceWith($moving.remove().css('width','1px').data('collapsibleTabsSettings', data)
 35+ .animate({width: expandedWidth+"px"}, "normal", function(){
 36+ $j(this).attr('style', 'display:block;');
 37+ $j($moving.data('collapsibleTabsSettings').expandedContainer).data('collapsibleTabsSettings').shifting = false;
 38+ $j.collapsibleTabs.handleResize();
 39+ }));
 40+ };
 41+
 42+ // Bind callback functions to animate our drop down menu in and out
 43+ // and then call the collapsibleTabs function on the menu
 44+ $j('#p-views ul').bind("beforeTabCollapse", function(){
 45+ if($j('#p-cactions').css('display')=='none')
 46+ $j("#p-cactions").addClass("filledPortlet").removeClass("emptyPortlet")
 47+ .find('h5').css('width','1px').animate({'width':'26px'}, 390);
 48+ }).bind("beforeTabExpand", function(){
 49+ if($j('#p-cactions li').length==1)
 50+ $j("#p-cactions h5").animate({'width':'1px'},370, function(){
 51+ $j(this).attr('style','').parent().addClass("emptyPortlet").removeClass("filledPortlet");
 52+ });
 53+ }).collapsibleTabs({
 54+ expandCondition: function(eleWidth) {
 55+ if( rtl ){
 56+ return ( $j('#right-navigation').position().left + $j('#right-navigation').width() + 1)
 57+ < ($j('#left-navigation').position().left - eleWidth);
 58+ } else {
 59+ return ( $j('#left-navigation').position().left + $j('#left-navigation').width() + 1)
 60+ < ($j('#right-navigation').position().left - eleWidth);
 61+ }
 62+ },
 63+ collapseCondition: function() {
 64+ if( rtl ){
 65+ return ( $j('#right-navigation').position().left + $j('#right-navigation').width())
 66+ > $j('#left-navigation').position().left;
 67+ } else {
 68+ return ( $j('#left-navigation').position().left + $j('#left-navigation').width())
 69+ > $j('#right-navigation').position().left;
 70+ }
 71+ }
 72+ });
 73+});
\ No newline at end of file
Property changes on: branches/wmf-deployment/extensions/UsabilityInitiative/CollapsibleTabs/CollapsibleTabs.js
___________________________________________________________________
Added: svn:mergeinfo
174 Merged /trunk/phase3/extensions/UsabilityInitiative/CollapsibleTabs/CollapsibleTabs.js:r56213,56215-56216,56218,56325,56334-56336,56338,56340,56343,56345,56347,56350,57154-57447
275 Merged /trunk/extensions/UsabilityInitiative/Vector/Modules/CollapsibleTabs/CollapsibleTabs.js:r58969
376 Merged /branches/REL1_15/phase3/extensions/UsabilityInitiative/CollapsibleTabs/CollapsibleTabs.js:r51646
477 Merged /trunk/extensions/UsabilityInitiative/CollapsibleTabs/CollapsibleTabs.js:r56151-57234,58926,58973-58974,59202
578 Merged /branches/usability/acaifix/CollapsibleTabs/CollapsibleTabs.js:r59192-59203
Added: svn:eol-style
679 + native
Index: branches/wmf-deployment/extensions/UsabilityInitiative/UsabilityInitiative.hooks.php
@@ -20,17 +20,17 @@
2121 'raw' => array(
2222 array( 'src' => 'css/suggestions.css', 'version' => 6 ),
2323 array( 'src' => 'css/wikiEditor.css', 'version' => 4 ),
24 - array( 'src' => 'css/wikiEditor.toolbar.css', 'version' => 6 ),
 24+ array( 'src' => 'css/wikiEditor.toolbar.css', 'version' => 7 ),
2525 array( 'src' => 'css/wikiEditor.dialogs.css', 'version' => 2 ),
26 - array( 'src' => 'css/wikiEditor.toc.css', 'version' => 6 ),
 26+ array( 'src' => 'css/wikiEditor.toc.css', 'version' => 10 ),
2727 array( 'src' => 'css/vector/jquery-ui-1.7.2.css', 'version' => '1.7.2' ),
2828 ),
2929 'combined' => array(
30 - array( 'src' => 'css/combined.css', 'version' => 11 ),
 30+ array( 'src' => 'css/combined.css', 'version' => 16 ),
3131 array( 'src' => 'css/vector/jquery-ui-1.7.2.css', 'version' => '1.7.2' ),
3232 ),
3333 'minified' => array(
34 - array( 'src' => 'css/combined.min.css', 'version' => 11 ),
 34+ array( 'src' => 'css/combined.min.css', 'version' => 16 ),
3535 array( 'src' => 'css/vector/jquery-ui-1.7.2.css', 'version' => '1.7.2' ),
3636 ),
3737 )
@@ -58,23 +58,24 @@
5959 'base_sets' => array(
6060 'raw' => array(
6161 array( 'src' => 'js/plugins/jquery.async.js', 'version' => 3 ),
62 - array( 'src' => 'js/plugins/jquery.autoEllipse.js', 'version' => 3 ),
 62+ array( 'src' => 'js/plugins/jquery.autoEllipse.js', 'version' => 4 ),
6363 array( 'src' => 'js/plugins/jquery.browser.js', 'version' => 3 ),
 64+ array( 'src' => 'js/plugins/jquery.collapsibleTabs.js', 'version' => 5 ),
6465 array( 'src' => 'js/plugins/jquery.cookie.js', 'version' => 3 ),
6566 array( 'src' => 'js/plugins/jquery.delayedBind.js', 'version' => 1 ),
6667 array( 'src' => 'js/plugins/jquery.namespaceSelect.js', 'version' => 1 ),
67 - array( 'src' => 'js/plugins/jquery.suggestions.js', 'version' => 4 ),
68 - array( 'src' => 'js/plugins/jquery.textSelection.js', 'version' => 16 ),
69 - array( 'src' => 'js/plugins/jquery.wikiEditor.js', 'version' => 12 ),
70 - array( 'src' => 'js/plugins/jquery.wikiEditor.toolbar.js', 'version' => 12 ),
71 - array( 'src' => 'js/plugins/jquery.wikiEditor.dialogs.js', 'version' => 5 ),
72 - array( 'src' => 'js/plugins/jquery.wikiEditor.toc.js', 'version' => 20 ),
 68+ array( 'src' => 'js/plugins/jquery.suggestions.js', 'version' => 6 ),
 69+ array( 'src' => 'js/plugins/jquery.textSelection.js', 'version' => 18 ),
 70+ array( 'src' => 'js/plugins/jquery.wikiEditor.js', 'version' => 14 ),
 71+ array( 'src' => 'js/plugins/jquery.wikiEditor.toolbar.js', 'version' => 23 ),
 72+ array( 'src' => 'js/plugins/jquery.wikiEditor.dialogs.js', 'version' => 8 ),
 73+ array( 'src' => 'js/plugins/jquery.wikiEditor.toc.js', 'version' => 27 ),
7374 ),
7475 'combined' => array(
75 - array( 'src' => 'js/plugins.combined.js', 'version' => 44 ),
 76+ array( 'src' => 'js/plugins.combined.js', 'version' => 67 ),
7677 ),
7778 'minified' => array(
78 - array( 'src' => 'js/plugins.combined.min.js', 'version' => 44 ),
 79+ array( 'src' => 'js/plugins.combined.min.js', 'version' => 67 ),
7980 ),
8081 ),
8182 );
Index: branches/wmf-deployment/extensions/UsabilityInitiative/images/wikiEditor/toolbar/indent.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: branches/wmf-deployment/extensions/UsabilityInitiative/images/wikiEditor/toolbar/format-big.png
Cannot display: file marked as a binary type.
svn:mime-type = image/png
Index: branches/wmf-deployment/extensions/UsabilityInitiative/images/wikiEditor/toolbar/format-italic.png
Cannot display: file marked as a binary type.
svn:mime-type = image/png
Index: branches/wmf-deployment/extensions/UsabilityInitiative/images/wikiEditor/toolbar/format-small.png
Cannot display: file marked as a binary type.
svn:mime-type = image/png
Index: branches/wmf-deployment/extensions/UsabilityInitiative/images/wikiEditor/toolbar/format-subscript.png
Cannot display: file marked as a binary type.
svn:mime-type = image/png
Index: branches/wmf-deployment/extensions/UsabilityInitiative/images/wikiEditor/toolbar/format-bold.png
Cannot display: file marked as a binary type.
svn:mime-type = image/png
Index: branches/wmf-deployment/extensions/UsabilityInitiative/images/wikiEditor/toolbar/png24/format-small.png
Cannot display: file marked as a binary type.
svn:mime-type = image/png
Index: branches/wmf-deployment/extensions/UsabilityInitiative/images/wikiEditor/toolbar/png24/insert-newline.png
Cannot display: file marked as a binary type.
svn:mime-type = image/png
Index: branches/wmf-deployment/extensions/UsabilityInitiative/images/wikiEditor/toolbar/png24/format-subscript.png
Cannot display: file marked as a binary type.
svn:mime-type = image/png
Index: branches/wmf-deployment/extensions/UsabilityInitiative/images/wikiEditor/toolbar/png24/format-bold.png
Cannot display: file marked as a binary type.
svn:mime-type = image/png
Index: branches/wmf-deployment/extensions/UsabilityInitiative/images/wikiEditor/toolbar/png24/format-superscript.png
Cannot display: file marked as a binary type.
svn:mime-type = image/png
Index: branches/wmf-deployment/extensions/UsabilityInitiative/images/wikiEditor/toolbar/png24/format-big.png
Cannot display: file marked as a binary type.
svn:mime-type = image/png
Index: branches/wmf-deployment/extensions/UsabilityInitiative/images/wikiEditor/toolbar/png24/format-italic.png
Cannot display: file marked as a binary type.
svn:mime-type = image/png
Index: branches/wmf-deployment/extensions/UsabilityInitiative/images/wikiEditor/toolbar/format-indent.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: branches/wmf-deployment/extensions/UsabilityInitiative/images/wikiEditor/toolbar/format-indent.png
___________________________________________________________________
Added: svn:mime-type
8283 + application/octet-stream
Index: branches/wmf-deployment/extensions/UsabilityInitiative/images/wikiEditor/toolbar/format-superscript.png
Cannot display: file marked as a binary type.
svn:mime-type = image/png
Index: branches/wmf-deployment/extensions/UsabilityInitiative/ClickTracking/ApiSpecialClickTracking.php
@@ -13,8 +13,7 @@
1414 * and "increment" as how many days to increment
1515 * @see includes/api/ApiBase#execute()
1616 */
17 - public function execute(){
18 -
 17+ public function execute() {
1918 $params = $this->extractRequestParams();
2019 $this->validateParams( $params );
2120 $event_id = $params['eventid'];
@@ -22,16 +21,20 @@
2322 $enddate = $params['enddate'];
2423 $increment = $params['increment'];
2524 $userDefString = $params['userdefs'];
26 -
27 - $click_data = array();
28 - try{
29 - $click_data = SpecialClickTracking::getChartData($event_id, $startdate, $enddate, $increment, $userDefString);
30 - $this->getResult()->addValue(array('datapoints'), 'expert', $click_data['expert']);
31 - $this->getResult()->addValue(array('datapoints'), 'basic', $click_data['basic']);
32 - $this->getResult()->addValue(array('datapoints'), 'intermediate', $click_data['intermediate']);
 25+
 26+ // this is if it's asking for tableData
 27+ if( isset( $params['tabledata'] ) ) {
 28+ $tableData = SpecialClickTracking::buildRowArray( $startdate, $enddate, $userDefString );
 29+ $this->getResult()->addValue( array( 'tablevals' ), 'vals', $tableData );
 30+ } else{ //chart data
 31+ $click_data = array();
 32+ try {
 33+ $click_data = SpecialClickTracking::getChartData( $event_id, $startdate, $enddate, $increment, $userDefString );
 34+ $this->getResult()->addValue( array( 'datapoints' ), 'expert', $click_data['expert'] );
 35+ $this->getResult()->addValue( array( 'datapoints' ), 'basic', $click_data['basic'] );
 36+ $this->getResult()->addValue( array( 'datapoints' ), 'intermediate', $click_data['intermediate'] );
 37+ } catch( Exception $e ) { /* no result */ }
3338 }
34 - catch(Exception $e){ /* no result */ }
35 -
3639 }
3740
3841 /**
@@ -45,51 +48,53 @@
4649 $this->dieUsageMsg( array( 'missingparam', $arg ) );
4750 }
4851 }
49 -
50 - //check if event id parses to an int greater than zero
51 - if( (int) $params['eventid'] <= 0){
52 - $this->dieUsage("Invalid event ID", "badeventid");
 52+
 53+ // check if event id parses to an int greater than zero
 54+ if( (int) $params['eventid'] < 0 ) {
 55+ $this->dieUsage( 'Invalid event ID', 'badeventid' );
5356 }
54 -
55 - //check start and end date are of proper format
56 - if($params['startdate'] != 0 && strptime( $this->space_out_date($params['startdate']), "%Y %m %d") === false){
57 - $this->dieUsage("startdate not in YYYYMMDD format: <<{$params['startdate']}>>", "badstartdate");
 57+
 58+ // check start and end date are of proper format
 59+ if( $params['startdate'] != 0 && strptime( $this->space_out_date( $params['startdate'] ), "%Y %m %d" ) === false ) {
 60+ $this->dieUsage( "startdate not in YYYYMMDD format: <<{$params['startdate']}>>", 'badstartdate' );
5861 }
59 - if($params['enddate'] != 0 && strptime( $this->space_out_date($params['enddate']), "%Y %m %d") === false){
60 - $this->dieUsage("enddate not in YYYYMMDD format:<<{$params['enddate']}>>", "badenddate");
 62+ if( $params['enddate'] != 0 && strptime( $this->space_out_date( $params['enddate'] ), "%Y %m %d" ) === false ) {
 63+ $this->dieUsage( "enddate not in YYYYMMDD format:<<{$params['enddate']}>>", 'badenddate' );
6164 }
62 -
63 - //check if increment is a positive int
64 - if( (int) $params['increment'] <= 0){
65 - $this->dieUsage("Invalid increment", "badincrement");
 65+
 66+ // check if increment is a positive int
 67+ if( (int) $params['increment'] <= 0 ) {
 68+ $this->dieUsage( 'Invalid increment', 'badincrement' );
6669 }
67 -
68 - if(json_decode($params['userdefs']) == null){
69 - $this->dieUsage("Invalid JSON encoding <<{$params['userdefs']}>>", "badjson");
 70+
 71+ if( json_decode( $params['userdefs'] ) == null ) {
 72+ $this->dieUsage( "Invalid JSON encoding <<{$params['userdefs']}>>", 'badjson' );
7073 }
7174 }
7275
7376 /**
74 - * Space out the dates,
 77+ * Space out the dates
7578 * @param $datewithnospaces date with no spaces
7679 * @return date with spaces
7780 */
78 - public function space_out_date($datewithnospaces){
79 - return (substr($datewithnospaces, 0, 4) . " " .substr($datewithnospaces, 4, 2) . " " . substr($datewithnospaces, 6, 2));
 81+ public function space_out_date( $datewithnospaces ) {
 82+ return ( substr( $datewithnospaces, 0, 4 ) . ' ' .substr( $datewithnospaces, 4, 2 ) . ' ' . substr( $datewithnospaces, 6, 2 ) );
8083 }
81 -
 84+
8285 public function getParamDescription() {
8386 return array(
8487 'eventid' => 'event ID (number)',
8588 'startdate' => 'start date for data in YYYYMMDD format',
8689 'enddate' =>'end date for the data in YYYYMMDD format',
8790 'increment' => 'increment interval (in days) for data points',
 91+ 'userdefs' => 'JSON object to encode user definitions',
 92+ 'tabledata' => 'set to 1 for table data instead of chart data'
8893 );
8994 }
9095
9196 public function getDescription() {
9297 return array(
93 - 'Returns data to the special:clicktracking visualization page'
 98+ 'Returns data to the Special:ClickTracking visualization page'
9499 );
95100 }
96101
@@ -100,16 +105,22 @@
101106 ApiBase::PARAM_MIN => 1
102107 ),
103108 'startdate' => array(
104 - ApiBase::PARAM_TYPE => 'integer'
 109+ ApiBase::PARAM_TYPE => 'timestamp'
105110 ),
106111 'enddate' => array(
107 - ApiBase::PARAM_TYPE => 'integer'
 112+ ApiBase::PARAM_TYPE => 'timestamp'
108113 ),
109114 'increment' => array(
110115 ApiBase::PARAM_TYPE => 'integer',
111116 ApiBase::PARAM_MIN => 1,
112117 ApiBase::PARAM_MAX => 365 //1 year
113 - )
 118+ ),
 119+ 'userdefs' => array(
 120+ ApiBase::PARAM_TYPE => 'string'
 121+ ),
 122+ 'tabledata' => array(
 123+ ApiBase::PARAM_TYPE => 'integer'
 124+ ),
114125 );
115126 }
116127
Index: branches/wmf-deployment/extensions/UsabilityInitiative/ClickTracking/ClickTracking.i18n.php
@@ -33,6 +33,7 @@
3434 'ct-user-contribs' => 'Total user contributions',
3535 'ct-user-span' => 'User contributions in timespan',
3636 'ct-and' => 'and',
 37+ 'ct-update-table' => 'Update table',
3738 );
3839
3940 /** Message documentation (Message documentation)
@@ -71,12 +72,25 @@
7273
7374 /** Arabic (العربية)
7475 * @author Meno25
 76+ * @author OsamaK
7577 */
7678 $messages['ar'] = array(
 79+ 'clicktracking' => 'تتبع نقرات مبادرة الاستخدامية',
7780 'ct-event-name' => 'اسم الحدث',
 81+ 'ct-expert-header' => 'نقرات "الخبراء"',
 82+ 'ct-intermediate-header' => 'نقرات "المتوسطين"',
 83+ 'ct-beginner-header' => 'نقرات "المبتدئين"',
 84+ 'ct-total-header' => 'مجموع النقرات',
7885 'ct-beginner' => 'مبتدئ',
7986 'ct-intermediate' => 'متوسط',
8087 'ct-expert' => 'خبير',
 88+ 'ct-date-range' => 'نطاق التاريخ',
 89+ 'ct-editing' => 'يحرر حاليًا:',
 90+ 'ct-anon-users' => 'المستخدمون المجهولون',
 91+ 'ct-user-contribs' => 'مجموع مساهمات المستخدم',
 92+ 'ct-user-span' => 'مساهمات المستخدم في فترة زمنية',
 93+ 'ct-and' => 'و',
 94+ 'ct-update-table' => 'حدّث الجدول',
8195 );
8296
8397 /** Belarusian (Taraškievica orthography) (Беларуская (тарашкевіца))
@@ -106,6 +120,7 @@
107121 'ct-user-contribs' => 'Агульны ўнёсак удзельніка',
108122 'ct-user-span' => 'Унёсак удзельніка за адлегласьць часу',
109123 'ct-and' => 'і',
 124+ 'ct-update-table' => 'Абнавіць табліцу',
110125 );
111126
112127 /** Bengali (বাংলা)
@@ -134,6 +149,16 @@
135150 'clicktracking' => 'Heuliañ klikoù an intrudu implijadusted',
136151 'clicktracking-desc' => "Heuliañ klikoù, talvezout a ra da heuliañ an darvoudoù na vez ket adkarget ur bajenn d'ho heul",
137152 'ct-title' => "Sammad ar c'hlikoù implijerien",
 153+ 'ct-event-name' => 'Anv an darvoud',
 154+ 'ct-total-header' => "Hollad ar c'hlikoù",
 155+ 'ct-start-date' => 'Deiziad kregiñ (AAAAMMJJ)',
 156+ 'ct-end-date' => 'Deiziad echuiñ (AAAAMMJJ)',
 157+ 'ct-beginner' => 'Deraouad',
 158+ 'ct-intermediate' => 'Etre',
 159+ 'ct-expert' => 'Mailh',
 160+ 'ct-editing' => "Oc'h aozañ er mare-mañ :",
 161+ 'ct-anon-users' => 'implijerien dizanv',
 162+ 'ct-and' => 'ha(g)',
138163 );
139164
140165 /** Bosnian (Bosanski)
@@ -170,6 +195,7 @@
171196 'ct-total-header' => 'Clics totals',
172197 'ct-start-date' => "Data d'inici (AAAAMMDD)",
173198 'ct-end-date' => 'Data de finalització (AAAAMMDD)',
 199+ 'ct-anon-users' => 'Usuaris anònims',
174200 );
175201
176202 /** Czech (Česky)
@@ -200,10 +226,12 @@
201227
202228 /** German (Deutsch)
203229 * @author Metalhead64
 230+ * @author Umherirrender
204231 */
205232 $messages['de'] = array(
206233 'clicktracking' => 'Benutzerfreundlichkeitsinitiative Klickverfolgung',
207234 'clicktracking-desc' => 'Klickverfolgung, gedacht für die Aufzeichnung von Aktionen, die nicht zu einer Seitenaktualisierung führen',
 235+ 'ct-title' => 'Gesamtsumme aller Benutzerklicks',
208236 'ct-event-name' => 'Ereignisname',
209237 'ct-expert-header' => 'Expertenklicks',
210238 'ct-intermediate-header' => 'Klicks von Mittleren',
@@ -211,12 +239,49 @@
212240 'ct-total-header' => 'Gesamtklicks',
213241 'ct-start-date' => 'Start (JJJJMMTT)',
214242 'ct-end-date' => 'Ende (JJJJMMTT)',
 243+ 'ct-increment-by' => 'Anzahl der Tage, die von jedem Datenpunkt repräsentiert werden',
215244 'ct-change-graph' => 'Grafik ändern',
216245 'ct-beginner' => 'Anfänger',
217246 'ct-intermediate' => 'Mittlere',
218247 'ct-expert' => 'Experte',
 248+ 'ct-date-range' => 'Datumsbereich',
 249+ 'ct-editing' => 'Derzeit bearbeitet von:',
 250+ 'ct-anon-users' => 'Anonyme Benutzer',
 251+ 'ct-user-contribs' => 'Gesamte Benutzerbeiträge',
 252+ 'ct-user-span' => 'Benutzerbeiträge in Zeitspanne',
 253+ 'ct-and' => 'und',
 254+ 'ct-update-table' => 'Tabelle aktualisieren',
219255 );
220256
 257+/** Zazaki (Zazaki)
 258+ * @author Aspar
 259+ * @author Xoser
 260+ */
 261+$messages['diq'] = array(
 262+ 'clicktracking' => 'tıknayiş u temaşakerdışê teşebbusê şuxul biyayişi',
 263+ 'clicktracking-desc' => 'Eka yew pele ke reciwane nibeno, ay ser gocekê trackingî rê bitekne',
 264+ 'ct-title' => 'tıknayişê karberê kombiyayeyi',
 265+ 'ct-event-name' => 'nameyê meselayi',
 266+ 'ct-expert-header' => 'tıknayişê "tecrubeyınan"',
 267+ 'ct-intermediate-header' => 'tıknayişê "seviyeya weseti"',
 268+ 'ct-beginner-header' => 'tıknayişê "ecemiyani"',
 269+ 'ct-total-header' => 'heme tıknayişi',
 270+ 'ct-start-date' => 'tarixê destpêkerdışi (YYYYMMDD)',
 271+ 'ct-end-date' => 'tarixê qediyayişi (YYYYMMDD)',
 272+ 'ct-increment-by' => 'Number of days each data point represents',
 273+ 'ct-change-graph' => 'Grafiki bıvurnê',
 274+ 'ct-beginner' => 'ecemi',
 275+ 'ct-intermediate' => 'seviyeya weseti',
 276+ 'ct-expert' => 'tecrubeyın',
 277+ 'ct-date-range' => 'tarix de',
 278+ 'ct-editing' => 'nıka vurneno',
 279+ 'ct-anon-users' => 'karberê anonimi',
 280+ 'ct-user-contribs' => 'heme ardimê karberi',
 281+ 'ct-user-span' => 'ardimê karberi',
 282+ 'ct-and' => 'u',
 283+ 'ct-update-table' => 'tabloya rocaneyi',
 284+);
 285+
221286 /** Lower Sorbian (Dolnoserbski)
222287 * @author Michawiki
223288 */
@@ -242,9 +307,11 @@
243308 'ct-user-contribs' => 'Wužywarske pśinoski dogromady',
244309 'ct-user-span' => 'Wužywarske pśinoski w casowem wótrězku',
245310 'ct-and' => 'a',
 311+ 'ct-update-table' => 'Tabelu aktualizěrowaś',
246312 );
247313
248314 /** Greek (Ελληνικά)
 315+ * @author Consta
249316 * @author Crazymadlover
250317 * @author Omnipaedista
251318 * @author ZaDiak
@@ -263,9 +330,11 @@
264331 'ct-beginner' => 'Αρχάριος',
265332 'ct-intermediate' => 'Μέτριος',
266333 'ct-expert' => 'Ειδικός',
 334+ 'ct-and' => 'και',
267335 );
268336
269337 /** Esperanto (Esperanto)
 338+ * @author Lucas
270339 * @author Yekrats
271340 */
272341 $messages['eo'] = array(
@@ -280,6 +349,9 @@
281350 'ct-beginner' => 'Novulo',
282351 'ct-intermediate' => 'Progresanto',
283352 'ct-expert' => 'Spertulo',
 353+ 'ct-editing' => 'Nune redaktante:',
 354+ 'ct-anon-users' => 'Sennomaj uzantoj',
 355+ 'ct-and' => 'kaj',
284356 );
285357
286358 /** Spanish (Español)
@@ -287,6 +359,7 @@
288360 * @author Crazymadlover
289361 * @author Dalton2
290362 * @author Locos epraix
 363+ * @author Translationista
291364 */
292365 $messages['es'] = array(
293366 'clicktracking' => 'Iniciativa de usabilidad de seguimiento mediante clics',
@@ -310,8 +383,29 @@
311384 'ct-user-contribs' => 'Total de contribuciones de los usuarios',
312385 'ct-user-span' => 'Contribuciones de usuario en lapso de tiempo',
313386 'ct-and' => 'y',
 387+ 'ct-update-table' => 'Actualizar tabla',
314388 );
315389
 390+/** Estonian (Eesti)
 391+ * @author Pikne
 392+ */
 393+$messages['et'] = array(
 394+ 'clicktracking' => 'Kasutushõlpsuse algatuse klõpsujälitus',
 395+ 'ct-event-name' => 'Sündmuse nimi',
 396+ 'ct-expert-header' => 'Asjatundjaklõpsud',
 397+ 'ct-intermediate-header' => 'Edasijõudnuklõpsud',
 398+ 'ct-beginner-header' => 'Algajaklõpsud',
 399+ 'ct-start-date' => 'Alguskuupäev (AAAAKKPP)',
 400+ 'ct-end-date' => 'Lõpukuupäev (AAAAKKPP)',
 401+ 'ct-beginner' => 'Algaja',
 402+ 'ct-intermediate' => 'Edasijõudnu',
 403+ 'ct-expert' => 'Asjatundja',
 404+ 'ct-date-range' => 'Kuupäevavahemik',
 405+ 'ct-editing' => 'Parajasti muutmisel:',
 406+ 'ct-anon-users' => 'Nimetud kasutajad',
 407+ 'ct-and' => 'ja',
 408+);
 409+
316410 /** Basque (Euskara)
317411 * @author An13sa
318412 */
@@ -330,13 +424,21 @@
331425 );
332426
333427 /** Finnish (Suomi)
 428+ * @author Cimon Avaro
334429 * @author Crt
335430 * @author Str4nd
336431 */
337432 $messages['fi'] = array(
338433 'clicktracking' => 'Käytettävyyshankkeen klikkausten seuranta',
339434 'clicktracking-desc' => 'Klikkausten seuranta, tarkoituksena seurata tapahtumia, jotka eivät aiheuta sivun uudelleenlataamista.',
 435+ 'ct-title' => 'Käyttäjän napsautuksien yhteenlaskettu määrä',
340436 'ct-event-name' => 'Tapahtuman nimi',
 437+ 'ct-total-header' => 'Napsautuksia yhteensä',
 438+ 'ct-start-date' => 'Alkamispäivä (VVVVKKPP)',
 439+ 'ct-end-date' => 'Lopetuspäivä (VVVVKKPP)',
 440+ 'ct-beginner' => 'Aloittelija',
 441+ 'ct-intermediate' => 'Keskitaso',
 442+ 'ct-expert' => 'Asiantuntija',
341443 'ct-anon-users' => 'Anonyymit käyttäjät',
342444 'ct-and' => 'ja',
343445 );
@@ -367,6 +469,7 @@
368470 'ct-user-contribs' => 'Contributions totales des utilisateurs',
369471 'ct-user-span' => "Contributions de l'utilisateur sur la durée",
370472 'ct-and' => 'et',
 473+ 'ct-update-table' => 'Mettre à jour la table',
371474 );
372475
373476 /** Galician (Galego)
@@ -394,6 +497,7 @@
395498 'ct-user-contribs' => 'Contribucións totais do usuario',
396499 'ct-user-span' => 'Contribucións do usuario nun período de tempo',
397500 'ct-and' => 'e',
 501+ 'ct-update-table' => 'Actualizar a táboa',
398502 );
399503
400504 /** Swiss German (Alemannisch)
@@ -421,16 +525,18 @@
422526 'ct-user-contribs' => 'Gsamti Benutzerbyytreg',
423527 'ct-user-span' => 'Benutzerbyytreg in Zytspanne',
424528 'ct-and' => 'un',
 529+ 'ct-update-table' => 'Tabälle aktualisiere',
425530 );
426531
427532 /** Hebrew (עברית)
428533 * @author Rotem Liss
 534+ * @author Rotemliss
429535 * @author YaronSh
430536 */
431537 $messages['he'] = array(
432538 'clicktracking' => 'מעקב לחיצות במיזם השימושיות',
433539 'clicktracking-desc' => 'מעקב לחיצות עבור בדיקת אירועים שאינם גורמים לרענון דף',
434 - 'ct-title' => 'כמות לחיצות המשתמשים המצטברות',
 540+ 'ct-title' => 'הכמות המצטברת של לחיצות המשתמשים',
435541 'ct-event-name' => 'שם האירוע',
436542 'ct-expert-header' => 'לחיצות של "מומחים"',
437543 'ct-intermediate-header' => 'לחיצות של "בינוניים"',
@@ -449,14 +555,17 @@
450556 'ct-user-contribs' => 'סך כל תרומות המשתמשים',
451557 'ct-user-span' => 'תרומות המשתמשים לאורך הזמן',
452558 'ct-and' => 'וגם',
 559+ 'ct-update-table' => 'עדכון הטבלה',
453560 );
454561
455562 /** Croatian (Hrvatski)
 563+ * @author Mvrban
456564 * @author Suradnik13
457565 */
458566 $messages['hr'] = array(
459567 'clicktracking' => 'Praćenje klikova u Inicijativi za uporabljivosti',
460568 'clicktracking-desc' => 'Praćenje klikova, napravljeno za praćenje događaja koji ne dovode do osvježavanja stanice',
 569+ 'ct-start-date' => 'Početni datum (DDMMYYYY)',
461570 );
462571
463572 /** Upper Sorbian (Hornjoserbsce)
@@ -484,6 +593,7 @@
485594 'ct-user-contribs' => 'Wužiwarske přinoški dohromady',
486595 'ct-user-span' => 'Wužiwarske přinoški w časowym wotrězku',
487596 'ct-and' => 'a',
 597+ 'ct-update-table' => 'Tabelu aktualizować',
488598 );
489599
490600 /** Hungarian (Magyar)
@@ -513,6 +623,7 @@
514624 'ct-user-contribs' => 'Összes szerkesztői közreműködés',
515625 'ct-user-span' => 'A szerkesztő közreműködései az időszakon belül',
516626 'ct-and' => 'és',
 627+ 'ct-update-table' => 'Táblázat frissítése',
517628 );
518629
519630 /** Interlingua (Interlingua)
@@ -521,6 +632,7 @@
522633 $messages['ia'] = array(
523634 'clicktracking' => 'Traciamento de clics del Initiativa de Usabilitate',
524635 'clicktracking-desc' => 'Traciamento de clics, pro traciar eventos que non causa un recargamento de pagina',
 636+ 'ct-title' => 'Clics de usator aggregate',
525637 'ct-event-name' => 'Nomine del evento',
526638 'ct-expert-header' => 'Clics "experte"',
527639 'ct-intermediate-header' => 'Clics "intermedie"',
@@ -533,6 +645,13 @@
534646 'ct-beginner' => 'Comenciante',
535647 'ct-intermediate' => 'Intermedie',
536648 'ct-expert' => 'Experte',
 649+ 'ct-date-range' => 'Intervallo de datas',
 650+ 'ct-editing' => 'Actualmente modificante:',
 651+ 'ct-anon-users' => 'Usatores anonyme',
 652+ 'ct-user-contribs' => 'Total de contributiones de usatores',
 653+ 'ct-user-span' => 'Contributiones de usatores in intervallo de tempore',
 654+ 'ct-and' => 'e',
 655+ 'ct-update-table' => 'Actualisar tabella',
537656 );
538657
539658 /** Indonesian (Bahasa Indonesia)
@@ -561,6 +680,7 @@
562681 'ct-user-contribs' => 'Total kontribusi pengguna',
563682 'ct-user-span' => 'Kontribusi pengguna dalam rentang waktu',
564683 'ct-and' => 'dan',
 684+ 'ct-update-table' => 'Pemutahiran tabel',
565685 );
566686
567687 /** Japanese (日本語)
@@ -589,6 +709,7 @@
590710 'ct-user-contribs' => '利用者投稿の合計',
591711 'ct-user-span' => '期間ごとの利用者投稿',
592712 'ct-and' => 'および',
 713+ 'ct-update-table' => 'テーブルを更新',
593714 );
594715
595716 /** Georgian (ქართული)
@@ -609,13 +730,31 @@
610731 'ct-and' => 'និង​',
611732 );
612733
 734+/** Korean (한국어)
 735+ * @author Klutzy
 736+ * @author Kwj2772
 737+ */
 738+$messages['ko'] = array(
 739+ 'clicktracking' => 'Usability Initiative 사용자 클릭 추적기',
 740+ 'clicktracking-desc' => '마우스 클릭 이벤트 중에서 웹 페이지 새로고침과 관계없는 것들을 추적합니다.',
 741+ 'ct-event-name' => '이벤트 이름',
 742+ 'ct-start-date' => '시작 날짜 (YYYYMMDD)',
 743+ 'ct-end-date' => '마지막 날짜 (YYYYMMDD)',
 744+ 'ct-beginner' => '초보자',
 745+ 'ct-intermediate' => '중급 사용자',
 746+ 'ct-expert' => '전문가',
 747+ 'ct-date-range' => '날짜 범위',
 748+ 'ct-and' => '그리고',
 749+ 'ct-update-table' => '표 업데이트',
 750+);
 751+
613752 /** Ripoarisch (Ripoarisch)
614753 * @author Purodha
615754 */
616755 $messages['ksh'] = array(
617756 'clicktracking' => 'Dä <i lang="en">Wikipedia Usability Initiative</i> ier Kleckverfolljung',
618757 'clicktracking-desc' => 'Klecks un Akßuhne Verfollje, di kein neu Sigg afroofe donn.',
619 - 'ct-title' => 'Jesampte Klecks vun enem Metmaacher',
 758+ 'ct-title' => 'Metmaacher ier jesampte Klecks',
620759 'ct-event-name' => 'Da Name vun dämm, wat passeet es',
621760 'ct-expert-header' => 'Klecks vun „{{int:Expert}}“',
622761 'ct-intermediate-header' => 'Klecks vun „{{int:Intermediate}}“',
@@ -642,6 +781,7 @@
643782 $messages['lb'] = array(
644783 'clicktracking' => 'Benotzerfrëndlechkeetsinitiative Suivi vun de Klicken',
645784 'clicktracking-desc' => "Suivi vun de Klicken, fir déi Aktiounen z'erfaassen déi net zu engem neie Luede vun der Säit féieren",
 785+ 'ct-title' => 'Opgezeechent Benotzerklicken',
646786 'ct-event-name' => 'Numm vum Evenement',
647787 'ct-expert-header' => '"Expert"-Klicken',
648788 'ct-intermediate-header' => '"Duerschnëtt"-Klicken',
@@ -654,10 +794,13 @@
655795 'ct-beginner' => 'Ufänger',
656796 'ct-intermediate' => 'Dertëschent',
657797 'ct-expert' => 'Expert',
 798+ 'ct-date-range' => 'Datumsberäich',
658799 'ct-editing' => 'Ännert elo:',
659800 'ct-anon-users' => 'Anonym Benotzer',
660801 'ct-user-contribs' => 'Total vun de Benotzer-Kontributiounen',
 802+ 'ct-user-span' => 'Benotzerkontributiounen am Zäitraum',
661803 'ct-and' => 'an',
 804+ 'ct-update-table' => 'Tabell aktualiséieren',
662805 );
663806
664807 /** Macedonian (Македонски)
@@ -666,8 +809,43 @@
667810 $messages['mk'] = array(
668811 'clicktracking' => 'Следење на кликнувања на Иницијативата за употребливост',
669812 'clicktracking-desc' => 'Следење на кликнувања, наменето за следење на постапки кои не предизвикуваат превчитување на страницата',
 813+ 'ct-title' => 'Насобрани кориснички кликови',
 814+ 'ct-event-name' => 'Име на настанот',
 815+ 'ct-expert-header' => '„Експертски“ кликови',
 816+ 'ct-intermediate-header' => '„Средно-учеснички“ кликови',
 817+ 'ct-beginner-header' => '„Почетнички“ кликови',
 818+ 'ct-total-header' => 'Вкупно кликови',
 819+ 'ct-start-date' => 'Почетен датум (ГГГГММДД)',
 820+ 'ct-end-date' => 'Завршен датум (ГГГГММДД)',
 821+ 'ct-increment-by' => 'Број на денови што ги претставува секоја податочна точка',
 822+ 'ct-change-graph' => 'Промени го графикот',
 823+ 'ct-beginner' => 'Почетник',
 824+ 'ct-intermediate' => 'Среден',
 825+ 'ct-expert' => 'Експерт',
 826+ 'ct-date-range' => 'Датуми',
 827+ 'ct-editing' => 'Моментално уредувате:',
 828+ 'ct-anon-users' => 'Анонимни корисници',
 829+ 'ct-user-contribs' => 'Вкупно кориснички придонеси',
 830+ 'ct-user-span' => 'Ккориснички придонеси за период',
 831+ 'ct-and' => 'и',
 832+ 'ct-update-table' => 'Ажурирај ја таблицата',
670833 );
671834
 835+/** Malayalam (മലയാളം)
 836+ * @author Praveenp
 837+ */
 838+$messages['ml'] = array(
 839+ 'ct-start-date' => 'തുടങ്ങുന്ന തീയതി (YYYYMMDD)',
 840+ 'ct-end-date' => 'അവസാനിക്കുന്ന തീയതി (YYYYMMDD)',
 841+ 'ct-change-graph' => 'ഗ്രാഫിൽ മാറ്റംവരുത്തുക',
 842+ 'ct-editing' => 'ഇപ്പോൾ തിരുത്തുന്നത്:',
 843+ 'ct-anon-users' => 'അജ്ഞാത ഉപയോക്താക്കൾ',
 844+ 'ct-user-contribs' => 'ഉപയോക്താവിന്റെ ആകെ സേവനങ്ങൾ',
 845+ 'ct-user-span' => 'ഉപയോക്താവിന്റെ സേവനങ്ങൾ സമയക്രമത്തിൽ',
 846+ 'ct-and' => 'ഒപ്പം',
 847+ 'ct-update-table' => 'പട്ടിക പുതുക്കുക',
 848+);
 849+
672850 /** Malay (Bahasa Melayu)
673851 * @author Kurniasan
674852 */
@@ -701,8 +879,43 @@
702880 'ct-user-contribs' => 'Totaal aantal gebruikersbijdragen',
703881 'ct-user-span' => 'Gebruikersbijdragen in periode',
704882 'ct-and' => 'en',
 883+ 'ct-update-table' => 'Tabel bijwerken',
705884 );
706885
 886+/** Norwegian Nynorsk (‪Norsk (nynorsk)‬)
 887+ * @author Gunnernett
 888+ */
 889+$messages['nn'] = array(
 890+ 'ct-start-date' => 'Startdato (ÅÅÅÅMMDD)',
 891+ 'ct-expert' => 'Ekspert',
 892+ 'ct-anon-users' => 'Anonyme brukarar',
 893+);
 894+
 895+/** Norwegian (bokmål)‬ (‪Norsk (bokmål)‬)
 896+ * @author Jon Harald Søby
 897+ */
 898+$messages['no'] = array(
 899+ 'clicktracking' => 'Klikksporing for brukervennlighetsprosjektet.',
 900+ 'clicktracking-desc' => 'Sporer klikk som ikke forårsaker lasting av ny side.',
 901+ 'ct-expert-header' => '«Ekspertklikk»',
 902+ 'ct-intermediate-header' => '«Mellomnivåbrukerklikk»',
 903+ 'ct-beginner-header' => '«Nybegynnerklikk»',
 904+ 'ct-total-header' => 'Totalt antall klikk',
 905+ 'ct-start-date' => 'Fra (ÅÅÅÅMMDD)',
 906+ 'ct-end-date' => 'Til (ÅÅÅÅMMDD)',
 907+ 'ct-increment-by' => 'Antall dager representert i hvert datapunkt.',
 908+ 'ct-change-graph' => 'Endre graf',
 909+ 'ct-beginner' => 'Nybegynner',
 910+ 'ct-intermediate' => 'Mellomnivåbruker',
 911+ 'ct-expert' => 'Ekspert',
 912+ 'ct-date-range' => 'Datoer som vises',
 913+ 'ct-editing' => 'Redigerer:',
 914+ 'ct-anon-users' => 'Anonyme brukere',
 915+ 'ct-user-contribs' => 'Totalt antall bidrag',
 916+ 'ct-user-span' => 'Bidrag i tid',
 917+ 'ct-and' => 'og',
 918+);
 919+
707920 /** Occitan (Occitan)
708921 * @author Cedric31
709922 */
@@ -728,9 +941,11 @@
729942 'ct-user-contribs' => 'Contribucions totalas dels utilizaires',
730943 'ct-user-span' => "Contribucions de l'utilizaire sus la durada",
731944 'ct-and' => 'e',
 945+ 'ct-update-table' => 'Metre a jorn la taula',
732946 );
733947
734948 /** Polish (Polski)
 949+ * @author Leinad
735950 * @author Sp5uhe
736951 */
737952 $messages['pl'] = array(
@@ -755,6 +970,7 @@
756971 'ct-user-contribs' => 'Ogółem wkład użytkownika',
757972 'ct-user-span' => 'Wkład użytkownika w przedziale czasu',
758973 'ct-and' => 'i',
 974+ 'ct-update-table' => 'Uaktualnij tabelę',
759975 );
760976
761977 /** Piedmontese (Piemontèis)
@@ -786,12 +1002,17 @@
7871003
7881004 /** Portuguese (Português)
7891005 * @author Giro720
 1006+ * @author Lijealso
7901007 */
7911008 $messages['pt'] = array(
7921009 'ct-change-graph' => 'Mudar gráfico',
7931010 'ct-beginner' => 'Iniciante',
7941011 'ct-intermediate' => 'Intermediário',
7951012 'ct-expert' => 'Experiente',
 1013+ 'ct-date-range' => 'Intervalo de datas',
 1014+ 'ct-editing' => 'A editar actualmente:',
 1015+ 'ct-anon-users' => 'Usuários anónimos',
 1016+ 'ct-and' => 'e',
7961017 );
7971018
7981019 /** Brazilian Portuguese (Português do Brasil)
@@ -829,6 +1050,7 @@
8301051 'ct-user-contribs' => 'Общий вклад участников',
8311052 'ct-user-span' => 'Вклад участников за период',
8321053 'ct-and' => 'и',
 1054+ 'ct-update-table' => 'Обновить таблицу',
8331055 );
8341056
8351057 /** Yakut (Саха тыла)
@@ -848,6 +1070,9 @@
8491071 'ct-beginner' => 'Саҥа кыттааччы',
8501072 'ct-intermediate' => 'Бороохтуйбут кыттааччы',
8511073 'ct-expert' => 'Эксперт',
 1074+ 'ct-date-range' => 'Күн-дьыл диапазона',
 1075+ 'ct-anon-users' => 'Ааттамматах кыттааччылар',
 1076+ 'ct-and' => 'уонна',
8521077 );
8531078
8541079 /** Slovak (Slovenčina)
@@ -856,6 +1081,7 @@
8571082 $messages['sk'] = array(
8581083 'clicktracking' => 'Sledovanie kliknutí pre Iniciatívu použiteľnosti',
8591084 'clicktracking-desc' => 'Sledovanie kliknutí, na sledovanie udalostí, ktoré nespôsobujú opätovné načítanie stránky',
 1085+ 'ct-title' => 'Agregovaných kliknutí',
8601086 'ct-event-name' => 'Názov udalosti',
8611087 'ct-expert-header' => 'Kliknutia „expertov“',
8621088 'ct-intermediate-header' => 'Kliknutia „pokročilých“',
@@ -868,6 +1094,12 @@
8691095 'ct-beginner' => 'Začiatočník',
8701096 'ct-intermediate' => 'Pokročilý',
8711097 'ct-expert' => 'Expert',
 1098+ 'ct-date-range' => 'Rozsah dátumov',
 1099+ 'ct-editing' => 'Momentálne upravuje:',
 1100+ 'ct-anon-users' => 'Anonymní používatelia',
 1101+ 'ct-user-contribs' => 'Používateľských príspevkov celkom',
 1102+ 'ct-user-span' => 'Používateľských príspevkov za obdobie',
 1103+ 'ct-and' => 'a',
8721104 );
8731105
8741106 /** Slovenian (Slovenščina)
@@ -878,12 +1110,26 @@
8791111 'clicktracking-desc' => 'Sledenje klikom, namenjeno odkrivanju dogodkov, ki preprečujejo osvežitev strani med urejanjem',
8801112 );
8811113
 1114+/** Telugu (తెలుగు)
 1115+ * @author Veeven
 1116+ */
 1117+$messages['te'] = array(
 1118+ 'ct-event-name' => 'ఘటన పేరు',
 1119+ 'ct-total-header' => 'మొత్తం నొక్కులు',
 1120+ 'ct-start-date' => 'ప్రారంభ తేదీ (YYYYMMDD)',
 1121+ 'ct-end-date' => 'ముగింపు తేదీ (YYYYMMDD)',
 1122+ 'ct-editing' => 'ప్రస్తుతం మారుస్తున్నారు:',
 1123+ 'ct-anon-users' => 'అజ్ఞాత వాడుకరులు',
 1124+ 'ct-and' => 'మరియు',
 1125+);
 1126+
8821127 /** Turkish (Türkçe)
8831128 * @author Joseph
8841129 */
8851130 $messages['tr'] = array(
8861131 'clicktracking' => 'Kullanılabilirlik Girişimi tıklama izleme',
8871132 'clicktracking-desc' => 'Tıklama izleme, bir sayfa yenilemesine sebep olmadan olayları izleme amaçlı',
 1133+ 'ct-title' => 'Kümeli kullanıcı tıklamaları',
8881134 'ct-event-name' => 'Olay adı',
8891135 'ct-expert-header' => '"Deneyimli" tıklamaları',
8901136 'ct-intermediate-header' => '"Orta düzeyde" tıklamaları',
@@ -897,9 +1143,12 @@
8981144 'ct-intermediate' => 'Orta düzeyde',
8991145 'ct-expert' => 'Deneyimli',
9001146 'ct-date-range' => 'Tarih aralığı',
 1147+ 'ct-editing' => 'Şuanda değiştiriyor:',
9011148 'ct-anon-users' => 'Anonim kullanıcılar',
9021149 'ct-user-contribs' => 'Toplam kullanıcı katkıları',
 1150+ 'ct-user-span' => 'Zaman içerisindeki kullanıcı katkıları',
9031151 'ct-and' => 've',
 1152+ 'ct-update-table' => 'Tabloyu güncelle',
9041153 );
9051154
9061155 /** Vèneto (Vèneto)
@@ -908,6 +1157,7 @@
9091158 $messages['vec'] = array(
9101159 'clicktracking' => "Traciamento click de l'Inissiativa par l'Usabilità",
9111160 'clicktracking-desc' => 'Traciamento dei click, par traciare i eventi che no provoca mia un refresh de la pagina.',
 1161+ 'ct-title' => 'Clic dei utenti messi insieme',
9121162 'ct-event-name' => "Nome de l'evento",
9131163 'ct-expert-header' => 'Clic de "esperti"',
9141164 'ct-intermediate-header' => 'Clic de "intermedi"',
@@ -920,6 +1170,13 @@
9211171 'ct-beginner' => 'Prinsipiante',
9221172 'ct-intermediate' => 'Intermedio',
9231173 'ct-expert' => 'Esperto',
 1174+ 'ct-date-range' => 'Interval de date',
 1175+ 'ct-editing' => 'En corso de modìfega:',
 1176+ 'ct-anon-users' => 'Utenti anonimi',
 1177+ 'ct-user-contribs' => 'Contributi utente totali',
 1178+ 'ct-user-span' => "Contributi de l'utente su la durata",
 1179+ 'ct-and' => 'e',
 1180+ 'ct-update-table' => 'Ajorna tabèla',
9241181 );
9251182
9261183 /** Veps (Vepsan kel')
@@ -956,6 +1213,7 @@
9571214 'ct-user-contribs' => 'Tổng số lần đóng góp',
9581215 'ct-user-span' => 'Số lần đóng góp trong thời gian',
9591216 'ct-and' => 'và',
 1217+ 'ct-update-table' => 'Cập nhật bảng',
9601218 );
9611219
9621220 /** Yue (粵語)
Index: branches/wmf-deployment/extensions/UsabilityInitiative/ClickTracking/ClickTracking.php
@@ -18,6 +18,9 @@
1919
2020 /* Configuration */
2121
 22+// Increment this value when you change ClickTracking.js
 23+$wgClickTrackingStyleVersion = 2;
 24+
2225 // click throttle, should be seen as "1 out of every $wgClickTrackThrottle users will have it enabled"
2326 // setting this to 1 means all users will have it enabled
2427 // setting to a negative number will disable it for all users
@@ -25,7 +28,7 @@
2629
2730 // set the time window for what we consider 'recent' contributions, in days
2831 $wgClickTrackContribGranularity1 = 60 * 60 * 24 * 365 / 2; // half a year
29 -$wgClickTrackContribGranularity2 =60 * 60 * 24 * 365 / 4; // 1/4 a year (3 months approx)
 32+$wgClickTrackContribGranularity2 = 60 * 60 * 24 * 365 / 4; // 1/4 a year (3 months approx)
3033 $wgClickTrackContribGranularity3 = 60 * 60 * 24 * 30; //30 days (1 month approx)
3134
3235 // Credits
@@ -45,20 +48,21 @@
4649 $dir = dirname( __FILE__ ) . '/';
4750 $wgAutoloadClasses['ClickTrackingHooks'] = $dir . 'ClickTracking.hooks.php';
4851 $wgAutoloadClasses['ApiClickTracking'] = $dir . 'ApiClickTracking.php';
49 -//$wgAutoloadClasses['SpecialClickTracking'] = $dir . 'SpecialClickTracking.php';
50 -//$wgAutoloadClasses['ApiSpecialClickTracking'] = $dir .'ApiSpecialClickTracking.php';
 52+$wgAutoloadClasses['SpecialClickTracking'] = $dir . 'SpecialClickTracking.php';
 53+$wgAutoloadClasses['ApiSpecialClickTracking'] = $dir .'ApiSpecialClickTracking.php';
5154
5255 // Hooked functions
5356 $wgHooks['LoadExtensionSchemaUpdates'][] = 'ClickTrackingHooks::schema';
54 -$wgHooks['EditPage::showEditForm:initial'][] = 'ClickTrackingHooks::addJS';
 57+$wgHooks['AjaxAddScript'][] = 'ClickTrackingHooks::addJS';
 58+$wgHooks['ParserTestTables'][] = 'ClickTrackingHooks::parserTestTables';
5559
5660 // Set up the new API module
5761 $wgAPIModules['clicktracking'] = 'ApiClickTracking';
58 -//$wgAPIModules['specialclicktracking'] = 'ApiSpecialClickTracking';
 62+$wgAPIModules['specialclicktracking'] = 'ApiSpecialClickTracking';
5963
6064 //Special page setup
61 -//$wgSpecialPages['ClickTracking'] = 'SpecialClickTracking';
62 -//$wgGroupPermissions['sysop']['clicktrack'] = true;
 65+$wgSpecialPages['ClickTracking'] = 'SpecialClickTracking';
 66+$wgGroupPermissions['sysop']['clicktrack'] = true;
6367
6468 // Adds Internationalized Messages
6569 $wgExtensionMessagesFiles['ClickTracking'] = $dir . 'ClickTracking.i18n.php';
Property changes on: branches/wmf-deployment/extensions/UsabilityInitiative/ClickTracking/ClickTracking.php
___________________________________________________________________
Deleted: svn:mergeinfo
6670 Reverse-merged /branches/REL1_15/phase3/extensions/UsabilityInitiative/ClickTracking/ClickTracking.php:r51646
6771 Reverse-merged /trunk/extensions/UsabilityInitiative/ClickTracking/ClickTracking.php:r56151-57234,57543-57549
6872 Reverse-merged /trunk/phase3/extensions/UsabilityInitiative/ClickTracking/ClickTracking.php:r56213,56215-56216,56218,56325,56334-56336,56338,56340,56343,56345,56347,56350,57154-57447,57541,57916,58151,58219,58633,58816
Index: branches/wmf-deployment/extensions/UsabilityInitiative/ClickTracking/SpecialClickTracking.php
@@ -8,36 +8,12 @@
99
1010 class SpecialClickTracking extends SpecialPage {
1111
12 - //set to zero for 'all'
13 - private $top_results = 10;
14 - private $normalize_top_results = false;
15 - private $normalize_results = false;
16 - private $minimum_date = '20090815'; //YYYYMMDD (+1 for today)
17 - private $end_timeframe = '20090902';
 12+ private static $minimum_date = '20091009'; //YYYYMMDD (+1 for today)
1813
19 -
2014 private static $userTypes = array("basic" => 0, "intermediate" => 1, "expert" => 2);
2115 private $user_defs = array();
2216
23 - //array of event_id => event_name
24 - public static $join_conds = " LEFT JOIN click_tracking_events ON event_id=click_tracking_events.id";
25 - public static $expert_user_conds = "user_total_contribs > 10 ";
26 - public static $intermediate_user_conds = "user_total_contribs < 10 AND user_total_contribs > 1 ";
27 - public static $basic_user_conds = "user_total_contribs <= 1";
2817
29 - /*
30 - * " DISTINCT session_id "
31 - *
32 - * " select count(*), event_id from click_tracking group by event_id order by count(*) desc limit 10;"
33 - *
34 - */
35 -
36 - private $event_id_to_name = array();
37 - private $name_to_event_id = array();
38 - private $time_constraint_sql = "";
39 -
40 -
41 -
4218 function __construct() {
4319 parent::__construct( 'ClickTracking' , 'clicktrack');
4420 wfLoadExtensionMessages( 'ClickTracking' );
@@ -47,28 +23,26 @@
4824 }
4925
5026
51 -
52 -
5327 function setDefaults(){
5428 $this->user_defs["basic"] = array(
5529 "anonymous" => "1",
5630 "total_contribs" => array(
57 - array("operation" => "<=", "value" => "1"),
 31+ array("operation" => "<=", "value" => "10"),
5832 ),
5933 );
6034
6135 $this->user_defs["intermediate"] = array(
6236 "anonymous" => "0",
6337 "total_contribs" => array(
64 - array("operation" => "<", "value" => "10"),
65 - array("operation" => ">", "value" => "1"),
 38+ array("operation" => "<", "value" => "400"),
 39+ array("operation" => ">", "value" => "10"),
6640 ),
6741 );
6842
6943 $this->user_defs["expert"] = array(
7044 "anonymous" => "0",
7145 "total_contribs" => array(
72 - array("operation" => ">=", "value" => "10"),
 46+ array("operation" => ">=", "value" => "400"),
7347 ),
7448 );
7549
@@ -113,7 +87,7 @@
11488 $header_row["event_header"] = wfMsg( 'ct-event-name' );
11589 $header_row["expert_header"] = wfMsg( 'ct-expert-header' );
11690 $header_row["intermediate_header"] = wfMsg( 'ct-intermediate-header' );
117 - $header_row["beginner_header"] = wfMsg( 'ct-beginner-header' );
 91+ $header_row["basic_header"] = wfMsg( 'ct-beginner-header' );
11892 $header_row["total_header"] = wfMsg( 'ct-total-header' );
11993 $outputTable .= Xml::buildTableRow( array( "class"=>"table_headers" ), $header_row );
12094
@@ -137,7 +111,7 @@
138112 //$wgOut->addHTML($this->buildControlBox());
139113
140114 $wgOut->addHTML($this->buildChartDialog());
141 - $wgOut->addHTML($this->buildUserDefDialog());
 115+ $wgOut->addHTML($this->buildUserDefBlankDialog());
142116
143117 }
144118
@@ -174,26 +148,7 @@
175149 if($isUserDefsJSON){
176150 $userDefs = json_decode($userDefs, true);
177151 }
178 -
179 - $userDefQueries = array();
180 -
181 - foreach ($userDefs as $name => $def){
182 - if(!isset($def['total_contribs'])){
183 - $def['total_contribs'] = array();
184 - }
185 - if(!isset($def['contrib_1'])){
186 - $def['contrib_1'] = array();
187 - }
188 - if(!isset($def['contrib_2'])){
189 - $def['contrib_2'] = array();
190 - }
191 - if(!isset($def['contrib_3'])){
192 - $def['contrib_3'] = array();
193 - }
194 - $userDefQueries["$name"] = self::buildUserDefQuery($def['anonymous'], $def['total_contribs'], $def['contrib_1'], $def['contrib_2'], $def['contrib_3']);
195 - }
196 -
197 -
 152+
198153 $basicUserData = array();
199154 $intermediateUserData = array();
200155 $expertUserData = array();
@@ -203,10 +158,13 @@
204159
205160 while( $currEndDate->format( "U" ) < $endDate->format( "U" ) ){
206161 $currEndDate->modify( "+$increment day$plural" );
207 - $time_constraints_statement = self::getTimeConstraintsStatement( $currBeginDate->format("Ymd"), $currEndDate->format("Ymd") );
208 - $basicUserData[] = self::getTableValue( $event_id, $userDefQueries['basic'], $time_constraints_statement );
209 - $intermediateUserData[] = self::getTableValue( $event_id, $userDefQueries['intermediate'], $time_constraints_statement );
210 - $expertUserData[] = self::getTableValue( $event_id, $userDefQueries['expert'], $time_constraints_statement );
 162+
 163+ $minDate = $currBeginDate->format("Ymd");
 164+ $maxDate = $currEndDate->format("Ymd");
 165+
 166+ $basicUserData[] = self::getTableValue( $event_id, $userDefs['basic'], $minDate, $maxDate );
 167+ $intermediateUserData[] = self::getTableValue( $event_id, $userDefs['intermediate'], $minDate, $maxDate );
 168+ $expertUserData[] = self::getTableValue( $event_id, $userDefs['expert'], $minDate, $maxDate );
211169 $currBeginDate->modify( "+$increment day$plural" );
212170 }
213171 return array("expert" => $expertUserData, "basic" => $basicUserData, "intermediate" => $intermediateUserData);
@@ -236,7 +194,7 @@
237195 }
238196
239197
240 - function buildUserDefDialog(){
 198+ function buildUserDefBlankDialog(){
241199 $control = "";
242200 $control .= Xml::openElement("div", array("id" => "user_def_dialog", "class" => "dialog"));
243201
@@ -244,14 +202,14 @@
245203 $control .= Xml::openElement("form", array("id" => "user_definition_form", "class" => "user_def_form"));
246204 $control .= Xml::openElement("fieldset", array("id" => "user_def_alter_fieldset"));
247205 $control .= Xml::openElement("legend", array("id" => "user_def_alter_legend"));
248 - $control .= wfMsg( "ct-editing" );
 206+ $control .= wfMsg( "editing" );
249207 $control .= Xml::closeElement("legend");
250208
251209 //[] anonymous users?
252210 $control .= Xml::openElement("div", array("id" => "anon_users_div", "class" => "checkbox_div control_div"));
253211 $control .= Xml::openElement("input", array("type" => "checkbox", "id" => "anon_users_checkbox", "class" => "user_def_checkbox"));
254212 $control .= Xml::closeElement("input");
255 - $control .= wfMsg("ct-anon-users");
 213+ $control .= wfMsg("anon-users");
256214 $control .= Xml::closeElement("div");
257215
258216 // ----------------
@@ -263,35 +221,44 @@
264222 $control .= Xml::openElement("div", array("id" => "total_users_contrib_div", "class" => "checkbox_div control_div"));
265223 $control .= Xml::openElement("input", array("type" => "checkbox", "id" => "contrib_checkbox", "class" => "user_def_checkbox"));
266224 $control .= Xml::closeElement("input");
267 - $control .= wfMsg("ct-user-contribs");
 225+ $control .= wfMsg("user-contribs");
268226
269 - $control .= Xml::openElement("div", array("id" => "contrib_sub_div", "class" => "checkbox_div sub_option_div"));
270 - $control .= $this->buildUserDefNumberSelect(false, false, "contrib_sub");
271 - $control .= Xml::closeElement("div");
272227
273228 $control .= Xml::closeElement("div");
274229
275230 // [] contributions in timespan 1
276 - // [] [>=V] [n ]
277 - // [] AND [>=V] [n ]
278231 $control .= Xml::openElement("div", array("id" => "contrib_span_1_div", "class" => "checkbox_div control_div"));
279232
280233 $control .= Xml::openElement("div", array("id" => "contrib_span_1_text_div", "class" => "checkbox_div"));
281234 $control .= Xml::openElement("input", array("type" => "checkbox", "id" => "contrib_span_1_checkbox", "class" => "user_def_checkbox"));
282235 $control .= Xml::closeElement("input");
283 - $control .= wfMsg("ct-user-span") . " 1";
 236+ $control .= wfMsg("user-span") . " 1";
284237 $control .= Xml::closeElement("div");
285 -
286 - $control .= Xml::openElement("div", array("id" => "contrib_span_1_range_1_div", "class" => "checkbox_div sub_option_div"));
287 - $control .= $this->buildUserDefNumberSelect(true, false, "contrib_span_1_1");
288238 $control .= Xml::closeElement("div");
289239
290 - $control .= Xml::openElement("div", array("id" => "contrib_span_1_range_2_div", "class" => "checkbox_div sub_option_div"));
291 - $control .= $this->buildUserDefNumberSelect(true, true, "contrib_span_1_2");
 240+ // [] contributions in timespan 2
 241+ $control .= Xml::openElement("div", array("id" => "contrib_span_2_div", "class" => "checkbox_div control_div"));
 242+
 243+ $control .= Xml::openElement("div", array("id" => "contrib_span_2_text_div", "class" => "checkbox_div"));
 244+ $control .= Xml::openElement("input", array("type" => "checkbox", "id" => "contrib_span_2_checkbox", "class" => "user_def_checkbox"));
 245+ $control .= Xml::closeElement("input");
 246+ $control .= wfMsg("user-span") . " 2";
292247 $control .= Xml::closeElement("div");
 248+ $control .= Xml::closeElement("div");
293249
 250+ // [] contributions in timespan 3
 251+ $control .= Xml::openElement("div", array("id" => "contrib_span_3_div", "class" => "checkbox_div control_div"));
 252+
 253+ $control .= Xml::openElement("div", array("id" => "contrib_span_3_text_div", "class" => "checkbox_div"));
 254+ $control .= Xml::openElement("input", array("type" => "checkbox", "id" => "contrib_span_3_checkbox", "class" => "user_def_checkbox"));
 255+ $control .= Xml::closeElement("input");
 256+ $control .= wfMsg("user-span") . " 3";
294257 $control .= Xml::closeElement("div");
 258+ $control .= Xml::closeElement("div");
295259
 260+
 261+
 262+
296263 $control .= Xml::closeElement("div");//close contrib opts
297264
298265 $control .= Xml::closeElement("fieldset");
@@ -301,6 +268,7 @@
302269 }
303270
304271
 272+
305273 function buildUserDefNumberSelect($include_checkbox, $include_and, $ids){
306274 $control = "";
307275 if($include_checkbox){
@@ -406,105 +374,73 @@
407375
408376 $control .= Xml::closeElement("tr");
409377
410 - $control .= Xml::closeElement("tbody");
411 - $control .= Xml::closeElement("table");
412 - $control .= Xml::closeElement("fieldset");
413 -
414 - $control .= Xml::closeElement("form");
415 -
416 - return $control;
417 - }
418 -
419 -
420 - function buildControlBox(){
421 -
422 - $control = Xml::openElement("form", array("id" => "control_box_form"));
423 - $control .= Xml::openElement("table", array("id" => "control_box_table"));
424 - $control .= Xml::openElement("tbody", array("id" => "control_box_tbody"));
425 -
426 -
427 - $control .= Xml::openElement("tr", array("id" => "start_date_row"));
428 -
429 - $control .= Xml::openElement("td", array("id" => "start_date_label", "class" => "control_box_label"));
430 - $control .= wfMsg( "ct-start-date" );
431 - $control .= Xml::closeElement("td");
432 -
433 - $control .= Xml::openElement("td", array("id" => "start_date_textarea"));
434 - $control .= Xml::openElement("input", array("type" => "text", "id" => "start_date", "class" => "control_box_input"));
435 - $control .= Xml::closeElement("input");
436 - $control .= Xml::closeElement("td");
437 -
438 - $control .= Xml::closeElement("tr");
439378
 379+ $control .= Xml::openElement("tr", array("id" => "update_row"));
440380
441 -
442 - $control .= Xml::openElement("tr", array("id" => "end_date_row"));
443 -
444 - $control .= Xml::openElement("td", array("id" => "end_date_label", "class" => "control_box_label"));
445 - $control .= wfMsg( "ct-end-date" );
 381+ $control .= Xml::openElement("td");
446382 $control .= Xml::closeElement("td");
447383
448 - $control .= Xml::openElement("td", array("id" => "end_date_textarea"));
449 - $control .= Xml::openElement("input", array("type" => "text", "id" => "end_date", "class" => "control_box_input"));
 384+ $control .= Xml::openElement("td", array("id" => "update_table_button_td"));
 385+ $control .= Xml::openElement("input", array("type" => "button", "id" => "update_table_button", "class" => "update_button", "value" =>wfMsg("ct-update-table")));
450386 $control .= Xml::closeElement("input");
451387 $control .= Xml::closeElement("td");
452388
453389 $control .= Xml::closeElement("tr");
454390
 391+ $control .= Xml::closeElement("tbody");
 392+ $control .= Xml::closeElement("table");
 393+ $control .= Xml::closeElement("fieldset");
455394
 395+ $control .= Xml::closeElement("form");
456396
457 - $control .= Xml::openElement("tr", array("id" => "increment_date_row"));
 397+ return $control;
 398+ }
 399+
 400+
 401+ /**
 402+ *
 403+ * @param $minTime
 404+ * @param $maxTime
 405+ * @param $userDefs
 406+ * @param $is_JSON
 407+ * @return unknown_type
 408+ */
 409+ public static function buildRowArray($minTime, $maxTime, $userDefs, $is_JSON= true){
458410
459 - $control .= Xml::openElement("td", array("id" => "increment_date_label", "class" => "control_box_label"));
460 - $control .= wfMsg( "ct-increment-by" );
461 - $control .= Xml::closeElement("td");
462411
463 - $control .= Xml::openElement("td", array("id" => "increment_date_textarea"));
464 - $control .= Xml::openElement("input", array("type" => "text", "id" => "increment_date", "class" => "control_box_input"));
465 - $control .= Xml::closeElement("input");
466 - $control .= Xml::closeElement("td");
 412+ if($minTime == 0){
 413+ $minTime = self::$minimum_date;
 414+ }
 415+ if($maxTime == 0){
 416+ $maxTime = gmdate("Ymd",time()); //today
 417+ }
467418
468 - $control .= Xml::closeElement("tr");
 419+ if($is_JSON){
 420+ $userDefs = json_decode($userDefs, true);
 421+ }
469422
470423
 424+ $events = self::getTopEvents($minTime, $maxTime);
471425
472 - $control .= Xml::openElement("tr", array("id" => "change_graph_row"));
473 - $control .= Xml::openElement("td", array("id" => "change_graph_cell", "colspan" => 2));
 426+ $returnArray = array();
474427
475 - $control .= Xml::openElement("input", array("type" => "button", "id" => "change_graph", "value" => wfMsg( "ct-change-graph" ) ) );
476 - $control .= Xml::closeElement("input");
477 - $control .= Xml::closeElement("td");
 428+ while(($data_result = $events->fetchRow()) != null){
 429+ $outputArray = array();
 430+ $outputArray['event_name'] = $data_result['event_name'];
 431+ $outputArray['event_id'] = $data_result['event_id'];
 432+ $outputArray['expert'] = self::getTableValue($data_result['event_id'], $userDefs["expert"]);
 433+ $outputArray['intermediate'] = self::getTableValue($data_result['event_id'], $userDefs["intermediate"]);
 434+ $outputArray['basic'] = self::getTableValue($data_result['event_id'], $userDefs["basic"]);
 435+ $outputArray['total'] = $data_result["totalevtid"];
 436+ $returnArray[] = $outputArray;
 437+ }
478438
479 - $control .= Xml::closeElement("tr");
 439+ return $returnArray;
480440
481 - $control .= Xml::closeElement("tbody");
482 - $control .= Xml::closeElement("table");
483 - $control .= Xml::closeElement("form");
484 -
485 - return $control;
486441 }
487442
488 -
489 -
490443 function buildRow($data_result, $row_count, $userDefs){
491444
492 - $userDefQueries = array();
493 - foreach ($userDefs as $name => $def){
494 - if(!isset($def['total_contribs'])){
495 - $def['total_contribs'] = array();
496 - }
497 - if(!isset($def['contrib_1'])){
498 - $def['contrib_1'] = array();
499 - }
500 - if(!isset($def['contrib_2'])){
501 - $def['contrib_2'] = array();
502 - }
503 - if(!isset($def['contrib_3'])){
504 - $def['contrib_3'] = array();
505 - }
506 - $userDefQueries["$name"] = self::buildUserDefQuery($def['anonymous'], $def['total_contribs'], $def['contrib_1'], $def['contrib_2'], $def['contrib_3']);
507 - }
508 -
509445 $outputRow = Xml::openElement("tr", array("class" => "table_data_row"));
510446
511447 //event name
@@ -514,7 +450,7 @@
515451 $outputRow .=Xml::closeElement("td");
516452
517453 //advanced users
518 - $cellValue = self::getTableValue($data_result['event_id'], $userDefQueries["expert"]);
 454+ $cellValue = self::getTableValue($data_result['event_id'], $userDefs["expert"]);
519455 $outputRow .=Xml::openElement("td",
520456 array("class" => "event_data expert_data", "id" => "event_expert_$row_count",
521457 "value" => $cellValue));
@@ -522,7 +458,7 @@
523459 $outputRow .=Xml::closeElement("td");
524460
525461 //intermediate users
526 - $cellValue = self::getTableValue($data_result['event_id'], $userDefQueries["intermediate"]);
 462+ $cellValue = self::getTableValue($data_result['event_id'], $userDefs["intermediate"]);
527463 $outputRow .=Xml::openElement("td",
528464 array("class" => "event_data intermediate_data", "id" => "event_intermediate_$row_count",
529465 "value" => $cellValue));
@@ -530,7 +466,7 @@
531467 $outputRow .=Xml::closeElement("td");
532468
533469 //basic users
534 - $cellValue = self::getTableValue($data_result['event_id'], $userDefQueries["basic"]);
 470+ $cellValue = self::getTableValue($data_result['event_id'], $userDefs["basic"]);
535471 $outputRow .=Xml::openElement("td",
536472 array("class" => "event_data basic_data", "id" => "event_basic_$row_count",
537473 "value" => $cellValue));
@@ -538,7 +474,7 @@
539475 $outputRow .=Xml::closeElement("td");
540476
541477 //totals
542 - $cellValue = $data_result["count(event_id)"];
 478+ $cellValue = $data_result["totalevtid"];
543479 $outputRow .=Xml::openElement("td",
544480 array("class" => "event_data total_data", "id" => "total_$row_count",
545481 "value" => $cellValue));
@@ -558,12 +494,15 @@
559495 * @param maxTime max day (YYYYMMDD)
560496 * NOTE: once some of the constraints have been finalized, this will use more of the Database functions and not raw SQL
561497 */
562 - static function getTimeConstraintsStatement( $minTime, $maxTime ){
 498+ static function getTimeConstraintsStatement( $minTime, $maxTime ){
563499 if($minTime == 0 || $maxTime == 0){
564500 return '';
565501 }
566502 else {
567 - return "WHERE action_time >= $minTime AND action_time <= $maxTime";
 503+ //the dates are stored in the DB as MW_TIMESTAMP formats, add the zeroes to fix that
 504+ $minTime .= "000000";
 505+ $maxTime .= "000000";
 506+ return "WHERE `action_time` >= '$minTime' AND `action_time` <= '$maxTime'";
568507 }
569508
570509 }
@@ -575,16 +514,22 @@
576515 * @return unknown_type
577516 * NOTE: once some of the constraints have been finalized, this will use more of the Database functions and not raw SQL
578517 */
579 - function getTopEvents($time_constraint_statement=''){
 518+ public static function getTopEvents($minTime = "", $maxTime = "", $normalize_top_results = false){
 519+
580520 $normalize = "click_tracking";
 521+ //escaped
 522+
 523+ $time_constraint_statement = self::getTimeConstraintsStatement($minTime,$maxTime);
581524 $time_constraint = $time_constraint_statement;
582 - if($this->normalize_top_results){
 525+
 526+ if($normalize_top_results){
583527 $normalize = "(select distinct session_id, event_id from click_tracking $time_constraint_statement) as t1";
584528 $time_constraint = "";
585529 }
586 - $limit = $this->top_results;
587 - $join = self::$join_conds;
588 - $sql = "select count(event_id), event_id,event_name from $normalize $join $time_constraint group by event_id order by count(event_id) desc limit $limit";
 530+ $join = " ";
 531+ $sql = "select count(event_id) as totalevtid, event_id,event_name from $normalize" .
 532+ " LEFT JOIN click_tracking_events ON event_id=click_tracking_events.id".
 533+ " $time_constraint group by event_id order by totalevtid desc";
589534
590535 //returns count(event_id),event_id, event_name, top one first
591536 $dbr = wfGetDB( DB_SLAVE );
@@ -597,26 +542,29 @@
598543 * Gets a table value for a given User ID
599544 * NOTE: once some of the constraints have been finalized, this will use more of the Database functions and not raw SQL
600545 */
601 - static function getTableValue($event_id, $user_conditions, $time_constraint_statement = '', $normalize_results=false){
 546+ static function getTableValue($event_id, $userDef, $minTime = '', $maxTime = '', $normalize_results = false){
602547
603548 $normalize = "click_tracking";
 549+ //escaped
 550+ $time_constraint_statement = self::getTimeConstraintsStatement($minTime,$maxTime);
604551 $time_constraint = $time_constraint_statement;
605552 if($normalize_results){
606553 $normalize = "(select distinct session_id, event_id, user_total_contribs, user_contribs_span1, user_contribs_span2, user_contribs_span3, is_logged_in from click_tracking $time_constraint_statement) as t1";
607554 $time_constraint = "";
608555 }
609556
 557+ $user_conditions = SpecialClickTracking::buildUserDefQuery($userDef);
610558
611559 $where = ($time_constraint == "" ? "where" : "");
612560
613561 $and = ($time_constraint == "" ? "": "and");
614562
615 - $sql ="select count(*) from $normalize $where $time_constraint $and ($user_conditions) and event_id=$event_id";
 563+ $sql ="select count(*) as totalcount from $normalize $where $time_constraint $and ($user_conditions) and event_id=$event_id";
616564
617565 $dbr = wfGetDB( DB_SLAVE );
618566 $result = $dbr->query($sql);
619567 $resRow = $result->fetchRow();
620 - return $resRow["count(*)"];
 568+ return $resRow["totalcount"];
621569 }
622570
623571 /**
@@ -628,35 +576,42 @@
629577 * @param $contrib_3 array, nonempty AND conditions for user_contribs_1
630578 * @return unknown_type query
631579 */
632 - static function buildUserDefQuery($include_anon_users, $total_contribs, $contrib_1, $contrib_2, $contrib_3){
 580+ public static function buildUserDefQuery($def){
 581+
 582+ $include_anon_users = (empty($def['anonymous'])?array():$def['anonymous']);
 583+ $total_contribs = (empty($def['total_contribs'])?array():$def['total_contribs']);
 584+ $contrib_1 = (empty($def['contrib_1'])?array():$def['contrib_1']);
 585+ $contrib_2 = (empty($def['contrib_2'])?array():$def['contrib_2']);
 586+ $contrib_3 = (empty($def['contrib_3'])?array():$def['contrib_3']);
 587+
633588 $or_conds = array();
634589 $and_conds = array();
635590 $sql = "";
636591
 592+
637593 if( (boolean)$include_anon_users ){
638594 $or_conds[] = array("field" => "is_logged_in", "operation" => "=", "value" =>"0");
639595 }
640596
641597 if(!empty($total_contribs)){
642598 foreach($total_contribs as $contribs){
643 - $and_conds[] = array("field" => "user_total_contribs", "operation" => $contribs["operation"], "value" => $contribs["value"]);
 599+ $and_conds[] = array("field" => "user_total_contribs", "operation" => SpecialClickTracking::validate_oper($contribs["operation"]), "value" => intval($contribs["value"]));
644600 }
645601 }
646602
647 -
648603 if(!empty($contrib_1)){
649604 foreach($contrib_1 as $contribs){
650 - $and_conds[] = array("field" => "user_contribs_span1", "operation" => $contribs["operation"], "value" => $contribs["value"]);
 605+ $and_conds[] = array("field" => "user_contribs_span1", "operation" => SpecialClickTracking::validate_oper($contribs["operation"]), "value" => intval($contribs["value"]));
651606 }
652607 }
653608 if(!empty($contrib_2)){
654609 foreach($contrib_2 as $contribs){
655 - $and_conds[] = array("field" => "user_contribs_span2", "operation" => $contribs["operation"], "value" => $contribs["value"]);
 610+ $and_conds[] = array("field" => "user_contribs_span2", "operation" => SpecialClickTracking::validate_oper($contribs["operation"]), "value" => intval($contribs["value"]));
656611 }
657612 }
658613 if(!empty($contrib_3)){
659614 foreach($contrib_3 as $contribs){
660 - $and_conds[] = array("field" => "user_contribs_span3", "operation" => $contribs["operation"], "value" => $contribs["value"]);
 615+ $and_conds[] = array("field" => "user_contribs_span3", "operation" => SpecialClickTracking::validate_oper($contribs["operation"]), "value" => intval($contribs["value"]));
661616 }
662617 }
663618
@@ -676,6 +631,19 @@
677632 return $sql;
678633 }
679634
 635+ public static function validate_oper($operation){
 636+ $o_trim = trim($operation);
 637+ switch($o_trim){ //valid operations
 638+ case ">":
 639+ case "<":
 640+ case "<=":
 641+ case ">=":
 642+ case "=":
 643+ return $o_trim;
 644+ default:
 645+ return "=";
 646+ }
 647+ }
680648
681649
682650 }
\ No newline at end of file
Index: branches/wmf-deployment/extensions/UsabilityInitiative/ClickTracking/ClickTracking.hooks.php
@@ -30,48 +30,48 @@
3131 return true;
3232 }
3333
34 -
35 -
36 - /*
37 - * check to see if user is throttled
 34+ /**
 35+ * Make sure the table exists for parser tests
 36+ * @param $tables
 37+ * @return unknown_type
3838 */
39 - public static function isUserThrottled(){
 39+ public static function parserTestTables( &$tables ) {
 40+ $tables[] = 'click_tracking';
 41+ $tables[] = 'click_tracking_events';
 42+ return true;
 43+ }
 44+
 45+ /**
 46+ * Check to see if user is throttled
 47+ */
 48+ public static function isUserThrottled() {
4049 global $wgClickTrackThrottle;
41 - if( ( $wgClickTrackThrottle >= 0 ) && ( rand() % $wgClickTrackThrottle == 0 ) ){
42 - return 'false';
43 - }
44 - else {
45 - return 'true';
46 - }
 50+ return !( $wgClickTrackThrottle >= 0 && rand() % $wgClickTrackThrottle == 0 );
4751 }
48 -
49 -
 52+
5053 /**
5154 * Adds JavaScript
5255 */
53 - public static function addJS(){
54 - global $wgOut;
 56+ public static function addJS() {
 57+ global $wgClickTrackingStyleVersion;
5558
5659 UsabilityInitiativeHooks::initialize();
57 - UsabilityInitiativeHooks::addScript( 'ClickTracking/ClickTracking.js' );
 60+ UsabilityInitiativeHooks::addScript( 'ClickTracking/ClickTracking.js', $wgClickTrackingStyleVersion );
5861 UsabilityInitiativeHooks::addVariables(
59 - array(
60 - 'wgTrackingToken' => ClickTrackingHooks::get_session_id()
 62+ array(
 63+ 'wgTrackingToken' => ClickTrackingHooks::get_session_id(),
 64+ 'wgClickTrackingIsThrottled' => ClickTrackingHooks::isUserThrottled()
6165 )
6266 );
63 - //need a literal false, not "false" to be output, to work prperly
64 - $userThrottle = ClickTrackingHooks::isUserThrottled();
65 - $wgOut->addScript("<script> var wgClickTrackingIsThrottled = $userThrottle; </script>");
66 -
 67+
6768 return true;
68 -
6969 }
7070
7171 /**
7272 * Gets the session ID...we just want a unique random ID for the page load
7373 * @return session ID
7474 */
75 - public static function get_session_id(){
 75+ public static function get_session_id() {
7676 global $wgUser;
7777 return wfGenerateToken( array( $wgUser->getName(), time() ) );
7878 }
@@ -81,7 +81,7 @@
8282 * @param $ts beginning timestamp
8383 * @return number of revsions this user has made
8484 */
85 - public static function getEditCountSince( $ts ){
 85+ public static function getEditCountSince( $ts ) {
8686 global $wgUser;
8787
8888 // convert to just the day
@@ -100,35 +100,35 @@
101101 );
102102
103103 // user hasn't made any edits in whatever amount of time
104 - if( $edits == null ){
 104+ if ( $edits == null ) {
105105 $edits = 0;
106106 }
107107
108108 return $edits;
109109 }
110110
111 -
112111 /**
113112 * Get event ID from name
114113 * @param $event_name String: name of the event to get
115114 * @return integer
116115 */
117 - public static function getEventIDFromName( $event_name ){
118 - $dbw = wfGetDB( DB_MASTER ); //replication lag means sometimes a new event will not exist in the table yet
 116+ public static function getEventIDFromName( $event_name ) {
 117+ $dbw = wfGetDB( DB_MASTER ); // replication lag means sometimes a new event will not exist in the table yet
119118
120119 $id_num = $dbw->selectField(
121120 'click_tracking_events',
122121 'id',
123 - array(
 122+ array(
124123 'event_name' => $event_name
125 - ),
 124+ ),
126125 __METHOD__
127126 );
128127
129128 // if this entry doesn't exist...
130129 // this will be incredibly rare as the whole database will only have a few hundred entries in it at most
131130 // and getting DB_MASTER up top would be wasteful
132 - if( $id_num === false ){
 131+ // FIXME: Use replace() instead of this selectField --> insert or update logic
 132+ if( $id_num === false ) {
133133 $dbw->insert(
134134 'click_tracking_events',
135135 array( 'event_name' => (string) $event_name ),
@@ -156,8 +156,8 @@
157157 * @param $contribs_in_timespan3 Integer: number of contributions user has made in timespan of granularity 3 (defined by ClickTracking/$wgClickTrackContribGranularity3)
158158 * @return true if the event was stored in the DB
159159 */
160 - public static function trackEvent( $session_id, $is_logged_in, $namespace, $event_id, $contribs = 0,
161 - $contribs_in_timespan1 = 0, $contribs_in_timespan2 = 0, $contribs_in_timespan3 = 0 ){
 160+ public static function trackEvent( $session_id, $is_logged_in, $namespace, $event_id, $contribs = 0,
 161+ $contribs_in_timespan1 = 0, $contribs_in_timespan2 = 0, $contribs_in_timespan3 = 0 ) {
162162 $dbw = wfGetDB( DB_MASTER );
163163
164164 $dbw->begin();
Index: branches/wmf-deployment/extensions/UsabilityInitiative/ClickTracking/SpecialClickTracking.css
@@ -37,6 +37,7 @@
3838
3939 .control_div {
4040 margin: 10px;
 41+ clear: both;
4142 }
4243
4344 .sub_option_div{
@@ -53,4 +54,10 @@
5455 display:inline;
5556 float:left;
5657 width:200px;
 58+}
 59+
 60+.add_condition_button{
 61+ float: right;
 62+ color: blue;
 63+ cursor: pointer;
5764 }
\ No newline at end of file
Index: branches/wmf-deployment/extensions/UsabilityInitiative/ClickTracking/ClickTracking.js
@@ -1,12 +1,21 @@
22 (function($) {
3 -
4 - if(!wgClickTrackingIsThrottled){
 3+ if( !wgClickTrackingIsThrottled ) {
54 // creates 'track action' function to call the clicktracking API and send the ID
6 - $.trackAction = function ( id ){
 5+ $.trackAction = function ( id ) {
76 $j.post( wgScriptPath + '/api.php', { 'action': 'clicktracking', 'eventid': id, 'token': wgTrackingToken } );
87 };
 8+
 9+ // Clicktrack the left sidebar links
 10+ $(document).ready( function() {
 11+ $( '#p-logo a, #p-navigation a, #p-tb a' ).click( function() {
 12+ var id = 'leftnav-' + skin + '-' +
 13+ ( $(this).attr( 'id' ) || $(this).parent().attr( 'id' ) );
 14+ window.location = wgScriptPath +
 15+ '/api.php?action=clicktracking&eventid=' + id + '&token=' +
 16+ wgTrackingToken +
 17+ '&redirectto=' + escape( $(this).attr( 'href' ) );
 18+ });
 19+ });
920 }
1021
11 -return $(this);
12 -
1322 })(jQuery);
\ No newline at end of file
Index: branches/wmf-deployment/extensions/UsabilityInitiative/ClickTracking/SpecialClickTracking.js
@@ -1,383 +1,509 @@
22 (function($) {
3 -
4 - $.renderUserDefDialogWith = function (userDef, defName){
5 - //change name
6 - $("#user_def_alter_legend").text($("#user_def_alter_legend").data("defaultChangeText") + " " + defName);
7 - $("#user_def_alter_legend").data("currentlyEditing", defName);
8 -
9 - var setContribs = function(conditionArray, contribName){
10 -
11 - initialDiv = $("<div>").attr("id", contribName +"_div");
12 - initialDiv.addClass("checkbox_div");
13 - initialDiv.addClass("control_div");
14 -
15 - textDiv = $("<div>").attr("id", contribName +"_text_div");
16 - mainCheckbox = $("<input>").attr("id", contribName +"_checkbox");
17 - mainCheckbox.attr("type", "checkbox");
18 - mainCheckbox.addClass("user_def_checkbox");
19 -
20 - if(conditionArray.length > 0){
21 - mainCheckbox.attr("checked", true);
 3+ /* Very limited JSON encoder */
 4+ $.json_encode = function( js_obj ) {
 5+ var returnstr = "{ ";
 6+
 7+ // trailing commas and json don't mix
 8+ var propertynum = 0;
 9+ for( property in js_obj ) {
 10+ if( propertynum > 0 ) {
 11+ returnstr +=", ";
2212 }
23 -
24 - textDiv.append(mainCheckbox);
25 - textDiv.text(""); //i18n txt here
26 - initialDiv.append(textDiv);
27 -
28 - var i=0;
29 - for( var condition in conditionArray){
30 - i++;
31 - conditionDiv = $("<div>").attr("id", contribName + "_range_" + i + "_div");
32 - conditionDiv.addClass("checkbox_div");
33 - conditionDiv.addClass("sub_option_div");
 13+ returnstr += "\"" + property + "\"" + " : ";
 14+ if( typeof js_obj[property] == 'object' ) {
 15+ returnstr += $.json_encode( js_obj[property] );
 16+ } else {
 17+ returnstr += "\"" + js_obj[property] + "\" ";
 18+ }
 19+ propertynum++;
 20+ }
3421
35 - //initialDiv.append(conditionDiv);
36 - cCheckbox = $("<input>").attr("id", contribName+"_"+i+"_checkbox");
37 - cCheckbox.attr("type", "checkbox");
38 - cCheckbox.attr("checked", true);
39 - cCheckbox.addClass("number_select_checkbox");
40 - conditionDiv.append(cCheckbox);
41 -
42 - cSelect = $("<select>").attr("id", contribName+"_"+i+"_ltgt");
43 - cSelect.addClass("number_select_ltgt");
44 -
45 - cOpt1 = $("<option>").attr("id", contribName+"_"+i+"_lt");
46 - cOpt1.addClass("number_select_ltgt_opt");
47 - cOpt1.attr("value", "lt");
48 - cOpt1.text("&lt;");
49 - if(condition["operation"] == "<"){
50 - cOpt1.attr("selected", true);
51 - }
52 -
53 -
54 - cOpt2 = $("<option>").attr("id", contribName+"_"+i+"_gt");
55 - cOpt2.addClass("number_select_ltgt_opt");
56 - cOpt2.attr("value", "gt");
57 - cOpt2.text("&gt;");
58 - if(condition["operation"] == ">"){
59 - cOpt2.attr("selected", true);
60 - }
61 -
62 - cOpt3 = $("<option>").attr("id", contribName+"_"+i+"_lteq");
63 - cOpt3.addClass("number_select_ltgt_opt");
64 - cOpt3.attr("value", "lteq");
65 - cOpt3.text("&lt;=");
66 - if(condition["operation"] == "<="){
67 - cOpt3.attr("selected", true);
68 - }
69 -
70 - cOpt4 = $("<option>").attr("id", contribName+"_"+i+"_gteq");
71 - cOpt4.addClass("number_select_ltgt_opt");
72 - cOpt4.attr("value", "gteq");
73 - cOpt4.text("&gt;=");
74 - if(condition["operation"] == ">="){
75 - cOpt4.attr("selected", true);
76 - }
77 -
78 - cSelect.append(cOpt1);
79 - cSelect.append(cOpt2);
80 - cSelect.append(cOpt3);
81 - cSelect.append(cOpt4);
82 - conditionDiv.append(cSelect);
83 -
84 - cTextInput = $("<input>").attr("id", contribName+"_"+i+"_text");
85 - cTextInput.addClass("number_select_text");
86 - cTextInput.text(condition["value"]);
87 - conditionDiv.append(cTextInput);
88 - initialDiv.append(conditionDiv);
89 - } //forloop
90 - initialDiv.data("totalConditions", i);
91 - return initialDiv;
92 - }; //setcontribs
93 -
94 -
95 - //check anonymous
96 - var anon = false;
97 - if(parseInt(userDef["anonymous"]) == 1){
98 - anon = true;
99 - }
100 - $("#anon_users_checkbox").attr('checked', anon);
101 -
102 - //clear out old contents
103 - $("#contrib_opts_container").clear();
104 -
105 - var setup_set_contribs = function(contribName){
106 - var current_contribs = userDef[contribName];
107 - if(current_contribs == undefined){
108 - current_contribs = new Array();
109 - }
110 - $("#contrib_opts_container").append(setContribs(current_contribs, contribName));
111 - };
112 -
113 -
114 - //total contribs
115 - setup_set_contribs("total_contribs");
116 - setup_set_contribs("contribs_span_1");
117 - setup_set_contribs("contribs_span_2");
118 - setup_set_contribs("contribs_span_3");
119 -
120 - }; //renderUserDefDialogWith
121 -
122 -
123 -
124 - $.getUserDefsFromDialog = function(){
 22+ returnstr += " }";
 23+ return returnstr;
 24+ };
 25+
 26+ $.getUserDefsFromDialog = function() {
12527 var currUserDefs = new Array();
126 - if($("#anon_users_checkbox").is(":checked")){
127 - currUserDefs["anonymous"] = 1;
 28+ if( $("#anon_users_checkbox").is( ":checked" ) ) {
 29+ currUserDefs['anonymous'] = 1;
 30+ } else {
 31+ currUserDefs['anonymous'] = 0;
12832 }
129 - else{
130 - currUserDefs["anonymous"] = 0;
131 - }
132 -
133 - var getCheckBoxData = function(contribName){
134 - if($("#"+ contribName +"_checkbox").is(":checked")){
 33+
 34+ var getCheckBoxData = function( contribName ) {
 35+ if( $("#"+ contribName + "_checkbox").is( ":checked" ) ) {
13536 currUserDefs[contribName] = new Array();
 37+ } else {
 38+ return;
13639 }
137 - else{ return;}
138 - var totalConds = $("#" + contribName +"_div").data("totalConditions");
 40+ var totalConds = $("#" + contribName + "_div").data("totalConditions");
13941 var i;
140 - for(i = 0; i <= totalConds; i++){
141 - if($(contribName+"_"+i+"_checkbox").is(":checked")){
142 - $(contribName+"_"+i+"_ltgt").children().each(function(){
143 - if($(this).is(":selected")){
 42+
 43+ for( i = 1; i <= totalConds; i++ ) {
 44+ if( $("#" + contribName + "_" + i + "_checkbox").is( ":checked" ) ) {
 45+ $("#" + contribName + "_" + i + "_ltgt").children().each(function() {
 46+ if( $(this).is( ":selected" ) ) {
14447 var currentCond = new Array();
145 - switch($(this).attr("value")){
146 - case 'lt': currentCond["operation"] = "<"; break;
147 - case 'lteq': currentCond["operation"] = "<="; break;
148 - case 'gt': currentCond["operation"] = ">"; break;
149 - case 'gteq' : currentCond["operation"] = ">="; break;
150 - default: currentCond["operation"] = "<"; break;
 48+ switch( $(this).attr("value") ) {
 49+ case 'lt':
 50+ currentCond['operation'] = '<';
 51+ break;
 52+ case 'lteq':
 53+ currentCond['operation'] = '<=';
 54+ break;
 55+ case 'gt':
 56+ currentCond['operation'] = '>';
 57+ break;
 58+ case 'gteq':
 59+ currentCond['operation'] = '>=';
 60+ break;
 61+ default:
 62+ currentCond['operation'] = '<';
 63+ break;
15164 }
152 - currentCond["value"] = $("#"+contribName+"_"+i+"_text").val();
 65+ currentCond['value'] = $("#" + contribName + "_" + i + "_text").val();
15366 currUserDefs[contribName].push(currentCond);
15467 }
15568 });
156 - } //ifchecked
157 - }//forloop
 69+ } // ifchecked
 70+ } // forloop
15871 };
159 -
160 -
 72+
16173 getCheckBoxData("total_contribs");
16274 getCheckBoxData("contribs_span_1");
16375 getCheckBoxData("contribs_span_2");
16476 getCheckBoxData("contribs_span_3");
16577 wgClickTrackUserDefs[$("#user_def_alter_legend").data("currentlyEditing")] = currUserDefs;
16678 };
167 -
168 - //functions
169 - $.updateChart = function(){
170 -
171 - event_name = $("#chart_img").data("event_name");
172 -
173 - var processChartJSON = function(data, status){
174 -
175 - var getMax = function(findMax){
 79+
 80+ $.renderUserDefDialogWith = function( userDef, defName ) {
 81+ // change name
 82+ $("#user_def_alter_legend").text($("#user_def_alter_legend").data("defaultChangeText") + " " + defName);
 83+ $("#user_def_alter_legend").data("currentlyEditing", defName);
 84+
 85+ var setContribs = function( conditionArray, contribName ) {
 86+ initialDiv = $("<div></div>").attr('id', contribName + '_div');
 87+ initialDiv.addClass('checkbox_div');
 88+ initialDiv.addClass('control_div');
 89+
 90+ textDiv = $("<div></div>").attr('id', contribName + '_text_div');
 91+ mainCheckbox = $("<input>").attr('id', contribName + '_checkbox');
 92+ mainCheckbox.attr('type', 'checkbox');
 93+ mainCheckbox.addClass('user_def_checkbox');
 94+
 95+ if( conditionArray.length > 0 ) {
 96+ mainCheckbox.attr( 'checked', true );
 97+ }
 98+
 99+ textDiv.append( mainCheckbox );
 100+ textDiv.text( contribName ); // i18n txt here
 101+ textDiv.css( 'display', 'inline' );
 102+ initialDiv.append( mainCheckbox );
 103+ initialDiv.append( textDiv );
 104+
 105+ var buildConditionDiv = function( condition, counter, isChecked ) {
 106+ conditionDiv = $("<div></div>").attr('id', contribName + '_range_' + counter + '_div');
 107+ conditionDiv.addClass( 'checkbox_div' );
 108+ conditionDiv.addClass( 'sub_option_div' );
 109+
 110+ //initialDiv.append(conditionDiv);
 111+ cCheckbox = $("<input></input>").attr('id', contribName + '_' + counter + '_checkbox');
 112+ cCheckbox.attr('type', 'checkbox');
 113+ if( isChecked ) {
 114+ cCheckbox.attr( 'checked', true );
 115+ }
 116+ cCheckbox.addClass( 'number_select_checkbox' );
 117+ conditionDiv.append( cCheckbox );
 118+
 119+ cSelect = $("<select></select>").attr('id', contribName + '_' + counter + '_ltgt');
 120+ cSelect.addClass( 'number_select_ltgt' );
 121+
 122+ cOpt1 = $("<option></option>").attr('id', contribName + '_' + counter + '_lt');
 123+ cOpt1.addClass( 'number_select_ltgt_opt' );
 124+ cOpt1.attr( 'value', 'lt' );
 125+ cOpt1.text( '<' );
 126+ if( condition['operation'] == '<' ) {
 127+ cOpt1.attr( 'selected', true );
 128+ }
 129+
 130+ cOpt2 = $("<option></option>").attr('id', contribName + '_' + counter + '_gt');
 131+ cOpt2.addClass( 'number_select_ltgt_opt' );
 132+ cOpt2.attr( 'value', 'gt' );
 133+ cOpt2.text( '>' );
 134+ if( condition['operation'] == '>' ) {
 135+ cOpt2.attr( 'selected', true );
 136+ }
 137+
 138+ cOpt3 = $("<option></option>").attr('id', contribName + '_' + counter + '_lteq');
 139+ cOpt3.addClass( 'number_select_ltgt_opt' );
 140+ cOpt3.attr( 'value', 'lteq' );
 141+ cOpt3.text( '<=' );
 142+ if( condition['operation'] == '<=' ) {
 143+ cOpt3.attr( 'selected', true );
 144+ }
 145+
 146+ cOpt4 = $("<option></option>").attr('id', contribName + '_' + counter + '_gteq');
 147+ cOpt4.addClass( 'number_select_ltgt_opt' );
 148+ cOpt4.attr( 'value', 'gteq' );
 149+ cOpt4.text( '>=' );
 150+ if( condition['operation'] == '>=' ) {
 151+ cOpt4.attr( 'selected', true );
 152+ }
 153+
 154+ cSelect.append( cOpt1 );
 155+ cSelect.append( cOpt2 );
 156+ cSelect.append( cOpt3 );
 157+ cSelect.append( cOpt4 );
 158+ conditionDiv.append( cSelect );
 159+
 160+ cTextInput = $("<input></input>").attr('id', contribName + '_' + counter + '_text');
 161+ cTextInput.addClass( 'number_select_text' );
 162+ cTextInput.attr( 'value', condition['value'] );
 163+ conditionDiv.append( cTextInput );
 164+ return conditionDiv;
 165+ };
 166+
 167+ var i = 0;
 168+ for( var condition in conditionArray ) {
 169+ i++;
 170+ var conditionDiv = buildConditionDiv( conditionArray[condition], i, true );
 171+ initialDiv.append( conditionDiv );
 172+ } // forloop
 173+ initialDiv.data( 'totalConditions', i );
 174+ addConditions = $("<div></div>").attr('id', contribName + '_addbutton');
 175+ addConditions.data( 'contribName', contribName );
 176+ addConditions.addClass( 'add_condition_button' );
 177+ addConditions.text( '+' );
 178+ initialDiv.append( addConditions );
 179+ addConditions.click( function() {
 180+ var initDiv = $("#" + $(this).data('contribName') + '_div');
 181+ var totalConds = initDiv.data( 'totalConditions' );
 182+ totalConds++;
 183+ initDiv.data( 'totalConditions', totalConds );
 184+ var tmpCond = new Array();
 185+ tmpCond['operation'] = ' ';
 186+ tmpCond['value'] = ' ';
 187+
 188+ buildConditionDiv(tmpCond, totalConds).insertBefore($(this));
 189+ initDiv.data( 'totalConditions', totalConds, false );
 190+ });
 191+
 192+ return initialDiv;
 193+ }; // setcontribs
 194+
 195+ // check anonymous
 196+ var anon = false;
 197+ if( parseInt( userDef['anonymous'] ) == 1 ) {
 198+ anon = true;
 199+ }
 200+ $("#anon_users_checkbox").attr('checked', anon);
 201+
 202+ // clear out old contents
 203+ $("#contrib_opts_container").empty();
 204+
 205+ var setup_set_contribs = function( contribName ) {
 206+ var current_contribs = userDef[contribName];
 207+ if( current_contribs == undefined ) {
 208+ current_contribs = new Array();
 209+ }
 210+ $("#contrib_opts_container").append( setContribs( current_contribs, contribName ) );
 211+ };
 212+
 213+ // total contribs
 214+ setup_set_contribs( 'total_contribs' );
 215+ setup_set_contribs( 'contribs_span_1' );
 216+ setup_set_contribs( 'contribs_span_2' );
 217+ setup_set_contribs( 'contribs_span_3' );
 218+
 219+ // OK button
 220+ var okButton = $("<input>").attr('id', 'ok_button');
 221+ okButton.attr( 'type', 'button' );
 222+ okButton.attr( 'value', 'ok' );
 223+ okButton.click(function() {
 224+ $.getUserDefsFromDialog();
 225+ $("#user_def_dialog").dialog('close');
 226+ });
 227+ $("#contrib_opts_container").append(okButton);
 228+ }; // renderUserDefDialogWith
 229+
 230+ // functions
 231+ $.updateChart = function() {
 232+ event_name = $("#chart_img").data('event_name');
 233+
 234+ var processChartJSON = function( data, status ) {
 235+
 236+ var getMax = function( findMax ) {
176237 var retval = Number.MIN_VALUE;
177 - for(var i in findMax){
178 - if(findMax[i] > retval) {
 238+ for( var i in findMax ) {
 239+ if( findMax[i] > retval ) {
179240 retval = findMax[i];
180241 }
181242 }
182243 return retval;
183244 };
184 -
185 - max1 = getMax(data['datapoints']['expert']);
186 - max2 = getMax(data['datapoints']['intermediate']);
187 - max3 = getMax(data['datapoints']['basic']);
188 - max = Math.max(max3, Math.max(max1,max2));
 245+
 246+ max1 = getMax( data['datapoints']['expert'] );
 247+ max2 = getMax( data['datapoints']['intermediate'] );
 248+ max3 = getMax( data['datapoints']['basic'] );
 249+ max = Math.max( max3, Math.max( max1, max2 ) );
189250 chartURL = 'http://chart.apis.google.com/chart?' +
190251 'chs=400x400&' +
191252 'cht=lc&' +
192253 'chco=FF0000,0000FF,00FF00&' +
193254 'chtt=' + event_name + ' from ' + $("#start_date").val() +' to ' +$("#end_date").val() + "&" +
194 - 'chdl=' + 'Expert|Intermediate|Beginner' + "&"+
 255+ 'chdl=' + 'Expert|Intermediate|Beginner' + "&" +
195256 'chxt=x,y&' +
196 - 'chd=t:' + data['datapoints']['expert'].join(',') + "|" +
 257+ 'chd=t:' + data['datapoints']['expert'].join(',') + "|" +
197258 data['datapoints']['intermediate'].join(',') + "|" + data['datapoints']['basic'].join(',') + "&" +
198259 'chds=0,'+ max +',0,'+ max +',0,'+ max
199260 ;
200 - $("#chart_img").attr( "src",chartURL);
 261+ $("#chart_img").attr( 'src', chartURL );
201262 };
202 -
203 -
 263+
204264 start_date = $("#start_date").val();
205 - if($("#start_date").hasClass("hidden")){
 265+ if( $("#start_date").hasClass( 'hidden' ) ) {
206266 start_date = '0';
207267 }
208 -
 268+
209269 end_date = $("#end_date").val();
210 - if($("#end_date").hasClass("hidden")){
 270+ if( $("#end_date").hasClass( 'hidden' ) ) {
211271 end_date = '0';
212272 }
213 -
214 - //post relevant info
215 - $j.post( wgScriptPath + '/api.php',
216 - { 'action': 'specialclicktracking', 'format': 'json',
217 - 'eventid': $("#chart_img").data( "eventid" ), 'increment': $("#chart_increment").val(),
218 - 'startdate': start_date, 'enddate':end_date, 'userdefs': wgClickTrackUserDefs } , processChartJSON, "json");
 273+
 274+ // post relevant info
 275+ $j.post( wgScriptPath + '/api.php',
 276+ { 'action': 'specialclicktracking', 'format': 'json',
 277+ 'eventid': $("#chart_img").data( 'eventid' ), 'increment': $("#chart_increment").val(),
 278+ 'startdate': start_date, 'enddate': end_date, 'userdefs': $.json_encode( wgClickTrackUserDefs ) },
 279+ processChartJSON, 'json'
 280+ );
219281 };
220 -
221 -
222 -
223 -
224 - //pretty colors for the table
225 - $.colorizeTable = function (){
226 - //expert
227 -
228 - //get totals
 282+
 283+ // pretty colors for the table
 284+ $.colorizeTable = function() {
 285+ // expert
 286+
 287+ // get totals
229288 var expert_total = 0;
230 -
231 - $(".expert_data").each(function(){
232 - expert_total += parseInt($(this).attr( "value"));
 289+
 290+ $(".expert_data").each(function() {
 291+ expert_total += parseInt( $(this).attr( 'value' ) );
233292 });
234 -
235 - //set proper red shade
236 - $(".expert_data").each(function(){
 293+
 294+ // set proper red shade
 295+ $(".expert_data").each(function() {
237296 var rval = 255;
238 - var gval = (expert_total == 0 ? 255 : 255 - (255 * $(this).attr("value") / expert_total));
 297+ var gval = ( expert_total == 0 ? 255 : 255 - ( 255 * $(this).attr( 'value' ) / expert_total ) );
239298 var bval = gval;
240 - rgbString = "rgb(" + parseInt(rval) + "," + parseInt(gval) + "," + parseInt(bval) + ")";
241 - $(this).data("rgb", rgbString);
242 - $(this).css("color", rgbString);
243 - $(this).css("background-color", rgbString);
 299+ rgbString = "rgb(" + parseInt( rval ) + "," + parseInt( gval ) + "," + parseInt( bval ) + ")";
 300+ $(this).data('rgb', rgbString);
 301+ $(this).css('color', rgbString);
 302+ $(this).css('background-color', rgbString);
244303 });
245 -
246304
247 - //intermediate
248 -
249 - //total
 305+ // intermediate
 306+
 307+ // total
250308 var intermediate_total = 0;
251 - $(".intermediate_data").each(function(){
252 - intermediate_total += parseInt($(this).attr( "value"));
 309+ $(".intermediate_data").each(function() {
 310+ intermediate_total += parseInt( $(this).attr( 'value' ) );
253311 });
254 -
255 -
256 - //blue shade
257 - $(".intermediate_data").each(function(){
258 - var rval = (intermediate_total == 0 ? 255 : 255 - (255 * $(this).attr("value") / intermediate_total));
 312+
 313+ // blue shade
 314+ $(".intermediate_data").each(function() {
 315+ var rval = ( intermediate_total == 0 ? 255 : 255 - ( 255 * $(this).attr( 'value' ) / intermediate_total ) );
259316 var gval = rval;
260317 var bval = 255;
261 - rgbString = "rgb(" + parseInt(rval) + "," + parseInt(gval) + "," + parseInt(bval) + ")";
262 - $(this).data("rgb", rgbString);
263 - $(this).css("color", rgbString);
264 - $(this).css("background-color", rgbString);
 318+ rgbString = "rgb(" + parseInt( rval ) + "," + parseInt( gval ) + "," + parseInt( bval ) + ")";
 319+ $(this).data('rgb', rgbString);
 320+ $(this).css('color', rgbString);
 321+ $(this).css('background-color', rgbString);
265322 });
266 -
267 - //total
 323+
 324+ // total
268325 var basic_total = 0;
269 - $(".basic_data").each(function(){
270 - basic_total += parseInt($(this).attr( "value"));
 326+ $(".basic_data").each(function() {
 327+ basic_total += parseInt( $(this).attr( 'value' ) );
271328 });
272 -
273 - //green shade
274 - $(".basic_data").each(function(){
275 - var rval = (basic_total == 0 ? 255 : 255 - (255 * $(this).attr("value") / basic_total));
 329+
 330+ // green shade
 331+ $(".basic_data").each(function() {
 332+ var rval = ( basic_total == 0 ? 255 : 255 - ( 255 * $(this).attr( 'value' ) / basic_total ) );
276333 var gval = 255;
277334 var bval = rval;
278 - rgbString = "rgb(" + parseInt(rval) + "," + parseInt(gval) + "," + parseInt(bval) + ")";
279 - $(this).data("rgb", rgbString);
280 - $(this).css("color", rgbString);
281 - $(this).css("background-color", rgbString);
 335+ rgbString = "rgb(" + parseInt( rval ) + "," + parseInt( gval ) + "," + parseInt( bval ) + ")";
 336+ $(this).data('rgb', rgbString);
 337+ $(this).css('color', rgbString);
 338+ $(this).css('background-color', rgbString);
282339 });
283 -
 340+
284341 // I wanted to do this with classes, but the element's style rule wins over class rule
285342 // and each element has its own alternative color
286 - $(".event_data").mouseover(function(){
287 - $(this).css("color", "#000000");
288 - $(this).css("background-color", "#FFFFFF");
 343+ $(".event_data").mouseover(function() {
 344+ $(this).css('color', '#000000');
 345+ $(this).css('background-color', '#FFFFFF');
289346 });
290 -
291 - $(".event_data").mouseout(function(){
 347+
 348+ $(".event_data").mouseout(function() {
292349 rgbString = $(this).data("rgb");
293 - $(this).css("color", rgbString);
294 - $(this).css("background-color", rgbString);
 350+ $(this).css('color', rgbString);
 351+ $(this).css('background-color', rgbString);
295352 });
296 -
297 - };
298 -
299 -
300 - $.setUIControls = function(){
301 -
302 - //SET UP DATE RANGES
303 -
304 -
305 - //date-pickers for start and end dates
306 - $('.date_range_input').each(function(){
 353+
 354+ }; // colorize
 355+
 356+ $.updateTable = function() {
 357+ var processTableJSON = function( data, status ) {
 358+ // clear
 359+ $(".table_data_row").each( function() { $(this).remove(); } );
 360+
 361+ var row_count = 0;
 362+ for( var row_iter in data['tablevals']['vals'] ) {
 363+ var row = data['tablevals']['vals'][row_iter]; // really, JS?
 364+ row_count++;
 365+
 366+ var outputRow = $("<tr></tr>");
 367+ outputRow.addClass( 'table_data_row' );
 368+
 369+ var cell =$("<td></td>").attr('id', 'event_name_' + row_count);
 370+ cell.addClass( 'event_name' );
 371+ cell.attr( 'value', row['event_id'] );
 372+ cell.text( row['event_name']);
 373+ outputRow.append( cell );
 374+
 375+ var createClassCell = function( userclass ) {
 376+ var newcell = $("<td></td>").attr('id', 'event_' + userclass + '_' + row_count);
 377+ newcell.addClass( 'event_data' );
 378+ newcell.addClass( userclass + '_data' );
 379+ newcell.text( row[userclass] );
 380+ newcell.attr( 'value', row[userclass] );
 381+ outputRow.append( newcell );
 382+ };
 383+
 384+ createClassCell( 'expert' );
 385+ createClassCell( 'intermediate' );
 386+ createClassCell( 'basic' );
 387+ createClassCell( 'total' );
 388+ $("#clicktrack_data_table").append( outputRow );
 389+ }
 390+
 391+ $.colorizeTable();
 392+ };
 393+
 394+ start_date = $("#start_date").val();
 395+ if( $("#start_date").hasClass( 'hidden' ) ) {
 396+ start_date = '0';
 397+ }
 398+
 399+ end_date = $("#end_date").val();
 400+ if( $("#end_date").hasClass( 'hidden' ) ) {
 401+ end_date = '0';
 402+ }
 403+
 404+ // post relevant info
 405+ $j.post( wgScriptPath + '/api.php',
 406+ { 'action': 'specialclicktracking', 'format': 'json',
 407+ 'eventid': 1, 'increment': $("#chart_increment").val(),
 408+ 'startdate': start_date, 'enddate': end_date, 'userdefs': $.json_encode( wgClickTrackUserDefs ), 'tabledata': 1 },
 409+ processTableJSON, 'json'
 410+ );
 411+
 412+ }; // updateTable
 413+
 414+ $.setUIControls = function() {
 415+ // SET UP DATE RANGES
 416+
 417+ // date-pickers for start and end dates
 418+ $('.date_range_input').each(function() {
307419 $(this).datepicker();
308 - $(this).datepicker('option', 'dateFormat', 'yymmdd');
 420+ $(this).datepicker( 'option', 'dateFormat', 'yymmdd' );
309421 });
310 - $('#start_date').datepicker('option', 'defaultDate', '-3m');
311 -
312 - var toggleDateInput = function(tableRow){
313 - var checked= false;
314 - tableRow.children().each(function(){
315 - if(checked == false){
316 - checked = $(this).children("input:checkbox").eq(0).is(":checked");}
 422+ var startDate = new Date();
 423+ $('#start_date').val("20091009"); // click_tracking start date as default
 424+
 425+ var toggleDateInput = function( tableRow ) {
 426+ var checked = false;
 427+ tableRow.children().each( function() {
 428+ if( checked == false ) {
 429+ checked = $(this).children("input:checkbox").eq(0).is(":checked");
 430+ }
317431 });
318 -
319 - if(checked){
320 - tableRow.removeClass("disabled_option");
321 - tableRow.children("td").each(function(){
322 - $(this).children(".date_range_input").removeClass("hidden");
 432+
 433+ if( checked ) {
 434+ tableRow.removeClass( 'disabled_option' );
 435+ tableRow.children("td").each(function() {
 436+ $(this).children(".date_range_input").removeClass( 'hidden' );
323437 });
324 - }
325 - else{
326 - tableRow.children("td").each(function(){
327 - $(this).children(".date_range_input").addClass("hidden");
 438+ } else {
 439+ tableRow.children("td").each(function() {
 440+ $(this).children(".date_range_input").addClass( 'hidden' );
328441 });
329 - tableRow.addClass("disabled_option");
 442+ tableRow.addClass( 'disabled_option' );
330443 }
331444 };
332 -
333 - $('.date_range_checkbox').click(function(){
334 - toggleDateInput($(this).closest("tr"));
 445+
 446+ $('.date_range_checkbox').click(function() {
 447+ toggleDateInput( $(this).closest( 'tr' ) );
335448 });
336 -
337 - //CHART DIALOG
 449+
 450+ // update table
 451+ $('#update_table_button').click($.updateTable);
 452+
 453+ // CHART DIALOG
338454 $("#chart_dialog").dialog({ autoOpen: false, width: 400 });
339 - $("#chart_img").css("cursor","pointer");
340 - $("#chart_img").click(function(){
 455+ $("#chart_img").css('cursor', 'pointer');
 456+ $("#chart_img").click(function() {
341457 $("#chart_dialog").dialog('open');
342458 });
 459+
 460+ $("#chart_increment").data( 'value', $("#chart_increment").val() );
343461
344 - $("#chart_increment").data("value", $("#chart_increment").val());
345 -
346 - $("#change_graph").click(function(){
 462+ $("#change_graph").click(function() {
347463 $("#chart_dialog").dialog('close');
348464
349 - //check if the value actually changed, if so, update and increment things accordingly
350 - if( $("#chart_increment").data("value") != $("#chart_increment").val() ){
351 - $("#chart_increment").data("value", $("#chart_increment").val());
 465+ // check if the value actually changed, if so, update and increment things accordingly
 466+ if( $("#chart_increment").data( 'value' ) != $("#chart_increment").val() ) {
 467+ $("#chart_increment").data( 'value', $("#chart_increment").val() );
352468 $.updateChart();
353469 }
354 -
 470+
355471 });
356 -
357 - //CHANGE USER INFO DIALOG
358 - $("#user_def_dialog").dialog({ autoOpen: true, width: 400 });
359 - $("#user_def_alter_legend").data("defaultChangeText", $("#user_def_alter_legend").text());
360 -
 472+
 473+ // CHANGE USER INFO DIALOG
 474+ $("#user_def_dialog").dialog({ autoOpen: false, width: 400 });
 475+ $("#user_def_alter_legend").data( 'defaultChangeText', $("#user_def_alter_legend").text() );
 476+
 477+ // CHANGE USER/INTERMEDIATE/EXPERT DIALOGS
 478+ var loadHeaderInfo = function( headerName ) {
 479+ $("#" + headerName + "_header").css('cursor', 'pointer');
 480+ $("#" + headerName + "_header").click(function() {
 481+ $.renderUserDefDialogWith( wgClickTrackUserDefs[headerName], headerName );
 482+ $("#user_def_dialog").dialog('open');
 483+ });
 484+ }; // headername
 485+
 486+ loadHeaderInfo( 'basic' );
 487+ loadHeaderInfo( 'intermediate' );
 488+ loadHeaderInfo( 'expert' );
 489+
361490 };
362 -
363 -
364 - $.changeDataLinks = function (){
365 -
366 - $(".event_name").each(function(){
367 - $(this).css("cursor", "pointer");
368 -
369 - $(this).click(function(){
370 - $("#chart_img").data("eventid", $(this).attr( "value" ));
371 - $("#chart_img").data("event_name", $(this).text());
 491+
 492+ $.changeDataLinks = function() {
 493+ $(".event_name").each(function() {
 494+ $(this).css('cursor', 'pointer');
 495+
 496+ $(this).click(function() {
 497+ $("#chart_img").data( 'eventid', $(this).attr( 'value' ) );
 498+ $("#chart_img").data( 'event_name', $(this).text() );
372499 $.updateChart();
373 - });//click
374 - });//each
375 - };//addlink
376 -
 500+ }); // click
 501+ }); // each
 502+ }; // addlink
 503+
377504 return $(this);
378505 })(jQuery);
379506
380 -//colorize the table on document.ready
381 -js2AddOnloadHook($j.colorizeTable);
382 -js2AddOnloadHook($j.changeDataLinks);
383 -js2AddOnloadHook($j.setUIControls);
384 -
 507+// colorize the table on document.ready
 508+js2AddOnloadHook( $j.colorizeTable );
 509+js2AddOnloadHook( $j.changeDataLinks );
 510+js2AddOnloadHook( $j.setUIControls );
\ No newline at end of file
Index: branches/wmf-deployment/extensions/UsabilityInitiative/ClickTracking/ApiClickTracking.php
@@ -12,7 +12,7 @@
1313 * runs when the API is called with "clicktracking", takes in "eventid" and an edit token given to the user, "token"
1414 * @see includes/api/ApiBase#execute()
1515 */
16 - public function execute(){
 16+ public function execute() {
1717 global $wgUser, $wgTitle, $wgClickTrackContribGranularity1, $wgClickTrackContribGranularity2, $wgClickTrackContribGranularity3;
1818
1919 $params = $this->extractRequestParams();
@@ -25,18 +25,15 @@
2626
2727 $is_logged_in = $wgUser->isLoggedIn();
2828 $now = time();
29 - $granularity1 = $is_logged_in?
30 - ClickTrackingHooks::getEditCountSince( $now - $wgClickTrackContribGranularity1 )
31 - : 0;
32 -
33 - $granularity2 = $is_logged_in?
34 - ClickTrackingHooks::getEditCountSince( $now - $wgClickTrackContribGranularity2 )
35 - : 0;
36 -
37 - $granularity3 = $is_logged_in?
38 - ClickTrackingHooks::getEditCountSince( $now - $wgClickTrackContribGranularity3 )
39 - : 0;
 29+ $granularity1 = $is_logged_in ?
 30+ ClickTrackingHooks::getEditCountSince( $now - $wgClickTrackContribGranularity1 ) : 0;
4031
 32+ $granularity2 = $is_logged_in ?
 33+ ClickTrackingHooks::getEditCountSince( $now - $wgClickTrackContribGranularity2 ) : 0;
 34+
 35+ $granularity3 = $is_logged_in ?
 36+ ClickTrackingHooks::getEditCountSince( $now - $wgClickTrackContribGranularity3 ) : 0;
 37+
4138 ClickTrackingHooks::trackEvent(
4239 $session_id, // randomly generated session ID
4340 $is_logged_in, // is the user logged in?
@@ -47,6 +44,15 @@
4845 $granularity2, //contributions made in granularity 2 time frame
4946 $granularity3 //contributions made in granularity 3 time frame
5047 );
 48+
 49+ // For links that go off the page, redirect the user
 50+ // FIXME: The API should have a proper infrastructure for this
 51+ if ( !is_null( $params['redirectto'] ) ) {
 52+ global $wgOut;
 53+ $wgOut->enable();
 54+ $wgOut->redirect( $params['redirectto'] );
 55+ $wgOut->output();
 56+ }
5157 }
5258
5359 /**
@@ -65,7 +71,8 @@
6672 public function getParamDescription() {
6773 return array(
6874 'eventid' => 'string of eventID',
69 - 'token' => 'unique edit ID for this edit session'
 75+ 'token' => 'unique edit ID for this edit session',
 76+ 'redirectto' => 'URL to redirect to (only used for links that go off the page)'
7077 );
7178 }
7279
@@ -77,18 +84,14 @@
7885
7986 public function getAllowedParams() {
8087 return array(
81 - 'eventid' => array(
82 - ApiBase::PARAM_TYPE => 'string'
83 - ),
84 - 'token' => array(
85 - ApiBase::PARAM_TYPE => 'string'
86 - )
 88+ 'eventid' => null,
 89+ 'token' => null,
 90+ 'redirectto' => null
8791 );
8892 }
8993
90 - // TODO: create a more useful 'version number'
9194 public function getVersion() {
92 - return __CLASS__ . ': $Id: $';
 95+ return __CLASS__ . ': $Id$';
9396 }
9497
9598 }
\ No newline at end of file
Property changes on: branches/wmf-deployment/extensions/UsabilityInitiative/ClickTracking/ApiClickTracking.php
___________________________________________________________________
Added: svn:keywords
9699 + Id
Property changes on: branches/wmf-deployment/extensions/UsabilityInitiative/ClickTracking
___________________________________________________________________
Modified: svn:mergeinfo
97100 Reverse-merged /trunk/extensions/UsabilityInitiative/ClickTracking:r57544-57549
98101 Merged /trunk/extensions/UsabilityInitiative/ClickTracking:r58926,58973-58974,59048,59202
99102 Merged /branches/usability/acaifix/ClickTracking:r59192-59203
Index: branches/wmf-deployment/extensions/UsabilityInitiative/EditToolbar/EditToolbar.js
@@ -147,44 +147,52 @@
148148 'heading-2' : {
149149 labelMsg: 'edittoolbar-tool-heading-2',
150150 action: {
151 - type: 'encapsulate',
 151+ type: 'replace',
152152 options: {
153 - pre: "==",
 153+ pre: '==',
154154 periMsg: 'edittoolbar-tool-heading-example',
155 - post: "=="
 155+ post: '==',
 156+ regex: /^(\s*)(={0,6})(.*?)\2(\s*)$/,
 157+ regexReplace: "\$1==\$3==\$4"
156158 }
157159 }
158160 },
159161 'heading-3' : {
160162 labelMsg: 'edittoolbar-tool-heading-3',
161163 action: {
162 - type: 'encapsulate',
 164+ type: 'replace',
163165 options: {
164 - pre: "===",
 166+ pre: '===',
165167 periMsg: 'edittoolbar-tool-heading-example',
166 - post: "==="
 168+ post: '===',
 169+ regex: /^(\s*)(={0,6})(.*?)\2(\s*)$/,
 170+ regexReplace: "\$1===\$3===\$4"
167171 }
168172 }
169173 },
170174 'heading-4' : {
171175 labelMsg: 'edittoolbar-tool-heading-4',
172176 action: {
173 - type: 'encapsulate',
 177+ type: 'replace',
174178 options: {
175 - pre: "====",
 179+ pre: '====',
176180 periMsg: 'edittoolbar-tool-heading-example',
177 - post: "===="
 181+ post: '====',
 182+ regex: /^(\s*)(={0,6})(.*?)\2(\s*)$/,
 183+ regexReplace: "\$1====\$3====\$4"
178184 }
179185 }
180186 },
181187 'heading-5' : {
182188 labelMsg: 'edittoolbar-tool-heading-5',
183189 action: {
184 - type: 'encapsulate',
 190+ type: 'replace',
185191 options: {
186 - pre: "=====",
 192+ pre: '=====',
187193 periMsg: 'edittoolbar-tool-heading-example',
188 - post: "====="
 194+ post: '=====',
 195+ regex: /^(\s*)(={0,6})(.*?)\2(\s*)$/,
 196+ regexReplace: "\$1=====\$3=====\$4"
189197 }
190198 }
191199 }
@@ -222,6 +230,19 @@
223231 ownline: true
224232 }
225233 }
 234+ },
 235+ 'indent': {
 236+ labelMsg: 'edittoolbar-tool-indent',
 237+ type: 'button',
 238+ icon: 'format-indent.png',
 239+ action: {
 240+ type: 'encapsulate',
 241+ options: {
 242+ pre: ":",
 243+ post: "",
 244+ ownline: true
 245+ }
 246+ }
226247 }
227248 }
228249 },
@@ -820,14 +841,17 @@
821842 'format': 'json'
822843 },
823844 success: function( data ) {
824 - // TODO: What happens if data.query.pageids is undefined?
825 - var page = data.query.pages[data.query.pageids[0]];
826 - var status = 'exists';
827 - if ( typeof page.missing != 'undefined' )
828 - status = 'notexists';
829 - else if ( typeof page.invalid != 'undefined' )
 845+ var status;
 846+ if ( typeof data.query == 'undefined' ) {
830847 status = 'invalid';
831 -
 848+ } else {
 849+ var page = data.query.pages[data.query.pageids[0]];
 850+ status = 'exists';
 851+ if ( typeof page.missing != 'undefined' )
 852+ status = 'notexists';
 853+ else if ( typeof page.invalid != 'undefined' )
 854+ status = 'invalid';
 855+ }
832856 cache[target] = status;
833857 updateWidget( status );
834858 }
@@ -845,7 +869,8 @@
846870 // Automatically copy the value of the internal link page title field to the link text field unless the user
847871 // has changed the link text field - this is a convience thing since most link texts are going to be the
848872 // the same as the page title
849 - $j( '#edittoolbar-link-int-target' ).bind( 'change keypress paste cut', function() {
 873+ // Also change the internal/external radio button accordingly
 874+ $j( '#edittoolbar-link-int-target' ).bind( 'change keydown paste cut', function() {
850875 // $j(this).val() is the old value, before the keypress
851876 if ( $j( '#edittoolbar-link-int-text' ).data( 'untouched' ) )
852877 // Defer this until $j(this).val() has been updated
@@ -853,8 +878,13 @@
854879 $j( '#edittoolbar-link-int-text' ).val( $j( '#edittoolbar-link-int-target' ).val() );
855880 }, 0 );
856881 });
857 - $j( '#edittoolbar-link-int-text' ).bind( 'change keypress paste cut', function() {
858 - $j(this).data( 'untouched', false );
 882+ $j( '#edittoolbar-link-int-text' ).bind( 'change keydown paste cut', function() {
 883+ var oldVal = $j(this).val();
 884+ var that = this;
 885+ setTimeout( function() {
 886+ if ( $j(that).val() != oldVal )
 887+ $j(that).data( 'untouched', false );
 888+ }, 0 );
859889 });
860890 // Set the initial value of the external link field to start out as a real URL
861891 $j( '#edittoolbar-link-ext-target' ).val( 'http://' );
@@ -1013,11 +1043,11 @@
10141044 }
10151045 },
10161046 open: function() {
 1047+ // Pre-fill the text fields based on the current selection
 1048+ var selection = $j(this).data( 'context' ).$textarea.focus().getSelection();
10171049 $j( '#edittoolbar-link-int-target, #edittoolbar-link-ext-target' )
10181050 .filter( ':visible' )
10191051 .focus();
1020 - // Pre-fill the text fields based on the current selection
1021 - var selection = $j(this).data( 'context' ).$textarea.getSelection();
10221052 $j( '#edittoolbar-link-dialog-tab-int' ).data( 'whitespace', [ '', '' ] );
10231053 $j( '#edittoolbar-link-dialog-tab-ext' ).data( 'whitespace', [ '', '' ] );
10241054 if ( selection != '' ) {
@@ -1068,6 +1098,7 @@
10691099 $j(this)
10701100 .find( 'button:first' )
10711101 .click();
 1102+ e.preventDefault();
10721103 }
10731104 });
10741105 }
@@ -1094,15 +1125,6 @@
10951126 $j(this).find( '[rel]' ).each( function() {
10961127 $j(this).text( gM( $j(this).attr( 'rel' ) ) );
10971128 });
1098 - // Execute the action associated with the first button
1099 - // when the user presses Enter
1100 - $j(this).closest( '.ui-dialog' ).keypress( function( e ) {
1101 - if ( ( e.keyCode || e.which ) == 13 ) {
1102 - $j(this)
1103 - .find( 'button:first' )
1104 - .click();
1105 - }
1106 - });
11071129 $j( '#edittoolbar-table-dimensions-rows' ).val( 2 );
11081130 $j( '#edittoolbar-table-dimensions-columns' ).val( 2 );
11091131 },
@@ -1174,6 +1196,7 @@
11751197 $j(this)
11761198 .find( 'button:first' )
11771199 .click();
 1200+ e.preventDefault();
11781201 }
11791202 });
11801203 }
@@ -1190,12 +1213,12 @@
11911214 <div id="edittoolbar-replace-emptysearch" rel="edittoolbar-tool-replace-emptysearch"></div>\
11921215 <div id="edittoolbar-replace-invalidregex"></div>\
11931216 </div>\
1194 - <fieldset><table><tr>\
 1217+ <fieldset><table style="width: 100%;"><tr>\
11951218 <td><label for="edittoolbar-replace-search" rel="edittoolbar-tool-replace-search"></label></td>\
1196 - <td><input type="text" id="edittoolbar-replace-search" /></td>\
 1219+ <td><input type="text" id="edittoolbar-replace-search" style="width: 100%;" /></td>\
11971220 </tr><tr>\
11981221 <td><label for="edittoolbar-replace-replace" rel="edittoolbar-tool-replace-replace"></label></td>\
1199 - <td><input type="text" id="edittoolbar-replace-replace" /></td>\
 1222+ <td><input type="text" id="edittoolbar-replace-replace" style="width: 100%;" /></td>\
12001223 </tr></table><table><tr>\
12011224 <td><input type="checkbox" id="edittoolbar-replace-case" /></td>\
12021225 <td><label for="edittoolbar-replace-case" rel="edittoolbar-tool-replace-case"></label></td>\
@@ -1207,15 +1230,6 @@
12081231 $j(this).find( '[rel]' ).each( function() {
12091232 $j(this).text( gM( $j(this).attr( 'rel' ) ) );
12101233 });
1211 - // Execute the action associated with the first button
1212 - // when the user presses Enter
1213 - $j(this).closest( '.ui-dialog' ).keypress( function( e ) {
1214 - if ( ( e.keyCode || e.which ) == 13 ) {
1215 - $j(this)
1216 - .find( 'button:first' )
1217 - .click();
1218 - }
1219 - });
12201234
12211235 // TODO: Find a cleaner way to share this function
12221236 $j(this).data( 'replaceCallback', function( mode ) {
@@ -1226,7 +1240,7 @@
12271241 return;
12281242 }
12291243 var replaceStr = $j( '#edittoolbar-replace-replace' ).val();
1230 - var flags = '';
 1244+ var flags = 'm';
12311245 var matchCase = $j( '#edittoolbar-replace-case' ).is( ':checked' );
12321246 var isRegex = $j( '#edittoolbar-replace-regex' ).is( ':checked' );
12331247 if ( !matchCase ) {
@@ -1298,13 +1312,16 @@
12991313 },
13001314 dialog: {
13011315 buttons: {
1302 - 'edittoolbar-tool-replace-button-findnext': function() {
 1316+ 'edittoolbar-tool-replace-button-findnext': function( e ) {
 1317+ $j(this).closest( '.ui-dialog' ).data( 'dialogaction', e.target );
13031318 $j(this).data( 'replaceCallback' ).call( this, 'find' );
13041319 },
1305 - 'edittoolbar-tool-replace-button-replacenext': function() {
 1320+ 'edittoolbar-tool-replace-button-replacenext': function( e ) {
 1321+ $j(this).closest( '.ui-dialog' ).data( 'dialogaction', e.target );
13061322 $j(this).data( 'replaceCallback' ).call( this, 'replace' );
13071323 },
1308 - 'edittoolbar-tool-replace-button-replaceall': function() {
 1324+ 'edittoolbar-tool-replace-button-replaceall': function( e ) {
 1325+ $j(this).closest( '.ui-dialog' ).data( 'dialogaction', e.target );
13091326 $j(this).data( 'replaceCallback' ).call( this, 'replaceAll' );
13101327 },
13111328 'edittoolbar-tool-replace-close': function() {
@@ -1312,27 +1329,35 @@
13131330 $j(this).data( 'context' ).$textarea
13141331 .unbind( 'keypress.srdialog' )
13151332 .focus();
 1333+ $j(this).closest( '.ui-dialog' ).data( 'dialogaction', false );
13161334 }
13171335 },
13181336 open: function() {
13191337 $j(this).data( 'offset', 0 );
13201338 $j( '#edittoolbar-replace-search' ).focus();
13211339 $j( '#edittoolbar-replace-nomatch, #edittoolbar-replace-success, #edittoolbar-replace-emptysearch, #edittoolbar-replace-invalidregex' ).hide();
1322 - if ( !( $j(this).data( 'dialogkeypressset' ) ) ) {
1323 - $j(this).data( 'dialogkeypressset', true );
 1340+ if ( !( $j(this).data( 'onetimeonlystuff' ) ) ) {
 1341+ $j(this).data( 'onetimeonlystuff', true );
13241342 // Execute the action associated with the first button
13251343 // when the user presses Enter
13261344 $j(this).closest( '.ui-dialog' ).keypress( function( e ) {
13271345 if ( ( e.keyCode || e.which ) == 13 ) {
1328 - $j(this).find( 'button:first' ).click();
 1346+ var button = $j(this).data( 'dialogaction' ) || $j(this).find( 'button:first' );
 1347+ button.click();
13291348 e.preventDefault();
13301349 }
13311350 });
 1351+ // Make tabbing to a button and pressing
 1352+ // Enter do what people expect
 1353+ $j(this).closest( '.ui-dialog' ).find( 'button' ).focus( function() {
 1354+ $j(this).closest( '.ui-dialog' ).data( 'dialogaction', this );
 1355+ });
13321356 }
13331357 var dialog = $j(this).closest( '.ui-dialog' );
13341358 $j(this).data( 'context' ).$textarea.bind( 'keypress.srdialog', function( e ) {
13351359 if ( ( e.keyCode || e.which ) == 13 ) {
1336 - dialog.find( 'button:first' ).click();
 1360+ var button = dialog.data( 'dialogaction' ) || dialog.find( 'button:first' );
 1361+ button.click();
13371362 e.preventDefault();
13381363 }
13391364 });
Property changes on: branches/wmf-deployment/extensions/UsabilityInitiative/EditToolbar/EditToolbar.js
___________________________________________________________________
Added: svn:mergeinfo
13401365 Merged /branches/REL1_15/phase3/extensions/UsabilityInitiative/EditToolbar/EditToolbar.js:r51646
13411366 Merged /trunk/extensions/UsabilityInitiative/EditToolbar/EditToolbar.js:r56151-57234,57425,58926,58973-58974,59202
13421367 Merged /branches/usability/acaifix/EditToolbar/EditToolbar.js:r59192-59203
13431368 Merged /trunk/phase3/extensions/UsabilityInitiative/EditToolbar/EditToolbar.js:r56213,56215-56216,56218,56325,56334-56336,56338,56340,56343,56345,56347,56350,57154-57447
13441369 Merged /trunk/extensions/UsabilityInitiative/WikiEditor/Modules/Toolbar/Toolbar.js:r58873,58923,58953
Index: branches/wmf-deployment/extensions/UsabilityInitiative/EditToolbar/EditToolbar.i18n.php
@@ -42,6 +42,7 @@
4343 'edittoolbar-tool-link-int-target-status-loading' => 'Checking page existence...',
4444 'edittoolbar-tool-link-int-invalid' => 'The title you specified is invalid.',
4545 'edittoolbar-tool-link-ext-invalid' => 'The URL you specified is invalid.',
 46+ 'edittoolbar-tool-link-empty' => "You didn't enter anything to link to.",
4647 'edittoolbar-tool-file' => 'Embedded file',
4748 'edittoolbar-tool-file-pre' => '$1{{ns:file}}:',
4849 'edittoolbar-tool-file-example' => 'Example.jpg',
Index: branches/wmf-deployment/extensions/UsabilityInitiative/EditToolbar/EditToolbar.php
@@ -13,13 +13,13 @@
1414 *
1515 * @author Trevor Parscal <tparscal@wikimedia.org>, Roan Kattouw <roan.kattouw@gmail.com>
1616 * @license GPL v2 or later
17 - * @version 0.1.1
 17+ * @version 0.1.3
1818 */
1919
2020 /* Configuration */
2121
2222 // Bump the version number every time you change any of the .css/.js files
23 -$wgEditToolbarStyleVersion = 58;
 23+$wgEditToolbarStyleVersion = 76;
2424
2525 // Set this to true to simply override the stock toolbar for everyone
2626 $wgEditToolbarGlobalEnable = false;
@@ -48,7 +48,7 @@
4949 'path' => __FILE__,
5050 'name' => 'EditToolbar',
5151 'author' => 'Trevor Parscal',
52 - 'version' => '0.1.1',
 52+ 'version' => '0.1.3',
5353 'url' => 'http://www.mediawiki.org/wiki/Extension:UsabilityInitiative',
5454 'descriptionmsg' => 'edittoolbar-desc',
5555 );
Index: branches/wmf-deployment/extensions/UsabilityInitiative/EditToolbar/EditToolbar.hooks.php
@@ -60,6 +60,7 @@
6161 'edittoolbar-tool-link-int-target-status-loading',
6262 'edittoolbar-tool-link-int-invalid',
6363 'edittoolbar-tool-link-ext-invalid',
 64+ 'edittoolbar-tool-link-empty',
6465 'edittoolbar-tool-file',
6566 'edittoolbar-tool-file-pre',
6667 'edittoolbar-tool-file-example',
Property changes on: branches/wmf-deployment/extensions/UsabilityInitiative
___________________________________________________________________
Modified: svn:mergeinfo
6768 Merged /trunk/extensions/UsabilityInitiative:r58926,58973-58974,59202
6869 Merged /branches/usability/acaifix:r58541-59203

Past revisions this follows-up on

RevisionCommit summaryAuthorDate
r57482new toolbar formating iconsadam19:35, 7 October 2009
r57677updating png24 indent iconadam19:29, 13 October 2009
r57743updates to the collapsible tabs jsadam05:20, 15 October 2009
r578331. Changed the styling of the TOC to match the styling of the booklet indexes...tparscal19:41, 16 October 2009
r57836Changed click handlers to mousedown - improves precieved performance.tparscal23:46, 16 October 2009
r57904adding collapsibleTabs plugin to the Makefile and recombining and compressing...adam18:20, 19 October 2009
r57906NavigableTOC: (bug 21177) Empty headers (like "====") treated weird. The NTOC...catrope18:28, 19 October 2009
r57916setting white-space to nowrap on the nav tabs in vector for better animatingadam20:50, 19 October 2009
r57918fixing a descrepency with the buffer space on expanding a tabadam21:09, 19 October 2009
r57921Addressing Roan's feedback on r57918adam21:41, 19 October 2009
r58069adding a new indent toolbar iconadam21:18, 23 October 2009
r58070Adding the indent icon to the edit toolbaradam21:19, 23 October 2009
r58096NavigableTOC: (bug 21153) Highlighting gets confused when a header is made lo...catrope19:44, 24 October 2009
r58156updating the indent toolbar iconadam19:21, 26 October 2009
r58170Correcting bug #21293 introduced in r57982 - removing a trailing comma that w...adam22:48, 26 October 2009
r58173WikiEditor Toolbar: removing overflow:hidden; from the toolbar sections and a...adam23:39, 26 October 2009
r58174altering two lines of the code I just commited to match our coding style guideadam23:44, 26 October 2009
r58198* EditToolbar: (bug 21269) Header dropdown cleverness, so selecting "== Foo =...catrope15:43, 27 October 2009
r58205babaco support, Removed some unused code, refactored for MySQL 4.0, created m...nimishg17:42, 27 October 2009
r58219fixing a slight bug with watch/unwatch. The icon watch/unwatch was dependent ...adam21:10, 27 October 2009
r58229Allowing the advanced toolbar of the wikieditor to gracefully handle a browse...adam22:31, 27 October 2009
r58253EditToolbar: (bug 21323) Clicking tabs makes browser jump to top of page; reg...catrope12:05, 28 October 2009
r58310EditToolbar: (bug 21343) Treat regexes as multiline in search&replace, so ^ a...catrope12:41, 29 October 2009
r58374NavigableTOC: (bug 21177) Empty headers show up weird (very small height)catrope20:19, 30 October 2009
r58425EditToolbar: (bug 21220) Selected value not copied to page title field in IE/...catrope11:36, 2 November 2009
r58426* NavigableTOC: (bug 21201) Display hand cursor over highlighted sections in ...catrope11:53, 2 November 2009
r58427EditToolbar: (bug 21016) Tabbing to a button and pressing Enter doesn't work ...catrope13:26, 2 November 2009
r58441NaNavigableTOC: Fix autoellipse bugginesscatrope20:46, 2 November 2009
r58448Fixes regression in r57836 which changed the event from click to mousedown - ...tparscal22:45, 2 November 2009
r58449Added a handler to unfocus the tab on mouseup - since the focus happens after...tparscal22:53, 2 November 2009
r58451Addressing Brion's comment on r58070 and making the indent toolbar icon funct...adam00:12, 3 November 2009
r58873* EditToolbar: Make header dropdown whitespace-tolerant...catrope20:52, 10 November 2009
r58923UsabilityIntiative: Toolbar: Fix header dropdown per bug 21476 comment #2catrope19:55, 11 November 2009
r58926UsabilityInitiative: Toolbar: Don't add empty sections resulting in a double ...catrope20:26, 11 November 2009
r58953* UsabilityIntiative: Hopefully fix bug 21342 (e.button != 0 check doesn't wo...catrope16:29, 12 November 2009
r58969Fixing a bug on collapsible tabs where the tabs would get stuck alternating b...adam20:36, 12 November 2009
r58973UsabilityInitiative: Fix for r58953catrope21:35, 12 November 2009
r58974Fix for r58973: needs parenthesescatrope21:40, 12 November 2009
r59048add trailing zeroes for MW_TIMESTAMP formatnimishg02:00, 14 November 2009
r59146* OptIn: (bug 21508) Trying to opt in as an already opted-in user displays th...catrope21:05, 16 November 2009
r59185acaifix: Some IE fixes. This should fix bug 21492, bug 21220, bug 21248 and b...catrope23:01, 17 November 2009
r59191acaifix: Change tactics for handling browsers that don't restore cursor posit...catrope00:16, 18 November 2009

Status & tagging log