Advertisement
stuppid_bot

Untitled

Nov 16th, 2016
218
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // Форматирование:
  2. // * два символа окончания строки до и после объявления фунций за исключением
  3. //   вложенных, анонимных, стрелочных функций и методов класса;
  4. // * два символа окончания строки до и после объявления класса
  5. // Переменную undefined можно переопределить
  6. const UNDEFINED = void 0;
  7.  
  8. // Имеет ли объект собственное свойство?
  9. const hasOwn = (prop, obj) => Object.prototype.hasOwnProperty.call(obj, prop);
  10. // http://bonsaiden.github.io/JavaScript-Garden/
  11. // Вохвращает тип объекта
  12. // getType(function () {}) --> "Function"
  13. const getType = obj =>
  14.   Object.prototype.toString.call(obj).slice(8, -1).toLowerCase();
  15. // Проверка типа объекта
  16. // isType('string', 'foo') --> true
  17. // isType('string', new String('foo')) --> true
  18. // Необходимость в этой функции появилась из-за щсобенностей оператора typeof
  19. // typeof 'foo' --> "string"
  20. // typeof new String('foo') --> "object"
  21. const isType = (type, obj) => type === getType(obj);
  22. const isFunction = obj => typeof obj === 'function';
  23. const isObject = obj => isType('object', obj);
  24. const isArray = Array.isArray;
  25. const isNumber = obj => isType('number', obj);
  26. const isString = obj => isType('string', obj);
  27. const isUndefined = obj => obj === UNDEFINED;
  28. const isNull = obj => obj === null;
  29. const isBool = obj => isType('boolean', obj);
  30. // http://jsfiddle.net/jeffshaver/DdEUW/
  31. // https://github.com/icelab/mustache-trimmer-rails/blob/master/lib/mustache/javascript_generator.rb
  32. // isEmpty('') --> true
  33. // isEmpty(' ') --> false
  34. // isEmpty([]) --> true
  35. // isEmpty({}) --> true
  36. // isEmpty({foo: true}) --> false
  37. const isEmpty = obj =>
  38.   !obj || obj.length === 0 || !Object.getOwnPropertyNames(obj).length;
  39. const isEven = x => x % 2 === 0;
  40. const isOdd = x => x % 2 === 1;
  41.  
  42. // Array functions
  43.  
  44. // Многие функции позаимстованы отсюда:
  45. // https://github.com/bendc/frontend-guidelines
  46. const toArray = (() =>
  47.   Array.from ? Array.from : obj => [].slice.call(obj)
  48. )();
  49.  
  50. const merge = (...sources) => Object.assign({}, ...sources);
  51. const sum = arr => arr.reduce((x, y) => x + y);
  52.  
  53. const contains = (() =>
  54.   Array.prototype.includes
  55.     ? (arr, value) => arr.includes(value)
  56.     : (arr, value) => arr.some(el => el === value)
  57. )();
  58.  
  59. const first = arr => arr[0];
  60. const last = arr => arr[arr.length - 1];
  61. // compact(['foo', 0]) --> ["foo"]
  62. const compact = arr => arr.filter(el => el);
  63. const unique = arr => [...new Set(arr)];
  64. // https://searchcode.com/codesearch/view/90754671/
  65. const union = (...arrs) => unique([].concat(...arrs));
  66. // Получаем случайный элемент массива
  67. const choice = arr => arr[Math.floor(Math.random() * arr.length)];
  68.  
  69.  
  70. // Слегка измененный алгоритм отсюда
  71. // http://stackoverflow.com/a/6274398/2240578
  72. function shuffle(arr) {
  73.   let i = arr.length;
  74.   while (i) {
  75.     const r = Math.floor(Math.random() * i--);
  76.     [arr[i], arr[r]] = [arr[r], arr[i]];
  77.   }
  78.   return arr;
  79. }
  80.  
  81.  
  82. // Украдено с Вконтакте
  83. // ~~rand(0, 10) --> вернет целое
  84. const rand = (min, max) => Math.random() * (max - min + 1) + min;
  85.  
  86. // String functions
  87.  
  88. // ucfirst('foo') --> "Foo"
  89. const ucfirst = str => str.charAt(0).toUpperCase() + str.slice(1);
  90. // splitLines('foo\r\nbar\nbaz') --> ["foo", "bar", "baz"]
  91. const splitLines = str => str.split(/\r?\n/g);
  92.  
  93.  
  94. // TODO: Убрать пробелы перед переводом строки
  95. // http://php.net/manual/ru/function.wordwrap.php
  96. /**
  97.   * @param {string} text
  98.   * @param {number} width
  99.   * @return {string}
  100.   */
  101. function wordWrap(text, width = 80) {
  102.   if (!isString(text)) {
  103.     throw new TypeError('text must be a string');
  104.   }
  105.   if (!isNumber(width)) {
  106.     throw new TypeError('width must be a number');
  107.   }
  108.   if (width <= 0) {
  109.     throw new Error('width must be greater than zero');
  110.   }
  111.   const lines = text.split('\n');
  112.   const out = [];
  113.   const re = new RegExp(`(\\s{1,${width}})|(\\S{1,${width}})`, 'g');
  114.   for (const line of lines) {
  115.     let buf = '';
  116.     let len = 0;
  117.     while (true) {
  118.       const matches = re.exec(line);
  119.       if (matches === null) {
  120.         break;
  121.       }
  122.       const [ , whitespace, word] = matches;
  123.       if (isUndefined(word)) {
  124.         if (whitespace.length + len <= width) {
  125.           buf += whitespace;
  126.           len += whitespace.length;
  127.         } else {
  128.           // Пробелы в конец не добавляем
  129.           buf += '\n';
  130.           len = 0;
  131.         }
  132.       } else {
  133.         if (word.length + len <= width) {
  134.           buf += word;
  135.           len += word.length;
  136.         } else {
  137.           buf += `\n${word}`;
  138.           len = word.length;
  139.         }
  140.       }
  141.     }
  142.     out.push(buf);
  143.   }
  144.   return out.sjoin('\n');
  145. }
  146.  
  147.  
  148. // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions
  149. const escapeRegExp = str => str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
  150.  
  151. const escapeHtml = unsafe =>
  152.   unsafe.replace(/&/g, '&amp;')
  153.     .replace(/</g, '&lt;')
  154.     .replace(/>/g, '&gt;')
  155.     .replace(/"/g, '&quot;')
  156.     .replace(/'/g, '&#39;');
  157.  
  158. // Работа с цветами
  159.  
  160. function rgbHex(red, green, blue) {
  161.   const hex = (((255 & red) << 16) + ((255 & green) << 8) + (blue & 255))
  162.     .toString(16);
  163.   return `#${'000000'.slice(hex.length)}${hex}`;
  164. }
  165.  
  166.  
  167. function hexRgb(hex) {
  168.   const matches = /^#?([a-fA-F0-9]{3}|[a-fA-F0-9]{6})$/.exec(hex);
  169.   if (!matches) {
  170.     return false;
  171.   }
  172.   hex = matches[1];
  173.   const val = parseInt(hex, 16);
  174.   return (hex.length === 3)
  175.     ? [val >> 8, val >> 4 & 15, val & 15]
  176.     : [val >> 16, val >> 8 & 255, val & 255];
  177. }
  178.  
  179.  
  180. // Смешиваем два цвета
  181. // mixHex('#000000', '#fff') --> "#808080"
  182. // mixHex('f00', '#00ff00') --> "#808000"
  183. // mixHex('ff00ff', '#ff00ff') --> "#ff00ff"
  184. // mixHex('#ff0000', '#0000ff') --> "#800080"
  185. // mixHex('777', '#999') --> "#888888"
  186. // mixHex('#111222', '222444') --> "#1a1b33"
  187. // mixHex('abcdef', '#fedcba') --> "#d5d5d5"
  188. // mixHex('#000', '#000222') --> "#000111"
  189. function mixHex(a, b) {
  190.   const c1 = hexRgb(a);
  191.   const c2 = hexRgb(b);
  192.   if (c1 === false || c2 === false) {
  193.     return false;
  194.   }
  195.   return rgbHex(
  196.     Math.round((c1[0] + c2[0]) / 2),
  197.     Math.round((c1[1] + c2[1]) / 2),
  198.     Math.round((c1[2] + c2[2]) / 2)
  199.   );
  200. }
  201.  
  202. // Математика
  203.  
  204. const deg2rad = angle => angle * Math.PI / 180;
  205.  
  206. // Пользовательские события
  207.  
  208. class EventEmitter {
  209.   constructor() {
  210.     this.listeners = {};
  211.     // Алиасы
  212.     this.on = this.addListener;
  213.     this.off = this.removeListener;
  214.   }
  215.  
  216.   addListener(type, listener) {
  217.     if (!isFunction(listener)) {
  218.       throw new TypeError('listener must be a function');
  219.     }
  220.     (this.hasListeners(type)
  221.       ? this.listeners[type]
  222.       : this.listeners[type] = []).push(listener);
  223.     return this;
  224.   }
  225.  
  226.   removeListener(type, listener) {
  227.     if (this.hasListeners(type)) {
  228.       const listeners = this.listeners[type];
  229.       while (true) {
  230.         const index = listeners.indexOf(listener);
  231.         if (index < 0) {
  232.           break;
  233.         }
  234.         listeners.splice(index, 1);
  235.       }
  236.       if (!listeners.length) {
  237.         delete this.listeners[type];
  238.       }
  239.     }
  240.     return this;
  241.   }
  242.  
  243.   removeAllListeners(type) {
  244.     if (arguments.length) {
  245.       if (this.hasListeners(type)) {
  246.         delete this.listeners[type];
  247.       }
  248.     } else {
  249.       this.listeners = {};
  250.     }
  251.     return this;
  252.   }
  253.  
  254.   emit(type, ...args) {
  255.     if (this.hasListeners(type)) {
  256.       for (const listener of this.listeners[type]) {
  257.         listener.apply(null, args);
  258.       }
  259.     }
  260.     return this;
  261.   }
  262.  
  263.   hasListeners(type) {
  264.     return hasOwn(type, this.listeners);
  265.   }
  266. }
  267.  
  268.  
  269. function testEventEmitter() {
  270.   function hello(name) {
  271.     return console.log(`Hello ${name}`);
  272.   }
  273.  
  274.   const emitter = new EventEmitter;
  275.   emitter.on('greeting', hello);
  276.   emitter.emit('greeting', 'World');
  277.   emitter.off('greeting', hello);
  278.   // Nothing will happen
  279.   emitter.emit('greeting', '...');
  280. }
  281.  
  282. // DOM
  283.  
  284. const gid = id => document.getElementById(id);
  285.  
  286. // https://developer.mozilla.org/en-US/Add-ons/Code_snippets/QuerySelector
  287. const $$ = (selector, el) =>
  288.   // NodeList имеет лишь метод item и свойство length, свойство предоставляет
  289.   // несравнимо больший функционал
  290.   toArray((el || document).querySelectorAll(selector));
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement