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