UNPKG

5.43 kBJavaScriptView Raw
1'use strict';
2
3import $ from 'jquery';
4import { MediaQuery } from './foundation.util.mediaQuery';
5import { Plugin } from './foundation.plugin';
6import { GetYoDigits } from './foundation.util.core';
7
8
9/**
10 * Interchange module.
11 * @module foundation.interchange
12 * @requires foundation.util.mediaQuery
13 */
14
15class Interchange extends Plugin {
16 /**
17 * Creates a new instance of Interchange.
18 * @class
19 * @name Interchange
20 * @fires Interchange#init
21 * @param {Object} element - jQuery object to add the trigger to.
22 * @param {Object} options - Overrides to the default plugin settings.
23 */
24 _setup(element, options) {
25 this.$element = element;
26 this.options = $.extend({}, Interchange.defaults, options);
27 this.rules = [];
28 this.currentPath = '';
29 this.className = 'Interchange'; // ie9 back compat
30
31 this._init();
32 this._events();
33 }
34
35 /**
36 * Initializes the Interchange plugin and calls functions to get interchange functioning on load.
37 * @function
38 * @private
39 */
40 _init() {
41 MediaQuery._init();
42
43 var id = this.$element[0].id || GetYoDigits(6, 'interchange');
44 this.$element.attr({
45 'data-resize': id,
46 'id': id
47 });
48
49 this._addBreakpoints();
50 this._generateRules();
51 this._reflow();
52 }
53
54 /**
55 * Initializes events for Interchange.
56 * @function
57 * @private
58 */
59 _events() {
60 this.$element.off('resizeme.zf.trigger').on('resizeme.zf.trigger', () => this._reflow());
61 }
62
63 /**
64 * Calls necessary functions to update Interchange upon DOM change
65 * @function
66 * @private
67 */
68 _reflow() {
69 var match;
70
71 // Iterate through each rule, but only save the last match
72 for (var i in this.rules) {
73 if(this.rules.hasOwnProperty(i)) {
74 var rule = this.rules[i];
75 if (window.matchMedia(rule.query).matches) {
76 match = rule;
77 }
78 }
79 }
80
81 if (match) {
82 this.replace(match.path);
83 }
84 }
85
86 /**
87 * Gets the Foundation breakpoints and adds them to the Interchange.SPECIAL_QUERIES object.
88 * @function
89 * @private
90 */
91 _addBreakpoints() {
92 for (var i in MediaQuery.queries) {
93 if (MediaQuery.queries.hasOwnProperty(i)) {
94 var query = MediaQuery.queries[i];
95 Interchange.SPECIAL_QUERIES[query.name] = query.value;
96 }
97 }
98 }
99
100 /**
101 * Checks the Interchange element for the provided media query + content pairings
102 * @function
103 * @private
104 * @param {Object} element - jQuery object that is an Interchange instance
105 * @returns {Array} scenarios - Array of objects that have 'mq' and 'path' keys with corresponding keys
106 */
107 _generateRules(element) {
108 var rulesList = [];
109 var rules;
110
111 if (this.options.rules) {
112 rules = this.options.rules;
113 }
114 else {
115 rules = this.$element.data('interchange');
116 }
117
118 rules = typeof rules === 'string' ? rules.match(/\[.*?\]/g) : rules;
119
120 for (var i in rules) {
121 if(rules.hasOwnProperty(i)) {
122 var rule = rules[i].slice(1, -1).split(', ');
123 var path = rule.slice(0, -1).join('');
124 var query = rule[rule.length - 1];
125
126 if (Interchange.SPECIAL_QUERIES[query]) {
127 query = Interchange.SPECIAL_QUERIES[query];
128 }
129
130 rulesList.push({
131 path: path,
132 query: query
133 });
134 }
135 }
136
137 this.rules = rulesList;
138 }
139
140 /**
141 * Update the `src` property of an image, or change the HTML of a container, to the specified path.
142 * @function
143 * @param {String} path - Path to the image or HTML partial.
144 * @fires Interchange#replaced
145 */
146 replace(path) {
147 if (this.currentPath === path) return;
148
149 var _this = this,
150 trigger = 'replaced.zf.interchange';
151
152 // Replacing images
153 if (this.$element[0].nodeName === 'IMG') {
154 this.$element.attr('src', path).on('load', function() {
155 _this.currentPath = path;
156 })
157 .trigger(trigger);
158 }
159 // Replacing background images
160 else if (path.match(/\.(gif|jpg|jpeg|png|svg|tiff)([?#].*)?/i)) {
161 path = path.replace(/\(/g, '%28').replace(/\)/g, '%29');
162 this.$element.css({ 'background-image': 'url('+path+')' })
163 .trigger(trigger);
164 }
165 // Replacing HTML
166 else {
167 $.get(path, function(response) {
168 _this.$element.html(response)
169 .trigger(trigger);
170 $(response).foundation();
171 _this.currentPath = path;
172 });
173 }
174
175 /**
176 * Fires when content in an Interchange element is done being loaded.
177 * @event Interchange#replaced
178 */
179 // this.$element.trigger('replaced.zf.interchange');
180 }
181
182 /**
183 * Destroys an instance of interchange.
184 * @function
185 */
186 _destroy() {
187 this.$element.off('resizeme.zf.trigger')
188 }
189}
190
191/**
192 * Default settings for plugin
193 */
194Interchange.defaults = {
195 /**
196 * Rules to be applied to Interchange elements. Set with the `data-interchange` array notation.
197 * @option
198 * @type {?array}
199 * @default null
200 */
201 rules: null
202};
203
204Interchange.SPECIAL_QUERIES = {
205 'landscape': 'screen and (orientation: landscape)',
206 'portrait': 'screen and (orientation: portrait)',
207 'retina': 'only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min--moz-device-pixel-ratio: 2), only screen and (-o-min-device-pixel-ratio: 2/1), only screen and (min-device-pixel-ratio: 2), only screen and (min-resolution: 192dpi), only screen and (min-resolution: 2dppx)'
208};
209
210export {Interchange};