Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

ab-interchange

Package Overview
Dependencies
Maintainers
1
Versions
23
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

ab-interchange - npm Package Compare versions

Comparing version 1.3.1 to 2.0.0

171

AB-interchange.js

@@ -9,28 +9,19 @@ ;(function(name, definition) {

}
}('abInterchange', function() {
}('interchange', function() {
'use strict';
function extend(){
for (var i = 1, len = arguments.length; i < len; i++) {
if (!arguments[i]) continue;
var pluginName = 'interchange',
attr = 'data-ab-interchange',
attrSrc = 'data-ab-interchange-src';
for (var key in arguments[i]) {
if (!arguments[i].hasOwnProperty(key)) continue;
arguments[0][key] = arguments[i][key];
}
}
return arguments[0];
}
var Plugin = function(el, options) {
this.el = el;
var Interchange = function(element, opt) {
if (!(this instanceof Interchange)) return new Interchange(element, opt);
var dataOptions = AB.isJson(this.el.getAttribute(attr)) ? JSON.parse(this.el.getAttribute(attr)) : {};
this.settings = AB.extend(Plugin.defaults, options, dataOptions);
this.settings = extend({}, Interchange.defaults, opt);
this.element = element;
this.$element = $(element);
this.rules = [];
this.currentPath = '';
this.defaultPath = '';
this.mode = 'img';
this.rules = [];
this.currentPath = '';
this.mode = this._defineMode();

@@ -40,12 +31,13 @@ this.preInit();

Interchange.defaults = {
lazy : true,
delay : 100,
offscreen : 1.5
Plugin.defaults = {
mode : 'background',
lazy : true,
delay : 100,
offscreen : 1.5
};
Interchange.prototype = {
Plugin.prototype = {
preInit: function() {
// no need for a plugin in case of 'picture' with good support
if (this.$element.closest('picture').length && window.HTMLPictureElement)
if (this.el.parentNode.matches('picture') && window.HTMLPictureElement)
return this;

@@ -59,3 +51,2 @@

._generateRules()
._setDefault()
._updatePath();

@@ -67,12 +58,7 @@

_defineMode: function() {
// images
if (this.element.nodeName === 'IMG')
// in case of <img /> there is no doubt
if (this.el.nodeName === 'IMG')
return 'img';
// background images
if (this.currentPath.match(/\.(gif|jpg|jpeg|tiff|png)([?#].*)?/i) || this.currentPath === 'empty.bg')
return 'bg';
// HTML
return 'ajax';
return this.settings.mode;
},

@@ -82,10 +68,4 @@

var rulesList = [],
rules;
rules = this.el.getAttribute(attrSrc).match(/\[[^\]]+\]/g);
if (this.settings.rules) {
rules = this.settings.rules;
} else {
rules = this.$element.data('ab-interchange').match(/\[[^\]]+\]/g);
}
for (var i = 0, len = rules.length; i < len; i++) {

@@ -107,20 +87,2 @@ var rule = rules[i].slice(1, -1).split(', '),

_setDefault: function() {
var path = '',
rules = this.rules,
rule;
// Iterate through each rule
for (var i = 0, len = rules.length; i < len; i++) {
rule = rules[i];
// check if default value is provided
if (rule.query === 'default' && this.defaultPath === '') {
this.defaultPath = rule.path;
}
}
return this;
},
_updatePath: function() {

@@ -130,3 +92,3 @@ var match = false,

rules = this.rules,
currentQuery = AB.mediaQuery.current,
//currentQuery = AB.mediaQuery.current,
rule;

@@ -138,3 +100,3 @@

if (window.matchMedia(AB.mediaQuery.get(rule.query)).matches) {
if (AB.mediaQuery.is(rule.query)) {
path = rule.path;

@@ -145,5 +107,5 @@ match = true;

this.currentPath = (path === '') ? this.defaultPath : path;
this.currentPath = path;
this._replace();
this._replace();
return this;

@@ -153,4 +115,3 @@ },

_onScroll: function() {
if (this._inView())
this._replace();
if (this._inView()) this._replace();

@@ -180,11 +141,12 @@ return this;

_inView: function() {
var scrollTop = $(window).scrollTop(),
var scrollTop = window.scrollY,
windowHeight = window.innerHeight;
return this.element.getBoundingClientRect().top + scrollTop <= scrollTop + windowHeight * this.settings.offscreen;
return this.el.getBoundingClientRect().top + scrollTop <= scrollTop + windowHeight * this.settings.offscreen;
},
_replace: function() {
var that = this,
path = that.currentPath,
trigger = 'replaced.ab-interchange';
var that = this,
path = that.currentPath,
eventName = 'replaced.ab-interchange';

@@ -196,3 +158,7 @@ that.mode = that._defineMode();

if (that.mode === 'img') {
that.$element.attr('src', path).load().trigger(trigger);
that.el.src = path;
var event = new CustomEvent(eventName);
window.dispatchEvent(event);
return that;

@@ -202,8 +168,13 @@ }

// background images
if (that.mode === 'bg') {
if (path === 'empty.bg') {
that.$element.css({ 'background-image': 'none' }).trigger(trigger);
} else {
that.$element.css({ 'background-image': 'url('+path+')' }).trigger(trigger);
}
if (that.mode === 'background') {
if (path)
path = 'url('+path+')';
else
path = 'none';
that.el.style.backgroundImage = path;
var event = new CustomEvent(eventName);
window.dispatchEvent(event);
return that;

@@ -213,10 +184,29 @@ }

// HTML
if (path === 'empty.ajax') {
that.$element.empty();
} else {
$.get(path, function(response) {
that.$element.html(response).trigger(trigger);
});
var request = new XMLHttpRequest();
if (!path) {
that.el.innerHTML = '';
return that;
}
request.open('GET', path, true);
request.onload = function() {
if (this.status >= 200 && this.status < 400) {
var resp = this.response;
that.el.innerHTML = resp;
var event = new CustomEvent(eventName);
window.dispatchEvent(event);
} else {
that.el.innerHTML = '';
}
};
request.onerror = function() {
that.el.innerHTML = '';
};
request.send();
return that;

@@ -227,12 +217,11 @@ }

function abInterchange(options){
var elements = document.querySelectorAll('[data-ab-interchange]');
AB[pluginName] = function(options) {
var elements = document.querySelectorAll('['+ attr +']');
for (var i = 0, len = elements.length; i < len; i++) {
if (elements[i].abInterchange) continue;
elements[i].abInterchange = new Interchange(elements[i], options);
if (elements[i][pluginName]) continue;
elements[i][pluginName] = new Plugin(elements[i], options);
}
}
};
return abInterchange;
return AB;
}));
{
"name": "ab-interchange",
"version": "1.3.1",
"version": "2.0.0",
"description": "AB-interchange: While responsive image loading is not really an easy task even today, here is a solution to manage conditional (based on breakpoints) loading of img, background-image or even HTML content.",

@@ -10,2 +10,6 @@ "main": "ab-interchange.js",

},
"bugs": {
"url": "https://github.com/lordfpx/AB-interchange/issues"
},
"homepage": "https://github.com/lordfpx/AB-interchange#readme",
"scripts": {

@@ -22,9 +26,12 @@ "test": "echo \"Error: no test specified\" && exit 1"

"responsive",
"AB-mediaQuery"
"AB-mediaQuery",
"another-brick",
"AB"
],
"author": "Thierry Philippe",
"author": "Thierry Philippe (@lordfpx)",
"license": "ISC",
"dependencies": {
"ab-mediaquery": "^1.4.4"
"ab-mediaquery": "^2.1.5",
"another-brick": "^1.0.1"
}
}
# AB-interchange
Responsive image loading is not an easy task even nowadays. Here is a solution to manage conditional (based on breakpoints) loading of:
- **img** (even **picture** on unsupported browsers)
AB-interchange is a pure JavaScript file that makes possible to conditionnaly load:
- **img** (it can be also used as **picture** polyfill on unsupported browsers)
- **background-image**
- **HTML content**
- **HTML content** (Ajax)
That plugin also has an lazy-loading option!
That plugin also has an **lazy-loading** option!
It's inspired by [Zurb Foundation](https://github.com/zurb/foundation-sites).
- [NPM](https://www.npmjs.com/package/ab-interchange)
Here is a demo page: [Codepen](http://codepen.io/lordfpx/pen/yJbwrK)
```
> npm install ab-mediaquery
```
or
```
> yarn add ab-mediaquery
```
NPM package: https://www.npmjs.com/package/ab-interchange
The plugin is **CommonJS** and **AMD** compliant (UMD).
> npm install ab-interchange
It's used on French website [ENGIE](https://particuliers.engie.fr/).
The plugin is **CommonJS** and **AMD** compliant.
---
## Dependencies:
- [jQuery](https://jquery.com/)
- [AB-mediaQueries](https://www.npmjs.com/package/ab-mediaquery)
- [AB (another-brick)](https://www.npmjs.com/package/ab-mediaquery)
- [AB-mediaQueries v2](https://www.npmjs.com/package/ab-mediaquery)
You can either loads those scripts or import them (with browserify or webpack for ex.):
```
import AB from 'another-brick';
import abMediaQuery from 'ab-mediaquery';
```
---
## Compatibility
Because of the usage of `matchMedia`, compatibility start from IE 10. To rise compatibility up to IE 9, you must add https://github.com/paulirish/matchMedia.js/ polyfill.
Because of the usage of `matchMedia`, compatibility start from IE 10. To rise compatibility up to IE 9, you must add this [polyfill](https://github.com/paulirish/matchMedia.js/).
---
## SETUP
You will need [jQuery](https://jquery.com/).
Follow [AB-mediaQuery](https://www.npmjs.com/package/ab-mediaquery) readme to configure it the way you like depending on your needs. For exemple:
The other dependency is [AB-mediaQuery](https://www.npmjs.com/package/ab-mediaquery).
```
abMediaQuery({
bp: {
smallOnly: 'screen and (max-width: 767px)',
mediumOnly: 'screen and (min-width: 768px) and (max-width: 1024px)',
medium: 'screen and (min-width: 768px)',
largeOnly: 'screen and (min-width: 1025px) and (max-width: 1280px)',
large: 'screen and (min-width: 1025px)'
}
});
```
Follow AB-mediaQuery readme to configure it the way you like depending on your needs (or init it with `abMediaQuery()` for default configuration).
Then you only need to initialize with `AB.interchange()` or with options:
Then you only need to initialize with `abInterchange()` or with options:
```
AB.interchange({
mode : 'img"
lazy : true, // or false
delay : 100 // debounce time on scroll event (only when lazy loading is true)
offscreen : 1.5 // load items only when in the view + 0.5 by default
});
```
```
abInterchange({
lazy : false, // or true
delay : 100 // debounce time on scroll event (only when lazy loading is true)
offscreen : 1.5 // load items only when in the view + 0.5 by default
});
```
You can also use **data-ab-interchange** attribute to pass those otpions individually.
**data-ab-interchange** attribute should contain a list of arrays with the path to the asset and the breakpoint name as defined in AB-mediaQuery. Beware to respect mobile first order!
**data-ab-interchange-src** attribute is where you define different sources and breakpoints defined with AB-mediaQuery.
It should contain a list of arrays with the path to the asset and the breakpoint name. Beware to respect mobile first order. Order is **VERY** important!
Defaults breakpoints defined by AB-mediaQueries are:
- small
- smallOnly
- medium
- mediumOnly
- large
- largeOnly
- huge
- hugeOnly
---
Plus set a default asset in case there is no media query matching: `[path/to/asset, default]`.
If you don't want any default asset, you can must set the corresponding value to empty the content (**NOT for IMG**):
- background-image: `[empty.bg, default]`
- HTML content: `[empty.ajax, default]`
## Examples
It's clever to prepare a spinner animation as first img src (or default CSS styling when `src=""`) before init, especially when using **lazy-loading** option.
### **picture**
```
<picture>
<source srcset="xxx" media="(min-width: 80em)"/>
<source srcset="xxx" media="(min-width: 64em)"/>
<source srcset="xxx" media="(min-width: 48em)"/>
<source srcset="xxx"/>
<img
alt=""
data-ab-interchange='{"lazy": false}"
data-ab-interchange-src="[xxx, smallOnly], [xxx, medium]"/>
</picture>
```
## Examples
### **img**
```
<img
src="spinner.gif"
data-ab-interchange="[path/to/default/img, default], [path/to/small/img, small], [path/to/medium/img, medium]"
>
```
```
<img
alt=""
data-ab-interchange='{"lazy": false}"
data-ab-interchange-src="[xxx, smallOnly], [xxx, medium]"/>
```

@@ -83,17 +109,17 @@

To determine if it's a background-image changing, the script looks for image file extensions (`gif|jpg|jpeg|tiff|png`).
```
<div
data-ab-interchange='{"mode": "background", "lazy": true, "delay": 100, "offscreen": 1.5}"
data-ab-interchange-src="[xxx, smallOnly], [xxx, medium]">
</div>
```
```
<div data-ab-interchange="[empty.bg, default], [path/to/medium/img, medium]"></div>
```
It this example, the will not be any background-image on small devices.
### **and even XMLHttpRequest content (ajax)!**
If the data-ab-interchange is neither an image format nor on an img tag, that will send and http request and put the response inside the element.
```
<div data-ab-interchange="[path/to/default/http/request, default], [path/to/small/http/request, small], [path/to/medium/http/request, medium]"></div>
```
```
<div
data-ab-interchange="{"mode": "ajax", "lazy": false}"
data-ab-interchange-src="[xxx, smallOnly], [xxx, mediumOnly]">
</div>
```

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc