1// 2// This plugin implements the handling of Upload 3// works together with AdminUploadController 4// 5(function($){ 6 var methods = { 7 init : function(options) { 8 return this.each(function(){ 9 var $this = $(this); 10 if ($this.data('upload')) { 11 return; // the plugin has been initialized already 12 } 13 14 var params = $.extend({ 15 onChange : function(filesCount) {}, 16 onFileAdd : function(info) {}, 17 onFileDraw : function(info) {}, 18 onSelect : function(){}, 19 onSubmit : function(){}, 20 fileMime : false, // A list of file MIME types that are allowed for upload. 21 fileMaxSize : false, //Maximum file size in bytes 22 fileBrowser : true, //whether init file browser 23 urlUpload : '/admin-upload/upload', 24 urlGet : '/admin-upload/get' 25 }, options); 26 27 $this. 28 data('params', params). 29 data('upload', 1); 30 31 var name = $this.attr('name'); 32 var end = name.substr(name.length-2, 2); 33 var info = $this.upload('info'); 34 var error = $this.upload('error'); 35 var i; 36 37 var $el = $this.closest('.element'); 38 $el.prepend($('<input type="hidden" value="-1">').attr('name', name)); 39 for (i=0; i < error.length; i++) { 40 var $span = $('<span class="error"></span>').text(error[i]); 41 $el.append($span); 42 } 43 44 if (end=='[]') { 45 $this.data('multiple', 1); 46 } 47 48 $this.upload('drawUpload'); 49 50 if ($this.attr('value')) { 51 if ($this.data('multiple')) { 52 var values = $this.attr('value').split(','); 53 for (i=0; i<values.length; i++) { 54 info[values[i]].upload_id = values[i]; 55 $this.upload('drawFile', info[values[i]]); 56 } 57 } else { 58 info[$this.attr('value')].upload_id = $this.attr('value'); 59 $(this).upload('drawFile', info[$this.attr('value')]); 60 } 61 } 62 $this.hide(); 63 $this.attr('disabled', 'disabled'); 64 $this.data('params').onChange.call($this, $this.upload('count')); 65 }); 66 } 67 , 68 increaseCount : function() { 69 this.data('count', this.upload('count')+1); 70 71 //in order to JS validation works 72 if (this.upload('count') == 1) { 73 //remove error message of JS validation 74 this.parent().find('.error').not('input').remove(); 75 } 76 } 77 , 78 decreaseCount : function() { 79 this.data('count', this.upload('count')-1); 80 } 81 , 82 count : function() { 83 return this.data('count') ? this.data('count') : 0; 84 } 85 , 86 drawFile : function(info) { 87 var $this = this; 88 89 $this.upload('destroyUploader'); 90 var $a = $('<a href="javascript:;" class="local local-link">x</a>'); 91 var $div = $('<div></div>'); 92 var $aFile = $('<a class="link"></a>'); 93 $aFile.attr('href', window.rootUrl + $this.data('params').urlGet + '?id=' + info.upload_id.toString().split('|', 2)[0]). 94 attr('target', '_top'); 95 96 $this.before( 97 $div.append($aFile.append(info.name)).append(' (' + info.size_readable + ')'). 98 append(' [').append($a).append(']').append( 99 $('<input type="hidden" />'). 100 attr('name', $this.attr('name')). 101 attr('value', info.upload_id))); 102 $a.click(function(){ 103 $(this).closest('div').remove(); 104 $this.upload('decreaseCount'); 105 $this.upload('destroyUploader'); 106 $this.upload('drawUpload'); 107 $this.data('params').onChange.call($this, $this.upload('count')); 108 }); 109 $this.data('params').onFileDraw.call($this, info); 110 $this.upload('increaseCount'); 111 $this.upload('drawUpload'); 112 } 113 , 114 drawUpload : function(){ 115 var $this = this; 116 117 $this.upload('destroyUploader'); 118 if (!$this.data('multiple') && $this.upload('count')) { 119 return; 120 } 121 var $a = ($this.data('params').fileBrowser ? $('<div class="upload-control-browse"><span>browse</span></div>') : '');
122 var $wrapper = $('<div class="upload-control"></div>'); 123 if ($this.upload('count')) { 124 $wrapper.css('margin-top', '1em'); 125 } 126 var $uploader = $this.upload('getUploader'); 127 $this.before( 128 $wrapper.append($uploader).append($a)); 129 $this.data('params').fileBrowser && $a.before(' '); 130 var $div = $('<div></div>'); 131 $('body').append($div); 132 $div.hide(); 133 $div.addClass('filesmanager-container'); 134 //so grid can update this 135 $div.get(0).uploader = $this; 136 if ($this.data('params').fileBrowser) { 137 $a.click(function(){ 138 $div.dialog({ 139 modal : true, 140 title : "Uploaded Files", 141 width : 800, 142 height: 600, 143 position : ['center', 100], 144 buttons : { 145 Cancel : function(){ 146 $(this).dialog("close"); 147 } 148 }, 149 open : function(){ 150 $.get(window.rootUrl + '/admin-upload/grid', { 151 prefix: $this.data('prefix'), 152 secure: $this.data('secure') 153 }, function(data, textStatus, jqXHR){ 154 $div.empty().append(data); 155 $(".grid-wrap").ngrid(); 156 }); 157 }, 158 close : function() { 159 $div.empty(); 160 $div.remove(); 161 } 162 }); 163 }); 164 165 166 $a.bind('mouseover mouseout', function(){ 167 $a.toggleClass('hover'); 168 }); 169 } 170 171 $this.upload('initUploader', $uploader); 172 } 173 , 174 addFile: function(info) { 175 var $this = this; 176 177 if (!info.ok) { 178 alert('Error: ' + info.error); 179 $this.upload('drawUpload'); 180 return; 181 } else if ($this.data('params').fileMime && 182 $.inArray(info.mime, $this.data('params').fileMime) == -1) { 183 184 alert('Incorrect file type : ' + 185 info.mime + 186 '. Expect one of: ' + 187 $this.data('params').fileMime.join(', ')); 188 $this.upload('drawUpload'); 189 return; 190 } 191 $(this).upload('drawFile', info); 192 $this.data('params').onChange.call($this, $this.upload('count')); 193 $this.data('params').onFileAdd.call($this, info); 194 } 195 , 196 info: function() { 197 return this.data("info"); 198 } 199 , 200 error: function() { 201 return this.data("error"); 202 } 203 , 204 destroyUploader : function() { 205 var $this = this; 206 207 //remove setInterval to avoide mempry leak 208 var $uploader = $this.closest('div').find('.upload-control-upload'); 209 $uploader.data('intervalId') && clearInterval($uploader.data('intervalId')); 210 211 $this.closest('div').find('div.upload-control').remove(); 212 $('#uploader-iframe-' + $this.attr('id')).remove(); 213 $('#uploader-form-' + $this.attr('id')).remove(); 214 } 215 , 216 getUploader : function() { 217 var $this = this; 218 var aUpload = $('<span>upload</span>'); 219 var $uploader = $('<div class="upload-control-upload"></div>').css({ 220 display: 'inline-block', 221 overflow: 'hidden', 222 'float':'left' 223 }).append(aUpload); 224 !$this.data('params').fileBrowser && $uploader.addClass('upload-control-upload-single'); 225 return $uploader; 226 } 227 , 228 initUploader : function($uploader) { 229 var $this = this; 230 231 var uploaderId = $this.attr('id'); 232 233 var $input = $('<input type="file" />').attr('name', 'upload'); 234 var $form = $('<form></form>').attr({ 235 method : 'post', 236 enctype : 'multipart/form-data', 237 action : window.rootUrl + $this.data('params').urlUpload, 238 target : 'uploader-iframe-' + uploaderId, 239 id : 'uploader-form-' + uploaderId 240 }).css({ 241 margin: 0, 242 padding: 0 243 }); 244 245 var $input_hidden = $('<input />').attr({ 246 name : 'prefix', 247 value : $this.data('prefix'), 248 type : 'hidden' 249 }); 250 251 var $input_hidden_secure = $('<input />').attr({ 252 name : 'secure', 253 value : $this.data('secure'), 254 type : 'hidden' 255 }); 256 257 $form.append($input_hidden).append($input_hidden_secure); 258 if ($this.data('params').fileMaxSize) { 259 var $input_hidden_limit = $('<input />').attr({ 260 name : 'MAX_FILE_SIZE', 261 value : $this.data('params').fileMaxSize, 262 type : 'hidden' 263 }); 264 $form.append($input_hidden_limit); 265 } 266 $form.append($input); 267 268 var $frame = $('<iframe></iframe>').attr({ 269 name : 'uploader-iframe-' + uploaderId, 270 id : 'uploader-iframe-' + uploaderId 271 }); 272 273 $('body').append($form); 274 $('body').append($frame); 275 $frame.hide(); 276 277 var $div = $input.wrap('<div></div>').parent().css({ 278 overflow : 'hidden', 279 width : $uploader.outerWidth(), 280 height : $uploader.outerHeight() 281 }).css({ 282 position : 'absolute', 283 'z-index' : 10000 284 }); 285 286 //allow some time to colculate size for $uploader 287 setTimeout(function(){ 288 $div.css({ 289 width : $uploader.outerWidth(), 290 height : $uploader.outerHeight() 291 }); 292 }, 100); 293 294 //emulate onresize event 295 var intervalId = setInterval(function(){ 296 if ($div.css('width')!=$uploader.outerWidth()) { 297 $div.css('width', $uploader.outerWidth()); 298 } 299 300 if ($div.css('height')!=$uploader.outerHeight()) { 301 $div.css('height', $uploader.outerHeight()); 302 } 303 }, 250); 304 //remember inetrval id to clear setInterval in destructure 305 $uploader.data('intervalId', intervalId); 306 307 $input.css({ 308 'float':'right' 309 }); 310 $div.css({ 311 opacity: 0, 312 display: 'none' 313 }); 314 315 $input.bind('mouseover mouseout', function(){ 316 $uploader.toggleClass('hover'); 317 }); 318 319 $uploader.mousemove(function(e){ 320 $div.css({ 321 display: 'block', 322 top: $uploader.offset().top+'px', 323 left: $uploader.offset().left+'px' 324 }); 325 }); 326 327 $input.change(function() { 328 $this.data('params').onSelect.call($this); 329 330 $this.data('params').onSubmit.call($this); 331 332 $uploader.find('span').empty().append('Uploading...').addClass('uploading'); 333 334 $form.submit(); 335 336 $frame.load(function() { 337 var frame = document.getElementById($frame.attr('id')); 338 var response = $(frame.contentWindow.document.body).text(); 339 //console.log(response); 340 try { 341 response = $.parseJSON(response); 342 } catch (e) { 343 response = { 344 ok : false, 345 error : 'Error of file uploading on server side' 346 }; 347 } 348 //console.log(response); 349 //allow to complete 'load' event up to the end 350 //before remove this element 351 setTimeout(function(){ 352 $this.upload('addFile', response); 353 }, 10); 354 }); 355 356 }); 357 } 358 359 }; 360 361 $.fn.upload = function(method) { 362 if ( methods[method] ) { 363 return methods[method].apply( this, Array.prototype.slice.call(arguments, 1)); 364 } else if (typeof method === 'object' || ! method) { 365 return methods.init.apply(this, arguments); 366 } else { 367 $.error('Method ' + method + ' does not exist on jQuery.upload'); 368 } 369 }; 370 371})(jQuery);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.