123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440 |
- var platform = {};
- if (typeof AppPreferencesLocalStorage === "undefined") {
- try {
- platform = require ('./platform');
- } catch (e) {
- }
- } else {
- platform = new AppPreferencesLocalStorage ();
- }
- /**
- * @constructor
- */
- function AppPreferences (defaultArgs) {
- this.defaultArgs = defaultArgs || {};
- }
- var promiseLib;
- if (typeof Promise !== "undefined") {
- promiseLib = Promise;
- } else if (typeof WinJS !== "undefined" && WinJS.Promise) {
- promiseLib = WinJS.Promise;
- } else if (typeof $ !== "undefined" && $.Deferred) {
- promiseLib = function (init) {
- var d = $.Deferred ();
- init (d.resolve.bind (d), d.reject.bind (d));
- return d.promise ();
- }
- }
- function promiseCheck (maxArgs, successCallback, errorCallback) {
- if (
- typeof successCallback !== 'function' && typeof errorCallback !== 'function'
- && arguments.length <= maxArgs + 1 // argCount
- && promiseLib
- ) {
- return true;
- } else {
- return false;
- }
- }
- if (!platform.nativeExec && typeof cordova !== "undefined")
- platform.nativeExec = cordova.exec.bind (cordova);
- AppPreferences.prototype.prepareKey = platform.prepareKey || function (mode, dict, key, value) {
- var args = {};
- for (var k in this.defaultArgs) {
- args[k] = this.defaultArgs[k];
- }
- var argList = [].slice.apply(arguments);
- argList.shift();
- if (
- (mode == 'get' && argList.length == 1) ||
- (mode == 'get' && argList.length == 2 && argList[1] == null) ||
- (mode == 'set' && argList.length == 2) ||
- (mode == 'set' && argList.length == 3 && argList[2] == null)
- ) {
- argList.unshift (undefined);
- }
- args.key = argList[1];
- if (argList[0] !== undefined)
- args.dict = argList[0]
- if (mode == 'set')
- args.value = argList[2];
- // console.log (JSON.stringify (argList), JSON.stringify (args));
- return args;
- }
- /**
- * Get a preference value
- *
- * @param {Function} successCallback The function to call when the value is available
- * @param {Function} errorCallback The function to call when value is unavailable
- * @param {String} dict Dictionary for key (OPTIONAL)
- * @param {String} key Key
- */
- AppPreferences.prototype.fetch = platform.fetch || function (
- successCallback, errorCallback, dict, key
- ) {
- var argCount = 2; // dict, key
- var promise = promiseCheck.apply (this, [argCount].concat ([].slice.call(arguments)));
- // for promises
- if (promise) {
- dict = successCallback;
- key = errorCallback;
- }
- var args = this.prepareKey ('get', dict, key);
- var _successCallback = function (_value) {
- var value = _value;
- try {
- value = JSON.parse (_value);
- } catch (e) {
- }
- successCallback (value);
- }
- var nativeExec = function (resolve, reject) {
- if (!args.key) {
- return reject ();
- }
- if (resolve !== successCallback) {
- successCallback = resolve;
- }
- if (platform.nativeFetch) {
- return platform.nativeFetch(_successCallback, reject, args);
- }
- return platform.nativeExec(_successCallback, reject, "AppPreferences", "fetch", [args]);
- }
- if (promise) {
- return new promiseLib (nativeExec);
- } else {
- nativeExec (successCallback, errorCallback);
- }
- };
- /**
- * Set a preference value
- *
- * @param {Function} successCallback The function to call when the value is set successfully
- * @param {Function} errorCallback The function to call when value is not set
- * @param {String} dict Dictionary for key (OPTIONAL)
- * @param {String} key Key
- * @param {String} value Value
- */
- AppPreferences.prototype.store = platform.store || function (
- successCallback, errorCallback, dict, key, value
- ) {
- var argCount = 3; // dict, key, value
- var promise = promiseCheck.apply (this, [argCount].concat ([].slice.call(arguments)));
- // for promises
- if (promise) {
- value = dict;
- key = errorCallback;
- dict = successCallback;
- }
- var args = this.prepareKey ('set', dict, key, value);
- args.type = typeof args.value;
- // VERY IMPORTANT THING
- // WP platform has some limitations, so we need to encode all values to JSON.
- // On plugin side we store value according to it's type.
- // So, every platform plugin must check for type, decode JSON and store
- // value decoded for basic types.
- // TODO: don't think about array of strings, it's android only.
- // Complex structures must be stored as JSON string.
- // On iOS strings stored as strings and JSON stored as NSData
- // Android:
- // Now, interesting thing: how to differentiate between string value
- // and complex value, encoded as json and stored as string?
- // I'm introduce setting named _<preference>_type with value "JSON"
- // Windows Phone ?
- args.value = JSON.stringify (args.value);
- var nativeExec = function (resolve, reject) {
- if (!args.key || args.value === null || args.value === undefined) {
- return reject ();
- }
- if (platform.nativeStore) {
- return platform.nativeStore (resolve, reject, args);
- }
- return platform.nativeExec (resolve, reject, "AppPreferences", "store", [args]);
- }
- if (promise) {
- return new promiseLib (nativeExec);
- } else {
- nativeExec (successCallback, errorCallback);
- }
- };
- /**
- * Remove value from preferences
- *
- * @param {Function} successCallback The function to call when the value is available
- * @param {Function} errorCallback The function to call when value is unavailable
- * @param {String} dict Dictionary for key (OPTIONAL)
- * @param {String} key Key
- */
- AppPreferences.prototype.remove = platform.remove || function (
- successCallback, errorCallback, dict, key
- ) {
- var argCount = 2; // dict, key
- var promise = promiseCheck.apply (this, [argCount].concat ([].slice.call(arguments)));
- // for promises
- if (promise) {
- key = errorCallback;
- dict = successCallback;
- }
- var args = this.prepareKey ('get', dict, key);
- var nativeExec = function (resolve, reject) {
- if (!args.key) {
- return reject ();
- }
- if (platform.nativeRemove) {
- return platform.nativeRemove (resolve, reject, args);
- }
- return platform.nativeExec (resolve, reject, "AppPreferences", "remove", [args]);
- }
- if (promise) {
- return new promiseLib (nativeExec);
- } else {
- nativeExec (successCallback, errorCallback);
- }
- };
- /**
- * Clear preferences
- *
- * @param {Function} successCallback The function to call when the value is available
- * @param {Function} errorCallback The function to call when value is unavailable
- * @param {String} dict Dictionary for key (OPTIONAL)
- * @param {String} key Key
- */
- AppPreferences.prototype.clearAll = platform.clearAll || function (
- successCallback, errorCallback
- ) {
- var argCount = 0;
- var promise = promiseCheck.apply (this, [argCount].concat ([].slice.call(arguments)));
- var args = {};
- for (var k in this.defaultArgs) {
- args[k] = this.defaultArgs[k];
- }
- var nativeExec = function (resolve, reject) {
- if (platform.nativeClearAll) {
- return platform.nativeClearAll (resolve, reject, args);
- }
- return platform.nativeExec (resolve, reject, "AppPreferences", "clearAll", [args]);
- }
- if (promise) {
- return new promiseLib (nativeExec);
- } else {
- nativeExec (successCallback, errorCallback);
- }
- };
- /**
- * Show native preferences interface
- *
- * @param {Function} successCallback The function to call when the value is available
- * @param {Function} errorCallback The function to call when value is unavailable
- * @param {String} dict Dictionary for key (OPTIONAL)
- * @param {String} key Key
- */
- AppPreferences.prototype.show = platform.show || function (
- successCallback, errorCallback
- ) {
- var argCount = 0;
- var promise = promiseCheck.apply (this, [argCount].concat ([].slice.call(arguments)));
- var nativeExec = function (resolve, reject) {
- return platform.nativeExec (resolve, reject, "AppPreferences", "show", []);
- }
- if (promise) {
- return new promiseLib (nativeExec);
- } else {
- nativeExec (successCallback, errorCallback);
- }
- };
- /**
- * Watch for preferences change
- *
- * @param {Function} successCallback The function to call when the value is available
- * @param {Function} errorCallback The function to call when value is unavailable
- * @param {Boolean} subscribe true value to subscribe, false - unsubscribe
- * @example How to get notified:
- * ```javascript
- * plugins.appPreferences.watch();
- * document.addEventListener ('preferencesChanged', function (evt) {
- * // with some platforms can give you details what is changed
- * if (evt.key) {
- * // handle key change
- * } else if (evt.all) {
- * // after clearAll
- * }
- * });
- * ```
- */
- AppPreferences.prototype.watch = platform.watch || function (
- successCallback, errorCallback, subscribe
- ) {
- if (typeof subscribe === "undefined") {
- subscribe = true;
- }
- var args = {};
- for (var k in this.defaultArgs) {
- args[k] = this.defaultArgs[k];
- }
- args.subscribe = subscribe;
- var nativeExec = function (resolve, reject) {
- if (platform.nativeWatch) {
- return platform.nativeWatch (resolve, reject, args);
- }
- return platform.nativeExec (resolve, reject, "AppPreferences", "watch", [args]);
- }
- nativeExec (successCallback, errorCallback);
- };
- /**
- * Return named configuration context
- * In iOS you'll get a suite configuration, on Android — named file
- * Supports: Android, iOS
- * @param {String} suiteName suite name
- * @returns {AppPreferences} AppPreferences object, bound to that suite
- */
- AppPreferences.prototype.iosSuite =
- AppPreferences.prototype.suite =
- function (suiteName) {
- var appPrefs = new AppPreferences ({
- iosSuiteName: suiteName, // deprecated, remove when ios code is ready
- suiteName: suiteName,
- });
- return appPrefs;
- }
- /**
- * Return cloud synchronized configuration context
- * Currently supports Windows and iOS/macOS
- * @returns {AppPreferences} AppPreferences object, bound to that suite
- */
- AppPreferences.prototype.cloudSync = function () {
- var appPrefs = new AppPreferences ({cloudSync: true});
- return appPrefs;
- }
- /**
- * Return default configuration context
- * Currently supports Windows and iOS/macOS
- * @returns {AppPreferences} AppPreferences object, bound to that suite
- */
- AppPreferences.prototype.defaults = function () {
- var appPrefs = new AppPreferences ();
- return appPrefs;
- }
- // WIP: functions to bind selected preferences to the form
- function setFormFields (formEl, fieldsData) {
- for (var i = 0; i < formEl.elements.length; i ++) {
- var formField = formEl.elements[i];
- if (!(formField.name in fieldsData)) {
- continue;
- }
- // TODO: multiple checkboxes value for one form field
- if (formField.type === 'radio' || formField.type === 'checkbox') {
- if (
- formField.value === fieldsData[formField.name]
- || formField.value === fieldsData[formField.name].toString()
- ) {
- formField.checked = true;
- }
- } else {
- formField.value = fieldsData[formField.name];
- }
- }
- }
- function bindFormToData (formEl, formData) {
- [].slice.apply (formEl.elements).forEach (function (el) {
- if (el.type.match (/^(?:radio|checkbox)$/)) {
- el.addEventListener ('change', getFormFields.bind (window, formEl, formData), false);
- } else {
- el.addEventListener ('input', getFormFields.bind (window, formEl, formData), false);
- }
- });
- }
- function getFormFields (formEl, formData) {
- formData = formData || {};
- for (var k in formData) {
- delete formData[k];
- }
- for (var i = 0; i < formEl.elements.length; i ++) {
- var formField = formEl.elements[i];
- var checkedType = formField.type.match (/^(?:radio|checkbox)$/);
- if ((checkedType && formField.checked) || !checkedType) {
- formData[formField.name] = formField.value;
- }
- }
- // console.log (formData);
- return formData;
- }
- if (typeof module !== "undefined") {
- module.exports = new AppPreferences();
- }
|