// ==UserScript== // @name 网页截屏 // @namespace https://github.com/CListery // @version 0.9 // @description 将选中元素截屏 // @license MIT // @author CListery // @require https://cdn.jsdelivr.net/npm/html2canvas@1/dist/html2canvas.min.js // @require https://cdn.jsdelivr.net/npm/jquery@3/dist/jquery.min.js // @require https://cdn.jsdelivr.net/npm/luna-dom-highlighter@1.0.2/luna-dom-highlighter.js // @resource lunaDomHighlighterCSS https://cdn.jsdelivr.net/npm/luna-dom-highlighter/luna-dom-highlighter.css // @match *://*/* // @icon data:image/svg+xml;base64,PHN2ZyBmaWxsPSIjZmZmZmZmIiBoZWlnaHQ9IjI0IiB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICAgIDxjaXJjbGUgY3g9IjEyIiBjeT0iMTIiIHI9IjMuMiIvPgogICAgPHBhdGggZD0iTTkgMkw3LjE3IDRINGMtMS4xIDAtMiAuOS0yIDJ2MTJjMCAxLjEuOSAyIDIgMmgxNmMxLjEgMCAyLS45IDItMlY2YzAtMS4xLS45LTItMi0yaC0zLjE3TDE1IDJIOXptMyAxNWMtMi43NiAwLTUtMi4yNC01LTVzMi4yNC01IDUtNSA1IDIuMjQgNSA1LTIuMjQgNS01IDV6Ii8+CiAgICA8cGF0aCBkPSJNMCAwaDI0djI0SDB6IiBmaWxsPSJub25lIi8+Cjwvc3ZnPgo= // @grant GM.getResourceUrl // @grant GM.getResourceText // @grant GM_getResourceText // @downloadURL https://update.greasyfork.icu/scripts/493588/%E7%BD%91%E9%A1%B5%E6%88%AA%E5%B1%8F.user.js // @updateURL https://update.greasyfork.icu/scripts/493588/%E7%BD%91%E9%A1%B5%E6%88%AA%E5%B1%8F.meta.js // ==/UserScript== ;(function () { 'use strict', // licia libraries // Built by eustia. // included: h toBool evalCss root cssSupports $ contain defaults (function (root, factory) { if (typeof define === 'function' && define.amd) { define([], factory) } else if (typeof module === 'object' && module.exports) { module.exports = factory() } else { root._licia = factory() } })(this, function () { /* eslint-disable */ var _licia = {} if (typeof window === 'object' && window._licia) _licia = window._licia /* ------------------------------ last ------------------------------ */ var last = (_licia.last = (function (exports) { /* Get the last element of array. * * |Name |Desc | * |------|-------------------------| * |arr |The array to query | * |return|The last element of array| */ /* example * last([1, 2]); // -> 2 */ /* typescript * export declare function last(arr: any[]): any; */ exports = function (arr) { var len = arr ? arr.length : 0 if (len) return arr[len - 1] } return exports })({})) /* ------------------------------ isUndef ------------------------------ */ var isUndef = (_licia.isUndef = (function (exports) { /* Check if value is undefined. * * |Name |Desc | * |------|--------------------------| * |val |Value to check | * |return|True if value is undefined| */ /* example * isUndef(void 0); // -> true * isUndef(null); // -> false */ /* typescript * export declare function isUndef(val: any): val is undefined; */ exports = function (val) { return val === void 0 } return exports })({})) /* ------------------------------ types ------------------------------ */ var types = (_licia.types = (function (exports) { /* Used for typescript definitions only. */ /* typescript * export declare namespace types { * interface Collection {} * interface List extends Collection { * [index: number]: T; * length: number; * } * interface ListIterator { * (value: T, index: number, list: List): TResult; * } * interface Dictionary extends Collection { * [index: string]: T; * } * interface ObjectIterator { * (element: T, key: string, list: Dictionary): TResult; * } * interface MemoIterator { * (prev: TResult, curr: T, index: number, list: List): TResult; * } * interface MemoObjectIterator { * (prev: TResult, curr: T, key: string, list: Dictionary): TResult; * } * type Fn = (...args: any[]) => T; * type AnyFn = Fn; * type PlainObj = { [name: string]: T }; * } * export declare const types: {}; */ exports = {} return exports })({})) /* ------------------------------ isObj ------------------------------ */ var isObj = (_licia.isObj = (function (exports) { /* Check if value is the language type of Object. * * |Name |Desc | * |------|--------------------------| * |val |Value to check | * |return|True if value is an object| * * [Language Spec](http://www.ecma-international.org/ecma-262/6.0/#sec-ecmascript-language-types) */ /* example * isObj({}); // -> true * isObj([]); // -> true */ /* typescript * export declare function isObj(val: any): boolean; */ exports = function (val) { var type = typeof val return !!val && (type === 'function' || type === 'object') } return exports })({})) /* ------------------------------ splitCase ------------------------------ */ var splitCase = (_licia.splitCase = (function (exports) { /* Split different string case to an array. * * |Name |Desc | * |------|---------------| * |str |String to split| * |return|Result array | */ /* example * splitCase('foo-bar'); // -> ['foo', 'bar'] * splitCase('foo bar'); // -> ['foo', 'bar'] * splitCase('foo_bar'); // -> ['foo', 'bar'] * splitCase('foo.bar'); // -> ['foo', 'bar'] * splitCase('fooBar'); // -> ['foo', 'bar'] * splitCase('foo-Bar'); // -> ['foo', 'bar'] */ /* typescript * export declare function splitCase(str: string): string[]; */ var regUpperCase = /([A-Z])/g var regSeparator = /[_.\- ]+/g var regTrim = /(^-)|(-$)/g exports = function (str) { str = str .replace(regUpperCase, '-$1') .toLowerCase() .replace(regSeparator, '-') .replace(regTrim, '') return str.split('-') } return exports })({})) /* ------------------------------ camelCase ------------------------------ */ var camelCase = (_licia.camelCase = (function (exports) { /* Convert string to "camelCase". * * |Name |Desc | * |------|------------------| * |str |String to convert | * |return|Camel cased string| */ /* example * camelCase('foo-bar'); // -> fooBar * camelCase('foo bar'); // -> fooBar * camelCase('foo_bar'); // -> fooBar * camelCase('foo.bar'); // -> fooBar */ /* typescript * export declare function camelCase(str: string): string; */ /* dependencies * splitCase */ exports = function (str) { var arr = splitCase(str) var ret = arr[0] arr.shift() arr.forEach(capitalize, arr) ret += arr.join('') return ret } function capitalize(val, idx) { this[idx] = val.replace(/\w/, function (match) { return match.toUpperCase() }) } return exports })({})) /* ------------------------------ kebabCase ------------------------------ */ var kebabCase = (_licia.kebabCase = (function (exports) { /* Convert string to "kebabCase". * * |Name |Desc | * |------|------------------| * |str |String to convert | * |return|Kebab cased string| */ /* example * kebabCase('fooBar'); // -> foo-bar * kebabCase('foo bar'); // -> foo-bar * kebabCase('foo_bar'); // -> foo-bar * kebabCase('foo.bar'); // -> foo-bar */ /* typescript * export declare function kebabCase(str: string): string; */ /* dependencies * splitCase */ exports = function (str) { return splitCase(str).join('-') } return exports })({})) /* ------------------------------ has ------------------------------ */ var has = (_licia.has = (function (exports) { /* Checks if key is a direct property. * * |Name |Desc | * |------|--------------------------------| * |obj |Object to query | * |key |Path to check | * |return|True if key is a direct property| */ /* example * has({ one: 1 }, 'one'); // -> true */ /* typescript * export declare function has(obj: {}, key: string): boolean; */ var hasOwnProp = Object.prototype.hasOwnProperty exports = function (obj, key) { return hasOwnProp.call(obj, key) } return exports })({})) /* ------------------------------ keys ------------------------------ */ var keys = (_licia.keys = (function (exports) { /* Create an array of the own enumerable property names of object. * * |Name |Desc | * |------|-----------------------| * |obj |Object to query | * |return|Array of property names| */ /* example * keys({ a: 1 }); // -> ['a'] */ /* typescript * export declare function keys(obj: any): string[]; */ /* dependencies * has */ if (Object.keys && !false) { exports = Object.keys } else { exports = function (obj) { var ret = [] for (var key in obj) { if (has(obj, key)) ret.push(key) } return ret } } return exports })({})) /* ------------------------------ idxOf ------------------------------ */ var idxOf = (_licia.idxOf = (function (exports) { /* Get the index at which the first occurrence of value. * * |Name |Desc | * |---------|--------------------| * |arr |Array to search | * |val |Value to search for | * |fromIdx=0|Index to search from| * |return |Value index | */ /* example * idxOf([1, 2, 1, 2], 2, 2); // -> 3 */ /* typescript * export declare function idxOf(arr: any[], val: any, fromIdx?: number): number; */ exports = function (arr, val, fromIdx) { return Array.prototype.indexOf.call(arr, val, fromIdx) } return exports })({})) /* ------------------------------ create ------------------------------ */ var create = (_licia.create = (function (exports) { /* Create new object using given object as prototype. * * |Name |Desc | * |------|-----------------------| * |proto |Prototype of new object| * |return|Created object | */ /* example * const obj = create({ a: 1 }); * console.log(obj.a); // -> 1 */ /* typescript * export declare function create(proto?: object): any; */ /* dependencies * isObj */ exports = function (proto) { if (!isObj(proto)) return {} if (objCreate && !false) return objCreate(proto) function noop() {} noop.prototype = proto return new noop() } var objCreate = Object.create return exports })({})) /* ------------------------------ inherits ------------------------------ */ var inherits = (_licia.inherits = (function (exports) { /* Inherit the prototype methods from one constructor into another. * * |Name |Desc | * |----------|-----------| * |Class |Child Class| * |SuperClass|Super Class| */ /* example * function People(name) { * this._name = name; * } * People.prototype = { * getName: function() { * return this._name; * } * }; * function Student(name) { * this._name = name; * } * inherits(Student, People); * const s = new Student('RedHood'); * s.getName(); // -> 'RedHood' */ /* typescript * export declare function inherits( * Class: types.AnyFn, * SuperClass: types.AnyFn * ): void; */ /* dependencies * create types */ exports = function (Class, SuperClass) { Class.prototype = create(SuperClass.prototype) } return exports })({})) /* ------------------------------ memoize ------------------------------ */ var memoize = (_licia.memoize = (function (exports) { /* Memoize a given function by caching the computed result. * * |Name |Desc | * |------|------------------------------------| * |fn |Function to have its output memoized| * |hashFn|Function to create cache key | * |return|New memoized function | */ /* example * const fibonacci = memoize(function(n) { * return n < 2 ? n : fibonacci(n - 1) + fibonacci(n - 2); * }); */ /* typescript * export declare function memoize( * fn: types.AnyFn, * hashFn?: types.AnyFn * ): types.AnyFn; */ /* dependencies * has types */ exports = function (fn, hashFn) { var memoize = function (key) { var cache = memoize.cache var address = '' + (hashFn ? hashFn.apply(this, arguments) : key) if (!has(cache, address)) cache[address] = fn.apply(this, arguments) return cache[address] } memoize.cache = {} return memoize } return exports })({})) /* ------------------------------ cssSupports ------------------------------ */ _licia.cssSupports = (function (exports) { /* Check if browser supports a given CSS feature. * * |Name |Desc | * |------|------------------| * |name |Css property name | * |val |Css property value| * |return|True if supports | */ /* example * cssSupports('display', 'flex'); // -> true * cssSupports('display', 'invalid'); // -> false * cssSupports('text-decoration-line', 'underline'); // -> true * cssSupports('grid'); // -> true * cssSupports('invalid'); // -> false */ /* typescript * export declare function cssSupports(name: string, val?: string): boolean; */ /* dependencies * memoize isUndef camelCase */ exports = memoize( function (name, value) { if (isUndef(value)) { name = camelCase(name) return !isUndef(style[name]) } style.cssText = '' style.cssText = name + ':' + value return !!style.length }, function (name, value) { return name + ' ' + value } ) var style = document.createElement('p').style return exports })({}) /* ------------------------------ optimizeCb ------------------------------ */ var optimizeCb = (_licia.optimizeCb = (function (exports) { /* Used for function context binding. */ /* typescript * export declare function optimizeCb( * fn: types.AnyFn, * ctx: any, * argCount?: number * ): types.AnyFn; */ /* dependencies * isUndef types */ exports = function (fn, ctx, argCount) { if (isUndef(ctx)) return fn switch (argCount == null ? 3 : argCount) { case 1: return function (val) { return fn.call(ctx, val) } case 3: return function (val, idx, collection) { return fn.call(ctx, val, idx, collection) } case 4: return function (accumulator, val, idx, collection) { return fn.call(ctx, accumulator, val, idx, collection) } } return function () { return fn.apply(ctx, arguments) } } return exports })({})) /* ------------------------------ evalCss ------------------------------ */ _licia.evalCss = (function (exports) { /* Load css into page. * * |Name |Desc | * |------|-------------| * |css |Css code | * |return|Style element| */ /* example * evalCss('body{background:#08c}'); */ /* typescript * export declare function evalCss(css: string): HTMLStyleElement; */ exports = function (css) { var style = document.createElement('style') style.textContent = css style.type = 'text/css' document.head.appendChild(style) return style } return exports })({}) /* ------------------------------ isEl ------------------------------ */ var isEl = (_licia.isEl = (function (exports) { /* Check if value is a DOM element. * * |Name |Desc | * |------|------------------------------| * |val |Value to check | * |return|True if value is a DOM element| */ /* example * isEl(document.body); // -> true */ /* typescript * export declare function isEl(val: any): val is Element; */ exports = function (val) { return !!(val && val.nodeType === 1) } return exports })({})) /* ------------------------------ startWith ------------------------------ */ var startWith = (_licia.startWith = (function (exports) { /* Check if string starts with the given target string. * * |Name |Desc | * |------|---------------------------------| * |str |String to search | * |prefix|String prefix | * |return|True if string starts with prefix| */ /* example * startWith('ab', 'a'); // -> true */ /* typescript * export declare function startWith(str: string, prefix: string): boolean; */ exports = function (str, prefix) { return str.indexOf(prefix) === 0 } return exports })({})) /* ------------------------------ identity ------------------------------ */ var identity = (_licia.identity = (function (exports) { /* Return the first argument given. * * |Name |Desc | * |------|-----------| * |val |Any value | * |return|Given value| */ /* example * identity('a'); // -> 'a' */ /* typescript * export declare function identity(val: T): T; */ exports = function (val) { return val } return exports })({})) /* ------------------------------ objToStr ------------------------------ */ var objToStr = (_licia.objToStr = (function (exports) { /* Alias of Object.prototype.toString. * * |Name |Desc | * |------|------------------------------------| * |val |Source value | * |return|String representation of given value| */ /* example * objToStr(5); // -> '[object Number]' */ /* typescript * export declare function objToStr(val: any): string; */ var ObjToStr = Object.prototype.toString exports = function (val) { return ObjToStr.call(val) } return exports })({})) /* ------------------------------ isArr ------------------------------ */ var isArr = (_licia.isArr = (function (exports) { /* Check if value is an `Array` object. * * |Name |Desc | * |------|----------------------------------| * |val |Value to check | * |return|True if value is an `Array` object| */ /* example * isArr([]); // -> true * isArr({}); // -> false */ /* typescript * export declare function isArr(val: any): val is any[]; */ /* dependencies * objToStr */ if (Array.isArray && !false) { exports = Array.isArray } else { exports = function (val) { return objToStr(val) === '[object Array]' } } return exports })({})) /* ------------------------------ castPath ------------------------------ */ var castPath = (_licia.castPath = (function (exports) { /* Cast value into a property path array. * * |Name |Desc | * |------|-------------------| * |path |Value to inspect | * |obj |Object to query | * |return|Property path array| */ /* example * castPath('a.b.c'); // -> ['a', 'b', 'c'] * castPath(['a']); // -> ['a'] * castPath('a[0].b'); // -> ['a', '0', 'b'] * castPath('a.b.c', { 'a.b.c': true }); // -> ['a.b.c'] */ /* typescript * export declare function castPath(path: string | string[], obj?: any): string[]; */ /* dependencies * has isArr */ exports = function (str, obj) { if (isArr(str)) return str if (obj && has(obj, str)) return [str] var ret = [] str.replace(regPropName, function (match, number, quote, str) { ret.push(quote ? str.replace(regEscapeChar, '$1') : number || match) }) return ret } // Lodash _stringToPath var regPropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g var regEscapeChar = /\\(\\)?/g return exports })({})) /* ------------------------------ safeGet ------------------------------ */ var safeGet = (_licia.safeGet = (function (exports) { /* Get object property, don't throw undefined error. * * |Name |Desc | * |------|-------------------------| * |obj |Object to query | * |path |Path of property to get | * |return|Target value or undefined| */ /* example * const obj = { a: { aa: { aaa: 1 } } }; * safeGet(obj, 'a.aa.aaa'); // -> 1 * safeGet(obj, ['a', 'aa']); // -> {aaa: 1} * safeGet(obj, 'a.b'); // -> undefined */ /* typescript * export declare function safeGet(obj: any, path: string | string[]): any; */ /* dependencies * isUndef castPath */ exports = function (obj, path) { path = castPath(path, obj) var prop prop = path.shift() while (!isUndef(prop)) { obj = obj[prop] if (obj == null) return prop = path.shift() } return obj } return exports })({})) /* ------------------------------ isFn ------------------------------ */ var isFn = (_licia.isFn = (function (exports) { /* Check if value is a function. * * |Name |Desc | * |------|---------------------------| * |val |Value to check | * |return|True if value is a function| * * Generator function is also classified as true. */ /* example * isFn(function() {}); // -> true * isFn(function*() {}); // -> true * isFn(async function() {}); // -> true */ /* typescript * export declare function isFn(val: any): val is Function; */ /* dependencies * objToStr */ exports = function (val) { var objStr = objToStr(val) return ( objStr === '[object Function]' || objStr === '[object GeneratorFunction]' || objStr === '[object AsyncFunction]' ) } return exports })({})) /* ------------------------------ getProto ------------------------------ */ var getProto = (_licia.getProto = (function (exports) { /* Get prototype of an object. * * |Name |Desc | * |------|---------------------------------------------| * |obj |Target object | * |return|Prototype of given object, null if not exists| */ /* example * const a = {}; * getProto(Object.create(a)); // -> a */ /* typescript * export declare function getProto(obj: any): any; */ /* dependencies * isObj isFn */ var getPrototypeOf = Object.getPrototypeOf var ObjectCtr = {}.constructor exports = function (obj) { if (!isObj(obj)) return if (getPrototypeOf && !false) return getPrototypeOf(obj) var proto = obj.__proto__ if (proto || proto === null) return proto if (isFn(obj.constructor)) return obj.constructor.prototype if (obj instanceof ObjectCtr) return ObjectCtr.prototype } return exports })({})) /* ------------------------------ isMiniProgram ------------------------------ */ var isMiniProgram = (_licia.isMiniProgram = (function (exports) { /* Check if running in wechat mini program. */ /* example * console.log(isMiniProgram); // -> true if running in mini program. */ /* typescript * export declare const isMiniProgram: boolean; */ /* dependencies * isFn */ /* eslint-disable no-undef */ exports = typeof wx !== 'undefined' && isFn(wx.openLocation) return exports })({})) /* ------------------------------ isNum ------------------------------ */ var isNum = (_licia.isNum = (function (exports) { /* Check if value is classified as a Number primitive or object. * * |Name |Desc | * |------|-------------------------------------| * |val |Value to check | * |return|True if value is correctly classified| */ /* example * isNum(5); // -> true * isNum(5.1); // -> true * isNum({}); // -> false */ /* typescript * export declare function isNum(val: any): val is number; */ /* dependencies * objToStr */ exports = function (val) { return objToStr(val) === '[object Number]' } return exports })({})) /* ------------------------------ isArrLike ------------------------------ */ var isArrLike = (_licia.isArrLike = (function (exports) { /* Check if value is array-like. * * |Name |Desc | * |------|---------------------------| * |val |Value to check | * |return|True if value is array like| * * Function returns false. */ /* example * isArrLike('test'); // -> true * isArrLike(document.body.children); // -> true; * isArrLike([1, 2, 3]); // -> true */ /* typescript * export declare function isArrLike(val: any): boolean; */ /* dependencies * isNum isFn */ var MAX_ARR_IDX = Math.pow(2, 53) - 1 exports = function (val) { if (!val) return false var len = val.length return isNum(len) && len >= 0 && len <= MAX_ARR_IDX && !isFn(val) } return exports })({})) /* ------------------------------ each ------------------------------ */ var each = (_licia.each = (function (exports) { /* Iterate over elements of collection and invokes iterator for each element. * * |Name |Desc | * |--------|------------------------------| * |obj |Collection to iterate over | * |iterator|Function invoked per iteration| * |ctx |Function context | */ /* example * each({ a: 1, b: 2 }, function(val, key) {}); */ /* typescript * export declare function each( * list: types.List, * iterator: types.ListIterator, * ctx?: any * ): types.List; * export declare function each( * object: types.Dictionary, * iterator: types.ObjectIterator, * ctx?: any * ): types.Collection; */ /* dependencies * isArrLike keys optimizeCb types */ exports = function (obj, iterator, ctx) { iterator = optimizeCb(iterator, ctx) var i, len if (isArrLike(obj)) { for (i = 0, len = obj.length; i < len; i++) iterator(obj[i], i, obj) } else { var _keys = keys(obj) for (i = 0, len = _keys.length; i < len; i++) { iterator(obj[_keys[i]], _keys[i], obj) } } return obj } return exports })({})) /* ------------------------------ createAssigner ------------------------------ */ var createAssigner = (_licia.createAssigner = (function (exports) { /* Used to create extend, extendOwn and defaults. * * |Name |Desc | * |--------|------------------------------| * |keysFn |Function to get object keys | * |defaults|No override when set to true | * |return |Result function, extend... | */ /* typescript * export declare function createAssigner( * keysFn: types.AnyFn, * defaults: boolean * ): types.AnyFn; */ /* dependencies * isUndef each types */ exports = function (keysFn, defaults) { return function (obj) { each(arguments, function (src, idx) { if (idx === 0) return var keys = keysFn(src) each(keys, function (key) { if (!defaults || isUndef(obj[key])) obj[key] = src[key] }) }) return obj } } return exports })({})) /* ------------------------------ extendOwn ------------------------------ */ var extendOwn = (_licia.extendOwn = (function (exports) { /* Like extend, but only copies own properties over to the destination object. * * |Name |Desc | * |-----------|------------------| * |destination|Destination object| * |...sources |Sources objects | * |return |Destination object| */ /* example * extendOwn({ name: 'RedHood' }, { age: 24 }); // -> {name: 'RedHood', age: 24} */ /* typescript * export declare function extendOwn(destination: any, ...sources: any[]): any; */ /* dependencies * keys createAssigner */ exports = createAssigner(keys) return exports })({})) /* ------------------------------ values ------------------------------ */ var values = (_licia.values = (function (exports) { /* Create an array of the own enumerable property values of object. * * |Name |Desc | * |------|------------------------| * |obj |Object to query | * |return|Array of property values| */ /* example * values({ one: 1, two: 2 }); // -> [1, 2] */ /* typescript * export declare function values(obj: any): any[]; */ /* dependencies * each */ exports = function (obj) { var ret = [] each(obj, function (val) { ret.push(val) }) return ret } return exports })({})) /* ------------------------------ isStr ------------------------------ */ var isStr = (_licia.isStr = (function (exports) { /* Check if value is a string primitive. * * |Name |Desc | * |------|-----------------------------------| * |val |Value to check | * |return|True if value is a string primitive| */ /* example * isStr('licia'); // -> true */ /* typescript * export declare function isStr(val: any): val is string; */ /* dependencies * objToStr */ exports = function (val) { return objToStr(val) === '[object String]' } return exports })({})) /* ------------------------------ contain ------------------------------ */ var contain = (_licia.contain = (function (exports) { /* Check if the value is present in the list. * * |Name |Desc | * |------|------------------------------------| * |target|Target object | * |val |Value to check | * |return|True if value is present in the list| */ /* example * contain([1, 2, 3], 1); // -> true * contain({ a: 1, b: 2 }, 1); // -> true * contain('abc', 'a'); // -> true */ /* typescript * export declare function contain(arr: any[] | {} | string, val: any): boolean; */ /* dependencies * idxOf isStr isArrLike values */ exports = function (arr, val) { if (isStr(arr)) return arr.indexOf(val) > -1 if (!isArrLike(arr)) arr = values(arr) return idxOf(arr, val) >= 0 } return exports })({})) /* ------------------------------ isBrowser ------------------------------ */ var isBrowser = (_licia.isBrowser = (function (exports) { /* Check if running in a browser. */ /* example * console.log(isBrowser); // -> true if running in a browser */ /* typescript * export declare const isBrowser: boolean; */ exports = typeof window === 'object' && typeof document === 'object' && document.nodeType === 9 return exports })({})) /* ------------------------------ isMatch ------------------------------ */ var isMatch = (_licia.isMatch = (function (exports) { /* Check if keys and values in src are contained in obj. * * |Name |Desc | * |------|----------------------------------| * |obj |Object to inspect | * |src |Object of property values to match| * |return|True if object is match | */ /* example * isMatch({ a: 1, b: 2 }, { a: 1 }); // -> true */ /* typescript * export declare function isMatch(obj: any, src: any): boolean; */ /* dependencies * keys */ exports = function (obj, src) { var _keys = keys(src) var len = _keys.length if (obj == null) return !len obj = Object(obj) for (var i = 0; i < len; i++) { var key = _keys[i] if (src[key] !== obj[key] || !(key in obj)) return false } return true } return exports })({})) /* ------------------------------ matcher ------------------------------ */ var matcher = (_licia.matcher = (function (exports) { /* Return a predicate function that checks if attrs are contained in an object. * * |Name |Desc | * |------|----------------------------------| * |attrs |Object of property values to match| * |return|New predicate function | */ /* example * const filter = require('licia/filter'); * * const objects = [ * { a: 1, b: 2, c: 3 }, * { a: 4, b: 5, c: 6 } * ]; * filter(objects, matcher({ a: 4, c: 6 })); // -> [{a: 4, b: 5, c: 6}] */ /* typescript * export declare function matcher(attrs: any): types.AnyFn; */ /* dependencies * extendOwn isMatch types */ exports = function (attrs) { attrs = extendOwn({}, attrs) return function (obj) { return isMatch(obj, attrs) } } return exports })({})) /* ------------------------------ restArgs ------------------------------ */ var restArgs = (_licia.restArgs = (function (exports) { /* This accumulates the arguments passed into an array, after a given index. * * |Name |Desc | * |----------|---------------------------------------| * |function |Function that needs rest parameters | * |startIndex|The start index to accumulates | * |return |Generated function with rest parameters| */ /* example * const paramArr = restArgs(function(rest) { * return rest; * }); * paramArr(1, 2, 3, 4); // -> [1, 2, 3, 4] */ /* typescript * export declare function restArgs( * fn: types.AnyFn, * startIndex?: number * ): types.AnyFn; */ /* dependencies * types */ exports = function (fn, startIdx) { startIdx = startIdx == null ? fn.length - 1 : +startIdx return function () { var len = Math.max(arguments.length - startIdx, 0) var rest = new Array(len) var i for (i = 0; i < len; i++) rest[i] = arguments[i + startIdx] // Call runs faster than apply. switch (startIdx) { case 0: return fn.call(this, rest) case 1: return fn.call(this, arguments[0], rest) case 2: return fn.call(this, arguments[0], arguments[1], rest) } var args = new Array(startIdx + 1) for (i = 0; i < startIdx; i++) args[i] = arguments[i] args[startIdx] = rest return fn.apply(this, args) } } return exports })({})) /* ------------------------------ mergeArr ------------------------------ */ var mergeArr = (_licia.mergeArr = (function (exports) { /* Merge the contents of arrays together into the first array. * * |Name |Desc | * |------|------------------------------------| * |first |Array to merge | * |arrays|Arrays to merge into the first array| * |return|First array | */ /* example * const a = [1, 2]; * mergeArr(a, [3, 4], [5, 6]); * console.log(a); // -> [1, 2, 3, 4, 5, 6] */ /* typescript * export declare function mergeArr( * first: ArrayLike, * ...arrays: ArrayLike[] * ): ArrayLike; */ /* dependencies * restArgs */ exports = restArgs(function (first, arrays) { var end = first.length for (var i = 0, len = arrays.length; i < len; i++) { var arr = arrays[i] for (var j = 0, _len = arr.length; j < _len; j++) { first[end++] = arr[j] } } first.length = end return first }) return exports })({})) /* ------------------------------ upperFirst ------------------------------ */ var upperFirst = (_licia.upperFirst = (function (exports) { /* Convert the first character of string to upper case. * * |Name |Desc | * |------|-----------------| * |str |String to convert| * |return|Converted string | */ /* example * upperFirst('red'); // -> Red */ /* typescript * export declare function upperFirst(str: string): string; */ exports = function (str) { if (str.length < 1) return str return str[0].toUpperCase() + str.slice(1) } return exports })({})) /* ------------------------------ prefix ------------------------------ */ var prefix = (_licia.prefix = (function (exports) { /* Add vendor prefixes to a CSS attribute. * * |Name |Desc | * |------|----------------------| * |name |Property name | * |return|Prefixed property name| * * ### dash * * Create a dasherize version. */ /* example * prefix('text-emphasis'); // -> 'WebkitTextEmphasis' * prefix.dash('text-emphasis'); // -> '-webkit-text-emphasis' * prefix('color'); // -> 'color' */ /* typescript * export declare namespace prefix { * function dash(name: string): string; * } * export declare function prefix(name: string): string; */ /* dependencies * memoize camelCase upperFirst has kebabCase */ exports = memoize(function (name) { name = name.replace(regPrefixes, '') name = camelCase(name) if (has(style, name)) return name var i = prefixes.length while (i--) { var prefixName = prefixes[i] + upperFirst(name) if (has(style, prefixName)) return prefixName } return name }) exports.dash = memoize(function (name) { var camelCaseResult = exports(name) return (regPrefixes.test(camelCaseResult) ? '-' : '') + kebabCase(camelCaseResult) }) var prefixes = ['O', 'ms', 'Moz', 'Webkit'] var regPrefixes = /^(O)|(ms)|(Moz)|(Webkit)|(-o-)|(-ms-)|(-moz-)|(-webkit-)/g var style = document.createElement('p').style return exports })({})) /* ------------------------------ property ------------------------------ */ var property = (_licia.property = (function (exports) { /* Return a function that will itself return the key property of any passed-in object. * * |Name |Desc | * |------|---------------------------| * |path |Path of the property to get| * |return|New accessor function | */ /* example * const obj = { a: { b: 1 } }; * property('a')(obj); // -> {b: 1} * property(['a', 'b'])(obj); // -> 1 */ /* typescript * export declare function property(path: string | string[]): types.AnyFn; */ /* dependencies * isArr safeGet types */ exports = function (path) { if (!isArr(path)) return shallowProperty(path) return function (obj) { return safeGet(obj, path) } } function shallowProperty(key) { return function (obj) { return obj == null ? void 0 : obj[key] } } return exports })({})) /* ------------------------------ safeCb ------------------------------ */ var safeCb = (_licia.safeCb = (function (exports) { /* Create callback based on input value. */ /* typescript * export declare function safeCb( * val?: any, * ctx?: any, * argCount?: number * ): types.AnyFn; */ /* dependencies * isFn isObj isArr optimizeCb matcher identity types property */ exports = function (val, ctx, argCount) { if (val == null) return identity if (isFn(val)) return optimizeCb(val, ctx, argCount) if (isObj(val) && !isArr(val)) return matcher(val) return property(val) } return exports })({})) /* ------------------------------ filter ------------------------------ */ var filter = (_licia.filter = (function (exports) { /* Iterates over elements of collection, returning an array of all the values that pass a truth test. * * |Name |Desc | * |---------|---------------------------------------| * |obj |Collection to iterate over | * |predicate|Function invoked per iteration | * |ctx |Predicate context | * |return |Array of all values that pass predicate| */ /* example * filter([1, 2, 3, 4, 5], function(val) { * return val % 2 === 0; * }); // -> [2, 4] */ /* typescript * export declare function filter( * list: types.List, * iterator: types.ListIterator, * context?: any * ): T[]; * export declare function filter( * object: types.Dictionary, * iterator: types.ObjectIterator, * context?: any * ): T[]; */ /* dependencies * safeCb each types */ exports = function (obj, predicate, ctx) { var ret = [] predicate = safeCb(predicate, ctx) each(obj, function (val, idx, list) { if (predicate(val, idx, list)) ret.push(val) }) return ret } return exports })({})) /* ------------------------------ unique ------------------------------ */ var unique = (_licia.unique = (function (exports) { /* Create duplicate-free version of an array. * * |Name |Desc | * |------|-----------------------------| * |arr |Array to inspect | * |cmp |Function for comparing values| * |return|New duplicate free array | */ /* example * unique([1, 2, 3, 1]); // -> [1, 2, 3] */ /* typescript * export declare function unique( * arr: any[], * cmp?: (a: any, b: any) => boolean | number * ): any[]; */ /* dependencies * filter */ exports = function (arr, cmp) { cmp = cmp || isEqual return filter(arr, function (item, idx, arr) { var len = arr.length while (++idx < len) { if (cmp(item, arr[idx])) return false } return true }) } function isEqual(a, b) { return a === b } return exports })({})) /* ------------------------------ allKeys ------------------------------ */ var allKeys = (_licia.allKeys = (function (exports) { /* Retrieve all the names of object's own and inherited properties. * * |Name |Desc | * |-------|---------------------------| * |obj |Object to query | * |options|Options | * |return |Array of all property names| * * Available options: * * |Name |Desc | * |------------------|-------------------------| * |prototype=true |Include prototype keys | * |unenumerable=false|Include unenumerable keys| * |symbol=false |Include symbol keys | * * Members of Object's prototype won't be retrieved. */ /* example * const obj = Object.create({ zero: 0 }); * obj.one = 1; * allKeys(obj); // -> ['zero', 'one'] */ /* typescript * export declare namespace allKeys { * interface IOptions { * prototype?: boolean; * unenumerable?: boolean; * } * } * export declare function allKeys( * obj: any, * options: { symbol: true } & allKeys.IOptions * ): Array; * export declare function allKeys( * obj: any, * options?: ({ symbol: false } & allKeys.IOptions) | allKeys.IOptions * ): string[]; */ /* dependencies * keys getProto unique */ var getOwnPropertyNames = Object.getOwnPropertyNames var getOwnPropertySymbols = Object.getOwnPropertySymbols exports = function (obj) { var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}, _ref$prototype = _ref.prototype, prototype = _ref$prototype === void 0 ? true : _ref$prototype, _ref$unenumerable = _ref.unenumerable, unenumerable = _ref$unenumerable === void 0 ? false : _ref$unenumerable, _ref$symbol = _ref.symbol, symbol = _ref$symbol === void 0 ? false : _ref$symbol var ret = [] if ((unenumerable || symbol) && getOwnPropertyNames) { var getKeys = keys if (unenumerable && getOwnPropertyNames) getKeys = getOwnPropertyNames do { ret = ret.concat(getKeys(obj)) if (symbol && getOwnPropertySymbols) { ret = ret.concat(getOwnPropertySymbols(obj)) } } while (prototype && (obj = getProto(obj)) && obj !== Object.prototype) ret = unique(ret) } else { if (prototype) { for (var key in obj) ret.push(key) } else { ret = keys(obj) } } return ret } return exports })({})) /* ------------------------------ defaults ------------------------------ */ _licia.defaults = (function (exports) { /* Fill in undefined properties in object with the first value present in the following list of defaults objects. * * |Name |Desc | * |------|------------------| * |obj |Destination object| * |...src|Sources objects | * |return|Destination object| */ /* example * defaults({ name: 'RedHood' }, { name: 'Unknown', age: 24 }); // -> {name: 'RedHood', age: 24} */ /* typescript * export declare function defaults(obj: any, ...src: any[]): any; */ /* dependencies * createAssigner allKeys */ exports = createAssigner(allKeys, true) return exports })({}) /* ------------------------------ extend ------------------------------ */ var extend = (_licia.extend = (function (exports) { /* Copy all of the properties in the source objects over to the destination object. * * |Name |Desc | * |-----------|------------------| * |destination|Destination object| * |...sources |Sources objects | * |return |Destination object| */ /* example * extend({ name: 'RedHood' }, { age: 24 }); // -> {name: 'RedHood', age: 24} */ /* typescript * export declare function extend(destination: any, ...sources: any[]): any; */ /* dependencies * createAssigner allKeys */ exports = createAssigner(allKeys) return exports })({})) /* ------------------------------ map ------------------------------ */ var map = (_licia.map = (function (exports) { /* Create an array of values by running each element in collection through iteratee. * * |Name |Desc | * |--------|------------------------------| * |object |Collection to iterate over | * |iterator|Function invoked per iteration| * |context |Function context | * |return |New mapped array | */ /* example * map([4, 8], function(n) { * return n * n; * }); // -> [16, 64] */ /* typescript * export declare function map( * list: types.List, * iterator: types.ListIterator, * context?: any * ): TResult[]; * export declare function map( * object: types.Dictionary, * iterator: types.ObjectIterator, * context?: any * ): TResult[]; */ /* dependencies * safeCb keys isArrLike types */ exports = function (obj, iterator, ctx) { iterator = safeCb(iterator, ctx) var _keys = !isArrLike(obj) && keys(obj) var len = (_keys || obj).length var results = Array(len) for (var i = 0; i < len; i++) { var curKey = _keys ? _keys[i] : i results[i] = iterator(obj[curKey], curKey, obj) } return results } return exports })({})) /* ------------------------------ toArr ------------------------------ */ var toArr = (_licia.toArr = (function (exports) { /* Convert value to an array. * * |Name |Desc | * |------|----------------| * |val |Value to convert| * |return|Converted array | */ /* example * toArr({ a: 1, b: 2 }); // -> [{a: 1, b: 2}] * toArr('abc'); // -> ['abc'] * toArr(1); // -> [1] * toArr(null); // -> [] */ /* typescript * export declare function toArr(val: any): any[]; */ /* dependencies * isArrLike map isArr isStr */ exports = function (val) { if (!val) return [] if (isArr(val)) return val if (isArrLike(val) && !isStr(val)) return map(val) return [val] } return exports })({})) /* ------------------------------ Class ------------------------------ */ var Class = (_licia.Class = (function (exports) { /* Create JavaScript class. * * |Name |Desc | * |-------|---------------------------------| * |methods|Public methods | * [statics|Static methods | * |return |Function used to create instances| */ /* example * const People = Class({ * initialize: function People(name, age) { * this.name = name; * this.age = age; * }, * introduce: function() { * return 'I am ' + this.name + ', ' + this.age + ' years old.'; * } * }); * * const Student = People.extend( * { * initialize: function Student(name, age, school) { * this.callSuper(People, 'initialize', arguments); * * this.school = school; * }, * introduce: function() { * return ( * this.callSuper(People, 'introduce') + * '\n I study at ' + * this.school + * '.' * ); * } * }, * { * is: function(obj) { * return obj instanceof Student; * } * } * ); * * const a = new Student('allen', 17, 'Hogwarts'); * a.introduce(); // -> 'I am allen, 17 years old. \n I study at Hogwarts.' * Student.is(a); // -> true */ /* typescript * export declare namespace Class { * class Base { * toString(): string; * } * class IConstructor extends Base { * constructor(...args: any[]); * static extend(methods: any, statics: any): IConstructor; * static inherits(Class: types.AnyFn): void; * static methods(methods: any): IConstructor; * static statics(statics: any): IConstructor; * [method: string]: any; * } * } * export declare function Class(methods: any, statics?: any): Class.IConstructor; */ /* dependencies * extend toArr inherits safeGet isMiniProgram types */ exports = function (methods, statics) { return Base.extend(methods, statics) } function makeClass(parent, methods, statics) { statics = statics || {} var className = methods.className || safeGet(methods, 'initialize.name') || '' delete methods.className var ctor = function () { var args = toArr(arguments) return this.initialize ? this.initialize.apply(this, args) || this : this } if (!isMiniProgram) { // unsafe-eval CSP violation try { ctor = new Function( 'toArr', 'return function ' + className + '()' + '{' + 'var args = toArr(arguments);' + 'return this.initialize ? this.initialize.apply(this, args) || this : this;' + '};' )(toArr) } catch (e) { /* eslint-disable no-empty */ } } inherits(ctor, parent) ctor.prototype.constructor = ctor ctor.extend = function (methods, statics) { return makeClass(ctor, methods, statics) } ctor.inherits = function (Class) { inherits(ctor, Class) } ctor.methods = function (methods) { extend(ctor.prototype, methods) return ctor } ctor.statics = function (statics) { extend(ctor, statics) return ctor } ctor.methods(methods).statics(statics) return ctor } var Base = (exports.Base = makeClass(Object, { className: 'Base', callSuper: function (parent, name, args) { var superMethod = parent.prototype[name] return superMethod.apply(this, args) }, toString: function () { return this.constructor.name }, })) return exports })({})) /* ------------------------------ Select ------------------------------ */ var Select = (_licia.Select = (function (exports) { /* Simple wrapper of querySelectorAll to make dom selection easier. * * ### constructor * * |Name |Desc | * |--------|-------------------| * |selector|Dom selector string| * * ### find * * Get desdendants of current matched elements. * * |Name |Desc | * |--------|-------------------| * |selector|Dom selector string| * * ### each * * Iterate over matched elements. * * |Name|Desc | * |----|------------------------------------| * |fn |Function to execute for each element| */ /* example * const $test = new Select('#test'); * $test.find('.test').each(function(idx, element) { * // Manipulate dom nodes * }); */ /* typescript * export declare class Select { * constructor(selector: string | Element | Document); * find(selector: string): Select; * each(fn: types.AnyFn): Select; * } */ /* dependencies * Class isStr each types mergeArr */ exports = Class({ className: 'Select', initialize: function (selector) { this.length = 0 if (!selector) return this if (isStr(selector)) return rootSelect.find(selector) if (selector.nodeType) { this[0] = selector this.length = 1 } }, find: function (selector) { var ret = new exports() this.each(function () { mergeArr(ret, this.querySelectorAll(selector)) }) return ret }, each: function (fn) { each(this, function (element, idx) { fn.call(element, idx, element) }) return this }, }) var rootSelect = new exports(document) return exports })({})) /* ------------------------------ $safeEls ------------------------------ */ var $safeEls = (_licia.$safeEls = (function (exports) { /* Convert value into an array, if it's a string, do querySelector. * * |Name |Desc | * |------|-----------------| * |val |Value to convert | * |return|Array of elements| */ /* example * $safeEls(document.querySelector('.test')); * $safeEls(document.querySelectorAll('.test')); * $safeEls('.test'); // -> Array of elements with test class */ /* typescript * export declare namespace $safeEls { * type El = Element | Element[] | NodeListOf | string; * } * export declare function $safeEls(val: $safeEls.El): Element[]; */ /* dependencies * isStr toArr Select */ exports = function (val) { return toArr(isStr(val) ? new Select(val) : val) } return exports })({})) /* ------------------------------ $attr ------------------------------ */ var $attr = (_licia.$attr = (function (exports) { /* Element attribute manipulation. * * Get the value of an attribute for the first element in the set of matched elements. * * |Name |Desc | * |-------|--------------------------------| * |element|Elements to manipulate | * |name |Attribute name | * |return |Attribute value of first element| * * Set one or more attributes for the set of matched elements. * * |Name |Desc | * |-------|----------------------| * |element|Elements to manipulate| * |name |Attribute name | * |val |Attribute value | * * |Name |Desc | * |----------|--------------------------------------| * |element |Elements to manipulate | * |attributes|Object of attribute-value pairs to set| * * ### remove * * Remove an attribute from each element in the set of matched elements. * * |Name |Desc | * |-------|----------------------| * |element|Elements to manipulate| * |name |Attribute name | */ /* example * $attr('#test', 'attr1', 'test'); * $attr('#test', 'attr1'); // -> test * $attr.remove('#test', 'attr1'); * $attr('#test', { * attr1: 'test', * attr2: 'test' * }); */ /* typescript * export declare namespace $attr { * function remove(element: $safeEls.El, name: string): void; * } * export declare function $attr( * element: $safeEls.El, * name: string, * value: string * ): void; * export declare function $attr( * element: $safeEls.El, * attributes: types.PlainObj * ): void; * export declare function $attr(element: $safeEls.El, name: string): string; */ /* dependencies * toArr isObj isStr each isUndef $safeEls types */ exports = function (els, name, val) { els = $safeEls(els) var isGetter = isUndef(val) && isStr(name) if (isGetter) return getAttr(els[0], name) var attrs = name if (!isObj(attrs)) { attrs = {} attrs[name] = val } setAttr(els, attrs) } exports.remove = function (els, names) { els = $safeEls(els) names = toArr(names) each(els, function (node) { each(names, function (name) { node.removeAttribute(name) }) }) } function getAttr(el, name) { return el.getAttribute(name) } function setAttr(els, attrs) { each(els, function (el) { each(attrs, function (val, name) { el.setAttribute(name, val) }) }) } return exports })({})) /* ------------------------------ $css ------------------------------ */ var $css = (_licia.$css = (function (exports) { /* Element css manipulation. * * Get the computed style properties for the first element in the set of matched elements. * * |Name |Desc | * |-------|--------------------------| * |element|Elements to manipulate | * |name |Property name | * |return |Css value of first element| * * Set one or more CSS properties for the set of matched elements. * * |Name |Desc | * |-------|----------------------| * |element|Elements to manipulate| * |name |Property name | * |val |Css value | * * |Name |Desc | * |----------|--------------------------------| * |element |Elements to manipulate | * |properties|Object of css-value pairs to set| */ /* example * $css('#test', { * color: '#fff', * background: 'black', * opacity: 0.5 * }); * $css('#test', 'display', 'block'); * $css('#test', 'color'); // -> #fff */ /* typescript * export declare function $css(element: $safeEls.El, name: string): string; * export declare function $css( * element: $safeEls.El, * name: string, * val: string * ): void; * export declare function $css( * element: $safeEls.El, * properties: types.PlainObj * ): void; */ /* dependencies * isStr isObj kebabCase isUndef contain isNum $safeEls prefix each types */ exports = function (nodes, name, val) { nodes = $safeEls(nodes) var isGetter = isUndef(val) && isStr(name) if (isGetter) return getCss(nodes[0], name) var css = name if (!isObj(css)) { css = {} css[name] = val } setCss(nodes, css) } function getCss(node, name) { return node.style[prefix(name)] || getComputedStyle(node, '').getPropertyValue(name) } function setCss(nodes, css) { each(nodes, function (node) { var cssText = ';' each(css, function (val, key) { key = prefix.dash(key) cssText += key + ':' + addPx(key, val) + ';' }) node.style.cssText += cssText }) } var cssNumProps = [ 'column-count', 'columns', 'font-weight', 'line-weight', 'opacity', 'z-index', 'zoom', ] function addPx(key, val) { var needPx = isNum(val) && !contain(cssNumProps, kebabCase(key)) return needPx ? val + 'px' : val } return exports })({})) /* ------------------------------ $data ------------------------------ */ var $data = (_licia.$data = (function (exports) { /* Wrapper of $attr, adds data- prefix to keys. */ /* example * $data('#test', 'attr1', 'eustia'); */ /* typescript * export declare function $data( * element: $safeEls.El, * name: string, * value: string * ): void; * export declare function $data( * element: $safeEls.El, * attributes: types.PlainObj * ): void; * export declare function $data(element: $safeEls.El, name: string): string; */ /* eslint-disable no-unused-vars */ /* dependencies * $attr isStr isObj each $safeEls types */ exports = function (nodes, name, val) { var dataName = name if (isStr(name)) dataName = 'data-' + name if (isObj(name)) { dataName = {} each(name, function (val, key) { dataName['data-' + key] = val }) } return $attr(nodes, dataName, val) } return exports })({})) /* ------------------------------ $insert ------------------------------ */ var $insert = (_licia.$insert = (function (exports) { /* Insert html on different position. * * ### before * * Insert content before elements. * * ### after * * Insert content after elements. * * ### prepend * * Insert content to the beginning of elements. * * ### append * * Insert content to the end of elements. * * |Name |Desc | * |-------|-----------------------| * |element|Elements to manipulate | * |content|Html strings or element| */ /* example * //
* $insert.before('#test', '
licia
'); * // ->
licia
* $insert.after('#test', '
licia
'); * // ->
licia
* $insert.prepend('#test', '
licia
'); * // ->
licia
* $insert.append('#test', '
licia
'); * // ->
licia
*/ /* typescript * export declare namespace $insert { * type IInsert = (element: $safeEls.El, content: string | Element) => void; * } * export declare const $insert: { * before: $insert.IInsert; * after: $insert.IInsert; * append: $insert.IInsert; * prepend: $insert.IInsert; * }; */ /* dependencies * each $safeEls isStr */ exports = { before: insertFactory('beforebegin'), after: insertFactory('afterend'), append: insertFactory('beforeend'), prepend: insertFactory('afterbegin'), } function insertFactory(type) { return function (nodes, val) { nodes = $safeEls(nodes) each(nodes, function (node) { if (isStr(val)) { node.insertAdjacentHTML(type, val) } else { var parentNode = node.parentNode switch (type) { case 'beforebegin': if (parentNode) { parentNode.insertBefore(val, node) } break case 'afterend': if (parentNode) { parentNode.insertBefore(val, node.nextSibling) } break case 'beforeend': node.appendChild(val) break case 'afterbegin': node.prepend(val) break } } }) } } return exports })({})) /* ------------------------------ $offset ------------------------------ */ var $offset = (_licia.$offset = (function (exports) { /* Get the position of the element in document. * * |Name |Desc | * |-------|----------------------| * |element|Elements to get offset| * |return |Element position | */ /* example * $offset('#test'); // -> {left: 0, top: 0, width: 0, height: 0} */ /* typescript * export declare namespace $offset { * interface IOffset { * left: number; * top: number; * width: number; * height: number; * } * } * export declare function $offset(element: $safeEls.El): $offset.IOffset; */ /* dependencies * $safeEls */ exports = function (els) { els = $safeEls(els) var el = els[0] var clientRect = el.getBoundingClientRect() return { left: clientRect.left + window.pageXOffset, top: clientRect.top + window.pageYOffset, width: Math.round(clientRect.width), height: Math.round(clientRect.height), } } return exports })({})) /* ------------------------------ $property ------------------------------ */ var $property = (_licia.$property = (function (exports) { /* Element property html, text, val getter and setter. * * ### html * * Get the HTML contents of the first element in the set of matched elements or * set the HTML contents of every matched element. * * ### text * * Get the combined text contents of each element in the set of matched * elements, including their descendants, or set the text contents of the * matched elements. * * ### val * * Get the current value of the first element in the set of matched elements or * set the value of every matched element. */ /* example * $property.html('#test', 'licia'); * $property.html('#test'); // -> licia */ /* typescript * export declare namespace $property { * interface IProperty { * (element: $safeEls.El, value: string): void; * (element: $safeEls.El): string; * } * } * export declare const $property: { * html: $property.IProperty; * val: $property.IProperty; * text: $property.IProperty; * }; */ /* dependencies * isUndef each $safeEls */ exports = { html: propFactory('innerHTML'), text: propFactory('textContent'), val: propFactory('value'), } function propFactory(name) { return function (nodes, val) { nodes = $safeEls(nodes) var node = nodes[0] if (isUndef(val)) { return node ? node[name] : '' } if (!node) return each(nodes, function (node) { node[name] = val }) } } return exports })({})) /* ------------------------------ $remove ------------------------------ */ var $remove = (_licia.$remove = (function (exports) { /* Remove the set of matched elements from the DOM. * * |Name |Desc | * |-------|------------------| * |element|Elements to delete| */ /* example * $remove('#test'); */ /* typescript * export declare function $remove(element: $safeEls.El); */ /* dependencies * each $safeEls */ exports = function (els) { els = $safeEls(els) each(els, function (el) { var parent = el.parentNode if (parent) parent.removeChild(el) }) } return exports })({})) /* ------------------------------ $show ------------------------------ */ var $show = (_licia.$show = (function (exports) { /* Show elements. * * |Name |Desc | * |-------|----------------| * |element|Elements to show| */ /* example * $show('#test'); */ /* typescript * export declare function $show(element: $safeEls.El): void; */ /* dependencies * each $safeEls */ exports = function (els) { els = $safeEls(els) each(els, function (el) { if (isHidden(el)) { el.style.display = getDefDisplay(el.nodeName) } }) } function isHidden(el) { return getComputedStyle(el, '').getPropertyValue('display') == 'none' } var elDisplay = {} function getDefDisplay(elName) { var el, display if (!elDisplay[elName]) { el = document.createElement(elName) document.documentElement.appendChild(el) display = getComputedStyle(el, '').getPropertyValue('display') el.parentNode.removeChild(el) display == 'none' && (display = 'block') elDisplay[elName] = display } return elDisplay[elName] } return exports })({})) /* ------------------------------ delegate ------------------------------ */ var delegate = (_licia.delegate = (function (exports) { /* Event delegation. * * ### add * * Add event delegation. * * |Name |Desc | * |--------|--------------| * |el |Parent element| * |type |Event type | * |selector|Match selector| * |cb |Event callback| * * ### remove * * Remove event delegation. */ /* example * const container = document.getElementById('container'); * function clickHandler() { * // Do something... * } * delegate.add(container, 'click', '.children', clickHandler); * delegate.remove(container, 'click', '.children', clickHandler); */ /* typescript * export declare const delegate: { * add(el: Element, type: string, selector: string, cb: types.AnyFn): void; * remove(el: Element, type: string, selector: string, cb: types.AnyFn): void; * }; */ /* dependencies * Class contain types */ function retTrue() { return true } function retFalse() { return false } function trigger(e) { var handlers = this.events[e.type] var handler var handlerQueue = formatHandlers.call(this, e, handlers) e = new exports.Event(e) var i = 0, j, matched, ret while ((matched = handlerQueue[i++]) && !e.isPropagationStopped()) { e.curTarget = matched.el j = 0 while ((handler = matched.handlers[j++]) && !e.isImmediatePropagationStopped()) { ret = handler.handler.apply(matched.el, [e]) if (ret === false) { e.preventDefault() e.stopPropagation() } } } } function formatHandlers(e, handlers) { var current = e.target var ret = [] var delegateCount = handlers.delegateCount var selector var matches var handler var i if (current.nodeType) { for (; current !== this; current = current.parentNode || this) { matches = [] for (i = 0; i < delegateCount; i++) { handler = handlers[i] selector = handler.selector + ' ' if (matches[selector] === undefined) { matches[selector] = contain(this.querySelectorAll(selector), current) } if (matches[selector]) matches.push(handler) } if (matches.length) ret.push({ el: current, handlers: matches, }) } } if (delegateCount < handlers.length) { ret.push({ el: this, handlers: handlers.slice(delegateCount), }) } return ret } exports = { add: function (el, type, selector, fn) { var handler = { selector: selector, handler: fn, } var handlers if (!el.events) el.events = {} if (!(handlers = el.events[type])) { handlers = el.events[type] = [] handlers.delegateCount = 0 el.addEventListener( type, function () { trigger.apply(el, arguments) }, false ) } selector ? handlers.splice(handlers.delegateCount++, 0, handler) : handlers.push(handler) }, remove: function (el, type, selector, fn) { var events = el.events if (!events || !events[type]) return var handlers = events[type] var i = handlers.length var handler while (i--) { handler = handlers[i] if ((!selector || handler.selector == selector) && handler.handler == fn) { handlers.splice(i, 1) if (handler.selector) { handlers.delegateCount-- } } } }, Event: Class({ className: 'Event', initialize: function Event(e) { this.origEvent = e }, isDefaultPrevented: retFalse, isPropagationStopped: retFalse, isImmediatePropagationStopped: retFalse, preventDefault: function () { var e = this.origEvent this.isDefaultPrevented = retTrue if (e && e.preventDefault) e.preventDefault() }, stopPropagation: function () { var e = this.origEvent this.isPropagationStopped = retTrue if (e && e.stopPropagation) e.stopPropagation() }, stopImmediatePropagation: function () { var e = this.origEvent this.isImmediatePropagationStopped = retTrue if (e && e.stopImmediatePropagation) e.stopImmediatePropagation() this.stopPropagation() }, }), } return exports })({})) /* ------------------------------ $event ------------------------------ */ var $event = (_licia.$event = (function (exports) { /* bind events to certain dom elements. */ /* example * function clickHandler() { * // Do something... * } * $event.on('#test', 'click', clickHandler); * $event.off('#test', 'click', clickHandler); */ /* typescript * export declare const $event: { * on( * element: $safeEls.El, * event: string, * selector: string, * handler: types.AnyFn * ): void; * on(element: $safeEls.El, event: string, handler: types.AnyFn): void; * off( * element: $safeEls.El, * event: string, * selector: string, * handler: types.AnyFn * ): void; * off(element: $safeEls.El, event: string, handler: types.AnyFn): void; * }; */ /* dependencies * delegate isUndef $safeEls each types */ exports = { on: eventFactory('add'), off: eventFactory('remove'), } function eventFactory(type) { return function (nodes, event, selector, handler) { nodes = $safeEls(nodes) if (isUndef(handler)) { handler = selector selector = undefined } each(nodes, function (node) { delegate[type](node, event, selector, handler) }) } } return exports })({})) /* ------------------------------ some ------------------------------ */ var some = (_licia.some = (function (exports) { /* Check if predicate return truthy for any element. * * |Name |Desc | * |---------|----------------------------------------------| * |obj |Collection to iterate over | * |predicate|Function to invoked per iteration | * |ctx |Predicate context | * |return |True if any element passes the predicate check| */ /* example * some([2, 5], function(val) { * return val % 2 === 0; * }); // -> true */ /* typescript * export declare function some( * list: types.List, * iterator?: types.ListIterator, * context?: any * ): boolean; * export declare function some( * object: types.Dictionary, * iterator?: types.ObjectIterator, * context?: any * ): boolean; */ /* dependencies * safeCb isArrLike keys types */ exports = function (obj, predicate, ctx) { predicate = safeCb(predicate, ctx) var _keys = !isArrLike(obj) && keys(obj) var len = (_keys || obj).length for (var i = 0; i < len; i++) { var key = _keys ? _keys[i] : i if (predicate(obj[key], key, obj)) return true } return false } return exports })({})) /* ------------------------------ $class ------------------------------ */ var $class = (_licia.$class = (function (exports) { /* Element class manipulations. * * ### add * * Add the specified class(es) to each element in the set of matched elements. * * |Name |Desc | * |-------|----------------------| * |element|Elements to manipulate| * |names |Classes to add | * * ### has * * Determine whether any of the matched elements are assigned the given class. * * |Name |Desc | * |-------|-------------------------------------| * |element|Elements to manipulate | * |name |Class name | * |return |True if elements has given class name| * * ### toggle * * Add or remove one or more classes from each element in the set of matched elements, depending on either the class's presence or the value of the state argument. * * |Name |Desc | * |-------|----------------------| * |element|Elements to manipulate| * |name |Class name to toggle | * * ### remove * * Remove a single class, multiple classes, or all classes from each element in the set of matched elements. * * |Name |Desc | * |-------|----------------------| * |element|Elements to manipulate| * |name |Class names to remove | */ /* example * $class.add('#test', 'class1'); * $class.add('#test', ['class1', 'class2']); * $class.has('#test', 'class1'); // -> true * $class.remove('#test', 'class1'); * $class.has('#test', 'class1'); // -> false * $class.toggle('#test', 'class1'); * $class.has('#test', 'class1'); // -> true */ /* typescript * export declare const $class: { * add(element: $safeEls.El, name: string | string[]): void; * has(element: $safeEls.El, name: string): boolean; * toggle(element: $safeEls.El, name: string): void; * remove(element: $safeEls.El, name: string): void; * }; */ /* dependencies * toArr some $safeEls isStr each */ exports = { add: function (els, name) { els = $safeEls(els) var names = safeName(name) each(els, function (el) { var classList = [] each(names, function (name) { if (!exports.has(el, name)) classList.push(name) }) if (classList.length !== 0) { el.className += (el.className ? ' ' : '') + classList.join(' ') } }) }, has: function (els, name) { els = $safeEls(els) var regName = new RegExp('(^|\\s)' + name + '(\\s|$)') return some(els, function (el) { return regName.test(el.className) }) }, toggle: function (els, name) { els = $safeEls(els) each(els, function (el) { if (!exports.has(el, name)) return exports.add(el, name) exports.remove(el, name) }) }, remove: function (els, name) { els = $safeEls(els) var names = safeName(name) each(els, function (el) { each(names, function (name) { el.classList.remove(name) }) }) }, } function safeName(name) { return isStr(name) ? name.split(/\s+/) : toArr(name) } return exports })({})) /* ------------------------------ $ ------------------------------ */ _licia.$ = (function (exports) { /* jQuery like style dom manipulator. * * ### Available methods * * offset, hide, show, first, last, get, eq, on, off, html, text, val, css, attr, * data, rmAttr, remove, addClass, rmClass, toggleClass, hasClass, append, prepend, * before, after */ /* example * const $btn = $('#btn'); * $btn.html('eustia'); * $btn.addClass('btn'); * $btn.show(); * $btn.on('click', function() { * // Do something... * }); */ /* typescript * export declare namespace $ { * class $ extends Select { * find(selector: string): $; * each(fn: types.AnyFn): $; * offset(): $offset.IOffset; * hide(): $; * show(): $; * first(): $; * last(): $; * get(index: number): Element; * eq(index: number): $; * on(event: string, selector: string, handler: types.AnyFn): $; * on(event: string, handler: types.AnyFn): $; * off(event: string, selector: string, handler: types.AnyFn): $; * off(event: string, handler: types.AnyFn): $; * html(): string; * html(value: string): $; * text(): string; * text(value: string): $; * val(): string; * val(value: string): $; * css(name: string): string; * css(name: string, value: string): $; * css(properties: types.PlainObj): $; * attr(name: string): string; * attr(name: string, value: string): $; * attr(attributes: types.PlainObj): $; * data(name: string): string; * data(name: string, value: string): $; * data(attributes: types.PlainObj): $; * rmAttr(name: string): $; * remove(): $; * addClass(name: string | string[]): $; * rmClass(name: string): $; * toggleClass(name: string): $; * hasClass(name: string): boolean; * parent(): $; * append(content: string | Element): $; * prepend(content: string | Element): $; * before(content: string | Element): $; * after(content: string | Element): $; * } * } * declare function $(selector: string | Element | Document): $.$; */ /* dependencies * Select $offset $show $css $attr $property last $remove $data $event $class $insert isUndef isStr types */ exports = function (selector) { return new Select(selector) } Select.methods({ offset: function () { return $offset(this) }, hide: function () { return this.css('display', 'none') }, show: function () { $show(this) return this }, first: function () { return exports(this[0]) }, last: function () { return exports(last(this)) }, get: function (idx) { return this[idx] }, eq: function (idx) { return exports(this[idx]) }, on: function (event, selector, handler) { $event.on(this, event, selector, handler) return this }, off: function (event, selector, handler) { $event.off(this, event, selector, handler) return this }, html: function (val) { var result = $property.html(this, val) if (isUndef(val)) return result return this }, text: function (val) { var result = $property.text(this, val) if (isUndef(val)) return result return this }, val: function (val) { var result = $property.val(this, val) if (isUndef(val)) return result return this }, css: function (name, val) { var result = $css(this, name, val) if (isGetter(name, val)) return result return this }, attr: function (name, val) { var result = $attr(this, name, val) if (isGetter(name, val)) return result return this }, data: function (name, val) { var result = $data(this, name, val) if (isGetter(name, val)) return result return this }, rmAttr: function (name) { $attr.remove(this, name) return this }, remove: function () { $remove(this) return this }, addClass: function (name) { $class.add(this, name) return this }, rmClass: function (name) { $class.remove(this, name) return this }, toggleClass: function (name) { $class.toggle(this, name) return this }, hasClass: function (name) { return $class.has(this, name) }, parent: function () { return exports(this[0].parentNode) }, append: function (val) { $insert.append(this, val) return this }, prepend: function (val) { $insert.prepend(this, val) return this }, before: function (val) { $insert.before(this, val) return this }, after: function (val) { $insert.after(this, val) return this }, }) var isGetter = function (name, val) { return isUndef(val) && isStr(name) } return exports })({}) /* ------------------------------ h ------------------------------ */ _licia.h = (function (exports) { /* Create html with JavaScript. * * |Name |Desc | * |--------|---------------| * |tag |Tag name | * |attrs |Attributes | * |...child|Children | * |return |Created element| */ /* example * const el = h( * 'div#test.title', * { * onclick: function() {}, * title: 'test' * }, * 'inner text' * ); * document.body.appendChild(el); */ /* typescript * export declare function h( * tag: string, * attrs?: types.PlainObj, * ...child: Array * ): HTMLElement; */ /* dependencies * isEl isStr startWith $class $css each isFn types */ exports = function (tag, attrs) { for ( var _len = arguments.length, children = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++ ) { children[_key - 2] = arguments[_key] } if (isEl(attrs) || isStr(attrs)) { children.unshift(attrs) attrs = null } if (!attrs) attrs = {} var _parseTag = parseTag(tag), tagName = _parseTag.tagName, id = _parseTag.id, classes = _parseTag.classes var el = document.createElement(tagName) if (id) el.setAttribute('id', id) $class.add(el, classes) each(children, function (child) { if (isStr(child)) { el.appendChild(document.createTextNode(child)) } else if (isEl(child)) { el.appendChild(child) } }) each(attrs, function (val, key) { if (isStr(val)) { el.setAttribute(key, val) } else if (isFn(val) && startWith(key, 'on')) { el.addEventListener(key.slice(2), val, false) } else if (key === 'style') { $css(el, val) } }) return el } function parseTag(tag) { var tagName = 'div' var id = '' var classes = [] var words = [] var word = '' for (var i = 0, len = tag.length; i < len; i++) { var c = tag[i] if (c === '#' || c === '.') { words.push(word) word = c } else { word += c } } words.push(word) for (var _i = 0, _len2 = words.length; _i < _len2; _i++) { word = words[_i] if (!word) continue if (startWith(word, '#')) { id = word.slice(1) } else if (startWith(word, '.')) { classes.push(word.slice(1)) } else { tagName = word } } return { tagName: tagName, id: id, classes: classes, } } return exports })({}) /* ------------------------------ root ------------------------------ */ _licia.root = (function (exports) { /* Root object reference, `global` in nodeJs, `window` in browser. */ /* typescript * export declare const root: any; */ /* dependencies * isBrowser */ exports = isBrowser ? window : global return exports })({}) /* ------------------------------ toBool ------------------------------ */ _licia.toBool = (function (exports) { /* Convert value to a boolean. * * |Name |Desc | * |------|-----------------| * |val |Value to convert | * |return|Converted boolean| */ /* example * toBool(true); // -> true * toBool(null); // -> false * toBool(1); // -> true * toBool(0); // -> false * toBool('0'); // -> false * toBool('1'); // -> true * toBool('false'); // -> false */ /* typescript * export declare function toBool(val: any): boolean; */ /* dependencies * isStr */ exports = function (val) { if (isStr(val)) { val = val.toLowerCase() return val !== '0' && val !== '' && val !== 'false' } return !!val } return exports })({}) return _licia }) let domHighlighter let highlightConfig let isCssLoaded = false let $container let isHighlighterInited = false const showInfo = _licia.cssSupports('clip-path', 'polygon(50% 0px, 0px 100%, 100% 100%)') const hasTouchSupport = 'ontouchstart' in _licia.root function initDomHighlighter() { if (isHighlighterInited) { return } let container = _licia.h('div', { class: '__chobitsu-hide__', style: { all: 'initial', }, }) $container = _licia.$(container) document.documentElement.appendChild(container) let domHighlighterContainer = null let shadowRoot = null if (container.attachShadow) { shadowRoot = container.attachShadow({ mode: 'open' }) } else if (container.createShadowRoot) { shadowRoot = container.createShadowRoot() } if (shadowRoot) { if (typeof GM_getResourceText == 'undefined') { GM.getResourceText = GM_getResourceText = async function (aResourceName) { let res = await (await fetch(await GM.getResourceUrl(aResourceName))).text() let saveRes = await GM.getValue(aResourceName) if (typeof saveRes === 'undefined') { GM.setValue(aResourceName, res) } else { return saveRes } return res } } // console.log('111111111', GM.getResourceText); // console.log('222222222', GM_getResourceText); const css = GM_getResourceText('lunaDomHighlighterCSS').replace( '/*# sourceMappingURL=luna-dom-highlighter.css.map*/', '' ) // console.log(css); const style = document.createElement('style') style.textContent = css style.type = 'text/css' shadowRoot.appendChild(style) domHighlighterContainer = document.createElement('div') shadowRoot.appendChild(domHighlighterContainer) } else { domHighlighterContainer = document.createElement('div') container.appendChild(domHighlighterContainer) if (!isCssLoaded) { _licia.evalCss(css) isCssLoaded = true } } highlightConfig = { showRulers: false, showExtensionLines: false, contrastAlgorithm: 'aa', showInfo: showInfo, showStyles: true, showAccessibilityInfo: false, colorFormat: 'hex', contentColor: 'rgba(111, 168, 220, .66)', paddingColor: 'rgba(147, 196, 125, .55)', borderColor: 'rgba(255, 229, 153, .66)', marginColor: 'rgba(246, 178, 107, .66)', monitorResize: _licia.toBool(_licia.root.ResizeObserver), } console.log(highlightConfig) domHighlighter = new LunaDomHighlighter(domHighlighterContainer, highlightConfig) window.addEventListener('resize', resizeHandler) isHighlighterInited = true } const viewportSize = _licia.h('div', { class: '__chobitsu-hide__', style: { position: 'fixed', right: 0, top: 0, background: '#fff', fontSize: 13, opacity: 0.5, padding: '4px 6px', }, }) let showViewportSizeOnResize = false function resizeHandler() { if (!showViewportSizeOnResize) return $viewportSize.text(`${window.innerWidth}px × ${window.innerHeight}px`) if (viewportSizeTimer) { clearTimeout(viewportSizeTimer) } else { document.documentElement.appendChild(viewportSize) } viewportSizeTimer = setTimeout(() => { $viewportSize.remove() viewportSizeTimer = null }, 1000) } const $viewportSize = _licia.$(viewportSize) let viewportSizeTimer function getElementFromPoint(e) { if (hasTouchSupport) { const touch = e.touches[0] || e.changedTouches[0] return document.elementFromPoint(touch.clientX, touch.clientY) } return document.elementFromPoint(e.clientX, e.clientY) } function isValidNode(node) { if (node.nodeType === 1) { const className = node.getAttribute('class') || '' if ( _licia.contain(className, '__chobitsu-hide__') || _licia.contain(className, 'html2canvas-container') ) { return false } } const isValid = !(node.nodeType === 3 && trim(node.nodeValue || '') === '') if (isValid && node.parentNode) { return isValidNode(node.parentNode) } return isValid } function moveListener(e) { const node = getElementFromPoint(e) if (!node || !isValidNode(node)) { return } if (node.nodeType !== 1 && node.nodeType !== 3) return _licia.defaults(highlightConfig, { contentColor: 'transparent', paddingColor: 'transparent', borderColor: 'transparent', marginColor: 'transparent', }) if (!showInfo) { _licia.extend(highlightConfig, { showInfo: false, }) } domHighlighter.highlight(node, highlightConfig) } function outListener() { domHighlighter.hide() } function clicklistener(event) { console.log(event.target) window.disableHighlight() $('#cancelhtml2canvas').text('正在生成截图...') html2canvas(event.target, { scale: 3, allowTaint: true, useCORS: true }).then((canvas) => { canvas.toBlob(function (blob) { let url = window.URL.createObjectURL(blob) window.open(url) setTimeout(() => { document.onkeydown = window.keydown_listener }, 0); $('#tryhtml2canvas').show() $('#cancelhtml2canvas').hide() }) }) } function addEvent(type, listener) { document.documentElement.addEventListener(type, listener, true) } function removeEvent(type, listener) { document.documentElement.removeEventListener(type, listener, true) } window.enableHighlight = function () { initDomHighlighter() addEvent('mousemove', moveListener) addEvent('mouseout', outListener) addEvent('click', clicklistener) } window.disableHighlight = function () { if (isHighlighterInited) { domHighlighter.destroy() $container.remove() window.removeEventListener('resize', resizeHandler) removeEvent('mousemove', moveListener) removeEvent('mouseout', outListener) removeEvent('click', clicklistener) isHighlighterInited = false } } window.captureHTML = () => { console.log('captureHTML...') // let handle = (event) => { // document.querySelector('html').removeEventListener('click', handle) // console.log(event.target) // html2canvas(event.target, { scale: 3, allowTaint: true, useCORS: true }).then((canvas) => { // canvas.toBlob(function (blob) { // let url = window.URL.createObjectURL(blob) // window.open(url) // $('#tryhtml2canvas').show() // }) // }) // } // setTimeout(() => { // document.querySelector('html').addEventListener('click', handle) // }, 0) setTimeout(() => { window.keydown_listener = document.onkeydown document.onkeydown = (e) => { let keyNum = window.event ? e.keyCode : e.which console.log('按键:', keyNum) if (keyNum === 27) { window.disableHighlight() setTimeout(() => { document.onkeydown = window.keydown_listener }, 0); $('#tryhtml2canvas').show() $('#cancelhtml2canvas').hide() } } window.enableHighlight() }, 0) $('#cancelhtml2canvas').text('按 ESC 取消截图') $('#cancelhtml2canvas').show() $('#tryhtml2canvas').hide() } let capturediv = document.createElement('div') capturediv.innerHTML = `
Try html2canvas
` document.body.appendChild(capturediv) let canceldiv = document.createElement('div') canceldiv.innerHTML = ` ` document.body.appendChild(canceldiv) let tryhtml2canvasE = capturediv.querySelector('#tryhtml2canvas') tryhtml2canvasE.onmouseenter = () => { tryhtml2canvasE.style.opacity = 1 } tryhtml2canvasE.onmouseleave = () => { tryhtml2canvasE.style.opacity = 0.7 } let isDragging = false let startX, startY, offsetX, offsetY const onMouseMove = (event) => { if (!isDragging) return console.log("onMouseMove") const currentX = event.clientX const currentY = event.clientY const dx = currentX - startX const dy = currentY - startY if (Math.abs(dx) > 5 || Math.abs(dy) > 5) { tryhtml2canvasE.style.left = `${currentX - offsetX}px` tryhtml2canvasE.style.top = `${currentY - offsetY}px` tryhtml2canvasE.removeEventListener('click', window.captureHTML) } } const onMouseDown = (event) => { console.log("onMouseDown") isDragging = true startX = event.clientX startY = event.clientY offsetX = startX - tryhtml2canvasE.getBoundingClientRect().left offsetY = startY - tryhtml2canvasE.getBoundingClientRect().top tryhtml2canvasE.style.cursor = 'grabbing' document.addEventListener('mousemove', onMouseMove) document.addEventListener('mouseup', onMouseUp) } const onMouseUp = (event) => { if (isDragging) { console.log("onMouseUp") isDragging = false tryhtml2canvasE.style.cursor = 'pointer' setTimeout(() => { tryhtml2canvasE.addEventListener('click', window.captureHTML) }, 0); document.removeEventListener('mousemove', onMouseMove) document.removeEventListener('mouseup', onMouseUp) } } tryhtml2canvasE.addEventListener('mousedown', onMouseDown) tryhtml2canvasE.addEventListener('click', window.captureHTML) })()