1 | <!DOCTYPE html>
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 | <html>
|
10 | <head>
|
11 | <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
12 | <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
13 |
|
14 | <title>FileAPI :: Demo :: example</title>
|
15 |
|
16 | <meta name="viewport" content="user-scalable=no, width=400, initial-scale=0.8, maximum-scale=0.8" />
|
17 | <meta name="apple-mobile-web-app-capable" content="yes" />
|
18 | <meta name="apple-mobile-web-app-status-bar-style" content="yes" />
|
19 | <meta name="format-detection" content="email=no" />
|
20 | <meta name="HandheldFriendly" content="true" />
|
21 |
|
22 | <script src="//yandex.st/jquery/1.8.2/jquery.min.js"></script>
|
23 | <script>if( !window.jQuery )document.write('<script src="/js/jquery.dev.js"><'+'/script>');</script>
|
24 |
|
25 | <script>
|
26 | var FileAPI = {
|
27 | debug: true
|
28 | , staticPath: '../dist/'
|
29 | };
|
30 | </script>
|
31 | <script src="../dist/FileAPI.min.js"></script>
|
32 | <script src="../plugins/FileAPI.id3.js"></script>
|
33 | <script src="../plugins/FileAPI.exif.js"></script>
|
34 |
|
35 | <script>
|
36 |
|
37 |
|
38 | (function (){
|
39 | var cache = {};
|
40 |
|
41 | this.tmpl = function tmpl(str, data){
|
42 |
|
43 |
|
44 | var fn = !/\W/.test(str) ?
|
45 | cache[str] = cache[str] ||
|
46 | tmpl(document.getElementById(str).innerHTML) :
|
47 |
|
48 |
|
49 |
|
50 | new Function("obj",
|
51 | "var p=[],print=function(){p.push.apply(p,arguments);};" +
|
52 |
|
53 |
|
54 | "with(obj){p.push('" +
|
55 |
|
56 |
|
57 | str
|
58 | .replace(/[\r\t\n]/g, " ")
|
59 | .split("<%").join("\t")
|
60 | .replace(/((^|%>)[^\t]*)'/g, "$1\r")
|
61 | .replace(/\t=(.*?)%>/g, "',$1,'")
|
62 | .split("\t").join("');")
|
63 | .split("%>").join("p.push('")
|
64 | .split("\r").join("\\'")
|
65 | + "');}return p.join('');");
|
66 |
|
67 |
|
68 | return data ? fn(data) : fn;
|
69 | };
|
70 | })();
|
71 | </script>
|
72 |
|
73 | <style>
|
74 | body {
|
75 | font-size: 15px;
|
76 | font-family: "Helvetica Neue";
|
77 | }
|
78 |
|
79 | .b-button {
|
80 | display: inline-block;
|
81 | *display: inline;
|
82 | *zoom: 1;
|
83 | position: relative;
|
84 | overflow: hidden;
|
85 | cursor: pointer;
|
86 | padding: 4px 15px;
|
87 | vertical-align: middle;
|
88 | border: 1px solid #ccc;
|
89 | border-radius: 3px;
|
90 | background-color: #f5f5f5;
|
91 | background: -moz-linear-gradient(top, #fff 0%, #f5f5f5 49%, #ececec 50%, #eee 100%);
|
92 | background: -webkit-linear-gradient(top, #fff 0%,#f5f5f5 49%,#ececec 50%,#eee 100%);
|
93 | background: -o-linear-gradient(top, #fff 0%,#f5f5f5 49%,#ececec 50%,#eee 100%);
|
94 | background: linear-gradient(to bottom, #fff 0%,#f5f5f5 49%,#ececec 50%,#eee 100%);
|
95 | -webkit-user-select: none;
|
96 | -moz-user-select: none;
|
97 | user-select: none;
|
98 | }
|
99 | .b-button_hover {
|
100 | border-color: #fa0;
|
101 | box-shadow: 0 0 2px #fa0;
|
102 | }
|
103 |
|
104 | .b-button__text {
|
105 | }
|
106 |
|
107 | .b-button__input {
|
108 | cursor: pointer;
|
109 | opacity: 0;
|
110 | filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);
|
111 | top: -10px;
|
112 | right: -40px;
|
113 | font-size: 50px;
|
114 | position: absolute;
|
115 | }
|
116 |
|
117 |
|
118 | #preview {
|
119 | max-width: 600px;
|
120 | box-shadow: 0 1px 3px rgba(0,0,0,.4);
|
121 | border-radius: 3px;
|
122 | }
|
123 | .b-file {
|
124 | height: 40px;
|
125 | padding: 5px;
|
126 | position: relative;
|
127 | overflow: hidden;
|
128 | border-radius: 3px;
|
129 | background-color: #fcfcfc;
|
130 | background: -webkit-linear-gradient(top, #fcfcfc 0%, #f6f6f6 100%);
|
131 | background: -moz-linear-gradient(top, #fcfcfc 0%, #f6f6f6 100%);
|
132 | background: -o-linear-gradient(top, #fcfcfc 0%, #f6f6f6 100%);
|
133 | background: linear-gradient(to bottom, #fcfcfc 0%, #f6f6f6 100%);
|
134 | clear: both;
|
135 | }
|
136 | .b-file__left {
|
137 | float: left;
|
138 | margin: 1px 0 0 2px;
|
139 | line-height: 0;
|
140 | }
|
141 | .b-file__left_border {
|
142 | border: 2px solid #fff;
|
143 | border-radius: 4px;
|
144 | }
|
145 |
|
146 | .b-file__right {
|
147 | margin-left: 45px;
|
148 | }
|
149 |
|
150 | .b-file__name {
|
151 | color: #36c;
|
152 | cursor: pointer;
|
153 | border-bottom: 1px dotted #36c;
|
154 | text-decoration: none;
|
155 | }
|
156 | .b-file__name:hover {
|
157 | color: #f00;
|
158 | border-bottom-color: #f00;
|
159 | }
|
160 |
|
161 | .b-file__info {
|
162 | color: #666;
|
163 | position: absolute;
|
164 | font-size: 12px;
|
165 | margin-top: 3px;
|
166 | }
|
167 |
|
168 | .b-file__bar {
|
169 | padding-top: 4px;
|
170 | }
|
171 |
|
172 | .b-file__error {
|
173 | color: #c00;
|
174 | }
|
175 | .b-file__done {
|
176 | color: #458383;
|
177 | }
|
178 | .b-file__abort {
|
179 | top: 10px;
|
180 | right: 20px;
|
181 | width: 15px;
|
182 | height: 15px;
|
183 | position: absolute;
|
184 | color: #c00;
|
185 | cursor: pointer;
|
186 | font-size: 20px;
|
187 | display: none;
|
188 | }
|
189 | .b-file_upload .b-file__abort { display: block; }
|
190 |
|
191 | .b-progress {
|
192 | width: 200px;
|
193 | height: 10px;
|
194 | border: 2px solid #E2E4E2;
|
195 | border-radius: 10px;
|
196 | box-shadow: inset 0 1px 1px rgba(0,0,0,.2);
|
197 | background-color: #d3d3d3;
|
198 | position: relative;
|
199 | }
|
200 | .b-progress__bar {
|
201 | width: 0;
|
202 | height: 10px;
|
203 | border-radius: 10px;
|
204 | background-color: #2D9DD7;
|
205 | background: -webkit-linear-gradient(top, #2D9DD7 0%, #1C81C7 100%);
|
206 | background: -moz-linear-gradient(top, #2D9DD7 0%, #1C81C7 100%);
|
207 | background: linear-gradient(to bottom, #2D9DD7 0%, #1C81C7 100%);
|
208 | -webkit-transition: width .5s ease-out;
|
209 | -moz-transition: width .5s ease-out;
|
210 | -ms-transition: width .5s ease-out;
|
211 | transition: width .5s ease-out;
|
212 | }
|
213 |
|
214 | .b-dropzone,
|
215 | .b-dropzone__bg {
|
216 | top: 0;
|
217 | left: 0;
|
218 | right: 0;
|
219 | bottom: 0;
|
220 | z-index: 30000;
|
221 | position: absolute;
|
222 | }
|
223 | .b-dropzone__bg {
|
224 | opacity: .2;
|
225 | background-color: #2D9DD7
|
226 | }
|
227 | .b-dropzone__txt {
|
228 | color: #1C81C7;
|
229 | text-shadow: 0 2px 1px #113C53;
|
230 | font-size: 400%;
|
231 | font-weight: bold;
|
232 | text-align: center;
|
233 | width: 500px;
|
234 | top: 50%;
|
235 | left: 50%;
|
236 | margin: -100px 0 0 -250px;
|
237 | z-index: 30001;
|
238 | position: absolute;
|
239 | }
|
240 |
|
241 | .b-layer {
|
242 | border: 3px solid #fff;
|
243 | border-radius: 5px;
|
244 | box-shadow: 0 1px 30px #000;
|
245 | background-color: #f3f3f3;
|
246 | top: 50px;
|
247 | left: 50%;
|
248 | z-index: 30002;
|
249 | position: absolute;
|
250 | margin-left: -150px;
|
251 | margin-bottom: 100px;
|
252 | }
|
253 | .b-layer__h1 {
|
254 | color: #fff;
|
255 | padding: 10px 10px;
|
256 | width: 300px;
|
257 | overflow: hidden;
|
258 | background-color: #2D9DD7;
|
259 | }
|
260 | .b-layer__img {
|
261 | padding: 5px 10px;
|
262 | text-align: center;
|
263 | border-top: 2px solid #fff;
|
264 | }
|
265 | .b-layer__info {
|
266 | padding: 2px 15px;
|
267 | border-top: 2px solid #fff;
|
268 | }
|
269 | .b-layer__info div {
|
270 | width: 280px;
|
271 | overflow: hidden;
|
272 | white-space: nowrap;
|
273 | }
|
274 |
|
275 |
|
276 | </style>
|
277 |
|
278 | </head>
|
279 | <body>
|
280 | <div style="left: 0; right: 0; bottom: 0; position: fixed; box-shadow: 0 0 5px rgba(0,0,0,.65); background-color: #f3f3f3;">
|
281 | <div style="padding: 5px 10px 10px">
|
282 | <a href="../">← index</a> |
|
283 | <b>demo</b> -
|
284 | <a href="./userpic.html">userpic</a> -
|
285 | <a href="./thumbnails.html">thumbnails</a> -
|
286 | <a href="./watermark.html">watermark</a> -
|
287 | <a href="./webcam.html">webcam</a> -
|
288 | <a href="./caman.html">caman.js</a>
|
289 | </div>
|
290 | </div>
|
291 |
|
292 | <div id="drop-zone" class="b-dropzone" style="display: none">
|
293 | <div class="b-dropzone__bg"></div>
|
294 | <div class="b-dropzone__txt">Drop files there</div>
|
295 | </div>
|
296 |
|
297 | <div id="oooops" style="display: none; margin: 10px; padding: 10px; border: 2px solid #f60; border-radius: 4px;">
|
298 | Увы, ваш браузер не поддерживает html5 и flash,
|
299 | поэтому смотреть тут нечего, а iframe не даёт всей красоты :]
|
300 | </div>
|
301 |
|
302 | <div id="buttons-panel">
|
303 | <div class="b-button js-fileapi-wrapper">
|
304 | <div class="b-button__text">Upload one file</div>
|
305 | <input name="files" class="b-button__input" type="file" />
|
306 | </div>
|
307 |
|
308 | <div class="b-button js-fileapi-wrapper">
|
309 | <div class="b-button__text">Multiple</div>
|
310 | <input name="files" class="b-button__input" type="file" multiple />
|
311 | </div>
|
312 |
|
313 | <div class="b-button js-fileapi-wrapper">
|
314 | <div class="b-button__text">jpg, jpeg & gif</div>
|
315 | <input name="files" class="b-button__input" type="file" accept="image/*" multiple />
|
316 | </div>
|
317 |
|
318 | <span id="drag-n-drop" style="display: none; padding: 0 30px">
|
319 | or drag'n'drop
|
320 | </span>
|
321 | </div>
|
322 |
|
323 | <div id="preview" style="margin-top: 30px"></div>
|
324 |
|
325 | <script id="b-file-ejs" type="text/ejs">
|
326 | <div id="file-<%=FileAPI.uid(file)%>" class="js-file b-file b-file_<%=file.type.split('/')[0]%>">
|
327 | <div class="js-left b-file__left">
|
328 | <img src="<%=icon[file.type.split('/')[0]]||icon.def%>" width="32" height="32" style="margin: 2px 0 0 3px"/>
|
329 | </div>
|
330 | <div class="b-file__right">
|
331 | <div><a class="js-name b-file__name"><%=file.name%></a></div>
|
332 | <div class="js-info b-file__info">size: <%=(file.size/FileAPI.KB).toFixed(2)%> KB</div>
|
333 | <div class="js-progress b-file__bar" style="display: none">
|
334 | <div class="b-progress"><div class="js-bar b-progress__bar"></div></div>
|
335 | </div>
|
336 | </div>
|
337 | <i class="js-abort b-file__abort" title="abort">×</i>
|
338 | </div>
|
339 | </script>
|
340 |
|
341 | <script id="b-layer-ejs" type="text/ejs">
|
342 | <div class="b-layer">
|
343 | <div class="b-layer__h1"><%=file.name%></div>
|
344 | <div class="js-img b-layer__img"></div>
|
345 | <div class="b-layer__info">
|
346 | <%
|
347 | FileAPI.each(info, function(val, key){
|
348 | if( Object.prototype.toString.call(val) == '[object Object]' ){
|
349 | var sub = '';
|
350 | FileAPI.each(val, function (val, key){ sub += '<div>'+key+': '+val+'</div>'; });
|
351 | if( sub ){
|
352 | %><%=key%><div style="margin: 0 0 5px 20px;"><%=sub%></div><%
|
353 | }
|
354 | } else {
|
355 | %>
|
356 | <div><%=key%>: <%=val%></div>
|
357 | <%
|
358 | }
|
359 | });
|
360 | %>
|
361 | </div>
|
362 | </div>
|
363 | </script>
|
364 |
|
365 |
|
366 | <script type="text/javascript">
|
367 | jQuery(function ($){
|
368 | if( !(FileAPI.support.cors || FileAPI.support.flash) ){
|
369 | $('#oooops').show();
|
370 | $('#buttons-panel').hide();
|
371 | }
|
372 |
|
373 | $(document).on('mouseenter mouseleave', '.b-button', function (evt){
|
374 | $(evt.currentTarget).toggleClass('b-button_hover', evt.type == 'mouseenter');
|
375 | });
|
376 |
|
377 |
|
378 | if( FileAPI.support.dnd ){
|
379 | $('#drag-n-drop').show();
|
380 | $(document).dnd(function (over){
|
381 | $('#drop-zone').toggle(over);
|
382 | }, function (files){
|
383 | onFiles(files);
|
384 | });
|
385 | }
|
386 |
|
387 |
|
388 | $('input[type="file"]').on('change', function (evt){
|
389 | var files = FileAPI.getFiles(evt);
|
390 | onFiles(files);
|
391 | FileAPI.reset(evt.currentTarget);
|
392 | });
|
393 |
|
394 |
|
395 | var FU = {
|
396 | icon: {
|
397 | def: '//cdn1.iconfinder.com/data/icons/CrystalClear/32x32/mimetypes/unknown.png'
|
398 | , image: '//cdn1.iconfinder.com/data/icons/humano2/32x32/apps/synfig_icon.png'
|
399 | , audio: '//cdn1.iconfinder.com/data/icons/august/PNG/Music.png'
|
400 | , video: '//cdn1.iconfinder.com/data/icons/df_On_Stage_Icon_Set/128/Video.png'
|
401 | },
|
402 |
|
403 | files: [],
|
404 | index: 0,
|
405 | active: false,
|
406 |
|
407 | add: function (file){
|
408 | FU.files.push(file);
|
409 |
|
410 | if( /^image/.test(file.type) ){
|
411 | FileAPI.Image(file).preview(35).rotate('auto').get(function (err, img){
|
412 | if( !err ){
|
413 | FU._getEl(file, '.js-left')
|
414 | .addClass('b-file__left_border')
|
415 | .html(img)
|
416 | ;
|
417 | }
|
418 | });
|
419 | }
|
420 | },
|
421 |
|
422 | getFileById: function (id){
|
423 | var i = FU.files.length;
|
424 | while( i-- ){
|
425 | if( FileAPI.uid(FU.files[i]) == id ){
|
426 | return FU.files[i];
|
427 | }
|
428 | }
|
429 | },
|
430 |
|
431 | showLayer: function (id){
|
432 | var $Layer = $('#layer-'+id), file = this.getFileById(id);
|
433 |
|
434 | if( !$Layer[0] ){
|
435 | $Layer = $('<div/>').appendTo('body').attr('id', 'layer-'+id);
|
436 | }
|
437 |
|
438 | $Layer.css('top', $(window).scrollTop() + 30);
|
439 |
|
440 | FileAPI.getInfo(file, function (err, info){
|
441 | $Layer
|
442 | .click(function (){ $(document).click(); })
|
443 | .html(tmpl($('#b-layer-ejs').html(), {
|
444 | file: file
|
445 | , info: $.extend(err ? {} : info, { size: (file.size/1024).toFixed(3) + ' KB' })
|
446 | }))
|
447 | ;
|
448 |
|
449 | if( /image/i.test(file.type) ){
|
450 | if( err ){
|
451 | $Layer.find('.js-img').html('Ooops.');
|
452 | }
|
453 | else {
|
454 | FileAPI.Image(file).preview(300).get(function (err, img){
|
455 | $Layer.find('.js-img').append(img);
|
456 | });
|
457 | }
|
458 | } else {
|
459 | $Layer.find('.js-img').remove();
|
460 | }
|
461 |
|
462 | $(document).off('click.layer keyup.layer').one('click.layer keyup.layer', function (evt){
|
463 | $Layer.remove();
|
464 | });
|
465 | });
|
466 | },
|
467 |
|
468 | start: function (){
|
469 | if( !FU.active && (FU.active = FU.files.length > FU.index) ){
|
470 | FU._upload(FU.files[FU.index]);
|
471 | }
|
472 | },
|
473 |
|
474 | abort: function (id){
|
475 | var file = this.getFileById(id);
|
476 | if( file.xhr ){
|
477 | file.xhr.abort();
|
478 | }
|
479 | },
|
480 |
|
481 | _getEl: function (file, sel){
|
482 | var $el = $('#file-'+FileAPI.uid(file));
|
483 | return sel ? $el.find(sel) : $el;
|
484 | },
|
485 |
|
486 | _upload: function (file){
|
487 | if( file ){
|
488 | file.xhr = FileAPI.upload({
|
489 | url: '/upload',
|
490 | files: { file: file },
|
491 | upload: function (){
|
492 | FU._getEl(file).addClass('b-file_upload');
|
493 | FU._getEl(file, '.js-progress')
|
494 | .css({ opacity: 0 }).show()
|
495 | .animate({ opacity: 1 }, 100)
|
496 | ;
|
497 | },
|
498 | progress: function (evt){
|
499 | FU._getEl(file, '.js-bar').css('width', evt.loaded/evt.total*100+'%');
|
500 | },
|
501 | complete: function (err, xhr){
|
502 | var state = err ? 'error' : 'done';
|
503 |
|
504 | FU._getEl(file).removeClass('b-file_upload');
|
505 | FU._getEl(file, '.js-progress').animate({ opacity: 0 }, 200, function (){ $(this).hide() });
|
506 | FU._getEl(file, '.js-info').append(', <b class="b-file__'+state+'">'+(err ? (xhr.statusText || err) : state)+'</b>');
|
507 |
|
508 | FU.index++;
|
509 | FU.active = false;
|
510 |
|
511 | FU.start();
|
512 | }
|
513 | });
|
514 | }
|
515 | }
|
516 | };
|
517 |
|
518 | function onFiles(files){
|
519 | var $Queue = $('<div/>').prependTo('#preview');
|
520 |
|
521 | FileAPI.each(files, function (file){
|
522 | if( file.size >= 25*FileAPI.MB ){
|
523 | alert('Sorrow.\nMax size 25MB')
|
524 | }
|
525 | else if( file.size === void 0 ){
|
526 | $('#oooops').show();
|
527 | $('#buttons-panel').hide();
|
528 | }
|
529 | else {
|
530 | $Queue.append(tmpl($('#b-file-ejs').html(), { file: file, icon: FU.icon }));
|
531 |
|
532 | FU.add(file);
|
533 | FU.start();
|
534 | }
|
535 | });
|
536 | }
|
537 |
|
538 |
|
539 | $(document)
|
540 | .on('click', '.js-file', function (evt){
|
541 | if( !evt.isDefaultPrevented() ){
|
542 | FU.showLayer(evt.currentTarget.id.split('-')[1]);
|
543 | evt.preventDefault();
|
544 | }
|
545 | })
|
546 | .on('click', '.js-abort', function (evt){
|
547 | FU.abort($(evt.target).closest('.js-file').attr('id').split('-')[1]);
|
548 | evt.preventDefault();
|
549 | })
|
550 | ;
|
551 | });
|
552 | </script>
|
553 |
|
554 | </body>
|
555 | </html>
|