mui.js 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456
  1. /**
  2. * MUI核心JS
  3. * @type _L4.$|Function
  4. */
  5. var mui = (function(document, undefined) {
  6. var readyRE = /complete|loaded|interactive/;
  7. var idSelectorRE = /^#([\w-]+)$/;
  8. var classSelectorRE = /^\.([\w-]+)$/;
  9. var tagSelectorRE = /^[\w-]+$/;
  10. var translateRE = /translate(?:3d)?\((.+?)\)/;
  11. var translateMatrixRE = /matrix(3d)?\((.+?)\)/;
  12. var $ = function(selector, context) {
  13. context = context || document;
  14. if (!selector)
  15. return wrap();
  16. if (typeof selector === 'object')
  17. if ($.isArrayLike(selector)) {
  18. return wrap($.slice.call(selector), null);
  19. } else {
  20. return wrap([selector], null);
  21. }
  22. if (typeof selector === 'function')
  23. return $.ready(selector);
  24. if (typeof selector === 'string') {
  25. try {
  26. selector = selector.trim();
  27. if (idSelectorRE.test(selector)) {
  28. var found = document.getElementById(RegExp.$1);
  29. return wrap(found ? [found] : []);
  30. }
  31. return wrap($.qsa(selector, context), selector);
  32. } catch (e) {}
  33. }
  34. return wrap();
  35. };
  36. var wrap = function(dom, selector) {
  37. dom = dom || [];
  38. Object.setPrototypeOf(dom, $.fn);
  39. dom.selector = selector || '';
  40. return dom;
  41. };
  42. $.uuid = 0;
  43. $.data = {};
  44. /**
  45. * extend(simple)
  46. * @param {type} target
  47. * @param {type} source
  48. * @param {type} deep
  49. * @returns {unresolved}
  50. */
  51. $.extend = function() { //from jquery2
  52. var options, name, src, copy, copyIsArray, clone,
  53. target = arguments[0] || {},
  54. i = 1,
  55. length = arguments.length,
  56. deep = false;
  57. if (typeof target === "boolean") {
  58. deep = target;
  59. target = arguments[i] || {};
  60. i++;
  61. }
  62. if (typeof target !== "object" && !$.isFunction(target)) {
  63. target = {};
  64. }
  65. if (i === length) {
  66. target = this;
  67. i--;
  68. }
  69. for (; i < length; i++) {
  70. if ((options = arguments[i]) != null) {
  71. for (name in options) {
  72. src = target[name];
  73. copy = options[name];
  74. if (target === copy) {
  75. continue;
  76. }
  77. if (deep && copy && ($.isPlainObject(copy) || (copyIsArray = $.isArray(copy)))) {
  78. if (copyIsArray) {
  79. copyIsArray = false;
  80. clone = src && $.isArray(src) ? src : [];
  81. } else {
  82. clone = src && $.isPlainObject(src) ? src : {};
  83. }
  84. target[name] = $.extend(deep, clone, copy);
  85. } else if (copy !== undefined) {
  86. target[name] = copy;
  87. }
  88. }
  89. }
  90. }
  91. return target;
  92. };
  93. /**
  94. * mui noop(function)
  95. */
  96. $.noop = function() {};
  97. /**
  98. * mui slice(array)
  99. */
  100. $.slice = [].slice;
  101. /**
  102. * mui filter(array)
  103. */
  104. $.filter = [].filter;
  105. $.type = function(obj) {
  106. return obj == null ? String(obj) : class2type[{}.toString.call(obj)] || "object";
  107. };
  108. /**
  109. * mui isArray
  110. */
  111. $.isArray = Array.isArray ||
  112. function(object) {
  113. return object instanceof Array;
  114. };
  115. /**
  116. * mui isArrayLike
  117. * @param {Object} obj
  118. */
  119. $.isArrayLike = function(obj) {
  120. var length = !!obj && "length" in obj && obj.length;
  121. var type = $.type(obj);
  122. if (type === "function" || $.isWindow(obj)) {
  123. return false;
  124. }
  125. return type === "array" || length === 0 ||
  126. typeof length === "number" && length > 0 && (length - 1) in obj;
  127. };
  128. /**
  129. * mui isWindow(需考虑obj为undefined的情况)
  130. */
  131. $.isWindow = function(obj) {
  132. return obj != null && obj === obj.window;
  133. };
  134. /**
  135. * mui isObject
  136. */
  137. $.isObject = function(obj) {
  138. return $.type(obj) === "object";
  139. };
  140. /**
  141. * mui isPlainObject
  142. */
  143. $.isPlainObject = function(obj) {
  144. return $.isObject(obj) && !$.isWindow(obj) && Object.getPrototypeOf(obj) === Object.prototype;
  145. };
  146. /**
  147. * mui isEmptyObject
  148. * @param {Object} o
  149. */
  150. $.isEmptyObject = function(o) {
  151. for (var p in o) {
  152. if (p !== undefined) {
  153. return false;
  154. }
  155. }
  156. return true;
  157. };
  158. /**
  159. * mui isFunction
  160. */
  161. $.isFunction = function(value) {
  162. return $.type(value) === "function";
  163. };
  164. /**
  165. * mui querySelectorAll
  166. * @param {type} selector
  167. * @param {type} context
  168. * @returns {Array}
  169. */
  170. $.qsa = function(selector, context) {
  171. context = context || document;
  172. return $.slice.call(classSelectorRE.test(selector) ? context.getElementsByClassName(RegExp.$1) : tagSelectorRE.test(selector) ? context.getElementsByTagName(selector) : context.querySelectorAll(selector));
  173. };
  174. /**
  175. * ready(DOMContentLoaded)
  176. * @param {type} callback
  177. * @returns {_L6.$}
  178. */
  179. $.ready = function(callback) {
  180. if (readyRE.test(document.readyState)) {
  181. callback($);
  182. } else {
  183. document.addEventListener('DOMContentLoaded', function() {
  184. callback($);
  185. }, false);
  186. }
  187. return this;
  188. };
  189. /**
  190. * 将 fn 缓存一段时间后, 再被调用执行
  191. * 此方法为了避免在 ms 段时间内, 执行 fn 多次. 常用于 resize , scroll , mousemove 等连续性事件中;
  192. * 当 ms 设置为 -1, 表示立即执行 fn, 即和直接调用 fn 一样;
  193. * 调用返回函数的 stop 停止最后一次的 buffer 效果
  194. * @param {Object} fn
  195. * @param {Object} ms
  196. * @param {Object} context
  197. */
  198. $.buffer = function(fn, ms, context) {
  199. var timer;
  200. var lastStart = 0;
  201. var lastEnd = 0;
  202. var ms = ms || 150;
  203. function run() {
  204. if (timer) {
  205. timer.cancel();
  206. timer = 0;
  207. }
  208. lastStart = $.now();
  209. fn.apply(context || this, arguments);
  210. lastEnd = $.now();
  211. }
  212. return $.extend(function() {
  213. if (
  214. (!lastStart) || // 从未运行过
  215. (lastEnd >= lastStart && $.now() - lastEnd > ms) || // 上次运行成功后已经超过ms毫秒
  216. (lastEnd < lastStart && $.now() - lastStart > ms * 8) // 上次运行或未完成,后8*ms毫秒
  217. ) {
  218. run.apply(this, arguments);
  219. } else {
  220. if (timer) {
  221. timer.cancel();
  222. }
  223. timer = $.later(run, ms, null, $.slice.call(arguments));
  224. }
  225. }, {
  226. stop: function() {
  227. if (timer) {
  228. timer.cancel();
  229. timer = 0;
  230. }
  231. }
  232. });
  233. };
  234. /**
  235. * each
  236. * @param {type} elements
  237. * @param {type} callback
  238. * @returns {_L8.$}
  239. */
  240. $.each = function(elements, callback, hasOwnProperty) {
  241. if (!elements) {
  242. return this;
  243. }
  244. if (typeof elements.length === 'number') {
  245. [].every.call(elements, function(el, idx) {
  246. return callback.call(el, idx, el) !== false;
  247. });
  248. } else {
  249. for (var key in elements) {
  250. if (hasOwnProperty) {
  251. if (elements.hasOwnProperty(key)) {
  252. if (callback.call(elements[key], key, elements[key]) === false) return elements;
  253. }
  254. } else {
  255. if (callback.call(elements[key], key, elements[key]) === false) return elements;
  256. }
  257. }
  258. }
  259. return this;
  260. };
  261. $.focus = function(element) {
  262. if ($.os.ios) {
  263. setTimeout(function() {
  264. element.focus();
  265. }, 10);
  266. } else {
  267. element.focus();
  268. }
  269. };
  270. /**
  271. * trigger event
  272. * @param {type} element
  273. * @param {type} eventType
  274. * @param {type} eventData
  275. * @returns {_L8.$}
  276. */
  277. $.trigger = function(element, eventType, eventData) {
  278. element.dispatchEvent(new CustomEvent(eventType, {
  279. detail: eventData,
  280. bubbles: true,
  281. cancelable: true
  282. }));
  283. return this;
  284. };
  285. /**
  286. * getStyles
  287. * @param {type} element
  288. * @param {type} property
  289. * @returns {styles}
  290. */
  291. $.getStyles = function(element, property) {
  292. var styles = element.ownerDocument.defaultView.getComputedStyle(element, null);
  293. if (property) {
  294. return styles.getPropertyValue(property) || styles[property];
  295. }
  296. return styles;
  297. };
  298. /**
  299. * parseTranslate
  300. * @param {type} translateString
  301. * @param {type} position
  302. * @returns {Object}
  303. */
  304. $.parseTranslate = function(translateString, position) {
  305. var result = translateString.match(translateRE || '');
  306. if (!result || !result[1]) {
  307. result = ['', '0,0,0'];
  308. }
  309. result = result[1].split(",");
  310. result = {
  311. x: parseFloat(result[0]),
  312. y: parseFloat(result[1]),
  313. z: parseFloat(result[2])
  314. };
  315. if (position && result.hasOwnProperty(position)) {
  316. return result[position];
  317. }
  318. return result;
  319. };
  320. /**
  321. * parseTranslateMatrix
  322. * @param {type} translateString
  323. * @param {type} position
  324. * @returns {Object}
  325. */
  326. $.parseTranslateMatrix = function(translateString, position) {
  327. var matrix = translateString.match(translateMatrixRE);
  328. var is3D = matrix && matrix[1];
  329. if (matrix) {
  330. matrix = matrix[2].split(",");
  331. if (is3D === "3d")
  332. matrix = matrix.slice(12, 15);
  333. else {
  334. matrix.push(0);
  335. matrix = matrix.slice(4, 7);
  336. }
  337. } else {
  338. matrix = [0, 0, 0];
  339. }
  340. var result = {
  341. x: parseFloat(matrix[0]),
  342. y: parseFloat(matrix[1]),
  343. z: parseFloat(matrix[2])
  344. };
  345. if (position && result.hasOwnProperty(position)) {
  346. return result[position];
  347. }
  348. return result;
  349. };
  350. $.hooks = {};
  351. $.addAction = function(type, hook) {
  352. var hooks = $.hooks[type];
  353. if (!hooks) {
  354. hooks = [];
  355. }
  356. hook.index = hook.index || 1000;
  357. hooks.push(hook);
  358. hooks.sort(function(a, b) {
  359. return a.index - b.index;
  360. });
  361. $.hooks[type] = hooks;
  362. return $.hooks[type];
  363. };
  364. $.doAction = function(type, callback) {
  365. if ($.isFunction(callback)) { //指定了callback
  366. $.each($.hooks[type], callback);
  367. } else { //未指定callback,直接执行
  368. $.each($.hooks[type], function(index, hook) {
  369. return !hook.handle();
  370. });
  371. }
  372. };
  373. /**
  374. * setTimeout封装
  375. * @param {Object} fn
  376. * @param {Object} when
  377. * @param {Object} context
  378. * @param {Object} data
  379. */
  380. $.later = function(fn, when, context, data) {
  381. when = when || 0;
  382. var m = fn;
  383. var d = data;
  384. var f;
  385. var r;
  386. if (typeof fn === 'string') {
  387. m = context[fn];
  388. }
  389. f = function() {
  390. m.apply(context, $.isArray(d) ? d : [d]);
  391. };
  392. r = setTimeout(f, when);
  393. return {
  394. id: r,
  395. cancel: function() {
  396. clearTimeout(r);
  397. }
  398. };
  399. };
  400. $.now = Date.now || function() {
  401. return +new Date();
  402. };
  403. var class2type = {};
  404. $.each(['Boolean', 'Number', 'String', 'Function', 'Array', 'Date', 'RegExp', 'Object', 'Error'], function(i, name) {
  405. class2type["[object " + name + "]"] = name.toLowerCase();
  406. });
  407. if (window.JSON) {
  408. $.parseJSON = JSON.parse;
  409. }
  410. /**
  411. * $.fn
  412. */
  413. $.fn = {
  414. each: function(callback) {
  415. [].every.call(this, function(el, idx) {
  416. return callback.call(el, idx, el) !== false;
  417. });
  418. return this;
  419. }
  420. };
  421. /**
  422. * 兼容 AMD 模块
  423. **/
  424. if (typeof define === 'function' && define.amd) {
  425. define('mui', [], function() {
  426. return $;
  427. });
  428. }
  429. return $;
  430. })(document);
  431. //window.mui = mui;
  432. //'$' in window || (window.$ = mui);