Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // Форматирование:
- // * два символа окончания строки до и после объявления фунций за исключением
- // вложенных, анонимных, стрелочных функций и методов класса;
- // * два символа окончания строки до и после объявления класса
- // Переменную undefined можно переопределить
- const UNDEFINED = void 0;
- // Имеет ли объект собственное свойство?
- const hasOwn = (prop, obj) => Object.prototype.hasOwnProperty.call(obj, prop);
- // http://bonsaiden.github.io/JavaScript-Garden/
- // Вохвращает тип объекта
- // getType(function () {}) --> "Function"
- const getType = obj =>
- Object.prototype.toString.call(obj).slice(8, -1).toLowerCase();
- // Проверка типа объекта
- // isType('string', 'foo') --> true
- // isType('string', new String('foo')) --> true
- // Необходимость в этой функции появилась из-за щсобенностей оператора typeof
- // typeof 'foo' --> "string"
- // typeof new String('foo') --> "object"
- const isType = (type, obj) => type === getType(obj);
- const isFunction = obj => typeof obj === 'function';
- const isObject = obj => isType('object', obj);
- const isArray = Array.isArray;
- const isNumber = obj => isType('number', obj);
- const isString = obj => isType('string', obj);
- const isUndefined = obj => obj === UNDEFINED;
- const isNull = obj => obj === null;
- const isBool = obj => isType('boolean', obj);
- // http://jsfiddle.net/jeffshaver/DdEUW/
- // https://github.com/icelab/mustache-trimmer-rails/blob/master/lib/mustache/javascript_generator.rb
- // isEmpty('') --> true
- // isEmpty(' ') --> false
- // isEmpty([]) --> true
- // isEmpty({}) --> true
- // isEmpty({foo: true}) --> false
- const isEmpty = obj =>
- !obj || obj.length === 0 || !Object.getOwnPropertyNames(obj).length;
- const isEven = x => x % 2 === 0;
- const isOdd = x => x % 2 === 1;
- // Array functions
- // Многие функции позаимстованы отсюда:
- // https://github.com/bendc/frontend-guidelines
- const toArray = (() =>
- Array.from ? Array.from : obj => [].slice.call(obj)
- )();
- const merge = (...sources) => Object.assign({}, ...sources);
- const sum = arr => arr.reduce((x, y) => x + y);
- const contains = (() =>
- Array.prototype.includes
- ? (arr, value) => arr.includes(value)
- : (arr, value) => arr.some(el => el === value)
- )();
- const first = arr => arr[0];
- const last = arr => arr[arr.length - 1];
- // compact(['foo', 0]) --> ["foo"]
- const compact = arr => arr.filter(el => el);
- const unique = arr => [...new Set(arr)];
- // https://searchcode.com/codesearch/view/90754671/
- const union = (...arrs) => unique([].concat(...arrs));
- // Получаем случайный элемент массива
- const choice = arr => arr[Math.floor(Math.random() * arr.length)];
- // Слегка измененный алгоритм отсюда
- // http://stackoverflow.com/a/6274398/2240578
- function shuffle(arr) {
- let i = arr.length;
- while (i) {
- const r = Math.floor(Math.random() * i--);
- [arr[i], arr[r]] = [arr[r], arr[i]];
- }
- return arr;
- }
- // Украдено с Вконтакте
- // ~~rand(0, 10) --> вернет целое
- const rand = (min, max) => Math.random() * (max - min + 1) + min;
- // String functions
- // ucfirst('foo') --> "Foo"
- const ucfirst = str => str.charAt(0).toUpperCase() + str.slice(1);
- // splitLines('foo\r\nbar\nbaz') --> ["foo", "bar", "baz"]
- const splitLines = str => str.split(/\r?\n/g);
- // TODO: Убрать пробелы перед переводом строки
- // http://php.net/manual/ru/function.wordwrap.php
- /**
- * @param {string} text
- * @param {number} width
- * @return {string}
- */
- function wordWrap(text, width = 80) {
- if (!isString(text)) {
- throw new TypeError('text must be a string');
- }
- if (!isNumber(width)) {
- throw new TypeError('width must be a number');
- }
- if (width <= 0) {
- throw new Error('width must be greater than zero');
- }
- const lines = text.split('\n');
- const out = [];
- const re = new RegExp(`(\\s{1,${width}})|(\\S{1,${width}})`, 'g');
- for (const line of lines) {
- let buf = '';
- let len = 0;
- while (true) {
- const matches = re.exec(line);
- if (matches === null) {
- break;
- }
- const [ , whitespace, word] = matches;
- if (isUndefined(word)) {
- if (whitespace.length + len <= width) {
- buf += whitespace;
- len += whitespace.length;
- } else {
- // Пробелы в конец не добавляем
- buf += '\n';
- len = 0;
- }
- } else {
- if (word.length + len <= width) {
- buf += word;
- len += word.length;
- } else {
- buf += `\n${word}`;
- len = word.length;
- }
- }
- }
- out.push(buf);
- }
- return out.sjoin('\n');
- }
- // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions
- const escapeRegExp = str => str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
- const escapeHtml = unsafe =>
- unsafe.replace(/&/g, '&')
- .replace(/</g, '<')
- .replace(/>/g, '>')
- .replace(/"/g, '"')
- .replace(/'/g, ''');
- // Работа с цветами
- function rgbHex(red, green, blue) {
- const hex = (((255 & red) << 16) + ((255 & green) << 8) + (blue & 255))
- .toString(16);
- return `#${'000000'.slice(hex.length)}${hex}`;
- }
- function hexRgb(hex) {
- const matches = /^#?([a-fA-F0-9]{3}|[a-fA-F0-9]{6})$/.exec(hex);
- if (!matches) {
- return false;
- }
- hex = matches[1];
- const val = parseInt(hex, 16);
- return (hex.length === 3)
- ? [val >> 8, val >> 4 & 15, val & 15]
- : [val >> 16, val >> 8 & 255, val & 255];
- }
- // Смешиваем два цвета
- // mixHex('#000000', '#fff') --> "#808080"
- // mixHex('f00', '#00ff00') --> "#808000"
- // mixHex('ff00ff', '#ff00ff') --> "#ff00ff"
- // mixHex('#ff0000', '#0000ff') --> "#800080"
- // mixHex('777', '#999') --> "#888888"
- // mixHex('#111222', '222444') --> "#1a1b33"
- // mixHex('abcdef', '#fedcba') --> "#d5d5d5"
- // mixHex('#000', '#000222') --> "#000111"
- function mixHex(a, b) {
- const c1 = hexRgb(a);
- const c2 = hexRgb(b);
- if (c1 === false || c2 === false) {
- return false;
- }
- return rgbHex(
- Math.round((c1[0] + c2[0]) / 2),
- Math.round((c1[1] + c2[1]) / 2),
- Math.round((c1[2] + c2[2]) / 2)
- );
- }
- // Математика
- const deg2rad = angle => angle * Math.PI / 180;
- // Пользовательские события
- class EventEmitter {
- constructor() {
- this.listeners = {};
- // Алиасы
- this.on = this.addListener;
- this.off = this.removeListener;
- }
- addListener(type, listener) {
- if (!isFunction(listener)) {
- throw new TypeError('listener must be a function');
- }
- (this.hasListeners(type)
- ? this.listeners[type]
- : this.listeners[type] = []).push(listener);
- return this;
- }
- removeListener(type, listener) {
- if (this.hasListeners(type)) {
- const listeners = this.listeners[type];
- while (true) {
- const index = listeners.indexOf(listener);
- if (index < 0) {
- break;
- }
- listeners.splice(index, 1);
- }
- if (!listeners.length) {
- delete this.listeners[type];
- }
- }
- return this;
- }
- removeAllListeners(type) {
- if (arguments.length) {
- if (this.hasListeners(type)) {
- delete this.listeners[type];
- }
- } else {
- this.listeners = {};
- }
- return this;
- }
- emit(type, ...args) {
- if (this.hasListeners(type)) {
- for (const listener of this.listeners[type]) {
- listener.apply(null, args);
- }
- }
- return this;
- }
- hasListeners(type) {
- return hasOwn(type, this.listeners);
- }
- }
- function testEventEmitter() {
- function hello(name) {
- return console.log(`Hello ${name}`);
- }
- const emitter = new EventEmitter;
- emitter.on('greeting', hello);
- emitter.emit('greeting', 'World');
- emitter.off('greeting', hello);
- // Nothing will happen
- emitter.emit('greeting', '...');
- }
- // DOM
- const gid = id => document.getElementById(id);
- // https://developer.mozilla.org/en-US/Add-ons/Code_snippets/QuerySelector
- const $$ = (selector, el) =>
- // NodeList имеет лишь метод item и свойство length, свойство предоставляет
- // несравнимо больший функционал
- toArray((el || document).querySelectorAll(selector));
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement