UNPKG

recent-searches

Version:

A JavaScript module to help anyone easily build recent searches functionality into their search.

367 lines (299 loc) 12.1 kB
(function webpackUniversalModuleDefinition(root, factory) { if(typeof exports === 'object' && typeof module === 'object') module.exports = factory(); else if(typeof define === 'function' && define.amd) define("RecentSearches", [], factory); else if(typeof exports === 'object') exports["RecentSearches"] = factory(); else root["RecentSearches"] = factory(); })((typeof self !== 'undefined' ? self : this), function() { return /******/ (function(modules) { // webpackBootstrap /******/ // The module cache /******/ var installedModules = {}; /******/ /******/ // The require function /******/ function __webpack_require__(moduleId) { /******/ /******/ // Check if module is in cache /******/ if(installedModules[moduleId]) { /******/ return installedModules[moduleId].exports; /******/ } /******/ // Create a new module (and put it into the cache) /******/ var module = installedModules[moduleId] = { /******/ i: moduleId, /******/ l: false, /******/ exports: {} /******/ }; /******/ /******/ // Execute the module function /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); /******/ /******/ // Flag the module as loaded /******/ module.l = true; /******/ /******/ // Return the exports of the module /******/ return module.exports; /******/ } /******/ /******/ /******/ // expose the modules object (__webpack_modules__) /******/ __webpack_require__.m = modules; /******/ /******/ // expose the module cache /******/ __webpack_require__.c = installedModules; /******/ /******/ // define getter function for harmony exports /******/ __webpack_require__.d = function(exports, name, getter) { /******/ if(!__webpack_require__.o(exports, name)) { /******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); /******/ } /******/ }; /******/ /******/ // define __esModule on exports /******/ __webpack_require__.r = function(exports) { /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); /******/ } /******/ Object.defineProperty(exports, '__esModule', { value: true }); /******/ }; /******/ /******/ // create a fake namespace object /******/ // mode & 1: value is a module id, require it /******/ // mode & 2: merge all properties of value into the ns /******/ // mode & 4: return value when already ns object /******/ // mode & 8|1: behave like require /******/ __webpack_require__.t = function(value, mode) { /******/ if(mode & 1) value = __webpack_require__(value); /******/ if(mode & 8) return value; /******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; /******/ var ns = Object.create(null); /******/ __webpack_require__.r(ns); /******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); /******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); /******/ return ns; /******/ }; /******/ /******/ // getDefaultExport function for compatibility with non-harmony modules /******/ __webpack_require__.n = function(module) { /******/ var getter = module && module.__esModule ? /******/ function getDefault() { return module['default']; } : /******/ function getModuleExports() { return module; }; /******/ __webpack_require__.d(getter, 'a', getter); /******/ return getter; /******/ }; /******/ /******/ // Object.prototype.hasOwnProperty.call /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; /******/ /******/ // __webpack_public_path__ /******/ __webpack_require__.p = ""; /******/ /******/ /******/ // Load entry module and return exports /******/ return __webpack_require__(__webpack_require__.s = 0); /******/ }) /************************************************************************/ /******/ ([ /* 0 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); // CONCATENATED MODULE: ./lib/MemoryStorage.ts function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } var MemoryStorage_MemoryStorage = function MemoryStorage(config) { var _this = this; _classCallCheck(this, MemoryStorage); _defineProperty(this, "DATA", {}); _defineProperty(this, "KEY", void 0); _defineProperty(this, "DEFAULT_VALUE", void 0); _defineProperty(this, "getItem", function () { return _this.DATA[_this.KEY] || _this.DEFAULT_VALUE; }); _defineProperty(this, "setItem", function (data) { _this.DATA[_this.KEY] = data; return true; }); var key = config.key, defaultValue = config.defaultValue; this.DATA = {}; this.KEY = key || DEFAULT_STORAGE_KEY; this.DEFAULT_VALUE = defaultValue; }; /* harmony default export */ var lib_MemoryStorage = (MemoryStorage_MemoryStorage); // CONCATENATED MODULE: ./lib/SafeLocalStorage.ts function SafeLocalStorage_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function SafeLocalStorage_defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } var DEFAULT_STORAGE_KEY = "__RECENT_SEARCHES__"; var isLocalStorageSupported = function isLocalStorageSupported() { var key = "__TEST__KEY__"; try { localStorage.setItem(key, ""); localStorage.removeItem(key); return true; } catch (error) { return false; } }; var safeDataParse = function safeDataParse(data, defaultValue) { if (!data) { return defaultValue; } try { return JSON.parse(data); } catch (e) { return defaultValue; } }; var SafeLocalStorage = function SafeLocalStorage(config) { var _this = this; SafeLocalStorage_classCallCheck(this, SafeLocalStorage); SafeLocalStorage_defineProperty(this, "KEY", void 0); SafeLocalStorage_defineProperty(this, "DEFAULT_VALUE", void 0); SafeLocalStorage_defineProperty(this, "getItem", function () { var data = localStorage.getItem(_this.KEY); return safeDataParse(data, _this.DEFAULT_VALUE); }); SafeLocalStorage_defineProperty(this, "setItem", function (items) { try { localStorage.setItem(_this.KEY, JSON.stringify(items)); return true; } catch (e) { return false; } }); var key = config.key, defaultValue = config.defaultValue; this.KEY = key || DEFAULT_STORAGE_KEY; this.DEFAULT_VALUE = defaultValue; }; var SafeLocalStorage_NewSafeLocalStorage = function NewSafeLocalStorage(config) { if (!isLocalStorageSupported()) { return new lib_MemoryStorage(config); } return new SafeLocalStorage(config); }; /* harmony default export */ var lib_SafeLocalStorage = (SafeLocalStorage_NewSafeLocalStorage); // CONCATENATED MODULE: ./lib/utils/score.ts var computeMatchScore = function computeMatchScore(search, query, rankBy, ttl) { var normalizedQuery = String(query); switch (rankBy) { case "PROXIMITY": return search.query.indexOf(normalizedQuery); case "TIME": return Math.log10(new Date().getTime() - search.timestamp); default: var matchDistance = search.query.indexOf(normalizedQuery); var timeDelta = Math.log2((new Date().getTime() - search.timestamp) / ttl + 1); var proximity = Math.log2(matchDistance + 1) || 1; if (matchDistance === -1) { return matchDistance; } return (0.01 + 0.49 * proximity + 0.49 * timeDelta) / 1; } }; /* harmony default export */ var utils_score = (computeMatchScore); // CONCATENATED MODULE: ./lib/utils/string.ts var isBlank = function isBlank() { var str = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ""; return /^\s*$/.test(str); }; var isValidQuery = function isValidQuery(query) { return typeof query === "string" && !isBlank(query) || typeof query === "number"; }; /* harmony default export */ var string = (isValidQuery); // CONCATENATED MODULE: ./lib/index.ts /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "RecentSearches", function() { return lib_RecentSearches; }); function lib_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function lib_defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } var lib_RecentSearches = function RecentSearches() { var _this = this; var config = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; lib_classCallCheck(this, RecentSearches); lib_defineProperty(this, "TTL", void 0); lib_defineProperty(this, "LIMIT", void 0); lib_defineProperty(this, "STORAGE", void 0); lib_defineProperty(this, "RANKING", void 0); lib_defineProperty(this, "RECENT_SEARCHES", []); lib_defineProperty(this, "getRecentSearches", function (query) { if (!string(query)) { return _this.RECENT_SEARCHES; } var matchedSearches = _this.RECENT_SEARCHES.map(function (search) { var score = utils_score(search, query, _this.RANKING, _this.TTL); return { data: search.data, query: search.query, score: score, timestamp: search.timestamp }; }).filter(_this.filterScoredResults).sort(_this.sortScoredResults).map(function (search) { return { data: search.data, query: search.query, timestamp: search.timestamp }; }); return matchedSearches; }); lib_defineProperty(this, "setRecentSearch", function (query, data) { if (!string(query)) { return _this.RECENT_SEARCHES; } var search = { data: data, query: String(query), timestamp: new Date().getTime() }; var existingQueryIndex = _this.RECENT_SEARCHES.findIndex(function (searchEntry) { return searchEntry.query === query; }); if (existingQueryIndex > -1) { _this.RECENT_SEARCHES.splice(existingQueryIndex, 1); } _this.RECENT_SEARCHES.unshift(search); _this.RECENT_SEARCHES = _this.RECENT_SEARCHES.slice(0, _this.LIMIT); _this.STORAGE.setItem(_this.RECENT_SEARCHES); return _this.RECENT_SEARCHES; }); lib_defineProperty(this, "filterScoredResults", function (search) { if (_this.RANKING === "TIME") { return true; } return search.score > -1; }); lib_defineProperty(this, "sortScoredResults", function (a, b) { return a.score - b.score; }); lib_defineProperty(this, "initializeStorageData", function () { var currentTimestamp = new Date().getTime(); var items = _this.STORAGE.getItem().filter(function (search) { return search.timestamp + _this.TTL >= currentTimestamp; }).slice(0, _this.LIMIT); _this.STORAGE.setItem(items); _this.RECENT_SEARCHES = items; return items; }); this.TTL = config.ttl || 1000 * 60 * 60 * 24; this.LIMIT = config.limit || 50; this.STORAGE = lib_SafeLocalStorage({ defaultValue: [], key: config.namespace }); this.RECENT_SEARCHES = this.initializeStorageData(); this.RANKING = config.ranking || "PROXIMITY_AND_TIME"; } /** * Retrieve recent searches for a given query. * If no query is passed, returns all recent searches * * @param {string} query? * @returns Search[] */ ; /* harmony default export */ var lib = __webpack_exports__["default"] = (lib_RecentSearches); /***/ }) /******/ ]); }); //# sourceMappingURL=index.js.map