UNPKG

amazeui

Version:

Sleek, intuitive, and powerful front-end framework for faster and easier web development.

608 lines (499 loc) 15.9 kB
'use strict'; var $ = require('jquery'); if (typeof $ === 'undefined') { throw new Error('Amaze UI 2.x requires jQuery :-(\n' + '\u7231\u4e0a\u4e00\u5339\u91ce\u9a6c\uff0c\u53ef\u4f60' + '\u7684\u5bb6\u91cc\u6ca1\u6709\u8349\u539f\u2026'); } var UI = $.AMUI || {}; var $win = $(window); var doc = window.document; var $html = $('html'); UI.VERSION = '{{VERSION}}'; UI.support = {}; UI.support.transition = (function() { var transitionEnd = (function() { // https://developer.mozilla.org/en-US/docs/Web/Events/transitionend#Browser_compatibility var element = doc.body || doc.documentElement; var transEndEventNames = { WebkitTransition: 'webkitTransitionEnd', MozTransition: 'transitionend', OTransition: 'oTransitionEnd otransitionend', transition: 'transitionend' }; for (var name in transEndEventNames) { if (element.style[name] !== undefined) { return transEndEventNames[name]; } } })(); return transitionEnd && {end: transitionEnd}; })(); UI.support.animation = (function() { var animationEnd = (function() { var element = doc.body || doc.documentElement; var animEndEventNames = { WebkitAnimation: 'webkitAnimationEnd', MozAnimation: 'animationend', OAnimation: 'oAnimationEnd oanimationend', animation: 'animationend' }; for (var name in animEndEventNames) { if (element.style[name] !== undefined) { return animEndEventNames[name]; } } })(); return animationEnd && {end: animationEnd}; })(); /* eslint-disable dot-notation */ UI.support.touch = ( ('ontouchstart' in window && navigator.userAgent.toLowerCase().match(/mobile|tablet/)) || (window.DocumentTouch && document instanceof window.DocumentTouch) || (window.navigator['msPointerEnabled'] && window.navigator['msMaxTouchPoints'] > 0) || // IE 10 (window.navigator['pointerEnabled'] && window.navigator['maxTouchPoints'] > 0) || // IE >=11 false); /* eslint-enable dot-notation */ // https://developer.mozilla.org/zh-CN/docs/DOM/MutationObserver UI.support.mutationobserver = (window.MutationObserver || window.WebKitMutationObserver || null); // https://github.com/Modernizr/Modernizr/blob/924c7611c170ef2dc502582e5079507aff61e388/feature-detects/forms/validation.js#L20 UI.support.formValidation = (typeof document.createElement('form'). checkValidity === 'function'); UI.utils = {}; /** * Debounce function * * @param {function} func Function to be debounced * @param {number} wait Function execution threshold in milliseconds * @param {bool} immediate Whether the function should be called at * the beginning of the delay instead of the * end. Default is false. * @description Executes a function when it stops being invoked for n seconds * @see _.debounce() http://underscorejs.org */ UI.utils.debounce = function(func, wait, immediate) { var timeout; return function() { var context = this; var args = arguments; var later = function() { timeout = null; if (!immediate) { func.apply(context, args); } }; var callNow = immediate && !timeout; clearTimeout(timeout); timeout = setTimeout(later, wait); if (callNow) { func.apply(context, args); } }; }; UI.utils.isInView = function(element, options) { var $element = $(element); var visible = !!($element.width() || $element.height()) && $element.css('display') !== 'none'; if (!visible) { return false; } var windowLeft = $win.scrollLeft(); var windowTop = $win.scrollTop(); var offset = $element.offset(); var left = offset.left; var top = offset.top; options = $.extend({topOffset: 0, leftOffset: 0}, options); return (top + $element.height() >= windowTop && top - options.topOffset <= windowTop + $win.height() && left + $element.width() >= windowLeft && left - options.leftOffset <= windowLeft + $win.width()); }; UI.utils.parseOptions = UI.utils.options = function(string) { if ($.isPlainObject(string)) { return string; } var start = (string ? string.indexOf('{') : -1); var options = {}; if (start != -1) { try { options = (new Function('', 'var json = ' + string.substr(start) + '; return JSON.parse(JSON.stringify(json));'))(); } catch (e) { } } return options; }; UI.utils.generateGUID = function(namespace) { var uid = namespace + '-' || 'am-'; do { uid += Math.random().toString(36).substring(2, 7); } while (document.getElementById(uid)); return uid; }; // @see https://davidwalsh.name/get-absolute-url UI.utils.getAbsoluteUrl = (function() { var a; return function(url) { if (!a) { a = document.createElement('a'); } a.href = url; return a.href; }; })(); /** * Plugin AMUI Component to jQuery * * @param {String} name - plugin name * @param {Function} Component - plugin constructor * @param {Object} [pluginOption] * @param {String} pluginOption.dataOptions * @param {Function} pluginOption.methodCall - custom method call * @param {Function} pluginOption.before * @param {Function} pluginOption.after * @since v2.4.1 */ UI.plugin = function UIPlugin(name, Component, pluginOption) { var old = $.fn[name]; pluginOption = pluginOption || {}; $.fn[name] = function(option) { var allArgs = Array.prototype.slice.call(arguments, 0); var args = allArgs.slice(1); var propReturn; var $set = this.each(function() { var $this = $(this); var dataName = 'amui.' + name; var dataOptionsName = pluginOption.dataOptions || ('data-am-' + name); var instance = $this.data(dataName); var options = $.extend({}, UI.utils.parseOptions($this.attr(dataOptionsName)), typeof option === 'object' && option); if (!instance && option === 'destroy') { return; } if (!instance) { $this.data(dataName, (instance = new Component(this, options))); } // custom method call if (pluginOption.methodCall) { pluginOption.methodCall.call($this, allArgs, instance); } else { // before method call pluginOption.before && pluginOption.before.call($this, allArgs, instance); if (typeof option === 'string') { propReturn = typeof instance[option] === 'function' ? instance[option].apply(instance, args) : instance[option]; } // after method call pluginOption.after && pluginOption.after.call($this, allArgs, instance); } }); return (propReturn === undefined) ? $set : propReturn; }; $.fn[name].Constructor = Component; // no conflict $.fn[name].noConflict = function() { $.fn[name] = old; return this; }; UI[name] = Component; }; // http://blog.alexmaccaw.com/css-transitions $.fn.emulateTransitionEnd = function(duration) { var called = false; var $el = this; $(this).one(UI.support.transition.end, function() { called = true; }); var callback = function() { if (!called) { $($el).trigger(UI.support.transition.end); } $el.transitionEndTimmer = undefined; }; this.transitionEndTimmer = setTimeout(callback, duration); return this; }; $.fn.redraw = function() { return this.each(function() { /* eslint-disable */ var redraw = this.offsetHeight; /* eslint-enable */ }); }; $.fn.transitionEnd = function(callback) { var endEvent = UI.support.transition.end; var dom = this; function fireCallBack(e) { callback.call(this, e); endEvent && dom.off(endEvent, fireCallBack); } if (callback && endEvent) { dom.on(endEvent, fireCallBack); } return this; }; $.fn.removeClassRegEx = function() { return this.each(function(regex) { var classes = $(this).attr('class'); if (!classes || !regex) { return false; } var classArray = []; classes = classes.split(' '); for (var i = 0, len = classes.length; i < len; i++) { if (!classes[i].match(regex)) { classArray.push(classes[i]); } } $(this).attr('class', classArray.join(' ')); }); }; // $.fn.alterClass = function(removals, additions) { var self = this; if (removals.indexOf('*') === -1) { // Use native jQuery methods if there is no wildcard matching self.removeClass(removals); return !additions ? self : self.addClass(additions); } var classPattern = new RegExp('\\s' + removals. replace(/\*/g, '[A-Za-z0-9-_]+'). split(' '). join('\\s|\\s') + '\\s', 'g'); self.each(function(i, it) { var cn = ' ' + it.className + ' '; while (classPattern.test(cn)) { cn = cn.replace(classPattern, ' '); } it.className = $.trim(cn); }); return !additions ? self : self.addClass(additions); }; // handle multiple browsers for requestAnimationFrame() // http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/ // https://github.com/gnarf/jquery-requestAnimationFrame UI.utils.rAF = (function() { return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || // if all else fails, use setTimeout function(callback) { return window.setTimeout(callback, 1000 / 60); // shoot for 60 fps }; })(); // handle multiple browsers for cancelAnimationFrame() UI.utils.cancelAF = (function() { return window.cancelAnimationFrame || window.webkitCancelAnimationFrame || window.mozCancelAnimationFrame || window.oCancelAnimationFrame || function(id) { window.clearTimeout(id); }; })(); // via http://davidwalsh.name/detect-scrollbar-width UI.utils.measureScrollbar = function() { if (document.body.clientWidth >= window.innerWidth) { return 0; } // if ($html.width() >= window.innerWidth) return; // var scrollbarWidth = window.innerWidth - $html.width(); var $measure = $('<div ' + 'style="width: 100px;height: 100px;overflow: scroll;' + 'position: absolute;top: -9999px;"></div>'); $(document.body).append($measure); var scrollbarWidth = $measure[0].offsetWidth - $measure[0].clientWidth; $measure.remove(); return scrollbarWidth; }; UI.utils.imageLoader = function($image, callback) { function loaded() { callback($image[0]); } function bindLoad() { this.one('load', loaded); if (/MSIE (\d+\.\d+);/.test(navigator.userAgent)) { var src = this.attr('src'); var param = src.match(/\?/) ? '&' : '?'; param += 'random=' + (new Date()).getTime(); this.attr('src', src + param); } } if (!$image.attr('src')) { loaded(); return; } if ($image[0].complete || $image[0].readyState === 4) { loaded(); } else { bindLoad.call($image); } }; /** * @see https://github.com/cho45/micro-template.js * (c) cho45 http://cho45.github.com/mit-license */ UI.template = function(id, data) { var me = UI.template; if (!me.cache[id]) { me.cache[id] = (function() { var name = id; var string = /^[\w\-]+$/.test(id) ? me.get(id) : (name = 'template(string)', id); // no warnings var line = 1; /* eslint-disable max-len, quotes */ var body = ('try { ' + (me.variable ? 'var ' + me.variable + ' = this.stash;' : 'with (this.stash) { ') + "this.ret += '" + string. replace(/<%/g, '\x11').replace(/%>/g, '\x13'). // if you want other tag, just edit this line replace(/'(?![^\x11\x13]+?\x13)/g, '\\x27'). replace(/^\s*|\s*$/g, ''). replace(/\n/g, function() { return "';\nthis.line = " + (++line) + "; this.ret += '\\n"; }). replace(/\x11-(.+?)\x13/g, "' + ($1) + '"). replace(/\x11=(.+?)\x13/g, "' + this.escapeHTML($1) + '"). replace(/\x11(.+?)\x13/g, "'; $1; this.ret += '") + "'; " + (me.variable ? "" : "}") + "return this.ret;" + "} catch (e) { throw 'TemplateError: ' + e + ' (on " + name + "' + ' line ' + this.line + ')'; } " + "//@ sourceURL=" + name + "\n" // source map ).replace(/this\.ret \+= '';/g, ''); /* eslint-enable max-len, quotes */ var func = new Function(body); var map = { '&': '&amp;', '<': '&lt;', '>': '&gt;', '\x22': '&#x22;', '\x27': '&#x27;' }; var escapeHTML = function(string) { return ('' + string).replace(/[&<>\'\"]/g, function(_) { return map[_]; }); }; return function(stash) { return func.call(me.context = { escapeHTML: escapeHTML, line: 1, ret: '', stash: stash }); }; })(); } return data ? me.cache[id](data) : me.cache[id]; }; UI.template.cache = {}; UI.template.get = function(id) { if (id) { var element = document.getElementById(id); return element && element.innerHTML || ''; } }; // Dom mutation watchers UI.DOMWatchers = []; UI.DOMReady = false; UI.ready = function(callback) { UI.DOMWatchers.push(callback); if (UI.DOMReady) { // console.log('Ready call'); callback(document); } }; UI.DOMObserve = function(elements, options, callback) { var Observer = UI.support.mutationobserver; if (!Observer) { return; } options = $.isPlainObject(options) ? options : {childList: true, subtree: true}; callback = typeof callback === 'function' && callback || function() { }; $(elements).each(function() { var element = this; var $element = $(element); if ($element.data('am.observer')) { return; } try { var observer = new Observer(UI.utils.debounce( function(mutations, instance) { callback.call(element, mutations, instance); // trigger this event manually if MutationObserver not supported $element.trigger('changed.dom.amui'); }, 50)); observer.observe(element, options); $element.data('am.observer', observer); } catch (e) { } }); }; $.fn.DOMObserve = function(options, callback) { return this.each(function() { /* eslint-disable new-cap */ UI.DOMObserve(this, options, callback); /* eslint-enable new-cap */ }); }; if (UI.support.touch) { $html.addClass('am-touch'); } $(document).on('changed.dom.amui', function(e) { var element = e.target; // TODO: just call changed element's watcher // every watcher callback should have a key // use like this: <div data-am-observe='key1, key2'> // get keys via $(element).data('amObserve') // call functions store with these keys $.each(UI.DOMWatchers, function(i, watcher) { watcher(element); }); }); $(function() { var $body = $(document.body); UI.DOMReady = true; // Run default init $.each(UI.DOMWatchers, function(i, watcher) { watcher(document); }); // watches DOM /* eslint-disable new-cap */ UI.DOMObserve('[data-am-observe]'); /* eslint-enable */ $html.removeClass('no-js').addClass('js'); UI.support.animation && $html.addClass('cssanimations'); // iOS standalone mode if (window.navigator.standalone) { $html.addClass('am-standalone'); } $('.am-topbar-fixed-top').length && $body.addClass('am-with-topbar-fixed-top'); $('.am-topbar-fixed-bottom').length && $body.addClass('am-with-topbar-fixed-bottom'); // Remove responsive classes in .am-layout var $layout = $('.am-layout'); $layout.find('[class*="md-block-grid"]').alterClass('md-block-grid-*'); $layout.find('[class*="lg-block-grid"]').alterClass('lg-block-grid'); // widgets not in .am-layout $('[data-am-widget]').each(function() { var $widget = $(this); // console.log($widget.parents('.am-layout').length) if ($widget.parents('.am-layout').length === 0) { $widget.addClass('am-no-layout'); } }); }); module.exports = UI;