r64414 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r64413‎ | r64414 | r64415 >
Date:00:16, 31 March 2010
Author:neilk
Status:deferred
Tags:
Comment:
single-click less ugly uploads
Modified paths:
  • /branches/js2-work/phase3/js/mwEmbed/modules/UploadWizard/css/uploadWizard.css (modified) (history)
  • /branches/js2-work/phase3/js/mwEmbed/modules/UploadWizard/mw.UploadWizard.js (modified) (history)

Diff [purge]

Index: branches/js2-work/phase3/js/mwEmbed/modules/UploadWizard/mw.UploadWizard.js
@@ -3,7 +3,7 @@
44 "mwe-upwiz-tab-details": "2. Add licenses and descriptions",
55 "mwe-upwiz-tab-thanks": "3. Use your files",
66 "mwe-upwiz-intro": "Introductory text (short)",
7 - "mwe-upwiz-select-files": "Select files:",
 7+ //"mwe-upwiz-select-files": "Select files:",
88 "mwe-upwiz-add-file-n": "Add another file",
99 "mwe-upwiz-add-file-0": "Add a file",
1010 "mwe-upwiz-browse": "Browse...",
@@ -277,7 +277,7 @@
278278 * 'new' 'transporting' 'transported' 'details' 'submitting-details' 'complete'
279279 * should fork this into two -- local and remote, e.g. filename
280280 */
281 -mw.UploadWizardUpload = function() {
 281+mw.UploadWizardUpload = function( filesDiv ) {
282282 var _this = this;
283283 _this.state = 'new';
284284 _this.transportWeight = 1; // default
@@ -292,7 +292,7 @@
293293
294294 // details
295295 _this.details = new mw.UploadWizardDetails( _this, $j( '#mwe-upwiz-macro-files' ));
296 - _this.ui = new mw.UploadWizardUploadInterface( _this );
 296+ _this.ui = new mw.UploadWizardUploadInterface( _this, filesDiv );
297297
298298 // handler -- usually ApiUploadHandler
299299 // _this.handler = new ( mw.getConfig( 'uploadHandlerClass' ) )( _this );
@@ -489,54 +489,72 @@
490490 /**
491491 * Create an interface fragment corresponding to a file input, suitable for Upload Wizard.
492492 * @param upload
 493+ * @param div to insert file interface
 494+ * @param addInterface interface to add a new one (assumed that we start out there)
493495 */
494 -mw.UploadWizardUploadInterface = function( upload ) {
 496+mw.UploadWizardUploadInterface = function( upload, filesDiv ) {
495497 var _this = this;
496498
497499 _this.upload = upload;
498500
499501 // may need to collaborate with the particular upload type sometimes
500502 // for the interface, as well as the uploadwizard. OY.
501 - _this.div = $j('<div></div>').get(0);
 503+ _this.div = $j('<div class="mwe-upwiz-file"></div>').get(0);
 504+ _this.isFilled = false;
502505
503 - _this.fileInputCtrl = $j('<input size=40 class="mwe-upwiz-file" name="file" type="file"/>').get(0);
 506+ _this.fileInputCtrl = $j('<input size="1" class="mwe-upwiz-file-input" name="file" type="file"/>')
 507+ .change( function() { _this.fileChanged() } )
 508+ .get(0);
504509
 510+
505511 // XXX better class for helper, we probably have a standard already
506 - _this.visibleFilename = $j('<div class="mwe-upwiz-visible-file helper">' + gM('mwe-upwiz-click-here') + '</div>');
 512+ _this.visibleFilename = $j('<div class="mwe-upwiz-visible-file"></div>').hide();
507513
508514 // XXX not sure if we will have a filename here -- we may want to autogenerate a "stashed" filename,
509515 // with this flow
510516 _this.filenameCtrl = $j('<input type="hidden" name="filename" value=""/>').get(0);
511 -
 517+
 518+ _this.fileCtrlContainer = $j('<div class="mwe-upwiz-file-ctrl-container">')
 519+ // the css trickery (along with css)
 520+ // here creates a giant size file input control which is contained within a div and then
 521+ // clipped for overflow. The effect is that we have a div (ctrl-container) we can position anywhere
 522+ // which works as a file input. It will be set to opacity:0 and then we can do whatever we want with
 523+ // interface "below".
 524+ // XXX caution -- if the add file input changes size we won't match, unless we add some sort of event to catch this.
512525 _this.form = $j('<form class="mwe-upwiz-form"></form>')
513 - .append($j('<div class="mwe-upwiz-file-ctrl-container">')
514 - .append( _this.fileInputCtrl )
515 - .append( _this.visibleFilename )
516 - ).append( _this.filenameCtrl ).get( 0 );
 526+ .append( _this.visibleFilename )
 527+ .append( _this.fileCtrlContainer
 528+ .append( _this.fileInputCtrl )
 529+ )
 530+ .append( _this.filenameCtrl ).get( 0 );
517531
518532 _this.progressMessage = $j('<span class="mwe-upwiz-status-message" style="display: none"></span>').get(0);
519533
520 - $j( _this.fileInputCtrl ).change( function() { _this.fileChanged() } );
521534
522535 _this.errorDiv = $j('<div class="mwe-upwiz-upload-error" style="display: none;"></div>').get(0);
523536
524537 _this.removeCtrl = $j( '<a title="' + gM( 'mwe-upwiz-remove-upload' )
525538 + '" href="#" class="mwe-upwiz-remove">x</a>' )
526539 .click( function() { _this.upload.remove() } )
 540+ .hide()
527541 .get( 0 );
528542
529543
530 -
531544 $j( _this.div ).append( _this.form )
532545 .append( _this.progressMessage )
533546 .append( _this.errorDiv )
534 - .append( _this.removeCtrl );
 547+ .append( _this.removeCtrl )
535548
 549+ // XXX evil hardcoded
 550+ // we don't really need filesdiv if we do it this way?
 551+ $j( _this.div ).insertBefore( '#mwe-upwiz-add-file' ); // append( _this.div );
 552+
536553 // _this.progressBar = ( no progress bar for individual uploads yet )
537554 // add a details thing to details
538555 // this should bind only to the FIRST transportProgress
539556 $j( upload ).bind( 'transportProgress', function(e) { _this.showTransportProgress(); e.stopPropagation() } );
540557 $j( upload ).bind( 'transported', function(e) { _this.showTransported(); e.stopPropagation(); } );
 558+
541559 };
542560
543561
@@ -608,6 +626,39 @@
609627 },
610628
611629 /**
 630+ * Move the file input to cover a certain element on the page.
 631+ * We use invisible file inputs because this is the only way to style a file input
 632+ * or otherwise get it to do what you want.
 633+ * It is helpful to sometimes move them to cover certain elements on the page, and
 634+ * even to pass events like hover
 635+ * @param selector jquery-compatible selector, for a single element
 636+ */
 637+ moveFileInputToCover: function( selector ) {
 638+ var _this = this;
 639+
 640+ var $covered = $j( selector );
 641+
 642+ _this.fileCtrlContainer
 643+ .css( $covered.position() )
 644+ .width( $covered.outerWidth() )
 645+ .height( $covered.outerHeight() );
 646+
 647+ // shift the file input over with negative margins,
 648+ // internal to the overflow-containing div, so the div shows all button
 649+ // and none of the textfield-like input
 650+ $j( _this.fileInputCtrl ).css( {
 651+ 'margin-left': '-' + ~~( $j( _this.fileInputCtrl).width() - $covered.outerWidth() - 10 ) + 'px',
 652+ 'margin-top' : '-' + ~~( $j( _this.fileInputCtrl).height() - $covered.outerHeight() - 10 ) + 'px'
 653+ } );
 654+
 655+ // pass hover events to the thing we cover, for interface niceties
 656+ $j( _this.fileCtrlContainer ).bind( 'mouseenter mouseleave', function() {
 657+ $j( selector ).toggleClass( 'hover' );
 658+ } );
 659+
 660+ },
 661+
 662+ /**
612663 * this does two things:
613664 * 1 ) since the file input has been hidden with some clever CSS ( to avoid x-browser styling issues ),
614665 * update the visible filename
@@ -632,7 +683,20 @@
633684 // this is a hack to get a filename guaranteed unique.
634685 uniqueFilename = mw.getConfig( 'userName' ) + "_" + ( new Date() ).getTime() + "_" + filename;
635686 $j( _this.filenameCtrl ).attr( 'value', uniqueFilename );
636 - $j( _this.upload ).trigger( 'filenameAccepted' );
 687+
 688+ if ( ! _this.isFilled ) {
 689+ _this.isFilled = true;
 690+ $j( _this.visibleFilename ).show();
 691+ $j( _this.removeCtrl ).show();
 692+ $j(_this.div ).css( {
 693+ 'position': 'relative', // own our own file input; it will move with us now.
 694+ 'height': '24px'
 695+ } );
 696+ _this.moveFileInputToCover( _this.visibleFilename );
 697+ $j( _this.upload ).trigger( 'filled' );
 698+ } else {
 699+ $j( _this.upload ).trigger( 'filenameAccepted' );
 700+ }
637701 },
638702
639703 /**
@@ -1657,9 +1721,9 @@
16581722 + '<div id="mwe-upwiz-content">'
16591723 + '<div id="mwe-upwiz-tabdiv-file">'
16601724 + '<div id="mwe-upwiz-intro">' + gM('mwe-upwiz-intro') + '</div>'
1661 - + '<div id="mwe-upwiz-select-files">' + gM('mwe-upwiz-select-files') + '</div>'
1662 - + '<div id="mwe-upwiz-files"></div>'
1663 - + '<div><a id="mwe-upwiz-add-file">' + gM("mwe-upwiz-add-file-0") + '</a></div>'
 1725+ + '<div id="mwe-upwiz-files">'
 1726+ + '<a id="mwe-upwiz-add-file">' + gM("mwe-upwiz-add-file-0") + '</a>'
 1727+ + '</div>'
16641728 + '<div><button id="mwe-upwiz-upload-ctrl" disabled="disabled">' + gM("mwe-upwiz-upload") + '</button></div>'
16651729 + '<div id="mwe-upwiz-progress"></div>'
16661730 + '<div style="clear: left;"></div>'
@@ -1711,7 +1775,7 @@
17121776 // within FILE tab div
17131777 // select files:
17141778 // place for file interfaces
1715 - $j('#mwe-upwiz-add-file').click( function() { _this.addUpload() } );
 1779+ // $j('#mwe-upwiz-add-file').click( function() { _this.newUpload() } );
17161780 $j('#mwe-upwiz-upload-ctrl').click( function() { _this.startUploads() } );
17171781
17181782 _this.setupDeedOwnWork();
@@ -1740,7 +1804,7 @@
17411805
17421806
17431807 // add one to start
1744 - _this.addUpload();
 1808+ _this.newUpload( '#mwe-upwiz-add-file' );
17451809
17461810 // "select" the first tab - highlight, make it visible, hide all others
17471811 _this.moveToTab('file');
@@ -1786,25 +1850,27 @@
17871851 * Finally stuff it into an array of uploads.
17881852 * @return boolean success
17891853 */
1790 - addUpload: function() {
 1854+ newUpload: function() {
17911855 var _this = this;
17921856 if ( _this.uploads.length == _this.maxUploads ) {
17931857 return false;
17941858 }
17951859
1796 - var upload = new mw.UploadWizardUpload();
 1860+ var upload = new mw.UploadWizardUpload( _this, '#mwe-upwiz-files' );
 1861+ _this.uploadToAdd = upload;
 1862+
 1863+ upload.ui.moveFileInputToCover( '#mwe-upwiz-add-file' );
17971864 $j( upload ).bind( 'filenameAccepted', function(e) { _this.updateFileCounts(); e.stopPropagation(); } );
17981865 $j( upload ).bind( 'removeUpload', function(e) { _this.removeUpload( upload ); e.stopPropagation(); } );
1799 - // this is only the UI one, so is the result even going to be there?
 1866+ $j( upload ).bind( 'filled', function(e) {
 1867+ _this.uploads.push( upload );
 1868+ _this.updateFileCounts();
 1869+ _this.newUpload();
 1870+ e.stopPropagation();
 1871+ } );
 1872+ // XXX bind to some error state
18001873
1801 - // bind to some error state
1802 -
1803 - _this.uploads.push( upload );
1804 -
1805 - $j( "#mwe-upwiz-files" ).append( upload.ui.div );
1806 -
1807 - _this.updateFileCounts();
1808 -
 1874+
18091875 return true;
18101876 },
18111877
@@ -1812,6 +1878,9 @@
18131879 * Remove an upload from our array of uploads, and the HTML UI
18141880 * We can remove the HTML UI directly, as jquery will just get the parent.
18151881 * We need to grep through the array of uploads, since we don't know the current index.
 1882+ * We need to update file counts for obvious reasons.
 1883+ * Finally, there is an uncounted upload, waiting to be used, which has a fileInput which covers the
 1884+ * "add an upload" button. This is absolutely positioned, so it needs to be moved if another upload was removed.
18161885 *
18171886 * @param upload
18181887 */
@@ -1819,6 +1888,7 @@
18201889 var _this = this;
18211890 mw.UploadWizardUtil.removeItem( _this.uploads, upload );
18221891 _this.updateFileCounts();
 1892+ _this.uploadToAdd.ui.moveFileInputToCover( '#mwe-upwiz-add-file' );
18231893 },
18241894
18251895 /**
@@ -1948,14 +2018,19 @@
19492019
19502020
19512021 /**
1952 - * Occurs whenever we need to update the interface based on how many files are there or have transported
1953 - * Also detects if all uploads have transported and kicks off the process that eventually gets us to Step 2.
 2022+ * Occurs whenever we need to update the interface based on how many files there are
19542023 */
19552024 updateFileCounts: function() {
19562025 var _this = this;
19572026
1958 - // Can we enable the "add an upload" button, and what should the text on the button show?
19592027 $j( '#mwe-upwiz-add-file' ).html( gM( 'mwe-upwiz-add-file-' + ( _this.uploads.length === 0 ? '0' : 'n' )) );
 2028+
 2029+ if ( _this.uploads.length ) {
 2030+ $j( '#mwe-upwiz-upload-ctrl' ).removeAttr( 'disabled' );
 2031+ } else {
 2032+ $j( '#mwe-upwiz-upload-ctrl' ).attr( 'disabled', 'disabled' );
 2033+ }
 2034+
19602035 if ( _this.uploads.length < _this.maxUploads ) {
19612036 $j( '#mwe-upwiz-add-file' ).removeAttr( 'disabled' );
19622037 } else {
@@ -1963,21 +2038,7 @@
19642039 }
19652040
19662041
1967 - // Can we enable the "start uploads" button?
1968 - var hasFile;
1969 - $j.each( _this.uploads, function (i, upload) {
1970 - if ( upload.originalFilename ) {
1971 - hasFile = true;
1972 - return false; // break $j.each
1973 - }
1974 - } );
19752042
1976 - if ( hasFile ) {
1977 - $j( '#mwe-upwiz-upload-ctrl' ).removeAttr( 'disabled' );
1978 - } else {
1979 - $j( '#mwe-upwiz-upload-ctrl' ).attr( 'disabled', 'disabled' );
1980 - }
1981 -
19822043 },
19832044
19842045 /**
Index: branches/js2-work/phase3/js/mwEmbed/modules/UploadWizard/css/uploadWizard.css
@@ -5,6 +5,9 @@
66 display: inline;
77 }
88
 9+#upload-wizard {
 10+ margin-top: 18px;
 11+}
912
1013 /*
1114 .upload-section {
@@ -82,6 +85,17 @@
8386 padding: 1em;
8487 }
8588
 89+#mwe-upwiz-add-file {
 90+ margin: 8px;
 91+ padding: 16px;
 92+ font-size: 16px;
 93+}
 94+
 95+/* NOT a pseudoclass */
 96+#mwe-upwiz-add-file.hover {
 97+ text-decoration: underline;
 98+}
 99+
86100 /* perhaps a general class for links that are actually "buttons" */
87101 #mwe-upwiz-add-file, .mwe-upwiz-remove, .mwe-upwiz-more-options {
88102 cursor: pointer;
@@ -89,25 +103,40 @@
90104
91105 /* CSS styling hack for file inputs - http://www.quirksmode.org/dom/inputfile.html */
92106 .mwe-upwiz-file-ctrl-container {
93 - position: relative;
94 - display: inline;
 107+ position: absolute;
 108+ overflow: hidden;
95109 }
96110
97 -.mwe-upwiz-file, .mwe-upwiz-visible-file {
98 - width: 250px;
99 - height: 20px;
 111+.mwe-upwiz-file-input, .mwe-upwiz-visible-file {
100112 cursor: pointer;
101113 }
102114
 115+/* file inputs are freakishly large to overflow the containing div -- we get a div
 116+ that can act as a more styleable single-click file input */
 117+.mwe-upwiz-file-input {
 118+ font-size: 100px;
 119+ -moz-opacity: 0.3;
 120+ filter:alpha(opacity: 0);
 121+ opacity: 0;
 122+ z-index: 2;
 123+}
 124+
 125+}
 126+
 127+.mwe-upwiz-file {
 128+ height: 24px;
 129+}
 130+
103131 .mwe-upwiz-visible-file {
104 - position: absolute;
105 - top: 0px;
106 - left: 0px;
107 - z-index: 1;
 132+ width: 300px;
 133+ height: 18px;
 134+ float: left;
 135+ /* top: 0px; */
 136+ /* left: 0px; */
108137 white-space: nowrap;
109138 overflow: hidden;
110139
111 - border: 1px solid blue; /* XXX just to make it visible for now */
 140+ /* border: 1px solid blue; XXX just to make it visible for now */
112141 }
113142
114143 /* XXX we probably have a standard for this */
@@ -118,26 +147,17 @@
119148 }
120149
121150
122 -.mwe-upwiz-file {
123 - position: relative;
124 - -moz-opacity: 0;
125 - filter:alpha(opacity: 0);
126 - opacity: 0;
127 - z-index: 2;
128 -}
129 -
 151+/*
130152 #mwe-upwiz-select-files {
131153 float: left;
132154 width: 100px;
133155 }
 156+*/
134157
135158 #mwe-upwiz-files {
136 - margin-left: 100px;
 159+ /* margin-left: 100px; */
137160 }
138161
139 -#mwe-upwiz-add-file {
140 - margin-left: 100px;
141 -}
142162
143163 .mwe-upwiz-remove {
144164 margin-left: 5px;

Status & tagging log