diff --git a/Gruntfile.js b/Gruntfile.js
index adee7e46..bd3fedd2 100644
--- a/Gruntfile.js
+++ b/Gruntfile.js
@@ -86,6 +86,7 @@ module.exports = function (grunt) {
modules: 'ignore'
},
files: {
+ 'js/dist/util.js' : 'js/src/util.js',
'js/dist/ripples.js' : 'js/src/ripples.js' //,
//'js/dist/alert.js' : 'js/src/alert.js',
//'js/dist/button.js' : 'js/src/button.js',
@@ -112,6 +113,7 @@ module.exports = function (grunt) {
modules: 'umd'
},
files: {
+ 'dist/js/umd/util.js' : 'js/src/util.js',
'dist/js/umd/ripples.js' : 'js/src/ripples.js' //,
//'dist/js/umd/alert.js' : 'js/src/alert.js',
//'dist/js/umd/button.js' : 'js/src/button.js',
@@ -173,6 +175,7 @@ module.exports = function (grunt) {
},
bootstrap: {
src: [
+ 'js/src/util.js',
'js/src/ripples.js',
//'js/src/alert.js',
//'js/src/button.js',
diff --git a/js/src/old/es6Template.js b/js/src/old/es6Template.js
index f59ec092..cd569e81 100644
--- a/js/src/old/es6Template.js
+++ b/js/src/old/es6Template.js
@@ -1,5 +1,6 @@
-const Foo = (($) => {
+import Util from './util'
+const Foo = (($) => {
/**
* ------------------------------------------------------------------------
@@ -8,21 +9,8 @@ const Foo = (($) => {
*/
const NAME = 'foo'
const DATA_KEY = `bmd.${NAME}`
- const EVENT_KEY = `.${DATA_KEY}`
- const DATA_API_KEY = '.data-api'
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
@@ -31,34 +19,15 @@ const Foo = (($) => {
class Foo {
constructor(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)
+ this.element = element
}
dispose() {
- $.removeData(this._element, DATA_KEY)
- this._element = null
+ $.removeData(this.element, DATA_KEY)
+ this.element = null
}
-
+ // ------------------------------------------------------------------------
// private
_bar(element) {
@@ -66,7 +35,7 @@ const Foo = (($) => {
return x
}
-
+ // ------------------------------------------------------------------------
// static
static _jQueryInterface(config) {
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
diff --git a/js/src/ripples.js b/js/src/ripples.js
index 1c3ff9a2..f9d5b1cf 100644
--- a/js/src/ripples.js
+++ b/js/src/ripples.js
@@ -1,3 +1,5 @@
+// FIXME: look at bootstrap/Util.js for transition support functions
+
const Ripples = (($) => {
/**
@@ -8,7 +10,17 @@ const Ripples = (($) => {
const NAME = 'ripples'
const DATA_KEY = `bmd.${NAME}`
const JQUERY_NO_CONFLICT = $.fn[NAME]
- const DEFAULT_OPTIONS = {}
+
+ const Default = {
+ containerSelector: '.ripple-container',
+ rippleSelector: 'div.ripple',
+ containerTemplate: `
`,
+ rippleTemplate: ``,
+ 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 {
- constructor(element, options) {
- this._element = $(element)
- this._options = $.extend({}, DEFAULT_OPTIONS, options)
- this._element.on("mousedown touchstart", this._onStartRipple)
+ constructor(element, config) {
+ this.element = $(element)
+ this.config = $.extend({}, Default, config)
+
+ // attach initial listener
+ this.element.on(this.config.triggerStart, this._onStartRipple)
}
dispose() {
- $.removeData(this._element, DATA_KEY)
- this._element = null
- this._containerElement = null
- this._rippleElement = null
- this._options = null
+ $.removeData(this.element, DATA_KEY)
+ this.element = null
+ this.containerElement = null
+ this.rippleElement = null
+ this.config = null
}
// ------------------------------------------------------------------------
@@ -54,7 +68,7 @@ const Ripples = (($) => {
}
// set the location and color each time (even if element is cached)
- this._rippleElement.addClass("ripple").css({
+ this.rippleElement.css({
"left": relX,
"top": relY,
"background-color": this._getRipplesColor()
@@ -69,38 +83,39 @@ const Ripples = (($) => {
// Call the rippleEnd function when the transition "on" ends
setTimeout(() => {
this.rippleEnd()
- }, 500)
+ }, this.config.duration)
// Detect when the user leaves the element (attach only when necessary for performance)
- this._element.on("mouseup mouseleave touchend", () => {
- this._rippleElement.data("mousedown", "off")
+ this.element.on(this.config.triggerEnd, () => {
+ this.rippleElement.data("mousedown", "off")
- if (this._rippleElement.data("animating") === "off") {
+ if (this.rippleElement.data("animating") === "off") {
this.rippleOut()
}
})
}
_findOrCreateContainer() {
- if (!this._containerElement || !this._containerElement.length > 0) {
- this._element.append("")
- this._containerElement = this._element.find(".ripple-container")
- this._rippleElement = this._containerElement.find("div.ripple")
+ if (!this.containerElement || !this.containerElement.length > 0) {
+ this.element.append(this.config.containerTemplate)
+ this.containerElement = this.element.find(this.config.containerSelector)
}
- 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)
_forceStyleApplication() {
- return window.getComputedStyle(this._rippleElement[0]).opacity
+ return window.getComputedStyle(this.rippleElement[0]).opacity
}
/**
* Get the relX
*/
_getRelX(event) {
- let wrapperOffset = this._containerElement.offset()
+ let wrapperOffset = this.containerElement.offset()
let result = null
if (!this.isTouch()) {
@@ -125,7 +140,7 @@ const Ripples = (($) => {
* Get the relY
*/
_getRelY(event) {
- let containerOffset = this._containerElement.offset()
+ let containerOffset = this.containerElement.offset()
let result = null
if (!this.isTouch()) {
@@ -154,43 +169,25 @@ const Ripples = (($) => {
* Get the ripple color
*/
_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
}
- /**
- * 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
*/
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
*/
rippleEnd() {
- this._rippleElement.data("animating", "off")
+ this.rippleElement.data("animating", "off")
- if (this._rippleElement.data("mousedown") === "off") {
- this.rippleOut(this._rippleElement)
+ if (this.rippleElement.data("mousedown") === "off") {
+ this.rippleOut(this.rippleElement)
}
}
@@ -198,18 +195,19 @@ const Ripples = (($) => {
* Turn off the ripple effect
*/
rippleOut() {
- this._rippleElement.off()
+ this.rippleElement.off()
- if (this._hasTransitionSupport()) {
- this._rippleElement.addClass("ripple-out")
+ if ($.transitionEndSupported()) {
+ this.rippleElement.addClass("ripple-out")
} else {
- this._rippleElement.animate({ "opacity": 0 }, 100, () => {
- this._rippleElement.trigger("transitionend")
+ this.rippleElement.animate({ "opacity": 0 }, 100, () => {
+ this.rippleElement.triggerStart("transitionend")
})
}
- this._rippleElement.on("transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd", () => {
- this._rippleElement.remove()
+ this.rippleElement.on($.transitionEndSelector(), () => {
+ this.rippleElement.remove()
+ this.rippleElement = null
})
}
@@ -219,8 +217,8 @@ const Ripples = (($) => {
rippleOn() {
let size = this._getNewSize()
- if (this._hasTransitionSupport()) {
- this._rippleElement
+ if ($.transitionEndSupported()) {
+ this.rippleElement
.css({
"-ms-transform": `scale(${size})`,
"-moz-transform": `scale(${size})`,
@@ -231,14 +229,14 @@ const Ripples = (($) => {
.data("animating", "on")
.data("mousedown", "on")
} else {
- this._rippleElement.animate({
- "width": 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-top": Math.max(this._element.outerWidth(), this._element.outerHeight()) * (-1),
+ this.rippleElement.animate({
+ "width": 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-top": Math.max(this.element.outerWidth(), this.element.outerHeight()) * (-1),
"opacity": 0.2
- }, 500, () => {
- this._rippleElement.trigger("transitionend")
+ }, this.config.duration, () => {
+ this.rippleElement.triggerStart("transitionend")
})
}
}
@@ -247,7 +245,7 @@ const Ripples = (($) => {
* Get the new size based on the element height/width and the ripple width
*/
_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
}
// ------------------------------------------------------------------------
diff --git a/js/src/util.js b/js/src/util.js
new file mode 100644
index 00000000..cfe8f6e4
--- /dev/null
+++ b/js/src/util.js
@@ -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