From: Trevor Parscal Date: Fri, 3 Aug 2012 18:50:36 +0000 (-0700) Subject: jsMessage: Redesign in Vector/Monobook as bubble with auto-hide X-Git-Tag: 1.31.0-rc.0~22771 X-Git-Url: http://git.cyclocoop.org/%22.htmlspecialchars%28%24url_syndic%29.%22?a=commitdiff_plain;h=4d0d72828b6798b74ea0bde3f84606dee88e2d0e;p=lhc%2Fweb%2Fwiklou.git jsMessage: Redesign in Vector/Monobook as bubble with auto-hide A bit like the "Growl" notifications on Mac. The message will auto-hide in all skins, which is especially useful with VisualEditor because you it does most things through ajax which means that a msg in there could be visible for way longer than it should be with no way of hiding it. By being designed as a floating bubble instead of a static positioned element in regular document flow it also prevents the page flow from being interrupted and moved down a bit. Again that was especially annoying in VisualEditor because jsMessage forced itself between the tab bar and the editor toolbar, which were meant to be against each other. Auto-hiding is disabled while the mouse if hovering the message. The timer starts again when the mouse is no longer on it. Also: * cleaned up some whitespace issues in vector.js * Removed jshintignore for skins/common Removed whitelisting of 'mw' global skins/common may not be prefect, but at least this way it gives warnings inside the code when writing/editing something, which is still useful. It helped to catch that 'mw' was used from the global scope. Change-Id: I41c70d78c8ed8aeb91a598dc4a7b26dfad8d8f6c --- diff --git a/.jshintignore b/.jshintignore index 8ba7fc36d1..9534f97715 100644 --- a/.jshintignore +++ b/.jshintignore @@ -18,6 +18,3 @@ resources/jquery.ui resources/mediawiki.libs/mediawiki.libs.jpegmeta.js tests/jasmine/lib/jasmine-1.0.1/jasmine-html.js tests/jasmine/lib/jasmine-1.0.1/jasmine.js - -# legacy stuff -skins/common diff --git a/.jshintrc b/.jshintrc index efbe54d9e1..4cf86b8e0d 100644 --- a/.jshintrc +++ b/.jshintrc @@ -1,7 +1,6 @@ { "predef": [ "mediaWiki", - "mw", "QUnit" ], diff --git a/RELEASE-NOTES-1.20 b/RELEASE-NOTES-1.20 index dfd747f702..b904f41c72 100644 --- a/RELEASE-NOTES-1.20 +++ b/RELEASE-NOTES-1.20 @@ -119,6 +119,7 @@ upgrade PHP if you have not done so prior to upgrading MediaWiki. * HTMLForm mutators can now be chained (they return $this) * A new message, "api-error-filetype-banned-type", is available for formatting API upload errors due to the file extension blacklist. +* jsMessage: Redesigned in Vector/Monobook as floating bubble with auto-hide. === Bug fixes in 1.20 === * (bug 30245) Use the correct way to construct a log page title. diff --git a/resources/mediawiki/mediawiki.util.js b/resources/mediawiki/mediawiki.util.js index c3e5e98eb2..38c19c4480 100644 --- a/resources/mediawiki/mediawiki.util.js +++ b/resources/mediawiki/mediawiki.util.js @@ -5,7 +5,9 @@ 'use strict'; // Local cache and alias - var util = { + var hideMessageTimeout, + messageBoxEvents = false, + util = { /** * Initialisation @@ -432,15 +434,16 @@ * @return {Boolean} True on success, false on failure. */ jsMessage: function ( message, className ) { + var $messageDiv = $( '#mw-js-message' ); + if ( !arguments.length || message === '' || message === null ) { - $( '#mw-js-message' ).empty().hide(); + $messageDiv.empty().hide(); + stopHideMessageTimeout(); return true; // Emptying and hiding message is intended behaviour, return true - } else { // We special-case skin structures provided by the software. Skins that // choose to abandon or significantly modify our formatting can just define // an mw-js-message div to start with. - var $messageDiv = $( '#mw-js-message' ); if ( !$messageDiv.length ) { $messageDiv = $( '
' ); if ( util.$content.parent().length ) { @@ -450,8 +453,24 @@ } } + if ( !messageBoxEvents ) { + $messageDiv + .on( { + 'mouseenter': stopHideMessageTimeout, + 'mouseleave': startHideMessageTimeout, + 'click': function() { + $(this).fadeOut( 'slow' ); + } + } ) + .on( 'click', 'a', function ( e ) { + // Prevent links, even those that don't exist yet, from causing the + // message box to close when clicked + e.stopPropagation(); + } ); + } + if ( className ) { - $messageDiv.prop( 'class', 'mw-js-message-' + className ); + $messageDiv.prop( 'className', 'mw-js-message-' + className ); } if ( typeof message === 'object' ) { @@ -462,6 +481,7 @@ } $messageDiv.slideDown(); + startHideMessageTimeout(); return true; } }, @@ -599,6 +619,18 @@ } }; + // Message auto-hide helpers + function hideMessage() { + $( '#mw-js-message' ).fadeOut( 'slow' ); + } + function stopHideMessageTimeout() { + clearTimeout( hideMessageTimeout ); + } + function startHideMessageTimeout() { + clearTimeout( hideMessageTimeout ); + hideMessageTimeout = setTimeout( hideMessage, 5000 ); + } + mw.util = util; }( mediaWiki, jQuery ) ); diff --git a/skins/common/shared.css b/skins/common/shared.css index 8c114f0b17..8c35626233 100644 --- a/skins/common/shared.css +++ b/skins/common/shared.css @@ -116,14 +116,19 @@ span.texhtml { #wpTextbox1 { clear: both; } + #toolbar img { cursor: pointer; } + div#mw-js-message { margin: 1em 5%; padding: 0.5em 2.5%; border: solid 1px #ddd; background-color: #fcfcfc; + /* Message hides on-click */ + /* See also mw.util.jsMessage */ + cursor: pointer; } /* Edit section links */ diff --git a/skins/common/wikibits.js b/skins/common/wikibits.js index 8f47499c48..6526e8b438 100644 --- a/skins/common/wikibits.js +++ b/skins/common/wikibits.js @@ -1,7 +1,7 @@ /** * MediaWiki legacy wikibits */ -(function(){ +( function ( mw ) { window.clientPC = navigator.userAgent.toLowerCase(); // Get client info window.is_gecko = /gecko/.test( clientPC ) && @@ -515,55 +515,14 @@ window.redirectToFragment = function( fragment ) { * Add a cute little box at the top of the screen to inform the user of * something, replacing any preexisting message. * - * @param message String -or- Dom Object HTML to be put inside the right div - * @param className String Used in adding a class; should be different for each - * call to allow CSS/JS to hide different boxes. null = no class used. - * @return Boolean True on success, false on failure + * @deprecated since 1.17 Use mw.util.jsMessage instead. + * @param {String|HTMLElement} message To be put inside the message box. + * @param {String} className Used in adding a class; Can be used to selectively + * apply CSS to a certain category of messages. null = no class used. + * @return {Boolean} True on success, false on failure */ -window.jsMsg = function( message, className ) { - if ( !document.getElementById ) { - return false; - } - // We special-case skin structures provided by the software. Skins that - // choose to abandon or significantly modify our formatting can just define - // an mw-js-message div to start with. - var messageDiv = document.getElementById( 'mw-js-message' ); - if ( !messageDiv ) { - messageDiv = document.createElement( 'div' ); - if ( document.getElementById( 'column-content' ) - && document.getElementById( 'content' ) ) { - // MonoBook, presumably - document.getElementById( 'content' ).insertBefore( - messageDiv, - document.getElementById( 'content' ).firstChild - ); - } else if ( document.getElementById( 'content' ) - && document.getElementById( 'article' ) ) { - // Non-Monobook but still recognizable (old-style) - document.getElementById( 'article').insertBefore( - messageDiv, - document.getElementById( 'article' ).firstChild - ); - } else { - return false; - } - } - - messageDiv.setAttribute( 'id', 'mw-js-message' ); - messageDiv.style.display = 'block'; - if( className ) { - messageDiv.setAttribute( 'class', 'mw-js-message-' + className ); - } - - if ( typeof message === 'object' ) { - while ( messageDiv.hasChildNodes() ) { // Remove old content - messageDiv.removeChild( messageDiv.firstChild ); - } - messageDiv.appendChild( message ); // Append new content - } else { - messageDiv.innerHTML = message; - } - return true; +window.jsMsg = function () { + return mw.util.jsMessage.apply( mw.util, arguments ); }; /** @@ -663,4 +622,4 @@ if ( ie6_bugs ) { importScriptURI( mw.config.get( 'stylepath' ) + '/common/IEFixes.js' ); } -})(); +}( mediaWiki ) ); diff --git a/skins/monobook/main.css b/skins/monobook/main.css index 2fe259e22c..0566e98cb7 100644 --- a/skins/monobook/main.css +++ b/skins/monobook/main.css @@ -913,3 +913,17 @@ div.mw-lag-warn-high { .tipsy { font-size: 127%; } + +/* jsMessage */ + +div#mw-js-message { + position: absolute; + margin: 0; + padding: 0.25em 1em; + right: 1em; + top: 1em; + width: 20em; + z-index: 10000; + -webkit-box-shadow: 0px 2px 5px 0px rgba(0, 0, 0, 0.125); + box-shadow: 0px 2px 5px 0px rgba(0, 0, 0, 0.125); +} diff --git a/skins/vector/screen.css b/skins/vector/screen.css index 32a6489e2f..e74bd96d16 100644 --- a/skins/vector/screen.css +++ b/skins/vector/screen.css @@ -784,8 +784,21 @@ div#content a.external[href *=".pdf?"], div#content a.external[href *=".PDF?"], position: relative; width: 100%; } -#mw-js-message { +div#mw-js-message { + background-color: #ffffff; + background-color: rgba(255, 255, 255, 0.93); font-size: 0.8em; + position: absolute; + margin: 0; + padding: 1em 2em; + right: 1em; + top: 7em; + width: 20em; + z-index: 10000; + border: solid 1px #a7d7f9; + border-radius: 0.75em; + -webkit-box-shadow: 0px 2px 10px 0px rgba(0, 0, 0, 0.125); + box-shadow: 0px 2px 10px 0px rgba(0, 0, 0, 0.125); } div#bodyContent { line-height: 1.5em; diff --git a/skins/vector/vector.js b/skins/vector/vector.js index cc76b3282e..8b719e5bc0 100644 --- a/skins/vector/vector.js +++ b/skins/vector/vector.js @@ -1,21 +1,21 @@ -/* +/** * Vector-specific scripts */ -jQuery( function( $ ) { - $( 'div.vectorMenu' ).each( function() { - var self = this; - $( 'h5:first a:first', this ) +jQuery( function ( $ ) { + $( 'div.vectorMenu' ).each( function () { + var $el = $( this ); + $el.find( 'h5:first a:first' ) // For accessibility, show the menu when the hidden link in the menu is clicked (bug 24298) - .click( function( e ) { - $( '.menu:first', self ).toggleClass( 'menuForceShow' ); + .click( function ( e ) { + $el.find( '.menu:first' ).toggleClass( 'menuForceShow' ); e.preventDefault(); - }) + } ) // When the hidden link has focus, also set a class that will change the arrow icon - .focus( function() { - $( self ).addClass( 'vectorMenuFocus' ); - }) - .blur( function() { - $( self ).removeClass( 'vectorMenuFocus' ); - }); - }); -}); + .focus( function () { + $el.addClass( 'vectorMenuFocus' ); + } ) + .blur( function () { + $el.removeClass( 'vectorMenuFocus' ); + } ); + } ); +} );