r73037 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r73036‎ | r73037 | r73038 >
Date:01:31, 15 September 2010
Author:tparscal
Status:resolved (Comments)
Tags:
Comment:
Ported JavaScript from UsabiltyIntiative/Vector
Modified paths:
  • /trunk/extensions/Vector/Vector.hooks.php (modified) (history)
  • /trunk/extensions/Vector/modules/vector.collapsibleNav.css (added) (history)
  • /trunk/extensions/Vector/modules/vector.collapsibleNav.js (added) (history)
  • /trunk/extensions/Vector/modules/vector.collapsibleTabs.js (added) (history)
  • /trunk/extensions/Vector/modules/vector.editWarning.js (added) (history)
  • /trunk/extensions/Vector/modules/vector.expandableSearch.css (added) (history)
  • /trunk/extensions/Vector/modules/vector.expandableSearch.js (added) (history)
  • /trunk/extensions/Vector/modules/vector.footerCleanup.css (added) (history)
  • /trunk/extensions/Vector/modules/vector.footerCleanup.js (added) (history)
  • /trunk/extensions/Vector/modules/vector.simpleSearch.js (added) (history)

Diff [purge]

Index: trunk/extensions/Vector/modules/vector.collapsibleTabs.js
@@ -0,0 +1,77 @@
 2+/*
 3+ * Collapsible tabs for Vector
 4+ */
 5+$(document).ready( function() {
 6+ var rtl = $( 'body' ).is( '.rtl' );
 7+
 8+ // Overloading the moveToCollapsed function to animate the transition
 9+ $.collapsibleTabs.moveToCollapsed = function( ele ) {
 10+ var $moving = $( ele );
 11+ $.collapsibleTabs.getSettings( $( $.collapsibleTabs.getSettings( $moving ).expandedContainer ) ).shifting = true;
 12+ var data = $.collapsibleTabs.getSettings( $moving );
 13+ // Remove the element from where it's at and put it in the dropdown menu
 14+ var target = data.collapsedContainer;
 15+ $moving.css( "position", "relative" )
 16+ .css( ( rtl ? 'left' : 'right' ), 0 )
 17+ .animate( { width: '1px' }, "normal", function() {
 18+ $( this ).hide();
 19+ // add the placeholder
 20+ $( '<span class="placeholder" style="display:none;"></span>' ).insertAfter( this );
 21+ $( this ).remove().prependTo( target ).data( 'collapsibleTabsSettings', data );
 22+ $( this ).attr( 'style', 'display:list-item;' );
 23+ $.collapsibleTabs.getSettings( $( $.collapsibleTabs.getSettings( $( ele ) ).expandedContainer ) )
 24+ .shifting = false;
 25+ $.collapsibleTabs.handleResize();
 26+ } );
 27+ };
 28+
 29+ // Overloading the moveToExpanded function to animate the transition
 30+ $.collapsibleTabs.moveToExpanded = function( ele ) {
 31+ var $moving = $( ele );
 32+ $.collapsibleTabs.getSettings( $( $.collapsibleTabs.getSettings( $moving ).expandedContainer ) ).shifting = true;
 33+ var data = $.collapsibleTabs.getSettings( $moving );
 34+ // grab the next appearing placeholder so we can use it for replacing
 35+ var $target = $( data.expandedContainer ).find( 'span.placeholder:first' );
 36+ var expandedWidth = data.expandedWidth;
 37+ $moving.css( "position", "relative" ).css( ( rtl ? 'right' : 'left' ), 0 ).css( 'width', '1px' );
 38+ $target.replaceWith( $moving.remove().css( 'width', '1px' ).data( 'collapsibleTabsSettings', data )
 39+ .animate( { width: expandedWidth+"px" }, "normal", function() {
 40+ $( this ).attr( 'style', 'display:block;' );
 41+ $.collapsibleTabs.getSettings( $( $.collapsibleTabs.getSettings( $moving ).expandedContainer ) )
 42+ .shifting = false;
 43+ $.collapsibleTabs.handleResize();
 44+ } ) );
 45+ };
 46+
 47+ // Bind callback functions to animate our drop down menu in and out
 48+ // and then call the collapsibleTabs function on the menu
 49+ $( '#p-views ul' ).bind( "beforeTabCollapse", function() {
 50+ if( $( '#p-cactions' ).css( 'display' ) == 'none' )
 51+ $( "#p-cactions" ).addClass( "filledPortlet" ).removeClass( "emptyPortlet" )
 52+ .find( 'h5' ).css( 'width','1px' ).animate( { 'width':'26px' }, 390 );
 53+ }).bind( "beforeTabExpand", function() {
 54+ if( $( '#p-cactions li' ).length == 1 )
 55+ $( "#p-cactions h5" ).animate( { 'width':'1px' }, 370, function() {
 56+ $( this ).attr( 'style', '' ).parent().addClass( "emptyPortlet" ).removeClass( "filledPortlet" );
 57+ });
 58+ }).collapsibleTabs( {
 59+ expandCondition: function( eleWidth ) {
 60+ if( rtl ){
 61+ return ( $( '#right-navigation' ).position().left + $( '#right-navigation' ).width() + 1 )
 62+ < ( $( '#left-navigation' ).position().left - eleWidth );
 63+ } else {
 64+ return ( $( '#left-navigation' ).position().left + $( '#left-navigation' ).width() + 1 )
 65+ < ( $( '#right-navigation' ).position().left - eleWidth );
 66+ }
 67+ },
 68+ collapseCondition: function() {
 69+ if( rtl ) {
 70+ return ( $( '#right-navigation' ).position().left + $( '#right-navigation' ).width() )
 71+ > $( '#left-navigation' ).position().left;
 72+ } else {
 73+ return ( $( '#left-navigation' ).position().left + $( '#left-navigation' ).width() )
 74+ > $( '#right-navigation' ).position().left;
 75+ }
 76+ }
 77+ } );
 78+} );
Property changes on: trunk/extensions/Vector/modules/vector.collapsibleTabs.js
___________________________________________________________________
Added: svn:eol-style
179 + native
Index: trunk/extensions/Vector/modules/vector.expandableSearch.css
@@ -0,0 +1,6 @@
 2+.expandableField {
 3+ display: block;
 4+}
 5+#simpleSearch {
 6+ overflow: auto;
 7+}
Property changes on: trunk/extensions/Vector/modules/vector.expandableSearch.css
___________________________________________________________________
Added: svn:eol-style
18 + native
Index: trunk/extensions/Vector/modules/vector.footerCleanup.js
@@ -0,0 +1,68 @@
 2+/*
 3+ * Footer cleanup for Vector
 4+ */
 5+$( document ).ready( function() {
 6+ $( '#editpage-copywarn' )
 7+ .add( '.editOptions' )
 8+ .wrapAll( '<div id="editpage-bottom"></div>' );
 9+ $( '#wpSummary' )
 10+ .data( 'hint',
 11+ $( '#wpSummaryLabel span small' )
 12+ .remove()
 13+ .text()
 14+ // FIXME - Not a long-term solution. This change should be done in the message itself
 15+ .replace( /\)|\(/g, '' )
 16+ )
 17+ .change( function() {
 18+ if ( $( this ).val().length == 0 ) {
 19+ $( this )
 20+ .addClass( 'inline-hint' )
 21+ .val( $( this ).data( 'hint' ) );
 22+ } else {
 23+ $( this ).removeClass( 'inline-hint' );
 24+ }
 25+ } )
 26+ .focus( function() {
 27+ if ( $( this ).val() == $( this ).data( 'hint' ) ) {
 28+ $( this )
 29+ .removeClass( 'inline-hint' )
 30+ .val( "" );
 31+ }
 32+ })
 33+ .blur( function() { $( this ).trigger( 'change' ); } )
 34+ .trigger( 'change' );
 35+ $( '#wpSummary' )
 36+ .add( '.editCheckboxes' )
 37+ .wrapAll( '<div id="editpage-summary-fields"></div>' );
 38+
 39+ $( '#editpage-specialchars' ).remove();
 40+
 41+ // transclusions
 42+ // FIXME - bad CSS styling here with double class selectors. Should address here.
 43+ var transclusionCount = $( '.templatesUsed ul li' ).size();
 44+ $( '.templatesUsed ul' )
 45+ .wrap( '<div id="transclusions-list" class="collapsible-list collapsed"></div>' )
 46+ .parent()
 47+ // FIXME: i18n, remove link from message and let community add link to transclusion page if it exists
 48+ .prepend( '<label>This page contains <a href="http://en.wikipedia.org/wiki/transclusion">transclusions</a> of <strong>'
 49+ + transclusionCount
 50+ + '</strong> other pages.</label>' );
 51+ $( '.mw-templatesUsedExplanation' ).remove();
 52+
 53+ $( '.collapsible-list label' )
 54+ .click( function() {
 55+ $( this )
 56+ .parent()
 57+ .toggleClass( 'expanded' )
 58+ .toggleClass( 'collapsed' )
 59+ .find( 'ul' )
 60+ .slideToggle( 'fast' );
 61+ return false;
 62+ })
 63+ .trigger( 'click' );
 64+ $( '#wpPreview, #wpDiff, .editHelp, #editpage-specialchars' )
 65+ .remove();
 66+ $( '#mw-editform-cancel' )
 67+ .remove()
 68+ .appendTo( '.editButtons' );
 69+} );
Property changes on: trunk/extensions/Vector/modules/vector.footerCleanup.js
___________________________________________________________________
Added: svn:eol-style
170 + native
Index: trunk/extensions/Vector/modules/vector.expandableSearch.js
@@ -0,0 +1,70 @@
 2+/*
 3+ * Expandable search for Vector
 4+ */
 5+$( document ).ready( function() {
 6+
 7+ /* Browser Support */
 8+
 9+ var map = {
 10+ // Left-to-right languages
 11+ 'ltr': {
 12+ // Collapsible Nav is broken in Opera < 9.6 and Konqueror < 4
 13+ 'msie': [['>=', 8]],
 14+ 'blackberry': false,
 15+ 'ipod': false,
 16+ 'iphone': false,
 17+ 'ps3': false
 18+ },
 19+ // Right-to-left languages
 20+ 'rtl': {
 21+ 'msie': [['>=', 8]],
 22+ 'blackberry': false,
 23+ 'ipod': false,
 24+ 'iphone': false,
 25+ 'ps3': false
 26+ }
 27+ };
 28+ if ( !$.client.test( map ) ) {
 29+ return true;
 30+ }
 31+
 32+ $( '#searchInput' )
 33+ .expandableField( {
 34+ 'beforeExpand': function( context ) {
 35+ // animate the containers border
 36+ $( this )
 37+ .parent()
 38+ .animate( {
 39+ 'borderTopColor': '#a0d8ff',
 40+ 'borderLeftColor': '#a0d8ff',
 41+ 'borderRightColor': '#a0d8ff',
 42+ 'borderBottomColor': '#a0d8ff' }, 'fast' );
 43+ },
 44+ 'beforeCondense': function( context ) {
 45+ // animate the containers border
 46+ $( this )
 47+ .parent()
 48+ .animate( {
 49+ 'borderTopColor': '#aaaaaa',
 50+ 'borderLeftColor': '#aaaaaa',
 51+ 'borderRightColor': '#aaaaaa',
 52+ 'borderBottomColor': '#aaaaaa' }, 'fast' );
 53+ },
 54+ 'afterExpand': function( context ) {
 55+ //trigger the collapsible tabs resize handler
 56+ if ( typeof $.collapsibleTabs != 'undefined' ){
 57+ $.collapsibleTabs.handleResize();
 58+ }
 59+ },
 60+ 'afterCondense': function( context ) {
 61+ //trigger the collapsible tabs resize handler
 62+ if ( typeof $.collapsibleTabs != 'undefined' ){
 63+ $.collapsibleTabs.handleResize();
 64+ }
 65+ },
 66+ 'expandToLeft': ! $( 'body' ).is( '.rtl' )
 67+ } )
 68+ .css( 'float', $( 'body' ).is( '.rtl' ) ? 'right' : 'left' )
 69+ .siblings( 'button' )
 70+ .css( 'float', $( 'body' ).is( '.rtl' ) ? 'right' : 'left' );
 71+} );
Property changes on: trunk/extensions/Vector/modules/vector.expandableSearch.js
___________________________________________________________________
Added: svn:eol-style
172 + native
Index: trunk/extensions/Vector/modules/vector.collapsibleNav.css
@@ -0,0 +1,68 @@
 2+/* Prototype code to show collapsing left nav options */
 3+#mw-panel.collapsible-nav div.portal {
 4+ background-image:url(../images/vector/collapsibleNav/portal-break.png?1);
 5+ background-position:left top;
 6+ background-repeat:no-repeat;
 7+ padding: 0.25em 0 !important;
 8+ margin: -11px 9px 10px 11px;
 9+}
 10+body.rtl #mw-panel.collapsible-nav div.portal {
 11+ background-position: right top;
 12+ margin: -11px 11px 10px 9px;
 13+}
 14+#mw-panel.collapsible-nav div.portal h5 {
 15+ color: #4D4D4D;
 16+ font-weight: normal;
 17+ background: url(../images/vector/collapsibleNav/arrow-down.png?1) 0 50% no-repeat;
 18+ padding: 4px 0 3px 1.5em;
 19+ margin-bottom: 0px;
 20+}
 21+body.rtl #mw-panel.collapsible-nav div.portal h5 {
 22+ background: url(../images/vector/collapsibleNav/arrow-down.png?1) 100% 50% no-repeat;
 23+ padding: 4px 1.5em 3px 0;
 24+}
 25+#mw-panel.collapsible-nav div.collapsed h5 {
 26+ color: #0645AD;
 27+ background: url(../images/vector/collapsibleNav/arrow-right.png?1) 0 50% no-repeat;
 28+ margin-bottom: 0px;
 29+}
 30+body.rtl #mw-panel.collapsible-nav div.collapsed h5 {
 31+ background: url(../images/vector/collapsibleNav/arrow-left.png?1) 100% 50% no-repeat;
 32+}
 33+#mw-panel.collapsible-nav div h5:hover {
 34+ cursor: pointer;
 35+ text-decoration: none;
 36+}
 37+#mw-panel.collapsible-nav div.collapsed h5:hover {
 38+ text-decoration: underline;
 39+}
 40+#mw-panel.collapsible-nav div.portal div.body {
 41+ background: none !important;
 42+ padding-top: 0px;
 43+ display: none;
 44+}
 45+#mw-panel.collapsible-nav div.persistent div.body {
 46+ display: block;
 47+}
 48+#mw-panel.collapsible-nav div.first h5 {
 49+ display: none;
 50+}
 51+#mw-panel.collapsible-nav div.persistent h5 {
 52+ background: none !important;
 53+ padding-left: 0.7em;
 54+ cursor: default;
 55+}
 56+#mw-panel.collapsible-nav div.portal div.body ul li {
 57+ padding: 0.25em 0;
 58+}
 59+#mw-panel.collapsible-nav div.first {
 60+ background-image: none;
 61+ margin-top: 0px;
 62+}
 63+#mw-panel.collapsible-nav div.persistent div.body {
 64+ margin-left: 0.5em;
 65+}
 66+body.rtl #mw-panel.collapsible-nav div.persistent div.body {
 67+ margin-left: 0;
 68+ margin-right: 0.5em;
 69+}
Property changes on: trunk/extensions/Vector/modules/vector.collapsibleNav.css
___________________________________________________________________
Added: svn:eol-style
170 + native
Index: trunk/extensions/Vector/modules/vector.editWarning.js
@@ -0,0 +1,69 @@
 2+/*
 3+ * Edit warning for Vector
 4+ */
 5+$(document).ready( function() {
 6+ // Check if EditWarning is enabled and if we need it
 7+ if ( $( '#wpTextbox1' ).size() == 0 ) {
 8+ return true;
 9+ }
 10+ // Get the original values of some form elements
 11+ $( '#wpTextbox1, #wpSummary' ).each( function() {
 12+ $(this).data( 'origtext', $(this).val() );
 13+ });
 14+ // Attach our own handler for onbeforeunload which respects the current one
 15+ var fallbackWindowOnBeforeUnload = window.onbeforeunload;
 16+ var ourWindowOnBeforeUnload = function() {
 17+ var fallbackResult = undefined;
 18+ var retval = undefined;
 19+ var thisFunc = arguments.callee;
 20+ // Check if someone already set on onbeforeunload hook
 21+ if ( fallbackWindowOnBeforeUnload ) {
 22+ // Get the result of their onbeforeunload hook
 23+ fallbackResult = fallbackWindowOnBeforeUnload();
 24+ }
 25+ // Check if their onbeforeunload hook returned something
 26+ if ( fallbackResult !== undefined ) {
 27+ // Exit here, returning their message
 28+ retval = fallbackResult;
 29+ } else {
 30+ // Check if the current values of some form elements are the same as
 31+ // the original values
 32+ if (
 33+ wgAction == 'submit' ||
 34+ $( '#wpTextbox1' ).data( 'origtext' ) != $( '#wpTextbox1' ).val() ||
 35+ $( '#wpSummary' ).data( 'origtext' ) != $( '#wpSummary' ).val()
 36+ ) {
 37+ // Return our message
 38+ retval = mw.usability.getMsg( 'vector-editwarning-warning' );
 39+ }
 40+ }
 41+
 42+ // Unset the onbeforeunload handler so we don't break page caching in Firefox
 43+ window.onbeforeunload = null;
 44+ if ( retval !== undefined ) {
 45+ // ...but if the user chooses not to leave the page, we need to rebind it
 46+ setTimeout( function() {
 47+ window.onbeforeunload = thisFunc;
 48+ } );
 49+ return retval;
 50+ }
 51+ };
 52+ var pageShowHandler = function() {
 53+ // Re-add onbeforeunload handler
 54+ window.onbeforeunload = ourWindowOnBeforeUnload;
 55+ };
 56+ pageShowHandler();
 57+ if ( window.addEventListener ) {
 58+ window.addEventListener('pageshow', pageShowHandler, false);
 59+ } else if ( window.attachEvent ) {
 60+ window.attachEvent( 'pageshow', pageShowHandler );
 61+ }
 62+
 63+ // Add form submission handler
 64+ $( 'form' ).submit( function() {
 65+ // Restore whatever previous onbeforeload hook existed
 66+ window.onbeforeunload = fallbackWindowOnBeforeUnload;
 67+ });
 68+});
 69+//Global storage of fallback for onbeforeunload hook
 70+var fallbackWindowOnBeforeUnload = null;
Property changes on: trunk/extensions/Vector/modules/vector.editWarning.js
___________________________________________________________________
Added: svn:eol-style
171 + native
Index: trunk/extensions/Vector/modules/vector.collapsibleNav.js
@@ -0,0 +1,226 @@
 2+/*
 3+ * Collapisble navigation for Vector
 4+ */
 5+$( document ).ready( function() {
 6+
 7+ /* Browser Support */
 8+
 9+ var map = {
 10+ // Left-to-right languages
 11+ 'ltr': {
 12+ // Collapsible Nav is broken in Opera < 9.6 and Konqueror < 4
 13+ 'msie': [['>=', 7]],
 14+ 'opera': [['>=', 9.6]],
 15+ 'konqueror': [['>=', 4.0]],
 16+ 'blackberry': false,
 17+ 'ipod': false,
 18+ 'iphone': false,
 19+ 'ps3': false
 20+ },
 21+ // Right-to-left languages
 22+ 'rtl': {
 23+ 'msie': [['>=', 7]],
 24+ 'opera': [['>=', 9.6]],
 25+ 'konqueror': [['>=', 4.0]],
 26+ 'blackberry': false,
 27+ 'ipod': false,
 28+ 'iphone': false,
 29+ 'ps3': false
 30+ }
 31+ };
 32+ if ( !$.client.test( map ) ) {
 33+ return true;
 34+ }
 35+
 36+ /* Bucket Testing */
 37+
 38+ // Fallback to old version
 39+ var version = 1;
 40+ // Allow new version override
 41+ if ( mediaWiki.config.get( 'wgCollapsibleNavForceNewVersion' ) ) {
 42+ version = 2;
 43+ } else {
 44+ // Make bucket testing optional
 45+ if ( mediaWiki.config.get( 'wgCollapsibleNavBucketTest' ) ) {
 46+ // This is be determined randomly, and then stored in a cookie
 47+ version = $.cookie( 'vector-nav-pref-version' );
 48+ // If the cookie didn't exist, or the value is out of range, generate a new one and save it
 49+ if ( version == null ) {
 50+ // 50% of the people will get the new version
 51+ version = Math.round( Math.random() + 1 );
 52+ $.cookie( 'vector-nav-pref-version', version, { 'expires': 30, 'path': '/' } );
 53+ }
 54+ }
 55+ }
 56+
 57+ /* Special Language Portal Handling */
 58+
 59+ // Language portal splitting feature (if it's turned on)
 60+ if ( version == 2 ) {
 61+ // How many links to show in the primary languages portal
 62+ var limit = 5;
 63+ // How many links there must be in the secondary portal to justify having a secondary portal
 64+ var threshold = 3;
 65+ // Make the interwiki language links list a secondary list, and create a new list before it as primary list
 66+ $( '#p-lang ul' ).addClass( 'secondary' ).before( '<ul class="primary"></ul>' );
 67+ // This is a list of languages in order of Wikipedia project size. This is the lowest fallback for choosing
 68+ // which links to show in the primary list. Ideally the browser's accept-language headers should steer this
 69+ // list, and we should fallback on a site configured (MediaWiki:Common.js) list of prefered languages.
 70+ var languages = [
 71+ 'en', 'fr', 'de', 'es', 'pt', 'it', 'ru', 'ja', 'nl', 'pl', 'zh', 'sv', 'ar', 'tr', 'uk', 'fi', 'no', 'ca',
 72+ 'ro', 'hu', 'ksh', 'id', 'he', 'cs', 'vi', 'ko', 'sr', 'fa', 'da', 'eo', 'sk', 'th', 'lt', 'vo', 'bg',
 73+ 'sl', 'hr', 'hi', 'et', 'mk', 'simple', 'new', 'ms', 'nn', 'gl', 'el', 'eu', 'ka', 'tl', 'bn', 'lv', 'ml',
 74+ 'bs', 'te', 'la', 'az', 'sh', 'war', 'br', 'is', 'mr', 'be-x-old', 'sq', 'cy', 'lb', 'ta', 'zh-classical',
 75+ 'an', 'jv', 'ht', 'oc', 'bpy', 'ceb', 'ur', 'zh-yue', 'pms', 'scn', 'be', 'roa-rup', 'qu', 'af', 'sw',
 76+ 'nds', 'fy', 'lmo', 'wa', 'ku', 'hy', 'su', 'yi', 'io', 'os', 'ga', 'ast', 'nap', 'vec', 'gu', 'cv',
 77+ 'bat-smg', 'kn', 'uz', 'zh-min-nan', 'si', 'als', 'yo', 'li', 'gan', 'arz', 'sah', 'tt', 'bar', 'gd', 'tg',
 78+ 'kk', 'pam', 'hsb', 'roa-tara', 'nah', 'mn', 'vls', 'gv', 'mi', 'am', 'ia', 'co', 'ne', 'fo', 'nds-nl',
 79+ 'glk', 'mt', 'ang', 'wuu', 'dv', 'km', 'sco', 'bcl', 'mg', 'my', 'diq', 'tk', 'szl', 'ug', 'fiu-vro', 'sc',
 80+ 'rm', 'nrm', 'ps', 'nv', 'hif', 'bo', 'se', 'sa', 'pnb', 'map-bms', 'lad', 'lij', 'crh', 'fur', 'kw', 'to',
 81+ 'pa', 'jbo', 'ba', 'ilo', 'csb', 'wo', 'xal', 'krc', 'ckb', 'pag', 'ln', 'frp', 'mzn', 'ce', 'nov', 'kv',
 82+ 'eml', 'gn', 'ky', 'pdc', 'lo', 'haw', 'mhr', 'dsb', 'stq', 'tpi', 'arc', 'hak', 'ie', 'so', 'bh', 'ext',
 83+ 'mwl', 'sd', 'ig', 'myv', 'ay', 'iu', 'na', 'cu', 'pi', 'kl', 'ty', 'lbe', 'ab', 'got', 'sm', 'as', 'mo',
 84+ 'ee', 'zea', 'av', 'ace', 'kg', 'bm', 'cdo', 'cbk-zam', 'kab', 'om', 'chr', 'pap', 'udm', 'ks', 'zu', 'rmy',
 85+ 'cr', 'ch', 'st', 'ik', 'mdf', 'kaa', 'aa', 'fj', 'srn', 'tet', 'or', 'pnt', 'bug', 'ss', 'ts', 'pcd',
 86+ 'pih', 'za', 'sg', 'lg', 'bxr', 'xh', 'ak', 'ha', 'bi', 've', 'tn', 'ff', 'dz', 'ti', 'ki', 'ny', 'rw',
 87+ 'chy', 'tw', 'sn', 'tum', 'ng', 'rn', 'mh', 'ii', 'cho', 'hz', 'kr', 'ho', 'mus', 'kj'
 88+ ];
 89+ // If the user has an Accept-Language cookie, use it. Otherwise, set it asynchronously but keep the default
 90+ // behavior for this page view.
 91+ var acceptLangCookie = $.cookie( 'accept-language' );
 92+ if ( acceptLangCookie != null ) {
 93+ // Put the user's accepted languages before the list ordered by wiki size
 94+ if ( acceptLangCookie != '' ) {
 95+ languages = acceptLangCookie.split( ',' ).concat( languages );
 96+ }
 97+ } else {
 98+ $.getJSON(
 99+ wgScriptPath + '/api.php?action=query&meta=userinfo&uiprop=acceptlang&format=json',
 100+ function( data ) {
 101+ var langs = [];
 102+ if (
 103+ typeof data.query != 'undefined' &&
 104+ typeof data.query.userinfo != 'undefined' &&
 105+ typeof data.query.userinfo.acceptlang != 'undefined'
 106+ ) {
 107+ for ( var j = 0; j < data.query.userinfo.acceptlang.length; j++ ) {
 108+ if ( data.query.userinfo.acceptlang[j].q != 0 ) {
 109+ langs.push( data.query.userinfo.acceptlang[j]['*'] );
 110+ }
 111+ }
 112+ }
 113+ $.cookie( 'accept-language', langs.join( ',' ), { 'path': '/', 'expires': 30 } );
 114+ }
 115+ );
 116+ }
 117+ // Shortcuts to the two lists
 118+ var $primary = $( '#p-lang ul.primary' );
 119+ var $secondary = $( '#p-lang ul.secondary' );
 120+ // Adjust the limit based on the threshold
 121+ if ( $secondary.children().length < limit + threshold ) {
 122+ limit += threshold;
 123+ }
 124+ // Move up to 5 of the links into the primary list, based on the priorities set forth in the languages list
 125+ var count = 0;
 126+ for ( var i = 0; i < languages.length; i++ ) {
 127+ var $link = $secondary.find( '.interwiki-' + languages[i] );
 128+ if ( $link.length ) {
 129+ if ( count++ < limit ) {
 130+ $link.appendTo( $primary );
 131+ } else {
 132+ break;
 133+ }
 134+ }
 135+ }
 136+ // If there's still links in the secondary list and we havn't filled the primary list to it's limit yet, move
 137+ // links into the primary list in order of appearance
 138+ if ( count < limit ) {
 139+ $secondary.children().each( function() {
 140+ if ( count++ < limit ) {
 141+ $(this).appendTo( $primary );
 142+ } else {
 143+ return false;
 144+ }
 145+ } );
 146+ }
 147+ // Hide the more portal if it's now empty, otherwise make the list into it's very own portal
 148+ if ( $secondary.children().length == 0 ) {
 149+ $secondary.remove();
 150+ } else {
 151+ $( '#p-lang' ).after( '<div id="p-lang-more" class="portal"><h5></h5><div class="body"></div></div>' );
 152+ $( '#p-lang-more h5' ).text( mw.usability.getMsg( 'vector-collapsiblenav-more' ) );
 153+ $secondary.appendTo( $( '#p-lang-more div.body' ) );
 154+ }
 155+ // Always show the primary interwiki language portal
 156+ $( '#p-lang' ).addClass( 'persistent' );
 157+ }
 158+
 159+ /* General Portal Modification */
 160+
 161+ // Always show the first portal
 162+ $( '#mw-panel > div.portal:first' ).addClass( 'first persistent' );
 163+ // Apply a class to the entire panel to activate styles
 164+ $( '#mw-panel' ).addClass( 'collapsible-nav' );
 165+ // Use cookie data to restore preferences of what to show and hide
 166+ $( '#mw-panel > div.portal:not(.persistent)' )
 167+ .each( function( i ) {
 168+ var id = $(this).attr( 'id' );
 169+ var state = $.cookie( 'vector-nav-' + id );
 170+ // In the case that we are not showing the new version, let's show the languages by default
 171+ if (
 172+ state == 'true' ||
 173+ ( state == null && i < 1 ) ||
 174+ ( state == null && version == 1 && id == 'p-lang' )
 175+ ) {
 176+ $(this)
 177+ .addClass( 'expanded' )
 178+ .find( 'div.body' )
 179+ .show();
 180+ } else {
 181+ $(this).addClass( 'collapsed' );
 182+ }
 183+ // Re-save cookie
 184+ if ( state != null ) {
 185+ $.cookie( 'vector-nav-' + $(this).attr( 'id' ), state, { 'expires': 30, 'path': '/' } );
 186+ }
 187+ } );
 188+ // Use the same function for all navigation headings - don't repeat yourself
 189+ function toggle( $element ) {
 190+ $.cookie(
 191+ 'vector-nav-' + $element.parent().attr( 'id' ),
 192+ $element.parent().is( '.collapsed' ),
 193+ { 'expires': 30, 'path': '/' }
 194+ );
 195+ $element
 196+ .parent()
 197+ .toggleClass( 'expanded' )
 198+ .toggleClass( 'collapsed' )
 199+ .find( 'div.body' )
 200+ .slideToggle( 'fast' );
 201+ }
 202+
 203+ /* Tab Indexing */
 204+
 205+ var $headings = $( '#mw-panel > div.portal:not(.persistent) > h5' );
 206+ // Get the highest tab index
 207+ var tabIndex = mw.usability.getMaxTabIndex() + 1;
 208+ // Fix the search not having a tabindex
 209+ $( '#searchInput' ).attr( 'tabindex', tabIndex++ );
 210+ // Make it keyboard accessible
 211+ $headings.each( function() {
 212+ $(this).attr( 'tabindex', tabIndex++ );
 213+ } );
 214+ // Toggle the selected menu's class and expand or collapse the menu
 215+ $headings
 216+ // Make the space and enter keys act as a click
 217+ .keydown( function( event ) {
 218+ if ( event.which == 13 /* Enter */ || event.which == 32 /* Space */ ) {
 219+ toggle( $(this) );
 220+ }
 221+ } )
 222+ .mousedown( function() {
 223+ toggle( $(this) );
 224+ $(this).blur();
 225+ return false;
 226+ } );
 227+} );
Property changes on: trunk/extensions/Vector/modules/vector.collapsibleNav.js
___________________________________________________________________
Added: svn:eol-style
1228 + native
Index: trunk/extensions/Vector/modules/vector.simpleSearch.js
@@ -0,0 +1,142 @@
 2+/* JavaScript for SimpleSearch extension */
 3+
 4+// Disable mwsuggest.js's effect on searchInput
 5+if ( typeof os_autoload_inputs !== 'undefined' && os_autoload_forms !== 'undefined' ) {
 6+ os_autoload_inputs = [];
 7+ os_autoload_forms = [];
 8+}
 9+
 10+$( document ).ready( function() {
 11+
 12+ var mod = {
 13+ 'browsers': {
 14+ // Left-to-right languages
 15+ 'ltr': {
 16+ // SimpleSearch is broken in Opera < 9.6
 17+ 'opera': [['>=', 9.6]],
 18+ 'docomo': false,
 19+ 'blackberry': false,
 20+ 'ipod': false,
 21+ 'iphone': false
 22+ },
 23+ // Right-to-left languages
 24+ 'rtl': {
 25+ 'opera': [['>=', 9.6]],
 26+ 'docomo': false,
 27+ 'blackberry': false,
 28+ 'ipod': false,
 29+ 'iphone': false
 30+ }
 31+ }
 32+ };
 33+ if ( !$.wikiEditor.isSupported( mod ) ) {
 34+ return true;
 35+ }
 36+
 37+ // Placeholder text
 38+ // if the placeholder attribute is supported, use it
 39+ if ( 'placeholder' in document.createElement( 'input' ) ) {
 40+ $( 'div#simpleSearch > input#searchInput' )
 41+ .attr( 'placeholder', mw.usability.getMsg( 'vector-simplesearch-search' ) );
 42+ } else {
 43+ $( 'div#simpleSearch > input#searchInput' )
 44+ .each( function() {
 45+ var $input = $( this );
 46+ $input
 47+ .bind( 'blur', function() {
 48+ if ( $input.val().length == 0 ) {
 49+ $input
 50+ .val( mw.usability.getMsg( 'vector-simplesearch-search' ) )
 51+ .addClass( 'placeholder' );
 52+ }
 53+ } )
 54+ .bind( 'focus', function() {
 55+ if ( $input.hasClass( 'placeholder' ) ) {
 56+ $input.val( '' ).removeClass( 'placeholder' );
 57+ }
 58+ } )
 59+ .parents( 'form' )
 60+ .bind( 'submit', function() {
 61+ $input.trigger( 'focus' );
 62+ } );
 63+ if ( $input.val() == '' ) {
 64+ $input.trigger( 'blur' );
 65+ }
 66+ } );
 67+ }
 68+ $( '#searchInput, #searchInput2, #powerSearchText, #searchText' ).suggestions( {
 69+ fetch: function( query ) {
 70+ var $this = $(this);
 71+ var request = $.ajax( {
 72+ url: wgScriptPath + '/api.php',
 73+ data: {
 74+ 'action': 'opensearch',
 75+ 'search': query,
 76+ 'namespace': 0,
 77+ 'suggest': ''
 78+ },
 79+ dataType: 'json',
 80+ success: function( data ) {
 81+ $this.suggestions( 'suggestions', data[1] );
 82+ }
 83+ });
 84+ $(this).data( 'request', request );
 85+ },
 86+ cancel: function () {
 87+ var request = $(this).data( 'request' );
 88+ // If the delay setting has caused the fetch to have not even happend yet, the request object will
 89+ // have never been set
 90+ if ( request && typeof request.abort == 'function' ) {
 91+ request.abort();
 92+ $(this).removeData( 'request' );
 93+ }
 94+ },
 95+ result: {
 96+ select: function( $textbox ) {
 97+ $textbox.closest( 'form' ).submit();
 98+ }
 99+ },
 100+ delay: 120,
 101+ positionFromLeft: $( 'body' ).is( '.rtl' ),
 102+ highlightInput: true
 103+ } )
 104+ .bind( 'paste cut', function( e ) {
 105+ // make sure paste and cut events from the mouse trigger the keypress handler and cause the suggestions to update
 106+ $( this ).trigger( 'keypress' );
 107+ } );
 108+ $( '#searchInput' ).suggestions( {
 109+ result: {
 110+ select: function( $textbox ) {
 111+ $textbox.closest( 'form' ).submit();
 112+ }
 113+ },
 114+ special: {
 115+ render: function( query ) {
 116+ if ( $(this).children().size() == 0 ) {
 117+ $(this).show()
 118+ $label = $( '<div />' )
 119+ .addClass( 'special-label' )
 120+ .text( mw.usability.getMsg( 'vector-simplesearch-containing' ) )
 121+ .appendTo( $(this) );
 122+ $query = $( '<div />' )
 123+ .addClass( 'special-query' )
 124+ .text( query )
 125+ .appendTo( $(this) );
 126+ $query.autoEllipsis();
 127+ } else {
 128+ $(this).find( '.special-query' )
 129+ .empty()
 130+ .text( query )
 131+ .autoEllipsis();
 132+ }
 133+ },
 134+ select: function( $textbox ) {
 135+ $textbox.closest( 'form' ).append(
 136+ $( '<input />' ).attr( { 'type': 'hidden', 'name': 'fulltext', 'value': 1 } )
 137+ );
 138+ $textbox.closest( 'form' ).submit();
 139+ }
 140+ },
 141+ $region: $( '#simpleSearch' )
 142+ } );
 143+});
Property changes on: trunk/extensions/Vector/modules/vector.simpleSearch.js
___________________________________________________________________
Added: svn:eol-style
1144 + native
Index: trunk/extensions/Vector/modules/vector.footerCleanup.css
@@ -0,0 +1,85 @@
 2+/* Prototype code to show collapsing left nav options */
 3+#editpage-bottom {
 4+ background-color: #F3F3F3;
 5+ border: 1px solid silver;
 6+ border-top: none;
 7+ padding: 20px 170px 20px 170px;
 8+ margin-right: -2px;
 9+}
 10+
 11+#editpage-bottom input.inline-hint {
 12+ color: #999999;
 13+ font-style: italic;
 14+}
 15+.collapsible-list {
 16+ border-top: 1px solid silver;
 17+ border-bottom: 1px solid silver;
 18+}
 19+.collapsible-list {
 20+ border-top: 1px solid silver;
 21+ border-bottom: 1px solid silver;
 22+ padding: 3px 2px;
 23+}
 24+.collapsible-list ul {
 25+ display: block;
 26+ padding: 0 0 0 14px;
 27+}
 28+.collapsible-list.collapsed label {
 29+ background: url(../images/vector/collapsibleNav/arrow-down.png?1) 0 50% no-repeat;
 30+ padding: 4px 0 3px 1.5em;
 31+ margin-bottom: 0px;
 32+}
 33+.collapsible-list.expanded label {
 34+ background: url(../images/vector/collapsibleNav/arrow-right.png?1) 0 50% no-repeat;
 35+ padding: 4px 0 3px 1.5em;
 36+ margin-bottom: 0px;
 37+}
 38+
 39+#editpage-bottom .editOptions {
 40+ width: 100%;
 41+}
 42+#editpage-bottom #wpSummaryLabel,
 43+#editpage-bottom #editpage-summary-fields,
 44+#editpage-bottom .editButtons {
 45+ float: left;
 46+}
 47+#editpage-bottom #wpSummaryLabel{
 48+ width: 150px;
 49+ margin-left: -150px;
 50+ position: relative;
 51+}
 52+#editpage-bottom #editpage-summary-fields {
 53+ width: 100%;
 54+ margin-right: -100%;
 55+}
 56+#editpage-bottom #editpage-summary-fields input.mw-summary {
 57+ width: 95%;
 58+}
 59+#editpage-bottom .editButtons {
 60+ width: 150px;
 61+ margin-right: -150px;
 62+ float: right;
 63+ position: relative;
 64+}
 65+#editpage-bottom #editpage-copywarn {
 66+ margin-left: -150px;
 67+ margin-right: 10px;
 68+}
 69+/* Why don't we use self clearing floats anywhere? */
 70+
 71+#editpage-bottom .editOptions:after {
 72+ content: ".";
 73+ display: block;
 74+ height: 0;
 75+ clear: both;
 76+ visibility: hidden;
 77+}
 78+#editpage-bottom .editOptions {
 79+ display: inline-block;
 80+}
 81+* html #editpage-bottom .editOptions {
 82+ height: 1%;
 83+}
 84+#editpage-bottom .editOptions {
 85+ display:block;
 86+}
\ No newline at end of file
Property changes on: trunk/extensions/Vector/modules/vector.footerCleanup.css
___________________________________________________________________
Added: svn:eol-style
187 + native
Index: trunk/extensions/Vector/Vector.hooks.php
@@ -14,11 +14,12 @@
1515 'collapsiblenav' => array(
1616 'name' => 'vector.collapsibleNav',
1717 'resources' => array(
18 - 'scripts' => '',
19 - 'styles' => '',
 18+ 'scripts' => 'vector.collapsibleNav.js',
 19+ 'styles' => 'vector.collapsibleNav.css',
2020 'messages' => array(
2121 'vector-collapsiblenav-more',
2222 ),
 23+ 'dependencies' => array( 'jquery.client' ),
2324 )
2425 'preferences' => array(
2526 'key' => 'vector-collapsiblenav',
@@ -36,15 +37,13 @@
3738 'collapsibletabs' => array(
3839 'name' => 'vector.collapsibleTabs',
3940 'resources' => array(
40 - 'scripts' => '',
41 - 'styles' => '',
 41+ 'scripts' => 'vector.collapsibleTabs.js',
4242 )
4343 ),
4444 'editwarning' => array(
4545 'name' => 'vector.editWarning',
4646 'resources' => array(
47 - 'scripts' => '',
48 - 'styles' => '',
 47+ 'scripts' => 'vector.editWarning.js',
4948 'messages' => array(
5049 'vector-editwarning-warning',
5150 ),
@@ -62,32 +61,32 @@
6362 'expandablesearch' => array(
6463 'name' => 'vector.expandableSearch',
6564 'resources' => array(
66 - 'scripts' => '',
67 - 'styles' => '',
 65+ 'scripts' => 'vector.expandableSearch.js',
 66+ 'styles' => 'vector.expandableSearch.css',
 67+ 'dependencies' => array( 'jquery.client' ),
6868 ),
6969 'preferences' => array(
70 - 'requirements' = array( 'vector-simplesearch', 'disablesuggest' ),
 70+ 'requirements' = array( 'vector-simplesearch' => true ),
7171 ),
7272 ),
7373 'footercleanup' => array(
7474 'name' => 'vector.footerCleanup',
7575 'resources' => array(
76 - 'scripts' => '',
77 - 'styles' => '',
 76+ 'scripts' => 'vector.footerCleanup.js',
 77+ 'styles' => 'vector.footerCleanup.css',
7878 ),
7979 ),
8080 'simplesearch' => array(
8181 'name' => 'vector.simpleSearch',
8282 'resources' => array(
83 - 'scripts' => '',
84 - 'styles' => '',
 83+ 'scripts' => 'vector.simpleSearch.js',
8584 'messages' => array(
8685 'vector-simplesearch-search',
8786 'vector-simplesearch-containing',
8887 ),
8988 ),
9089 'preferences' => array(
91 - 'requirements' = array( 'vector-simplesearch', 'disablesuggest' ),
 90+ 'requirements' = array( 'vector-simplesearch' => true, 'disablesuggest' => false ),
9291 ),
9392 ),
9493 );
@@ -107,8 +106,9 @@
108107 if ( !$enabled ) {
109108 return false;
110109 }
111 - foreach ( self::$modules[$module]['preferences']['requirements'] as $requirement ) {
112 - if ( !$wgUser->getOption( $requirement ) ) {
 110+ foreach ( self::$modules[$module]['preferences']['requirements'] as $requirement => $value ) {
 111+ // Important! We really do want fuzzy evaluation here
 112+ if ( $wgUser->getOption( $requirement ) != $value ) {
113113 return false;
114114 }
115115 }
@@ -190,6 +190,8 @@
191191 * Adds modules to ResourceLoader
192192 */
193193 public static function resourceLoaderRegisterModules() {
194 - ResourceLoader::register( );
 194+ foreach ( self::$modules as $module ) {
 195+ ResourceLoader::register( $module['name'], $module['resources'] );
 196+ }
195197 }
196198 }
\ No newline at end of file

Follow-up revisions

RevisionCommit summaryAuthorDate
r73389Fixed regression in r73037 that caused Vector extension to load modules on no...tparscal18:41, 20 September 2010

Comments

#Comment by MaxSem (talk | contribs)   10:25, 20 September 2010

Seen on TWN:

$.client is undefined
#Comment by Trevor Parscal (WMF) (talk | contribs)   17:48, 20 September 2010

$.client is shorthand for the jQuery.client object, which is provided by the jquery.client module which includes the /resources/jquery.client.js script. This would be loaded based on dependency information like:

'dependencies' => array( 'jquery.client' )

It's possible I missed a dependency, and you are using a feature with a missing dependency - while when I was testing I was using that together with another feature which does list the dependency (thus masking the error). What assortment of features were turned on/off?

#Comment by MaxSem (talk | contribs)   18:01, 20 September 2010

Reproduceable for me by just visiting http://translatewiki.net/wiki/Support with FF while logged off.

#Comment by Trevor Parscal (WMF) (talk | contribs)   18:42, 20 September 2010

Yes, however, I can not reproduce on my localhost. However, it did bring to my attention a regression that causes vector skin modules to load on non-vector skins, fixed in r73389.

#Comment by Catrope (talk | contribs)   14:49, 1 October 2010

This would'be been sooo much easier to review if you had copied the files in one commit and modified them in the next.

I keep repeating this: do not copy/move files and change them in the same commit, use separate commits for that.

+// Disable mwsuggest.js's effect on searchInput 
+if ( typeof os_autoload_inputs !== 'undefined' && os_autoload_forms !== 'undefined' ) {
+	os_autoload_inputs = [];
+	os_autoload_forms = [];
+}

This needs to access window.os_* now.

#Comment by Trevor Parscal (WMF) (talk | contribs)   18:02, 1 October 2010

Sorry about the move/change. Oh, and you are wrong, os_* is accessible without pre-pending window.

#Comment by Catrope (talk | contribs)   18:02, 1 October 2010

You're right, sorry about that.

Status & tagging log