Index: trunk/extensions/UsabilityInitiative/UsabilityInitiative.hooks.php |
— | — | @@ -60,23 +60,23 @@ |
61 | 61 | array( 'src' => 'js/plugins/jquery.autoEllipse.js', 'version' => 1 ), |
62 | 62 | array( 'src' => 'js/plugins/jquery.browser.js', 'version' => 3 ), |
63 | 63 | array( 'src' => 'js/plugins/jquery.cookie.js', 'version' => 3 ), |
64 | | - array( 'src' => 'js/plugins/jquery.delayedBind.js', 'version' => 0 ), |
| 64 | + array( 'src' => 'js/plugins/jquery.delayedBind.js', 'version' => 1 ), |
65 | 65 | array( 'src' => 'js/plugins/jquery.namespaceSelect.js', 'version' => 1 ), |
66 | 66 | array( 'src' => 'js/plugins/jquery.suggestions.js', 'version' => 4 ), |
67 | 67 | array( 'src' => 'js/plugins/jquery.textSelection.js', 'version' => 10 ), |
68 | 68 | array( 'src' => 'js/plugins/jquery.wikiEditor.js', 'version' => 5 ), |
69 | 69 | array( 'src' => 'js/plugins/jquery.wikiEditor.toolbar.js', 'version' => 11 ), |
70 | 70 | array( 'src' => 'js/plugins/jquery.wikiEditor.dialogs.js', 'version' => 3 ), |
71 | | - array( 'src' => 'js/plugins/jquery.wikiEditor.toc.js', 'version' => 6 ), |
| 71 | + array( 'src' => 'js/plugins/jquery.wikiEditor.toc.js', 'version' => 7 ), |
72 | 72 | // FIXME: jQuery UI doesn't belong here, should move to no_js2 |
73 | 73 | // once we figure out how to do jQuery UI properly in JS2 |
74 | 74 | array( 'src' => 'js/js2/jquery-ui-1.7.2.js', 'version' => '1.7.2y' ), |
75 | 75 | ), |
76 | 76 | 'combined' => array( |
77 | | - array( 'src' => 'js/plugins.combined.js', 'version' => 24 ), |
| 77 | + array( 'src' => 'js/plugins.combined.js', 'version' => 25 ), |
78 | 78 | ), |
79 | 79 | 'minified' => array( |
80 | | - array( 'src' => 'js/plugins.combined.min.js', 'version' => 24 ), |
| 80 | + array( 'src' => 'js/plugins.combined.min.js', 'version' => 25 ), |
81 | 81 | ), |
82 | 82 | ), |
83 | 83 | ); |
Index: trunk/extensions/UsabilityInitiative/js/plugins/jquery.wikiEditor.toc.js |
— | — | @@ -43,7 +43,7 @@ |
44 | 44 | $.wikiEditor.modules.toc.fn.build( context ); |
45 | 45 | $.wikiEditor.modules.toc.fn.update( context ); |
46 | 46 | context.$textarea |
47 | | - .bind( 'keyup encapsulateSelection', |
| 47 | + .delayedBind( 1000, 'keyup encapsulateSelection', |
48 | 48 | function( event ) { |
49 | 49 | var context = $(this).data( 'wikiEditor-context' ); |
50 | 50 | $(this).eachAsync( { |
— | — | @@ -55,7 +55,7 @@ |
56 | 56 | } ); |
57 | 57 | } |
58 | 58 | ) |
59 | | - .bind( 'mouseup scrollToPosition focus', |
| 59 | + .bind( 'mouseup scrollToPosition focus keyup encapsulateSelection', |
60 | 60 | function( event ) { |
61 | 61 | var context = $(this).data( 'wikiEditor-context' ); |
62 | 62 | $(this).eachAsync( { |
Index: trunk/extensions/UsabilityInitiative/js/plugins/jquery.delayedBind.js |
— | — | @@ -1,40 +1,69 @@ |
2 | 2 | (function( $ ) { |
| 3 | +/** |
| 4 | + * Function that escapes spaces in event names. This is needed because |
| 5 | + * "_delayedBind-foo bar-1000" refers to two events |
| 6 | + */ |
| 7 | +function encodeEvent( event ) { |
| 8 | + return event.replace( /-/g, '--' ).replace( / /g, '-' ); |
| 9 | +} |
| 10 | + |
3 | 11 | $.fn.extend( { |
4 | 12 | /** |
5 | 13 | * Bind a callback to an event in a delayed fashion. |
6 | 14 | * In detail, this means that the callback will be called a certain |
7 | 15 | * time after the event fires, but the timer is reset every time |
8 | 16 | * the event fires. |
| 17 | + * @param timeout Number of milliseconds to wait |
9 | 18 | * @param event Name of the event (string) |
| 19 | + * @param data Data to pass to the event handler (optional) |
10 | 20 | * @param callback Function to call |
11 | | - * @param timeout Number of milliseconds to wait |
12 | 21 | */ |
13 | | - delayedBind: function( event, callback, timeout ) { |
| 22 | + // TODO: Handle data param properly |
| 23 | + delayedBind: function( timeout, event, data, callback ) { |
| 24 | + var encEvent = encodeEvent( event ); |
14 | 25 | return this.each( function() { |
15 | 26 | var that = this; |
16 | | - $(this).bind( event, function() { |
17 | | - var timerID = $(this).data( '_delayedBindTimerID-' + event ); |
18 | | - var args = arguments; |
19 | | - // Cancel the running timer |
20 | | - if ( typeof timerID != 'undefined' ) |
21 | | - clearTimeout( timerID ); |
22 | | - timerID = setTimeout( function() { |
23 | | - callback.apply( that, args ); |
| 27 | + // Bind the top half |
| 28 | + // Do this only once for every (event, timeout) pair |
| 29 | + if ( !( $(this).data( '_delayedBindBound-' + encEvent + '-' + timeout ) ) ) { |
| 30 | + $(this).data( '_delayedBindBound-' + encEvent + '-' + timeout, true ); |
| 31 | + $(this).bind( event, function() { |
| 32 | + var timerID = $(this).data( '_delayedBindTimerID-' + encEvent + '-' + timeout ); |
| 33 | + // Cancel the running timer |
| 34 | + if ( typeof timerID != 'undefined' ) |
| 35 | + clearTimeout( timerID ); |
| 36 | + timerID = setTimeout( function() { |
| 37 | + $(that).trigger( '_delayedBind-' + encEvent + '-' + timeout ); |
24 | 38 | }, timeout ); |
25 | | - $(this).data( '_delayedBindTimerID-' + event, timerID ); |
26 | | - } ); |
| 39 | + $(this).data( '_delayedBindTimerID-' + encEvent + '-' + timeout, timerID ); |
| 40 | + } ); |
| 41 | + } |
| 42 | + |
| 43 | + // Bottom half |
| 44 | + $(this).bind( '_delayedBind-' + encEvent + '-' + timeout, data, callback ); |
27 | 45 | } ); |
28 | 46 | }, |
29 | 47 | |
30 | 48 | /** |
31 | 49 | * Cancel the timers for delayed events on the selected elements. |
32 | 50 | */ |
33 | | - delayedBindCancel: function( event ) { |
| 51 | + delayedBindCancel: function( timeout, event ) { |
| 52 | + var encEvent = encodeEvent( event ); |
34 | 53 | return this.each( function() { |
35 | | - var timerID = $(this).data( '_delayedBindTimerID-' + event ); |
| 54 | + var timerID = $(this).data( '_delayedBindTimerID-' + encEvent + '-' + timeout ); |
36 | 55 | if ( typeof timerID != 'undefined' ) |
37 | 56 | clearTimeout( timerID ); |
38 | 57 | } ); |
| 58 | + }, |
| 59 | + |
| 60 | + /** |
| 61 | + * Unbind an event bound with delayedBind() |
| 62 | + */ |
| 63 | + delayedBindUnbind: function( timeout, event, callback ) { |
| 64 | + var encEvent = encodeEvent( event ); |
| 65 | + return this.each( function() { |
| 66 | + $(this).unbind( '_delayedBind-' + encEvent + '-' + timeout, callback ); |
| 67 | + } ); |
39 | 68 | } |
40 | 69 | } ); |
41 | 70 | } )( jQuery ); |
Index: trunk/extensions/UsabilityInitiative/js/plugins.combined.js |
— | — | @@ -276,42 +276,71 @@ |
277 | 277 | }; |
278 | 278 | |
279 | 279 | (function( $ ) { |
| 280 | +/** |
| 281 | + * Function that escapes spaces in event names. This is needed because |
| 282 | + * "_delayedBind-foo bar-1000" refers to two events |
| 283 | + */ |
| 284 | +function encodeEvent( event ) { |
| 285 | + return event.replace( /-/g, '--' ).replace( / /g, '-' ); |
| 286 | +} |
| 287 | + |
280 | 288 | $.fn.extend( { |
281 | 289 | /** |
282 | 290 | * Bind a callback to an event in a delayed fashion. |
283 | 291 | * In detail, this means that the callback will be called a certain |
284 | 292 | * time after the event fires, but the timer is reset every time |
285 | 293 | * the event fires. |
| 294 | + * @param timeout Number of milliseconds to wait |
286 | 295 | * @param event Name of the event (string) |
| 296 | + * @param data Data to pass to the event handler (optional) |
287 | 297 | * @param callback Function to call |
288 | | - * @param timeout Number of milliseconds to wait |
289 | 298 | */ |
290 | | - delayedBind: function( event, callback, timeout ) { |
| 299 | + // TODO: Handle data param properly |
| 300 | + delayedBind: function( timeout, event, data, callback ) { |
| 301 | + var encEvent = encodeEvent( event ); |
291 | 302 | return this.each( function() { |
292 | 303 | var that = this; |
293 | | - $(this).bind( event, function() { |
294 | | - var timerID = $(this).data( '_delayedBindTimerID-' + event ); |
295 | | - var args = arguments; |
296 | | - // Cancel the running timer |
297 | | - if ( typeof timerID != 'undefined' ) |
298 | | - clearTimeout( timerID ); |
299 | | - timerID = setTimeout( function() { |
300 | | - callback.apply( that, args ); |
| 304 | + // Bind the top half |
| 305 | + // Do this only once for every (event, timeout) pair |
| 306 | + if ( !( $(this).data( '_delayedBindBound-' + encEvent + '-' + timeout ) ) ) { |
| 307 | + $(this).data( '_delayedBindBound-' + encEvent + '-' + timeout, true ); |
| 308 | + $(this).bind( event, function() { |
| 309 | + var timerID = $(this).data( '_delayedBindTimerID-' + encEvent + '-' + timeout ); |
| 310 | + // Cancel the running timer |
| 311 | + if ( typeof timerID != 'undefined' ) |
| 312 | + clearTimeout( timerID ); |
| 313 | + timerID = setTimeout( function() { |
| 314 | + $(that).trigger( '_delayedBind-' + encEvent + '-' + timeout ); |
301 | 315 | }, timeout ); |
302 | | - $(this).data( '_delayedBindTimerID-' + event, timerID ); |
303 | | - } ); |
| 316 | + $(this).data( '_delayedBindTimerID-' + encEvent + '-' + timeout, timerID ); |
| 317 | + } ); |
| 318 | + } |
| 319 | + |
| 320 | + // Bottom half |
| 321 | + $(this).bind( '_delayedBind-' + encEvent + '-' + timeout, data, callback ); |
304 | 322 | } ); |
305 | 323 | }, |
306 | 324 | |
307 | 325 | /** |
308 | 326 | * Cancel the timers for delayed events on the selected elements. |
309 | 327 | */ |
310 | | - delayedBindCancel: function( event ) { |
| 328 | + delayedBindCancel: function( timeout, event ) { |
| 329 | + var encEvent = encodeEvent( event ); |
311 | 330 | return this.each( function() { |
312 | | - var timerID = $(this).data( '_delayedBindTimerID-' + event ); |
| 331 | + var timerID = $(this).data( '_delayedBindTimerID-' + encEvent + '-' + timeout ); |
313 | 332 | if ( typeof timerID != 'undefined' ) |
314 | 333 | clearTimeout( timerID ); |
315 | 334 | } ); |
| 335 | + }, |
| 336 | + |
| 337 | + /** |
| 338 | + * Unbind an event bound with delayedBind() |
| 339 | + */ |
| 340 | + delayedBindUnbind: function( timeout, event, callback ) { |
| 341 | + var encEvent = encodeEvent( event ); |
| 342 | + return this.each( function() { |
| 343 | + $(this).unbind( '_delayedBind-' + encEvent + '-' + timeout, callback ); |
| 344 | + } ); |
316 | 345 | } |
317 | 346 | } ); |
318 | 347 | } )( jQuery ); |
— | — | @@ -1947,7 +1976,7 @@ |
1948 | 1977 | $.wikiEditor.modules.toc.fn.build( context ); |
1949 | 1978 | $.wikiEditor.modules.toc.fn.update( context ); |
1950 | 1979 | context.$textarea |
1951 | | - .bind( 'keyup encapsulateSelection', |
| 1980 | + .delayedBind( 1000, 'keyup encapsulateSelection', |
1952 | 1981 | function( event ) { |
1953 | 1982 | var context = $(this).data( 'wikiEditor-context' ); |
1954 | 1983 | $(this).eachAsync( { |
— | — | @@ -1959,7 +1988,7 @@ |
1960 | 1989 | } ); |
1961 | 1990 | } |
1962 | 1991 | ) |
1963 | | - .bind( 'mouseup scrollToPosition focus', |
| 1992 | + .bind( 'mouseup scrollToPosition focus keyup encapsulateSelection', |
1964 | 1993 | function( event ) { |
1965 | 1994 | var context = $(this).data( 'wikiEditor-context' ); |
1966 | 1995 | $(this).eachAsync( { |
Index: trunk/extensions/UsabilityInitiative/js/plugins.combined.min.js |
— | — | @@ -18,9 +18,11 @@ |
19 | 19 | var expires='';if(options.expires&&(typeof options.expires=='number'||options.expires.toUTCString)){var date;if(typeof options.expires=='number'){date=new Date();date.setTime(date.getTime()+(options.expires*24*60*60*1000));}else{date=options.expires;} |
20 | 20 | expires='; expires='+date.toUTCString();} |
21 | 21 | var path=options.path?'; path='+(options.path):'';var domain=options.domain?'; domain='+(options.domain):'';var secure=options.secure?'; secure':'';document.cookie=[name,'=',encodeURIComponent(value),expires,path,domain,secure].join('');}else{var cookieValue=null;if(document.cookie&&document.cookie!=''){var cookies=document.cookie.split(';');for(var i=0;i<cookies.length;i++){var cookie=jQuery.trim(cookies[i]);if(cookie.substring(0,name.length+1)==(name+'=')){cookieValue=decodeURIComponent(cookie.substring(name.length+1));break;}}} |
22 | | -return cookieValue;}};(function($){$.fn.extend({delayedBind:function(event,callback,timeout){return this.each(function(){var that=this;$(this).bind(event,function(){var timerID=$(this).data('_delayedBindTimerID-'+event);var args=arguments;if(typeof timerID!='undefined') |
23 | | -clearTimeout(timerID);timerID=setTimeout(function(){callback.apply(that,args);},timeout);$(this).data('_delayedBindTimerID-'+event,timerID);});});},delayedBindCancel:function(event){return this.each(function(){var timerID=$(this).data('_delayedBindTimerID-'+event);if(typeof timerID!='undefined') |
24 | | -clearTimeout(timerID);});}});})(jQuery);(function($){$.fn.namespaceSelector=function(defaultNS){if(typeof defaultNS=='undefined') |
| 22 | +return cookieValue;}};(function($){function encodeEvent(event){return event.replace(/-/g,'--').replace(/ /g,'-');} |
| 23 | +$.fn.extend({delayedBind:function(timeout,event,data,callback){var encEvent=encodeEvent(event);return this.each(function(){var that=this;if(!($(this).data('_delayedBindBound-'+encEvent+'-'+timeout))){$(this).data('_delayedBindBound-'+encEvent+'-'+timeout,true);$(this).bind(event,function(){var timerID=$(this).data('_delayedBindTimerID-'+encEvent+'-'+timeout);if(typeof timerID!='undefined') |
| 24 | +clearTimeout(timerID);timerID=setTimeout(function(){$(that).trigger('_delayedBind-'+encEvent+'-'+timeout);},timeout);$(this).data('_delayedBindTimerID-'+encEvent+'-'+timeout,timerID);});} |
| 25 | +$(this).bind('_delayedBind-'+encEvent+'-'+timeout,data,callback);});},delayedBindCancel:function(timeout,event){var encEvent=encodeEvent(event);return this.each(function(){var timerID=$(this).data('_delayedBindTimerID-'+encEvent+'-'+timeout);if(typeof timerID!='undefined') |
| 26 | +clearTimeout(timerID);});},delayedBindUnbind:function(timeout,event,callback){var encEvent=encodeEvent(event);return this.each(function(){$(this).unbind('_delayedBind-'+encEvent+'-'+timeout,callback);});}});})(jQuery);(function($){$.fn.namespaceSelector=function(defaultNS){if(typeof defaultNS=='undefined') |
25 | 27 | defaultNS=0;return this.each(function(){for(var id in wgFormattedNamespaces){var opt=$('<option />').attr('value',id).text(wgFormattedNamespaces[id]);if(id==defaultNS) |
26 | 28 | opt.attr('selected','selected');opt.appendTo($(this));}});};})(jQuery);(function($){$.suggestions={cancel:function(context){if(context.data.timerID!=null){clearTimeout(context.data.timerID);} |
27 | 29 | if(typeof context.config.cancel=='function'){context.config.cancel.call(context.data.$textbox);}},restore:function(context){context.data.$textbox.val(context.data.prevText);},update:function(context,delayed){function maybeFetch(){if(context.data.$textbox.val()!==context.data.prevText){context.data.prevText=context.data.$textbox.val();if(typeof context.config.fetch=='function'){context.config.fetch.call(context.data.$textbox,context.data.$textbox.val());}}} |
— | — | @@ -125,7 +127,7 @@ |
126 | 128 | 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);} |
127 | 129 | $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]));}} |
128 | 130 | $.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));}});}}};})(jQuery);(function($){$.wikiEditor.modules.toc={api:{},fn:{create:function(context,config){if('$toc'in context.modules){return;} |
129 | | -context.modules.$toc=$('<div></div>').addClass('wikiEditor-ui-toc').attr('id','wikiEditor-ui-toc');$.wikiEditor.modules.toc.fn.build(context,config);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').css('marginTop',-(context.$ui.find('.wikiEditor-ui-bottom').height()));context.$ui.find('.wikiEditor-ui-text').css(($('body.rtl').size()?'marginLeft':'marginRight'),'12em');$.wikiEditor.modules.toc.fn.build(context);$.wikiEditor.modules.toc.fn.update(context);context.$textarea.bind('keyup encapsulateSelection',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',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++;} |
| 131 | +context.modules.$toc=$('<div></div>').addClass('wikiEditor-ui-toc').attr('id','wikiEditor-ui-toc');$.wikiEditor.modules.toc.fn.build(context,config);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').css('marginTop',-(context.$ui.find('.wikiEditor-ui-bottom').height()));context.$ui.find('.wikiEditor-ui-text').css(($('body.rtl').size()?'marginLeft':'marginRight'),'12em');$.wikiEditor.modules.toc.fn.build(context);$.wikiEditor.modules.toc.fn.update(context);context.$textarea.delayedBind(1000,'keyup encapsulateSelection',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',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++;} |
130 | 132 | section=Math.max(0,section);} |
131 | 133 | context.modules.$toc.find('a.section-'+section).addClass('currentSelection');}},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;} |
132 | 134 | sections[sections.length]=outline[i];}else if(outline[i].nLevel<level){break;}} |