common.js 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. // Polyfill start
  2. function polyfill(obj, name, value) {
  3. if (!obj[name]) Object.defineProperty(obj, name, {
  4. value: value,
  5. });
  6. }
  7. polyfill(Object, 'assign', function () {
  8. var obj = arguments[0];
  9. for (var i = 1; i < arguments.length; i ++) {
  10. var arg = arguments[i];
  11. arg && Object.keys(arg).forEach(function (key) {
  12. obj[key] = arg[key];
  13. });
  14. }
  15. return obj;
  16. });
  17. polyfill(String.prototype, 'startsWith', function (str) {
  18. return this.slice(0, str.length) === str;
  19. });
  20. polyfill(String.prototype, 'endsWith', function (str) {
  21. return this.slice(-str.length) === str;
  22. });
  23. polyfill(Array.prototype, 'findIndex', function (predicate) {
  24. var length = this.length;
  25. for (var i = 0; i < length; i ++) {
  26. var item = this[i];
  27. if (predicate(item, i, this)) return i;
  28. }
  29. return -1;
  30. });
  31. polyfill(Array.prototype, 'find', function (predicate) {
  32. return this[this.findIndex(predicate)];
  33. });
  34. // Polyfill end
  35. var _ = exports;
  36. _.i18n = function (name, args) {
  37. return browser.i18n.getMessage(name, args) || name;
  38. };
  39. _.defaultImage = '/public/images/icon128.png';
  40. function normalizeKeys(key) {
  41. if (!key) key = [];
  42. if (!Array.isArray(key)) key = key.toString().split('.');
  43. return key;
  44. }
  45. _.normalizeKeys = normalizeKeys;
  46. _.object = function () {
  47. function get(obj, key, def) {
  48. var keys = normalizeKeys(key);
  49. for (var i = 0, len = keys.length; i < len; i ++) {
  50. key = keys[i];
  51. if (obj && typeof obj === 'object' && (key in obj)) obj = obj[key];
  52. else return def;
  53. }
  54. return obj;
  55. }
  56. function set(obj, key, val) {
  57. var keys = normalizeKeys(key);
  58. if (!keys.length) return val;
  59. var sub = obj = obj || {};
  60. for (var i = 0, len = keys.length - 1; i < len; i ++) {
  61. key = keys[i];
  62. sub = sub[key] = sub[key] || {};
  63. }
  64. var lastKey = keys[keys.length - 1];
  65. if (val == null) {
  66. delete sub[lastKey];
  67. } else {
  68. sub[lastKey] = val;
  69. }
  70. return obj;
  71. }
  72. return {
  73. get: get,
  74. set: set,
  75. };
  76. }();
  77. _.initHooks = function () {
  78. var hooks = [];
  79. function fire(data) {
  80. hooks.slice().forEach(function (hook) {
  81. hook(data);
  82. });
  83. }
  84. function hook(callback) {
  85. hooks.push(callback);
  86. return function () {
  87. var i = hooks.indexOf(callback);
  88. ~i && hooks.splice(i, 1);
  89. };
  90. }
  91. return {
  92. hook: hook,
  93. fire: fire,
  94. };
  95. };
  96. _.initOptions = function () {
  97. var options = {};
  98. var hooks = _.initHooks();
  99. var ready = _.sendMessage({cmd: 'GetAllOptions'})
  100. .then(function (data) {
  101. options = data;
  102. data && hooks.fire(data);
  103. });
  104. function getOption(key, def) {
  105. var keys = normalizeKeys(key);
  106. return _.object.get(options, keys, def);
  107. }
  108. function setOption(key, value) {
  109. _.sendMessage({
  110. cmd: 'SetOptions',
  111. data: {
  112. key: key,
  113. value: value,
  114. },
  115. });
  116. }
  117. function updateOptions(data) {
  118. Object.keys(data).forEach(function (key) {
  119. _.object.set(options, key, data[key]);
  120. });
  121. hooks.fire(data);
  122. }
  123. _.options = {
  124. get: getOption,
  125. set: setOption,
  126. update: updateOptions,
  127. hook: hooks.hook,
  128. ready: ready,
  129. };
  130. };
  131. _.sendMessage = function (data) {
  132. return browser.runtime.sendMessage(data)
  133. .catch(function (err) {
  134. console.error(err);
  135. });
  136. };
  137. _.debounce = function (func, time) {
  138. function run(thisObj, args) {
  139. timer = null;
  140. func.apply(thisObj, args);
  141. }
  142. var timer;
  143. return function () {
  144. timer && clearTimeout(timer);
  145. var args = [];
  146. for (var i = 0; i < arguments.length; i++) args.push(arguments[i]);
  147. timer = setTimeout(run, time, this, args);
  148. };
  149. };
  150. _.noop = function () {};
  151. _.zfill = function (num, length) {
  152. num = num.toString();
  153. while (num.length < length) num = '0' + num;
  154. return num;
  155. };
  156. _.getUniqId = function () {
  157. return Date.now().toString(36) + Math.random().toString(36).slice(2, 6);
  158. };
  159. /**
  160. * Get locale attributes such as `@name:zh-CN`
  161. */
  162. _.getLocaleString = function (meta, key) {
  163. var lang = navigator.languages.find(function (lang) {
  164. return (key + ':' + lang) in meta;
  165. });
  166. if (lang) key += ':' + lang;
  167. return meta[key] || '';
  168. };