|
| 1 | +/** |
| 2 | + * File picker and finder for device storages on Firefox OS devices |
| 3 | + * |
| 4 | + * This library provides an easy-to-use asynchronous interface for other Firefox OS apps to search for files |
| 5 | + * on Firefox OS devices. The library is based on an event-based architecture, letting developers build |
| 6 | + * beautiful asynchronous API for their apps. |
| 7 | + * |
| 8 | + * The `Finder` library is best used by developers looking to pick a file from the `sdcard` for their apps. |
| 9 | + * |
| 10 | + * This library depends on [EventEmitter](https://github.com/Wolfy87/EventEmitter) by Wolfy87, included with the |
| 11 | + * package. |
| 12 | + * |
| 13 | + * @version 1.0.0 |
| 14 | + * @license The MIT License (MIT) |
| 15 | + * |
| 16 | + * Copyright (c) 2014 Applait Technologies LLP |
| 17 | + */ |
| 18 | + |
| 19 | +var Applait = Applait || {}; |
| 20 | + |
| 21 | +/** |
| 22 | + * Core `Finder` class. Provides the constructor for applications to instantiate. |
| 23 | + * |
| 24 | + * @constructor |
| 25 | + * @param {object=} options - Default options for the `Finder` constructor. It can include any of the following |
| 26 | + * properties: |
| 27 | + * |
| 28 | + * - `type` : `{string}` : Can be one of `sdcard`, `music`, `pictures`, `videos`. Defaults to `sdcard`. |
| 29 | + * - `minSearchLength`: `{number}` : The minimum length of search string without which search will not be triggered. |
| 30 | + * Defaults to `3`. |
| 31 | + * - `debugMode`: `{boolean}` : If `true`, enables debug mode which logs all messages to the browser console. This |
| 32 | + * should be disabled in production mode to reduce memory footprint. |
| 33 | + * |
| 34 | + * @example |
| 35 | + * var finder = new Applait.Finder({ type: "sdcard", debugMode: true }); |
| 36 | + */ |
| 37 | +Applait.Finder = function (options) { |
| 38 | + |
| 39 | + this.options = options || {}; |
| 40 | + |
| 41 | + this.type = options.type || "sdcard"; |
| 42 | + |
| 43 | + this.minSearchLength = (options.minSearchLength && typeof options.minSearchLength === "number") ? |
| 44 | + options.minSearchLength || 3; |
| 45 | + |
| 46 | + this.debugMode = (options.debugMode && options.debugMode === true) ? true : false; |
| 47 | + |
| 48 | + this.storages = navigator.getDeviceStorages && navigator.getDeviceStorages(this.type); |
| 49 | + |
| 50 | + this.events = new EventEmitter(); |
| 51 | + |
| 52 | +}; |
| 53 | + |
| 54 | +/** |
| 55 | + * Instantiate search |
| 56 | + * |
| 57 | + * @memberOf Applait.Finder |
| 58 | + * @param {string} needle - The string to match file names from the device storage. |
| 59 | + * @return {null} - Only if `needle` length is less than 3 characters or if no DeviceStorages are found. |
| 60 | + */ |
| 61 | +Applait.Finder.prototype.search = function (needle) { |
| 62 | + |
| 63 | + var context = this, |
| 64 | + filematchcount = 0; |
| 65 | + |
| 66 | + needle = needle.trim(); |
| 67 | + |
| 68 | + if (needle.length < context.minSearchLength) { |
| 69 | + if (context.debugMode) { |
| 70 | + console.log("Search cancelled. Less than " + context.minSearchLength + " characters search string"); |
| 71 | + } |
| 72 | + context.events.emitEvent("searchCancelled", ["Search string should be at least " + context.minSearchLength |
| 73 | + + " characters"]); |
| 74 | + return null; |
| 75 | + } |
| 76 | + |
| 77 | + if (context.storages.length < 1) { |
| 78 | + if (context.debugMode) console.log("empty", needle); |
| 79 | + context.events.emitEvent("empty", [needle]); |
| 80 | + return null; |
| 81 | + } |
| 82 | + |
| 83 | + if (context.debugMode) console.log("searchBegin", needle); |
| 84 | + context.events.emitEvent("searchBegin", [needle]); |
| 85 | + |
| 86 | + context.storages.forEach(function (storage) { |
| 87 | + |
| 88 | + var cursor = storage.enumerate(); |
| 89 | + |
| 90 | + if (context.debugMode) console.log("storageSearchBegin", storage.storageName, needle); |
| 91 | + context.events.emitEvent("storageSearchBegin", [storage.storageName, needle]); |
| 92 | + |
| 93 | + cursor.onsuccess = function () { |
| 94 | + |
| 95 | + if (this.result) { |
| 96 | + |
| 97 | + var file = this.result; |
| 98 | + var fileinfo = context.splitname(file.name); |
| 99 | + |
| 100 | + if (fileinfo.name.indexOf(needle) > -1) { |
| 101 | + filematchcount++; |
| 102 | + if (context.debugMode) console.log("fileFound", file, fileinfo, storage.storageName); |
| 103 | + context.events.emitEvent("fileFound", [file, fileinfo, storage.storageName]); |
| 104 | + } |
| 105 | + |
| 106 | + if (!this.done) { |
| 107 | + this.continue(); |
| 108 | + } else { |
| 109 | + if (context.debugMode) console.log("searchComplete", storage.storageName, needle, filematchcount); |
| 110 | + context.events.emitEvent("searchComplete", [storage.storageName, needle, filematchcount]); |
| 111 | + } |
| 112 | + } else { |
| 113 | + if (context.debugMode) console.log("searchComplete", storage.storageName, needle, filematchcount); |
| 114 | + context.events.emitEvent("searchComplete", [storage.storageName, needle, filematchcount]); |
| 115 | + } |
| 116 | + |
| 117 | + }; |
| 118 | + |
| 119 | + cursor.onerror = function () { |
| 120 | + if (context.debugMode) console.log("Error accessing device storage '" + storage.storageName + "'", this.error); |
| 121 | + context.events.emitEvent('error', ["Error accessing device storage '" + storage.storageName + "'", this.error]); |
| 122 | + }; |
| 123 | + |
| 124 | + }); |
| 125 | +}; |
| 126 | + |
| 127 | +/** |
| 128 | + * Splits full file path into basename and path to directory. |
| 129 | + * |
| 130 | + * @memberOf Applait.Finder |
| 131 | + * @param {string} filename - Filename obtained for `File.filename` |
| 132 | + * @return {object} - An object with two keys: |
| 133 | + * |
| 134 | + * - `name` - the basename of the file with extension |
| 135 | + * - `path` - path to the file's directory. |
| 136 | + */ |
| 137 | +Applait.Finder.prototype.splitname = function (filename) { |
| 138 | + filename = filename.split(/[\\/]/); |
| 139 | + |
| 140 | +return { "name": filename.pop(), "path": filename.join("/") }; |
| 141 | +}; |
0 commit comments