123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260 |
- 'use strict';
- import $ from 'jquery';
- import { onLoad } from './foundation.core.utils';
- import { Motion } from './foundation.util.motion';
- const MutationObserver = (function () {
- var prefixes = ['WebKit', 'Moz', 'O', 'Ms', ''];
- for (var i=0; i < prefixes.length; i++) {
- if (`${prefixes[i]}MutationObserver` in window) {
- return window[`${prefixes[i]}MutationObserver`];
- }
- }
- return false;
- }());
- const triggers = (el, type) => {
- el.data(type).split(' ').forEach(id => {
- $(`#${id}`)[ type === 'close' ? 'trigger' : 'triggerHandler'](`${type}.zf.trigger`, [el]);
- });
- };
- var Triggers = {
- Listeners: {
- Basic: {},
- Global: {}
- },
- Initializers: {}
- }
- Triggers.Listeners.Basic = {
- openListener: function() {
- triggers($(this), 'open');
- },
- closeListener: function() {
- let id = $(this).data('close');
- if (id) {
- triggers($(this), 'close');
- }
- else {
- $(this).trigger('close.zf.trigger');
- }
- },
- toggleListener: function() {
- let id = $(this).data('toggle');
- if (id) {
- triggers($(this), 'toggle');
- } else {
- $(this).trigger('toggle.zf.trigger');
- }
- },
- closeableListener: function(e) {
- e.stopPropagation();
- let animation = $(this).data('closable');
- if(animation !== ''){
- Motion.animateOut($(this), animation, function() {
- $(this).trigger('closed.zf');
- });
- }else{
- $(this).fadeOut().trigger('closed.zf');
- }
- },
- toggleFocusListener: function() {
- let id = $(this).data('toggle-focus');
- $(`#${id}`).triggerHandler('toggle.zf.trigger', [$(this)]);
- }
- };
- // Elements with [data-open] will reveal a plugin that supports it when clicked.
- Triggers.Initializers.addOpenListener = ($elem) => {
- $elem.off('click.zf.trigger', Triggers.Listeners.Basic.openListener);
- $elem.on('click.zf.trigger', '[data-open]', Triggers.Listeners.Basic.openListener);
- }
- // Elements with [data-close] will close a plugin that supports it when clicked.
- // If used without a value on [data-close], the event will bubble, allowing it to close a parent component.
- Triggers.Initializers.addCloseListener = ($elem) => {
- $elem.off('click.zf.trigger', Triggers.Listeners.Basic.closeListener);
- $elem.on('click.zf.trigger', '[data-close]', Triggers.Listeners.Basic.closeListener);
- }
- // Elements with [data-toggle] will toggle a plugin that supports it when clicked.
- Triggers.Initializers.addToggleListener = ($elem) => {
- $elem.off('click.zf.trigger', Triggers.Listeners.Basic.toggleListener);
- $elem.on('click.zf.trigger', '[data-toggle]', Triggers.Listeners.Basic.toggleListener);
- }
- // Elements with [data-closable] will respond to close.zf.trigger events.
- Triggers.Initializers.addCloseableListener = ($elem) => {
- $elem.off('close.zf.trigger', Triggers.Listeners.Basic.closeableListener);
- $elem.on('close.zf.trigger', '[data-closeable], [data-closable]', Triggers.Listeners.Basic.closeableListener);
- }
- // Elements with [data-toggle-focus] will respond to coming in and out of focus
- Triggers.Initializers.addToggleFocusListener = ($elem) => {
- $elem.off('focus.zf.trigger blur.zf.trigger', Triggers.Listeners.Basic.toggleFocusListener);
- $elem.on('focus.zf.trigger blur.zf.trigger', '[data-toggle-focus]', Triggers.Listeners.Basic.toggleFocusListener);
- }
- // More Global/complex listeners and triggers
- Triggers.Listeners.Global = {
- resizeListener: function($nodes) {
- if(!MutationObserver){//fallback for IE 9
- $nodes.each(function(){
- $(this).triggerHandler('resizeme.zf.trigger');
- });
- }
- //trigger all listening elements and signal a resize event
- $nodes.attr('data-events', "resize");
- },
- scrollListener: function($nodes) {
- if(!MutationObserver){//fallback for IE 9
- $nodes.each(function(){
- $(this).triggerHandler('scrollme.zf.trigger');
- });
- }
- //trigger all listening elements and signal a scroll event
- $nodes.attr('data-events', "scroll");
- },
- closeMeListener: function(e, pluginId){
- let plugin = e.namespace.split('.')[0];
- let plugins = $(`[data-${plugin}]`).not(`[data-yeti-box="${pluginId}"]`);
- plugins.each(function(){
- let _this = $(this);
- _this.triggerHandler('close.zf.trigger', [_this]);
- });
- }
- }
- // Global, parses whole document.
- Triggers.Initializers.addClosemeListener = function(pluginName) {
- var yetiBoxes = $('[data-yeti-box]'),
- plugNames = ['dropdown', 'tooltip', 'reveal'];
- if(pluginName){
- if(typeof pluginName === 'string'){
- plugNames.push(pluginName);
- }else if(typeof pluginName === 'object' && typeof pluginName[0] === 'string'){
- plugNames = plugNames.concat(pluginName);
- }else{
- console.error('Plugin names must be strings');
- }
- }
- if(yetiBoxes.length){
- let listeners = plugNames.map((name) => {
- return `closeme.zf.${name}`;
- }).join(' ');
- $(window).off(listeners).on(listeners, Triggers.Listeners.Global.closeMeListener);
- }
- }
- function debounceGlobalListener(debounce, trigger, listener) {
- let timer, args = Array.prototype.slice.call(arguments, 3);
- $(window).off(trigger).on(trigger, function(e) {
- if (timer) { clearTimeout(timer); }
- timer = setTimeout(function(){
- listener.apply(null, args);
- }, debounce || 10);//default time to emit scroll event
- });
- }
- Triggers.Initializers.addResizeListener = function(debounce){
- let $nodes = $('[data-resize]');
- if($nodes.length){
- debounceGlobalListener(debounce, 'resize.zf.trigger', Triggers.Listeners.Global.resizeListener, $nodes);
- }
- }
- Triggers.Initializers.addScrollListener = function(debounce){
- let $nodes = $('[data-scroll]');
- if($nodes.length){
- debounceGlobalListener(debounce, 'scroll.zf.trigger', Triggers.Listeners.Global.scrollListener, $nodes);
- }
- }
- Triggers.Initializers.addMutationEventsListener = function($elem) {
- if(!MutationObserver){ return false; }
- let $nodes = $elem.find('[data-resize], [data-scroll], [data-mutate]');
- //element callback
- var listeningElementsMutation = function (mutationRecordsList) {
- var $target = $(mutationRecordsList[0].target);
- //trigger the event handler for the element depending on type
- switch (mutationRecordsList[0].type) {
- case "attributes":
- if ($target.attr("data-events") === "scroll" && mutationRecordsList[0].attributeName === "data-events") {
- $target.triggerHandler('scrollme.zf.trigger', [$target, window.pageYOffset]);
- }
- if ($target.attr("data-events") === "resize" && mutationRecordsList[0].attributeName === "data-events") {
- $target.triggerHandler('resizeme.zf.trigger', [$target]);
- }
- if (mutationRecordsList[0].attributeName === "style") {
- $target.closest("[data-mutate]").attr("data-events","mutate");
- $target.closest("[data-mutate]").triggerHandler('mutateme.zf.trigger', [$target.closest("[data-mutate]")]);
- }
- break;
- case "childList":
- $target.closest("[data-mutate]").attr("data-events","mutate");
- $target.closest("[data-mutate]").triggerHandler('mutateme.zf.trigger', [$target.closest("[data-mutate]")]);
- break;
- default:
- return false;
- //nothing
- }
- };
- if ($nodes.length) {
- //for each element that needs to listen for resizing, scrolling, or mutation add a single observer
- for (var i = 0; i <= $nodes.length - 1; i++) {
- var elementObserver = new MutationObserver(listeningElementsMutation);
- elementObserver.observe($nodes[i], { attributes: true, childList: true, characterData: false, subtree: true, attributeFilter: ["data-events", "style"] });
- }
- }
- }
- Triggers.Initializers.addSimpleListeners = function() {
- let $document = $(document);
- Triggers.Initializers.addOpenListener($document);
- Triggers.Initializers.addCloseListener($document);
- Triggers.Initializers.addToggleListener($document);
- Triggers.Initializers.addCloseableListener($document);
- Triggers.Initializers.addToggleFocusListener($document);
- }
- Triggers.Initializers.addGlobalListeners = function() {
- let $document = $(document);
- Triggers.Initializers.addMutationEventsListener($document);
- Triggers.Initializers.addResizeListener();
- Triggers.Initializers.addScrollListener();
- Triggers.Initializers.addClosemeListener();
- }
- Triggers.init = function ($, Foundation) {
- onLoad($(window), function () {
- if ($.triggersInitialized !== true) {
- Triggers.Initializers.addSimpleListeners();
- Triggers.Initializers.addGlobalListeners();
- $.triggersInitialized = true;
- }
- });
- if(Foundation) {
- Foundation.Triggers = Triggers;
- // Legacy included to be backwards compatible for now.
- Foundation.IHearYou = Triggers.Initializers.addGlobalListeners
- }
- }
- export {Triggers};
|