prvi
This commit is contained in:
317
ZpcBulletinBoard/wwwroot/lib/ladda/js/ladda.js
Normal file
317
ZpcBulletinBoard/wwwroot/lib/ladda/js/ladda.js
Normal file
@@ -0,0 +1,317 @@
|
||||
/*!
|
||||
* 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 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 spinner;
|
||||
|
||||
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);
|
||||
}
|
||||
Reference in New Issue
Block a user