~fusonic/chive/1.1

« back to all changes in this revision

Viewing changes to yii/web/js/source/jquery.multifile.js

  • Committer: Matthias Burtscher
  • Date: 2010-02-12 09:12:35 UTC
  • Revision ID: matthias.burtscher@fusonic.net-20100212091235-jqxrb62klx872ajc
* Updated Yii to 1.1.0
* Removed CodePress and CodeMirror
* Updated jQuery and some plugins
* Cleaned some code ...

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
 ### jQuery Multiple File Upload Plugin v 1.29 - 2008-06-26 ###
3
 
 * http://www.fyneworks.com/ - diego@fyneworks.com
 
2
 ### jQuery Multiple File Upload Plugin v1.46 - 2009-05-12 ###
 
3
 * Home: http://www.fyneworks.com/jquery/multiple-file-upload/
 
4
 * Code: http://code.google.com/p/jquery-multifile-plugin/
 
5
 *
4
6
 * Dual licensed under the MIT and GPL licenses:
5
7
 *   http://www.opensource.org/licenses/mit-license.php
6
8
 *   http://www.gnu.org/licenses/gpl.html
7
9
 ###
8
 
 Project: http://jquery.com/plugins/project/MultiFile/
9
 
 Website: http://www.fyneworks.com/jquery/multiple-file-upload/
10
10
*/
11
11
 
12
12
/*# AVOID COLLISIONS #*/
13
 
;if(jQuery) (function($){
 
13
;if(window.jQuery) (function($){
14
14
/*# AVOID COLLISIONS #*/
15
 
 
16
 
 // extend jQuery - $.MultiFile hook
17
 
 $.extend($, {
18
 
  MultiFile: function( o /* Object */ ){
19
 
   //return $("INPUT[@type='file'].multi").MultiFile(o);
20
 
   return $("input:file.multi").MultiFile(o);
21
 
  }
22
 
 });
23
 
 
24
 
 //===
25
 
 
26
 
 // extend $.MultiFile - default options
27
 
 $.extend($.MultiFile, {
28
 
  options: {
29
 
   accept: '', max: -1,
30
 
   // error handling function
31
 
   error: function(s){
32
 
    if($.blockUI){
33
 
     $.blockUI({
34
 
      message: s.replace(/\n/gi,'<br/>'),
35
 
      css: {
36
 
       border:'none', padding:'15px', size:'12.0pt',
37
 
       backgroundColor:'#900', color:'#fff',
38
 
       opacity:'.8','-webkit-border-radius': '10px','-moz-border-radius': '10px'
39
 
      }
40
 
     });
41
 
     window.setTimeout($.unblockUI, 2000);
42
 
    }
43
 
    else{
44
 
     alert(s);
45
 
    }
46
 
   },
47
 
   // namePattern: $name/$id (from master element), $i (slave count), $g (group count)
48
 
   namePattern: '$name',
49
 
   // STRING: collection lets you show messages in different languages
50
 
   STRING: {
51
 
    remove:'remove',
52
 
    denied:'You cannot select a $ext file.\nTry again...',
53
 
    selected:'File selected: $file',
54
 
    duplicate:'This file has already been selected:\n$file'
55
 
   }
56
 
  }
57
 
 });
58
 
 
59
 
 //===
60
 
 
61
 
 // extend $.MultiFile - global methods
62
 
 $.extend($.MultiFile, {
63
 
 
64
 
 
65
 
  /**
66
 
   * This utility makes it easy to disable all 'empty' file elements in the document before submitting a form.
67
 
   * It marks the affected elements so they can be easily re-enabled after the form submission or validation.
68
 
   *
69
 
   * Returns a jQuery collection of all affected elements.
70
 
   *
71
 
   * @name disableEmpty
72
 
   * @type jQuery
73
 
   * @cat Plugins/Multifile
74
 
   * @author Diego A. (http://www.fyneworks.com/)
75
 
   *
76
 
   * @example $.MultiFile.disableEmpty();
77
 
   * @param String class (optional) A string specifying a class to be applied to all affected elements - Default: 'mfD'.
78
 
   */
79
 
  disableEmpty: function(klass){
80
 
   var o = [];
81
 
   $('input:file').each(function(){ if($(this).val()=='') o[o.length] = this; });
82
 
   return $(o).each(function(){ this.disabled = true }).addClass(klass || 'mfD');
83
 
  },
84
 
 
85
 
 
86
 
 /**
87
 
  * This method re-enables 'empty' file elements that were disabled (and marked) with the $.MultiFile.disableEmpty method.
88
 
  *
89
 
  * Returns a jQuery collection of all affected elements.
90
 
  *
91
 
  * @name reEnableEmpty
92
 
  * @type jQuery
93
 
  * @cat Plugins/Multifile
94
 
  * @author Diego A. (http://www.fyneworks.com/)
95
 
  *
96
 
  * @example $.MultiFile.reEnableEmpty();
97
 
  * @param String klass (optional) A string specifying the class that was used to mark affected elements - Default: 'mfD'.
98
 
  */
99
 
  reEnableEmpty: function(klass){
100
 
   klass = klass || 'mfD';
101
 
   return $('input:file.'+klass).removeClass(klass).each(function(){ this.disabled = false });
102
 
  },
103
 
  autoIntercept: [ 'submit', 'ajaxSubmit', 'validate' /* array of methods to intercept */ ],
104
 
  intercepted: {},
105
 
  intercept: function(methods, context, args){
106
 
   var method, value; args = args || [];
107
 
   if(args.constructor.toString().indexOf("Array")<0) args = [ args ];
108
 
   if(typeof(methods)=='function'){
109
 
    $.MultiFile.disableEmpty();
110
 
    value = methods.apply(context || window, args);
111
 
    $.MultiFile.reEnableEmpty();
112
 
    return value;
113
 
   };
114
 
   if(methods.constructor.toString().indexOf("Array")<0) methods = [methods];
115
 
   for(var i=0;i<methods.length;i++){
116
 
    method = methods[i]+''; // make sure that we have a STRING
117
 
    if(method) (function(method){ // make sure that method is ISOLATED for the interception
118
 
     $.MultiFile.intercepted[method] = $.fn[method] || function(){};
119
 
     $.fn[method] = function(){
120
 
      $.MultiFile.disableEmpty();
121
 
      value = $.MultiFile.intercepted[method].apply(this, arguments);
122
 
      $.MultiFile.reEnableEmpty();
123
 
      return value;
124
 
     }; // interception
125
 
    })(method); // MAKE SURE THAT method IS ISOLATED for the interception
126
 
   };// for each method
127
 
  }
128
 
 });
129
 
 
130
 
 //===
131
 
 
132
 
 // extend jQuery function library
133
 
 $.extend($.fn, {
134
 
 
135
 
   // Use this function to clear values of file inputs
136
 
   // But this doesn't always work: $(element).val('').attr('value', '')[0].value = '';
137
 
   reset: function(){ return this.each(function(){ try{ this.reset(); }catch(e){} }); },
138
 
 
139
 
   // MultiFile function
140
 
   MultiFile: function( options /* Object */ ){
141
 
 
142
 
    //### http://plugins.jquery.com/node/1363
143
 
    // utility method to integrate this plugin with others...
144
 
    if($.MultiFile.autoIntercept){
145
 
     $.MultiFile.intercept( $.MultiFile.autoIntercept /* array of methods to intercept */ );
146
 
     $.MultiFile.autoIntercept = null; /* only run this once */
147
 
    };
148
 
 
149
 
    //===
150
 
 
151
 
    // Bind to each element in current jQuery object
152
 
    return $(this).each(function(group_count){
153
 
     if(this._MultiFile) return; this._MultiFile = true;
154
 
 
 
15
 
 
16
        // plugin initialization
 
17
        $.fn.MultiFile = function(options){
 
18
                if(this.length==0) return this; // quick fail
 
19
                
 
20
                // Handle API methods
 
21
                if(typeof arguments[0]=='string'){
 
22
                        // Perform API methods on individual elements
 
23
                        if(this.length>1){
 
24
                                var args = arguments;
 
25
                                return this.each(function(){
 
26
                                        $.fn.MultiFile.apply($(this), args);
 
27
    });
 
28
                        };
 
29
                        // Invoke API method handler
 
30
                        $.fn.MultiFile[arguments[0]].apply(this, $.makeArray(arguments).slice(1) || []);
 
31
                        // Quick exit...
 
32
                        return this;
 
33
                };
 
34
                
 
35
                // Initialize options for this call
 
36
                var options = $.extend(
 
37
                        {}/* new object */,
 
38
                        $.fn.MultiFile.options/* default options */,
 
39
                        options || {} /* just-in-time options */
 
40
                );
 
41
                
 
42
                // Empty Element Fix!!!
 
43
                // this code will automatically intercept native form submissions
 
44
                // and disable empty file elements
 
45
                $('form')
 
46
                .not('MultiFile-intercepted')
 
47
                .addClass('MultiFile-intercepted')
 
48
                .submit($.fn.MultiFile.disableEmpty);
 
49
                
 
50
                //### http://plugins.jquery.com/node/1363
 
51
                // utility method to integrate this plugin with others...
 
52
                if($.fn.MultiFile.options.autoIntercept){
 
53
                        $.fn.MultiFile.intercept( $.fn.MultiFile.options.autoIntercept /* array of methods to intercept */ );
 
54
                        $.fn.MultiFile.options.autoIntercept = null; /* only run this once */
 
55
                };
 
56
                
 
57
                // loop through each matched element
 
58
                this
 
59
                 .not('.MultiFile-applied')
 
60
                        .addClass('MultiFile-applied')
 
61
                .each(function(){
 
62
                        //#####################################################################
 
63
                        // MAIN PLUGIN FUNCTIONALITY - START
 
64
                        //#####################################################################
 
65
                        
155
66
       // BUG 1251 FIX: http://plugins.jquery.com/project/comments/add/1251
156
67
       // variable group_count would repeat itself on multiple calls to the plugin.
157
68
       // this would cause a conflict with multiple elements
158
69
       // changes scope of variable to global so id will be unique over n calls
159
70
       window.MultiFile = (window.MultiFile || 0) + 1;
160
 
       group_count = window.MultiFile;
161
 
 
 
71
       var group_count = window.MultiFile;
 
72
       
162
73
       // Copy parent attributes - Thanks to Jonas Wagner
163
74
       // we will use this one to create new input elements
164
 
       var MF = {e:this, E:$(this), clone:$(this).clone()};
165
 
 
 
75
       var MultiFile = {e:this, E:$(this), clone:$(this).clone()};
 
76
       
166
77
       //===
167
 
 
 
78
       
168
79
       //# USE CONFIGURATION
169
80
       if(typeof options=='number') options = {max:options};
170
 
       if(typeof options=='string') options = {accept:options};
171
81
       var o = $.extend({},
172
 
        $.MultiFile.options,
 
82
        $.fn.MultiFile.options,
173
83
        options || {},
174
 
        ($.meta ? MF.E.data()/*NEW metadata plugin*/ :
175
 
        ($.metadata ? MF.E.metadata()/*OLD metadata plugin*/ :
176
 
        null/*metadata plugin not available*/)) || {}
 
84
                                        ($.metadata? MultiFile.E.metadata(): ($.meta?MultiFile.E.data():null)) || {}, /* metadata options */
 
85
                                                                {} /* internals */
177
86
       );
178
87
       // limit number of files that can be selected?
179
 
       if(!(o.max>0) /*IsNull(MF.max)*/){
180
 
        o.max = MF.E.attr('maxlength');
181
 
        if(!(o.max>0) /*IsNull(MF.max)*/){
182
 
         o.max = (String(MF.e.className.match(/\b(max|limit)\-([0-9]+)\b/gi) || ['']).match(/[0-9]+/gi) || [''])[0];
 
88
       if(!(o.max>0) /*IsNull(MultiFile.max)*/){
 
89
        o.max = MultiFile.E.attr('maxlength');
 
90
        if(!(o.max>0) /*IsNull(MultiFile.max)*/){
 
91
         o.max = (String(MultiFile.e.className.match(/\b(max|limit)\-([0-9]+)\b/gi) || ['']).match(/[0-9]+/gi) || [''])[0];
183
92
         if(!(o.max>0)) o.max = -1;
184
93
         else           o.max = String(o.max).match(/[0-9]+/gi)[0];
185
94
        }
186
95
       };
187
96
       o.max = new Number(o.max);
188
97
       // limit extensions?
189
 
       o.accept = o.accept || MF.E.attr('accept') || '';
 
98
       o.accept = o.accept || MultiFile.E.attr('accept') || '';
190
99
       if(!o.accept){
191
 
        o.accept = (MF.e.className.match(/\b(accept\-[\w\|]+)\b/gi)) || '';
 
100
        o.accept = (MultiFile.e.className.match(/\b(accept\-[\w\|]+)\b/gi)) || '';
192
101
        o.accept = new String(o.accept).replace(/^(accept|ext)\-/i,'');
193
102
       };
194
 
 
 
103
       
195
104
       //===
196
 
 
 
105
       
197
106
       // APPLY CONFIGURATION
198
 
       $.extend(MF, o || {});
199
 
       MF.STRING = $.extend({},$.MultiFile.options.STRING,MF.STRING);
200
 
 
 
107
                                                        $.extend(MultiFile, o || {});
 
108
       MultiFile.STRING = $.extend({},$.fn.MultiFile.options.STRING,MultiFile.STRING);
 
109
       
201
110
       //===
202
 
 
 
111
       
203
112
       //#########################################
204
113
       // PRIVATE PROPERTIES/METHODS
205
 
       $.extend(MF, {
 
114
       $.extend(MultiFile, {
206
115
        n: 0, // How many elements are currently selected?
207
116
        slaves: [], files: [],
208
 
        instanceKey: MF.e.id || 'MultiFile'+String(group_count), // Instance Key?
209
 
        generateID: function(z){ return MF.instanceKey + (z>0 ?'_F'+String(z):''); },
 
117
        instanceKey: MultiFile.e.id || 'MultiFile'+String(group_count), // Instance Key?
 
118
        generateID: function(z){ return MultiFile.instanceKey + (z>0 ?'_F'+String(z):''); },
210
119
        trigger: function(event, element){
211
 
         var handler = MF[event], value = $(element).attr('value');
 
120
         var handler = MultiFile[event], value = $(element).attr('value');
212
121
         if(handler){
213
 
          var returnValue = handler(element, value, MF);
 
122
          var returnValue = handler(element, value, MultiFile);
214
123
          if( returnValue!=null ) return returnValue;
215
124
         }
216
125
         return true;
217
126
        }
218
127
       });
219
 
 
 
128
       
220
129
       //===
221
 
 
 
130
       
222
131
       // Setup dynamic regular expression for extension validation
223
132
       // - thanks to John-Paul Bader: http://smyck.de/2006/08/11/javascript-dynamic-regular-expresions/
224
 
       if(String(MF.accept).length>1){
225
 
        MF.rxAccept = new RegExp('\\.('+(MF.accept?MF.accept:'')+')$','gi');
 
133
       if(String(MultiFile.accept).length>1){
 
134
                                                                MultiFile.accept = MultiFile.accept.replace(/\W+/g,'|').replace(/^\W|\W$/g,'');
 
135
        MultiFile.rxAccept = new RegExp('\\.('+(MultiFile.accept?MultiFile.accept:'')+')$','gi');
226
136
       };
227
 
 
 
137
       
228
138
       //===
229
 
 
 
139
       
230
140
       // Create wrapper to hold our file list
231
 
       MF.wrapID = MF.instanceKey+'_wrap'; // Wrapper ID?
232
 
       MF.E.wrap('<div id="'+MF.wrapID+'"></div>');
233
 
       MF.wrapper = $('#'+MF.wrapID+'');
234
 
 
235
 
       //===
236
 
 
237
 
       // MF MUST have a name - default: file1[], file2[], file3[]
238
 
       MF.e.name = MF.e.name || 'file'+ group_count +'[]';
239
 
 
240
 
       //===
241
 
 
242
 
       // Create a wrapper for the labels
243
 
       // * OPERA BUG: NO_MODIFICATION_ALLOWED_ERR ('labels' is a read-only property)
244
 
       // this changes allows us to keep the files in the order they were selected
245
 
       MF.wrapper.append( '<span id="'+MF.wrapID+'_labels"></span>' );
246
 
       MF.labels = $('#'+MF.wrapID+'_labels');
247
 
 
248
 
       //===
249
 
 
 
141
       MultiFile.wrapID = MultiFile.instanceKey+'_wrap'; // Wrapper ID?
 
142
       MultiFile.E.wrap('<div class="MultiFile-wrap" id="'+MultiFile.wrapID+'"></div>');
 
143
       MultiFile.wrapper = $('#'+MultiFile.wrapID+'');
 
144
       
 
145
       //===
 
146
       
 
147
       // MultiFile MUST have a name - default: file1[], file2[], file3[]
 
148
       MultiFile.e.name = MultiFile.e.name || 'file'+ group_count +'[]';
 
149
       
 
150
       //===
 
151
       
 
152
                                                        if(!MultiFile.list){
 
153
                                                                // Create a wrapper for the list
 
154
                                                                // * OPERA BUG: NO_MODIFICATION_ALLOWED_ERR ('list' is a read-only property)
 
155
                                                                // this change allows us to keep the files in the order they were selected
 
156
                                                                MultiFile.wrapper.append( '<div class="MultiFile-list" id="'+MultiFile.wrapID+'_list"></div>' );
 
157
                                                                MultiFile.list = $('#'+MultiFile.wrapID+'_list');
 
158
                                                        };
 
159
       MultiFile.list = $(MultiFile.list);
 
160
                                                        
 
161
       //===
 
162
       
250
163
       // Bind a new element
251
 
       MF.addSlave = function( slave, slave_count ){
 
164
       MultiFile.addSlave = function( slave, slave_count ){
 
165
                                                                //if(window.console) console.log('MultiFile.addSlave',slave_count);
 
166
                                                                
252
167
        // Keep track of how many elements have been displayed
253
 
        MF.n++;
 
168
        MultiFile.n++;
254
169
        // Add reference to master element
255
 
        slave.MF = MF;
256
 
        // Count slaves
257
 
        slave.i = slave_count;
258
 
 
259
 
        // BUG FIX: http://plugins.jquery.com/node/1495
260
 
        // Clear identifying properties from clones
261
 
        if(slave.i>0) slave.id = slave.name = null;
262
 
 
 
170
        slave.MultiFile = MultiFile;
 
171
                                                                
 
172
                                                                // BUG FIX: http://plugins.jquery.com/node/1495
 
173
                                                                // Clear identifying properties from clones
 
174
                                                                if(slave_count>0) slave.id = slave.name = '';
 
175
                                                                
263
176
        // Define element's ID and name (upload components need this!)
264
 
        slave.id = slave.id || MF.generateID(slave.i);
265
 
 
266
 
        //slave.name = (slave.name || MF.E.attr('name') || 'file');// + (slave.i>0?slave.i:''); // same name as master element
 
177
        //slave.id = slave.id || MultiFile.generateID(slave_count);
 
178
                                                                if(slave_count>0) slave.id = MultiFile.generateID(slave_count);
 
179
                                                                //FIX for: http://code.google.com/p/jquery-multifile-plugin/issues/detail?id=23
 
180
        
267
181
        // 2008-Apr-29: New customizable naming convention (see url below)
268
182
        // http://groups.google.com/group/jquery-dev/browse_frm/thread/765c73e41b34f924#
269
 
        slave.name = String(MF.namePattern
270
 
         /*master name*/.replace(/\$name/gi,MF.E.attr('name'))
271
 
         /*master id  */.replace(/\$id/gi,  MF.E.attr('id'))
272
 
         /*group count*/.replace(/\$g/gi,   (group_count>0?group_count:''))
273
 
         /*slave count*/.replace(/\$i/gi,   (slave_count>0?slave_count:''))
 
183
        slave.name = String(MultiFile.namePattern
 
184
         /*master name*/.replace(/\$name/gi,$(MultiFile.clone).attr('name'))
 
185
         /*master id  */.replace(/\$id/gi,  $(MultiFile.clone).attr('id'))
 
186
         /*group count*/.replace(/\$g/gi,   group_count)//(group_count>0?group_count:''))
 
187
         /*slave count*/.replace(/\$i/gi,   slave_count)//(slave_count>0?slave_count:''))
274
188
        );
275
 
 
276
 
        // Clear value
277
 
        $(slave).val('').attr('value','')[0].value = '';
278
 
 
 
189
        
279
190
        // If we've reached maximum number, disable input slave
280
 
        if( (MF.max > 0) && ((MF.n-1) > (MF.max)) )//{ // MF.n Starts at 1, so subtract 1 to find true count
 
191
        if( (MultiFile.max > 0) && ((MultiFile.n-1) > (MultiFile.max)) )//{ // MultiFile.n Starts at 1, so subtract 1 to find true count
281
192
         slave.disabled = true;
282
193
        //};
283
 
 
 
194
        
284
195
        // Remember most recent slave
285
 
        MF.current = MF.slaves[slave.i] = slave;
286
 
 
287
 
        // now let's use jQuery
288
 
        slave = $(slave);
289
 
 
 
196
        MultiFile.current = MultiFile.slaves[slave_count] = slave;
 
197
        
 
198
                                                                // We'll use jQuery from now on
 
199
                                                                slave = $(slave);
 
200
        
 
201
        // Clear value
 
202
        slave.val('').attr('value','')[0].value = '';
 
203
        
 
204
                                                                // Stop plugin initializing on slaves
 
205
                                                                slave.addClass('MultiFile-applied');
 
206
                                                                
290
207
        // Triggered when a file is selected
291
 
        $(slave).change(function(){
292
 
 
 
208
        slave.change(function(){
 
209
          //if(window.console) console.log('MultiFile.slave.change',slave_count);
 
210
                                                                 
293
211
          // Lose focus to stop IE7 firing onchange again
294
212
          $(this).blur();
295
 
 
 
213
          
296
214
          //# Trigger Event! onFileSelect
297
 
          if(!MF.trigger('onFileSelect', this, MF)) return false;
 
215
          if(!MultiFile.trigger('onFileSelect', this, MultiFile)) return false;
298
216
          //# End Event!
299
 
 
 
217
          
300
218
          //# Retrive value of selected file from element
301
219
          var ERROR = '', v = String(this.value || ''/*.attr('value)*/);
302
 
 
 
220
          
303
221
          // check extension
304
 
          if(MF.accept){
305
 
           if(v!=''){
306
 
            if(!v.match(MF.rxAccept)){
307
 
             ERROR = MF.STRING.denied.replace('$ext', String(v.match(/\.\w{1,4}$/gi)));
308
 
            }
309
 
           }
310
 
          };
311
 
 
 
222
          if(MultiFile.accept && v && !v.match(MultiFile.rxAccept))//{
 
223
            ERROR = MultiFile.STRING.denied.replace('$ext', String(v.match(/\.\w{1,4}$/gi)));
 
224
           //}
 
225
          //};
 
226
          
312
227
          // Disallow duplicates
313
 
          for(var f=0;f<MF.slaves.length;f++){
314
 
           if(MF.slaves[f]!=this){
315
 
            if(MF.slaves[f].value==v){
316
 
             ERROR = MF.STRING.duplicate.replace('$file', v.match(/[^\/\\]+$/gi));
317
 
            }
318
 
           }
319
 
          };
320
 
 
 
228
                                                                                for(var f in MultiFile.slaves)//{
 
229
           if(MultiFile.slaves[f] && MultiFile.slaves[f]!=this)//{
 
230
                                                                                //console.log(MultiFile.slaves[f],MultiFile.slaves[f].value);
 
231
            if(MultiFile.slaves[f].value==v)//{
 
232
             ERROR = MultiFile.STRING.duplicate.replace('$file', v.match(/[^\/\\]+$/gi));
 
233
            //};
 
234
           //};
 
235
          //};
 
236
          
321
237
          // Create a new file input element
322
 
          //var newEle = $('<input name="'+(MF.E.attr('name') || '')+'" type="file"/>');
323
 
          var newEle = $(MF.clone).clone();// Copy parent attributes - Thanks to Jonas Wagner
 
238
          var newEle = $(MultiFile.clone).clone();// Copy parent attributes - Thanks to Jonas Wagner
324
239
          //# Let's remember which input we've generated so
325
240
          // we can disable the empty ones before submission
326
241
          // See: http://plugins.jquery.com/node/1495
327
242
          newEle.addClass('MultiFile');
328
 
 
 
243
          
329
244
          // Handle error
330
245
          if(ERROR!=''){
331
246
            // Handle error
332
 
            MF.error(ERROR);
333
 
 
334
 
            // Clear element value (DOES NOT WORK in some browsers)
335
 
            //slave.reset().val('').attr('value', '')[0].value = '';
336
 
 
337
 
            // 2007-06-24: BUG FIX - Thanks to Adrian Wróbel <adrian [dot] wrobel [at] gmail.com>
 
247
            MultiFile.error(ERROR);
 
248
                                                                                                
 
249
            // 2007-06-24: BUG FIX - Thanks to Adrian Wr�bel <adrian [dot] wrobel [at] gmail.com>
338
250
            // Ditch the trouble maker and add a fresh new element
339
 
            MF.n--;
340
 
            MF.addSlave(newEle[0], this.i);
 
251
            MultiFile.n--;
 
252
            MultiFile.addSlave(newEle[0], slave_count);
341
253
            slave.parent().prepend(newEle);
342
254
            slave.remove();
343
255
            return false;
344
256
          };
345
 
 
 
257
          
346
258
          // Hide this element (NB: display:none is evil!)
347
259
          $(this).css({ position:'absolute', top: '-3000px' });
348
 
 
 
260
          
349
261
          // Add new element to the form
350
 
          MF.labels.before(newEle);//.append(newEle);
351
 
 
 
262
          slave.after(newEle);
 
263
          
352
264
          // Update list
353
 
          MF.addToList( this );
354
 
 
 
265
          MultiFile.addToList( this, slave_count );
 
266
          
355
267
          // Bind functionality
356
 
          MF.addSlave( newEle[0], this.i+1 );
357
 
 
 
268
          MultiFile.addSlave( newEle[0], slave_count+1 );
 
269
          
358
270
          //# Trigger Event! afterFileSelect
359
 
          if(!MF.trigger('afterFileSelect', this, MF)) return false;
 
271
          if(!MultiFile.trigger('afterFileSelect', this, MultiFile)) return false;
360
272
          //# End Event!
361
 
 
 
273
          
362
274
        }); // slave.change()
363
 
 
364
 
       };// MF.addSlave
 
275
                                                                
 
276
                                                                // Save control to element
 
277
                                                                $(slave).data('MultiFile', MultiFile);
 
278
                                                                
 
279
       };// MultiFile.addSlave
365
280
       // Bind a new element
366
 
 
367
 
 
368
 
 
 
281
       
 
282
       
 
283
       
369
284
       // Add a new file to the list
370
 
       MF.addToList = function( slave ){
371
 
 
 
285
       MultiFile.addToList = function( slave, slave_count ){
 
286
        //if(window.console) console.log('MultiFile.addToList',slave_count);
 
287
                                                                
372
288
        //# Trigger Event! onFileAppend
373
 
        if(!MF.trigger('onFileAppend', slave, MF)) return false;
 
289
        if(!MultiFile.trigger('onFileAppend', slave, MultiFile)) return false;
374
290
        //# End Event!
375
 
 
 
291
        
376
292
        // Create label elements
377
293
        var
378
 
         r = $('<div></div>'),
 
294
         r = $('<div class="MultiFile-label"></div>'),
379
295
         v = String(slave.value || ''/*.attr('value)*/),
380
 
         a = $('<span class="file" title="'+MF.STRING.selected.replace('$file', v)+'">'+v.match(/[^\/\\]+$/gi)[0]+'</span>'),
381
 
         b = $('<a href="#'+MF.wrapID+'">'+MF.STRING.remove+'</a>');
382
 
 
 
296
         a = $('<span class="MultiFile-title" title="'+MultiFile.STRING.selected.replace('$file', v)+'">'+MultiFile.STRING.file.replace('$file', v.match(/[^\/\\]+$/gi)[0])+'</span>'),
 
297
         b = $('<a class="MultiFile-remove" href="#'+MultiFile.wrapID+'">'+MultiFile.STRING.remove+'</a>');
 
298
        
383
299
        // Insert label
384
 
        MF.labels.append(
385
 
         r.append('[', b, ']&nbsp;', a)//.prepend(slave.i+': ')
 
300
        MultiFile.list.append(
 
301
         r.append(b, ' ', a)
386
302
        );
387
 
 
388
 
        b.click(function(){
389
 
 
 
303
        
 
304
        b
 
305
                                                                .click(function(){
 
306
         
390
307
          //# Trigger Event! onFileRemove
391
 
          if(!MF.trigger('onFileRemove', slave, MF)) return false;
 
308
          if(!MultiFile.trigger('onFileRemove', slave, MultiFile)) return false;
392
309
          //# End Event!
393
 
 
394
 
          MF.n--;
395
 
          MF.current.disabled = false;
396
 
 
 
310
          
 
311
          MultiFile.n--;
 
312
          MultiFile.current.disabled = false;
 
313
          
397
314
          // Remove element, remove label, point to current
398
 
          if(slave.i==0){
399
 
           $(MF.current).remove();
400
 
           MF.current = slave;
401
 
          }
402
 
          else{
403
 
           $(slave).remove();
404
 
          };
405
 
          $(this).parent().remove();
406
 
 
 
315
                                                                                MultiFile.slaves[slave_count] = null;
 
316
                                                                                $(slave).remove();
 
317
                                                                                $(this).parent().remove();
 
318
                                                                                
407
319
          // Show most current element again (move into view) and clear selection
408
 
          $(MF.current).css({ position:'', top: '' }).reset().val('').attr('value', '')[0].value = '';
409
 
 
 
320
          $(MultiFile.current).css({ position:'', top: '' });
 
321
                                                                                $(MultiFile.current).reset().val('').attr('value', '')[0].value = '';
 
322
          
410
323
          //# Trigger Event! afterFileRemove
411
 
          if(!MF.trigger('afterFileRemove', slave, MF)) return false;
 
324
          if(!MultiFile.trigger('afterFileRemove', slave, MultiFile)) return false;
412
325
          //# End Event!
413
 
 
414
 
 
 
326
                                                                                
415
327
          return false;
416
328
        });
417
 
 
 
329
        
418
330
        //# Trigger Event! afterFileAppend
419
 
        if(!MF.trigger('afterFileAppend', slave, MF)) return false;
 
331
        if(!MultiFile.trigger('afterFileAppend', slave, MultiFile)) return false;
420
332
        //# End Event!
421
 
 
422
 
       }; // MF.addToList
 
333
        
 
334
       }; // MultiFile.addToList
423
335
       // Add element to selected files list
424
 
 
425
 
 
426
 
 
 
336
       
 
337
       
 
338
       
427
339
       // Bind functionality to the first element
428
 
       if(!MF.MF) MF.addSlave(MF.e, 0);
429
 
 
 
340
       if(!MultiFile.MultiFile) MultiFile.addSlave(MultiFile.e, 0);
 
341
       
430
342
       // Increment control count
431
 
       //MF.I++; // using window.MultiFile
432
 
       MF.n++;
433
 
 
434
 
    });
435
 
    // each element
436
 
 
437
 
   }
438
 
   // MultiFile function
439
 
 
440
 
 });
441
 
 // extend jQuery function library
442
 
 
443
 
 
444
 
 
445
 
 /*
446
 
  ### Default implementation ###
447
 
  The plugin will attach itself to file inputs
448
 
  with the class 'multi' when the page loads
449
 
 */
450
 
 $(function(){ $.MultiFile() });
451
 
 
452
 
 
453
 
 
 
343
       //MultiFile.I++; // using window.MultiFile
 
344
       MultiFile.n++;
 
345
                                                        
 
346
                                                        // Save control to element
 
347
                                                        MultiFile.E.data('MultiFile', MultiFile);
 
348
                                                        
 
349
 
 
350
                        //#####################################################################
 
351
                        // MAIN PLUGIN FUNCTIONALITY - END
 
352
                        //#####################################################################
 
353
                }); // each element
 
354
        };
 
355
        
 
356
        /*--------------------------------------------------------*/
 
357
        
 
358
        /*
 
359
                ### Core functionality and API ###
 
360
        */
 
361
        $.extend($.fn.MultiFile, {
 
362
  /**
 
363
   * This method removes all selected files
 
364
   *
 
365
   * Returns a jQuery collection of all affected elements.
 
366
   *
 
367
   * @name reset
 
368
   * @type jQuery
 
369
   * @cat Plugins/MultiFile
 
370
   * @author Diego A. (http://www.fyneworks.com/)
 
371
   *
 
372
   * @example $.fn.MultiFile.reset();
 
373
   */
 
374
  reset: function(){
 
375
                        var settings = $(this).data('MultiFile');
 
376
                        //if(settings) settings.wrapper.find('a.MultiFile-remove').click();
 
377
                        if(settings) settings.list.find('a.MultiFile-remove').click();
 
378
   return $(this);
 
379
  },
 
380
  
 
381
  
 
382
  /**
 
383
   * This utility makes it easy to disable all 'empty' file elements in the document before submitting a form.
 
384
   * It marks the affected elements so they can be easily re-enabled after the form submission or validation.
 
385
   *
 
386
   * Returns a jQuery collection of all affected elements.
 
387
   *
 
388
   * @name disableEmpty
 
389
   * @type jQuery
 
390
   * @cat Plugins/MultiFile
 
391
   * @author Diego A. (http://www.fyneworks.com/)
 
392
   *
 
393
   * @example $.fn.MultiFile.disableEmpty();
 
394
   * @param String class (optional) A string specifying a class to be applied to all affected elements - Default: 'mfD'.
 
395
   */
 
396
  disableEmpty: function(klass){ klass = (typeof(klass)=='string'?klass:'')||'mfD';
 
397
   var o = [];
 
398
   $('input:file.MultiFile').each(function(){ if($(this).val()=='') o[o.length] = this; });
 
399
   return $(o).each(function(){ this.disabled = true }).addClass(klass);
 
400
  },
 
401
  
 
402
  
 
403
                /**
 
404
                        * This method re-enables 'empty' file elements that were disabled (and marked) with the $.fn.MultiFile.disableEmpty method.
 
405
                        *
 
406
                        * Returns a jQuery collection of all affected elements.
 
407
                        *
 
408
                        * @name reEnableEmpty
 
409
                        * @type jQuery
 
410
                        * @cat Plugins/MultiFile
 
411
                        * @author Diego A. (http://www.fyneworks.com/)
 
412
                        *
 
413
                        * @example $.fn.MultiFile.reEnableEmpty();
 
414
                        * @param String klass (optional) A string specifying the class that was used to mark affected elements - Default: 'mfD'.
 
415
                        */
 
416
  reEnableEmpty: function(klass){ klass = (typeof(klass)=='string'?klass:'')||'mfD';
 
417
   return $('input:file.'+klass).removeClass(klass).each(function(){ this.disabled = false });
 
418
  },
 
419
  
 
420
  
 
421
                /**
 
422
                        * This method will intercept other jQuery plugins and disable empty file input elements prior to form submission
 
423
                        *
 
424
        
 
425
                        * @name intercept
 
426
                        * @cat Plugins/MultiFile
 
427
                        * @author Diego A. (http://www.fyneworks.com/)
 
428
                        *
 
429
                        * @example $.fn.MultiFile.intercept();
 
430
                        * @param Array methods (optional) Array of method names to be intercepted
 
431
                        */
 
432
  intercepted: {},
 
433
  intercept: function(methods, context, args){
 
434
   var method, value; args = args || [];
 
435
   if(args.constructor.toString().indexOf("Array")<0) args = [ args ];
 
436
   if(typeof(methods)=='function'){
 
437
    $.fn.MultiFile.disableEmpty();
 
438
    value = methods.apply(context || window, args);
 
439
                                //SEE-http://code.google.com/p/jquery-multifile-plugin/issues/detail?id=27
 
440
                                setTimeout(function(){ $.fn.MultiFile.reEnableEmpty() },1000);
 
441
    return value;
 
442
   };
 
443
   if(methods.constructor.toString().indexOf("Array")<0) methods = [methods];
 
444
   for(var i=0;i<methods.length;i++){
 
445
    method = methods[i]+''; // make sure that we have a STRING
 
446
    if(method) (function(method){ // make sure that method is ISOLATED for the interception
 
447
     $.fn.MultiFile.intercepted[method] = $.fn[method] || function(){};
 
448
     $.fn[method] = function(){
 
449
      $.fn.MultiFile.disableEmpty();
 
450
      value = $.fn.MultiFile.intercepted[method].apply(this, arguments);
 
451
                                                //SEE-http://code.google.com/p/jquery-multifile-plugin/issues/detail?id=27
 
452
      setTimeout(function(){ $.fn.MultiFile.reEnableEmpty() },1000);
 
453
      return value;
 
454
     }; // interception
 
455
    })(method); // MAKE SURE THAT method IS ISOLATED for the interception
 
456
   };// for each method
 
457
  }
 
458
 });
 
459
        
 
460
        /*--------------------------------------------------------*/
 
461
        
 
462
        /*
 
463
                ### Default Settings ###
 
464
                eg.: You can override default control like this:
 
465
                $.fn.MultiFile.options.accept = 'gif|jpg';
 
466
        */
 
467
        $.fn.MultiFile.options = { //$.extend($.fn.MultiFile, { options: {
 
468
                accept: '', // accepted file extensions
 
469
                max: -1,    // maximum number of selectable files
 
470
                
 
471
                // name to use for newly created elements
 
472
                namePattern: '$name', // same name by default (which creates an array)
 
473
                
 
474
                // STRING: collection lets you show messages in different languages
 
475
                STRING: {
 
476
                        remove:'x',
 
477
                        denied:'You cannot select a $ext file.\nTry again...',
 
478
                        file:'$file',
 
479
                        selected:'File selected: $file',
 
480
                        duplicate:'This file has already been selected:\n$file'
 
481
                },
 
482
                
 
483
                // name of methods that should be automcatically intercepted so the plugin can disable
 
484
                // extra file elements that are empty before execution and automatically re-enable them afterwards
 
485
  autoIntercept: [ 'submit', 'ajaxSubmit', 'ajaxForm', 'validate' /* array of methods to intercept */ ],
 
486
                
 
487
                // error handling function
 
488
                error: function(s){
 
489
                        /*
 
490
                        ERROR! blockUI is not currently working in IE
 
491
                        if($.blockUI){
 
492
                                $.blockUI({
 
493
                                        message: s.replace(/\n/gi,'<br/>'),
 
494
                                        css: { 
 
495
                                                border:'none', padding:'15px', size:'12.0pt',
 
496
                                                backgroundColor:'#900', color:'#fff',
 
497
                                                opacity:'.8','-webkit-border-radius': '10px','-moz-border-radius': '10px'
 
498
                                        }
 
499
                                });
 
500
                                window.setTimeout($.unblockUI, 2000);
 
501
                        }
 
502
                        else//{// save a byte!
 
503
                        */
 
504
                         alert(s);
 
505
                        //}// save a byte!
 
506
                }
 
507
 }; //} });
 
508
        
 
509
        /*--------------------------------------------------------*/
 
510
        
 
511
        /*
 
512
                ### Additional Methods ###
 
513
                Required functionality outside the plugin's scope
 
514
        */
 
515
        
 
516
        // Native input reset method - because this alone doesn't always work: $(element).val('').attr('value', '')[0].value = '';
 
517
        $.fn.reset = function(){ return this.each(function(){ try{ this.reset(); }catch(e){} }); };
 
518
        
 
519
        /*--------------------------------------------------------*/
 
520
        
 
521
        /*
 
522
                ### Default implementation ###
 
523
                The plugin will attach itself to file inputs
 
524
                with the class 'multi' when the page loads
 
525
        */
 
526
        $(function(){
 
527
  //$("input:file.multi").MultiFile();
 
528
  $("input[type=file].multi").MultiFile();
 
529
 });
 
530
        
 
531
        
 
532
        
454
533
/*# AVOID COLLISIONS #*/
455
534
})(jQuery);
456
535
/*# AVOID COLLISIONS #*/