ES6语法
/*!
* Ladda
* http://lab.hakim.se/ladda
* MIT licensed
*
* Copyright (C) 2018 Hakim El Hattab, http://hakim.se
*/
import {Spinner} from 'spin.js';
// All currently instantiated instances of Ladda
var ALL_INSTANCES = [];
/**
* Creates a new instance of Ladda which wraps the
* target button element.
*
* @return An API object that can be used to control
* the loading animation state.
*/
export function create( button ) {
if( typeof button === 'undefined' ) {
console.warn( "Ladda button target must be defined." );
return;
}
// The button must have the class "ladda-button"
if ( !button.classList.contains('ladda-button') ) {
button.classList.add( 'ladda-button' );
}
// Style is required, default to "expand-right"
if( !button.hasAttribute( 'data-style' ) ) {
button.setAttribute( 'data-style', 'expand-right' );
}
// The text contents must be wrapped in a ladda-label
// element, create one if it doesn't already exist
if( !button.querySelector( '.ladda-label' ) ) {
var laddaLabel = document.createElement( 'span' );
laddaLabel.className = 'ladda-label';
wrapContent( button, laddaLabel );
}
// The spinner component
var spinner,
spinnerWrapper = button.querySelector( '.ladda-spinner' );
// Wrapper element for the spinner
if( !spinnerWrapper ) {
spinnerWrapper = document.createElement( 'span' );
spinnerWrapper.className = 'ladda-spinner';
}
button.appendChild( spinnerWrapper );
// Timer used to delay starting/stopping
var timer;
var instance = {
/**
* Enter the loading state.
*/
start: function() {
// Create the spinner if it doesn't already exist
if( !spinner ) {
spinner = createSpinner( button );
}
button.disabled = true;
button.setAttribute( 'data-loading', '' );
clearTimeout( timer );
spinner.spin( spinnerWrapper );
this.setProgress( 0 );
return this; // chain
},
/**
* Enter the loading state, after a delay.
*/
startAfter: function( delay ) {
clearTimeout( timer );
timer = setTimeout( function() { instance.start(); }, delay );
return this; // chain
},
/**
* Exit the loading state.
*/
stop: function() {
if (instance.isLoading()) {
button.disabled = false;
button.removeAttribute( 'data-loading' );
}
// Kill the animation after a delay to make sure it
// runs for the duration of the button transition
clearTimeout( timer );
if( spinner ) {
timer = setTimeout( function() { spinner.stop(); }, 1000 );
}
return this; // chain
},
/**
* Toggle the loading state on/off.
*/
toggle: function() {
return this.isLoading() ? this.stop() : this.start();
},
/**
* Sets the width of the visual progress bar inside of
* this Ladda button
*
* @param {Number} progress in the range of 0-1
*/
setProgress: function( progress ) {
// Cap it
progress = Math.max( Math.min( progress, 1 ), 0 );
var progressElement = button.querySelector( '.ladda-progress' );
// Remove the progress bar if we're at 0 progress
if( progress === 0 && progressElement && progressElement.parentNode ) {
progressElement.parentNode.removeChild( progressElement );
}
else {
if( !progressElement ) {
progressElement = document.createElement( 'div' );
progressElement.className = 'ladda-progress';
button.appendChild( progressElement );
}
progressElement.style.width = ( ( progress || 0 ) * button.offsetWidth ) + 'px';
}
},
isLoading: function() {
return button.hasAttribute( 'data-loading' );
},
remove: function() {
clearTimeout( timer );
button.disabled = false;
button.removeAttribute( 'data-loading' );
if( spinner ) {
spinner.stop();
spinner = null;
}
ALL_INSTANCES.splice( ALL_INSTANCES.indexOf(instance), 1 );
}
};
ALL_INSTANCES.push( instance );
return instance;
}
/**
* Binds the target buttons to automatically enter the
* loading state when clicked.
*
* @param target Either an HTML element or a CSS selector.
* @param options
* - timeout Number of milliseconds to wait before
* automatically cancelling the animation.
* - callback A function to be called with the Ladda
* instance when a target button is clicked.
*/
export function bind( target, options ) {
var targets;
if( typeof target === 'string' ) {
targets = document.querySelectorAll( target );
}
else if( typeof target === 'object' ) {
targets = [ target ];
} else {
throw new Error('target must be string or object');
}
options = options || {};
for( var i = 0; i < targets.length; i++ ) {
bindElement(targets[i], options);
}
}
/**
* Stops ALL current loading animations.
*/
export function stopAll() {
for( var i = 0, len = ALL_INSTANCES.length; i < len; i++ ) {
ALL_INSTANCES[i].stop();
}
}
/**
* Get the first ancestor node from an element, having a
* certain type.
*
* @param elem An HTML element
* @param type an HTML tag type (uppercased)
*
* @return An HTML element
*/
function getAncestorOfTagType( elem, type ) {
while ( elem.parentNode && elem.tagName !== type ) {
elem = elem.parentNode;
}
return ( type === elem.tagName ) ? elem : undefined;
}
function createSpinner( button ) {
var height = button.offsetHeight,
spinnerColor,
spinnerLines;
if( height === 0 ) {
// We may have an element that is not visible so
// we attempt to get the height in a different way
height = parseFloat( window.getComputedStyle( button ).height );
}
// If the button is tall we can afford some padding
if( height > 32 ) {
height *= 0.8;
}
// Prefer an explicit height if one is defined
if( button.hasAttribute( 'data-spinner-size' ) ) {
height = parseInt( button.getAttribute( 'data-spinner-size' ), 10 );
}
// Allow buttons to specify the color of the spinner element
if( button.hasAttribute( 'data-spinner-color' ) ) {
spinnerColor = button.getAttribute( 'data-spinner-color' );
}
// Allow buttons to specify the number of lines of the spinner
if( button.hasAttribute( 'data-spinner-lines' ) ) {
spinnerLines = parseInt( button.getAttribute( 'data-spinner-lines' ), 10 );
}
var radius = height * 0.2,
length = radius * 0.6,
width = radius < 7 ? 2 : 3;
return new Spinner( {
color: spinnerColor || '#fff',
lines: spinnerLines || 12,
radius: radius,
length: length,
width: width,
animation: 'ladda-spinner-line-fade',
zIndex: 'auto',
top: 'auto',
left: 'auto',
className: ''
} );
}
function wrapContent( node, wrapper ) {
var r = document.createRange();
r.selectNodeContents( node );
r.surroundContents( wrapper );
node.appendChild( wrapper );
}
function bindElement( element, options ) {
if( typeof element.addEventListener !== 'function' ) {
return;
}
var instance = create( element );
var timeout = -1;
element.addEventListener( 'click', function() {
// If the button belongs to a form, make sure all the
// fields in that form are filled out
var valid = true;
var form = getAncestorOfTagType( element, 'FORM' );
if( typeof form !== 'undefined' && !form.hasAttribute('novalidate') ) {
// Modern form validation
if( typeof form.checkValidity === 'function' ) {
valid = form.checkValidity();
}
}
if( valid ) {
// This is asynchronous to avoid an issue where disabling
// the button prevents forms from submitting
instance.startAfter( 1 );
// Set a loading timeout if one is specified
if( typeof options.timeout === 'number' ) {
clearTimeout( timeout );
timeout = setTimeout( instance.stop, options.timeout );
}
// Invoke callbacks
if( typeof options.callback === 'function' ) {
options.callback.apply( null, [ instance ] );
}
}
}, false );
}
ES2015语法
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; /*!
* Ladda
* http://lab.hakim.se/ladda
* MIT licensed
*
* Copyright (C) 2018 Hakim El Hattab, http://hakim.se
*/
exports.create = create;
exports.bind = bind;
exports.stopAll = stopAll;
var _spin = require('spin.js');
// All currently instantiated instances of Ladda
var ALL_INSTANCES = [];
/**
* Creates a new instance of Ladda which wraps the
* target button element.
*
* @return An API object that can be used to control
* the loading animation state.
*/
function create(button) {
if (typeof button === 'undefined') {
console.warn("Ladda button target must be defined.");
return;
}
// The button must have the class "ladda-button"
if (!button.classList.contains('ladda-button')) {
button.classList.add('ladda-button');
}
// Style is required, default to "expand-right"
if (!button.hasAttribute('data-style')) {
button.setAttribute('data-style', 'expand-right');
}
// The text contents must be wrapped in a ladda-label
// element, create one if it doesn't already exist
if (!button.querySelector('.ladda-label')) {
var laddaLabel = document.createElement('span');
laddaLabel.className = 'ladda-label';
wrapContent(button, laddaLabel);
}
// The spinner component
var spinner,
spinnerWrapper = button.querySelector('.ladda-spinner');
// Wrapper element for the spinner
if (!spinnerWrapper) {
spinnerWrapper = document.createElement('span');
spinnerWrapper.className = 'ladda-spinner';
}
button.appendChild(spinnerWrapper);
// Timer used to delay starting/stopping
var timer;
var instance = {
/**
* Enter the loading state.
*/
start: function start() {
// Create the spinner if it doesn't already exist
if (!spinner) {
spinner = createSpinner(button);
}
button.disabled = true;
button.setAttribute('data-loading', '');
clearTimeout(timer);
spinner.spin(spinnerWrapper);
this.setProgress(0);
return this; // chain
},
/**
* Enter the loading state, after a delay.
*/
startAfter: function startAfter(delay) {
clearTimeout(timer);
timer = setTimeout(function () {
instance.start();
}, delay);
return this; // chain
},
/**
* Exit the loading state.
*/
stop: function stop() {
if (instance.isLoading()) {
button.disabled = false;
button.removeAttribute('data-loading');
}
// Kill the animation after a delay to make sure it
// runs for the duration of the button transition
clearTimeout(timer);
if (spinner) {
timer = setTimeout(function () {
spinner.stop();
}, 1000);
}
return this; // chain
},
/**
* Toggle the loading state on/off.
*/
toggle: function toggle() {
return this.isLoading() ? this.stop() : this.start();
},
/**
* Sets the width of the visual progress bar inside of
* this Ladda button
*
* @param {Number} progress in the range of 0-1
*/
setProgress: function setProgress(progress) {
// Cap it
progress = Math.max(Math.min(progress, 1), 0);
var progressElement = button.querySelector('.ladda-progress');
// Remove the progress bar if we're at 0 progress
if (progress === 0 && progressElement && progressElement.parentNode) {
progressElement.parentNode.removeChild(progressElement);
} else {
if (!progressElement) {
progressElement = document.createElement('div');
progressElement.className = 'ladda-progress';
button.appendChild(progressElement);
}
progressElement.style.width = (progress || 0) * button.offsetWidth + 'px';
}
},
isLoading: function isLoading() {
return button.hasAttribute('data-loading');
},
remove: function remove() {
clearTimeout(timer);
button.disabled = false;
button.removeAttribute('data-loading');
if (spinner) {
spinner.stop();
spinner = null;
}
ALL_INSTANCES.splice(ALL_INSTANCES.indexOf(instance), 1);
}
};
ALL_INSTANCES.push(instance);
return instance;
}
/**
* Binds the target buttons to automatically enter the
* loading state when clicked.
*
* @param target Either an HTML element or a CSS selector.
* @param options
* - timeout Number of milliseconds to wait before
* automatically cancelling the animation.
* - callback A function to be called with the Ladda
* instance when a target button is clicked.
*/
function bind(target, options) {
var targets;
if (typeof target === 'string') {
targets = document.querySelectorAll(target);
} else if ((typeof target === 'undefined' ? 'undefined' : _typeof(target)) === 'object') {
targets = [target];
} else {
throw new Error('target must be string or object');
}
options = options || {};
for (var i = 0; i < targets.length; i++) {
bindElement(targets[i], options);
}
}
/**
* Stops ALL current loading animations.
*/
function stopAll() {
for (var i = 0, len = ALL_INSTANCES.length; i < len; i++) {
ALL_INSTANCES[i].stop();
}
}
/**
* Get the first ancestor node from an element, having a
* certain type.
*
* @param elem An HTML element
* @param type an HTML tag type (uppercased)
*
* @return An HTML element
*/
function getAncestorOfTagType(elem, type) {
while (elem.parentNode && elem.tagName !== type) {
elem = elem.parentNode;
}
return type === elem.tagName ? elem : undefined;
}
function createSpinner(button) {
var height = button.offsetHeight,
spinnerColor,
spinnerLines;
if (height === 0) {
// We may have an element that is not visible so
// we attempt to get the height in a different way
height = parseFloat(window.getComputedStyle(button).height);
}
// If the button is tall we can afford some padding
if (height > 32) {
height *= 0.8;
}
// Prefer an explicit height if one is defined
if (button.hasAttribute('data-spinner-size')) {
height = parseInt(button.getAttribute('data-spinner-size'), 10);
}
// Allow buttons to specify the color of the spinner element
if (button.hasAttribute('data-spinner-color')) {
spinnerColor = button.getAttribute('data-spinner-color');
}
// Allow buttons to specify the number of lines of the spinner
if (button.hasAttribute('data-spinner-lines')) {
spinnerLines = parseInt(button.getAttribute('data-spinner-lines'), 10);
}
var radius = height * 0.2,
length = radius * 0.6,
width = radius < 7 ? 2 : 3;
return new _spin.Spinner({
color: spinnerColor || '#fff',
lines: spinnerLines || 12,
radius: radius,
length: length,
width: width,
animation: 'ladda-spinner-line-fade',
zIndex: 'auto',
top: 'auto',
left: 'auto',
className: ''
});
}
function wrapContent(node, wrapper) {
var r = document.createRange();
r.selectNodeContents(node);
r.surroundContents(wrapper);
node.appendChild(wrapper);
}
function bindElement(element, options) {
if (typeof element.addEventListener !== 'function') {
return;
}
var instance = create(element);
var timeout = -1;
element.addEventListener('click', function () {
// If the button belongs to a form, make sure all the
// fields in that form are filled out
var valid = true;
var form = getAncestorOfTagType(element, 'FORM');
if (typeof form !== 'undefined' && !form.hasAttribute('novalidate')) {
// Modern form validation
if (typeof form.checkValidity === 'function') {
valid = form.checkValidity();
}
}
if (valid) {
// This is asynchronous to avoid an issue where disabling
// the button prevents forms from submitting
instance.startAfter(1);
// Set a loading timeout if one is specified
if (typeof options.timeout === 'number') {
clearTimeout(timeout);
timeout = setTimeout(instance.stop, options.timeout);
}
// Invoke callbacks
if (typeof options.callback === 'function') {
options.callback.apply(null, [instance]);
}
}
}, false);
}
ES6在线编译ES5工具地址