script.js 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. define('views/Script', function (require, _exports, module) {
  2. var store = require('utils').store;
  3. var cache = require('cache');
  4. var DEFAULT_ICON = '/images/icon48.png';
  5. module.exports = {
  6. props: ['script'],
  7. template: cache.get('/options/components/script.html'),
  8. data: function () {
  9. return {
  10. safeIcon: DEFAULT_ICON,
  11. };
  12. },
  13. computed: {
  14. canUpdate: function () {
  15. var script = this.script;
  16. return script.update && (
  17. script.custom.updateURL ||
  18. script.meta.updateURL ||
  19. script.custom.downloadURL ||
  20. script.meta.downloadURL ||
  21. script.custom.lastInstallURL
  22. );
  23. },
  24. homepageURL: function () {
  25. var script = this.script;
  26. return script.custom.homepageURL || script.meta.homepageURL || script.meta.homepage;
  27. },
  28. author: function () {
  29. var text = this.script.meta.author;
  30. if (!text) return;
  31. var matches = text.match(/^(.*?)\s<(\S*?@\S*?)>$/);
  32. return {
  33. email: matches && matches[2],
  34. name: matches ? matches[1] : text,
  35. };
  36. },
  37. labelEnable: function () {
  38. return this.script.enabled ? _.i18n('buttonDisable') : _.i18n('buttonEnable');
  39. },
  40. },
  41. ready: function () {
  42. var _this = this;
  43. _this.$el.addEventListener('dragstart', _this.onDragStart.bind(_this), false);
  44. var icon = _this.script.meta.icon;
  45. if (icon && icon !== _this.safeIcon) {
  46. _this.loadImage(icon)
  47. .then(function (url) {
  48. _this.safeIcon = url;
  49. }, function () {
  50. _this.safeIcon = DEFAULT_ICON;
  51. });
  52. }
  53. },
  54. methods: {
  55. getLocaleString: function (key) {
  56. return _.getLocaleString(this.script.meta, key);
  57. },
  58. loadImage: function () {
  59. var images = {};
  60. return function (url) {
  61. if (!url) return Promise.reject();
  62. var promise = images[url];
  63. if (!promise) {
  64. var cache = store.cache[url];
  65. promise = cache ? Promise.resolve(cache)
  66. : new Promise(function (resolve, reject) {
  67. var img = new Image;
  68. img.onload = function () {
  69. resolve(url);
  70. };
  71. img.onerror = function () {
  72. reject(url);
  73. };
  74. img.src = url;
  75. });
  76. images[url] = promise;
  77. }
  78. return promise;
  79. };
  80. }(),
  81. onEdit: function () {
  82. var _this = this;
  83. _this.$dispatch('EditScript', _this.script.id);
  84. },
  85. onRemove: function () {
  86. var _this = this;
  87. _.sendMessage({
  88. cmd: 'RemoveScript',
  89. data: _this.script.id,
  90. });
  91. },
  92. onEnable: function () {
  93. var _this = this;
  94. _.sendMessage({
  95. cmd: 'UpdateScriptInfo',
  96. data: {
  97. id: _this.script.id,
  98. enabled: _this.script.enabled ? 0 : 1,
  99. },
  100. });
  101. },
  102. onUpdate: function () {
  103. _.sendMessage({
  104. cmd: 'CheckUpdate',
  105. data: this.script.id,
  106. });
  107. },
  108. onDragStart: function (e) {
  109. var _this = this;
  110. new DND(e, function (data) {
  111. _this.$dispatch('MoveScript', data);
  112. });
  113. },
  114. },
  115. };
  116. function DND(e, cb) {
  117. var _this = this;
  118. _this.mousemove = _this.mousemove.bind(_this);
  119. _this.mouseup = _this.mouseup.bind(_this);
  120. if (e) {
  121. e.preventDefault();
  122. _this.start(e);
  123. }
  124. _this.onDrop = cb;
  125. }
  126. DND.prototype.start = function (e) {
  127. var _this = this;
  128. var dragging = _this.dragging = {};
  129. var el = dragging.el = e.currentTarget;
  130. var parent = el.parentNode;
  131. var rect = el.getBoundingClientRect();
  132. dragging.offset = {
  133. x: e.clientX - rect.left,
  134. y: e.clientY - rect.top,
  135. };
  136. var next = el.nextElementSibling;
  137. dragging.delta = (next ? next.getBoundingClientRect().top : parent.offsetHeight) - rect.top;
  138. dragging.lastIndex = dragging.index = [].indexOf.call(parent.children, el);
  139. dragging.elements = [].filter.call(parent.children, function (el) {
  140. return el !== dragging.el;
  141. });
  142. var dragged = dragging.dragged = el.cloneNode(true);
  143. dragged.classList.add('dragging');
  144. dragged.style.left = rect.left + 'px';
  145. dragged.style.top = rect.top + 'px';
  146. dragged.style.width = rect.width + 'px';
  147. parent.appendChild(dragged);
  148. el.classList.add('dragging-placeholder');
  149. document.addEventListener('mousemove', _this.mousemove, false);
  150. document.addEventListener('mouseup', _this.mouseup, false);
  151. };
  152. DND.prototype.mousemove = function (e) {
  153. var _this = this;
  154. var dragging = _this.dragging;
  155. var dragged = dragging.dragged;
  156. dragged.style.left = e.clientX - dragging.offset.x + 'px';
  157. dragged.style.top = e.clientY - dragging.offset.y + 'px';
  158. var hoveredIndex = dragging.elements.findIndex(function (el) {
  159. if (!el) return;
  160. if (el.classList.contains('dragging-moving')) return;
  161. var rect = el.getBoundingClientRect();
  162. var pad = 10;
  163. return (
  164. e.clientX >= rect.left + pad
  165. && e.clientX <= rect.left + rect.width - pad
  166. && e.clientY >= rect.top + pad
  167. && e.clientY <= rect.top + rect.height - pad
  168. );
  169. });
  170. if (~hoveredIndex) {
  171. var hoveredEl = dragging.elements[hoveredIndex];
  172. var lastIndex = dragging.lastIndex;
  173. var isDown = hoveredIndex >= lastIndex;
  174. var el = dragging.el;
  175. var delta = dragging.delta;
  176. if (isDown) {
  177. hoveredIndex ++;
  178. hoveredEl.parentNode.insertBefore(el, hoveredEl.nextElementSibling);
  179. } else {
  180. delta = -delta;
  181. hoveredEl.parentNode.insertBefore(el, hoveredEl);
  182. }
  183. dragging.lastIndex = hoveredIndex;
  184. _this.animate(dragging.elements.slice(
  185. isDown ? lastIndex : hoveredIndex,
  186. isDown ? hoveredIndex : lastIndex
  187. ), delta);
  188. }
  189. _this.checkScroll(e.clientY);
  190. };
  191. DND.prototype.animate = function (elements, delta) {
  192. function endAnimation(e) {
  193. e.target.classList.remove('dragging-moving');
  194. e.target.removeEventListener('transitionend', endAnimation, false);
  195. }
  196. elements.forEach(function (el) {
  197. if (!el) return;
  198. el.classList.add('dragging-moving');
  199. el.style.transition = 'none';
  200. el.style.transform = 'translateY(' + delta + 'px)';
  201. el.addEventListener('transitionend', endAnimation, false);
  202. setTimeout(function () {
  203. el.style.transition = '';
  204. el.style.transform = '';
  205. });
  206. });
  207. };
  208. DND.prototype.mouseup = function () {
  209. var _this = this;
  210. document.removeEventListener('mousemove', _this.mousemove, false);
  211. document.removeEventListener('mouseup', _this.mouseup, false);
  212. var dragging = _this.dragging;
  213. dragging.dragged.remove();
  214. dragging.el.classList.remove('dragging-placeholder');
  215. _this.dragging = null;
  216. _this.onDrop && _this.onDrop({
  217. from: dragging.index,
  218. to: dragging.lastIndex,
  219. });
  220. };
  221. DND.prototype.checkScroll = function (y) {
  222. var dragging = this.dragging;
  223. var scrollThreshold = 10;
  224. dragging.scroll = 0;
  225. var offset = dragging.el.parentNode.getBoundingClientRect();
  226. var delta = (y - (offset.bottom - scrollThreshold)) / scrollThreshold;
  227. if (delta > 0) {
  228. dragging.scroll = 1 + Math.min(~~ (delta * 5), 10);
  229. } else {
  230. delta = (offset.top + scrollThreshold - y) / scrollThreshold;
  231. if (delta > 0) dragging.scroll = -1 - Math.min(~~ (delta * 5), 10);
  232. }
  233. if (dragging.scroll) this.scrollParent();
  234. };
  235. DND.prototype.scrollParent = function () {
  236. function scroll() {
  237. var dragging = _this.dragging;
  238. if (dragging) {
  239. if (dragging.scroll) {
  240. dragging.el.parentNode.scrollTop += dragging.scroll;
  241. setTimeout(scroll, 32);
  242. } else dragging.scrolling = false;
  243. }
  244. }
  245. var _this = this;
  246. if (!_this.dragging.scrolling) {
  247. _this.dragging.scrolling = true;
  248. scroll();
  249. }
  250. };
  251. });