]> git.proxmox.com Git - sencha-touch.git/blob - src/src/device/filesystem/HTML5.js
import Sencha Touch 2.4.2 source
[sencha-touch.git] / src / src / device / filesystem / HTML5.js
1 /**
2 * @private
3 */
4 Ext.define('Ext.device.filesystem.HTML5', {
5 extend: 'Ext.device.filesystem.Abstract',
6 /**
7 * Requests a {@link Ext.device.filesystem.FileSystem} instance.
8 *
9 * var me = this;
10 * var fs = Ext.create("Ext.device.FileSystem", {});
11 * fs.requestFileSystem({
12 * type: window.PERSISTENT,
13 * size: 1024 * 1024,
14 * success: function(fileSystem) {
15 * me.fs = fileSystem;
16 * },
17 * failure: function(err) {
18 * console.log("FileSystem Failure: " + err.code);
19 * }
20 * });
21 *
22 * @param {Object} config
23 * The object which contains the following config options:
24 *
25 * @param {Number} config.type
26 * window.TEMPORARY (0) or window.PERSISTENT (1)
27 *
28 * @param {Number} config.size
29 * Storage space, in Bytes, needed by the application
30 *
31 * @param {Function} config.success This is required.
32 * The callback to be called when the file system has been successfully created.
33 *
34 * @param {Ext.device.filesystem.FileSystem} config.success.fileSystem
35 * The created file system.
36 *
37 * @param {Function} config.failure This is optional.
38 * The callback to be called when an error occurred.
39 *
40 * @param {Object} config.failure.error
41 * The occurred error.
42 *
43 * @param {Object} config.scope
44 * The scope object
45 */
46 requestFileSystem: function(config) {
47 if (!config.success) {
48 Ext.Logger.error('Ext.device.filesystem#requestFileSystem: You must specify a `success` callback.');
49 return null;
50 }
51
52 var me = this;
53 var successCallback = function(fs) {
54 var fileSystem = Ext.create('Ext.device.filesystem.FileSystem', fs);
55 config.success.call(config.scope || me, fileSystem);
56 };
57
58 window.requestFileSystem(
59 config.type,
60 config.size,
61 successCallback,
62 config.failure || Ext.emptyFn
63 );
64 }
65 }, function() {
66 /**
67 * The FileSystem class which is used to represent a file system.
68 */
69 Ext.define('Ext.device.filesystem.FileSystem', {
70 fs: null,
71 root: null,
72
73 constructor: function(fs) {
74 this.fs = fs;
75 this.root = Ext.create('Ext.device.filesystem.DirectoryEntry', '/', this);
76 },
77
78 /**
79 * Returns a {@link Ext.device.filesystem.DirectoryEntry} instance for the root of the file system.
80 *
81 * @return {Ext.device.filesystem.DirectoryEntry}
82 * The file system root directory.
83 */
84 getRoot: function() {
85 return this.root;
86 }
87 }, function() {
88 /**
89 * The Entry class which is used to represent entries in a file system,
90 * each of which may be a {@link Ext.device.filesystem.FileEntry} or a {@link Ext.device.filesystem.DirectoryEntry}.
91 *
92 * This is an abstract class.
93 * @abstract
94 */
95 Ext.define('Ext.device.filesystem.Entry', {
96 directory: false,
97 path: 0,
98 fileSystem: null,
99 entry: null,
100
101 constructor: function(directory, path, fileSystem) {
102 this.directory = directory;
103 this.path = path;
104 this.fileSystem = fileSystem;
105 },
106
107 /**
108 * Returns whether the entry is a file.
109 *
110 * @return {Boolean}
111 * The entry is a file.
112 */
113 isFile: function() {
114 return !this.directory;
115 },
116
117 /**
118 * Returns whether the entry is a directory.
119 *
120 * @return {Boolean}
121 * The entry is a directory.
122 */
123 isDirectory: function() {
124 return this.directory;
125 },
126
127 /**
128 * Returns the name of the entry, excluding the path leading to it.
129 *
130 * @return {String}
131 * The entry name.
132 */
133 getName: function() {
134 var components = this.path.split('/');
135 for (var i = components.length - 1; i >= 0; --i) {
136 if (components[i].length > 0) {
137 return components[i];
138 }
139 }
140
141 return '/';
142 },
143
144 /**
145 * Returns the full absolute path from the root to the entry.
146 *
147 * @return {String}
148 * The entry full path.
149 */
150 getFullPath: function() {
151 return this.path;
152 },
153
154 /**
155 * Returns the file system on which the entry resides.
156 *
157 * @return {Ext.device.filesystem.FileSystem}
158 * The entry file system.
159 */
160 getFileSystem: function() {
161 return this.fileSystem;
162 },
163
164 getEntry: function() {
165 return null;
166 },
167
168 /**
169 * Moves the entry to a different location on the file system.
170 *
171 * @param {Object} config
172 * The object which contains the following config options:
173 *
174 * @param {Ext.device.filesystem.DirectoryEntry} config.parent This is required.
175 * The directory to which to move the entry.
176 *
177 * @param {String} config.newName This is optional.
178 * The new name of the entry to move. Defaults to the entry's current name if unspecified.
179 *
180 * @param {Function} config.success This is optional.
181 * The callback to be called when the entry has been successfully moved.
182 *
183 * @param {Ext.device.filesystem.Entry} config.success.entry
184 * The entry for the new location.
185 *
186 * @param {Function} config.failure This is optional.
187 * The callback to be called when an error occurred.
188 *
189 * @param {Object} config.failure.error
190 * The occurred error.
191 *
192 * @param {Object} config.scope
193 * The scope object
194 */
195 moveTo: function(config) {
196 if (config.parent == null) {
197 Ext.Logger.error('Ext.device.filesystem.Entry#moveTo: You must specify a new `parent` of the entry.');
198 return null;
199 }
200
201 var me = this;
202
203 this.getEntry(
204 {
205 options: config.options || {},
206 success: function(sourceEntry) {
207 config.parent.getEntry(
208 {
209 options: config.options || {},
210 success: function(destinationEntry) {
211 if (config.copy) {
212 sourceEntry.copyTo(destinationEntry, config.newName, function(entry) {
213 config.success.call(
214 config.scope || me,
215 entry.isDirectory ? Ext.create('Ext.device.filesystem.DirectoryEntry', entry.fullPath, me.fileSystem) : Ext.create('Ext.device.filesystem.FileEntry', entry.fullPath, me.fileSystem)
216 );
217 }, config.failure);
218 } else {
219 sourceEntry.moveTo(destinationEntry, config.newName, function(entry) {
220 config.success.call(
221 config.scope || me,
222 entry.isDirectory ? Ext.create('Ext.device.filesystem.DirectoryEntry', entry.fullPath, me.fileSystem) : Ext.create('Ext.device.filesystem.FileEntry', entry.fullPath, me.fileSystem)
223 );
224 }, config.failure);
225 }
226 },
227 failure: config.failure
228 }
229 );
230 },
231 failure: config.failure
232 }
233 );
234 },
235
236 /**
237 * Works the same way as {@link Ext.device.filesystem.Entry#moveTo}, but copies the entry.
238 */
239 copyTo: function(config) {
240 this.moveTo(Ext.apply(config, {
241 copy: true
242 }));
243 },
244
245 /**
246 * Removes the entry from the file system.
247 *
248 * @param {Object} config
249 * The object which contains the following config options:
250 *
251 * @param {Boolean} config.recursively This is optional
252 * Deletes a directory and all of its contents
253 *
254 * @param {Function} config.success This is optional.
255 * The callback to be called when the entry has been successfully removed.
256 *
257 * @param {Function} config.failure This is optional.
258 * The callback to be called when an error occurred.
259 *
260 * @param {Object} config.failure.error
261 * The occurred error.
262 *
263 * @param {Object} config.scope
264 * The scope object
265 */
266 remove: function(config) {
267 this.getEntry(
268 {
269 success: function(entry) {
270 if (config.recursively && this.directory) {
271 entry.removeRecursively(config.success, config.failure)
272 } else {
273 entry.remove(config.success, config.failure)
274 }
275 },
276 failure: config.failure
277 }
278 )
279 },
280
281 /**
282 * Looks up the parent directory containing the entry.
283 *
284 * @param {Object} config
285 * The object which contains the following config options:
286 *
287 * @param {Function} config.success This is required.
288 * The callback to be called when the parent directory has been successfully selected.
289 *
290 * @param {Ext.device.filesystem.DirectoryEntry} config.success.entry
291 * The parent directory of the entry.
292 *
293 * @param {Function} config.failure This is optional.
294 * The callback to be called when an error occurred.
295 *
296 * @param {Object} config.failure.error
297 * The occurred error.
298 *
299 * @param {Object} config.scope
300 * The scope object
301 */
302 getParent: function(config) {
303 if (!config.success) {
304 Ext.Logger.error('Ext.device.filesystem.Entry#getParent: You must specify a `success` callback.');
305 return null;
306 }
307
308 var me = this;
309 this.getEntry(
310 {
311 options: config.options || {},
312 success: function(entry) {
313 entry.getParent(
314 function(parentEntry) {
315 config.success.call(
316 config.scope || me,
317 parentEntry.isDirectory
318 ? Ext.create('Ext.device.filesystem.DirectoryEntry', parentEntry.fullPath, me.fileSystem)
319 : Ext.create('Ext.device.filesystem.FileEntry', parentEntry.fullPath, me.fileSystem)
320 )
321 },
322 config.failure
323 )
324
325 },
326 failure: config.failure
327 }
328 )
329 }
330 });
331
332 /**
333 * The DirectoryEntry class which is used to represent a directory on a file system.
334 */
335 Ext.define('Ext.device.filesystem.DirectoryEntry', {
336 extend: 'Ext.device.filesystem.Entry',
337 cachedDirectory: null,
338
339 constructor: function(path, fileSystem) {
340 this.callParent([true, path, fileSystem]);
341 },
342
343 /**
344 * Requests a Directory from the Local File System
345 *
346 * @param {Object} config
347 *
348 * @param {Object} config.options
349 * File creation options {create:true, exclusive:false}
350 *
351 * @param {Boolean} config.options.create
352 * Indicates if the directory should be created if it doesn't exist
353 *
354 * @param {Boolean} config.options.exclusive
355 * Used with the create option only indicates whether a creation causes an error if the directory already exists
356 *
357 * @param {Function} config.success
358 * The function called when the Directory is returned successfully
359 *
360 * @param {Ext.device.filesystem.DirectoryEntry} config.success.directory
361 * DirectoryEntry Object
362 *
363 * @param {Function} config.failure
364 * The function called when the Directory request causes an error
365 *
366 * @param {FileError} config.failure.error
367 */
368 getEntry: function(config) {
369 var me = this;
370 var callback = config.success;
371
372 if ((config.options && config.options.create) && this.path) {
373 var folders = this.path.split("/");
374 if (folders[0] == '.' || folders[0] == '') {
375 folders = folders.slice(1);
376 }
377
378 var recursiveCreation = function(dirEntry) {
379 if (folders.length) {
380 dirEntry.getDirectory(folders.shift(), config.options, recursiveCreation, config.failure);
381 } else {
382 callback(dirEntry);
383 }
384 };
385
386 recursiveCreation(this.fileSystem.fs.root);
387 } else {
388 this.fileSystem.fs.root.getDirectory(this.path, config.options,
389 function(directory) {
390 config.success.call(config.scope || me, directory);
391 },
392 config.failure
393 );
394 }
395 },
396
397 /**
398 * Lists all the entries in the directory.
399 *
400 * @param {Object} config
401 * The object which contains the following config options:
402 *
403 * @param {Function} config.success This is required.
404 * The callback to be called when the entries has been successfully read.
405 *
406 * @param {Ext.device.filesystem.Entry[]} config.success.entries
407 * The array of entries of the directory.
408 *
409 * @param {Function} config.failure This is optional.
410 * The callback to be called when an error occurred.
411 *
412 * @param {Object} config.failure.error
413 * The occurred error.
414 *
415 * @param {Object} config.scope
416 * The scope object
417 */
418 readEntries: function(config) {
419 if (!config.success) {
420 Ext.Logger.error('Ext.device.filesystem.DirectoryEntry#readEntries: You must specify a `success` callback.');
421 return null;
422 }
423
424 var me = this;
425 this.getEntry(
426 {
427 success: function(dirEntry) {
428 var directoryReader = dirEntry.createReader();
429 directoryReader.readEntries(
430 function(entryInfos) {
431 var entries = [],
432 i = 0,
433 len = entryInfos.length;
434
435 for (; i < len; i++) {
436 entryInfo = entryInfos[i];
437 entries[i] = entryInfo.isDirectory
438 ? Ext.create('Ext.device.filesystem.DirectoryEntry', entryInfo.fullPath, me.fileSystem)
439 : Ext.create('Ext.device.filesystem.FileEntry', entryInfo.fullPath, me.fileSystem);
440 }
441 config.success.call(config.scope || this, entries);
442 },
443 function(error) {
444 if (config.failure) {
445 config.failure.call(config.scope || this, error);
446 }
447 }
448 );
449 },
450 failure: config.failure
451 }
452 );
453 },
454
455 /**
456 * Creates or looks up a file.
457 *
458 * @param {Object} config
459 * The object which contains the following config options:
460 *
461 * @param {String} config.path This is required.
462 * The absolute path or relative path from the entry to the file to create or select.
463 *
464 * @param {Object} config.options This is optional.
465 * The object which contains the following options:
466 *
467 * @param {Boolean} config.options.create This is optional.
468 * Indicates whether to create a file, if path does not exist.
469 *
470 * @param {Boolean} config.options.exclusive This is optional. Used with 'create', by itself has no effect.
471 * Indicates that method should fail, if path already exists.
472 *
473 * @param {Function} config.success This is optional.
474 * The callback to be called when the file has been successfully created or selected.
475 *
476 * @param {Ext.device.filesystem.Entry} config.success.entry
477 * The created or selected file.
478 *
479 * @param {Function} config.failure This is optional.
480 * The callback to be called when an error occurred.
481 *
482 * @param {Object} config.failure.error
483 * The occurred error.
484 *
485 * @param {Object} config.scope
486 * The scope object
487 */
488 getFile: function(config) {
489 if (config.path == null) {
490 Ext.Logger.error('Ext.device.filesystem.DirectoryEntry#getFile: You must specify a `path` of the file.');
491 return null;
492 }
493
494 var me = this;
495 var fullPath = this.path + config.path;
496 var fileEntry = Ext.create('Ext.device.filesystem.FileEntry', fullPath, this.fileSystem);
497 fileEntry.getEntry(
498 {
499 success: function() {
500 config.success.call(config.scope || me, fileEntry);
501 },
502 options: config.options || {},
503 failure: config.failure
504 }
505 )
506 },
507
508 /**
509 * Works the same way as {@link Ext.device.filesystem.DirectoryEntry#getFile},
510 * but creates or looks up a directory.
511 */
512 getDirectory: function(config) {
513 if (config.path == null) {
514 Ext.Logger.error('Ext.device.filesystem.DirectoryEntry#getFile: You must specify a `path` of the file.');
515 return null;
516 }
517
518 var me = this;
519 var fullPath = this.path + config.path;
520 var directoryEntry = Ext.create('Ext.device.filesystem.DirectoryEntry', fullPath, this.fileSystem);
521 directoryEntry.getEntry(
522 {
523 success: function() {
524 config.success.call(config.scope || me, directoryEntry);
525 },
526 options: config.options || {},
527 failure: config.failure
528 }
529 )
530 },
531
532 /**
533 * Works the same way as {@link Ext.device.filesystem.Entry#remove},
534 * but removes the directory and all of its contents, if any.
535 */
536 removeRecursively: function(config) {
537 this.remove(Ext.apply(config, {
538 recursively: true
539 }));
540 }
541 });
542
543 /**
544 * The FileEntry class which is used to represent a file on a file system.
545 */
546 Ext.define('Ext.device.filesystem.FileEntry', {
547 extend: 'Ext.device.filesystem.Entry',
548
549 length: 0,
550 offset: 0,
551
552 constructor: function(path, fileSystem) {
553 this.callParent([false, path, fileSystem]);
554 this.offset = 0;
555 this.length = 0;
556 },
557
558 /**
559 * Requests a File Handle from the Local File System
560 *
561 * @param {Object} config
562 *
563 * @param {String} config.file
564 * Filename optionally including path in string format '/tmp/debug.txt' or a File Object
565 *
566 * @param {Object} config.options
567 * File creation options {create:true, exclusive:false}
568 *
569 * @param {Boolean} config.options.create
570 * Indicates if the file should be created if it doesn't exist
571 *
572 * @param {Boolean} config.options.exclusive
573 * Used with the create option only indicates whether a creation causes an error if the file already exists
574 *
575 * @param {Function} config.success
576 * The function called when the filesystem is returned successfully
577 *
578 * @param {FileSystem} config.success.entry
579 *
580 * @param {Function} config.failure
581 * The function called when the filesystem request causes and error
582 *
583 * @param {FileError} config.failure.error
584 *
585 */
586 getEntry: function(config) {
587 var me = this;
588 var originalConfig = Ext.applyIf({}, config);
589 if (this.fileSystem) {
590 var failure = function(evt) {
591 if ((config.options && config.options.create) && Ext.isString(this.path)) {
592 var folders = this.path.split("/");
593 if (folders[0] == '.' || folders[0] == '') {
594 folders = folders.slice(1);
595 }
596
597 if (folders.length > 1 && !config.recursive === true) {
598 folders.pop();
599
600 var dirEntry = Ext.create('Ext.device.filesystem.DirectoryEntry', folders.join("/"), me.fileSystem);
601 dirEntry.getEntry(
602 {
603 options: config.options,
604 success: function() {
605 originalConfig.recursive = true;
606 me.getEntry(originalConfig);
607 },
608 failure: config.failure
609 }
610 );
611 } else {
612 if (config.failure) {
613 config.failure.call(config.scope || me, evt);
614 }
615 }
616 } else {
617 if (config.failure) {
618 config.failure.call(config.scope || me, evt);
619 }
620 }
621 };
622
623 this.fileSystem.fs.root.getFile(this.path, config.options || null,
624 function(fileEntry) {
625 fileEntry.file(
626 function(file) {
627 me.length = file.size;
628 originalConfig.success.call(config.scope || me, fileEntry);
629 },
630 function(error) {
631 failure.call(config.scope || me, error);
632 }
633 );
634 },
635 function(error) {
636 failure.call(config.scope || me, error);
637 }
638 );
639 } else {
640 config.failure({code: -1, message: "FileSystem not Initialized"});
641 }
642 },
643
644 /**
645 * Returns the byte offset into the file at which the next read/write will occur.
646 *
647 * @return {Number}
648 * The file offset.
649 */
650 getOffset: function() {
651 return this.offset;
652 },
653
654 /**
655 * Sets the byte offset into the file at which the next read/write will occur.
656 *
657 * @param {Object} config
658 * The object which contains the following config options:
659 *
660 * @param {Number} config.offset This is required.
661 * The file offset to set. If negative, the offset back from the end of the file.
662 *
663 * @param {Function} config.success This is optional.
664 * The callback to be called when the file offset has been successfully set.
665 *
666 * @param {Function} config.failure This is optional.
667 * The callback to be called when an error occurred.
668 *
669 * @param {Object} config.failure.error
670 * The occurred error.
671 *
672 * @param {Object} config.scope
673 * The scope object
674 */
675 seek: function(config) {
676 if (config.offset == null) {
677 Ext.Logger.error('Ext.device.filesystem.FileEntry#seek: You must specify an `offset` in the file.');
678 return null;
679 }
680
681 this.offset = config.offset || 0;
682
683 if (config.success) {
684 config.success.call(config.scope || this);
685 }
686 },
687
688 /**
689 * Reads the data from the file starting at the file offset.
690 *
691 * @param {Object} config
692 * The object which contains the following config options:
693 *
694 * @param {Number} config.length This is optional.
695 * The length of bytes to read from the file. Defaults to the file's current size if unspecified.
696 *
697 * @param {String} config.encoding
698 * Optional encoding type used only for reading as Text
699 *
700 * @param {String} config.type
701 * Type of reading to use options are "text" (default), "dataURL", "binaryString" and "arrayBuffer"
702 *
703 * @param {Object} config.reader
704 * Optional config params to be applied to a File Reader
705 *
706 * @param {Function} config.reader.onloadstart
707 * @param {Function} config.reader.onloadprogress
708 * @param {Function} config.reader.onload
709 * @param {Function} config.reader.onabort
710 * @param {Function} config.reader.onerror
711 * @param {Function} config.reader.onloadend
712 *
713 * @param {Function} config.success This is optional.
714 * The callback to be called when the data has been successfully read.
715 *
716 * @param {Object} config.success.data
717 * The read data.
718 *
719 * @param {Function} config.failure This is optional.
720 * The callback to be called when an error occurred.
721 *
722 * @param {Object} config.failure.error
723 * The occurred error.
724 *
725 * @param {Object} config.scope
726 * The scope object
727 */
728 read: function(config) {
729 var me = this;
730 this.getEntry(
731 {
732 success: function(fileEntry) {
733 fileEntry.file(
734 function(file) {
735 if (Ext.isNumber(config.length)) {
736 if (Ext.isFunction(file.slice)) {
737 file = file.slice(me.offset, config.length);
738 } else {
739 if (config.failure) {
740 config.failure.call(config.scope || me, {code: -2, message: "File missing slice functionality"});
741 }
742 return;
743 }
744 }
745
746 var reader = new FileReader();
747 reader.onloadend = function(evt) {
748 config.success.call(config.scope || me, evt.target.result);
749 };
750
751 reader.onerror = function(error) {
752 config.failure.call(config.scope || me, error);
753 };
754
755 if (config.reader) {
756 reader = Ext.applyIf(reader, config.reader);
757 }
758
759 config.encoding = config.encoding || "UTF8";
760
761 switch (config.type) {
762 default:
763 case "text":
764 reader.readAsText(file, config.encoding);
765 break;
766 case "dataURL":
767 reader.readAsDataURL(file);
768 break;
769 case "binaryString":
770 reader.readAsBinaryString(file);
771 break;
772 case "arrayBuffer":
773 reader.readAsArrayBuffer(file);
774 break;
775 }
776 },
777 function(error) {
778 config.failure.call(config.scope || me, error)
779 }
780 );
781 },
782 failure: function(error) {
783 config.failure.call(config.scope || me, error)
784 }
785 }
786 )
787 },
788
789 /**
790 * Writes the data to the file starting at the file offset.
791 *
792 * @param {Object} config
793 * The object which contains the following config options:
794 *
795 * @param {Object} config.data This is required.
796 * The data to write to the file.
797 *
798 * @param {Boolean} config.append This is optional.
799 * Append to the end of the file
800 *
801 * @param {Object} config.writer
802 * Optional config params to be applied to a File Reader
803 *
804 * @param {Function} config.writer.onwritestart
805 * @param {Function} config.writer.onprogress
806 * @param {Function} config.writer.onwrite
807 * @param {Function} config.writer.onabort
808 * @param {Function} config.writer.onerror
809 * @param {Function} config.writer.onwriteend
810 *
811 * @param {Function} config.success This is optional.
812 * The callback to be called when the data has been successfully written.
813 *
814 * @param {Function} config.failure This is optional.
815 * The callback to be called when an error occurred.
816 *
817 * @param {Object} config.failure.error
818 * The occurred error.
819 *
820 * @param {Object} config.scope
821 * The scope object
822 */
823 write: function(config) {
824 if (config.data == null) {
825 Ext.Logger.error('Ext.device.filesystem.FileEntry#write: You must specify `data` to write into the file.');
826 return null;
827 }
828
829 var me = this;
830 this.getEntry(
831 {
832 options: config.options || {},
833 success: function(fileEntry) {
834 fileEntry.createWriter(
835 function(writer) {
836 writer.onwriteend = function(evt) {
837 me.length = evt.target.length;
838 config.success.call(config.scope || me, evt.result);
839 };
840
841 writer.onerror = function(error) {
842 config.failure.call(config.scope || me, error);
843 };
844
845 if (config.writer) {
846 writer = Ext.applyIf(writer, config.writer);
847 }
848
849 if (me.offset) {
850 writer.seek(me.offset);
851 } else if (config.append) {
852 writer.seek(me.length);
853 }
854
855 me.writeData (writer, config.data);
856 },
857 function(error) {
858 config.failure.call(config.scope || me, error)
859 }
860 )
861 },
862 failure: function(error) {
863 config.failure.call(config.scope || me, error)
864 }
865 }
866 )
867 },
868
869 writeData: function(writer, data) {
870 writer.write(new Blob([data]));
871 },
872
873 /**
874 * Truncates or extends the file to the specified size in bytes.
875 * If the file is extended, the added bytes are null bytes.
876 *
877 * @param {Object} config
878 * The object which contains the following config options:
879 *
880 * @param {Number} config.size This is required.
881 * The new file size.
882 *
883 * @param {Function} config.success This is optional.
884 * The callback to be called when the file size has been successfully changed.
885 *
886 * @param {Function} config.failure This is optional.
887 * The callback to be called when an error occurred.
888 *
889 * @param {Object} config.failure.error
890 * The occurred error.
891 *
892 * @param {Object} config.scope
893 * The scope object
894 */
895 truncate: function(config) {
896 if (config.size == null) {
897 Ext.Logger.error('Ext.device.filesystem.FileEntry#write: You must specify a `size` of the file.');
898 return null;
899 }
900
901 var me = this;
902 //noinspection JSValidateTypes
903 this.getEntry(
904 {
905 success: function(fileEntry) {
906 fileEntry.createWriter(
907 function(writer) {
908 writer.truncate(config.size);
909 config.success.call(config.scope || me, me);
910 },
911 function(error) {
912 config.failure.call(config.scope || me, error)
913 }
914 )
915 },
916 failure: function(error) {
917 config.failure.call(config.scope || me, error)
918 }
919 }
920 )
921 }
922 });
923 });
924 });