厚积薄发
end: blogTitle 博客的标题和副标题
- 博客园
- 首页
- 新随笔
- 联系
- 订阅 <a id="blog_nav_rss_image" class="aHeaderXML" href="http://www.cnblogs.com/dee0912/rss"><img src="//www.cnblogs.com/images/xml.gif" alt="订阅" /></a>
- 管理
done 随笔-305 文章-65 评论-38
end: blogStats
end: navigator 博客导航栏
end: header 头部
done
jQuery File Upload 的 GitHub 地址:https://github.com/blueimp/jQuery-File-Upload
插件描述:jQuery File Upload 是一个 jQuery 图片上传组件,支持多文件上传、取消、删除,上传前缩略图预览、列表显示图片大小,支持上传进度条显示。插件基于开放的标准,如 HTML5 和 JavaScript ,不需要额外的浏览器插件(例如使用Adobe 的 Flash ),在旧版浏览器中使用 XMLHttpRequest 上传文件。(参见:http://www.jq22.com/jquery-info230)。
需求:在一个页面中包含多个插件实例。例如在生鲜电商网站后台的食谱添加/编辑页面,需要上传/编辑一道菜的食材和配料,就需要在页面中同时包含两个上传实例。插件的文档中有关于单页面多实例的介绍:Multiple File Upload Widgets on the same page,里面说明很简单,把 demo 中 index.html 的 form 表单的 id 改成 class,再简单修改 js/main.js 就可以了。
在很天真的试过之后,发现根本不是这么回事,index.html 中文件域的 name 是写死的,根本无法满足单页面多实例的需求,只能对插件进行修改...而且在改完之后发现修改的工作量很大。
代码是在 demo 的基础上,后端使用 php,删除了不需要的文件,比如其他后端语言处理程序。没有做数据验证和入库等处理,展示页面直接遍历文件夹读取文件。
最终效果图:
初始界面
上传图片及刷新页面
文件结构及主要修改文件
js
server
/index.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 | <!DOCTYPE HTML> <!-- /* * jQuery File Upload Plugin Demo 9.1.0 * https://github.com/blueimp/jQuery-File-Upload * * Copyright 2010, Sebastian Tschan * https://blueimp.net * * Licensed under the MIT license: * http://www.opensource.org/licenses/MIT */ --> <html lang="en"> <head> <!-- Force latest IE rendering engine or ChromeFrame if installed --> <!--[if IE]> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> <![endif]--> <meta charset="utf-8"> <title>jQuery File Upload Demo</title> <meta name="description" content="File Upload widget with multiple file selection, drag&drop support, progress bars, validation and preview images, audio and video for jQuery. Supports cross-domain, chunked and resumable file uploads and client-side image resizing. Works with any server-side platform (PHP, Python, Ruby on Rails, Java, Node.js, Go etc.) that supports standard HTML form file uploads."> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <!-- Bootstrap styles --> <link rel="stylesheet" href="css/bootstrap.min.css"> <!-- Generic page styles --> <link rel="stylesheet" href="css/style.css"> <!-- blueimp Gallery styles --> <link rel="stylesheet" href="css/blueimp-gallery.min.css"> <!-- CSS to style the file input field as button and adjust the Bootstrap progress bars --> <link rel="stylesheet" href="css/jquery.fileupload.css"> <!-- <link rel="stylesheet" href="css/jquery.fileupload-ui.css"> --> <!-- CSS adjustments for browsers with JavaScript disabled --> <noscript><link rel="stylesheet" href="css/jquery.fileupload-noscript.css"></noscript> <noscript><link rel="stylesheet" href="css/jquery.fileupload-ui-noscript.css"></noscript> </head> <body> <div class="container"> <!-- The file upload form used as target for the file upload widget --> <form class="fileupload" action="server/php" method="POST" enctype="multipart/form-data"> <!-- The fileupload-buttonbar contains buttons to add/delete files and start/cancel the upload --> <div class="row fileupload-buttonbar"> <div class="col-lg-7"> <!-- The fileinput-button span is used to style the file input field as button --> <span class="btn btn-primary">食材</span> <span class="btn btn-success fileinput-button"> <i class="glyphicon glyphicon-plus"></i> <span>Add files...</span> <input type="file" name="food[]" multiple> </span> <button type="submit" class="btn btn-primary start"> <i class="glyphicon glyphicon-upload"></i> <span>Start upload</span> </button> <button type="reset" class="btn btn-warning cancel"> <i class="glyphicon glyphicon-ban-circle"></i> <span>Cancel upload</span> </button> <button type="button" class="btn btn-danger delete"> <i class="glyphicon glyphicon-trash"></i> <span>Delete</span> </button> <input type="checkbox" class="toggle"> <!-- The global file processing state --> <span class="fileupload-process"></span> </div> <!-- The global progress state --> <div class="col-lg-5 fileupload-progress fade"> <!-- The global progress bar --> <div class="progress progress-striped active" role="progressbar" aria-valuemin="0" aria-valuemax="100"> <div class="progress-bar progress-bar-success" style="width:0%;"></div> </div> <!-- The extended global progress state --> <div class="progress-extended"> </div> </div> </div> <!-- The table listing the files available for upload/download --> <table role="presentation" class="table table-striped"><tbody class="files"></tbody></table> </form> <!-- Multiple File Upload Widgets on the same page --> <form class="fileupload" action="server/php" method="POST" enctype="multipart/form-data"> <!-- The fileupload-buttonbar contains buttons to add/delete files and start/cancel the upload --> <div class="row fileupload-buttonbar"> <div class="col-lg-7"> <!-- The fileinput-button span is used to style the file input field as button --> <span class="btn btn-primary">配料</span> <span class="btn btn-success fileinput-button"> <i class="glyphicon glyphicon-plus"></i> <span>Add files...</span> <input type="file" name="batching[]" multiple> </span> <button type="submit" class="btn btn-primary start"> <i class="glyphicon glyphicon-upload"></i> <span>Start upload</span> </button> <button type="reset" class="btn btn-warning cancel"> <i class="glyphicon glyphicon-ban-circle"></i> <span>Cancel upload</span> </button> <button type="button" class="btn btn-danger delete"> <i class="glyphicon glyphicon-trash"></i> <span>Delete</span> </button> <input type="checkbox" class="toggle"> <!-- The global file processing state --> <span class="fileupload-process"></span> </div> <!-- The global progress state --> <div class="col-lg-5 fileupload-progress fade"> <!-- The global progress bar --> <div class="progress progress-striped active" role="progressbar" aria-valuemin="0" aria-valuemax="100"> <div class="progress-bar progress-bar-success" style="width:0%;"></div> </div> <!-- The extended global progress state --> <div class="progress-extended"> </div> </div> </div> <!-- The table listing the files available for upload/download --> <table role="presentation" class="table table-striped"><tbody class="files"></tbody></table> </form> </div> <!-- The blueimp Gallery widget --> <div id="blueimp-gallery" class="blueimp-gallery blueimp-gallery-controls" data-filter=":even"> <div class="slides"></div> <h3 class="title"></h3> <a class="prev">‹</a> <a class="next">›</a> <a class="close">×</a> <a class="play-pause"></a> <ol class="indicator"></ol> </div> <!-- The template to display files available for upload --> <script id="template-upload" type="text/x-tmpl"> {% for (var i=0, file; file=o.files[i]; i++) { %} <tr class="template-upload fade"> <td> <span class="preview"></span> </td> <td> <p class="name">{%=file.name%}</p> <strong class="error text-danger"></strong> </td> <td> <p class="size">Processing...</p> <div class="progress progress-striped active" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0"><div class="progress-bar progress-bar-success" style="width:0%;"></div></div> </td> <td> {% if (!i && !o.options.autoUpload) { %} <button class="btn btn-primary start" disabled> <i class="glyphicon glyphicon-upload"></i> <span>Start</span> </button> {% } %} {% if (!i) { %} <button class="btn btn-warning cancel"> <i class="glyphicon glyphicon-ban-circle"></i> <span>Cancel</span> </button> {% } %} </td> </tr> {% } %} </script> <!-- The template to display files available for download --> <script id="template-download" type="text/x-tmpl"> {% for (var i=0, file; file=o.files[i]; i++) { %} <tr class="template-download fade"> <td> <span class="preview"> {% if (file.thumbnailUrl) { %} <a href="{%=file.url%}" title="{%=file.name%}" download="{%=file.name%}" data-gallery><img src="{%=file.thumbnailUrl%}"></a> {% } %} </span> </td> <td> <p class="name"> {% if (file.url) { %} <a href="{%=file.url%}" title="{%=file.name%}" download="{%=file.name%}" {%=file.thumbnailUrl?'data-gallery':''%}>{%=file.name%}</a> {% } else { %} <span>{%=file.name%}</span> {% } %} </p> {% if (file.error) { %} <div><span class="label label-danger">Error</span> {%=file.error%}</div> {% } %} </td> <td> <span class="size">{%=o.formatFileSize(file.size)%}</span> </td> <td> {% if (file.deleteUrl) { %} <button class="btn btn-danger delete" data-type="{%=file.deleteType%}" data-url="{%=file.deleteUrl%}"{% if (file.deleteWithCredentials) { %} data-xhr-fields='{"withCredentials":true}'{% } %}> <i class="glyphicon glyphicon-trash"></i> <span>Delete</span> </button> <input type="checkbox" name="delete" value="1" class="toggle"> {% } else { %} <button class="btn btn-warning cancel"> <i class="glyphicon glyphicon-ban-circle"></i> <span>Cancel</span> </button> {% } %} </td> </tr> {% } %} </script> <script src="js/jquery/1.10.2/jquery.min.js"></script> <!-- The jQuery UI widget factory, can be omitted if jQuery UI is already included --> <script src="js/vendor/jquery.ui.widget.js"></script> <!-- The Templates plugin is included to render the upload/download listings --> <script src="js/tmpl.min.js"></script> <!-- The Load Image plugin is included for the preview images and image resizing functionality --> <script src="js/load-image.all.min.js"></script> <!-- The Canvas to Blob plugin is included for image resizing functionality --> <script src="js/canvas-to-blob.min.js"></script> <!-- Bootstrap JS is not required, but included for the responsive demo navigation --> <script src="js/bootstrap/3.0.0/js/bootstrap.min.js"></script> <!-- blueimp Gallery script --> <script src="js/jquery.blueimp-gallery.min.js"></script> <!-- The Iframe Transport is required for browsers without support for XHR file uploads --> <script src="js/jquery.iframe-transport.js"></script> <!-- The basic File Upload plugin --> <script src="js/jquery.fileupload.js"></script> <!-- The File Upload processing plugin --> <script src="js/jquery.fileupload-process.js"></script> <!-- The File Upload image preview & resize plugin --> <script src="js/jquery.fileupload-image.js"></script> <!-- The File Upload audio preview plugin --> <script src="js/jquery.fileupload-audio.js"></script> <!-- The File Upload video preview plugin --> <script src="js/jquery.fileupload-video.js"></script> <!-- The File Upload validation plugin --> <script src="js/jquery.fileupload-validate.js"></script> <!-- The File Upload user interface plugin --> <script src="js/jquery.fileupload-ui.js"></script> <!-- The main application script --> <script src="js/main.js"></script> <!-- The XDomainRequest Transport is included for cross-domain file deletion for IE 8 and IE 9 --> <!--[if (gte IE 8)&(lt IE 10)]> <script src="js/cors/jquery.xdr-transport.js"></script> <![endif]--> </body> <script> // $('.fileupload').fileupload({ // // Uncomment the following to send cross-domain cookies: // //xhrFields: {withCredentials: true}, // url: 'server/php/?fields=shirt,sweater', // }); var fields = 'food,batching'; $('.fileupload').fileupload({ url: 'server/php/?fields=' + fields, add: function (e, data) { // 不用点击直接上传 var jqXHR = data.submit() .success(function (result, textStatus, jqXHR) {}) .error(function (jqXHR, textStatus, errorThrown) {}) .complete(function (result, textStatus, jqXHR) {}); } });
$.ajax({ url: 'server/php/?fields=' + fields, success(data) { var dataObj = JSON.parse(data); $.each(dataObj, function(name, value) { $.each(value, function(k, v){ var item = '<tr class="template-download fade in">'; item += '<td><span class="preview"><a data-gallery="" download="' + v.name + '" title="' + v.name + '" href="' + v.url + '"><img src="' + v.thumbnailUrl + '"></a></span></td><td><p class="name"><a data-gallery="" download="' + v.name + '" title="' + v.url + '" href="' + v.url + '">' + v.name + '</a></p></td><td><span class="size">' + (v.size / 1000) + ' KB</span></td><td>';
item += '<button data-url="' + v.deleteUrl + '" data-type="' + v.deleteType + '" class="btn btn-danger delete" ><i class="glyphicon glyphicon-trash"></i><span>Delete</span></button>'; item += ' <input type="checkbox" class="toggle" value="1" name="delete"></td></tr>';
var $item = $(item); $input_file = eval($("input[type='file'][name='" + name + "[]']")); $item.appendTo($input_file.parents('.fileupload-buttonbar').siblings('.table-striped').children('.files')); }); }); } }); </script> </html> |
说明:
通过 fields 来配置文件中不同的文件域,多个文件域的 name 用逗号 , 隔开。这是修改后 demo 中唯一需要根据页面文件域 name 的不同要做配置地方
1 | var fields = 'food,batching'; |
/js/jquery.fileupload-ui.js
修改 $.widget('blueimp.fileupload', $.blueimp.fileupload, {}) 中 的 getFilesFromResponse
1 2 3 4 5 6 7 8 9 10 11 | getFilesFromResponse: function (data) { var paramName = JSON.stringify(data.paramName); if(paramName) { var files = paramName.slice(2,-4); } // console.log(files,eval("data.result."+files)); if (data.result && $.isArray(eval("data.result."+files))) { return eval("data.result."+files); } return []; }, |
把写死的 files 改成页面中实际的 name
完整文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 | /* * jQuery File Upload User Interface Plugin 9.6.0 * https://github.com/blueimp/jQuery-File-Upload * * Copyright 2010, Sebastian Tschan * https://blueimp.net * * Licensed under the MIT license: * http://www.opensource.org/licenses/MIT */
/* jshint nomen:false */ /* global define, window */
(function (factory) { 'use strict'; if (typeof define === 'function' && define.amd) { // Register as an anonymous AMD module: define([ 'jquery', 'tmpl', './jquery.fileupload-image', './jquery.fileupload-audio', './jquery.fileupload-video', './jquery.fileupload-validate' ], factory); } else { // Browser globals: factory( window.jQuery, window.tmpl ); } }(function ($, tmpl) { 'use strict';
$.blueimp.fileupload.prototype._specialOptions.push( 'filesContainer', 'uploadTemplateId', 'downloadTemplateId' );
// The UI version extends the file upload widget // and adds complete user interface interaction: $.widget('blueimp.fileupload', $.blueimp.fileupload, {
options: { // By default, files added to the widget are uploaded as soon // as the user clicks on the start buttons. To enable automatic // uploads, set the following option to true: autoUpload: false, // The ID of the upload template: uploadTemplateId: 'template-upload', // The ID of the download template: downloadTemplateId: 'template-download', // The container for the list of files. If undefined, it is set to // an element with class "files" inside of the widget element: filesContainer: undefined, // By default, files are appended to the files container. // Set the following option to true, to prepend files instead: prependFiles: false, // The expected data type of the upload response, sets the dataType // option of the $.ajax upload requests: dataType: 'json',
// Error and info messages: messages: { unknownError: 'Unknown error' },
// Function returning the current number of files, // used by the maxNumberOfFiles validation: getNumberOfFiles: function () { return this.filesContainer.children() .not('.processing').length; },
// Callback to retrieve the list of files from the server response: getFilesFromResponse: function (data) { var paramName = JSON.stringify(data.paramName); if(paramName) { var files = paramName.slice(2,-4); } // console.log(files,eval("data.result."+files)); if (data.result && $.isArray(eval("data.result."+files))) { return eval("data.result."+files); } return []; },
// The add callback is invoked as soon as files are added to the fileupload // widget (via file input selection, drag & drop or add API call). // See the basic file upload widget for more information: add: function (e, data) { if (e.isDefaultPrevented()) { return false; } var $this = $(this), that = $this.data('blueimp-fileupload') || $this.data('fileupload'), options = that.options; data.context = that._renderUpload(data.files) .data('data', data) .addClass('processing'); options.filesContainer[ options.prependFiles ? 'prepend' : 'append' ](data.context); that._forceReflow(data.context); that._transition(data.context); data.process(function () { return $this.fileupload('process', data); }).always(function () { data.context.each(function (index) { $(this).find('.size').text( that._formatFileSize(data.files[index].size) ); }).removeClass('processing'); that._renderPreviews(data); }).done(function () { data.context.find('.start').prop('disabled', false); if ((that._trigger('added', e, data) !== false) && (options.autoUpload || data.autoUpload) && data.autoUpload !== false) { data.submit(); } }).fail(function () { if (data.files.error) { data.context.each(function (index) { var error = data.files[index].error; if (error) { $(this).find('.error').text(error); } }); } }); }, // Callback for the start of each file upload request: send: function (e, data) { if (e.isDefaultPrevented()) { return false; } var that = $(this).data('blueimp-fileupload') || $(this).data('fileupload'); if (data.context && data.dataType && data.dataType.substr(0, 6) === 'iframe') { // Iframe Transport does not support progress events. // In lack of an indeterminate progress bar, we set // the progress to 100%, showing the full animated bar: data.context .find('.progress').addClass( !$.support.transition && 'progress-animated' ) .attr('aria-valuenow', 100) .children().first().css( 'width', '100%' ); } return that._trigger('sent', e, data); }, // Callback for successful uploads: done: function (e, data) { if (e.isDefaultPrevented()) { return false; } var that = $(this).data('blueimp-fileupload') || $(this).data('fileupload'), getFilesFromResponse = data.getFilesFromResponse || that.options.getFilesFromResponse, files = getFilesFromResponse(data), template, deferred; if (data.context) { data.context.each(function (index) { var file = files[index] || {error: 'Empty file upload result'}; deferred = that._addFinishedDeferreds(); that._transition($(this)).done( function () { var node = $(this); template = that._renderDownload([file]) .replaceAll(node); that._forceReflow(template); that._transition(template).done( function () { data.context = $(this); that._trigger('completed', e, data); that._trigger('finished', e, data); deferred.resolve(); } ); } ); }); } else { template = that._renderDownload(files)[ that.options.prependFiles ? 'prependTo' : 'appendTo' ](that.options.filesContainer); that._forceReflow(template); deferred = that._addFinishedDeferreds(); that._transition(template).done( function () { data.context = $(this); that._trigger('completed', e, data); that._trigger('finished', e, data); deferred.resolve(); } ); } }, // Callback for failed (abort or error) uploads: fail: function (e, data) { if (e.isDefaultPrevented()) { return false; } var that = $(this).data('blueimp-fileupload') || $(this).data('fileupload'), template, deferred; if (data.context) { data.context.each(function (index) { if (data.errorThrown !== 'abort') { var file = data.files[index]; file.error = file.error || data.errorThrown || data.i18n('unknownError'); deferred = that._addFinishedDeferreds(); that._transition($(this)).done( function () { var node = $(this); template = that._renderDownload([file]) .replaceAll(node); that._forceReflow(template); that._transition(template).done( function () { data.context = $(this); that._trigger('failed', e, data); that._trigger('finished', e, data); deferred.resolve(); } ); } ); } else { deferred = that._addFinishedDeferreds(); that._transition($(this)).done( function () { $(this).remove(); that._trigger('failed', e, data); that._trigger('finished', e, data); deferred.resolve(); } ); } }); } else if (data.errorThrown !== 'abort') { data.context = that._renderUpload(data.files)[ that.options.prependFiles ? 'prependTo' : 'appendTo' ](that.options.filesContainer) .data('data', data); that._forceReflow(data.context); deferred = that._addFinishedDeferreds(); that._transition(data.context).done( function () { data.context = $(this); that._trigger('failed', e, data); that._trigger('finished', e, data); deferred.resolve(); } ); } else { that._trigger('failed', e, data); that._trigger('finished', e, data); that._addFinishedDeferreds().resolve(); } }, // Callback for upload progress events: progress: function (e, data) { if (e.isDefaultPrevented()) { return false; } var progress = Math.floor(data.loaded / data.total * 100); if (data.context) { data.context.each(function () { $(this).find('.progress') .attr('aria-valuenow', progress) .children().first().css( 'width', progress + '%' ); }); } }, // Callback for global upload progress events: progressall: function (e, data) { if (e.isDefaultPrevented()) { return false; } var $this = $(this), progress = Math.floor(data.loaded / data.total * 100), globalProgressNode = $this.find('.fileupload-progress'), extendedProgressNode = globalProgressNode .find('.progress-extended'); if (extendedProgressNode.length) { extendedProgressNode.html( ($this.data('blueimp-fileupload') || $this.data('fileupload')) ._renderExtendedProgress(data) ); } globalProgressNode .find('.progress') .attr('aria-valuenow', progress) .children().first().css( 'width', progress + '%' ); }, // Callback for uploads start, equivalent to the global ajaxStart event: start: function (e) { if (e.isDefaultPrevented()) { return false; } var that = $(this).data('blueimp-fileupload') || $(this).data('fileupload'); that._resetFinishedDeferreds(); that._transition($(this).find('.fileupload-progress')).done( function () { that._trigger('started', e); } ); }, // Callback for uploads stop, equivalent to the global ajaxStop event: stop: function (e) { if (e.isDefaultPrevented()) { return false; } var that = $(this).data('blueimp-fileupload') || $(this).data('fileupload'), deferred = that._addFinishedDeferreds(); $.when.apply($, that._getFinishedDeferreds()) .done(function () { that._trigger('stopped', e); }); that._transition($(this).find('.fileupload-progress')).done( function () { $(this).find('.progress') .attr('aria-valuenow', '0') .children().first().css('width', '0%'); $(this).find('.progress-extended').html(' '); deferred.resolve(); } ); }, processstart: function (e) { if (e.isDefaultPrevented()) { return false; } $(this).addClass('fileupload-processing'); }, processstop: function (e) { if (e.isDefaultPrevented()) { return false; } $(this).removeClass('fileupload-processing'); }, // Callback for file deletion: destroy: function (e, data) { if (e.isDefaultPrevented()) { return false; } var that = $(this).data('blueimp-fileupload') || $(this).data('fileupload'), removeNode = function () { that._transition(data.context).done( function () { $(this).remove(); that._trigger('destroyed', e, data); } ); }; if (data.url) { data.dataType = data.dataType || that.options.dataType; $.ajax(data).done(removeNode).fail(function () { that._trigger('destroyfailed', e, data); }); } else { removeNode(); } } },
_resetFinishedDeferreds: function () { this._finishedUploads = []; },
_addFinishedDeferreds: function (deferred) { if (!deferred) { deferred = $.Deferred(); } this._finishedUploads.push(deferred); return deferred; },
_getFinishedDeferreds: function () { return this._finishedUploads; },
// Link handler, that allows to download files // by drag & drop of the links to the desktop: _enableDragToDesktop: function () { var link = $(this), url = link.prop('href'), name = link.prop('download'), type = 'application/octet-stream'; link.bind('dragstart', function (e) { try { e.originalEvent.dataTransfer.setData( 'DownloadURL', [type, name, url].join(':') ); } catch (ignore) {} }); },
_formatFileSize: function (bytes) { if (typeof bytes !== 'number') { return ''; } if (bytes >= 1000000000) { return (bytes / 1000000000).toFixed(2) + ' GB'; } if (bytes >= 1000000) { return (bytes / 1000000).toFixed(2) + ' MB'; } return (bytes / 1000).toFixed(2) + ' KB'; },
_formatBitrate: function (bits) { if (typeof bits !== 'number') { return ''; } if (bits >= 1000000000) { return (bits / 1000000000).toFixed(2) + ' Gbit/s'; } if (bits >= 1000000) { return (bits / 1000000).toFixed(2) + ' Mbit/s'; } if (bits >= 1000) { return (bits / 1000).toFixed(2) + ' kbit/s'; } return bits.toFixed(2) + ' bit/s'; },
_formatTime: function (seconds) { var date = new Date(seconds * 1000), days = Math.floor(seconds / 86400); days = days ? days + 'd ' : ''; return days + ('0' + date.getUTCHours()).slice(-2) + ':' + ('0' + date.getUTCMinutes()).slice(-2) + ':' + ('0' + date.getUTCSeconds()).slice(-2); },
_formatPercentage: function (floatValue) { return (floatValue * 100).toFixed(2) + ' %'; },
_renderExtendedProgress: function (data) { return this._formatBitrate(data.bitrate) + ' | ' + this._formatTime( (data.total - data.loaded) * 8 / data.bitrate ) + ' | ' + this._formatPercentage( data.loaded / data.total ) + ' | ' + this._formatFileSize(data.loaded) + ' / ' + this._formatFileSize(data.total); },
_renderTemplate: function (func, files) { if (!func) { return $(); } var result = func({ files: files, formatFileSize: this._formatFileSize, options: this.options }); if (result instanceof $) { return result; } return $(this.options.templatesContainer).html(result).children(); },
_renderPreviews: function (data) { data.context.find('.preview').each(function (index, elm) { $(elm).append(data.files[index].preview); }); },
_renderUpload: function (files) { return this._renderTemplate( this.options.uploadTemplate, files ); },
_renderDownload: function (files) { return this._renderTemplate( this.options.downloadTemplate, files ).find('a[download]').each(this._enableDragToDesktop).end(); },
_startHandler: function (e) { e.preventDefault(); var button = $(e.currentTarget), template = button.closest('.template-upload'), data = template.data('data'); button.prop('disabled', true); if (data && data.submit) { data.submit(); } },
_cancelHandler: function (e) { e.preventDefault(); var template = $(e.currentTarget) .closest('.template-upload,.template-download'), data = template.data('data') || {}; data.context = data.context || template; if (data.abort) { data.abort(); } else { data.errorThrown = 'abort'; this._trigger('fail', e, data); } },
_deleteHandler: function (e) { e.preventDefault(); var button = $(e.currentTarget); this._trigger('destroy', e, $.extend({ context: button.closest('.template-download'), type: 'DELETE' }, button.data())); },
_forceReflow: function (node) { return $.support.transition && node.length && node[0].offsetWidth; },
_transition: function (node) { var dfd = $.Deferred(); if ($.support.transition && node.hasClass('fade') && node.is(':visible')) { node.bind( $.support.transition.end, function (e) { // Make sure we don't respond to other transitions events // in the container element, e.g. from button elements: if (e.target === node[0]) { node.unbind($.support.transition.end); dfd.resolveWith(node); } } ).toggleClass('in'); } else { node.toggleClass('in'); dfd.resolveWith(node); } return dfd; },
_initButtonBarEventHandlers: function () { var fileUploadButtonBar = this.element.find('.fileupload-buttonbar'), filesList = this.options.filesContainer; this._on(fileUploadButtonBar.find('.start'), { click: function (e) { e.preventDefault(); filesList.find('.start').click(); } }); this._on(fileUploadButtonBar.find('.cancel'), { click: function (e) { e.preventDefault(); filesList.find('.cancel').click(); } }); this._on(fileUploadButtonBar.find('.delete'), { click: function (e) { e.preventDefault(); filesList.find('.toggle:checked') .closest('.template-download') .find('.delete').click(); fileUploadButtonBar.find('.toggle') .prop('checked', false); } }); this._on(fileUploadButtonBar.find('.toggle'), { change: function (e) { filesList.find('.toggle').prop( 'checked', $(e.currentTarget).is(':checked') ); } }); },
_destroyButtonBarEventHandlers: function () { this._off( this.element.find('.fileupload-buttonbar') .find('.start, .cancel, .delete'), 'click' ); this._off( this.element.find('.fileupload-buttonbar .toggle'), 'change.' ); },
_initEventHandlers: function () { this._super(); this._on(this.options.filesContainer, { 'click .start': this._startHandler, 'click .cancel': this._cancelHandler, 'click .delete': this._deleteHandler }); this._initButtonBarEventHandlers(); },
_destroyEventHandlers: function () { this._destroyButtonBarEventHandlers(); this._off(this.options.filesContainer, 'click'); this._super(); },
_enableFileInputButton: function () { this.element.find('.fileinput-button input') .prop('disabled', false) .parent().removeClass('disabled'); },
_disableFileInputButton: function () { this.element.find('.fileinput-button input') .prop('disabled', true) .parent().addClass('disabled'); },
_initTemplates: function () { var options = this.options; options.templatesContainer = this.document[0].createElement( options.filesContainer.prop('nodeName') ); if (tmpl) { if (options.uploadTemplateId) { options.uploadTemplate = tmpl(options.uploadTemplateId); } if (options.downloadTemplateId) { options.downloadTemplate = tmpl(options.downloadTemplateId); } } },
_initFilesContainer: function () { var options = this.options; if (options.filesContainer === undefined) { options.filesContainer = this.element.find('.files'); } else if (!(options.filesContainer instanceof $)) { options.filesContainer = $(options.filesContainer); } },
_initSpecialOptions: function () { this._super(); this._initFilesContainer(); this._initTemplates(); },
_create: function () { this._super(); this._resetFinishedDeferreds(); if (!$.support.fileInput) { this._disableFileInputButton(); } },
enable: function () { var wasDisabled = false; if (this.options.disabled) { wasDisabled = true; } this._super(); if (wasDisabled) { this.element.find('input, button').prop('disabled', false); this._enableFileInputButton(); } },
disable: function () { if (!this.options.disabled) { this.element.find('input, button').prop('disabled', true); this._disableFileInputButton(); } this._super(); }
});
})); |
./js/main.js
注释以下代码
1 2 3 4 5 | $('.fileupload').fileupload({ // Uncomment the following to send cross-domain cookies: //xhrFields: {withCredentials: true}, url: 'server/php/' }); |
移至 ./index.html 中
./server/php/index.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | <?php /* * jQuery File Upload Plugin PHP Example 5.14 * https://github.com/blueimp/jQuery-File-Upload * * Copyright 2010, Sebastian Tschan * https://blueimp.net * * Licensed under the MIT license: * http://www.opensource.org/licenses/MIT */
error_reporting(E_ALL | E_STRICT); require('UploadHandler.php');
// 添加图片 if(! empty($_FILES)) { $keys = array_keys($_FILES); if(! empty($keys)) { $key = $keys[0]; } else { $key = null; } } else { // 删除图片时的参数 $pathinfo = pathinfo($_SERVER['REQUEST_URI']); if(! empty($pathinfo['filename'])) { $dirname = preg_match('/^\?(.*)=.*$/', $pathinfo['filename'], $match); if(! empty($match[1]) && $match[1] != 'fields') { $key = $match[1]; } else { $key = null; } } else { $key = null; } }
$upload_handler = new UploadHandler($key); |
根据不同的添加/删除的不同情况,传递不同的参数,同时在页面加载时通过 ajax 获取不同文件夹的文件用于展示(并没有做多层目录或者文件存储目录与文件域的 name 不同的情况的考虑,同时实际项目的 url 模式也有可能与程序中的正则表达式不匹配,可在实际项目中根据实际情况修改)
./server/php/UploadHandler.php 上传类
修改了 $this->options 中关于上传路径的参数,原 demo 中是写死的
1 2 3 4 5 6 7 8 9 10 11 12 | function __construct($dir = null, $options = null, $initialize = true, $error_messages = null) { if($dir === null) { $dir = 'files'; } $this->options = array( 'script_url' => $this->get_full_url().'/', 'upload_dir' => dirname($this->get_server_var('SCRIPT_FILENAME')).'/'.$dir.'/', 'upload_url' => $this->get_full_url().'/'.$dir.'/', 'user_dirs' => false, 'mkdir_mode' => 0755, 'param_name' => $dir, .......... |
修改了 get_singular_param_name 方法
1 2 3 4 | protected function get_singular_param_name() { // return substr($this->options['param_name'], 0, -1); return $this->options['param_name']; } |
修改了 get 方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | public function get($print_response = true) { if ($print_response && isset($_GET['download'])) { return $this->download(); }
if(isset($_GET['fields']) && $_GET['fields'] != '') { $fields = $_GET['fields']; if(strpos($fields, ',') === false) { // 只有一个实例 $this->options['upload_dir'] = dirname($this->get_server_var('SCRIPT_FILENAME')).'/'.$fields.'/'; $this->options['upload_url'] = $this->get_full_url().'/'.$fields.'/'; $this->options['param_name'] = $fields;
$response = array( $val => $this->get_file_objects() ); $return = $this->generate_response($response, $print_response); } else { // 多个实例 $fields = explode(',', $fields); $return = array(); foreach($fields as $key => $val) {
$this->options['upload_dir'] = dirname($this->get_server_var('SCRIPT_FILENAME')).'/'.$val.'/'; $this->options['upload_url'] = $this->get_full_url().'/'.$val.'/'; $this->options['param_name'] = $val;
$response = $this->get_file_objects(); if(! empty($response)) { $return[$val] = $response; } } } echo json_encode($return); } } |
get 方法主要用于刷新页面后展示之前的上传列表,这个只是最简单的实现,实际项目中应该是通过数据库查找
完整文件:
+ View Code
GitHub 地址: https://github.com/dee0912/jquery_file_upload_multipart
标签: jQuery File Upload, 上传插件
好文要顶 关注我 收藏该文
+加关注
0
0
« 上一篇:PHP 字符串的隐式转换规则以及针对包含字母的字符串的递增/递减操作
posted @ 2016-06-17 00:30 黄棣-dee 阅读(1266) 评论(0) 编辑 收藏
end: topics 文章、评论容器
刷新评论刷新页面返回顶部
注册用户登录后才能发表评论,请 登录 或 注册,访问网站首页。
【推荐】50万行VC++源码: 大型组态工控、电力仿真CAD与GIS源码库
【推荐】别再闷头写代码!找对工具,事半功倍,全能开发工具包用起来
【福利】网易云信1周年接入开发者突破10万,送红包活动火热开展中
最新IT新闻:
· 苹果拟申请新商标,Magic Toolbar是什么来头?
» 更多新闻...
最新知识库文章:
end: forFlow
end: mainContent 主体内容容器
done
公告
昵称:黄棣-dee
园龄:3年4个月
粉丝:28
关注:6
+加关注
| |||||||||
日 | 一 | 二 | 三 | 四 | 五 | 六 | |||
25 | 26 | 27 | 28 | 29 | 30 | 1 | |||
2 | 3 | 4 | 5 | 6 | 7 | ||||
9 | 10 | 11 | 12 | 13 | 14 | 15 | |||
16 | 17 | 18 | 19 | 20 | 21 | 22 | |||
23 | 24 | 25 | 26 | 27 | 28 | 29 | |||
30 | 31 | 1 | 2 | 3 | 4 | 5 |
搜索
常用链接
最新随笔
- 1. PHP 使用 curl_* 系列函数和 curl_multi_* 系列函数进行多接口调用时的性能对比
- 2. 在 Linux 下搭建 Git 服务器
- 3. 使用 SVN Hook 实现服务器端代码自动更新
- 4. 一道无限级分类题的 PHP 实现
- 5. MySQL 5.6 记录 SQL 语句与慢查询
- 6. 使用 Composer 为 ThinkPHP(3.2.3)框架添加和管理组件
- 7. PHP 实现数学问题:组合
- 8. PHP 数组的拷贝是按值传递 or 按引用传递
- 9. jQuery File Upload 单页面多实例的实现
- 10. PHP 字符串的隐式转换规则以及针对包含字母的字符串的递增/递减操作
我的标签
- ThinkPHP(31)
- Javascript 笔记与总结(23)
- php(23)
- nginx(20)
- php错误与异常(18)
- Web 在线文件管理器学习笔记与总结(15)
- http(12)
- memcached(11)
- MySQL(11)
- PHP设计模式(11)
- 更多
随笔分类(277)
- Apache / Nginx / Lighttpd(21)
- CMS
- Git / GitHub(2)
- HTML & CSS(1)
- HTML5 & CSS3(2)
- HTTP 协议(10)
- IDE(2)
- Javascript(34)
- jQuery / jQuery UI(23)
- jQuery Mobile
- Linux(18)
- Memcached / Redis(21)
- MySQL / SQL(12)
- Node.js(1)
- NoSQL
- PHP(84)
- SVN(8)
- ThinkPHP(33)
- Web安全(1)
- Web标准 & 浏览器(1)
- 读书笔记
- 其它(3)
随笔档案(305)
- 2016年10月 (1)
- 2016年8月 (5)
- 2016年6月 (7)
- 2016年5月 (13)
- 2016年4月 (9)
- 2016年3月 (6)
- 2016年2月 (13)
- 2016年1月 (6)
- 2015年12月 (6)
- 2015年11月 (9)
- 2015年10月 (9)
- 2015年9月 (12)
- 2015年8月 (17)
- 2015年7月 (24)
- 2015年6月 (9)
- 2015年5月 (29)
- 2015年4月 (56)
- 2015年3月 (24)
- 2015年2月 (5)
- 2015年1月 (3)
- 2014年12月 (9)
- 2014年11月 (14)
- 2014年10月 (9)
- 2014年9月 (10)
文章档案(6)
积分与排名
- 积分 - 29808
- 排名 - 8141
最新评论
- 1. Re:在 Linux 下搭建 Git 服务器
- 楼主辛苦了,谢谢
- --ck2016
- 2. Re:宿主机( win 7 系统) ping 虚拟机VMware( cent os 6.6 ) 出现“请求超时”或者“无法访问目标主机”的解决方法
- 关闭虚拟机的防火墙:1) 重启后生效 开启: chkconfig iptables on 关闭: chkconfig iptables off 2) 即时生效,重启后失效 开启: service ip......
- --hainingwyx
- 3. Re:使用 JSONP 实现简单的 SSO 单点登录
- mark jsonp 单点登录
- --lk_
- 4. Re:ThinkPHP 3.2.3 使用 Swift Mailer 邮件系统发送邮件
- @小何php你是在tp下测试吗,访问的url要和文件路径对应啊...
- --黄棣-dee
- 5. Re:ThinkPHP 3.2.3 使用 Swift Mailer 邮件系统发送邮件
- @黄棣-dee请问我本地运行直接输入127.0.0.1,就可以吗?我还是没发出邮件。。。...
- --小何php
- 6. Re:ThinkPHP 3.2.3 使用 Swift Mailer 邮件系统发送邮件
- @黄棣-dee嗯,我试试,谢谢啊!非常感谢...
- --小何php
- 7. Re:ThinkPHP 3.2.3 使用 Swift Mailer 邮件系统发送邮件
- @小何php另外一个你测试最好别用qq邮箱的smtp服务器,换126或者别的邮箱...
- --黄棣-dee
- 8. Re:ThinkPHP 3.2.3 使用 Swift Mailer 邮件系统发送邮件
- @小何php配置就用我这篇文章第一段config.php的格式配置,MAIL_USER用你的qq邮箱,MAIL_PWD要去qq邮箱首页的设置里获取授权码:“设置” -- “POP3/IMAP/SMTP......
- --黄棣-dee
- 9. Re:ThinkPHP 3.2.3 使用 Swift Mailer 邮件系统发送邮件
- 前辈你好,我请教一下,我的发送邮箱是1241256555@qq.com
- 我在配置文件里面该怎么写?还有就是我把上面搞好之后,直接在本地运行能实现功能吗?
- --小何php
- 10. Re:PHP+jQuery 注册模块开发
- 写的太好了
- --小何php
- 11. Re:PHP 开发 APP 接口 学习笔记与总结 - APP 接口实例 [3] 首页 APP 接口开发方案 ② 读取缓存方式
- 都是慕课网的东西。。。
- --ikratos
- 12. Re:jQuery 两种方法实现IE10以下浏览器的placeholder效果
- 当文本框是密码输入框的时候,要分开来。因为密码输入框输进去的是一个个的圆点
- --风沙渡
- 13. Re:PHP+jQuery 注册模块开发
- 写的不错~
- --星月梦缘
- 14. Re:jQuery 实现带下拉提示且自动填充的邮箱
- mark
- --rpg
- 15. Re:PHP+jQuery 注册模块开发
- 恩,方法的连写,谢谢你,这篇博客很不错
- --Lasthelloworld
- 16. Re:PHP+jQuery 注册模块开发
- @Lasthelloworld原生的js不支持方法的连写...
- --dee0912
- 17. Re:PHP+jQuery 注册模块开发
- 谢谢,原生Js的函数可以这样吗,他的术语是什么,我去百度一下
- --Lasthelloworld
- 18. Re:PHP+jQuery 注册模块开发
- @Lasthelloworld对,同时绑定多个事件...
- --dee0912
- 19. Re:PHP+jQuery 注册模块开发
- @dee0912你好,我有一个位置不是很明白,jquery 支持$('#id').focus(function(){ }).click(function(){});这一句,代表同时给id元素绑定两个事......
- --Lasthelloworld
- 20. Re:PHP+jQuery 注册模块开发
- @Lasthelloworld...
- --dee0912
- 21. Re:PHP+jQuery 注册模块开发
- 为什么我在chrome中提示语句未出现呢,能否提供下源码我看看
- --Lasthelloworld
- 22. Re:[ PHP+jQuery ] ajax 多级联动菜单的应用:电商网站的用户地址选择功能 ( 一 ) - 传统下拉菜单
- 你的博客太好了
- --前端摸索者
- 23. Re:PHP+jQuery 列表分页类 ( 支持 url 分页 / ajax 分页 )
- 真好,谢谢
- --窝火
- 24. Re:PHP+jQuery 长文章分页类 ( 支持 url / ajax 分页方式 )
- @dee0912其實不會,你想像一下,用你的ajax方式其實是把一篇文章拆分出多個塊然後輸出,而這種方式則不需要拆分就直接輸出你只要在你的服務端配置一下內容壓縮輸出即可,這樣不會有多大影響你可以研究下......
- --討論Go語言的QQ群195112
- 25. Re:PHP+jQuery 长文章分页类 ( 支持 url / ajax 分页方式 )
- @討論Go語言的QQ群195112一次取出全部文章内容,确实可以既利于搜索引擎,同时又有无刷新的效果,不过如果文章内容比较多的话,加载时应该会比较慢吧...
- --dee0912
- 26. Re:PHP+jQuery 长文章分页类 ( 支持 url / ajax 分页方式 )
- 這麼做還有一個好處,那就是減少了http請求的次數
- --討論Go語言的QQ群195112
- 27. Re:PHP+jQuery 长文章分页类 ( 支持 url / ajax 分页方式 )
- @dee0912其實可以兩全其美用js配合一下就能做到不但可以有很好的體驗另外還能讓seo抓到php那邊echo出所有分頁的內容之後隱藏掉,然後點擊分頁的時候在顯示即可...
- --討論Go語言的QQ群195112
- 28. Re:PHP+jQuery 长文章分页类 ( 支持 url / ajax 分页方式 )
- @討論Go語言的QQ群195112恩,ajax 对 seo是不利。所以想利于 seo 就用 url 分页,想提高用户体验就用 ajax 分页。...
- --dee0912
- 29. Re:PHP+jQuery 长文章分页类 ( 支持 url / ajax 分页方式 )
- 其實就是ajax分頁而已,不過這樣分頁對於SEO來說是一個硬傷
- --討論Go語言的QQ群195112
- 30. Re:jQuery 实现带下拉提示且自动填充的邮箱
- mark
- --savey
- 31. Re:PHP+jQuery 支持 url 分页 / ajax 分页 的列表分页类
- 学习了,刚好要用到ajax分页技术.
- --savey
- 32. Re:PHP+jQuery 注册模块开发
- 好文要顶 有图有源码的狂顶。。。。
- --wangxu871023
- 33. Re:PHP+jQuery 注册模块开发
- 特别喜欢你的CSS,漂亮:)
- --buyifly
- 34. Re:PHP+jQuery 注册模块开发
- @buyifly你好,除了数据库连接文件和引用的zend,思路和源码已经全部贴出来了。zend的下载地址已经附在文中了...
- --dee0912
- 35. Re:PHP+jQuery 注册模块开发
- 不错 好东西
- --paulihe
- 36. Re:PHP+jQuery 注册模块开发
- 真不错,请问能提供下载吗?
- --buyifly
- 37. Re:jQuery 实现带下拉提示且自动填充的邮箱
- mark
- --圆月|弯刀
- 38. Re:jQuery 实现带下拉提示且自动填充的邮箱
- mark...........
- --快刀客
阅读排行榜
- 1. jQuery File Upload 单页面多实例的实现(1266)
- 2. [ PHP+jQuery ] ajax 多级联动菜单的应用:电商网站的用户地址选择功能 ( 一 ) - 传统下拉菜单(818)
- 3. PHP+jQuery 注册模块开发(790)
- 4. 宿主机( win 7 系统) ping 虚拟机VMware( cent os 6.6 ) 出现“请求超时”或者“无法访问目标主机”的解决方法(768)
- 5. PHP json_decode 函数解析 json 结果为 NULL 的解决方法(739)
- 6. CentOS 6.6 安装 Node.js(731)
- 7. MySQL 命令行导出、导入Select 查询结果(716)
- 8. 基于 ThinkPHP 3.2.3 的页面静态化功能的实现(661)
- 9. ThinkPHP 3.2.3 使用 PHPExcel 处理 Excel 表格(612)
- 10. PHP+jQuery 列表分页类 ( 支持 url 分页 / ajax 分页 )(543)
- 11. CSS 实现背景图尺寸不随浏览器缩放而变化(500)
- 12. 基于 jQuery Jcrop 插件的功能模块:头像剪裁(493)
- 13. artDialog ( v 6.0.2 ) content 参数引入页面 html 内容(488)
- 14. jQuery 实现带下拉提示且自动填充的邮箱(431)
- 15. 在 Linux 下搭建 Git 服务器(386)
- 16. jQuery 两种方法实现IE10以下浏览器的placeholder效果(369)
- 17. ThinkPHP 3.2.2 实现持久登录 ( 记住我 )(348)
- 18. ThinkPHP 3.2.2 在 volist 多重循环嵌套中使用 if 判断标签(342)
- 19. PHP+jQuery 注册模块的改进之二:激活链接的URL设置与有效期(342)
- 20. PHP+jQuery 长文章分页类 ( 支持 url / ajax 分页方式 )(339)
- 21. jQuery+CSS 简单代码实现遮罩层( 兼容主流浏览器 )(328)
- 22. VirtualBox + CentOS 使用 NAT + Host-Only 方式联网(328)
- 23. 使用 Composer 为 ThinkPHP(3.2.3)框架添加和管理组件(327)
- 24. SVN 树冲突的解决方法(Ubuntu 环境)(326)
- 25. jQuery 复合选择器的几个例子(296)
- 26. Ueditor 1.4.3.1 使用 ThinkPHP 3.2.3 的上传类进行图片上传(268)
- 27. html 实体转换为字符:转换 UEditor 编辑器 ( 在 ThinkPHP 3.2.2 中 ) 保存的数据(251)
- 28. PHP 使用 mcrypt 扩展中的 mcrypt_encrypt() 和 mcrypt_decrypt() 对数据进行加密和解密(249)
- 29. PHP 两个多维数组根据某个键的值进行组合排序的几种思路(241)
- 30. [ PHP+jQuery ] ajax 多级联动菜单的应用:电商网站的用户地址选择功能 ( 二 ) - 仿亚马逊下拉面板(235)
- 31. Ubuntu 安装 ImageMagic(6.9.1-6)及 PHP 的 imagick (3.0.1)扩展(229)
- 32. ThinkPHP 3.2.3 简单后台模块开发(一)常用配置(215)
- 33. JavaScript + PHP 实现刷新继续保持倒计时的按钮(183)
- 34. Nginx 报错: nginx: [error] open() "/usr/local/nginx/logs/nginx.pid" failed (2: No such file or directory) 的解决方法(178)
- 35. ThinkPHP 3.2.3 使用 Swift Mailer 邮件系统发送邮件(174)
- 36. PHP 开发 APP 接口 学习笔记与总结 - APP 接口实例 [6] 版本升级接口开发(169)
- 37. cURL 学习笔记与总结(2)网页爬虫、天气预报(163)
- 38. PHP 开发 APP 接口 学习笔记与总结 - 静态缓存(151)
- 39. SVN 分支管理(151)
- 40. PHP+jQuery 注册模块的改进之一:验证码存入SESSION(146)
评论排行榜
- 1. PHP+jQuery 注册模块开发(14)
- 2. PHP+jQuery 长文章分页类 ( 支持 url / ajax 分页方式 )(6)
- 3. ThinkPHP 3.2.3 使用 Swift Mailer 邮件系统发送邮件(6)
- 4. jQuery 实现带下拉提示且自动填充的邮箱(4)
- 5. PHP+jQuery 列表分页类 ( 支持 url 分页 / ajax 分页 )(2)
- 6. jQuery 两种方法实现IE10以下浏览器的placeholder效果(1)
- 7. 宿主机( win 7 系统) ping 虚拟机VMware( cent os 6.6 ) 出现“请求超时”或者“无法访问目标主机”的解决方法(1)
- 8. [ PHP+jQuery ] ajax 多级联动菜单的应用:电商网站的用户地址选择功能 ( 一 ) - 传统下拉菜单(1)
- 9. PHP 开发 APP 接口 学习笔记与总结 - APP 接口实例 [3] 首页 APP 接口开发方案 ② 读取缓存方式(1)
- 10. 在 Linux 下搭建 Git 服务器(1)
- 11. 使用 JSONP 实现简单的 SSO 单点登录(1)
推荐排行榜
- 1. PHP+jQuery 注册模块开发(7)
- 2. [ PHP+jQuery ] ajax 多级联动菜单的应用:电商网站的用户地址选择功能 ( 一 ) - 传统下拉菜单(3)
- 3. CSS 实现背景图尺寸不随浏览器缩放而变化(2)
- 4. jQuery 实现带下拉提示且自动填充的邮箱(2)
- 5. jQuery 图片剪裁插件使用之 imgAreaSelect(1)
- 6. PHP+jQuery 列表分页类 ( 支持 url 分页 / ajax 分页 )(1)
- 7. PHP 开发 APP 接口 学习笔记与总结 - APP 接口实例 [5] 版本设计分析及数据表设计(1)
- 8. 使用 JavaScript 实现基本队列、优先队列和循环队列(1)
- 9. ThinkPHP 3.2.3 加减乘法验证码类(1)
- 10. 宿主机( win 7 系统) ping 虚拟机VMware( cent os 6.6 ) 出现“请求超时”或者“无法访问目标主机”的解决方法(1)
- 11. PDO 学习与使用 ( 一 ) :PDO 对象、exec 方法、query 方法与防 SQL 注入(1)
end: sideBarMain
end: sideBar 侧边栏容器
end: main
done Copyright ©2016 黄棣-dee
end: footer
end: home 自定义的最大容器 PageEndHtml Block Begin
访客数:
2016/05/17 起统计
PageEndHtml Block End