mirror of
https://github.com/mdbootstrap/mdb-ui-kit.git
synced 2025-02-18 04:30:38 +03:00
ripples es6 refactoring with a util class
This commit is contained in:
parent
3abd40f72a
commit
8cb4f02d63
|
@ -86,6 +86,7 @@ module.exports = function (grunt) {
|
||||||
modules: 'ignore'
|
modules: 'ignore'
|
||||||
},
|
},
|
||||||
files: {
|
files: {
|
||||||
|
'js/dist/util.js' : 'js/src/util.js',
|
||||||
'js/dist/ripples.js' : 'js/src/ripples.js' //,
|
'js/dist/ripples.js' : 'js/src/ripples.js' //,
|
||||||
//'js/dist/alert.js' : 'js/src/alert.js',
|
//'js/dist/alert.js' : 'js/src/alert.js',
|
||||||
//'js/dist/button.js' : 'js/src/button.js',
|
//'js/dist/button.js' : 'js/src/button.js',
|
||||||
|
@ -112,6 +113,7 @@ module.exports = function (grunt) {
|
||||||
modules: 'umd'
|
modules: 'umd'
|
||||||
},
|
},
|
||||||
files: {
|
files: {
|
||||||
|
'dist/js/umd/util.js' : 'js/src/util.js',
|
||||||
'dist/js/umd/ripples.js' : 'js/src/ripples.js' //,
|
'dist/js/umd/ripples.js' : 'js/src/ripples.js' //,
|
||||||
//'dist/js/umd/alert.js' : 'js/src/alert.js',
|
//'dist/js/umd/alert.js' : 'js/src/alert.js',
|
||||||
//'dist/js/umd/button.js' : 'js/src/button.js',
|
//'dist/js/umd/button.js' : 'js/src/button.js',
|
||||||
|
@ -173,6 +175,7 @@ module.exports = function (grunt) {
|
||||||
},
|
},
|
||||||
bootstrap: {
|
bootstrap: {
|
||||||
src: [
|
src: [
|
||||||
|
'js/src/util.js',
|
||||||
'js/src/ripples.js',
|
'js/src/ripples.js',
|
||||||
//'js/src/alert.js',
|
//'js/src/alert.js',
|
||||||
//'js/src/button.js',
|
//'js/src/button.js',
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
const Foo = (($) => {
|
import Util from './util'
|
||||||
|
|
||||||
|
const Foo = (($) => {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ------------------------------------------------------------------------
|
* ------------------------------------------------------------------------
|
||||||
|
@ -8,21 +9,8 @@ const Foo = (($) => {
|
||||||
*/
|
*/
|
||||||
const NAME = 'foo'
|
const NAME = 'foo'
|
||||||
const DATA_KEY = `bmd.${NAME}`
|
const DATA_KEY = `bmd.${NAME}`
|
||||||
const EVENT_KEY = `.${DATA_KEY}`
|
|
||||||
const DATA_API_KEY = '.data-api'
|
|
||||||
const JQUERY_NO_CONFLICT = $.fn[NAME]
|
const JQUERY_NO_CONFLICT = $.fn[NAME]
|
||||||
|
|
||||||
const Selector = {
|
|
||||||
DATA_DISMISS: '[data-dismiss="foo"]'
|
|
||||||
}
|
|
||||||
|
|
||||||
const Event = {
|
|
||||||
CLOSE: `close${EVENT_KEY}`,
|
|
||||||
CLOSED: `closed${EVENT_KEY}`,
|
|
||||||
CLICK_DATA_API: `click${EVENT_KEY}${DATA_API_KEY}`
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ------------------------------------------------------------------------
|
* ------------------------------------------------------------------------
|
||||||
* Class Definition
|
* Class Definition
|
||||||
|
@ -31,34 +19,15 @@ const Foo = (($) => {
|
||||||
class Foo {
|
class Foo {
|
||||||
|
|
||||||
constructor(element) {
|
constructor(element) {
|
||||||
this._element = element
|
this.element = element
|
||||||
}
|
|
||||||
|
|
||||||
// getters
|
|
||||||
static get NAME() {
|
|
||||||
return NAME
|
|
||||||
}
|
|
||||||
|
|
||||||
// public
|
|
||||||
close(element) {
|
|
||||||
element = element || this._element
|
|
||||||
|
|
||||||
let rootElement = this._getRootElement(element)
|
|
||||||
let customEvent = this._triggerCloseEvent(rootElement)
|
|
||||||
|
|
||||||
if (customEvent.isDefaultPrevented()) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
this._removeElement(rootElement)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dispose() {
|
dispose() {
|
||||||
$.removeData(this._element, DATA_KEY)
|
$.removeData(this.element, DATA_KEY)
|
||||||
this._element = null
|
this.element = null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
// private
|
// private
|
||||||
|
|
||||||
_bar(element) {
|
_bar(element) {
|
||||||
|
@ -66,7 +35,7 @@ const Foo = (($) => {
|
||||||
return x
|
return x
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
// static
|
// static
|
||||||
static _jQueryInterface(config) {
|
static _jQueryInterface(config) {
|
||||||
return this.each(function () {
|
return this.each(function () {
|
||||||
|
@ -83,32 +52,8 @@ const Foo = (($) => {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
static _handleClose(fooInstance) {
|
|
||||||
return function (event) {
|
|
||||||
if (event) {
|
|
||||||
event.preventDefault()
|
|
||||||
}
|
|
||||||
|
|
||||||
fooInstance.close(this)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ------------------------------------------------------------------------
|
|
||||||
* Data Api implementation
|
|
||||||
* ------------------------------------------------------------------------
|
|
||||||
*/
|
|
||||||
|
|
||||||
$(document).on(
|
|
||||||
Event.CLICK_DATA_API,
|
|
||||||
Selector.DATA_DISMISS,
|
|
||||||
Foo._handleClose(new Foo())
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ------------------------------------------------------------------------
|
* ------------------------------------------------------------------------
|
||||||
* jQuery
|
* jQuery
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
// FIXME: look at bootstrap/Util.js for transition support functions
|
||||||
|
|
||||||
const Ripples = (($) => {
|
const Ripples = (($) => {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -8,7 +10,17 @@ const Ripples = (($) => {
|
||||||
const NAME = 'ripples'
|
const NAME = 'ripples'
|
||||||
const DATA_KEY = `bmd.${NAME}`
|
const DATA_KEY = `bmd.${NAME}`
|
||||||
const JQUERY_NO_CONFLICT = $.fn[NAME]
|
const JQUERY_NO_CONFLICT = $.fn[NAME]
|
||||||
const DEFAULT_OPTIONS = {}
|
|
||||||
|
const Default = {
|
||||||
|
containerSelector: '.ripple-container',
|
||||||
|
rippleSelector: 'div.ripple',
|
||||||
|
containerTemplate: `<div class='ripple-container'></div>`,
|
||||||
|
rippleTemplate: `<div class='ripple'></div>`,
|
||||||
|
touchUserAgentRegex: /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i,
|
||||||
|
triggerStart: 'mousedown touchstart',
|
||||||
|
triggerEnd: 'mouseup mouseleave touchend',
|
||||||
|
duration: 500
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ------------------------------------------------------------------------
|
* ------------------------------------------------------------------------
|
||||||
|
@ -17,18 +29,20 @@ const Ripples = (($) => {
|
||||||
*/
|
*/
|
||||||
class Ripples {
|
class Ripples {
|
||||||
|
|
||||||
constructor(element, options) {
|
constructor(element, config) {
|
||||||
this._element = $(element)
|
this.element = $(element)
|
||||||
this._options = $.extend({}, DEFAULT_OPTIONS, options)
|
this.config = $.extend({}, Default, config)
|
||||||
this._element.on("mousedown touchstart", this._onStartRipple)
|
|
||||||
|
// attach initial listener
|
||||||
|
this.element.on(this.config.triggerStart, this._onStartRipple)
|
||||||
}
|
}
|
||||||
|
|
||||||
dispose() {
|
dispose() {
|
||||||
$.removeData(this._element, DATA_KEY)
|
$.removeData(this.element, DATA_KEY)
|
||||||
this._element = null
|
this.element = null
|
||||||
this._containerElement = null
|
this.containerElement = null
|
||||||
this._rippleElement = null
|
this.rippleElement = null
|
||||||
this._options = null
|
this.config = null
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
@ -54,7 +68,7 @@ const Ripples = (($) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
// set the location and color each time (even if element is cached)
|
// set the location and color each time (even if element is cached)
|
||||||
this._rippleElement.addClass("ripple").css({
|
this.rippleElement.css({
|
||||||
"left": relX,
|
"left": relX,
|
||||||
"top": relY,
|
"top": relY,
|
||||||
"background-color": this._getRipplesColor()
|
"background-color": this._getRipplesColor()
|
||||||
|
@ -69,38 +83,39 @@ const Ripples = (($) => {
|
||||||
// Call the rippleEnd function when the transition "on" ends
|
// Call the rippleEnd function when the transition "on" ends
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.rippleEnd()
|
this.rippleEnd()
|
||||||
}, 500)
|
}, this.config.duration)
|
||||||
|
|
||||||
// Detect when the user leaves the element (attach only when necessary for performance)
|
// Detect when the user leaves the element (attach only when necessary for performance)
|
||||||
this._element.on("mouseup mouseleave touchend", () => {
|
this.element.on(this.config.triggerEnd, () => {
|
||||||
this._rippleElement.data("mousedown", "off")
|
this.rippleElement.data("mousedown", "off")
|
||||||
|
|
||||||
if (this._rippleElement.data("animating") === "off") {
|
if (this.rippleElement.data("animating") === "off") {
|
||||||
this.rippleOut()
|
this.rippleOut()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
_findOrCreateContainer() {
|
_findOrCreateContainer() {
|
||||||
if (!this._containerElement || !this._containerElement.length > 0) {
|
if (!this.containerElement || !this.containerElement.length > 0) {
|
||||||
this._element.append("<div class='ripple-container'><div class='ripple'></div></div>")
|
this.element.append(this.config.containerTemplate)
|
||||||
this._containerElement = this._element.find(".ripple-container")
|
this.containerElement = this.element.find(this.config.containerSelector)
|
||||||
this._rippleElement = this._containerElement.find("div.ripple")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return this._containerElement
|
// always add the rippleElement, it is always removed
|
||||||
|
this.containerElement.append(this.config.rippleTemplate)
|
||||||
|
this.rippleElement = this.containerElement.find(this.config.rippleSelector)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure the ripple has the styles applied (ugly hack but it works)
|
// Make sure the ripple has the styles applied (ugly hack but it works)
|
||||||
_forceStyleApplication() {
|
_forceStyleApplication() {
|
||||||
return window.getComputedStyle(this._rippleElement[0]).opacity
|
return window.getComputedStyle(this.rippleElement[0]).opacity
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the relX
|
* Get the relX
|
||||||
*/
|
*/
|
||||||
_getRelX(event) {
|
_getRelX(event) {
|
||||||
let wrapperOffset = this._containerElement.offset()
|
let wrapperOffset = this.containerElement.offset()
|
||||||
|
|
||||||
let result = null
|
let result = null
|
||||||
if (!this.isTouch()) {
|
if (!this.isTouch()) {
|
||||||
|
@ -125,7 +140,7 @@ const Ripples = (($) => {
|
||||||
* Get the relY
|
* Get the relY
|
||||||
*/
|
*/
|
||||||
_getRelY(event) {
|
_getRelY(event) {
|
||||||
let containerOffset = this._containerElement.offset()
|
let containerOffset = this.containerElement.offset()
|
||||||
let result = null
|
let result = null
|
||||||
|
|
||||||
if (!this.isTouch()) {
|
if (!this.isTouch()) {
|
||||||
|
@ -154,43 +169,25 @@ const Ripples = (($) => {
|
||||||
* Get the ripple color
|
* Get the ripple color
|
||||||
*/
|
*/
|
||||||
_getRipplesColor() {
|
_getRipplesColor() {
|
||||||
let color = this._element.data("ripple-color") ? this._element.data("ripple-color") : window.getComputedStyle(this._element[0]).color
|
let color = this.element.data("ripple-color") ? this.element.data("ripple-color") : window.getComputedStyle(this.element[0]).color
|
||||||
return color
|
return color
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Verify if the client browser has transistion support
|
|
||||||
*/
|
|
||||||
_hasTransitionSupport() {
|
|
||||||
let thisBody = document.body || document.documentElement
|
|
||||||
let thisStyle = thisBody.style
|
|
||||||
|
|
||||||
let support = (
|
|
||||||
thisStyle.transition !== undefined ||
|
|
||||||
thisStyle.WebkitTransition !== undefined ||
|
|
||||||
thisStyle.MozTransition !== undefined ||
|
|
||||||
thisStyle.MsTransition !== undefined ||
|
|
||||||
thisStyle.OTransition !== undefined
|
|
||||||
)
|
|
||||||
|
|
||||||
return support
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Verify if the client is using a mobile device
|
* Verify if the client is using a mobile device
|
||||||
*/
|
*/
|
||||||
isTouch() {
|
isTouch() {
|
||||||
return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)
|
return this.config.touchUserAgentRegex.test(navigator.userAgent)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* End the animation of the ripple
|
* End the animation of the ripple
|
||||||
*/
|
*/
|
||||||
rippleEnd() {
|
rippleEnd() {
|
||||||
this._rippleElement.data("animating", "off")
|
this.rippleElement.data("animating", "off")
|
||||||
|
|
||||||
if (this._rippleElement.data("mousedown") === "off") {
|
if (this.rippleElement.data("mousedown") === "off") {
|
||||||
this.rippleOut(this._rippleElement)
|
this.rippleOut(this.rippleElement)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -198,18 +195,19 @@ const Ripples = (($) => {
|
||||||
* Turn off the ripple effect
|
* Turn off the ripple effect
|
||||||
*/
|
*/
|
||||||
rippleOut() {
|
rippleOut() {
|
||||||
this._rippleElement.off()
|
this.rippleElement.off()
|
||||||
|
|
||||||
if (this._hasTransitionSupport()) {
|
if ($.transitionEndSupported()) {
|
||||||
this._rippleElement.addClass("ripple-out")
|
this.rippleElement.addClass("ripple-out")
|
||||||
} else {
|
} else {
|
||||||
this._rippleElement.animate({ "opacity": 0 }, 100, () => {
|
this.rippleElement.animate({ "opacity": 0 }, 100, () => {
|
||||||
this._rippleElement.trigger("transitionend")
|
this.rippleElement.triggerStart("transitionend")
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
this._rippleElement.on("transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd", () => {
|
this.rippleElement.on($.transitionEndSelector(), () => {
|
||||||
this._rippleElement.remove()
|
this.rippleElement.remove()
|
||||||
|
this.rippleElement = null
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -219,8 +217,8 @@ const Ripples = (($) => {
|
||||||
rippleOn() {
|
rippleOn() {
|
||||||
let size = this._getNewSize()
|
let size = this._getNewSize()
|
||||||
|
|
||||||
if (this._hasTransitionSupport()) {
|
if ($.transitionEndSupported()) {
|
||||||
this._rippleElement
|
this.rippleElement
|
||||||
.css({
|
.css({
|
||||||
"-ms-transform": `scale(${size})`,
|
"-ms-transform": `scale(${size})`,
|
||||||
"-moz-transform": `scale(${size})`,
|
"-moz-transform": `scale(${size})`,
|
||||||
|
@ -231,14 +229,14 @@ const Ripples = (($) => {
|
||||||
.data("animating", "on")
|
.data("animating", "on")
|
||||||
.data("mousedown", "on")
|
.data("mousedown", "on")
|
||||||
} else {
|
} else {
|
||||||
this._rippleElement.animate({
|
this.rippleElement.animate({
|
||||||
"width": Math.max(this._element.outerWidth(), this._element.outerHeight()) * 2,
|
"width": Math.max(this.element.outerWidth(), this.element.outerHeight()) * 2,
|
||||||
"height": Math.max(this._element.outerWidth(), this._element.outerHeight()) * 2,
|
"height": Math.max(this.element.outerWidth(), this.element.outerHeight()) * 2,
|
||||||
"margin-left": Math.max(this._element.outerWidth(), this._element.outerHeight()) * (-1),
|
"margin-left": Math.max(this.element.outerWidth(), this.element.outerHeight()) * (-1),
|
||||||
"margin-top": Math.max(this._element.outerWidth(), this._element.outerHeight()) * (-1),
|
"margin-top": Math.max(this.element.outerWidth(), this.element.outerHeight()) * (-1),
|
||||||
"opacity": 0.2
|
"opacity": 0.2
|
||||||
}, 500, () => {
|
}, this.config.duration, () => {
|
||||||
this._rippleElement.trigger("transitionend")
|
this.rippleElement.triggerStart("transitionend")
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -247,7 +245,7 @@ const Ripples = (($) => {
|
||||||
* Get the new size based on the element height/width and the ripple width
|
* Get the new size based on the element height/width and the ripple width
|
||||||
*/
|
*/
|
||||||
_getNewSize() {
|
_getNewSize() {
|
||||||
return (Math.max(this._element.outerWidth(), this._element.outerHeight()) / this._rippleElement.outerWidth()) * 2.5
|
return (Math.max(this.element.outerWidth(), this.element.outerHeight()) / this.rippleElement.outerWidth()) * 2.5
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
|
82
js/src/util.js
Normal file
82
js/src/util.js
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
const Util = (($) => {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ------------------------------------------------------------------------
|
||||||
|
* Private TransitionEnd Helpers
|
||||||
|
* ------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
let transitionEnd = false
|
||||||
|
let transitionEndSelector = ""
|
||||||
|
|
||||||
|
const TransitionEndEvent = {
|
||||||
|
WebkitTransition: 'webkitTransitionEnd',
|
||||||
|
MozTransition: 'transitionend',
|
||||||
|
OTransition: 'oTransitionEnd otransitionend',
|
||||||
|
transition: 'transitionend'
|
||||||
|
}
|
||||||
|
|
||||||
|
function transitionEndTest() {
|
||||||
|
if (window.QUnit) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
let el = document.createElement('mdb')
|
||||||
|
|
||||||
|
for (let name in TransitionEndEvent) {
|
||||||
|
if (el.style[name] !== undefined) {
|
||||||
|
return TransitionEndEvent[name] //{ end: TransitionEndEvent[name] }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
function setTransitionEndSupport() {
|
||||||
|
transitionEnd = transitionEndTest()
|
||||||
|
$.fn.transitionEndSupported = () => {
|
||||||
|
return transitionEnd
|
||||||
|
}
|
||||||
|
|
||||||
|
// generate a selector
|
||||||
|
for (let name in TransitionEndEvent) {
|
||||||
|
transitionEndSelector += ` ${TransitionEndEvent[name]}`
|
||||||
|
}
|
||||||
|
$.fn.transitionEndSelector = () => {
|
||||||
|
return transitionEndSelector
|
||||||
|
} // FIXME: make this a Util.* method instead?
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* --------------------------------------------------------------------------
|
||||||
|
* Public Util Api
|
||||||
|
* --------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
let Util = {
|
||||||
|
|
||||||
|
isChar(evt) {
|
||||||
|
if (typeof evt.which == "undefined") {
|
||||||
|
return true
|
||||||
|
} else if (typeof evt.which == "number" && evt.which > 0) {
|
||||||
|
return !evt.ctrlKey && !evt.metaKey && !evt.altKey && evt.which != 8 && evt.which != 9
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/* /!**
|
||||||
|
* Verify if the client browser has transistion support
|
||||||
|
*!/
|
||||||
|
hasTransitionSupport() {
|
||||||
|
return transition
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
|
||||||
|
setTransitionEndSupport()
|
||||||
|
return Util
|
||||||
|
|
||||||
|
})(jQuery)
|
||||||
|
|
||||||
|
export default Util
|
Loading…
Reference in New Issue
Block a user