mirror of
https://github.com/lnbits/lnbits-legend.git
synced 2025-02-24 14:51:05 +01:00
* remove static/vendor * add node dependencies * add bolt11-decoder * run npm install inside dockerimage * only use bundle.js and bundle.css * use node_modules for bundling vendor assets * remove dead code * make argument optional * reintroduce vendor dir * reintroduce vendor and single javascript files, minification * wrong moment, remove minification * lock packages with non critical issues * black
37923 lines
1 MiB
37923 lines
1 MiB
/*!
|
|
* Quasar Framework v1.13.2
|
|
* (c) 2015-present Razvan Stoenescu
|
|
* Released under the MIT License.
|
|
*/
|
|
|
|
(function (global, factory) {
|
|
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('vue')) :
|
|
typeof define === 'function' && define.amd ? define(['vue'], factory) :
|
|
(global = global || self, global.Quasar = factory(global.Vue));
|
|
}(this, (function (Vue) { 'use strict';
|
|
|
|
Vue = Vue && Object.prototype.hasOwnProperty.call(Vue, 'default') ? Vue['default'] : Vue;
|
|
|
|
var version = "1.13.2";
|
|
|
|
/* eslint-disable no-useless-escape */
|
|
|
|
var isSSR = typeof window === 'undefined';
|
|
var fromSSR = false;
|
|
var onSSR = isSSR;
|
|
|
|
var iosEmulated = false;
|
|
var iosCorrection;
|
|
|
|
function getMatch (userAgent, platformMatch) {
|
|
var match = /(edge|edga|edgios)\/([\w.]+)/.exec(userAgent) ||
|
|
/(opr)[\/]([\w.]+)/.exec(userAgent) ||
|
|
/(vivaldi)[\/]([\w.]+)/.exec(userAgent) ||
|
|
/(chrome|crios)[\/]([\w.]+)/.exec(userAgent) ||
|
|
/(iemobile)[\/]([\w.]+)/.exec(userAgent) ||
|
|
/(version)(applewebkit)[\/]([\w.]+).*(safari)[\/]([\w.]+)/.exec(userAgent) ||
|
|
/(webkit)[\/]([\w.]+).*(version)[\/]([\w.]+).*(safari)[\/]([\w.]+)/.exec(userAgent) ||
|
|
/(firefox|fxios)[\/]([\w.]+)/.exec(userAgent) ||
|
|
/(webkit)[\/]([\w.]+)/.exec(userAgent) ||
|
|
/(opera)(?:.*version|)[\/]([\w.]+)/.exec(userAgent) ||
|
|
/(msie) ([\w.]+)/.exec(userAgent) ||
|
|
(userAgent.indexOf('trident') >= 0 && /(rv)(?::| )([\w.]+)/.exec(userAgent)) ||
|
|
(userAgent.indexOf('compatible') < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(userAgent)) ||
|
|
[];
|
|
|
|
return {
|
|
browser: match[5] || match[3] || match[1] || '',
|
|
version: match[2] || match[4] || '0',
|
|
versionNumber: match[4] || match[2] || '0',
|
|
platform: platformMatch[0] || ''
|
|
}
|
|
}
|
|
|
|
function getPlatformMatch (userAgent) {
|
|
return /(ipad)/.exec(userAgent) ||
|
|
/(ipod)/.exec(userAgent) ||
|
|
/(windows phone)/.exec(userAgent) ||
|
|
/(iphone)/.exec(userAgent) ||
|
|
/(kindle)/.exec(userAgent) ||
|
|
/(silk)/.exec(userAgent) ||
|
|
/(android)/.exec(userAgent) ||
|
|
/(win)/.exec(userAgent) ||
|
|
/(mac)/.exec(userAgent) ||
|
|
/(linux)/.exec(userAgent) ||
|
|
/(cros)/.exec(userAgent) ||
|
|
/(playbook)/.exec(userAgent) ||
|
|
/(bb)/.exec(userAgent) ||
|
|
/(blackberry)/.exec(userAgent) ||
|
|
[]
|
|
}
|
|
|
|
var hasTouch = isSSR === false
|
|
? 'ontouchstart' in window || window.navigator.maxTouchPoints > 0
|
|
: false;
|
|
|
|
function applyIosCorrection (is) {
|
|
var obj;
|
|
|
|
iosCorrection = { is: Object.assign({}, is) };
|
|
|
|
delete is.mac;
|
|
delete is.desktop;
|
|
|
|
var platform = Math.min(window.innerHeight, window.innerWidth) > 414
|
|
? 'ipad'
|
|
: 'iphone';
|
|
|
|
Object.assign(is, ( obj = {
|
|
mobile: true,
|
|
ios: true,
|
|
platform: platform
|
|
}, obj[ platform ] = true, obj ));
|
|
}
|
|
|
|
function getPlatform (UA) {
|
|
var
|
|
userAgent = UA.toLowerCase(),
|
|
platformMatch = getPlatformMatch(userAgent),
|
|
matched = getMatch(userAgent, platformMatch),
|
|
browser = {};
|
|
|
|
if (matched.browser) {
|
|
browser[matched.browser] = true;
|
|
browser.version = matched.version;
|
|
browser.versionNumber = parseInt(matched.versionNumber, 10);
|
|
}
|
|
|
|
if (matched.platform) {
|
|
browser[matched.platform] = true;
|
|
}
|
|
|
|
var knownMobiles = browser.android ||
|
|
browser.ios ||
|
|
browser.bb ||
|
|
browser.blackberry ||
|
|
browser.ipad ||
|
|
browser.iphone ||
|
|
browser.ipod ||
|
|
browser.kindle ||
|
|
browser.playbook ||
|
|
browser.silk ||
|
|
browser['windows phone'];
|
|
|
|
// These are all considered mobile platforms, meaning they run a mobile browser
|
|
if (knownMobiles === true || userAgent.indexOf('mobile') > -1) {
|
|
browser.mobile = true;
|
|
|
|
if (browser.edga || browser.edgios) {
|
|
browser.edge = true;
|
|
matched.browser = 'edge';
|
|
}
|
|
else if (browser.crios) {
|
|
browser.chrome = true;
|
|
matched.browser = 'chrome';
|
|
}
|
|
else if (browser.fxios) {
|
|
browser.firefox = true;
|
|
matched.browser = 'firefox';
|
|
}
|
|
}
|
|
// If it's not mobile we should consider it's desktop platform, meaning it runs a desktop browser
|
|
// It's a workaround for anonymized user agents
|
|
// (browser.cros || browser.mac || browser.linux || browser.win)
|
|
else {
|
|
browser.desktop = true;
|
|
}
|
|
|
|
// Set iOS if on iPod, iPad or iPhone
|
|
if (browser.ipod || browser.ipad || browser.iphone) {
|
|
browser.ios = true;
|
|
}
|
|
|
|
if (browser['windows phone']) {
|
|
browser.winphone = true;
|
|
delete browser['windows phone'];
|
|
}
|
|
|
|
// Chrome, Opera 15+, Vivaldi and Safari are webkit based browsers
|
|
if (
|
|
browser.chrome ||
|
|
browser.opr ||
|
|
browser.safari ||
|
|
browser.vivaldi ||
|
|
// we expect unknown, non iOS mobile browsers to be webkit based
|
|
(
|
|
browser.mobile === true &&
|
|
browser.ios !== true &&
|
|
knownMobiles !== true
|
|
)
|
|
) {
|
|
browser.webkit = true;
|
|
}
|
|
|
|
// IE11 has a new token so we will assign it msie to avoid breaking changes
|
|
if (browser.rv || browser.iemobile) {
|
|
matched.browser = 'ie';
|
|
browser.ie = true;
|
|
}
|
|
|
|
// Blackberry browsers are marked as Safari on BlackBerry
|
|
if (browser.safari && browser.blackberry || browser.bb) {
|
|
matched.browser = 'blackberry';
|
|
browser.blackberry = true;
|
|
}
|
|
|
|
// Playbook browsers are marked as Safari on Playbook
|
|
if (browser.safari && browser.playbook) {
|
|
matched.browser = 'playbook';
|
|
browser.playbook = true;
|
|
}
|
|
|
|
// Opera 15+ are identified as opr
|
|
if (browser.opr) {
|
|
matched.browser = 'opera';
|
|
browser.opera = true;
|
|
}
|
|
|
|
// Stock Android browsers are marked as Safari on Android.
|
|
if (browser.safari && browser.android) {
|
|
matched.browser = 'android';
|
|
browser.android = true;
|
|
}
|
|
|
|
// Kindle browsers are marked as Safari on Kindle
|
|
if (browser.safari && browser.kindle) {
|
|
matched.browser = 'kindle';
|
|
browser.kindle = true;
|
|
}
|
|
|
|
// Kindle Silk browsers are marked as Safari on Kindle
|
|
if (browser.safari && browser.silk) {
|
|
matched.browser = 'silk';
|
|
browser.silk = true;
|
|
}
|
|
|
|
if (browser.vivaldi) {
|
|
matched.browser = 'vivaldi';
|
|
browser.vivaldi = true;
|
|
}
|
|
|
|
// Assign the name and platform variable
|
|
browser.name = matched.browser;
|
|
browser.platform = matched.platform;
|
|
|
|
if (isSSR === false) {
|
|
if (userAgent.indexOf('electron') > -1) {
|
|
browser.electron = true;
|
|
}
|
|
else if (document.location.href.indexOf('-extension://') > -1) {
|
|
browser.bex = true;
|
|
}
|
|
else {
|
|
if (window.Capacitor !== void 0) {
|
|
browser.capacitor = true;
|
|
browser.nativeMobile = true;
|
|
browser.nativeMobileWrapper = 'capacitor';
|
|
}
|
|
else if (window._cordovaNative !== void 0 || window.cordova !== void 0) {
|
|
browser.cordova = true;
|
|
browser.nativeMobile = true;
|
|
browser.nativeMobileWrapper = 'cordova';
|
|
}
|
|
|
|
if (
|
|
hasTouch === true &&
|
|
browser.mac === true &&
|
|
(
|
|
(browser.desktop === true && browser.safari === true) ||
|
|
(
|
|
browser.nativeMobile === true &&
|
|
browser.android !== true &&
|
|
browser.ios !== true &&
|
|
browser.ipad !== true
|
|
)
|
|
)
|
|
) {
|
|
/*
|
|
* Correction needed for iOS since the default
|
|
* setting on iPad is to request desktop view; if we have
|
|
* touch support and the user agent says it's a
|
|
* desktop, we infer that it's an iPhone/iPad with desktop view
|
|
* so we must fix the false positives
|
|
*/
|
|
applyIosCorrection(browser);
|
|
}
|
|
}
|
|
|
|
fromSSR = browser.nativeMobile === void 0 &&
|
|
browser.electron === void 0 &&
|
|
document.querySelector('[data-server-rendered]') !== null;
|
|
|
|
if (fromSSR === true) {
|
|
onSSR = true;
|
|
}
|
|
}
|
|
|
|
return browser
|
|
}
|
|
|
|
var userAgent = isSSR !== true
|
|
? navigator.userAgent || navigator.vendor || window.opera
|
|
: '';
|
|
|
|
var ssrClient = {
|
|
has: {
|
|
touch: false,
|
|
webStorage: false
|
|
},
|
|
within: { iframe: false }
|
|
};
|
|
|
|
// We export "client" for hydration error-free parts,
|
|
// like touch directives who do not (and must NOT) wait
|
|
// for the client takeover;
|
|
// Do NOT import this directly in your app, unless you really know
|
|
// what you are doing.
|
|
var client = isSSR === false
|
|
? {
|
|
userAgent: userAgent,
|
|
is: getPlatform(userAgent),
|
|
has: {
|
|
touch: hasTouch,
|
|
webStorage: (function () {
|
|
try {
|
|
if (window.localStorage) {
|
|
return true
|
|
}
|
|
}
|
|
catch (e) {}
|
|
return false
|
|
})()
|
|
},
|
|
within: {
|
|
iframe: window.self !== window.top
|
|
}
|
|
}
|
|
: ssrClient;
|
|
|
|
var Platform = {
|
|
install: function install ($q, queues) {
|
|
var this$1 = this;
|
|
|
|
if (isSSR === true) {
|
|
// we're on server-side, so we push
|
|
// to the server queue instead of
|
|
// applying directly
|
|
queues.server.push(function (q, ctx) {
|
|
q.platform = this$1.parseSSR(ctx.ssr);
|
|
});
|
|
}
|
|
else if (fromSSR === true) {
|
|
// must match with server-side before
|
|
// client taking over in order to prevent
|
|
// hydration errors
|
|
Object.assign(this, client, iosCorrection, ssrClient);
|
|
|
|
// takeover should increase accuracy for
|
|
// the rest of the props; we also avoid
|
|
// hydration errors
|
|
queues.takeover.push(function (q) {
|
|
onSSR = fromSSR = false;
|
|
Object.assign(q.platform, client);
|
|
iosCorrection = void 0;
|
|
});
|
|
|
|
// we need to make platform reactive
|
|
// for the takeover phase
|
|
Vue.util.defineReactive($q, 'platform', this);
|
|
}
|
|
else {
|
|
// we don't have any business with SSR, so
|
|
// directly applying...
|
|
Object.assign(this, client);
|
|
$q.platform = this;
|
|
}
|
|
}
|
|
};
|
|
|
|
if (isSSR === true) {
|
|
Platform.parseSSR = function (/* ssrContext */ ssr) {
|
|
var userAgent = ssr.req.headers['user-agent'] || ssr.req.headers['User-Agent'] || '';
|
|
return Object.assign({}, client,
|
|
{userAgent: userAgent,
|
|
is: getPlatform(userAgent)})
|
|
};
|
|
}
|
|
else {
|
|
iosEmulated = client.is.ios === true &&
|
|
window.navigator.vendor.toLowerCase().indexOf('apple') === -1;
|
|
}
|
|
|
|
var listenOpts = {
|
|
hasPassive: false,
|
|
passiveCapture: true,
|
|
notPassiveCapture: true
|
|
};
|
|
|
|
try {
|
|
var opts = Object.defineProperty({}, 'passive', {
|
|
get: function get () {
|
|
Object.assign(listenOpts, {
|
|
hasPassive: true,
|
|
passive: { passive: true },
|
|
notPassive: { passive: false },
|
|
passiveCapture: { passive: true, capture: true },
|
|
notPassiveCapture: { passive: false, capture: true }
|
|
});
|
|
}
|
|
});
|
|
window.addEventListener('qtest', null, opts);
|
|
window.removeEventListener('qtest', null, opts);
|
|
}
|
|
catch (e) {}
|
|
|
|
function noop () {}
|
|
|
|
function leftClick (e) {
|
|
return e.button === 0
|
|
}
|
|
|
|
function middleClick (e) {
|
|
return e.button === 1
|
|
}
|
|
|
|
function rightClick (e) {
|
|
return e.button === 2
|
|
}
|
|
|
|
function position (e) {
|
|
if (e.touches && e.touches[0]) {
|
|
e = e.touches[0];
|
|
}
|
|
else if (e.changedTouches && e.changedTouches[0]) {
|
|
e = e.changedTouches[0];
|
|
}
|
|
else if (e.targetTouches && e.targetTouches[0]) {
|
|
e = e.targetTouches[0];
|
|
}
|
|
|
|
return {
|
|
top: e.clientY,
|
|
left: e.clientX
|
|
}
|
|
}
|
|
|
|
function getEventPath (e) {
|
|
if (e.path) {
|
|
return e.path
|
|
}
|
|
if (e.composedPath) {
|
|
return e.composedPath()
|
|
}
|
|
|
|
var path = [];
|
|
var el = e.target;
|
|
|
|
while (el) {
|
|
path.push(el);
|
|
|
|
if (el.tagName === 'HTML') {
|
|
path.push(document);
|
|
path.push(window);
|
|
return path
|
|
}
|
|
|
|
el = el.parentElement;
|
|
}
|
|
}
|
|
|
|
// Reasonable defaults
|
|
var
|
|
LINE_HEIGHT = 40,
|
|
PAGE_HEIGHT = 800;
|
|
|
|
function getMouseWheelDistance (e) {
|
|
var assign;
|
|
|
|
var x = e.deltaX, y = e.deltaY;
|
|
|
|
if ((x || y) && e.deltaMode) {
|
|
var multiplier = e.deltaMode === 1 ? LINE_HEIGHT : PAGE_HEIGHT;
|
|
x *= multiplier;
|
|
y *= multiplier;
|
|
}
|
|
|
|
if (e.shiftKey && !x) {
|
|
(assign = [x, y], y = assign[0], x = assign[1]);
|
|
}
|
|
|
|
return { x: x, y: y }
|
|
}
|
|
|
|
function stop (e) {
|
|
e.stopPropagation();
|
|
}
|
|
|
|
function prevent (e) {
|
|
e.cancelable !== false && e.preventDefault();
|
|
}
|
|
|
|
function stopAndPrevent (e) {
|
|
e.cancelable !== false && e.preventDefault();
|
|
e.stopPropagation();
|
|
}
|
|
|
|
function preventDraggable (el, status) {
|
|
if (el === void 0 || (status === true && el.__dragPrevented === true)) {
|
|
return
|
|
}
|
|
|
|
var fn = status === true
|
|
? function (el) {
|
|
el.__dragPrevented = true;
|
|
el.addEventListener('dragstart', prevent, listenOpts.notPassiveCapture);
|
|
}
|
|
: function (el) {
|
|
delete el.__dragPrevented;
|
|
el.removeEventListener('dragstart', prevent, listenOpts.notPassiveCapture);
|
|
};
|
|
|
|
el.querySelectorAll('a, img').forEach(fn);
|
|
}
|
|
|
|
function create (name, ref) {
|
|
if ( ref === void 0 ) ref = {};
|
|
var bubbles = ref.bubbles; if ( bubbles === void 0 ) bubbles = false;
|
|
var cancelable = ref.cancelable; if ( cancelable === void 0 ) cancelable = false;
|
|
|
|
try {
|
|
return new Event(name, { bubbles: bubbles, cancelable: cancelable })
|
|
}
|
|
catch (e) {
|
|
// IE doesn't support `new Event()`, so...
|
|
var evt = document.createEvent('Event');
|
|
evt.initEvent(name, bubbles, cancelable);
|
|
return evt
|
|
}
|
|
}
|
|
|
|
function addEvt (ctx, targetName, events) {
|
|
var name = "__q_" + targetName + "_evt";
|
|
|
|
ctx[name] = ctx[name] !== void 0
|
|
? ctx[name].concat(events)
|
|
: events;
|
|
|
|
events.forEach(function (evt) {
|
|
evt[0].addEventListener(evt[1], ctx[evt[2]], listenOpts[evt[3]]);
|
|
});
|
|
}
|
|
|
|
function cleanEvt (ctx, targetName) {
|
|
var name = "__q_" + targetName + "_evt";
|
|
|
|
if (ctx[name] !== void 0) {
|
|
ctx[name].forEach(function (evt) {
|
|
evt[0].removeEventListener(evt[1], ctx[evt[2]], listenOpts[evt[3]]);
|
|
});
|
|
ctx[name] = void 0;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* also update /types/utils/event.d.ts
|
|
*/
|
|
|
|
var event = {
|
|
listenOpts: listenOpts,
|
|
leftClick: leftClick,
|
|
middleClick: middleClick,
|
|
rightClick: rightClick,
|
|
position: position,
|
|
getEventPath: getEventPath,
|
|
getMouseWheelDistance: getMouseWheelDistance,
|
|
stop: stop,
|
|
prevent: prevent,
|
|
stopAndPrevent: stopAndPrevent,
|
|
preventDraggable: preventDraggable,
|
|
create: create
|
|
};
|
|
|
|
function debounce (fn, wait, immediate) {
|
|
if ( wait === void 0 ) wait = 250;
|
|
|
|
var timeout;
|
|
|
|
function debounced (/* ...args */) {
|
|
var this$1 = this;
|
|
|
|
var args = arguments;
|
|
|
|
var later = function () {
|
|
timeout = void 0;
|
|
if (immediate !== true) {
|
|
fn.apply(this$1, args);
|
|
}
|
|
};
|
|
|
|
clearTimeout(timeout);
|
|
if (immediate === true && timeout === void 0) {
|
|
fn.apply(this, args);
|
|
}
|
|
timeout = setTimeout(later, wait);
|
|
}
|
|
|
|
debounced.cancel = function () {
|
|
clearTimeout(timeout);
|
|
};
|
|
|
|
return debounced
|
|
}
|
|
|
|
var SIZE_LIST = ['sm', 'md', 'lg', 'xl'];
|
|
var passive = listenOpts.passive;
|
|
|
|
var Screen = {
|
|
width: 0,
|
|
height: 0,
|
|
|
|
name: 'xs',
|
|
|
|
sizes: {
|
|
sm: 600,
|
|
md: 1024,
|
|
lg: 1440,
|
|
xl: 1920
|
|
},
|
|
|
|
lt: {
|
|
sm: true,
|
|
md: true,
|
|
lg: true,
|
|
xl: true
|
|
},
|
|
gt: {
|
|
xs: false,
|
|
sm: false,
|
|
md: false,
|
|
lg: false
|
|
},
|
|
xs: true,
|
|
sm: false,
|
|
md: false,
|
|
lg: false,
|
|
xl: false,
|
|
|
|
setSizes: noop,
|
|
setDebounce: noop,
|
|
|
|
install: function install ($q, queues, cfg) {
|
|
var this$1 = this;
|
|
|
|
if (isSSR === true) {
|
|
$q.screen = this;
|
|
return
|
|
}
|
|
|
|
var classes = cfg.screen !== void 0 && cfg.screen.bodyClasses === true;
|
|
|
|
var update = function (force) {
|
|
var
|
|
w = window.innerWidth,
|
|
h = window.innerHeight;
|
|
|
|
if (h !== this$1.height) {
|
|
this$1.height = h;
|
|
}
|
|
|
|
if (w !== this$1.width) {
|
|
this$1.width = w;
|
|
}
|
|
else if (force !== true) {
|
|
return
|
|
}
|
|
|
|
var s = this$1.sizes;
|
|
|
|
this$1.gt.xs = w >= s.sm;
|
|
this$1.gt.sm = w >= s.md;
|
|
this$1.gt.md = w >= s.lg;
|
|
this$1.gt.lg = w >= s.xl;
|
|
this$1.lt.sm = w < s.sm;
|
|
this$1.lt.md = w < s.md;
|
|
this$1.lt.lg = w < s.lg;
|
|
this$1.lt.xl = w < s.xl;
|
|
this$1.xs = this$1.lt.sm;
|
|
this$1.sm = this$1.gt.xs === true && this$1.lt.md === true;
|
|
this$1.md = this$1.gt.sm === true && this$1.lt.lg === true;
|
|
this$1.lg = this$1.gt.md === true && this$1.lt.xl === true;
|
|
this$1.xl = this$1.gt.lg;
|
|
|
|
s = (this$1.xs === true && 'xs') ||
|
|
(this$1.sm === true && 'sm') ||
|
|
(this$1.md === true && 'md') ||
|
|
(this$1.lg === true && 'lg') ||
|
|
'xl';
|
|
|
|
if (s !== this$1.name) {
|
|
if (classes === true) {
|
|
document.body.classList.remove(("screen--" + (this$1.name)));
|
|
document.body.classList.add(("screen--" + s));
|
|
}
|
|
this$1.name = s;
|
|
}
|
|
};
|
|
|
|
var updateEvt, updateSizes = {}, updateDebounce = 16;
|
|
|
|
this.setSizes = function (sizes) {
|
|
SIZE_LIST.forEach(function (name) {
|
|
if (sizes[name] !== void 0) {
|
|
updateSizes[name] = sizes[name];
|
|
}
|
|
});
|
|
};
|
|
this.setDebounce = function (deb) {
|
|
updateDebounce = deb;
|
|
};
|
|
|
|
var start = function () {
|
|
var
|
|
style = getComputedStyle(document.body),
|
|
target = window.visualViewport !== void 0
|
|
? window.visualViewport
|
|
: window;
|
|
|
|
// if css props available
|
|
if (style.getPropertyValue('--q-size-sm')) {
|
|
SIZE_LIST.forEach(function (name) {
|
|
this$1.sizes[name] = parseInt(style.getPropertyValue(("--q-size-" + name)), 10);
|
|
});
|
|
}
|
|
|
|
this$1.setSizes = function (sizes) {
|
|
SIZE_LIST.forEach(function (name) {
|
|
if (sizes[name]) {
|
|
this$1.sizes[name] = sizes[name];
|
|
}
|
|
});
|
|
update(true);
|
|
};
|
|
|
|
this$1.setDebounce = function (delay) {
|
|
updateEvt !== void 0 && target.removeEventListener('resize', updateEvt, passive);
|
|
updateEvt = delay > 0
|
|
? debounce(update, delay)
|
|
: update;
|
|
target.addEventListener('resize', updateEvt, passive);
|
|
};
|
|
|
|
this$1.setDebounce(updateDebounce);
|
|
|
|
if (Object.keys(updateSizes).length > 0) {
|
|
this$1.setSizes(updateSizes);
|
|
updateSizes = void 0; // free up memory
|
|
}
|
|
else {
|
|
update();
|
|
}
|
|
|
|
// due to optimizations, this would be left out otherwise
|
|
classes === true && this$1.name === 'xs' &&
|
|
document.body.classList.add("screen--xs");
|
|
};
|
|
|
|
if (fromSSR === true) {
|
|
queues.takeover.push(start);
|
|
}
|
|
else {
|
|
start();
|
|
}
|
|
|
|
Vue.util.defineReactive($q, 'screen', this);
|
|
}
|
|
};
|
|
|
|
var Dark = {
|
|
isActive: false,
|
|
mode: false,
|
|
|
|
install: function install ($q, queues, ref) {
|
|
var this$1 = this;
|
|
var dark = ref.dark;
|
|
|
|
this.isActive = dark === true;
|
|
|
|
if (isSSR === true) {
|
|
queues.server.push(function (q, ctx) {
|
|
q.dark = {
|
|
isActive: false,
|
|
mode: false,
|
|
set: function (val) {
|
|
ctx.ssr.Q_BODY_CLASSES = ctx.ssr.Q_BODY_CLASSES
|
|
.replace(' body--light', '')
|
|
.replace(' body--dark', '') + " body--" + (val === true ? 'dark' : 'light');
|
|
|
|
q.dark.isActive = val === true;
|
|
q.dark.mode = val;
|
|
},
|
|
toggle: function () {
|
|
q.dark.set(q.dark.isActive === false);
|
|
}
|
|
};
|
|
|
|
q.dark.set(dark);
|
|
});
|
|
|
|
this.set = noop;
|
|
return
|
|
}
|
|
|
|
var initialVal = dark !== void 0
|
|
? dark
|
|
: false;
|
|
|
|
if (fromSSR === true) {
|
|
var ssrSet = function (val) {
|
|
this$1.__fromSSR = val;
|
|
};
|
|
|
|
var originalSet = this.set;
|
|
|
|
this.set = ssrSet;
|
|
ssrSet(initialVal);
|
|
|
|
queues.takeover.push(function () {
|
|
this$1.set = originalSet;
|
|
this$1.set(this$1.__fromSSR);
|
|
});
|
|
}
|
|
else {
|
|
this.set(initialVal);
|
|
}
|
|
|
|
Vue.util.defineReactive(this, 'isActive', this.isActive);
|
|
Vue.util.defineReactive($q, 'dark', this);
|
|
},
|
|
|
|
set: function set (val) {
|
|
var this$1 = this;
|
|
|
|
this.mode = val;
|
|
|
|
if (val === 'auto') {
|
|
if (this.__media === void 0) {
|
|
this.__media = window.matchMedia('(prefers-color-scheme: dark)');
|
|
this.__updateMedia = function () { this$1.set('auto'); };
|
|
this.__media.addListener(this.__updateMedia);
|
|
}
|
|
|
|
val = this.__media.matches;
|
|
}
|
|
else if (this.__media !== void 0) {
|
|
this.__media.removeListener(this.__updateMedia);
|
|
this.__media = void 0;
|
|
}
|
|
|
|
this.isActive = val === true;
|
|
|
|
document.body.classList.remove(("body--" + (val === true ? 'light' : 'dark')));
|
|
document.body.classList.add(("body--" + (val === true ? 'dark' : 'light')));
|
|
},
|
|
|
|
toggle: function toggle () {
|
|
Dark.set(Dark.isActive === false);
|
|
},
|
|
|
|
__media: void 0
|
|
};
|
|
|
|
var getTrue = function () { return true; };
|
|
|
|
function filterInvalidPath (path) {
|
|
return typeof path === 'string' &&
|
|
path !== '' &&
|
|
path !== '/' &&
|
|
path !== '#/'
|
|
}
|
|
|
|
function normalizeExitPath (path) {
|
|
path.startsWith('#') === true && (path = path.substr(1));
|
|
path.startsWith('/') === false && (path = '/' + path);
|
|
path.endsWith('/') === true && (path = path.substr(0, path.length - 1));
|
|
return '#' + path
|
|
}
|
|
|
|
function getShouldExitFn (cfg) {
|
|
if (cfg.backButtonExit === false) {
|
|
return function () { return false; }
|
|
}
|
|
|
|
if (cfg.backButtonExit === '*') {
|
|
return getTrue
|
|
}
|
|
|
|
// Add default root path
|
|
var exitPaths = [ '#/' ];
|
|
|
|
// Add custom exit paths
|
|
Array.isArray(cfg.backButtonExit) === true && exitPaths.push.apply(
|
|
exitPaths, cfg.backButtonExit.filter(filterInvalidPath).map(normalizeExitPath)
|
|
);
|
|
|
|
return function () { return exitPaths.includes(window.location.hash); }
|
|
}
|
|
|
|
var History = {
|
|
__history: [],
|
|
add: noop,
|
|
remove: noop,
|
|
|
|
install: function install (cfg) {
|
|
var this$1 = this;
|
|
|
|
if (isSSR === true) {
|
|
return
|
|
}
|
|
|
|
var ref = client.is;
|
|
var cordova = ref.cordova;
|
|
var capacitor = ref.capacitor;
|
|
|
|
if (cordova !== true && capacitor !== true) {
|
|
return
|
|
}
|
|
|
|
this.add = function (entry) {
|
|
if (entry.condition === void 0) {
|
|
entry.condition = getTrue;
|
|
}
|
|
this$1.__history.push(entry);
|
|
};
|
|
|
|
this.remove = function (entry) {
|
|
var index = this$1.__history.indexOf(entry);
|
|
if (index >= 0) {
|
|
this$1.__history.splice(index, 1);
|
|
}
|
|
};
|
|
|
|
var shouldExit = getShouldExitFn(
|
|
Object.assign(
|
|
{ backButtonExit: true },
|
|
cfg[cordova === true ? 'cordova' : 'capacitor']
|
|
)
|
|
);
|
|
|
|
var backHandler = function () {
|
|
if (this$1.__history.length) {
|
|
var entry = this$1.__history[this$1.__history.length - 1];
|
|
|
|
if (entry.condition() === true) {
|
|
this$1.__history.pop();
|
|
entry.handler();
|
|
}
|
|
}
|
|
else if (shouldExit() === true) {
|
|
navigator.app.exitApp();
|
|
}
|
|
else {
|
|
window.history.back();
|
|
}
|
|
};
|
|
|
|
if (cordova === true) {
|
|
document.addEventListener('deviceready', function () {
|
|
document.addEventListener('backbutton', backHandler, false);
|
|
});
|
|
}
|
|
else {
|
|
window.Capacitor.Plugins.App.addListener('backButton', backHandler);
|
|
}
|
|
}
|
|
};
|
|
|
|
var langEn = {
|
|
isoName: 'en-us',
|
|
nativeName: 'English (US)',
|
|
label: {
|
|
clear: 'Clear',
|
|
ok: 'OK',
|
|
cancel: 'Cancel',
|
|
close: 'Close',
|
|
set: 'Set',
|
|
select: 'Select',
|
|
reset: 'Reset',
|
|
remove: 'Remove',
|
|
update: 'Update',
|
|
create: 'Create',
|
|
search: 'Search',
|
|
filter: 'Filter',
|
|
refresh: 'Refresh'
|
|
},
|
|
date: {
|
|
days: 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'),
|
|
daysShort: 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'),
|
|
months: 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_'),
|
|
monthsShort: 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'),
|
|
firstDayOfWeek: 0, // 0-6, 0 - Sunday, 1 Monday, ...
|
|
format24h: false,
|
|
pluralDay: 'days'
|
|
},
|
|
table: {
|
|
noData: 'No data available',
|
|
noResults: 'No matching records found',
|
|
loading: 'Loading...',
|
|
selectedRecords: function (rows) {
|
|
return rows === 1
|
|
? '1 record selected.'
|
|
: (rows === 0 ? 'No' : rows) + ' records selected.'
|
|
},
|
|
recordsPerPage: 'Records per page:',
|
|
allRows: 'All',
|
|
pagination: function (start, end, total) {
|
|
return start + '-' + end + ' of ' + total
|
|
},
|
|
columns: 'Columns'
|
|
},
|
|
editor: {
|
|
url: 'URL',
|
|
bold: 'Bold',
|
|
italic: 'Italic',
|
|
strikethrough: 'Strikethrough',
|
|
underline: 'Underline',
|
|
unorderedList: 'Unordered List',
|
|
orderedList: 'Ordered List',
|
|
subscript: 'Subscript',
|
|
superscript: 'Superscript',
|
|
hyperlink: 'Hyperlink',
|
|
toggleFullscreen: 'Toggle Fullscreen',
|
|
quote: 'Quote',
|
|
left: 'Left align',
|
|
center: 'Center align',
|
|
right: 'Right align',
|
|
justify: 'Justify align',
|
|
print: 'Print',
|
|
outdent: 'Decrease indentation',
|
|
indent: 'Increase indentation',
|
|
removeFormat: 'Remove formatting',
|
|
formatting: 'Formatting',
|
|
fontSize: 'Font Size',
|
|
align: 'Align',
|
|
hr: 'Insert Horizontal Rule',
|
|
undo: 'Undo',
|
|
redo: 'Redo',
|
|
heading1: 'Heading 1',
|
|
heading2: 'Heading 2',
|
|
heading3: 'Heading 3',
|
|
heading4: 'Heading 4',
|
|
heading5: 'Heading 5',
|
|
heading6: 'Heading 6',
|
|
paragraph: 'Paragraph',
|
|
code: 'Code',
|
|
size1: 'Very small',
|
|
size2: 'A bit small',
|
|
size3: 'Normal',
|
|
size4: 'Medium-large',
|
|
size5: 'Big',
|
|
size6: 'Very big',
|
|
size7: 'Maximum',
|
|
defaultFont: 'Default Font',
|
|
viewSource: 'View Source'
|
|
},
|
|
tree: {
|
|
noNodes: 'No nodes available',
|
|
noResults: 'No matching nodes found'
|
|
}
|
|
};
|
|
|
|
function getLocale () {
|
|
if (isSSR === true) { return }
|
|
|
|
var val =
|
|
navigator.language ||
|
|
navigator.languages[0] ||
|
|
navigator.browserLanguage ||
|
|
navigator.userLanguage ||
|
|
navigator.systemLanguage;
|
|
|
|
if (val) {
|
|
return val.toLowerCase()
|
|
}
|
|
}
|
|
|
|
var lang = {
|
|
getLocale: getLocale,
|
|
|
|
install: function install ($q, queues, lang) {
|
|
var this$1 = this;
|
|
|
|
var initialLang = lang || langEn;
|
|
|
|
this.set = function (langObject, ssrContext) {
|
|
if ( langObject === void 0 ) langObject = langEn;
|
|
|
|
var lang = Object.assign({}, langObject,
|
|
{rtl: langObject.rtl === true,
|
|
getLocale: getLocale});
|
|
|
|
if (isSSR === true) {
|
|
if (ssrContext === void 0) {
|
|
console.error('SSR ERROR: second param required: Quasar.lang.set(lang, ssrContext)');
|
|
return
|
|
}
|
|
|
|
var dir = lang.rtl === true ? 'rtl' : 'ltr';
|
|
var attrs = "lang=" + (lang.isoName) + " dir=" + dir;
|
|
|
|
lang.set = ssrContext.$q.lang.set;
|
|
|
|
ssrContext.Q_HTML_ATTRS = ssrContext.Q_PREV_LANG !== void 0
|
|
? ssrContext.Q_HTML_ATTRS.replace(ssrContext.Q_PREV_LANG, attrs)
|
|
: attrs;
|
|
|
|
ssrContext.Q_PREV_LANG = attrs;
|
|
ssrContext.$q.lang = lang;
|
|
}
|
|
else {
|
|
if (fromSSR === false) {
|
|
var el = document.documentElement;
|
|
el.setAttribute('dir', lang.rtl === true ? 'rtl' : 'ltr');
|
|
el.setAttribute('lang', lang.isoName);
|
|
}
|
|
|
|
lang.set = this$1.set;
|
|
$q.lang = this$1.props = lang;
|
|
this$1.isoName = lang.isoName;
|
|
this$1.nativeName = lang.nativeName;
|
|
}
|
|
};
|
|
|
|
if (isSSR === true) {
|
|
queues.server.push(function (q, ctx) {
|
|
q.lang = {};
|
|
q.lang.set = function (langObject) {
|
|
this$1.set(langObject, ctx.ssr);
|
|
};
|
|
|
|
q.lang.set(initialLang);
|
|
});
|
|
|
|
this.isoName = initialLang.isoName;
|
|
this.nativeName = initialLang.nativeName;
|
|
this.props = initialLang;
|
|
}
|
|
else {
|
|
Vue.util.defineReactive($q, 'lang', {});
|
|
this.set(initialLang);
|
|
}
|
|
}
|
|
};
|
|
|
|
var reRGBA = /^rgb(a)?\((\d{1,3}),(\d{1,3}),(\d{1,3}),?([01]?\.?\d*?)?\)$/;
|
|
|
|
function rgbToHex (ref) {
|
|
var r = ref.r;
|
|
var g = ref.g;
|
|
var b = ref.b;
|
|
var a = ref.a;
|
|
|
|
var alpha = a !== void 0;
|
|
|
|
r = Math.round(r);
|
|
g = Math.round(g);
|
|
b = Math.round(b);
|
|
|
|
if (
|
|
r > 255 ||
|
|
g > 255 ||
|
|
b > 255 ||
|
|
(alpha && a > 100)
|
|
) {
|
|
throw new TypeError('Expected 3 numbers below 256 (and optionally one below 100)')
|
|
}
|
|
|
|
a = alpha
|
|
? (Math.round(255 * a / 100) | 1 << 8).toString(16).slice(1)
|
|
: '';
|
|
|
|
return '#' + ((b | g << 8 | r << 16) | 1 << 24).toString(16).slice(1) + a
|
|
}
|
|
|
|
function rgbToString (ref) {
|
|
var r = ref.r;
|
|
var g = ref.g;
|
|
var b = ref.b;
|
|
var a = ref.a;
|
|
|
|
return ("rgb" + (a !== void 0 ? 'a' : '') + "(" + r + "," + g + "," + b + (a !== void 0 ? ',' + (a / 100) : '') + ")")
|
|
}
|
|
|
|
function hexToRgb (hex) {
|
|
if (typeof hex !== 'string') {
|
|
throw new TypeError('Expected a string')
|
|
}
|
|
|
|
hex = hex.replace(/^#/, '');
|
|
|
|
if (hex.length === 3) {
|
|
hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];
|
|
}
|
|
else if (hex.length === 4) {
|
|
hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2] + hex[3] + hex[3];
|
|
}
|
|
|
|
var num = parseInt(hex, 16);
|
|
|
|
return hex.length > 6
|
|
? { r: num >> 24 & 255, g: num >> 16 & 255, b: num >> 8 & 255, a: Math.round((num & 255) / 2.55) }
|
|
: { r: num >> 16, g: num >> 8 & 255, b: num & 255 }
|
|
}
|
|
|
|
function hsvToRgb (ref) {
|
|
var h = ref.h;
|
|
var s = ref.s;
|
|
var v = ref.v;
|
|
var a = ref.a;
|
|
|
|
var r, g, b;
|
|
s = s / 100;
|
|
v = v / 100;
|
|
|
|
h = h / 360;
|
|
var
|
|
i = Math.floor(h * 6),
|
|
f = h * 6 - i,
|
|
p = v * (1 - s),
|
|
q = v * (1 - f * s),
|
|
t = v * (1 - (1 - f) * s);
|
|
|
|
switch (i % 6) {
|
|
case 0:
|
|
r = v;
|
|
g = t;
|
|
b = p;
|
|
break
|
|
case 1:
|
|
r = q;
|
|
g = v;
|
|
b = p;
|
|
break
|
|
case 2:
|
|
r = p;
|
|
g = v;
|
|
b = t;
|
|
break
|
|
case 3:
|
|
r = p;
|
|
g = q;
|
|
b = v;
|
|
break
|
|
case 4:
|
|
r = t;
|
|
g = p;
|
|
b = v;
|
|
break
|
|
case 5:
|
|
r = v;
|
|
g = p;
|
|
b = q;
|
|
break
|
|
}
|
|
|
|
return {
|
|
r: Math.round(r * 255),
|
|
g: Math.round(g * 255),
|
|
b: Math.round(b * 255),
|
|
a: a
|
|
}
|
|
}
|
|
|
|
function rgbToHsv (ref) {
|
|
var r = ref.r;
|
|
var g = ref.g;
|
|
var b = ref.b;
|
|
var a = ref.a;
|
|
|
|
var
|
|
max = Math.max(r, g, b),
|
|
min = Math.min(r, g, b),
|
|
d = max - min,
|
|
s = (max === 0 ? 0 : d / max),
|
|
v = max / 255;
|
|
var h;
|
|
|
|
switch (max) {
|
|
case min:
|
|
h = 0;
|
|
break
|
|
case r:
|
|
h = (g - b) + d * (g < b ? 6 : 0);
|
|
h /= 6 * d;
|
|
break
|
|
case g:
|
|
h = (b - r) + d * 2;
|
|
h /= 6 * d;
|
|
break
|
|
case b:
|
|
h = (r - g) + d * 4;
|
|
h /= 6 * d;
|
|
break
|
|
}
|
|
|
|
return {
|
|
h: Math.round(h * 360),
|
|
s: Math.round(s * 100),
|
|
v: Math.round(v * 100),
|
|
a: a
|
|
}
|
|
}
|
|
|
|
function textToRgb (str) {
|
|
if (typeof str !== 'string') {
|
|
throw new TypeError('Expected a string')
|
|
}
|
|
|
|
var color = str.replace(/ /g, '');
|
|
|
|
var m = reRGBA.exec(color);
|
|
|
|
if (m === null) {
|
|
return hexToRgb(color)
|
|
}
|
|
|
|
var rgb = {
|
|
r: Math.min(255, parseInt(m[2], 10)),
|
|
g: Math.min(255, parseInt(m[3], 10)),
|
|
b: Math.min(255, parseInt(m[4], 10))
|
|
};
|
|
|
|
if (m[1]) {
|
|
var alpha = parseFloat(m[5]);
|
|
rgb.a = Math.min(1, isNaN(alpha) === true ? 1 : alpha) * 100;
|
|
}
|
|
|
|
return rgb
|
|
}
|
|
|
|
/* works as darken if percent < 0 */
|
|
function lighten (color, percent) {
|
|
if (typeof color !== 'string') {
|
|
throw new TypeError('Expected a string as color')
|
|
}
|
|
if (typeof percent !== 'number') {
|
|
throw new TypeError('Expected a numeric percent')
|
|
}
|
|
|
|
var rgb = textToRgb(color),
|
|
t = percent < 0 ? 0 : 255,
|
|
p = Math.abs(percent) / 100,
|
|
R = rgb.r,
|
|
G = rgb.g,
|
|
B = rgb.b;
|
|
|
|
return '#' + (
|
|
0x1000000 + (Math.round((t - R) * p) + R) * 0x10000 +
|
|
(Math.round((t - G) * p) + G) * 0x100 +
|
|
(Math.round((t - B) * p) + B)
|
|
).toString(16).slice(1)
|
|
}
|
|
|
|
function luminosity (color) {
|
|
if (typeof color !== 'string' && (!color || color.r === void 0)) {
|
|
throw new TypeError('Expected a string or a {r, g, b} object as color')
|
|
}
|
|
|
|
var
|
|
rgb = typeof color === 'string' ? textToRgb(color) : color,
|
|
r = rgb.r / 255,
|
|
g = rgb.g / 255,
|
|
b = rgb.b / 255,
|
|
R = r <= 0.03928 ? r / 12.92 : Math.pow((r + 0.055) / 1.055, 2.4),
|
|
G = g <= 0.03928 ? g / 12.92 : Math.pow((g + 0.055) / 1.055, 2.4),
|
|
B = b <= 0.03928 ? b / 12.92 : Math.pow((b + 0.055) / 1.055, 2.4);
|
|
return 0.2126 * R + 0.7152 * G + 0.0722 * B
|
|
}
|
|
|
|
function brightness (color) {
|
|
if (typeof color !== 'string' && (!color || color.r === void 0)) {
|
|
throw new TypeError('Expected a string or a {r, g, b} object as color')
|
|
}
|
|
|
|
var rgb = typeof color === 'string'
|
|
? textToRgb(color)
|
|
: color;
|
|
|
|
return (rgb.r * 299 + rgb.g * 587 + rgb.b * 114) / 1000
|
|
}
|
|
|
|
function blend (fgColor, bgColor) {
|
|
if (typeof fgColor !== 'string' && (!fgColor || fgColor.r === void 0)) {
|
|
throw new TypeError('Expected a string or a {r, g, b[, a]} object as fgColor')
|
|
}
|
|
|
|
if (typeof bgColor !== 'string' && (!bgColor || bgColor.r === void 0)) {
|
|
throw new TypeError('Expected a string or a {r, g, b[, a]} object as bgColor')
|
|
}
|
|
|
|
var
|
|
rgb1 = typeof fgColor === 'string' ? textToRgb(fgColor) : fgColor,
|
|
r1 = rgb1.r / 255,
|
|
g1 = rgb1.g / 255,
|
|
b1 = rgb1.b / 255,
|
|
a1 = rgb1.a !== void 0 ? rgb1.a / 100 : 1,
|
|
rgb2 = typeof bgColor === 'string' ? textToRgb(bgColor) : bgColor,
|
|
r2 = rgb2.r / 255,
|
|
g2 = rgb2.g / 255,
|
|
b2 = rgb2.b / 255,
|
|
a2 = rgb2.a !== void 0 ? rgb2.a / 100 : 1,
|
|
a = a1 + a2 * (1 - a1),
|
|
r = Math.round(((r1 * a1 + r2 * a2 * (1 - a1)) / a) * 255),
|
|
g = Math.round(((g1 * a1 + g2 * a2 * (1 - a1)) / a) * 255),
|
|
b = Math.round(((b1 * a1 + b2 * a2 * (1 - a1)) / a) * 255);
|
|
|
|
var ret = { r: r, g: g, b: b, a: Math.round(a * 100) };
|
|
return typeof fgColor === 'string'
|
|
? rgbToHex(ret)
|
|
: ret
|
|
}
|
|
|
|
function changeAlpha (color, offset) {
|
|
if (typeof color !== 'string') {
|
|
throw new TypeError('Expected a string as color')
|
|
}
|
|
|
|
if (offset === void 0 || offset < -1 || offset > 1) {
|
|
throw new TypeError('Expected offset to be between -1 and 1')
|
|
}
|
|
|
|
var ref = textToRgb(color);
|
|
var r = ref.r;
|
|
var g = ref.g;
|
|
var b = ref.b;
|
|
var a = ref.a;
|
|
var alpha = a !== void 0 ? a / 100 : 0;
|
|
|
|
return rgbToHex({
|
|
r: r, g: g, b: b, a: Math.round(Math.min(1, Math.max(0, alpha + offset)) * 100)
|
|
})
|
|
}
|
|
|
|
function setBrand (color, value, element) {
|
|
if ( element === void 0 ) element = document.body;
|
|
|
|
if (typeof color !== 'string') {
|
|
throw new TypeError('Expected a string as color')
|
|
}
|
|
if (typeof value !== 'string') {
|
|
throw new TypeError('Expected a string as value')
|
|
}
|
|
if (!(element instanceof Element)) {
|
|
throw new TypeError('Expected a DOM element')
|
|
}
|
|
|
|
element.style.setProperty(("--q-color-" + color), value);
|
|
}
|
|
|
|
function getBrand (color, element) {
|
|
if ( element === void 0 ) element = document.body;
|
|
|
|
if (typeof color !== 'string') {
|
|
throw new TypeError('Expected a string as color')
|
|
}
|
|
if (!(element instanceof Element)) {
|
|
throw new TypeError('Expected a DOM element')
|
|
}
|
|
|
|
return getComputedStyle(element).getPropertyValue(("--q-color-" + color)).trim() || null
|
|
}
|
|
|
|
function getPaletteColor (colorName) {
|
|
if (typeof colorName !== 'string') {
|
|
throw new TypeError('Expected a string as color')
|
|
}
|
|
|
|
var el = document.createElement('div');
|
|
|
|
el.className = "text-" + colorName + " invisible fixed no-pointer-events";
|
|
document.body.appendChild(el);
|
|
|
|
var result = getComputedStyle(el).getPropertyValue('color');
|
|
|
|
el.remove();
|
|
|
|
return rgbToHex(textToRgb(result))
|
|
}
|
|
|
|
var colors = {
|
|
rgbToHex: rgbToHex,
|
|
hexToRgb: hexToRgb,
|
|
hsvToRgb: hsvToRgb,
|
|
rgbToHsv: rgbToHsv,
|
|
textToRgb: textToRgb,
|
|
lighten: lighten,
|
|
luminosity: luminosity,
|
|
brightness: brightness,
|
|
blend: blend,
|
|
changeAlpha: changeAlpha,
|
|
setBrand: setBrand,
|
|
getBrand: getBrand,
|
|
getPaletteColor: getPaletteColor
|
|
};
|
|
|
|
var lastKeyCompositionStatus = false;
|
|
|
|
function onKeyDownComposition (evt) {
|
|
lastKeyCompositionStatus = evt.isComposing === true;
|
|
}
|
|
|
|
function shouldIgnoreKey (evt) {
|
|
return lastKeyCompositionStatus === true ||
|
|
evt !== Object(evt) ||
|
|
evt.isComposing === true ||
|
|
evt.qKeyEvent === true
|
|
}
|
|
|
|
function isKeyCode (evt, keyCodes) {
|
|
return shouldIgnoreKey(evt) === true
|
|
? false
|
|
: [].concat(keyCodes).includes(evt.keyCode)
|
|
}
|
|
|
|
function getMobilePlatform (is) {
|
|
if (is.ios === true) { return 'ios' }
|
|
if (is.android === true) { return 'android' }
|
|
}
|
|
|
|
function getBodyClasses (ref, cfg) {
|
|
var is = ref.is;
|
|
var has = ref.has;
|
|
var within = ref.within;
|
|
|
|
var cls = [
|
|
is.desktop === true ? 'desktop' : 'mobile',
|
|
((has.touch === false ? 'no-' : '') + "touch")
|
|
];
|
|
|
|
if (is.mobile === true) {
|
|
var mobile = getMobilePlatform(is);
|
|
mobile !== void 0 && cls.push('platform-' + mobile);
|
|
}
|
|
|
|
if (is.nativeMobile === true) {
|
|
var type = is.nativeMobileWrapper;
|
|
|
|
cls.push(type);
|
|
cls.push('native-mobile');
|
|
|
|
if (
|
|
is.ios === true &&
|
|
(cfg[type] === void 0 || cfg[type].iosStatusBarPadding !== false)
|
|
) {
|
|
cls.push('q-ios-padding');
|
|
}
|
|
}
|
|
else if (is.electron === true) {
|
|
cls.push('electron');
|
|
}
|
|
else if (is.bex === true) {
|
|
cls.push('bex');
|
|
}
|
|
|
|
within.iframe === true && cls.push('within-iframe');
|
|
|
|
return cls
|
|
}
|
|
|
|
// SSR takeover corrections
|
|
function clientUpdate () {
|
|
var classes = document.body.className;
|
|
var newCls = classes;
|
|
|
|
if (iosCorrection !== void 0) {
|
|
newCls = newCls.replace('desktop', 'platform-ios mobile');
|
|
}
|
|
|
|
if (client.has.touch === true) {
|
|
newCls = newCls.replace('no-touch', 'touch');
|
|
}
|
|
|
|
if (client.within.iframe === true) {
|
|
newCls += ' within-iframe';
|
|
}
|
|
|
|
if (classes !== newCls) {
|
|
document.body.className = newCls;
|
|
}
|
|
}
|
|
|
|
function setColors (brand) {
|
|
for (var color in brand) {
|
|
setBrand(color, brand[color]);
|
|
}
|
|
}
|
|
|
|
var Body = {
|
|
install: function install (queues, cfg) {
|
|
if (isSSR === true) {
|
|
queues.server.push(function (q, ctx) {
|
|
var
|
|
cls = getBodyClasses(q.platform, cfg),
|
|
fn = ctx.ssr.setBodyClasses;
|
|
|
|
if (cfg.screen !== void 0 && cfg.screen.bodyClass === true) {
|
|
cls.push('screen--xs');
|
|
}
|
|
|
|
if (typeof fn === 'function') {
|
|
fn(cls);
|
|
}
|
|
else {
|
|
ctx.ssr.Q_BODY_CLASSES = cls.join(' ');
|
|
}
|
|
});
|
|
|
|
return
|
|
}
|
|
|
|
if (fromSSR === true) {
|
|
clientUpdate();
|
|
}
|
|
else {
|
|
var cls = getBodyClasses(client, cfg);
|
|
|
|
if (client.is.ie === true && client.is.versionNumber === 11) {
|
|
cls.forEach(function (c) { return document.body.classList.add(c); });
|
|
}
|
|
else {
|
|
document.body.classList.add.apply(document.body.classList, cls);
|
|
}
|
|
}
|
|
|
|
cfg.brand !== void 0 && setColors(cfg.brand);
|
|
|
|
if (client.is.ios === true) {
|
|
// needed for iOS button active state
|
|
document.body.addEventListener('touchstart', noop);
|
|
}
|
|
|
|
window.addEventListener('keydown', onKeyDownComposition, true);
|
|
}
|
|
};
|
|
|
|
var materialIcons = {
|
|
name: 'material-icons',
|
|
type: {
|
|
positive: 'check_circle',
|
|
negative: 'warning',
|
|
info: 'info',
|
|
warning: 'priority_high'
|
|
},
|
|
arrow: {
|
|
up: 'arrow_upward',
|
|
right: 'arrow_forward',
|
|
down: 'arrow_downward',
|
|
left: 'arrow_back',
|
|
dropdown: 'arrow_drop_down'
|
|
},
|
|
chevron: {
|
|
left: 'chevron_left',
|
|
right: 'chevron_right'
|
|
},
|
|
colorPicker: {
|
|
spectrum: 'gradient',
|
|
tune: 'tune',
|
|
palette: 'style'
|
|
},
|
|
pullToRefresh: {
|
|
icon: 'refresh'
|
|
},
|
|
carousel: {
|
|
left: 'chevron_left',
|
|
right: 'chevron_right',
|
|
up: 'keyboard_arrow_up',
|
|
down: 'keyboard_arrow_down',
|
|
navigationIcon: 'lens'
|
|
},
|
|
chip: {
|
|
remove: 'cancel',
|
|
selected: 'check'
|
|
},
|
|
datetime: {
|
|
arrowLeft: 'chevron_left',
|
|
arrowRight: 'chevron_right',
|
|
now: 'access_time',
|
|
today: 'today'
|
|
},
|
|
editor: {
|
|
bold: 'format_bold',
|
|
italic: 'format_italic',
|
|
strikethrough: 'strikethrough_s',
|
|
underline: 'format_underlined',
|
|
unorderedList: 'format_list_bulleted',
|
|
orderedList: 'format_list_numbered',
|
|
subscript: 'vertical_align_bottom',
|
|
superscript: 'vertical_align_top',
|
|
hyperlink: 'link',
|
|
toggleFullscreen: 'fullscreen',
|
|
quote: 'format_quote',
|
|
left: 'format_align_left',
|
|
center: 'format_align_center',
|
|
right: 'format_align_right',
|
|
justify: 'format_align_justify',
|
|
print: 'print',
|
|
outdent: 'format_indent_decrease',
|
|
indent: 'format_indent_increase',
|
|
removeFormat: 'format_clear',
|
|
formatting: 'text_format',
|
|
fontSize: 'format_size',
|
|
align: 'format_align_left',
|
|
hr: 'remove',
|
|
undo: 'undo',
|
|
redo: 'redo',
|
|
heading: 'format_size',
|
|
code: 'code',
|
|
size: 'format_size',
|
|
font: 'font_download',
|
|
viewSource: 'code'
|
|
},
|
|
expansionItem: {
|
|
icon: 'keyboard_arrow_down',
|
|
denseIcon: 'arrow_drop_down'
|
|
},
|
|
fab: {
|
|
icon: 'add',
|
|
activeIcon: 'close'
|
|
},
|
|
field: {
|
|
clear: 'cancel',
|
|
error: 'error'
|
|
},
|
|
pagination: {
|
|
first: 'first_page',
|
|
prev: 'keyboard_arrow_left',
|
|
next: 'keyboard_arrow_right',
|
|
last: 'last_page'
|
|
},
|
|
rating: {
|
|
icon: 'grade'
|
|
},
|
|
stepper: {
|
|
done: 'check',
|
|
active: 'edit',
|
|
error: 'warning'
|
|
},
|
|
tabs: {
|
|
left: 'chevron_left',
|
|
right: 'chevron_right',
|
|
up: 'keyboard_arrow_up',
|
|
down: 'keyboard_arrow_down'
|
|
},
|
|
table: {
|
|
arrowUp: 'arrow_upward',
|
|
warning: 'warning',
|
|
firstPage: 'first_page',
|
|
prevPage: 'chevron_left',
|
|
nextPage: 'chevron_right',
|
|
lastPage: 'last_page'
|
|
},
|
|
tree: {
|
|
icon: 'play_arrow'
|
|
},
|
|
uploader: {
|
|
done: 'done',
|
|
clear: 'clear',
|
|
add: 'add_box',
|
|
upload: 'cloud_upload',
|
|
removeQueue: 'clear_all',
|
|
removeUploaded: 'done_all'
|
|
}
|
|
};
|
|
|
|
var iconSet = {
|
|
install: function install ($q, queues, iconSet) {
|
|
var this$1 = this;
|
|
|
|
var initialSet = iconSet || materialIcons;
|
|
|
|
this.set = function (setObject, ssrContext) {
|
|
var def = Object.assign({}, setObject);
|
|
|
|
if (isSSR === true) {
|
|
if (ssrContext === void 0) {
|
|
console.error('SSR ERROR: second param required: Quasar.iconSet.set(iconSet, ssrContext)');
|
|
return
|
|
}
|
|
|
|
def.set = ssrContext.$q.iconSet.set;
|
|
ssrContext.$q.iconSet = def;
|
|
}
|
|
else {
|
|
def.set = this$1.set;
|
|
$q.iconSet = def;
|
|
}
|
|
};
|
|
|
|
if (isSSR === true) {
|
|
queues.server.push(function (q, ctx) {
|
|
q.iconSet = {};
|
|
q.iconSet.set = function (setObject) {
|
|
this$1.set(setObject, ctx.ssr);
|
|
};
|
|
|
|
q.iconSet.set(initialSet);
|
|
});
|
|
}
|
|
else {
|
|
Vue.util.defineReactive($q, 'iconMapFn', void 0);
|
|
Vue.util.defineReactive($q, 'iconSet', {});
|
|
|
|
this.set(initialSet);
|
|
}
|
|
}
|
|
};
|
|
|
|
var autoInstalled = [
|
|
Platform, Screen, Dark
|
|
];
|
|
|
|
var queues = {
|
|
server: [], // on SSR update
|
|
takeover: [] // on client takeover
|
|
};
|
|
|
|
var $q = {
|
|
version: version,
|
|
config: {}
|
|
};
|
|
|
|
function install (Vue, opts) {
|
|
if ( opts === void 0 ) opts = {};
|
|
|
|
if (this.__qInstalled === true) { return }
|
|
this.__qInstalled = true;
|
|
|
|
var cfg = $q.config = Object.freeze(opts.config || {});
|
|
|
|
// required plugins
|
|
Platform.install($q, queues);
|
|
Body.install(queues, cfg);
|
|
Dark.install($q, queues, cfg);
|
|
Screen.install($q, queues, cfg);
|
|
History.install(cfg);
|
|
lang.install($q, queues, opts.lang);
|
|
iconSet.install($q, queues, opts.iconSet);
|
|
|
|
if (isSSR === true) {
|
|
Vue.mixin({
|
|
beforeCreate: function beforeCreate () {
|
|
this.$q = this.$root.$options.$q;
|
|
}
|
|
});
|
|
}
|
|
else {
|
|
Vue.prototype.$q = $q;
|
|
}
|
|
|
|
opts.components && Object.keys(opts.components).forEach(function (key) {
|
|
var c = opts.components[key];
|
|
if (typeof c === 'function') {
|
|
Vue.component(c.options.name, c);
|
|
}
|
|
});
|
|
|
|
opts.directives && Object.keys(opts.directives).forEach(function (key) {
|
|
var d = opts.directives[key];
|
|
if (d.name !== undefined && d.unbind !== void 0) {
|
|
Vue.directive(d.name, d);
|
|
}
|
|
});
|
|
|
|
if (opts.plugins) {
|
|
var param = { $q: $q, queues: queues, cfg: cfg };
|
|
Object.keys(opts.plugins).forEach(function (key) {
|
|
var p = opts.plugins[key];
|
|
if (typeof p.install === 'function' && autoInstalled.includes(p) === false) {
|
|
p.install(param);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
var units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB'];
|
|
|
|
function humanStorageSize (bytes) {
|
|
var u = 0;
|
|
|
|
while (parseInt(bytes, 10) >= 1024 && u < units.length - 1) {
|
|
bytes /= 1024;
|
|
++u;
|
|
}
|
|
|
|
return ("" + (bytes.toFixed(1)) + (units[u]))
|
|
}
|
|
|
|
function capitalize (str) {
|
|
return str.charAt(0).toUpperCase() + str.slice(1)
|
|
}
|
|
|
|
function between (v, min, max) {
|
|
return max <= min
|
|
? min
|
|
: Math.min(max, Math.max(min, v))
|
|
}
|
|
|
|
function normalizeToInterval (v, min, max) {
|
|
if (max <= min) {
|
|
return min
|
|
}
|
|
|
|
var size = (max - min + 1);
|
|
|
|
var index = min + (v - min) % size;
|
|
if (index < min) {
|
|
index = size + index;
|
|
}
|
|
|
|
return index === 0 ? 0 : index // fix for (-a % a) => -0
|
|
}
|
|
|
|
function pad (v, length, char) {
|
|
if ( length === void 0 ) length = 2;
|
|
if ( char === void 0 ) char = '0';
|
|
|
|
if (v === void 0 || v === null) {
|
|
return v
|
|
}
|
|
|
|
var val = '' + v;
|
|
return val.length >= length
|
|
? val
|
|
: new Array(length - val.length + 1).join(char) + val
|
|
}
|
|
|
|
var format = {
|
|
humanStorageSize: humanStorageSize,
|
|
capitalize: capitalize,
|
|
between: between,
|
|
normalizeToInterval: normalizeToInterval,
|
|
pad: pad
|
|
};
|
|
|
|
function cache (vm, key, obj) {
|
|
if (isSSR === true) { return obj }
|
|
|
|
var k = "__qcache_" + key;
|
|
return vm[k] === void 0
|
|
? (vm[k] = obj)
|
|
: vm[k]
|
|
}
|
|
|
|
function cacheWithFn (vm, key, fn) {
|
|
if (isSSR === true) { return fn() }
|
|
|
|
var k = "__qcache_" + key;
|
|
return vm[k] === void 0
|
|
? (vm[k] = fn())
|
|
: vm[k]
|
|
}
|
|
|
|
function getPropCacheMixin (propName, proxyPropName) {
|
|
var obj;
|
|
|
|
return {
|
|
data: function data () {
|
|
var obj;
|
|
|
|
var target = {};
|
|
var source = this[propName];
|
|
|
|
for (var prop in source) {
|
|
target[prop] = source[prop];
|
|
}
|
|
|
|
return ( obj = {}, obj[proxyPropName] = target, obj )
|
|
},
|
|
|
|
watch: ( obj = {}, obj[propName] = function (newObj, oldObj) {
|
|
var target = this[proxyPropName];
|
|
|
|
if (oldObj !== void 0) {
|
|
// we first delete obsolete events
|
|
for (var prop in oldObj) {
|
|
if (newObj[prop] === void 0) {
|
|
this.$delete(target, prop);
|
|
}
|
|
}
|
|
}
|
|
|
|
for (var prop$1 in newObj) {
|
|
// we then update changed events
|
|
if (target[prop$1] !== newObj[prop$1]) {
|
|
this.$set(target, prop$1, newObj[prop$1]);
|
|
}
|
|
}
|
|
}, obj )
|
|
}
|
|
}
|
|
|
|
var ariaHidden = { 'aria-hidden': 'true' };
|
|
|
|
var AttrsMixin = getPropCacheMixin('$attrs', 'qAttrs');
|
|
|
|
var
|
|
xhr = isSSR ? null : XMLHttpRequest,
|
|
send = isSSR ? null : xhr.prototype.send,
|
|
stackStart = [],
|
|
stackStop = [];
|
|
|
|
var highjackCount = 0;
|
|
|
|
function translate (ref) {
|
|
var p = ref.p;
|
|
var pos = ref.pos;
|
|
var active = ref.active;
|
|
var horiz = ref.horiz;
|
|
var reverse = ref.reverse;
|
|
var dir = ref.dir;
|
|
|
|
var x = 1, y = 1;
|
|
|
|
if (horiz) {
|
|
if (reverse) { x = -1; }
|
|
if (pos === 'bottom') { y = -1; }
|
|
return { transform: ("translate3d(" + (x * (p - 100)) + "%," + (active ? 0 : y * -200) + "%,0)") }
|
|
}
|
|
|
|
if (reverse) { y = -1; }
|
|
if (pos === 'right') { x = -1; }
|
|
return { transform: ("translate3d(" + (active ? 0 : dir * x * -200) + "%," + (y * (p - 100)) + "%,0)") }
|
|
}
|
|
|
|
function inc (p, amount) {
|
|
if (typeof amount !== 'number') {
|
|
if (p < 25) {
|
|
amount = Math.random() * 3 + 3;
|
|
}
|
|
else if (p < 65) {
|
|
amount = Math.random() * 3;
|
|
}
|
|
else if (p < 85) {
|
|
amount = Math.random() * 2;
|
|
}
|
|
else if (p < 99) {
|
|
amount = 0.6;
|
|
}
|
|
else {
|
|
amount = 0;
|
|
}
|
|
}
|
|
return between(p + amount, 0, 100)
|
|
}
|
|
|
|
function highjackAjax (start, stop) {
|
|
stackStart.push(start);
|
|
stackStop.push(stop);
|
|
|
|
highjackCount++;
|
|
|
|
if (highjackCount > 1) { return }
|
|
|
|
function endHandler () {
|
|
stackStop.forEach(function (fn) { fn(); });
|
|
}
|
|
|
|
xhr.prototype.send = function (/* ...args */) {
|
|
stackStart.forEach(function (fn) { fn(); });
|
|
this.addEventListener('loadend', endHandler, false);
|
|
send.apply(this, arguments);
|
|
};
|
|
}
|
|
|
|
function restoreAjax (start, stop) {
|
|
stackStart.splice(stackStart.indexOf(start), 1);
|
|
stackStop.splice(stackStop.indexOf(stop), 1);
|
|
|
|
highjackCount = Math.max(0, highjackCount - 1);
|
|
if (!highjackCount) {
|
|
xhr.prototype.send = send;
|
|
}
|
|
}
|
|
|
|
var QAjaxBar = Vue.extend({
|
|
name: 'QAjaxBar',
|
|
|
|
props: {
|
|
position: {
|
|
type: String,
|
|
default: 'top',
|
|
validator: function (val) { return ['top', 'right', 'bottom', 'left'].includes(val); }
|
|
},
|
|
size: {
|
|
type: String,
|
|
default: '2px'
|
|
},
|
|
color: String,
|
|
skipHijack: Boolean,
|
|
reverse: Boolean
|
|
},
|
|
|
|
data: function data () {
|
|
return {
|
|
calls: 0,
|
|
progress: 0,
|
|
onScreen: false,
|
|
animate: true
|
|
}
|
|
},
|
|
|
|
computed: {
|
|
classes: function classes () {
|
|
return "q-loading-bar q-loading-bar--" + (this.position) +
|
|
(this.color !== void 0 ? (" bg-" + (this.color)) : '') +
|
|
(this.animate === true ? '' : ' no-transition')
|
|
},
|
|
|
|
style: function style () {
|
|
var active = this.onScreen;
|
|
|
|
var o = translate({
|
|
p: this.progress,
|
|
pos: this.position,
|
|
active: active,
|
|
horiz: this.horizontal,
|
|
reverse: this.$q.lang.rtl === true && ['top', 'bottom'].includes(this.position)
|
|
? !this.reverse
|
|
: this.reverse,
|
|
dir: this.$q.lang.rtl === true ? -1 : 1
|
|
});
|
|
|
|
o[this.sizeProp] = this.size;
|
|
o.opacity = active ? 1 : 0;
|
|
|
|
return o
|
|
},
|
|
|
|
horizontal: function horizontal () {
|
|
return this.position === 'top' || this.position === 'bottom'
|
|
},
|
|
|
|
sizeProp: function sizeProp () {
|
|
return this.horizontal ? 'height' : 'width'
|
|
},
|
|
|
|
attrs: function attrs () {
|
|
return this.onScreen === true
|
|
? {
|
|
role: 'progressbar',
|
|
'aria-valuemin': 0,
|
|
'aria-valuemax': 100,
|
|
'aria-valuenow': this.progress
|
|
}
|
|
: ariaHidden
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
start: function start (speed) {
|
|
var this$1 = this;
|
|
if ( speed === void 0 ) speed = 300;
|
|
|
|
var oldSpeed = this.speed;
|
|
this.speed = Math.max(0, speed) || 0;
|
|
|
|
this.calls++;
|
|
|
|
if (this.calls > 1) {
|
|
if (oldSpeed === 0 && speed > 0) {
|
|
this.__work();
|
|
}
|
|
else if (oldSpeed > 0 && speed <= 0) {
|
|
clearTimeout(this.timer);
|
|
}
|
|
return
|
|
}
|
|
|
|
clearTimeout(this.timer);
|
|
this.$emit('start');
|
|
|
|
this.progress = 0;
|
|
|
|
if (this.onScreen === true) { return }
|
|
|
|
this.onScreen = true;
|
|
this.animate = false;
|
|
this.timer = setTimeout(function () {
|
|
this$1.animate = true;
|
|
speed > 0 && this$1.__work();
|
|
}, 100);
|
|
},
|
|
|
|
increment: function increment (amount) {
|
|
if (this.calls > 0) {
|
|
this.progress = inc(this.progress, amount);
|
|
}
|
|
},
|
|
|
|
stop: function stop () {
|
|
var this$1 = this;
|
|
|
|
this.calls = Math.max(0, this.calls - 1);
|
|
if (this.calls > 0) { return }
|
|
|
|
clearTimeout(this.timer);
|
|
this.$emit('stop');
|
|
|
|
var end = function () {
|
|
this$1.animate = true;
|
|
this$1.progress = 100;
|
|
this$1.timer = setTimeout(function () {
|
|
this$1.onScreen = false;
|
|
}, 1000);
|
|
};
|
|
|
|
if (this.progress === 0) {
|
|
this.timer = setTimeout(end, 1);
|
|
}
|
|
else {
|
|
end();
|
|
}
|
|
},
|
|
|
|
__work: function __work () {
|
|
var this$1 = this;
|
|
|
|
if (this.progress < 100) {
|
|
this.timer = setTimeout(function () {
|
|
this$1.increment();
|
|
this$1.__work();
|
|
}, this.speed);
|
|
}
|
|
}
|
|
},
|
|
|
|
mounted: function mounted () {
|
|
if (this.skipHijack !== true) {
|
|
this.hijacked = true;
|
|
highjackAjax(this.start, this.stop);
|
|
}
|
|
},
|
|
|
|
beforeDestroy: function beforeDestroy () {
|
|
clearTimeout(this.timer);
|
|
this.hijacked === true && restoreAjax(this.start, this.stop);
|
|
},
|
|
|
|
render: function render (h) {
|
|
return h('div', {
|
|
class: this.classes,
|
|
style: this.style,
|
|
attrs: this.attrs
|
|
})
|
|
}
|
|
});
|
|
|
|
var sizes = {
|
|
xs: 18,
|
|
sm: 24,
|
|
md: 32,
|
|
lg: 38,
|
|
xl: 46
|
|
};
|
|
|
|
function getSizeMixin (sizes) {
|
|
return {
|
|
props: {
|
|
size: String
|
|
},
|
|
|
|
computed: {
|
|
sizeStyle: function sizeStyle () {
|
|
if (this.size !== void 0) {
|
|
return { fontSize: this.size in sizes ? ((sizes[this.size]) + "px") : this.size }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
var SizeMixin = getSizeMixin(sizes);
|
|
|
|
var TagMixin = {
|
|
props: {
|
|
tag: {
|
|
type: String,
|
|
default: 'div'
|
|
}
|
|
}
|
|
};
|
|
|
|
var ListenersMixin = getPropCacheMixin('$listeners', 'qListeners');
|
|
|
|
function slot (vm, slotName, otherwise) {
|
|
return vm.$scopedSlots[slotName] !== void 0
|
|
? vm.$scopedSlots[slotName]()
|
|
: otherwise
|
|
}
|
|
|
|
function uniqueSlot (vm, slotName, otherwise) {
|
|
return vm.$scopedSlots[slotName] !== void 0
|
|
? vm.$scopedSlots[slotName]().slice()
|
|
: otherwise
|
|
}
|
|
|
|
/**
|
|
* Source definitely exists,
|
|
* so it's merged with the possible slot
|
|
*/
|
|
function mergeSlot (source, vm, slotName) {
|
|
return vm.$scopedSlots[slotName] !== void 0
|
|
? source.concat(vm.$scopedSlots[slotName]())
|
|
: source
|
|
}
|
|
|
|
/**
|
|
* Merge with possible slot,
|
|
* even if source might not exist
|
|
*/
|
|
function mergeSlotSafely (source, vm, slotName) {
|
|
if (vm.$scopedSlots[slotName] === void 0) {
|
|
return source
|
|
}
|
|
|
|
var slot = vm.$scopedSlots[slotName]();
|
|
return source !== void 0
|
|
? source.concat(slot)
|
|
: slot
|
|
}
|
|
|
|
var QIcon = Vue.extend({
|
|
name: 'QIcon',
|
|
|
|
mixins: [ ListenersMixin, SizeMixin, TagMixin ],
|
|
|
|
props: {
|
|
tag: {
|
|
default: 'i'
|
|
},
|
|
|
|
name: String,
|
|
color: String,
|
|
left: Boolean,
|
|
right: Boolean
|
|
},
|
|
|
|
computed: {
|
|
classes: function classes () {
|
|
// "notranslate" class is for Google Translate
|
|
// to avoid tampering with Material Icons ligature font
|
|
return 'q-icon notranslate' +
|
|
(this.left === true ? ' on-left' : '') +
|
|
(this.right === true ? ' on-right' : '') +
|
|
(this.color !== void 0 ? (" text-" + (this.color)) : '')
|
|
},
|
|
|
|
type: function type () {
|
|
var this$1 = this;
|
|
|
|
var cls;
|
|
var icon = this.name;
|
|
|
|
if (!icon) {
|
|
return {
|
|
none: true,
|
|
cls: this.classes
|
|
}
|
|
}
|
|
|
|
if (this.$q.iconMapFn !== void 0) {
|
|
var res = this.$q.iconMapFn(icon);
|
|
if (res !== void 0) {
|
|
if (res.icon !== void 0) {
|
|
icon = res.icon;
|
|
}
|
|
else {
|
|
return {
|
|
cls: res.cls + ' ' + this.classes,
|
|
content: res.content !== void 0
|
|
? res.content
|
|
: ' '
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (icon.startsWith('M') === true) {
|
|
var ref = icon.split('|');
|
|
var def = ref[0];
|
|
var viewBox = ref[1];
|
|
|
|
return {
|
|
svg: true,
|
|
cls: this.classes,
|
|
nodes: def.split('&&').map(function (path) {
|
|
var ref = path.split('@@');
|
|
var d = ref[0];
|
|
var style = ref[1];
|
|
var transform = ref[2];
|
|
return this$1.$createElement('path', {
|
|
attrs: {
|
|
d: d,
|
|
transform: transform
|
|
},
|
|
style: style
|
|
})
|
|
}),
|
|
viewBox: viewBox !== void 0 ? viewBox : '0 0 24 24'
|
|
}
|
|
}
|
|
|
|
if (icon.startsWith('img:') === true) {
|
|
return {
|
|
img: true,
|
|
cls: this.classes,
|
|
src: icon.substring(4)
|
|
}
|
|
}
|
|
|
|
if (icon.startsWith('svguse:') === true) {
|
|
var ref$1 = icon.split('|');
|
|
var def$1 = ref$1[0];
|
|
var viewBox$1 = ref$1[1];
|
|
|
|
return {
|
|
svguse: true,
|
|
cls: this.classes,
|
|
src: def$1.substring(7),
|
|
viewBox: viewBox$1 !== void 0 ? viewBox$1 : '0 0 24 24'
|
|
}
|
|
}
|
|
|
|
var content = ' ';
|
|
|
|
if (/^[l|f]a[s|r|l|b|d]{0,1} /.test(icon) || icon.startsWith('icon-') === true) {
|
|
cls = icon;
|
|
}
|
|
else if (icon.startsWith('bt-') === true) {
|
|
cls = "bt " + icon;
|
|
}
|
|
else if (icon.startsWith('eva-') === true) {
|
|
cls = "eva " + icon;
|
|
}
|
|
else if (/^ion-(md|ios|logo)/.test(icon) === true) {
|
|
cls = "ionicons " + icon;
|
|
}
|
|
else if (icon.startsWith('ion-') === true) {
|
|
cls = "ionicons ion-" + (this.$q.platform.is.ios === true ? 'ios' : 'md') + (icon.substr(3));
|
|
}
|
|
else if (icon.startsWith('mdi-') === true) {
|
|
cls = "mdi " + icon;
|
|
}
|
|
else if (icon.startsWith('iconfont ') === true) {
|
|
cls = "" + icon;
|
|
}
|
|
else if (icon.startsWith('ti-') === true) {
|
|
cls = "themify-icon " + icon;
|
|
}
|
|
else {
|
|
cls = 'material-icons';
|
|
|
|
if (icon.startsWith('o_') === true) {
|
|
icon = icon.substring(2);
|
|
cls += '-outlined';
|
|
}
|
|
else if (icon.startsWith('r_') === true) {
|
|
icon = icon.substring(2);
|
|
cls += '-round';
|
|
}
|
|
else if (icon.startsWith('s_') === true) {
|
|
icon = icon.substring(2);
|
|
cls += '-sharp';
|
|
}
|
|
|
|
content = icon;
|
|
}
|
|
|
|
return {
|
|
cls: cls + ' ' + this.classes,
|
|
content: content
|
|
}
|
|
}
|
|
},
|
|
|
|
render: function render (h) {
|
|
var data = {
|
|
class: this.type.cls,
|
|
style: this.sizeStyle,
|
|
on: Object.assign({}, this.qListeners),
|
|
attrs: {
|
|
'aria-hidden': 'true',
|
|
role: 'presentation'
|
|
}
|
|
};
|
|
|
|
if (this.type.none === true) {
|
|
return h(this.tag, data, slot(this, 'default'))
|
|
}
|
|
|
|
if (this.type.img === true) {
|
|
data.attrs.src = this.type.src;
|
|
return h('img', data)
|
|
}
|
|
|
|
if (this.type.svg === true) {
|
|
data.attrs.focusable = 'false'; /* needed for IE11 */
|
|
data.attrs.viewBox = this.type.viewBox;
|
|
|
|
return h('svg', data, mergeSlot(this.type.nodes, this, 'default'))
|
|
}
|
|
if (this.type.svguse === true) {
|
|
data.attrs.focusable = 'false'; /* needed for IE11 */
|
|
data.attrs.viewBox = this.type.viewBox;
|
|
|
|
return h('svg', data, [
|
|
h('use', {
|
|
attrs: {
|
|
'xlink:href': this.type.src
|
|
}
|
|
}),
|
|
mergeSlot(this.type.nodes, this, 'default')
|
|
])
|
|
}
|
|
|
|
return h(this.tag, data, mergeSlot([
|
|
this.type.content
|
|
], this, 'default'))
|
|
}
|
|
});
|
|
|
|
var QAvatar = Vue.extend({
|
|
name: 'QAvatar',
|
|
|
|
mixins: [ ListenersMixin, SizeMixin ],
|
|
|
|
props: {
|
|
fontSize: String,
|
|
|
|
color: String,
|
|
textColor: String,
|
|
|
|
icon: String,
|
|
square: Boolean,
|
|
rounded: Boolean
|
|
},
|
|
|
|
computed: {
|
|
classes: function classes () {
|
|
var obj;
|
|
|
|
return ( obj = {}, obj[("bg-" + (this.color))] = this.color, obj[("text-" + (this.textColor) + " q-chip--colored")] = this.textColor, obj['q-avatar--square'] = this.square, obj['rounded-borders'] = this.rounded, obj )
|
|
},
|
|
|
|
contentStyle: function contentStyle () {
|
|
if (this.fontSize) {
|
|
return { fontSize: this.fontSize }
|
|
}
|
|
}
|
|
},
|
|
|
|
render: function render (h) {
|
|
var icon = this.icon !== void 0
|
|
? [ h(QIcon, { props: { name: this.icon } }) ]
|
|
: void 0;
|
|
|
|
return h('div', {
|
|
staticClass: 'q-avatar',
|
|
style: this.sizeStyle,
|
|
class: this.classes,
|
|
on: Object.assign({}, this.qListeners)
|
|
}, [
|
|
h('div', {
|
|
staticClass: 'q-avatar__content row flex-center overflow-hidden',
|
|
style: this.contentStyle
|
|
}, mergeSlotSafely(icon, this, 'default'))
|
|
])
|
|
}
|
|
});
|
|
|
|
var QBadge = Vue.extend({
|
|
name: 'QBadge',
|
|
|
|
mixins: [ ListenersMixin ],
|
|
|
|
props: {
|
|
color: String,
|
|
textColor: String,
|
|
|
|
floating: Boolean,
|
|
transparent: Boolean,
|
|
multiLine: Boolean,
|
|
outline: Boolean,
|
|
|
|
label: [Number, String],
|
|
|
|
align: {
|
|
type: String,
|
|
validator: function (v) { return ['top', 'middle', 'bottom'].includes(v); }
|
|
}
|
|
},
|
|
|
|
computed: {
|
|
style: function style () {
|
|
if (this.align !== void 0) {
|
|
return { verticalAlign: this.align }
|
|
}
|
|
},
|
|
|
|
classes: function classes () {
|
|
var text = this.outline === true
|
|
? this.color || this.textColor
|
|
: this.textColor;
|
|
|
|
return 'q-badge flex inline items-center no-wrap' +
|
|
" q-badge--" + (this.multiLine === true ? 'multi' : 'single') + "-line" +
|
|
(this.outline === true
|
|
? ' q-badge--outline'
|
|
: (this.color !== void 0 ? (" bg-" + (this.color)) : '')
|
|
) +
|
|
(text !== void 0 ? (" text-" + text) : '') +
|
|
(this.floating === true ? ' q-badge--floating' : '') +
|
|
(this.transparent === true ? ' q-badge--transparent' : '')
|
|
},
|
|
|
|
attrs: function attrs () {
|
|
return {
|
|
role: 'alert',
|
|
'aria-label': this.label
|
|
}
|
|
}
|
|
},
|
|
|
|
render: function render (h) {
|
|
return h('div', {
|
|
style: this.style,
|
|
class: this.classes,
|
|
attrs: this.attrs,
|
|
on: Object.assign({}, this.qListeners)
|
|
}, this.label !== void 0 ? [ this.label ] : slot(this, 'default'))
|
|
}
|
|
});
|
|
|
|
var DarkMixin = {
|
|
props: {
|
|
dark: {
|
|
type: Boolean,
|
|
default: null
|
|
}
|
|
},
|
|
|
|
computed: {
|
|
isDark: function isDark () {
|
|
return this.dark === null
|
|
? this.$q.dark.isActive
|
|
: this.dark
|
|
}
|
|
}
|
|
};
|
|
|
|
var attrs = { role: 'alert' };
|
|
|
|
var QBanner = Vue.extend({
|
|
name: 'QBanner',
|
|
|
|
mixins: [ ListenersMixin, DarkMixin ],
|
|
|
|
props: {
|
|
inlineActions: Boolean,
|
|
dense: Boolean,
|
|
rounded: Boolean
|
|
},
|
|
|
|
render: function render (h) {
|
|
var actions = slot(this, 'action');
|
|
var child = [
|
|
h('div', {
|
|
staticClass: 'q-banner__avatar col-auto row items-center self-start'
|
|
}, slot(this, 'avatar')),
|
|
|
|
h('div', {
|
|
staticClass: 'q-banner__content col text-body2'
|
|
}, slot(this, 'default'))
|
|
];
|
|
|
|
actions !== void 0 && child.push(
|
|
h('div', {
|
|
staticClass: 'q-banner__actions row items-center justify-end',
|
|
class: ("col-" + (this.inlineActions === true ? 'auto' : 'all'))
|
|
}, actions)
|
|
);
|
|
|
|
return h('div', {
|
|
staticClass: 'q-banner row items-center',
|
|
class: {
|
|
'q-banner--top-padding': actions !== void 0 && !this.inlineActions,
|
|
'q-banner--dense': this.dense,
|
|
'q-banner--dark q-dark': this.isDark,
|
|
'rounded-borders': this.rounded
|
|
},
|
|
attrs: attrs,
|
|
on: Object.assign({}, this.qListeners)
|
|
}, child)
|
|
}
|
|
});
|
|
|
|
var attrs$1 = { role: 'toolbar' };
|
|
|
|
var QBar = Vue.extend({
|
|
name: 'QBar',
|
|
|
|
mixins: [ ListenersMixin, DarkMixin ],
|
|
|
|
props: {
|
|
dense: Boolean
|
|
},
|
|
|
|
computed: {
|
|
classes: function classes () {
|
|
return "q-bar--" + (this.dense === true ? 'dense' : 'standard') + " " +
|
|
"q-bar--" + (this.isDark === true ? 'dark' : 'light')
|
|
}
|
|
},
|
|
|
|
render: function render (h) {
|
|
return h('div', {
|
|
staticClass: 'q-bar row no-wrap items-center',
|
|
class: this.classes,
|
|
attrs: attrs$1,
|
|
on: Object.assign({}, this.qListeners)
|
|
}, slot(this, 'default'))
|
|
}
|
|
});
|
|
|
|
var
|
|
alignMap = {
|
|
left: 'start',
|
|
center: 'center',
|
|
right: 'end',
|
|
between: 'between',
|
|
around: 'around',
|
|
evenly: 'evenly',
|
|
stretch: 'stretch'
|
|
},
|
|
alignValues = Object.keys(alignMap);
|
|
|
|
var AlignMixin = {
|
|
props: {
|
|
align: {
|
|
type: String,
|
|
validator: function (v) { return alignValues.includes(v); }
|
|
}
|
|
},
|
|
|
|
computed: {
|
|
alignClass: function alignClass () {
|
|
var align = this.align === void 0
|
|
? (this.vertical === true ? 'stretch' : 'left')
|
|
: this.align;
|
|
|
|
return ((this.vertical === true ? 'items' : 'justify') + "-" + (alignMap[align]))
|
|
}
|
|
}
|
|
};
|
|
|
|
var QBreadcrumbs = Vue.extend({
|
|
name: 'QBreadcrumbs',
|
|
|
|
mixins: [ ListenersMixin, AlignMixin ],
|
|
|
|
props: {
|
|
separator: {
|
|
type: String,
|
|
default: '/'
|
|
},
|
|
separatorColor: String,
|
|
|
|
activeColor: {
|
|
type: String,
|
|
default: 'primary'
|
|
},
|
|
|
|
gutter: {
|
|
type: String,
|
|
validator: function (v) { return ['none', 'xs', 'sm', 'md', 'lg', 'xl'].includes(v); },
|
|
default: 'sm'
|
|
}
|
|
},
|
|
|
|
computed: {
|
|
classes: function classes () {
|
|
return ("" + (this.alignClass) + (this.gutter === 'none' ? '' : (" q-gutter-" + (this.gutter))))
|
|
},
|
|
|
|
sepClass: function sepClass () {
|
|
if (this.separatorColor) {
|
|
return ("text-" + (this.separatorColor))
|
|
}
|
|
},
|
|
|
|
activeClass: function activeClass () {
|
|
return ("text-" + (this.activeColor))
|
|
}
|
|
},
|
|
|
|
render: function render (h) {
|
|
var this$1 = this;
|
|
|
|
var nodes = slot(this, 'default');
|
|
if (nodes === void 0) { return }
|
|
|
|
var els = 1;
|
|
|
|
var
|
|
child = [],
|
|
len = nodes.filter(function (c) { return c.tag !== void 0 && c.tag.endsWith('-QBreadcrumbsEl'); }).length,
|
|
separator = this.$scopedSlots.separator !== void 0
|
|
? this.$scopedSlots.separator
|
|
: function () { return this$1.separator; };
|
|
|
|
nodes.forEach(function (comp) {
|
|
if (comp.tag !== void 0 && comp.tag.endsWith('-QBreadcrumbsEl')) {
|
|
var middle = els < len;
|
|
els++;
|
|
|
|
child.push(h('div', {
|
|
staticClass: 'flex items-center',
|
|
class: middle ? this$1.activeClass : 'q-breadcrumbs--last'
|
|
}, [ comp ]));
|
|
|
|
if (middle) {
|
|
child.push(h('div', {
|
|
staticClass: 'q-breadcrumbs__separator', class: this$1.sepClass
|
|
}, separator()));
|
|
}
|
|
}
|
|
else {
|
|
child.push(comp);
|
|
}
|
|
});
|
|
|
|
return h('div', {
|
|
staticClass: 'q-breadcrumbs',
|
|
on: Object.assign({}, this.qListeners)
|
|
}, [
|
|
h('div', {
|
|
staticClass: 'flex items-center',
|
|
class: this.classes
|
|
}, child)
|
|
])
|
|
}
|
|
});
|
|
|
|
var routerLinkProps = {
|
|
to: [String, Object],
|
|
exact: Boolean,
|
|
append: Boolean,
|
|
replace: Boolean,
|
|
activeClass: String,
|
|
exactActiveClass: String,
|
|
disable: Boolean
|
|
};
|
|
|
|
var RouterLinkMixin = {
|
|
props: routerLinkProps,
|
|
|
|
computed: {
|
|
hasRouterLink: function hasRouterLink () {
|
|
return this.disable !== true && this.to !== void 0 && this.to !== null && this.to !== ''
|
|
},
|
|
|
|
routerLinkProps: function routerLinkProps () {
|
|
return {
|
|
to: this.to,
|
|
exact: this.exact,
|
|
append: this.append,
|
|
replace: this.replace,
|
|
activeClass: this.activeClass || 'q-router-link--active',
|
|
exactActiveClass: this.exactActiveClass || 'q-router-link--exact-active',
|
|
event: this.disable === true ? '' : void 0
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
var QBreadcrumbsEl = Vue.extend({
|
|
name: 'QBreadcrumbsEl',
|
|
|
|
mixins: [ ListenersMixin, RouterLinkMixin ],
|
|
|
|
props: {
|
|
label: String,
|
|
icon: String
|
|
},
|
|
|
|
render: function render (h) {
|
|
var obj;
|
|
|
|
var child = [];
|
|
|
|
this.icon !== void 0 && child.push(
|
|
h(QIcon, {
|
|
staticClass: 'q-breadcrumbs__el-icon',
|
|
class: this.label !== void 0 ? 'q-breadcrumbs__el-icon--with-label' : null,
|
|
props: { name: this.icon }
|
|
})
|
|
);
|
|
|
|
this.label && child.push(this.label);
|
|
|
|
return h(this.hasRouterLink === true ? 'router-link' : 'span', ( obj = {
|
|
staticClass: 'q-breadcrumbs__el q-link flex inline items-center relative-position',
|
|
props: this.hasRouterLink === true ? this.routerLinkProps : null
|
|
}, obj[this.hasRouterLink === true ? 'nativeOn' : 'on'] = Object.assign({}, this.qListeners), obj ), mergeSlot(child, this, 'default'))
|
|
}
|
|
});
|
|
|
|
var mixin = {
|
|
mixins: [ ListenersMixin ],
|
|
|
|
props: {
|
|
color: String,
|
|
size: {
|
|
type: [Number, String],
|
|
default: '1em'
|
|
}
|
|
},
|
|
|
|
computed: {
|
|
cSize: function cSize () {
|
|
return this.size in sizes
|
|
? ((sizes[this.size]) + "px")
|
|
: this.size
|
|
},
|
|
|
|
classes: function classes () {
|
|
if (this.color) {
|
|
return ("text-" + (this.color))
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
var QSpinner = Vue.extend({
|
|
name: 'QSpinner',
|
|
|
|
mixins: [ mixin ],
|
|
|
|
props: {
|
|
thickness: {
|
|
type: Number,
|
|
default: 5
|
|
}
|
|
},
|
|
|
|
render: function render (h) {
|
|
return h('svg', {
|
|
staticClass: 'q-spinner q-spinner-mat',
|
|
class: this.classes,
|
|
on: Object.assign({}, this.qListeners),
|
|
attrs: {
|
|
focusable: 'false' /* needed for IE11 */,
|
|
'width': this.cSize,
|
|
'height': this.cSize,
|
|
'viewBox': '25 25 50 50'
|
|
}
|
|
}, [
|
|
h('circle', {
|
|
staticClass: 'path',
|
|
attrs: {
|
|
'cx': '50',
|
|
'cy': '50',
|
|
'r': '20',
|
|
'fill': 'none',
|
|
'stroke': 'currentColor',
|
|
'stroke-width': this.thickness,
|
|
'stroke-miterlimit': '10'
|
|
}
|
|
})
|
|
])
|
|
}
|
|
});
|
|
|
|
function offset (el) {
|
|
if (el === window) {
|
|
return { top: 0, left: 0 }
|
|
}
|
|
var ref = el.getBoundingClientRect();
|
|
var top = ref.top;
|
|
var left = ref.left;
|
|
return { top: top, left: left }
|
|
}
|
|
|
|
function style (el, property) {
|
|
return window.getComputedStyle(el).getPropertyValue(property)
|
|
}
|
|
|
|
function height (el) {
|
|
return el === window
|
|
? window.innerHeight
|
|
: el.getBoundingClientRect().height
|
|
}
|
|
|
|
function width (el) {
|
|
return el === window
|
|
? window.innerWidth
|
|
: el.getBoundingClientRect().width
|
|
}
|
|
|
|
function css (element, css) {
|
|
var style = element.style;
|
|
|
|
Object.keys(css).forEach(function (prop) {
|
|
style[prop] = css[prop];
|
|
});
|
|
}
|
|
|
|
function cssBatch (elements, style) {
|
|
elements.forEach(function (el) { return css(el, style); });
|
|
}
|
|
|
|
function ready (fn) {
|
|
if (typeof fn !== 'function') {
|
|
return
|
|
}
|
|
|
|
if (document.readyState !== 'loading') {
|
|
return fn()
|
|
}
|
|
|
|
document.addEventListener('DOMContentLoaded', fn, false);
|
|
}
|
|
|
|
// internal
|
|
function childHasFocus (el, focusedEl) {
|
|
if (el === void 0 || el.contains(focusedEl) === true) {
|
|
return true
|
|
}
|
|
|
|
for (var next = el.nextElementSibling; next !== null; next = next.nextElementSibling) {
|
|
if (next.contains(focusedEl)) {
|
|
return true
|
|
}
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
// internal
|
|
function getBodyFullscreenElement (isFullscreen, activeEl) {
|
|
return isFullscreen === true
|
|
? (
|
|
// when a video tag enters fullscreen activeEl is null
|
|
activeEl === document.documentElement || activeEl === null
|
|
? document.body
|
|
: activeEl
|
|
)
|
|
: document.body
|
|
}
|
|
|
|
var dom = {
|
|
offset: offset,
|
|
style: style,
|
|
height: height,
|
|
width: width,
|
|
css: css,
|
|
cssBatch: cssBatch,
|
|
ready: ready
|
|
};
|
|
|
|
function throttle (fn, limit) {
|
|
if ( limit === void 0 ) limit = 250;
|
|
|
|
var wait = false, result;
|
|
|
|
return function (/* ...args */) {
|
|
if (wait === false) {
|
|
wait = true;
|
|
setTimeout(function () { wait = false; }, limit);
|
|
result = fn.apply(this, arguments);
|
|
}
|
|
|
|
return result
|
|
}
|
|
}
|
|
|
|
function showRipple (evt, el, ctx, forceCenter) {
|
|
ctx.modifiers.stop === true && stop(evt);
|
|
|
|
var color = ctx.modifiers.color;
|
|
var center = ctx.modifiers.center;
|
|
center = center === true || forceCenter === true;
|
|
|
|
var
|
|
node = document.createElement('span'),
|
|
innerNode = document.createElement('span'),
|
|
pos = position(evt);
|
|
var ref = el.getBoundingClientRect();
|
|
var left = ref.left;
|
|
var top = ref.top;
|
|
var width = ref.width;
|
|
var height = ref.height;
|
|
var diameter = Math.sqrt(width * width + height * height),
|
|
radius = diameter / 2,
|
|
centerX = ((width - diameter) / 2) + "px",
|
|
x = center ? centerX : ((pos.left - left - radius) + "px"),
|
|
centerY = ((height - diameter) / 2) + "px",
|
|
y = center ? centerY : ((pos.top - top - radius) + "px");
|
|
|
|
innerNode.className = 'q-ripple__inner';
|
|
css(innerNode, {
|
|
height: (diameter + "px"),
|
|
width: (diameter + "px"),
|
|
transform: ("translate3d(" + x + "," + y + ",0) scale3d(.2,.2,1)"),
|
|
opacity: 0
|
|
});
|
|
|
|
node.className = "q-ripple" + (color ? ' text-' + color : '');
|
|
node.setAttribute('dir', 'ltr');
|
|
node.appendChild(innerNode);
|
|
el.appendChild(node);
|
|
|
|
var abort = function () {
|
|
node.remove();
|
|
clearTimeout(timer);
|
|
};
|
|
ctx.abort.push(abort);
|
|
|
|
var timer = setTimeout(function () {
|
|
innerNode.classList.add('q-ripple__inner--enter');
|
|
innerNode.style.transform = "translate3d(" + centerX + "," + centerY + ",0) scale3d(1,1,1)";
|
|
innerNode.style.opacity = 0.2;
|
|
|
|
timer = setTimeout(function () {
|
|
innerNode.classList.remove('q-ripple__inner--enter');
|
|
innerNode.classList.add('q-ripple__inner--leave');
|
|
innerNode.style.opacity = 0;
|
|
|
|
timer = setTimeout(function () {
|
|
node.remove();
|
|
ctx.abort.splice(ctx.abort.indexOf(abort), 1);
|
|
}, 275);
|
|
}, 250);
|
|
}, 50);
|
|
}
|
|
|
|
function updateModifiers (ctx, ref) {
|
|
var modifiers = ref.modifiers;
|
|
var value = ref.value;
|
|
var arg = ref.arg;
|
|
|
|
var cfg = Object.assign({}, $q.config.ripple, modifiers, value);
|
|
ctx.modifiers = {
|
|
early: cfg.early === true,
|
|
stop: cfg.stop === true,
|
|
center: cfg.center === true,
|
|
color: cfg.color || arg,
|
|
keyCodes: [].concat(cfg.keyCodes || 13)
|
|
};
|
|
}
|
|
|
|
function destroy (el) {
|
|
var ctx = el.__qripple;
|
|
if (ctx !== void 0) {
|
|
ctx.abort.forEach(function (fn) { fn(); });
|
|
cleanEvt(ctx, 'main');
|
|
delete el._qripple;
|
|
}
|
|
}
|
|
|
|
var Ripple = {
|
|
name: 'ripple',
|
|
|
|
inserted: function inserted (el, binding) {
|
|
if (el.__qripple !== void 0) {
|
|
destroy(el);
|
|
el.__qripple_destroyed = true;
|
|
}
|
|
|
|
var ctx = {
|
|
enabled: binding.value !== false,
|
|
modifiers: {},
|
|
abort: [],
|
|
|
|
start: function start (evt) {
|
|
if (
|
|
ctx.enabled === true &&
|
|
evt.qSkipRipple !== true &&
|
|
// on ENTER in form IE emits a PointerEvent with negative client cordinates
|
|
(client.is.ie !== true || evt.clientX >= 0) &&
|
|
(
|
|
ctx.modifiers.early === true
|
|
? ['mousedown', 'touchstart'].includes(evt.type) === true
|
|
: evt.type === 'click'
|
|
)
|
|
) {
|
|
showRipple(evt, el, ctx, evt.qKeyEvent === true);
|
|
}
|
|
},
|
|
|
|
keystart: throttle(function (evt) {
|
|
if (
|
|
ctx.enabled === true &&
|
|
evt.qSkipRipple !== true &&
|
|
isKeyCode(evt, ctx.modifiers.keyCodes) === true &&
|
|
evt.type === ("key" + (ctx.modifiers.early === true ? 'down' : 'up'))
|
|
) {
|
|
showRipple(evt, el, ctx, true);
|
|
}
|
|
}, 300)
|
|
};
|
|
|
|
updateModifiers(ctx, binding);
|
|
|
|
el.__qripple = ctx;
|
|
|
|
addEvt(ctx, 'main', [
|
|
[ el, 'mousedown', 'start', 'passive' ],
|
|
[ el, 'touchstart', 'start', 'passive' ],
|
|
[ el, 'click', 'start', 'passive' ],
|
|
[ el, 'keydown', 'keystart', 'passive' ],
|
|
[ el, 'keyup', 'keystart', 'passive' ]
|
|
]);
|
|
},
|
|
|
|
update: function update (el, binding) {
|
|
var ctx = el.__qripple;
|
|
if (ctx !== void 0 && binding.oldValue !== binding.value) {
|
|
ctx.enabled = binding.value !== false;
|
|
|
|
if (ctx.enabled === true && Object(binding.value) === binding.value) {
|
|
updateModifiers(ctx, binding);
|
|
}
|
|
}
|
|
},
|
|
|
|
unbind: function unbind (el) {
|
|
if (el.__qripple_destroyed === void 0) {
|
|
destroy(el);
|
|
}
|
|
else {
|
|
delete el.__qripple_destroyed;
|
|
}
|
|
}
|
|
};
|
|
|
|
var RippleMixin = {
|
|
directives: {
|
|
Ripple: Ripple
|
|
},
|
|
|
|
props: {
|
|
ripple: {
|
|
type: [Boolean, Object],
|
|
default: true
|
|
}
|
|
}
|
|
};
|
|
|
|
var padding = {
|
|
none: 0,
|
|
xs: 4,
|
|
sm: 8,
|
|
md: 16,
|
|
lg: 24,
|
|
xl: 32
|
|
};
|
|
|
|
var BtnMixin = {
|
|
mixins: [
|
|
ListenersMixin,
|
|
RippleMixin,
|
|
AlignMixin,
|
|
getSizeMixin({
|
|
xs: 8,
|
|
sm: 10,
|
|
md: 14,
|
|
lg: 20,
|
|
xl: 24
|
|
})
|
|
],
|
|
|
|
props: {
|
|
type: String,
|
|
|
|
to: [ Object, String ],
|
|
replace: Boolean,
|
|
append: Boolean,
|
|
|
|
label: [ Number, String ],
|
|
icon: String,
|
|
iconRight: String,
|
|
|
|
round: Boolean,
|
|
outline: Boolean,
|
|
flat: Boolean,
|
|
unelevated: Boolean,
|
|
rounded: Boolean,
|
|
push: Boolean,
|
|
glossy: Boolean,
|
|
|
|
size: String,
|
|
fab: Boolean,
|
|
fabMini: Boolean,
|
|
padding: String,
|
|
|
|
color: String,
|
|
textColor: String,
|
|
noCaps: Boolean,
|
|
noWrap: Boolean,
|
|
dense: Boolean,
|
|
|
|
tabindex: [ Number, String ],
|
|
|
|
align: { default: 'center' },
|
|
stack: Boolean,
|
|
stretch: Boolean,
|
|
loading: {
|
|
type: Boolean,
|
|
default: null
|
|
},
|
|
disable: Boolean
|
|
},
|
|
|
|
computed: {
|
|
style: function style () {
|
|
if (this.fab === false && this.fabMini === false) {
|
|
return this.sizeStyle
|
|
}
|
|
},
|
|
|
|
isRounded: function isRounded () {
|
|
return this.rounded === true || this.fab === true || this.fabMini === true
|
|
},
|
|
|
|
isActionable: function isActionable () {
|
|
return this.disable !== true && this.loading !== true
|
|
},
|
|
|
|
computedTabIndex: function computedTabIndex () {
|
|
return this.isActionable === true ? this.tabindex || 0 : -1
|
|
},
|
|
|
|
hasRouterLink: function hasRouterLink () {
|
|
return this.disable !== true && this.to !== void 0 && this.to !== null && this.to !== ''
|
|
},
|
|
|
|
isLink: function isLink () {
|
|
return this.type === 'a' || this.hasRouterLink === true
|
|
},
|
|
|
|
design: function design () {
|
|
if (this.flat === true) { return 'flat' }
|
|
if (this.outline === true) { return 'outline' }
|
|
if (this.push === true) { return 'push' }
|
|
if (this.unelevated === true) { return 'unelevated' }
|
|
return 'standard'
|
|
},
|
|
|
|
currentLocation: function currentLocation () {
|
|
if (this.hasRouterLink === true) {
|
|
// we protect from accessing this.$route without
|
|
// actually needing it so that we won't trigger
|
|
// unnecessary updates
|
|
return this.append === true
|
|
? this.$router.resolve(this.to, this.$route, true)
|
|
: this.$router.resolve(this.to)
|
|
}
|
|
},
|
|
|
|
attrs: function attrs () {
|
|
var attrs = { tabindex: this.computedTabIndex };
|
|
|
|
if (this.type !== 'a') {
|
|
attrs.type = this.type || 'button';
|
|
}
|
|
|
|
if (this.hasRouterLink === true) {
|
|
attrs.href = this.currentLocation.href;
|
|
attrs.role = 'link';
|
|
}
|
|
else {
|
|
attrs.role = this.type === 'a' ? 'link' : 'button';
|
|
}
|
|
|
|
if (this.loading === true && this.percentage !== void 0) {
|
|
attrs.role = 'progressbar';
|
|
attrs['aria-valuemin'] = 0;
|
|
attrs['aria-valuemax'] = 100;
|
|
attrs['aria-valuenow'] = this.percentage;
|
|
}
|
|
|
|
if (this.disable === true) {
|
|
attrs.disabled = '';
|
|
attrs['aria-disabled'] = 'true';
|
|
}
|
|
|
|
return attrs
|
|
},
|
|
|
|
classes: function classes () {
|
|
var colors;
|
|
|
|
if (this.color !== void 0) {
|
|
if (this.flat === true || this.outline === true) {
|
|
colors = "text-" + (this.textColor || this.color);
|
|
}
|
|
else {
|
|
colors = "bg-" + (this.color) + " text-" + (this.textColor || 'white');
|
|
}
|
|
}
|
|
else if (this.textColor) {
|
|
colors = "text-" + (this.textColor);
|
|
}
|
|
|
|
return "q-btn--" + (this.design) + " " +
|
|
"q-btn--" + (this.round === true ? 'round' : ("rectangle" + (this.isRounded === true ? ' q-btn--rounded' : ''))) +
|
|
(colors !== void 0 ? ' ' + colors : '') +
|
|
(this.isActionable === true ? ' q-btn--actionable q-focusable q-hoverable' : (this.disable === true ? ' disabled' : '')) +
|
|
(this.fab === true ? ' q-btn--fab' : (this.fabMini === true ? ' q-btn--fab-mini' : '')) +
|
|
(this.noCaps === true ? ' q-btn--no-uppercase' : '') +
|
|
(this.noWrap === true ? '' : ' q-btn--wrap') + // this is for IE11
|
|
(this.dense === true ? ' q-btn--dense' : '') +
|
|
(this.stretch === true ? ' no-border-radius self-stretch' : '') +
|
|
(this.glossy === true ? ' glossy' : '')
|
|
},
|
|
|
|
innerClasses: function innerClasses () {
|
|
return this.alignClass + (this.stack === true ? ' column' : ' row') +
|
|
(this.noWrap === true ? ' no-wrap text-no-wrap' : '') +
|
|
(this.loading === true ? ' q-btn__content--hidden' : '')
|
|
},
|
|
|
|
wrapperStyle: function wrapperStyle () {
|
|
if (this.padding !== void 0) {
|
|
return {
|
|
padding: this.padding
|
|
.split(/\s+/)
|
|
.map(function (v) { return v in padding ? padding[v] + 'px' : v; })
|
|
.join(' '),
|
|
minWidth: '0',
|
|
minHeight: '0'
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
var directions = [ 'left', 'right', 'up', 'down', 'horizontal', 'vertical' ];
|
|
|
|
var modifiersAll = {
|
|
left: true,
|
|
right: true,
|
|
up: true,
|
|
down: true,
|
|
horizontal: true,
|
|
vertical: true,
|
|
all: true
|
|
};
|
|
|
|
function getModifierDirections (mod) {
|
|
var dir = {};
|
|
|
|
directions.forEach(function (direction) {
|
|
if (mod[direction]) {
|
|
dir[direction] = true;
|
|
}
|
|
});
|
|
|
|
if (Object.keys(dir).length === 0) {
|
|
return modifiersAll
|
|
}
|
|
|
|
if (dir.horizontal === true) {
|
|
dir.left = dir.right = true;
|
|
}
|
|
if (dir.vertical === true) {
|
|
dir.up = dir.down = true;
|
|
}
|
|
if (dir.left === true && dir.right === true) {
|
|
dir.horizontal = true;
|
|
}
|
|
if (dir.up === true && dir.down === true) {
|
|
dir.vertical = true;
|
|
}
|
|
if (dir.horizontal === true && dir.vertical === true) {
|
|
dir.all = true;
|
|
}
|
|
|
|
return dir
|
|
}
|
|
|
|
var getTouchTarget = isSSR === false && iosEmulated !== true && (
|
|
client.is.ios === true ||
|
|
window.navigator.vendor.toLowerCase().indexOf('apple') > -1
|
|
)
|
|
? function () { return document; }
|
|
: function (target) { return target; };
|
|
|
|
function shouldStart (evt, ctx) {
|
|
return ctx.event === void 0 &&
|
|
evt.target !== void 0 &&
|
|
evt.target.draggable !== true &&
|
|
typeof ctx.handler === 'function' &&
|
|
evt.target.nodeName.toUpperCase() !== 'INPUT' &&
|
|
(evt.qClonedBy === void 0 || evt.qClonedBy.indexOf(ctx.uid) === -1)
|
|
}
|
|
|
|
var passiveCapture = listenOpts.passiveCapture;
|
|
|
|
var
|
|
touchTarget = void 0,
|
|
keyboardTarget = void 0,
|
|
mouseTarget = void 0;
|
|
|
|
var iconAttrs = { role: 'img', 'aria-hidden': 'true' };
|
|
|
|
var QBtn = Vue.extend({
|
|
name: 'QBtn',
|
|
|
|
mixins: [ BtnMixin ],
|
|
|
|
props: {
|
|
percentage: Number,
|
|
darkPercentage: Boolean
|
|
},
|
|
|
|
computed: {
|
|
hasLabel: function hasLabel () {
|
|
return this.label !== void 0 && this.label !== null && this.label !== ''
|
|
},
|
|
|
|
computedRipple: function computedRipple () {
|
|
return this.ripple === false
|
|
? false
|
|
: Object.assign({}, {keyCodes: this.isLink === true ? [ 13, 32 ] : [ 13 ]},
|
|
(this.ripple === true ? {} : this.ripple))
|
|
},
|
|
|
|
percentageStyle: function percentageStyle () {
|
|
var val = Math.max(0, Math.min(100, this.percentage));
|
|
if (val > 0) {
|
|
return { transition: 'transform 0.6s', transform: ("translateX(" + (val - 100) + "%)") }
|
|
}
|
|
},
|
|
|
|
onEvents: function onEvents () {
|
|
if (this.loading === true) {
|
|
return {
|
|
mousedown: this.__onLoadingEvt,
|
|
touchstart: this.__onLoadingEvt,
|
|
click: this.__onLoadingEvt,
|
|
keydown: this.__onLoadingEvt,
|
|
keyup: this.__onLoadingEvt
|
|
}
|
|
}
|
|
else if (this.isActionable === true) {
|
|
var on = Object.assign({}, this.qListeners,
|
|
{click: this.click,
|
|
keydown: this.__onKeydown,
|
|
mousedown: this.__onMousedown});
|
|
|
|
if (this.$q.platform.has.touch === true) {
|
|
on.touchstart = this.__onTouchstart;
|
|
}
|
|
|
|
return on
|
|
}
|
|
|
|
return {}
|
|
},
|
|
|
|
directives: function directives () {
|
|
if (this.disable !== true && this.ripple !== false) {
|
|
return [{
|
|
name: 'ripple',
|
|
value: this.computedRipple,
|
|
modifiers: { center: this.round }
|
|
}]
|
|
}
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
click: function click (e) {
|
|
var this$1 = this;
|
|
|
|
if (e !== void 0) {
|
|
if (e.defaultPrevented === true) {
|
|
return
|
|
}
|
|
|
|
var el = document.activeElement;
|
|
// focus button if it came from ENTER on form
|
|
// prevent the new submit (already done)
|
|
if (
|
|
this.type === 'submit' &&
|
|
(
|
|
(this.$q.platform.is.ie === true && (e.clientX < 0 || e.clientY < 0)) ||
|
|
(
|
|
el !== document.body &&
|
|
this.$el.contains(el) === false &&
|
|
// required for iOS and desktop Safari
|
|
el.contains(this.$el) === false
|
|
)
|
|
)
|
|
) {
|
|
this.$el.focus();
|
|
|
|
var onClickCleanup = function () {
|
|
document.removeEventListener('keydown', stopAndPrevent, true);
|
|
document.removeEventListener('keyup', onClickCleanup, passiveCapture);
|
|
this$1.$el !== void 0 && this$1.$el.removeEventListener('blur', onClickCleanup, passiveCapture);
|
|
};
|
|
|
|
document.addEventListener('keydown', stopAndPrevent, true);
|
|
document.addEventListener('keyup', onClickCleanup, passiveCapture);
|
|
this.$el.addEventListener('blur', onClickCleanup, passiveCapture);
|
|
}
|
|
|
|
if (this.hasRouterLink === true) {
|
|
if (
|
|
e.ctrlKey === true ||
|
|
e.shiftKey === true ||
|
|
e.altKey === true ||
|
|
e.metaKey === true
|
|
) {
|
|
// if it has meta keys, let vue-router link
|
|
// handle this by its own
|
|
return
|
|
}
|
|
|
|
stopAndPrevent(e);
|
|
}
|
|
}
|
|
|
|
var go = function () {
|
|
// vue-router now throwing error if navigating
|
|
// to the same route that the user is currently at
|
|
// https://github.com/vuejs/vue-router/issues/2872
|
|
this$1.$router[this$1.replace === true ? 'replace' : 'push'](this$1.currentLocation.route, void 0, noop);
|
|
};
|
|
|
|
this.$emit('click', e, go);
|
|
this.hasRouterLink === true && e.navigate !== false && go();
|
|
},
|
|
|
|
__onKeydown: function __onKeydown (e) {
|
|
if (isKeyCode(e, [ 13, 32 ]) === true) {
|
|
stopAndPrevent(e);
|
|
|
|
if (keyboardTarget !== this.$el) {
|
|
keyboardTarget !== void 0 && this.__cleanup();
|
|
|
|
// focus external button if the focus helper was focused before
|
|
this.$el.focus();
|
|
|
|
keyboardTarget = this.$el;
|
|
this.$el.classList.add('q-btn--active');
|
|
document.addEventListener('keyup', this.__onPressEnd, true);
|
|
this.$el.addEventListener('blur', this.__onPressEnd, passiveCapture);
|
|
}
|
|
}
|
|
|
|
this.$emit('keydown', e);
|
|
},
|
|
|
|
__onTouchstart: function __onTouchstart (e) {
|
|
var this$1 = this;
|
|
|
|
if (touchTarget !== this.$el) {
|
|
touchTarget !== void 0 && this.__cleanup();
|
|
touchTarget = this.$el;
|
|
var target = this.touchTargetEl = getTouchTarget(e.target);
|
|
target.addEventListener('touchcancel', this.__onPressEnd, passiveCapture);
|
|
target.addEventListener('touchend', this.__onPressEnd, passiveCapture);
|
|
}
|
|
|
|
// avoid duplicated mousedown event
|
|
// triggering another early ripple
|
|
this.avoidMouseRipple = true;
|
|
clearTimeout(this.mouseTimer);
|
|
this.mouseTimer = setTimeout(function () {
|
|
this$1.avoidMouseRipple = false;
|
|
}, 200);
|
|
|
|
this.$emit('touchstart', e);
|
|
},
|
|
|
|
__onMousedown: function __onMousedown (e) {
|
|
if (mouseTarget !== this.$el) {
|
|
mouseTarget !== void 0 && this.__cleanup();
|
|
mouseTarget = this.$el;
|
|
this.$el.classList.add('q-btn--active');
|
|
document.addEventListener('mouseup', this.__onPressEnd, passiveCapture);
|
|
}
|
|
|
|
e.qSkipRipple = this.avoidMouseRipple === true;
|
|
this.$emit('mousedown', e);
|
|
},
|
|
|
|
__onPressEnd: function __onPressEnd (e) {
|
|
// needed for IE (because it emits blur when focusing button from focus helper)
|
|
if (e !== void 0 && e.type === 'blur' && document.activeElement === this.$el) {
|
|
return
|
|
}
|
|
|
|
if (e !== void 0 && e.type === 'keyup') {
|
|
if (keyboardTarget === this.$el && isKeyCode(e, [ 13, 32 ]) === true) {
|
|
// for click trigger
|
|
var evt = new MouseEvent('click', e);
|
|
evt.qKeyEvent = true;
|
|
e.defaultPrevented === true && prevent(evt);
|
|
e.cancelBubble === true && stop(evt);
|
|
this.$el.dispatchEvent(evt);
|
|
|
|
stopAndPrevent(e);
|
|
|
|
// for ripple
|
|
e.qKeyEvent = true;
|
|
}
|
|
|
|
this.$emit('keyup', e);
|
|
}
|
|
|
|
this.__cleanup();
|
|
},
|
|
|
|
__cleanup: function __cleanup (destroying) {
|
|
var blurTarget = this.$refs.blurTarget;
|
|
|
|
if (
|
|
destroying !== true &&
|
|
(touchTarget === this.$el || mouseTarget === this.$el) &&
|
|
blurTarget !== void 0 &&
|
|
blurTarget !== document.activeElement
|
|
) {
|
|
blurTarget.setAttribute('tabindex', -1);
|
|
blurTarget.focus();
|
|
}
|
|
|
|
if (touchTarget === this.$el) {
|
|
var target = this.touchTargetEl;
|
|
target.removeEventListener('touchcancel', this.__onPressEnd, passiveCapture);
|
|
target.removeEventListener('touchend', this.__onPressEnd, passiveCapture);
|
|
touchTarget = this.touchTargetEl = void 0;
|
|
}
|
|
|
|
if (mouseTarget === this.$el) {
|
|
document.removeEventListener('mouseup', this.__onPressEnd, passiveCapture);
|
|
mouseTarget = void 0;
|
|
}
|
|
|
|
if (keyboardTarget === this.$el) {
|
|
document.removeEventListener('keyup', this.__onPressEnd, true);
|
|
this.$el !== void 0 && this.$el.removeEventListener('blur', this.__onPressEnd, passiveCapture);
|
|
keyboardTarget = void 0;
|
|
}
|
|
|
|
this.$el !== void 0 && this.$el.classList.remove('q-btn--active');
|
|
},
|
|
|
|
__onLoadingEvt: function __onLoadingEvt (evt) {
|
|
stopAndPrevent(evt);
|
|
evt.qSkipRipple = true;
|
|
}
|
|
},
|
|
|
|
beforeDestroy: function beforeDestroy () {
|
|
this.__cleanup(true);
|
|
},
|
|
|
|
render: function render (h) {
|
|
var inner = [];
|
|
|
|
this.icon !== void 0 && inner.push(
|
|
h(QIcon, {
|
|
attrs: iconAttrs,
|
|
props: { name: this.icon, left: this.stack === false && this.hasLabel === true }
|
|
})
|
|
);
|
|
|
|
this.hasLabel === true && inner.push(
|
|
h('span', { staticClass: 'block' }, [ this.label ])
|
|
);
|
|
|
|
inner = mergeSlot(inner, this, 'default');
|
|
|
|
if (this.iconRight !== void 0 && this.round === false) {
|
|
inner.push(
|
|
h(QIcon, {
|
|
attrs: iconAttrs,
|
|
props: { name: this.iconRight, right: this.stack === false && this.hasLabel === true }
|
|
})
|
|
);
|
|
}
|
|
|
|
var child = [
|
|
h('span', {
|
|
staticClass: 'q-focus-helper',
|
|
ref: 'blurTarget'
|
|
})
|
|
];
|
|
|
|
if (this.loading === true && this.percentage !== void 0) {
|
|
child.push(
|
|
h('span', {
|
|
staticClass: 'q-btn__progress absolute-full overflow-hidden'
|
|
}, [
|
|
h('span', {
|
|
staticClass: 'q-btn__progress-indicator fit block',
|
|
class: this.darkPercentage === true ? 'q-btn__progress--dark' : '',
|
|
style: this.percentageStyle
|
|
})
|
|
])
|
|
);
|
|
}
|
|
|
|
child.push(
|
|
h('span', {
|
|
staticClass: 'q-btn__wrapper col row q-anchor--skip',
|
|
style: this.wrapperStyle
|
|
}, [
|
|
h('span', {
|
|
staticClass: 'q-btn__content text-center col items-center q-anchor--skip',
|
|
class: this.innerClasses
|
|
}, inner)
|
|
])
|
|
);
|
|
|
|
this.loading !== null && child.push(
|
|
h('transition', {
|
|
props: { name: 'q-transition--fade' }
|
|
}, this.loading === true ? [
|
|
h('span', {
|
|
key: 'loading',
|
|
staticClass: 'absolute-full flex flex-center'
|
|
}, this.$scopedSlots.loading !== void 0 ? this.$scopedSlots.loading() : [ h(QSpinner) ])
|
|
] : void 0)
|
|
);
|
|
|
|
return h(this.isLink === true ? 'a' : 'button', {
|
|
staticClass: 'q-btn q-btn-item non-selectable no-outline',
|
|
class: this.classes,
|
|
style: this.style,
|
|
attrs: this.attrs,
|
|
on: this.onEvents,
|
|
directives: this.directives
|
|
}, child)
|
|
}
|
|
});
|
|
|
|
var QBtnGroup = Vue.extend({
|
|
name: 'QBtnGroup',
|
|
|
|
mixin: [ ListenersMixin ],
|
|
|
|
props: {
|
|
unelevated: Boolean,
|
|
outline: Boolean,
|
|
flat: Boolean,
|
|
rounded: Boolean,
|
|
push: Boolean,
|
|
stretch: Boolean,
|
|
glossy: Boolean,
|
|
spread: Boolean
|
|
},
|
|
|
|
computed: {
|
|
classes: function classes () {
|
|
var this$1 = this;
|
|
|
|
return ['unelevated', 'outline', 'flat', 'rounded', 'push', 'stretch', 'glossy']
|
|
.filter(function (t) { return this$1[t] === true; })
|
|
.map(function (t) { return ("q-btn-group--" + t); }).join(' ')
|
|
}
|
|
},
|
|
|
|
render: function render (h) {
|
|
return h('div', {
|
|
staticClass: 'q-btn-group row no-wrap ' +
|
|
(this.spread === true ? 'q-btn-group--spread' : 'inline'),
|
|
class: this.classes,
|
|
on: Object.assign({}, this.qListeners)
|
|
}, slot(this, 'default'))
|
|
}
|
|
});
|
|
|
|
function clearSelection () {
|
|
if (window.getSelection !== void 0) {
|
|
var selection = window.getSelection();
|
|
if (selection.empty !== void 0) {
|
|
selection.empty();
|
|
}
|
|
else if (selection.removeAllRanges !== void 0) {
|
|
selection.removeAllRanges();
|
|
Platform.is.mobile !== true && selection.addRange(document.createRange());
|
|
}
|
|
}
|
|
else if (document.selection !== void 0) {
|
|
document.selection.empty();
|
|
}
|
|
}
|
|
|
|
var AnchorMixin = {
|
|
props: {
|
|
target: {
|
|
default: true
|
|
},
|
|
noParentEvent: Boolean,
|
|
contextMenu: Boolean
|
|
},
|
|
|
|
watch: {
|
|
contextMenu: function contextMenu (val) {
|
|
if (this.anchorEl !== void 0) {
|
|
this.__unconfigureAnchorEl();
|
|
this.__configureAnchorEl(val);
|
|
}
|
|
},
|
|
|
|
target: function target () {
|
|
if (this.anchorEl !== void 0) {
|
|
this.__unconfigureAnchorEl();
|
|
}
|
|
|
|
this.__pickAnchorEl();
|
|
},
|
|
|
|
noParentEvent: function noParentEvent (val) {
|
|
if (this.anchorEl !== void 0) {
|
|
if (val === true) {
|
|
this.__unconfigureAnchorEl();
|
|
}
|
|
else {
|
|
this.__configureAnchorEl();
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
__showCondition: function __showCondition (evt) {
|
|
// abort with no parent configured or on multi-touch
|
|
if (this.anchorEl === void 0) {
|
|
return false
|
|
}
|
|
if (evt === void 0) {
|
|
return true
|
|
}
|
|
return evt.touches === void 0 || evt.touches.length <= 1
|
|
},
|
|
|
|
__contextClick: function __contextClick (evt) {
|
|
var this$1 = this;
|
|
|
|
this.hide(evt);
|
|
this.$nextTick(function () {
|
|
this$1.show(evt);
|
|
});
|
|
prevent(evt);
|
|
},
|
|
|
|
__toggleKey: function __toggleKey (evt) {
|
|
isKeyCode(evt, 13) === true && this.toggle(evt);
|
|
},
|
|
|
|
__mobileCleanup: function __mobileCleanup (evt) {
|
|
this.anchorEl.classList.remove('non-selectable');
|
|
clearTimeout(this.touchTimer);
|
|
|
|
if (this.showing === true && evt !== void 0) {
|
|
clearSelection();
|
|
}
|
|
},
|
|
|
|
__mobilePrevent: prevent,
|
|
|
|
__mobileTouch: function __mobileTouch (evt) {
|
|
var this$1 = this;
|
|
|
|
this.__mobileCleanup(evt);
|
|
|
|
if (this.__showCondition(evt) !== true) {
|
|
return
|
|
}
|
|
|
|
this.hide(evt);
|
|
this.anchorEl.classList.add('non-selectable');
|
|
|
|
var target = getTouchTarget(evt.target);
|
|
addEvt(this, 'anchor', [
|
|
[ target, 'touchmove', '__mobileCleanup', 'passive' ],
|
|
[ target, 'touchend', '__mobileCleanup', 'passive' ],
|
|
[ target, 'touchcancel', '__mobileCleanup', 'passive' ],
|
|
[ this.anchorEl, 'contextmenu', '__mobilePrevent', 'notPassive' ]
|
|
]);
|
|
|
|
this.touchTimer = setTimeout(function () {
|
|
this$1.show(evt);
|
|
}, 300);
|
|
},
|
|
|
|
__unconfigureAnchorEl: function __unconfigureAnchorEl () {
|
|
cleanEvt(this, 'anchor');
|
|
},
|
|
|
|
__configureAnchorEl: function __configureAnchorEl (context) {
|
|
if ( context === void 0 ) context = this.contextMenu;
|
|
|
|
if (this.noParentEvent === true || this.anchorEl === void 0) { return }
|
|
|
|
var evts;
|
|
|
|
if (context === true) {
|
|
if (this.$q.platform.is.mobile === true) {
|
|
evts = [
|
|
[ this.anchorEl, 'touchstart', '__mobileTouch', 'passive' ]
|
|
];
|
|
}
|
|
else {
|
|
evts = [
|
|
[ this.anchorEl, 'click', 'hide', 'passive' ],
|
|
[ this.anchorEl, 'contextmenu', '__contextClick', 'notPassive' ]
|
|
];
|
|
}
|
|
}
|
|
else {
|
|
evts = [
|
|
[ this.anchorEl, 'click', 'toggle', 'passive' ],
|
|
[ this.anchorEl, 'keyup', '__toggleKey', 'passive' ]
|
|
];
|
|
}
|
|
|
|
addEvt(this, 'anchor', evts);
|
|
},
|
|
|
|
__setAnchorEl: function __setAnchorEl (el) {
|
|
this.anchorEl = el;
|
|
while (this.anchorEl.classList.contains('q-anchor--skip')) {
|
|
this.anchorEl = this.anchorEl.parentNode;
|
|
}
|
|
this.__configureAnchorEl();
|
|
},
|
|
|
|
__pickAnchorEl: function __pickAnchorEl () {
|
|
if (this.target === false || this.target === '') {
|
|
this.anchorEl = void 0;
|
|
}
|
|
else if (this.target === true) {
|
|
this.__setAnchorEl(this.parentEl);
|
|
}
|
|
else {
|
|
var el = this.target;
|
|
|
|
if (typeof this.target === 'string') {
|
|
try {
|
|
el = document.querySelector(this.target);
|
|
}
|
|
catch (err) {
|
|
el = void 0;
|
|
}
|
|
}
|
|
|
|
if (el !== void 0 && el !== null) {
|
|
this.anchorEl = el._isVue === true && el.$el !== void 0 ? el.$el : el;
|
|
this.__configureAnchorEl();
|
|
}
|
|
else {
|
|
this.anchorEl = void 0;
|
|
console.error(("Anchor: target \"" + (this.target) + "\" not found"), this);
|
|
}
|
|
}
|
|
},
|
|
|
|
__changeScrollEvent: function __changeScrollEvent (scrollTarget, fn) {
|
|
var fnProp = (fn !== void 0 ? 'add' : 'remove') + "EventListener";
|
|
var fnHandler = fn !== void 0 ? fn : this.__scrollFn;
|
|
|
|
if (scrollTarget !== window) {
|
|
scrollTarget[fnProp]('scroll', fnHandler, listenOpts.passive);
|
|
}
|
|
|
|
window[fnProp]('scroll', fnHandler, listenOpts.passive);
|
|
|
|
this.__scrollFn = fn;
|
|
}
|
|
},
|
|
|
|
created: function created () {
|
|
var this$1 = this;
|
|
|
|
if (
|
|
typeof this.__configureScrollTarget === 'function' &&
|
|
typeof this.__unconfigureScrollTarget === 'function'
|
|
) {
|
|
this.noParentEventWatcher = this.$watch('noParentEvent', function () {
|
|
if (this$1.__scrollTarget !== void 0) {
|
|
this$1.__unconfigureScrollTarget();
|
|
this$1.__configureScrollTarget();
|
|
}
|
|
});
|
|
}
|
|
},
|
|
|
|
mounted: function mounted () {
|
|
this.parentEl = this.$el.parentNode;
|
|
this.__pickAnchorEl();
|
|
|
|
if (this.value === true && this.anchorEl === void 0) {
|
|
this.$emit('input', false);
|
|
}
|
|
},
|
|
|
|
beforeDestroy: function beforeDestroy () {
|
|
clearTimeout(this.touchTimer);
|
|
this.noParentEventWatcher !== void 0 && this.noParentEventWatcher();
|
|
this.__anchorCleanup !== void 0 && this.__anchorCleanup();
|
|
this.__unconfigureAnchorEl();
|
|
}
|
|
};
|
|
|
|
var TimeoutMixin = {
|
|
methods: {
|
|
__nextTick: function __nextTick (fn) {
|
|
this.__tickFn = fn;
|
|
},
|
|
|
|
__prepareTick: function __prepareTick () {
|
|
var this$1 = this;
|
|
|
|
if (this.__tickFn !== void 0) {
|
|
var fn = this.__tickFn;
|
|
this.$nextTick(function () {
|
|
if (this$1.__tickFn === fn) {
|
|
this$1.__tickFn();
|
|
this$1.__tickFn = void 0;
|
|
}
|
|
});
|
|
}
|
|
},
|
|
|
|
__clearTick: function __clearTick () {
|
|
this.__tickFn = void 0;
|
|
},
|
|
|
|
__setTimeout: function __setTimeout (fn, delay) {
|
|
clearTimeout(this.__timer);
|
|
this.__timer = setTimeout(fn, delay);
|
|
},
|
|
|
|
__clearTimeout: function __clearTimeout () {
|
|
clearTimeout(this.__timer);
|
|
}
|
|
},
|
|
|
|
beforeDestroy: function beforeDestroy () {
|
|
this.__tickFn = void 0;
|
|
clearTimeout(this.__timer);
|
|
}
|
|
};
|
|
|
|
var ModelToggleMixin = {
|
|
mixins: [ TimeoutMixin, ListenersMixin ],
|
|
|
|
props: {
|
|
value: {
|
|
type: Boolean,
|
|
default: void 0
|
|
}
|
|
},
|
|
|
|
data: function data () {
|
|
return {
|
|
showing: false
|
|
}
|
|
},
|
|
|
|
watch: {
|
|
value: function value (val) {
|
|
this.__processModelChange(val);
|
|
},
|
|
|
|
$route: function $route () {
|
|
this.hideOnRouteChange === true && this.showing === true && this.hide();
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
toggle: function toggle (evt) {
|
|
this[this.showing === true ? 'hide' : 'show'](evt);
|
|
},
|
|
|
|
show: function show (evt) {
|
|
var this$1 = this;
|
|
|
|
if (this.disable === true || (this.__showCondition !== void 0 && this.__showCondition(evt) !== true)) {
|
|
return
|
|
}
|
|
|
|
if (this.qListeners.input !== void 0 && isSSR === false) {
|
|
this.$emit('input', true);
|
|
this.payload = evt;
|
|
this.$nextTick(function () {
|
|
if (this$1.payload === evt) {
|
|
this$1.payload = void 0;
|
|
}
|
|
});
|
|
}
|
|
|
|
if (this.value === void 0 || this.qListeners.input === void 0 || isSSR === true) {
|
|
this.__processShow(evt);
|
|
}
|
|
},
|
|
|
|
__processShow: function __processShow (evt) {
|
|
if (this.showing === true) {
|
|
return
|
|
}
|
|
|
|
// need to call it before setting showing to true
|
|
// in order to not ruin the animation
|
|
this.__preparePortal !== void 0 && this.__preparePortal();
|
|
|
|
this.showing = true;
|
|
|
|
this.$emit('before-show', evt);
|
|
|
|
if (this.__show !== void 0) {
|
|
this.__clearTick();
|
|
this.__show(evt);
|
|
this.__prepareTick();
|
|
}
|
|
else {
|
|
this.$emit('show', evt);
|
|
}
|
|
},
|
|
|
|
hide: function hide (evt) {
|
|
var this$1 = this;
|
|
|
|
if (this.disable === true) {
|
|
return
|
|
}
|
|
|
|
if (this.qListeners.input !== void 0 && isSSR === false) {
|
|
this.$emit('input', false);
|
|
this.payload = evt;
|
|
this.$nextTick(function () {
|
|
if (this$1.payload === evt) {
|
|
this$1.payload = void 0;
|
|
}
|
|
});
|
|
}
|
|
if (this.value === void 0 || this.qListeners.input === void 0 || isSSR === true) {
|
|
this.__processHide(evt);
|
|
}
|
|
},
|
|
|
|
__processHide: function __processHide (evt) {
|
|
if (this.showing === false) {
|
|
return
|
|
}
|
|
|
|
this.showing = false;
|
|
|
|
this.$emit('before-hide', evt);
|
|
|
|
if (this.__hide !== void 0) {
|
|
this.__clearTick();
|
|
this.__hide(evt);
|
|
this.__prepareTick();
|
|
}
|
|
else {
|
|
this.$emit('hide', evt);
|
|
}
|
|
},
|
|
|
|
__processModelChange: function __processModelChange (val) {
|
|
if (this.disable === true && val === true) {
|
|
this.qListeners.input !== void 0 && this.$emit('input', false);
|
|
}
|
|
else if ((val === true) !== this.showing) {
|
|
this[("__process" + (val === true ? 'Show' : 'Hide'))](this.payload);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
function closePortalMenus (vm, evt) {
|
|
do {
|
|
if (vm.$options.name === 'QMenu') {
|
|
vm.hide(evt);
|
|
|
|
// is this a point of separation?
|
|
if (vm.separateClosePopup === true) {
|
|
return vm.$parent
|
|
}
|
|
}
|
|
else if (vm.__renderPortal !== void 0) {
|
|
// treat it as point of separation if parent is QPopupProxy
|
|
// (so mobile matches desktop behavior)
|
|
// and hide it too
|
|
if (vm.$parent !== void 0 && vm.$parent.$options.name === 'QPopupProxy') {
|
|
vm.hide(evt);
|
|
return vm.$parent
|
|
}
|
|
else {
|
|
return vm
|
|
}
|
|
}
|
|
vm = vm.$parent;
|
|
} while (vm !== void 0)
|
|
}
|
|
|
|
function closePortals (vm, evt, depth) {
|
|
while (depth !== 0 && vm !== void 0) {
|
|
if (vm.__renderPortal !== void 0) {
|
|
depth--;
|
|
|
|
if (vm.$options.name === 'QMenu') {
|
|
vm = closePortalMenus(vm, evt);
|
|
continue
|
|
}
|
|
|
|
vm.hide(evt);
|
|
}
|
|
|
|
vm = vm.$parent;
|
|
}
|
|
}
|
|
|
|
function isOnGlobalDialog (vm) {
|
|
while (vm !== void 0) {
|
|
if (vm.$options.name === 'QGlobalDialog') {
|
|
return true
|
|
}
|
|
if (vm.$options.name === 'QDialog') {
|
|
return false
|
|
}
|
|
|
|
vm = vm.$parent;
|
|
}
|
|
return false
|
|
}
|
|
|
|
var Portal = {
|
|
inheritAttrs: false,
|
|
|
|
props: {
|
|
contentClass: [ Array, String, Object ],
|
|
contentStyle: [ Array, String, Object ]
|
|
},
|
|
|
|
methods: {
|
|
__showPortal: function __showPortal () {
|
|
var this$1 = this;
|
|
|
|
if (this.$q.fullscreen !== void 0 && this.$q.fullscreen.isCapable === true) {
|
|
var append = function (isFullscreen) {
|
|
if (this$1.__portal === void 0) {
|
|
return
|
|
}
|
|
|
|
var newParent = getBodyFullscreenElement(
|
|
isFullscreen,
|
|
this$1.$q.fullscreen.activeEl
|
|
);
|
|
|
|
if (
|
|
this$1.__portal.$el.parentElement !== newParent &&
|
|
newParent.contains(this$1.$el) === (this$1.__onGlobalDialog === false)
|
|
) {
|
|
newParent.appendChild(this$1.__portal.$el);
|
|
}
|
|
};
|
|
|
|
this.unwatchFullscreen = this.$watch('$q.fullscreen.isActive', append);
|
|
|
|
var isActive = this.$q.fullscreen.isActive;
|
|
|
|
if (this.__onGlobalDialog === false || isActive === true) {
|
|
append(isActive);
|
|
}
|
|
}
|
|
else if (this.__portal !== void 0 && this.__onGlobalDialog === false) {
|
|
document.body.appendChild(this.__portal.$el);
|
|
}
|
|
},
|
|
|
|
__hidePortal: function __hidePortal () {
|
|
if (this.__portal !== void 0) {
|
|
if (this.unwatchFullscreen !== void 0) {
|
|
this.unwatchFullscreen();
|
|
this.unwatchFullscreen = void 0;
|
|
}
|
|
|
|
if (this.__onGlobalDialog === false) {
|
|
this.__portal.$destroy();
|
|
this.__portal.$el.remove();
|
|
}
|
|
|
|
this.__portal = void 0;
|
|
}
|
|
},
|
|
|
|
__preparePortal: function __preparePortal () {
|
|
var this$1 = this;
|
|
|
|
if (this.__portal === void 0) {
|
|
this.__portal = this.__onGlobalDialog === true
|
|
? {
|
|
$el: this.$el,
|
|
$refs: this.$refs
|
|
}
|
|
: new Vue({
|
|
name: 'QPortal',
|
|
parent: this,
|
|
|
|
inheritAttrs: false,
|
|
|
|
render: function (h) { return this$1.__renderPortal(h); },
|
|
|
|
components: this.$options.components,
|
|
directives: this.$options.directives
|
|
}).$mount();
|
|
}
|
|
}
|
|
},
|
|
|
|
render: function render (h) {
|
|
if (this.__onGlobalDialog === true) {
|
|
return this.__renderPortal(h)
|
|
}
|
|
|
|
if (this.__portal !== void 0) {
|
|
this.__portal.$forceUpdate();
|
|
}
|
|
},
|
|
|
|
beforeDestroy: function beforeDestroy () {
|
|
this.__hidePortal();
|
|
}
|
|
};
|
|
|
|
if (isSSR === false) {
|
|
Portal.created = function () {
|
|
this.__onGlobalDialog = isOnGlobalDialog(this.$parent);
|
|
};
|
|
}
|
|
|
|
var TransitionMixin = {
|
|
props: {
|
|
transitionShow: {
|
|
type: String,
|
|
default: 'fade'
|
|
},
|
|
|
|
transitionHide: {
|
|
type: String,
|
|
default: 'fade'
|
|
}
|
|
},
|
|
|
|
data: function data () {
|
|
return {
|
|
transitionState: this.showing
|
|
}
|
|
},
|
|
|
|
watch: {
|
|
showing: function showing (val) {
|
|
var this$1 = this;
|
|
|
|
this.transitionShow !== this.transitionHide && this.$nextTick(function () {
|
|
this$1.transitionState = val;
|
|
});
|
|
}
|
|
},
|
|
|
|
computed: {
|
|
transition: function transition () {
|
|
return 'q-transition--' + (this.transitionState === true ? this.transitionHide : this.transitionShow)
|
|
}
|
|
}
|
|
};
|
|
|
|
function getVmOfNode (el) {
|
|
for (var node = el; node !== null; node = node.parentNode) {
|
|
// node.__vue__ can be null if the instance was destroyed
|
|
if (node.__vue__ === null) {
|
|
return
|
|
}
|
|
if (node.__vue__ !== void 0) {
|
|
return node.__vue__
|
|
}
|
|
}
|
|
}
|
|
|
|
function isVmChildOf (childVm, parentVm) {
|
|
for (var vm = childVm; vm !== void 0; vm = vm.$parent) {
|
|
if (vm === parentVm) {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
var timer;
|
|
|
|
var notPassiveCapture = listenOpts.notPassiveCapture;
|
|
var passiveCapture$1 = listenOpts.passiveCapture;
|
|
var handlers = {
|
|
click: [],
|
|
focus: []
|
|
};
|
|
|
|
function execHandlers (list, evt) {
|
|
for (var i = list.length - 1; i >= 0; i--) {
|
|
if (list[i](evt) === void 0) {
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
function globalHandler (evt) {
|
|
clearTimeout(timer);
|
|
|
|
// prevent autofocus on body resulting from blur
|
|
if (evt.type === 'focusin' && evt.target.hasAttribute('tabindex') === true) {
|
|
timer = setTimeout(function () {
|
|
execHandlers(handlers.focus, evt);
|
|
}, 200);
|
|
}
|
|
else {
|
|
execHandlers(handlers.click, evt);
|
|
}
|
|
}
|
|
|
|
var ClickOutside = {
|
|
name: 'click-outside',
|
|
|
|
bind: function bind (el, ref, vnode) {
|
|
var value = ref.value;
|
|
var arg = ref.arg;
|
|
|
|
var vmEl = vnode.componentInstance || vnode.context;
|
|
|
|
var ctx = {
|
|
trigger: value,
|
|
toggleEl: arg,
|
|
|
|
handler: function handler (evt) {
|
|
var target = evt.target;
|
|
|
|
if (
|
|
target !== void 0 &&
|
|
target.nodeType !== 8 &&
|
|
// directives that prevent click by using pointer-events none generate click on html element
|
|
target !== document.documentElement &&
|
|
target.classList.contains('no-pointer-events') === false &&
|
|
(
|
|
ctx.toggleEl === void 0 ||
|
|
ctx.toggleEl.contains(target) === false
|
|
) &&
|
|
(
|
|
target === document.body ||
|
|
isVmChildOf(getVmOfNode(target), vmEl) === false
|
|
)
|
|
) {
|
|
// mark the event as being processed by clickOutside
|
|
// used to prevent refocus after menu close
|
|
evt.qClickOutside = true;
|
|
|
|
return ctx.trigger(evt)
|
|
}
|
|
}
|
|
};
|
|
|
|
if (el.__qclickoutside) {
|
|
el.__qclickoutside_old = el.__qclickoutside;
|
|
}
|
|
|
|
el.__qclickoutside = ctx;
|
|
|
|
if (handlers.click.length === 0) {
|
|
document.addEventListener('mousedown', globalHandler, notPassiveCapture);
|
|
document.addEventListener('touchstart', globalHandler, notPassiveCapture);
|
|
document.addEventListener('focusin', globalHandler, passiveCapture$1);
|
|
}
|
|
|
|
handlers.click.push(ctx.handler);
|
|
|
|
ctx.timerFocusin = setTimeout(function () {
|
|
handlers.focus.push(ctx.handler);
|
|
}, 500);
|
|
},
|
|
|
|
update: function update (el, ref) {
|
|
var value = ref.value;
|
|
var oldValue = ref.oldValue;
|
|
var arg = ref.arg;
|
|
|
|
var ctx = el.__qclickoutside;
|
|
|
|
if (value !== oldValue) {
|
|
ctx.trigger = value;
|
|
}
|
|
if (arg !== ctx.arg) {
|
|
ctx.toggleEl = arg;
|
|
}
|
|
},
|
|
|
|
unbind: function unbind (el) {
|
|
var ctx = el.__qclickoutside_old || el.__qclickoutside;
|
|
if (ctx !== void 0) {
|
|
clearTimeout(ctx.timerFocusin);
|
|
|
|
var
|
|
indexClick = handlers.click.findIndex(function (h) { return h === ctx.handler; }),
|
|
indexFocus = handlers.focus.findIndex(function (h) { return h === ctx.handler; });
|
|
|
|
indexClick > -1 && handlers.click.splice(indexClick, 1);
|
|
indexFocus > -1 && handlers.focus.splice(indexFocus, 1);
|
|
|
|
if (handlers.click.length === 0) {
|
|
clearTimeout(timer);
|
|
document.removeEventListener('mousedown', globalHandler, notPassiveCapture);
|
|
document.removeEventListener('touchstart', globalHandler, notPassiveCapture);
|
|
document.removeEventListener('focusin', globalHandler, passiveCapture$1);
|
|
}
|
|
|
|
delete el[el.__qclickoutside_old ? '__qclickoutside_old' : '__qclickoutside'];
|
|
}
|
|
}
|
|
};
|
|
|
|
var scrollTargets = isSSR === false
|
|
? [ null, document, document.body, document.scrollingElement, document.documentElement ]
|
|
: [];
|
|
|
|
function getScrollTarget (el, target) {
|
|
if (typeof target === 'string') {
|
|
try {
|
|
target = document.querySelector(target);
|
|
}
|
|
catch (err) {
|
|
target = void 0;
|
|
}
|
|
}
|
|
|
|
if (target === void 0 || target === null) {
|
|
target = el.closest('.scroll,.scroll-y,.overflow-auto');
|
|
}
|
|
else if (target._isVue === true && target.$el !== void 0) {
|
|
target = target.$el;
|
|
}
|
|
|
|
return scrollTargets.includes(target)
|
|
? window
|
|
: target
|
|
}
|
|
|
|
function getScrollHeight (el) {
|
|
return (el === window ? document.body : el).scrollHeight
|
|
}
|
|
|
|
function getScrollWidth (el) {
|
|
return (el === window ? document.body : el).scrollWidth
|
|
}
|
|
|
|
function getScrollPosition (scrollTarget) {
|
|
if (scrollTarget === window) {
|
|
return window.pageYOffset || window.scrollY || document.body.scrollTop || 0
|
|
}
|
|
return scrollTarget.scrollTop
|
|
}
|
|
|
|
function getHorizontalScrollPosition (scrollTarget) {
|
|
if (scrollTarget === window) {
|
|
return window.pageXOffset || window.scrollX || document.body.scrollLeft || 0
|
|
}
|
|
return scrollTarget.scrollLeft
|
|
}
|
|
|
|
function animScrollTo (el, to, duration) {
|
|
if ( duration === void 0 ) duration = 0;
|
|
|
|
var pos = getScrollPosition(el);
|
|
|
|
if (duration <= 0) {
|
|
if (pos !== to) {
|
|
setScroll(el, to);
|
|
}
|
|
return
|
|
}
|
|
|
|
requestAnimationFrame(function () {
|
|
var newPos = pos + (to - pos) / Math.max(16, duration) * 16;
|
|
setScroll(el, newPos);
|
|
if (newPos !== to) {
|
|
animScrollTo(el, to, duration - 16);
|
|
}
|
|
});
|
|
}
|
|
|
|
function animHorizontalScrollTo (el, to, duration) {
|
|
if ( duration === void 0 ) duration = 0;
|
|
|
|
var pos = getHorizontalScrollPosition(el);
|
|
|
|
if (duration <= 0) {
|
|
if (pos !== to) {
|
|
setHorizontalScroll(el, to);
|
|
}
|
|
return
|
|
}
|
|
|
|
requestAnimationFrame(function () {
|
|
var newPos = pos + (to - pos) / Math.max(16, duration) * 16;
|
|
setHorizontalScroll(el, newPos);
|
|
if (newPos !== to) {
|
|
animHorizontalScrollTo(el, to, duration - 16);
|
|
}
|
|
});
|
|
}
|
|
|
|
function setScroll (scrollTarget, offset) {
|
|
if (scrollTarget === window) {
|
|
window.scrollTo(window.pageXOffset || window.scrollX || document.body.scrollLeft || 0, offset);
|
|
return
|
|
}
|
|
scrollTarget.scrollTop = offset;
|
|
}
|
|
|
|
function setHorizontalScroll (scrollTarget, offset) {
|
|
if (scrollTarget === window) {
|
|
window.scrollTo(offset, window.pageYOffset || window.scrollY || document.body.scrollTop || 0);
|
|
return
|
|
}
|
|
scrollTarget.scrollLeft = offset;
|
|
}
|
|
|
|
function setScrollPosition (scrollTarget, offset, duration) {
|
|
if (duration) {
|
|
animScrollTo(scrollTarget, offset, duration);
|
|
return
|
|
}
|
|
setScroll(scrollTarget, offset);
|
|
}
|
|
|
|
function setHorizontalScrollPosition (scrollTarget, offset, duration) {
|
|
if (duration) {
|
|
animHorizontalScrollTo(scrollTarget, offset, duration);
|
|
return
|
|
}
|
|
setHorizontalScroll(scrollTarget, offset);
|
|
}
|
|
|
|
var size;
|
|
function getScrollbarWidth () {
|
|
if (size !== undefined) {
|
|
return size
|
|
}
|
|
|
|
var
|
|
inner = document.createElement('p'),
|
|
outer = document.createElement('div');
|
|
|
|
css(inner, {
|
|
width: '100%',
|
|
height: '200px'
|
|
});
|
|
css(outer, {
|
|
position: 'absolute',
|
|
top: '0px',
|
|
left: '0px',
|
|
visibility: 'hidden',
|
|
width: '200px',
|
|
height: '150px',
|
|
overflow: 'hidden'
|
|
});
|
|
|
|
outer.appendChild(inner);
|
|
|
|
document.body.appendChild(outer);
|
|
|
|
var w1 = inner.offsetWidth;
|
|
outer.style.overflow = 'scroll';
|
|
var w2 = inner.offsetWidth;
|
|
|
|
if (w1 === w2) {
|
|
w2 = outer.clientWidth;
|
|
}
|
|
|
|
outer.remove();
|
|
size = w1 - w2;
|
|
|
|
return size
|
|
}
|
|
|
|
function hasScrollbar (el, onY) {
|
|
if ( onY === void 0 ) onY = true;
|
|
|
|
if (!el || el.nodeType !== Node.ELEMENT_NODE) {
|
|
return false
|
|
}
|
|
|
|
return onY
|
|
? (
|
|
el.scrollHeight > el.clientHeight && (
|
|
el.classList.contains('scroll') ||
|
|
el.classList.contains('overflow-auto') ||
|
|
['auto', 'scroll'].includes(window.getComputedStyle(el)['overflow-y'])
|
|
)
|
|
)
|
|
: (
|
|
el.scrollWidth > el.clientWidth && (
|
|
el.classList.contains('scroll') ||
|
|
el.classList.contains('overflow-auto') ||
|
|
['auto', 'scroll'].includes(window.getComputedStyle(el)['overflow-x'])
|
|
)
|
|
)
|
|
}
|
|
|
|
var scroll = {
|
|
getScrollTarget: getScrollTarget,
|
|
|
|
getScrollHeight: getScrollHeight,
|
|
getScrollWidth: getScrollWidth,
|
|
|
|
getScrollPosition: getScrollPosition,
|
|
getHorizontalScrollPosition: getHorizontalScrollPosition,
|
|
|
|
animScrollTo: animScrollTo,
|
|
animHorizontalScrollTo: animHorizontalScrollTo,
|
|
|
|
setScrollPosition: setScrollPosition,
|
|
setHorizontalScrollPosition: setHorizontalScrollPosition,
|
|
|
|
getScrollbarWidth: getScrollbarWidth,
|
|
hasScrollbar: hasScrollbar
|
|
};
|
|
|
|
var handlers$1 = [];
|
|
var escDown = false;
|
|
|
|
var EscapeKey = {
|
|
__install: function __install () {
|
|
this.__installed = true;
|
|
window.addEventListener('keydown', function (evt) {
|
|
escDown = evt.keyCode === 27;
|
|
});
|
|
window.addEventListener('blur', function () {
|
|
escDown === true && (escDown = false);
|
|
});
|
|
window.addEventListener('keyup', function (evt) {
|
|
if (escDown === true) {
|
|
escDown = false;
|
|
|
|
if (handlers$1.length !== 0 && isKeyCode(evt, 27) === true) {
|
|
handlers$1[handlers$1.length - 1].fn(evt);
|
|
}
|
|
}
|
|
});
|
|
},
|
|
|
|
register: function register (comp, fn) {
|
|
if (comp.$q.platform.is.desktop === true) {
|
|
this.__installed !== true && this.__install();
|
|
handlers$1.push({ comp: comp, fn: fn });
|
|
}
|
|
},
|
|
|
|
pop: function pop (comp) {
|
|
if (comp.$q.platform.is.desktop === true) {
|
|
var index = handlers$1.findIndex(function (h) { return h.comp === comp; });
|
|
if (index > -1) {
|
|
handlers$1.splice(index, 1);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
var vpLeft, vpTop;
|
|
|
|
function validatePosition (pos) {
|
|
var parts = pos.split(' ');
|
|
if (parts.length !== 2) {
|
|
return false
|
|
}
|
|
if (!['top', 'center', 'bottom'].includes(parts[0])) {
|
|
console.error('Anchor/Self position must start with one of top/center/bottom');
|
|
return false
|
|
}
|
|
if (!['left', 'middle', 'right'].includes(parts[1])) {
|
|
console.error('Anchor/Self position must end with one of left/middle/right');
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
function validateOffset (val) {
|
|
if (!val) { return true }
|
|
if (val.length !== 2) { return false }
|
|
if (typeof val[0] !== 'number' || typeof val[1] !== 'number') {
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
function parsePosition (pos) {
|
|
var parts = pos.split(' ');
|
|
return { vertical: parts[0], horizontal: parts[1] }
|
|
}
|
|
|
|
function getAnchorProps (el, offset) {
|
|
var ref = el.getBoundingClientRect();
|
|
var top = ref.top;
|
|
var left = ref.left;
|
|
var right = ref.right;
|
|
var bottom = ref.bottom;
|
|
var width = ref.width;
|
|
var height = ref.height;
|
|
|
|
if (offset !== void 0) {
|
|
top -= offset[1];
|
|
left -= offset[0];
|
|
bottom += offset[1];
|
|
right += offset[0];
|
|
|
|
width += offset[0];
|
|
height += offset[1];
|
|
}
|
|
|
|
return {
|
|
top: top,
|
|
left: left,
|
|
right: right,
|
|
bottom: bottom,
|
|
width: width,
|
|
height: height,
|
|
middle: left + (right - left) / 2,
|
|
center: top + (bottom - top) / 2
|
|
}
|
|
}
|
|
|
|
function getTargetProps (el) {
|
|
return {
|
|
top: 0,
|
|
center: el.offsetHeight / 2,
|
|
bottom: el.offsetHeight,
|
|
left: 0,
|
|
middle: el.offsetWidth / 2,
|
|
right: el.offsetWidth
|
|
}
|
|
}
|
|
|
|
// cfg: { el, anchorEl, anchorOrigin, selfOrigin, offset, absoluteOffset, cover, fit, maxHeight, maxWidth }
|
|
function setPosition (cfg) {
|
|
if (client.is.ios === true && window.visualViewport !== void 0) {
|
|
// uses the q-position-engine CSS class
|
|
|
|
var el = document.body.style;
|
|
var ref = window.visualViewport;
|
|
var left = ref.offsetLeft;
|
|
var top = ref.offsetTop;
|
|
|
|
if (left !== vpLeft) {
|
|
el.setProperty('--q-pe-left', left + 'px');
|
|
vpLeft = left;
|
|
}
|
|
if (top !== vpTop) {
|
|
el.setProperty('--q-pe-top', top + 'px');
|
|
vpTop = top;
|
|
}
|
|
}
|
|
|
|
var anchorProps;
|
|
|
|
// scroll position might change
|
|
// if max-height/-width changes, so we
|
|
// need to restore it after we calculate
|
|
// the new positioning
|
|
var ref$1 = cfg.el;
|
|
var scrollLeft = ref$1.scrollLeft;
|
|
var scrollTop = ref$1.scrollTop;
|
|
|
|
if (cfg.absoluteOffset === void 0) {
|
|
anchorProps = getAnchorProps(cfg.anchorEl, cfg.cover === true ? [0, 0] : cfg.offset);
|
|
}
|
|
else {
|
|
var ref$2 = cfg.anchorEl.getBoundingClientRect();
|
|
var anchorTop = ref$2.top;
|
|
var anchorLeft = ref$2.left;
|
|
var top$1 = anchorTop + cfg.absoluteOffset.top,
|
|
left$1 = anchorLeft + cfg.absoluteOffset.left;
|
|
|
|
anchorProps = { top: top$1, left: left$1, width: 1, height: 1, right: left$1 + 1, center: top$1, middle: left$1, bottom: top$1 + 1 };
|
|
}
|
|
|
|
var elStyle = {
|
|
maxHeight: cfg.maxHeight,
|
|
maxWidth: cfg.maxWidth,
|
|
visibility: 'visible'
|
|
};
|
|
|
|
if (cfg.fit === true || cfg.cover === true) {
|
|
elStyle.minWidth = anchorProps.width + 'px';
|
|
if (cfg.cover === true) {
|
|
elStyle.minHeight = anchorProps.height + 'px';
|
|
}
|
|
}
|
|
|
|
Object.assign(cfg.el.style, elStyle);
|
|
|
|
var
|
|
targetProps = getTargetProps(cfg.el),
|
|
props = {
|
|
top: anchorProps[cfg.anchorOrigin.vertical] - targetProps[cfg.selfOrigin.vertical],
|
|
left: anchorProps[cfg.anchorOrigin.horizontal] - targetProps[cfg.selfOrigin.horizontal]
|
|
};
|
|
|
|
applyBoundaries(props, anchorProps, targetProps, cfg.anchorOrigin, cfg.selfOrigin);
|
|
|
|
elStyle = {
|
|
top: props.top + 'px',
|
|
left: props.left + 'px'
|
|
};
|
|
|
|
if (props.maxHeight !== void 0) {
|
|
elStyle.maxHeight = props.maxHeight + 'px';
|
|
|
|
if (anchorProps.height > props.maxHeight) {
|
|
elStyle.minHeight = elStyle.maxHeight;
|
|
}
|
|
}
|
|
if (props.maxWidth !== void 0) {
|
|
elStyle.maxWidth = props.maxWidth + 'px';
|
|
|
|
if (anchorProps.width > props.maxWidth) {
|
|
elStyle.minWidth = elStyle.maxWidth;
|
|
}
|
|
}
|
|
|
|
Object.assign(cfg.el.style, elStyle);
|
|
|
|
// restore scroll position
|
|
if (cfg.el.scrollTop !== scrollTop) {
|
|
cfg.el.scrollTop = scrollTop;
|
|
}
|
|
if (cfg.el.scrollLeft !== scrollLeft) {
|
|
cfg.el.scrollLeft = scrollLeft;
|
|
}
|
|
}
|
|
|
|
function applyBoundaries (props, anchorProps, targetProps, anchorOrigin, selfOrigin) {
|
|
var
|
|
currentHeight = targetProps.bottom,
|
|
currentWidth = targetProps.right,
|
|
margin = getScrollbarWidth(),
|
|
innerHeight = window.innerHeight - margin,
|
|
innerWidth = document.body.clientWidth;
|
|
|
|
if (props.top < 0 || props.top + currentHeight > innerHeight) {
|
|
if (selfOrigin.vertical === 'center') {
|
|
props.top = anchorProps[anchorOrigin.vertical] > innerHeight / 2
|
|
? Math.max(0, innerHeight - currentHeight)
|
|
: 0;
|
|
props.maxHeight = Math.min(currentHeight, innerHeight);
|
|
}
|
|
else if (anchorProps[anchorOrigin.vertical] > innerHeight / 2) {
|
|
var anchorY = Math.min(
|
|
innerHeight,
|
|
anchorOrigin.vertical === 'center'
|
|
? anchorProps.center
|
|
: (anchorOrigin.vertical === selfOrigin.vertical ? anchorProps.bottom : anchorProps.top)
|
|
);
|
|
props.maxHeight = Math.min(currentHeight, anchorY);
|
|
props.top = Math.max(0, anchorY - currentHeight);
|
|
}
|
|
else {
|
|
props.top = Math.max(0, anchorOrigin.vertical === 'center'
|
|
? anchorProps.center
|
|
: (anchorOrigin.vertical === selfOrigin.vertical ? anchorProps.top : anchorProps.bottom)
|
|
);
|
|
props.maxHeight = Math.min(currentHeight, innerHeight - props.top);
|
|
}
|
|
}
|
|
|
|
if (props.left < 0 || props.left + currentWidth > innerWidth) {
|
|
props.maxWidth = Math.min(currentWidth, innerWidth);
|
|
if (selfOrigin.horizontal === 'middle') {
|
|
props.left = anchorProps[anchorOrigin.horizontal] > innerWidth / 2
|
|
? Math.max(0, innerWidth - currentWidth)
|
|
: 0;
|
|
}
|
|
else if (anchorProps[anchorOrigin.horizontal] > innerWidth / 2) {
|
|
var anchorX = Math.min(
|
|
innerWidth,
|
|
anchorOrigin.horizontal === 'middle'
|
|
? anchorProps.middle
|
|
: (anchorOrigin.horizontal === selfOrigin.horizontal ? anchorProps.right : anchorProps.left)
|
|
);
|
|
props.maxWidth = Math.min(currentWidth, anchorX);
|
|
props.left = Math.max(0, anchorX - props.maxWidth);
|
|
}
|
|
else {
|
|
props.left = Math.max(0, anchorOrigin.horizontal === 'middle'
|
|
? anchorProps.middle
|
|
: (anchorOrigin.horizontal === selfOrigin.horizontal ? anchorProps.left : anchorProps.right)
|
|
);
|
|
props.maxWidth = Math.min(currentWidth, innerWidth - props.left);
|
|
}
|
|
}
|
|
}
|
|
|
|
var QMenu = Vue.extend({
|
|
name: 'QMenu',
|
|
|
|
mixins: [
|
|
AttrsMixin,
|
|
DarkMixin,
|
|
AnchorMixin,
|
|
ModelToggleMixin,
|
|
Portal,
|
|
TransitionMixin
|
|
],
|
|
|
|
directives: {
|
|
ClickOutside: ClickOutside
|
|
},
|
|
|
|
props: {
|
|
persistent: Boolean,
|
|
autoClose: Boolean,
|
|
separateClosePopup: Boolean,
|
|
|
|
noRouteDismiss: Boolean,
|
|
noRefocus: Boolean,
|
|
noFocus: Boolean,
|
|
|
|
fit: Boolean,
|
|
cover: Boolean,
|
|
|
|
square: Boolean,
|
|
|
|
anchor: {
|
|
type: String,
|
|
validator: validatePosition
|
|
},
|
|
self: {
|
|
type: String,
|
|
validator: validatePosition
|
|
},
|
|
offset: {
|
|
type: Array,
|
|
validator: validateOffset
|
|
},
|
|
|
|
scrollTarget: {
|
|
default: void 0
|
|
},
|
|
|
|
touchPosition: Boolean,
|
|
|
|
maxHeight: {
|
|
type: String,
|
|
default: null
|
|
},
|
|
maxWidth: {
|
|
type: String,
|
|
default: null
|
|
}
|
|
},
|
|
|
|
computed: {
|
|
horizSide: function horizSide () {
|
|
return this.$q.lang.rtl === true ? 'right' : 'left'
|
|
},
|
|
|
|
anchorOrigin: function anchorOrigin () {
|
|
return parsePosition(
|
|
this.anchor || (
|
|
this.cover === true ? "center middle" : ("bottom " + (this.horizSide))
|
|
)
|
|
)
|
|
},
|
|
|
|
selfOrigin: function selfOrigin () {
|
|
return this.cover === true
|
|
? this.anchorOrigin
|
|
: parsePosition(this.self || ("top " + (this.horizSide)))
|
|
},
|
|
|
|
menuClass: function menuClass () {
|
|
return (this.square === true ? ' q-menu--square' : '') +
|
|
(this.isDark === true ? ' q-menu--dark q-dark' : '')
|
|
},
|
|
|
|
hideOnRouteChange: function hideOnRouteChange () {
|
|
return this.persistent !== true &&
|
|
this.noRouteDismiss !== true
|
|
},
|
|
|
|
onEvents: function onEvents () {
|
|
var on = Object.assign({}, this.qListeners,
|
|
// stop propagating these events from children
|
|
{input: stop,
|
|
'popup-show': stop,
|
|
'popup-hide': stop});
|
|
|
|
if (this.autoClose === true) {
|
|
on.click = this.__onAutoClose;
|
|
}
|
|
|
|
return on
|
|
},
|
|
|
|
attrs: function attrs () {
|
|
return Object.assign({}, {tabindex: -1},
|
|
this.qAttrs)
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
focus: function focus () {
|
|
var node = this.__portal !== void 0 && this.__portal.$refs !== void 0
|
|
? this.__portal.$refs.inner
|
|
: void 0;
|
|
|
|
if (node !== void 0 && node.contains(document.activeElement) !== true) {
|
|
node = node.querySelector('[autofocus], [data-autofocus]') || node;
|
|
node.focus();
|
|
}
|
|
},
|
|
|
|
__show: function __show (evt) {
|
|
var this$1 = this;
|
|
|
|
// IE can have null document.activeElement
|
|
this.__refocusTarget = this.noRefocus === false && document.activeElement !== null
|
|
? document.activeElement
|
|
: void 0;
|
|
|
|
EscapeKey.register(this, function () {
|
|
if (this$1.persistent !== true) {
|
|
this$1.$emit('escape-key');
|
|
this$1.hide();
|
|
}
|
|
});
|
|
|
|
this.__showPortal();
|
|
this.__configureScrollTarget();
|
|
|
|
this.absoluteOffset = void 0;
|
|
|
|
if (evt !== void 0 && (this.touchPosition || this.contextMenu)) {
|
|
var pos = position(evt);
|
|
|
|
if (pos.left !== void 0) {
|
|
var ref = this.anchorEl.getBoundingClientRect();
|
|
var top = ref.top;
|
|
var left = ref.left;
|
|
this.absoluteOffset = { left: pos.left - left, top: pos.top - top };
|
|
}
|
|
}
|
|
|
|
if (this.unwatch === void 0) {
|
|
this.unwatch = this.$watch(
|
|
function () { return this$1.$q.screen.width + '|' + this$1.$q.screen.height + '|' + this$1.self + '|' + this$1.anchor; },
|
|
this.updatePosition
|
|
);
|
|
}
|
|
|
|
this.$el.dispatchEvent(create('popup-show', { bubbles: true }));
|
|
|
|
// IE can have null document.activeElement
|
|
if (this.noFocus !== true && document.activeElement !== null) {
|
|
document.activeElement.blur();
|
|
}
|
|
|
|
this.__nextTick(function () {
|
|
this$1.updatePosition();
|
|
this$1.noFocus !== true && this$1.focus();
|
|
});
|
|
|
|
this.__setTimeout(function () {
|
|
// required in order to avoid the "double-tap needed" issue
|
|
if (this$1.$q.platform.is.ios === true) {
|
|
// if auto-close, then this click should
|
|
// not close the menu
|
|
this$1.__avoidAutoClose = this$1.autoClose;
|
|
this$1.__portal.$el.click();
|
|
}
|
|
|
|
this$1.updatePosition();
|
|
this$1.$emit('show', evt);
|
|
}, 300);
|
|
},
|
|
|
|
__hide: function __hide (evt) {
|
|
var this$1 = this;
|
|
|
|
this.__anchorCleanup(true);
|
|
|
|
// check null for IE
|
|
if (
|
|
this.__refocusTarget !== void 0 &&
|
|
this.__refocusTarget !== null &&
|
|
(
|
|
// menu was hidden from code or ESC plugin
|
|
evt === void 0 ||
|
|
// menu was not closed from a mouse or touch clickOutside
|
|
evt.qClickOutside !== true
|
|
)
|
|
) {
|
|
this.__refocusTarget.focus();
|
|
}
|
|
|
|
this.$el.dispatchEvent(create('popup-hide', { bubbles: true }));
|
|
|
|
this.__setTimeout(function () {
|
|
this$1.__hidePortal();
|
|
this$1.$emit('hide', evt);
|
|
}, 300);
|
|
},
|
|
|
|
__anchorCleanup: function __anchorCleanup (hiding) {
|
|
this.absoluteOffset = void 0;
|
|
|
|
if (this.unwatch !== void 0) {
|
|
this.unwatch();
|
|
this.unwatch = void 0;
|
|
}
|
|
|
|
if (hiding === true || this.showing === true) {
|
|
EscapeKey.pop(this);
|
|
this.__unconfigureScrollTarget();
|
|
}
|
|
},
|
|
|
|
__unconfigureScrollTarget: function __unconfigureScrollTarget () {
|
|
if (this.__scrollTarget !== void 0) {
|
|
this.__changeScrollEvent(this.__scrollTarget);
|
|
this.__scrollTarget = void 0;
|
|
}
|
|
},
|
|
|
|
__configureScrollTarget: function __configureScrollTarget () {
|
|
if (this.anchorEl !== void 0 || this.scrollTarget !== void 0) {
|
|
this.__scrollTarget = getScrollTarget(this.anchorEl, this.scrollTarget);
|
|
this.__changeScrollEvent(this.__scrollTarget, this.updatePosition);
|
|
}
|
|
},
|
|
|
|
__onAutoClose: function __onAutoClose (e) {
|
|
// if auto-close, then the ios double-tap fix which
|
|
// issues a click should not close the menu
|
|
if (this.__avoidAutoClose !== true) {
|
|
closePortalMenus(this, e);
|
|
this.qListeners.click !== void 0 && this.$emit('click', e);
|
|
}
|
|
else {
|
|
this.__avoidAutoClose = false;
|
|
}
|
|
},
|
|
|
|
updatePosition: function updatePosition () {
|
|
if (this.anchorEl === void 0 || this.__portal === void 0) {
|
|
return
|
|
}
|
|
|
|
var el = this.__portal.$el;
|
|
|
|
if (el.nodeType === 8) { // IE replaces the comment with delay
|
|
setTimeout(this.updatePosition, 25);
|
|
return
|
|
}
|
|
|
|
setPosition({
|
|
el: el,
|
|
offset: this.offset,
|
|
anchorEl: this.anchorEl,
|
|
anchorOrigin: this.anchorOrigin,
|
|
selfOrigin: this.selfOrigin,
|
|
absoluteOffset: this.absoluteOffset,
|
|
fit: this.fit,
|
|
cover: this.cover,
|
|
maxHeight: this.maxHeight,
|
|
maxWidth: this.maxWidth
|
|
});
|
|
},
|
|
|
|
__onClickOutside: function __onClickOutside (e) {
|
|
if (this.persistent !== true && this.showing === true) {
|
|
var targetClassList = e.target.classList;
|
|
|
|
this.hide(e);
|
|
if (
|
|
// always prevent touch event
|
|
e.type === 'touchstart' ||
|
|
// prevent click if it's on a dialog backdrop
|
|
targetClassList.contains('q-dialog__backdrop')
|
|
) {
|
|
stopAndPrevent(e);
|
|
}
|
|
return true
|
|
}
|
|
},
|
|
|
|
__renderPortal: function __renderPortal (h) {
|
|
return h('transition', {
|
|
props: { name: this.transition }
|
|
}, [
|
|
this.showing === true ? h('div', {
|
|
ref: 'inner',
|
|
staticClass: 'q-menu q-position-engine scroll' + this.menuClass,
|
|
class: this.contentClass,
|
|
style: this.contentStyle,
|
|
attrs: this.attrs,
|
|
on: this.onEvents,
|
|
directives: [{
|
|
name: 'click-outside',
|
|
value: this.__onClickOutside,
|
|
arg: this.anchorEl
|
|
}]
|
|
}, slot(this, 'default')) : null
|
|
])
|
|
}
|
|
},
|
|
|
|
mounted: function mounted () {
|
|
this.__processModelChange(this.value);
|
|
},
|
|
|
|
beforeDestroy: function beforeDestroy () {
|
|
// When the menu is destroyed while open we can only emit the event on anchorEl
|
|
if (this.showing === true && this.anchorEl !== void 0) {
|
|
this.anchorEl.dispatchEvent(
|
|
create('popup-hide', { bubbles: true })
|
|
);
|
|
}
|
|
}
|
|
});
|
|
|
|
var QBtnDropdown = Vue.extend({
|
|
name: 'QBtnDropdown',
|
|
|
|
mixins: [ BtnMixin ],
|
|
|
|
props: {
|
|
value: Boolean,
|
|
split: Boolean,
|
|
dropdownIcon: String,
|
|
|
|
contentClass: [ Array, String, Object ],
|
|
contentStyle: [ Array, String, Object ],
|
|
|
|
cover: Boolean,
|
|
persistent: Boolean,
|
|
noRouteDismiss: Boolean,
|
|
autoClose: Boolean,
|
|
|
|
menuAnchor: {
|
|
type: String,
|
|
default: 'bottom right'
|
|
},
|
|
menuSelf: {
|
|
type: String,
|
|
default: 'top right'
|
|
},
|
|
menuOffset: Array,
|
|
|
|
disableMainBtn: Boolean,
|
|
disableDropdown: Boolean,
|
|
|
|
noIconAnimation: Boolean
|
|
},
|
|
|
|
data: function data () {
|
|
return {
|
|
showing: this.value
|
|
}
|
|
},
|
|
|
|
watch: {
|
|
value: function value (val) {
|
|
this.$refs.menu !== void 0 && this.$refs.menu[val ? 'show' : 'hide']();
|
|
}
|
|
},
|
|
|
|
render: function render (h) {
|
|
var this$1 = this;
|
|
|
|
var label = slot(this, 'label', []);
|
|
var attrs = {
|
|
'aria-expanded': this.showing === true ? 'true' : 'false',
|
|
'aria-haspopup': 'true'
|
|
};
|
|
|
|
if (
|
|
this.disable === true ||
|
|
(
|
|
(this.split === false && this.disableMainBtn === true) ||
|
|
this.disableDropdown === true
|
|
)
|
|
) {
|
|
attrs['aria-disabled'] = 'true';
|
|
}
|
|
|
|
var Arrow = [
|
|
h(QIcon, {
|
|
props: { name: this.dropdownIcon || this.$q.iconSet.arrow.dropdown },
|
|
class: 'q-btn-dropdown__arrow' +
|
|
(this.showing === true && this.noIconAnimation === false ? ' rotate-180' : '') +
|
|
(this.split === false ? ' q-btn-dropdown__arrow-container' : '')
|
|
})
|
|
];
|
|
|
|
this.disableDropdown !== true && Arrow.push(
|
|
h(QMenu, {
|
|
ref: 'menu',
|
|
props: {
|
|
cover: this.cover,
|
|
fit: true,
|
|
persistent: this.persistent,
|
|
noRouteDismiss: this.noRouteDismiss,
|
|
autoClose: this.autoClose,
|
|
anchor: this.menuAnchor,
|
|
self: this.menuSelf,
|
|
offset: this.menuOffset,
|
|
contentClass: this.contentClass,
|
|
contentStyle: this.contentStyle,
|
|
separateClosePopup: true
|
|
},
|
|
on: cache(this, 'menu', {
|
|
'before-show': function (e) {
|
|
this$1.showing = true;
|
|
this$1.$emit('before-show', e);
|
|
},
|
|
show: function (e) {
|
|
this$1.$emit('show', e);
|
|
this$1.$emit('input', true);
|
|
},
|
|
'before-hide': function (e) {
|
|
this$1.showing = false;
|
|
this$1.$emit('before-hide', e);
|
|
},
|
|
hide: function (e) {
|
|
this$1.$emit('hide', e);
|
|
this$1.$emit('input', false);
|
|
}
|
|
})
|
|
}, slot(this, 'default'))
|
|
);
|
|
|
|
if (this.split === false) {
|
|
return h(QBtn, {
|
|
class: 'q-btn-dropdown q-btn-dropdown--simple',
|
|
props: Object.assign({}, this.$props,
|
|
{disable: this.disable === true || this.disableMainBtn === true,
|
|
noWrap: true,
|
|
round: false}),
|
|
attrs: attrs,
|
|
on: cache(this, 'nonSpl', {
|
|
click: function (e) {
|
|
this$1.$emit('click', e);
|
|
}
|
|
})
|
|
}, label.concat(Arrow))
|
|
}
|
|
|
|
var Btn = h(QBtn, {
|
|
class: 'q-btn-dropdown--current',
|
|
props: Object.assign({}, this.$props,
|
|
{disable: this.disable === true || this.disableMainBtn === true,
|
|
noWrap: true,
|
|
iconRight: this.iconRight,
|
|
round: false}),
|
|
on: cache(this, 'spl', {
|
|
click: function (e) {
|
|
this$1.hide();
|
|
this$1.$emit('click', e);
|
|
}
|
|
})
|
|
}, label);
|
|
|
|
return h(QBtnGroup, {
|
|
props: {
|
|
outline: this.outline,
|
|
flat: this.flat,
|
|
rounded: this.rounded,
|
|
push: this.push,
|
|
unelevated: this.unelevated,
|
|
glossy: this.glossy,
|
|
stretch: this.stretch
|
|
},
|
|
staticClass: 'q-btn-dropdown q-btn-dropdown--split no-wrap q-btn-item'
|
|
}, [
|
|
Btn,
|
|
|
|
h(QBtn, {
|
|
staticClass: 'q-btn-dropdown__arrow-container',
|
|
attrs: attrs,
|
|
props: {
|
|
disable: this.disable === true || this.disableDropdown === true,
|
|
outline: this.outline,
|
|
flat: this.flat,
|
|
rounded: this.rounded,
|
|
push: this.push,
|
|
size: this.size,
|
|
color: this.color,
|
|
textColor: this.textColor,
|
|
dense: this.dense,
|
|
ripple: this.ripple
|
|
}
|
|
}, Arrow)
|
|
])
|
|
},
|
|
|
|
methods: {
|
|
toggle: function toggle (evt) {
|
|
this.$refs.menu && this.$refs.menu.toggle(evt);
|
|
},
|
|
|
|
show: function show (evt) {
|
|
this.$refs.menu && this.$refs.menu.show(evt);
|
|
},
|
|
|
|
hide: function hide (evt) {
|
|
this.$refs.menu && this.$refs.menu.hide(evt);
|
|
}
|
|
},
|
|
|
|
mounted: function mounted () {
|
|
this.value === true && this.show();
|
|
}
|
|
});
|
|
|
|
var FormMixin = {
|
|
props: {
|
|
name: String
|
|
},
|
|
|
|
computed: {
|
|
formAttrs: function formAttrs () {
|
|
return {
|
|
type: 'hidden',
|
|
name: this.name,
|
|
value: this.value
|
|
}
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
__injectFormInput: function __injectFormInput (child, action, className) {
|
|
child[action](
|
|
this.$createElement('input', {
|
|
staticClass: 'hidden',
|
|
class: className,
|
|
attrs: this.formAttrs,
|
|
domProps: this.formDomProps
|
|
})
|
|
);
|
|
}
|
|
}
|
|
};
|
|
|
|
var FormFieldMixin = {
|
|
props: {
|
|
name: String
|
|
},
|
|
|
|
computed: {
|
|
nameProp: function nameProp () {
|
|
return this.name || this.for
|
|
}
|
|
}
|
|
};
|
|
|
|
var QBtnToggle = Vue.extend({
|
|
name: 'QBtnToggle',
|
|
|
|
mixins: [ ListenersMixin, RippleMixin, FormMixin ],
|
|
|
|
props: {
|
|
value: {
|
|
required: true
|
|
},
|
|
|
|
options: {
|
|
type: Array,
|
|
required: true,
|
|
validator: function (v) { return v.every(
|
|
function (opt) { return ('label' in opt || 'icon' in opt || 'slot' in opt) && 'value' in opt; }
|
|
); }
|
|
},
|
|
|
|
// To avoid seeing the active raise shadow through the transparent button, give it a color (even white).
|
|
color: String,
|
|
textColor: String,
|
|
toggleColor: {
|
|
type: String,
|
|
default: 'primary'
|
|
},
|
|
toggleTextColor: String,
|
|
|
|
outline: Boolean,
|
|
flat: Boolean,
|
|
unelevated: Boolean,
|
|
rounded: Boolean,
|
|
push: Boolean,
|
|
glossy: Boolean,
|
|
|
|
size: String,
|
|
padding: String,
|
|
|
|
noCaps: Boolean,
|
|
noWrap: Boolean,
|
|
dense: Boolean,
|
|
readonly: Boolean,
|
|
disable: Boolean,
|
|
|
|
stack: Boolean,
|
|
stretch: Boolean,
|
|
|
|
spread: Boolean,
|
|
|
|
clearable: Boolean
|
|
},
|
|
|
|
computed: {
|
|
hasActiveValue: function hasActiveValue () {
|
|
var this$1 = this;
|
|
|
|
return this.options.find(function (opt) { return opt.value === this$1.value; }) !== void 0
|
|
},
|
|
|
|
formAttrs: function formAttrs () {
|
|
return {
|
|
type: 'hidden',
|
|
name: this.name,
|
|
value: this.value
|
|
}
|
|
},
|
|
|
|
btnOptions: function btnOptions () {
|
|
var this$1 = this;
|
|
|
|
var mergeOption = function (opt, key) { return opt[key] === void 0 ? this$1[key] : opt[key]; };
|
|
|
|
return this.options.map(function (opt, i) { return ({
|
|
slot: opt.slot,
|
|
|
|
options: {
|
|
key: i,
|
|
class: opt.class,
|
|
style: opt.style,
|
|
on: Object.assign({}, this$1.qListeners,
|
|
{click: function (e) { return this$1.__set(opt.value, opt, e); }}),
|
|
attrs: opt.attrs,
|
|
props: Object.assign({}, opt,
|
|
{slot: void 0,
|
|
class: void 0,
|
|
style: void 0,
|
|
value: void 0,
|
|
attrs: void 0,
|
|
|
|
outline: this$1.outline,
|
|
flat: this$1.flat,
|
|
rounded: this$1.rounded,
|
|
push: this$1.push,
|
|
unelevated: this$1.unelevated,
|
|
dense: this$1.dense,
|
|
|
|
disable: this$1.disable === true || opt.disable === true,
|
|
|
|
// Options that come from the button specific options first, then from general props
|
|
color: opt.value === this$1.value ? mergeOption(opt, 'toggleColor') : mergeOption(opt, 'color'),
|
|
textColor: opt.value === this$1.value ? mergeOption(opt, 'toggleTextColor') : mergeOption(opt, 'textColor'),
|
|
noCaps: mergeOption(opt, 'noCaps') === true,
|
|
noWrap: mergeOption(opt, 'noWrap') === true,
|
|
|
|
size: mergeOption(opt, 'size'),
|
|
padding: mergeOption(opt, 'padding'),
|
|
ripple: mergeOption(opt, 'ripple'),
|
|
stack: mergeOption(opt, 'stack') === true,
|
|
stretch: mergeOption(opt, 'stretch') === true})
|
|
}
|
|
}); })
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
__set: function __set (value, opt, e) {
|
|
if (this.readonly !== true) {
|
|
if (this.value === value) {
|
|
if (this.clearable === true) {
|
|
this.$emit('input', null, null);
|
|
this.$emit('clear');
|
|
}
|
|
}
|
|
else {
|
|
this.$emit('input', value, opt);
|
|
}
|
|
|
|
this.$emit('click', e);
|
|
}
|
|
}
|
|
},
|
|
|
|
render: function render (h) {
|
|
var this$1 = this;
|
|
|
|
var child = this.btnOptions.map(function (opt) {
|
|
return h(QBtn, opt.options, opt.slot !== void 0 ? slot(this$1, opt.slot) : void 0)
|
|
});
|
|
|
|
if (this.name !== void 0 && this.disable !== true && this.hasActiveValue === true) {
|
|
this.__injectFormInput(child, 'push');
|
|
}
|
|
|
|
return h(QBtnGroup, {
|
|
staticClass: 'q-btn-toggle',
|
|
props: {
|
|
outline: this.outline,
|
|
flat: this.flat,
|
|
rounded: this.rounded,
|
|
push: this.push,
|
|
stretch: this.stretch,
|
|
unelevated: this.unelevated,
|
|
glossy: this.glossy,
|
|
spread: this.spread
|
|
}
|
|
}, mergeSlot(child, this, 'default'))
|
|
}
|
|
});
|
|
|
|
var QCard = Vue.extend({
|
|
name: 'QCard',
|
|
|
|
mixins: [ ListenersMixin, DarkMixin, TagMixin ],
|
|
|
|
props: {
|
|
square: Boolean,
|
|
flat: Boolean,
|
|
bordered: Boolean
|
|
},
|
|
|
|
computed: {
|
|
classes: function classes () {
|
|
return 'q-card' +
|
|
(this.isDark === true ? ' q-card--dark q-dark' : '') +
|
|
(this.bordered === true ? ' q-card--bordered' : '') +
|
|
(this.square === true ? ' q-card--square no-border-radius' : '') +
|
|
(this.flat === true ? ' q-card--flat no-shadow' : '')
|
|
}
|
|
},
|
|
|
|
render: function render (h) {
|
|
return h(this.tag, {
|
|
class: this.classes,
|
|
on: Object.assign({}, this.qListeners)
|
|
}, slot(this, 'default'))
|
|
}
|
|
});
|
|
|
|
var QCardSection = Vue.extend({
|
|
name: 'QCardSection',
|
|
|
|
mixins: [ ListenersMixin, TagMixin ],
|
|
|
|
props: {
|
|
horizontal: Boolean
|
|
},
|
|
|
|
computed: {
|
|
classes: function classes () {
|
|
return 'q-card__section ' +
|
|
"q-card__section--" + (this.horizontal === true ? 'horiz row no-wrap' : 'vert')
|
|
}
|
|
},
|
|
|
|
render: function render (h) {
|
|
return h(this.tag, {
|
|
class: this.classes,
|
|
on: Object.assign({}, this.qListeners)
|
|
}, slot(this, 'default'))
|
|
}
|
|
});
|
|
|
|
var QCardActions = Vue.extend({
|
|
name: 'QCardActions',
|
|
|
|
mixins: [ ListenersMixin, AlignMixin ],
|
|
|
|
props: {
|
|
vertical: Boolean
|
|
},
|
|
|
|
computed: {
|
|
classes: function classes () {
|
|
return ("q-card__actions--" + (this.vertical === true ? 'vert column' : 'horiz row') + " " + (this.alignClass))
|
|
}
|
|
},
|
|
|
|
render: function render (h) {
|
|
return h('div', {
|
|
staticClass: 'q-card__actions',
|
|
class: this.classes,
|
|
on: Object.assign({}, this.qListeners)
|
|
}, slot(this, 'default'))
|
|
}
|
|
});
|
|
|
|
function parseArg (arg) {
|
|
// delta (min velocity -- dist / time)
|
|
// mobile min distance on first move
|
|
// desktop min distance until deciding if it's a swipe or not
|
|
var data = [0.06, 6, 50];
|
|
|
|
if (typeof arg === 'string' && arg.length) {
|
|
arg.split(':').forEach(function (val, index) {
|
|
var v = parseFloat(val);
|
|
v && (data[index] = v);
|
|
});
|
|
}
|
|
|
|
return data
|
|
}
|
|
|
|
function destroy$1 (el) {
|
|
var ctx = el.__qtouchswipe;
|
|
|
|
if (ctx !== void 0) {
|
|
cleanEvt(ctx, 'main');
|
|
cleanEvt(ctx, 'temp');
|
|
|
|
client.is.firefox === true && preventDraggable(el, false);
|
|
ctx.styleCleanup !== void 0 && ctx.styleCleanup();
|
|
|
|
delete el.__qtouchswipe;
|
|
}
|
|
}
|
|
|
|
var TouchSwipe = {
|
|
name: 'touch-swipe',
|
|
|
|
bind: function bind (el, ref) {
|
|
var value = ref.value;
|
|
var arg = ref.arg;
|
|
var modifiers = ref.modifiers;
|
|
|
|
if (el.__qtouchswipe !== void 0) {
|
|
destroy$1(el);
|
|
el.__qtouchswipe_destroyed = true;
|
|
}
|
|
|
|
// early return, we don't need to do anything
|
|
if (modifiers.mouse !== true && client.has.touch !== true) {
|
|
return
|
|
}
|
|
|
|
var mouseCapture = modifiers.mouseCapture === true ? 'Capture' : '';
|
|
|
|
var ctx = {
|
|
handler: value,
|
|
sensitivity: parseArg(arg),
|
|
|
|
modifiers: modifiers,
|
|
direction: getModifierDirections(modifiers),
|
|
|
|
noop: noop,
|
|
|
|
mouseStart: function mouseStart (evt) {
|
|
if (shouldStart(evt, ctx) && leftClick(evt)) {
|
|
addEvt(ctx, 'temp', [
|
|
[ document, 'mousemove', 'move', ("notPassive" + mouseCapture) ],
|
|
[ document, 'mouseup', 'end', 'notPassiveCapture' ]
|
|
]);
|
|
ctx.start(evt, true);
|
|
}
|
|
},
|
|
|
|
touchStart: function touchStart (evt) {
|
|
if (shouldStart(evt, ctx)) {
|
|
var target = getTouchTarget(evt.target);
|
|
addEvt(ctx, 'temp', [
|
|
[ target, 'touchmove', 'move', 'notPassiveCapture' ],
|
|
[ target, 'touchcancel', 'end', 'notPassiveCapture' ],
|
|
[ target, 'touchend', 'end', 'notPassiveCapture' ]
|
|
]);
|
|
ctx.start(evt);
|
|
}
|
|
},
|
|
|
|
start: function start (evt, mouseEvent) {
|
|
client.is.firefox === true && preventDraggable(el, true);
|
|
|
|
var pos = position(evt);
|
|
|
|
ctx.event = {
|
|
x: pos.left,
|
|
y: pos.top,
|
|
time: Date.now(),
|
|
mouse: mouseEvent === true,
|
|
dir: false
|
|
};
|
|
},
|
|
|
|
move: function move (evt) {
|
|
if (ctx.event === void 0) {
|
|
return
|
|
}
|
|
|
|
if (ctx.event.dir !== false) {
|
|
stopAndPrevent(evt);
|
|
return
|
|
}
|
|
|
|
var time = Date.now() - ctx.event.time;
|
|
|
|
if (time === 0) {
|
|
return
|
|
}
|
|
|
|
var
|
|
pos = position(evt),
|
|
distX = pos.left - ctx.event.x,
|
|
absX = Math.abs(distX),
|
|
distY = pos.top - ctx.event.y,
|
|
absY = Math.abs(distY);
|
|
|
|
if (ctx.event.mouse !== true) {
|
|
if (absX < ctx.sensitivity[1] && absY < ctx.sensitivity[1]) {
|
|
ctx.end(evt);
|
|
return
|
|
}
|
|
}
|
|
else if (absX < ctx.sensitivity[2] && absY < ctx.sensitivity[2]) {
|
|
return
|
|
}
|
|
|
|
var
|
|
velX = absX / time,
|
|
velY = absY / time;
|
|
|
|
if (
|
|
ctx.direction.vertical === true &&
|
|
absX < absY &&
|
|
absX < 100 &&
|
|
velY > ctx.sensitivity[0]
|
|
) {
|
|
ctx.event.dir = distY < 0 ? 'up' : 'down';
|
|
}
|
|
|
|
if (
|
|
ctx.direction.horizontal === true &&
|
|
absX > absY &&
|
|
absY < 100 &&
|
|
velX > ctx.sensitivity[0]
|
|
) {
|
|
ctx.event.dir = distX < 0 ? 'left' : 'right';
|
|
}
|
|
|
|
if (
|
|
ctx.direction.up === true &&
|
|
absX < absY &&
|
|
distY < 0 &&
|
|
absX < 100 &&
|
|
velY > ctx.sensitivity[0]
|
|
) {
|
|
ctx.event.dir = 'up';
|
|
}
|
|
|
|
if (
|
|
ctx.direction.down === true &&
|
|
absX < absY &&
|
|
distY > 0 &&
|
|
absX < 100 &&
|
|
velY > ctx.sensitivity[0]
|
|
) {
|
|
ctx.event.dir = 'down';
|
|
}
|
|
|
|
if (
|
|
ctx.direction.left === true &&
|
|
absX > absY &&
|
|
distX < 0 &&
|
|
absY < 100 &&
|
|
velX > ctx.sensitivity[0]
|
|
) {
|
|
ctx.event.dir = 'left';
|
|
}
|
|
|
|
if (
|
|
ctx.direction.right === true &&
|
|
absX > absY &&
|
|
distX > 0 &&
|
|
absY < 100 &&
|
|
velX > ctx.sensitivity[0]
|
|
) {
|
|
ctx.event.dir = 'right';
|
|
}
|
|
|
|
if (ctx.event.dir !== false) {
|
|
stopAndPrevent(evt);
|
|
|
|
if (ctx.event.mouse === true) {
|
|
document.body.classList.add('no-pointer-events--children');
|
|
document.body.classList.add('non-selectable');
|
|
clearSelection();
|
|
|
|
ctx.styleCleanup = function (withDelay) {
|
|
ctx.styleCleanup = void 0;
|
|
|
|
document.body.classList.remove('non-selectable');
|
|
|
|
var remove = function () {
|
|
document.body.classList.remove('no-pointer-events--children');
|
|
};
|
|
|
|
if (withDelay === true) { setTimeout(remove, 50); }
|
|
else { remove(); }
|
|
};
|
|
}
|
|
|
|
ctx.handler({
|
|
evt: evt,
|
|
touch: ctx.event.mouse !== true,
|
|
mouse: ctx.event.mouse,
|
|
direction: ctx.event.dir,
|
|
duration: time,
|
|
distance: {
|
|
x: absX,
|
|
y: absY
|
|
}
|
|
});
|
|
}
|
|
else {
|
|
ctx.end(evt);
|
|
}
|
|
},
|
|
|
|
end: function end (evt) {
|
|
if (ctx.event === void 0) {
|
|
return
|
|
}
|
|
|
|
cleanEvt(ctx, 'temp');
|
|
client.is.firefox === true && preventDraggable(el, false);
|
|
ctx.styleCleanup !== void 0 && ctx.styleCleanup(true);
|
|
evt !== void 0 && ctx.event.dir !== false && stopAndPrevent(evt);
|
|
|
|
ctx.event = void 0;
|
|
}
|
|
};
|
|
|
|
el.__qtouchswipe = ctx;
|
|
|
|
modifiers.mouse === true && addEvt(ctx, 'main', [
|
|
[ el, 'mousedown', 'mouseStart', ("passive" + mouseCapture) ]
|
|
]);
|
|
|
|
client.has.touch === true && addEvt(ctx, 'main', [
|
|
[ el, 'touchstart', 'touchStart', ("passive" + (modifiers.capture === true ? 'Capture' : '')) ],
|
|
[ el, 'touchmove', 'noop', "notPassiveCapture" ]
|
|
]);
|
|
},
|
|
|
|
update: function update (el, ref) {
|
|
var oldValue = ref.oldValue;
|
|
var value = ref.value;
|
|
|
|
var ctx = el.__qtouchswipe;
|
|
if (ctx !== void 0 && oldValue !== value) {
|
|
typeof value !== 'function' && ctx.end();
|
|
ctx.handler = value;
|
|
}
|
|
},
|
|
|
|
unbind: function unbind (el) {
|
|
if (el.__qtouchswipe_destroyed === void 0) {
|
|
destroy$1(el);
|
|
}
|
|
else {
|
|
delete el.__qtouchswipe_destroyed;
|
|
}
|
|
}
|
|
};
|
|
|
|
var PanelWrapper = Vue.extend({
|
|
name: 'QTabPanelWrapper',
|
|
|
|
render: function render (h) {
|
|
return h('div', {
|
|
staticClass: 'q-panel scroll',
|
|
attrs: { role: 'tabpanel' },
|
|
// stop propagation of content emitted @input
|
|
// which would tamper with Panel's model
|
|
on: cache(this, 'stop', { input: stop })
|
|
}, slot(this, 'default'))
|
|
}
|
|
});
|
|
|
|
var PanelParentMixin = {
|
|
mixins: [ ListenersMixin ],
|
|
|
|
directives: {
|
|
TouchSwipe: TouchSwipe
|
|
},
|
|
|
|
props: {
|
|
value: {
|
|
required: true
|
|
},
|
|
|
|
animated: Boolean,
|
|
infinite: Boolean,
|
|
swipeable: Boolean,
|
|
vertical: Boolean,
|
|
|
|
transitionPrev: String,
|
|
transitionNext: String,
|
|
|
|
keepAlive: Boolean
|
|
},
|
|
|
|
data: function data () {
|
|
return {
|
|
panelIndex: null,
|
|
panelTransition: null
|
|
}
|
|
},
|
|
|
|
computed: {
|
|
panelDirectives: function panelDirectives () {
|
|
if (this.swipeable === true) {
|
|
return [{
|
|
name: 'touch-swipe',
|
|
value: this.__swipe,
|
|
modifiers: {
|
|
horizontal: this.vertical !== true,
|
|
vertical: this.vertical,
|
|
mouse: true
|
|
}
|
|
}]
|
|
}
|
|
},
|
|
|
|
contentKey: function contentKey () {
|
|
return typeof this.value === 'string' || typeof this.value === 'number'
|
|
? this.value
|
|
: String(this.value)
|
|
},
|
|
|
|
transitionPrevComputed: function transitionPrevComputed () {
|
|
return this.transitionPrev || ("slide-" + (this.vertical === true ? 'down' : 'right'))
|
|
},
|
|
|
|
transitionNextComputed: function transitionNextComputed () {
|
|
return this.transitionNext || ("slide-" + (this.vertical === true ? 'up' : 'left'))
|
|
}
|
|
},
|
|
|
|
watch: {
|
|
value: function value (newVal, oldVal) {
|
|
var this$1 = this;
|
|
|
|
var index = this.__isValidPanelName(newVal) === true
|
|
? this.__getPanelIndex(newVal)
|
|
: -1;
|
|
|
|
if (this.__forcedPanelTransition !== true) {
|
|
this.__updatePanelTransition(
|
|
index === -1 ? 0 : (index < this.__getPanelIndex(oldVal) ? -1 : 1)
|
|
);
|
|
}
|
|
|
|
if (this.panelIndex !== index) {
|
|
this.panelIndex = index;
|
|
this.$emit('before-transition', newVal, oldVal);
|
|
this.$nextTick(function () {
|
|
this$1.$emit('transition', newVal, oldVal);
|
|
});
|
|
}
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
next: function next () {
|
|
this.__go(1);
|
|
},
|
|
|
|
previous: function previous () {
|
|
this.__go(-1);
|
|
},
|
|
|
|
goTo: function goTo (name) {
|
|
this.$emit('input', name);
|
|
},
|
|
|
|
__isValidPanelName: function __isValidPanelName (name) {
|
|
return name !== void 0 && name !== null && name !== ''
|
|
},
|
|
|
|
__getPanelIndex: function __getPanelIndex (name) {
|
|
return this.panels.findIndex(function (panel) {
|
|
var opt = panel.componentOptions;
|
|
return opt &&
|
|
opt.propsData.name === name &&
|
|
opt.propsData.disable !== '' &&
|
|
opt.propsData.disable !== true
|
|
})
|
|
},
|
|
|
|
__getAllPanels: function __getAllPanels () {
|
|
var this$1 = this;
|
|
|
|
return this.panels.filter(
|
|
function (panel) { return panel.componentOptions !== void 0 &&
|
|
this$1.__isValidPanelName(panel.componentOptions.propsData.name); }
|
|
)
|
|
},
|
|
|
|
__getAvailablePanels: function __getAvailablePanels () {
|
|
return this.panels.filter(function (panel) {
|
|
var opt = panel.componentOptions;
|
|
return opt &&
|
|
opt.propsData.name !== void 0 &&
|
|
opt.propsData.disable !== '' &&
|
|
opt.propsData.disable !== true
|
|
})
|
|
},
|
|
|
|
__updatePanelTransition: function __updatePanelTransition (direction) {
|
|
var val = direction !== 0 && this.animated === true && this.panelIndex !== -1
|
|
? 'q-transition--' + (direction === -1 ? this.transitionPrevComputed : this.transitionNextComputed)
|
|
: null;
|
|
|
|
if (this.panelTransition !== val) {
|
|
this.panelTransition = val;
|
|
}
|
|
},
|
|
|
|
__go: function __go (direction, startIndex) {
|
|
var this$1 = this;
|
|
if ( startIndex === void 0 ) startIndex = this.panelIndex;
|
|
|
|
var index = startIndex + direction;
|
|
var slots = this.panels;
|
|
|
|
while (index > -1 && index < slots.length) {
|
|
var opt = slots[index].componentOptions;
|
|
|
|
if (
|
|
opt !== void 0 &&
|
|
opt.propsData.disable !== '' &&
|
|
opt.propsData.disable !== true
|
|
) {
|
|
this.__updatePanelTransition(direction);
|
|
this.__forcedPanelTransition = true;
|
|
this.$emit('input', slots[index].componentOptions.propsData.name);
|
|
setTimeout(function () {
|
|
this$1.__forcedPanelTransition = false;
|
|
});
|
|
return
|
|
}
|
|
|
|
index += direction;
|
|
}
|
|
|
|
if (this.infinite === true && slots.length > 0 && startIndex !== -1 && startIndex !== slots.length) {
|
|
this.__go(direction, direction === -1 ? slots.length : -1);
|
|
}
|
|
},
|
|
|
|
__swipe: function __swipe (evt) {
|
|
var dir = this.vertical === true ? 'up' : 'left';
|
|
this.__go((this.$q.lang.rtl === true ? -1 : 1) * (evt.direction === dir ? 1 : -1));
|
|
},
|
|
|
|
__updatePanelIndex: function __updatePanelIndex () {
|
|
var index = this.__getPanelIndex(this.value);
|
|
|
|
if (this.panelIndex !== index) {
|
|
this.panelIndex = index;
|
|
}
|
|
|
|
return true
|
|
},
|
|
|
|
__getPanelContent: function __getPanelContent (h) {
|
|
if (this.panels.length === 0) {
|
|
return
|
|
}
|
|
|
|
var panel = this.__isValidPanelName(this.value) &&
|
|
this.__updatePanelIndex() &&
|
|
this.panels[this.panelIndex];
|
|
|
|
var content = this.keepAlive === true
|
|
? [
|
|
h('keep-alive', [
|
|
h(PanelWrapper, {
|
|
key: this.contentKey
|
|
}, [ panel ])
|
|
])
|
|
]
|
|
: [
|
|
h('div', {
|
|
staticClass: 'q-panel scroll',
|
|
key: this.contentKey,
|
|
attrs: { role: 'tabpanel' },
|
|
// stop propagation of content emitted @input
|
|
// which would tamper with Panel's model
|
|
on: cache(this, 'stop', { input: stop })
|
|
}, [ panel ])
|
|
];
|
|
|
|
return this.animated === true
|
|
? [
|
|
h('transition', {
|
|
props: {
|
|
name: this.panelTransition
|
|
}
|
|
}, content)
|
|
]
|
|
: content
|
|
}
|
|
},
|
|
|
|
render: function render (h) {
|
|
this.panels = slot(this, 'default', []);
|
|
return this.__renderPanels(h)
|
|
}
|
|
};
|
|
|
|
var PanelChildMixin = {
|
|
mixins: [ ListenersMixin ],
|
|
|
|
props: {
|
|
name: {
|
|
required: true
|
|
},
|
|
disable: Boolean
|
|
}
|
|
};
|
|
|
|
var FullscreenMixin = {
|
|
props: {
|
|
fullscreen: Boolean,
|
|
noRouteFullscreenExit: Boolean
|
|
},
|
|
|
|
data: function data () {
|
|
return {
|
|
inFullscreen: false
|
|
}
|
|
},
|
|
|
|
watch: {
|
|
$route: function $route () {
|
|
this.noRouteFullscreenExit !== true && this.exitFullscreen();
|
|
},
|
|
|
|
fullscreen: function fullscreen (v) {
|
|
if (this.inFullscreen !== v) {
|
|
this.toggleFullscreen();
|
|
}
|
|
},
|
|
|
|
inFullscreen: function inFullscreen (v) {
|
|
this.$emit('update:fullscreen', v);
|
|
this.$emit('fullscreen', v);
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
toggleFullscreen: function toggleFullscreen () {
|
|
if (this.inFullscreen === true) {
|
|
this.exitFullscreen();
|
|
}
|
|
else {
|
|
this.setFullscreen();
|
|
}
|
|
},
|
|
|
|
setFullscreen: function setFullscreen () {
|
|
if (this.inFullscreen === true) {
|
|
return
|
|
}
|
|
|
|
this.inFullscreen = true;
|
|
this.container = this.$el.parentNode;
|
|
this.container.replaceChild(this.fullscreenFillerNode, this.$el);
|
|
document.body.appendChild(this.$el);
|
|
document.body.classList.add('q-body--fullscreen-mixin');
|
|
|
|
this.__historyFullscreen = {
|
|
handler: this.exitFullscreen
|
|
};
|
|
History.add(this.__historyFullscreen);
|
|
},
|
|
|
|
exitFullscreen: function exitFullscreen () {
|
|
var this$1 = this;
|
|
|
|
if (this.inFullscreen !== true) {
|
|
return
|
|
}
|
|
|
|
if (this.__historyFullscreen !== void 0) {
|
|
History.remove(this.__historyFullscreen);
|
|
this.__historyFullscreen = void 0;
|
|
}
|
|
this.container.replaceChild(this.$el, this.fullscreenFillerNode);
|
|
document.body.classList.remove('q-body--fullscreen-mixin');
|
|
this.inFullscreen = false;
|
|
|
|
if (this.$el.scrollIntoView !== void 0) {
|
|
setTimeout(function () { this$1.$el.scrollIntoView(); });
|
|
}
|
|
}
|
|
},
|
|
|
|
beforeMount: function beforeMount () {
|
|
this.fullscreenFillerNode = document.createElement('span');
|
|
},
|
|
|
|
mounted: function mounted () {
|
|
this.fullscreen === true && this.setFullscreen();
|
|
},
|
|
|
|
beforeDestroy: function beforeDestroy () {
|
|
this.exitFullscreen();
|
|
}
|
|
};
|
|
|
|
var
|
|
hasMap = typeof Map === 'function',
|
|
hasSet = typeof Set === 'function',
|
|
hasArrayBuffer = typeof ArrayBuffer === 'function';
|
|
|
|
function isDeepEqual (a, b) {
|
|
if (a === b) {
|
|
return true
|
|
}
|
|
|
|
if (a !== null && b !== null && typeof a === 'object' && typeof b === 'object') {
|
|
if (a.constructor !== b.constructor) {
|
|
return false
|
|
}
|
|
|
|
var length, i;
|
|
|
|
if (a.constructor === Array) {
|
|
length = a.length;
|
|
|
|
if (length !== b.length) {
|
|
return false
|
|
}
|
|
|
|
for (i = length; i-- !== 0;) {
|
|
if (isDeepEqual(a[i], b[i]) !== true) {
|
|
return false
|
|
}
|
|
}
|
|
|
|
return true
|
|
}
|
|
|
|
if (hasMap === true && a.constructor === Map) {
|
|
if (a.size !== b.size) {
|
|
return false
|
|
}
|
|
|
|
i = a.entries().next();
|
|
while (i.done !== true) {
|
|
if (b.has(i.value[0]) !== true) {
|
|
return false
|
|
}
|
|
i = i.next();
|
|
}
|
|
|
|
i = a.entries().next();
|
|
while (i.done !== true) {
|
|
if (isDeepEqual(i.value[1], b.get(i.value[0])) !== true) {
|
|
return false
|
|
}
|
|
i = i.next();
|
|
}
|
|
|
|
return true
|
|
}
|
|
|
|
if (hasSet === true && a.constructor === Set) {
|
|
if (a.size !== b.size) {
|
|
return false
|
|
}
|
|
|
|
i = a.entries().next();
|
|
while (i.done !== true) {
|
|
if (b.has(i.value[0]) !== true) {
|
|
return false
|
|
}
|
|
i = i.next();
|
|
}
|
|
|
|
return true
|
|
}
|
|
|
|
if (hasArrayBuffer === true && a.buffer != null && a.buffer.constructor === ArrayBuffer) {
|
|
length = a.length;
|
|
|
|
if (length !== b.length) {
|
|
return false
|
|
}
|
|
|
|
for (i = length; i-- !== 0;) {
|
|
if (a[i] !== b[i]) {
|
|
return false
|
|
}
|
|
}
|
|
|
|
return true
|
|
}
|
|
|
|
if (a.constructor === RegExp) {
|
|
return a.source === b.source && a.flags === b.flags
|
|
}
|
|
|
|
if (a.valueOf !== Object.prototype.valueOf) {
|
|
return a.valueOf() === b.valueOf()
|
|
}
|
|
|
|
if (a.toString !== Object.prototype.toString) {
|
|
return a.toString() === b.toString()
|
|
}
|
|
|
|
var keys = Object.keys(a);
|
|
length = keys.length;
|
|
|
|
if (length !== Object.keys(b).length) {
|
|
return false
|
|
}
|
|
|
|
for (i = length; i-- !== 0;) {
|
|
var key = keys[i];
|
|
if (isDeepEqual(a[key], b[key]) !== true) {
|
|
return false
|
|
}
|
|
}
|
|
|
|
return true
|
|
}
|
|
|
|
// true if both NaN, false otherwise
|
|
return a !== a && b !== b // eslint-disable-line no-self-compare
|
|
}
|
|
|
|
function isDate (v) {
|
|
return Object.prototype.toString.call(v) === '[object Date]'
|
|
}
|
|
|
|
function isNumber (v) {
|
|
return typeof v === 'number' && isFinite(v)
|
|
}
|
|
|
|
var QCarousel = Vue.extend({
|
|
name: 'QCarousel',
|
|
|
|
mixins: [ DarkMixin, PanelParentMixin, FullscreenMixin ],
|
|
|
|
props: {
|
|
height: String,
|
|
padding: Boolean,
|
|
|
|
controlType: {
|
|
type: String,
|
|
validator: function (v) { return [ 'regular', 'flat', 'outline', 'push', 'unelevated' ].includes(v); },
|
|
default: 'flat'
|
|
},
|
|
controlColor: String,
|
|
controlTextColor: String,
|
|
|
|
autoplay: [ Number, Boolean ],
|
|
|
|
arrows: Boolean,
|
|
prevIcon: String,
|
|
nextIcon: String,
|
|
|
|
navigation: Boolean,
|
|
navigationPosition: {
|
|
type: String,
|
|
validator: function (v) { return [ 'top', 'right', 'bottom', 'left' ].includes(v); }
|
|
},
|
|
navigationIcon: String,
|
|
navigationActiveIcon: String,
|
|
|
|
thumbnails: Boolean
|
|
},
|
|
|
|
computed: {
|
|
style: function style () {
|
|
if (this.inFullscreen !== true && this.height !== void 0) {
|
|
return {
|
|
height: this.height
|
|
}
|
|
}
|
|
},
|
|
|
|
direction: function direction () {
|
|
return this.vertical === true ? 'vertical' : 'horizontal'
|
|
},
|
|
|
|
classes: function classes () {
|
|
return "q-carousel q-panel-parent q-carousel--with" + (this.padding === true ? '' : 'out') + "-padding" +
|
|
(this.inFullscreen === true ? ' fullscreen' : '') +
|
|
(this.isDark === true ? ' q-carousel--dark q-dark' : '') +
|
|
(this.arrows === true ? (" q-carousel--arrows-" + (this.direction)) : '') +
|
|
(this.navigation === true ? (" q-carousel--navigation-" + (this.navigationPositionComputed)) : '')
|
|
},
|
|
|
|
arrowIcons: function arrowIcons () {
|
|
var ico = [
|
|
this.prevIcon || this.$q.iconSet.carousel[this.vertical === true ? 'up' : 'left'],
|
|
this.nextIcon || this.$q.iconSet.carousel[this.vertical === true ? 'down' : 'right']
|
|
];
|
|
|
|
return this.vertical === false && this.$q.lang.rtl === true
|
|
? ico.reverse()
|
|
: ico
|
|
},
|
|
|
|
navIcon: function navIcon () {
|
|
return this.navigationIcon || this.$q.iconSet.carousel.navigationIcon
|
|
},
|
|
|
|
navActiveIcon: function navActiveIcon () {
|
|
return this.navigationActiveIcon || this.navIcon
|
|
},
|
|
|
|
navigationPositionComputed: function navigationPositionComputed () {
|
|
return this.navigationPosition || (this.vertical === true ? 'right' : 'bottom')
|
|
},
|
|
|
|
controlProps: function controlProps () {
|
|
var obj;
|
|
|
|
return ( obj = {
|
|
color: this.controlColor,
|
|
textColor: this.controlTextColor,
|
|
round: true
|
|
}, obj[ this.controlType ] = true, obj.dense = true, obj )
|
|
},
|
|
|
|
transitionPrevComputed: function transitionPrevComputed () {
|
|
return this.transitionPrev || "fade"
|
|
},
|
|
|
|
transitionNextComputed: function transitionNextComputed () {
|
|
return this.transitionNext || "fade"
|
|
}
|
|
},
|
|
|
|
watch: {
|
|
value: function value () {
|
|
if (this.autoplay) {
|
|
clearInterval(this.timer);
|
|
this.__startTimer();
|
|
}
|
|
},
|
|
|
|
autoplay: function autoplay (val) {
|
|
if (val) {
|
|
this.__startTimer();
|
|
}
|
|
else {
|
|
clearInterval(this.timer);
|
|
}
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
__startTimer: function __startTimer () {
|
|
this.timer = setTimeout(
|
|
this.next,
|
|
isNumber(this.autoplay) ? this.autoplay : 5000
|
|
);
|
|
},
|
|
|
|
__getNavigationContainer: function __getNavigationContainer (h, type, mapping) {
|
|
return h('div', {
|
|
class: 'q-carousel__control q-carousel__navigation no-wrap absolute flex' +
|
|
" q-carousel__navigation--" + type + " q-carousel__navigation--" + (this.navigationPositionComputed) +
|
|
(this.controlColor !== void 0 ? (" text-" + (this.controlColor)) : '')
|
|
}, [
|
|
h('div', {
|
|
staticClass: 'q-carousel__navigation-inner flex flex-center no-wrap'
|
|
}, this.__getAvailablePanels().map(mapping))
|
|
])
|
|
},
|
|
|
|
__getContent: function __getContent (h) {
|
|
var this$1 = this;
|
|
|
|
var node = [];
|
|
|
|
if (this.navigation === true) {
|
|
var fn = this.$scopedSlots['navigation-icon'] !== void 0
|
|
? this.$scopedSlots['navigation-icon']
|
|
: function (opts) { return h(QBtn, {
|
|
key: 'nav' + opts.name,
|
|
class: ("q-carousel__navigation-icon q-carousel__navigation-icon--" + (opts.active === true ? '' : 'in') + "active"),
|
|
props: opts.btnProps,
|
|
on: cache(this$1, 'nav#' + opts.name, { click: opts.onClick })
|
|
}); };
|
|
|
|
var maxIndex = this.panels.length - 1;
|
|
node.push(
|
|
this.__getNavigationContainer(h, 'buttons', function (panel, index) {
|
|
var name = panel.componentOptions.propsData.name;
|
|
var active = this$1.panelIndex === index;
|
|
|
|
return fn({
|
|
index: index,
|
|
maxIndex: maxIndex,
|
|
name: name,
|
|
active: active,
|
|
btnProps: Object.assign({}, {icon: active === true ? this$1.navActiveIcon : this$1.navIcon,
|
|
size: 'sm'},
|
|
this$1.controlProps),
|
|
onClick: function () { this$1.goTo(name); }
|
|
})
|
|
})
|
|
);
|
|
}
|
|
else if (this.thumbnails === true) {
|
|
var color = this.controlColor !== void 0
|
|
? (" text-" + (this.controlColor))
|
|
: '';
|
|
|
|
node.push(this.__getNavigationContainer(h, 'thumbnails', function (panel) {
|
|
var slide = panel.componentOptions.propsData;
|
|
|
|
return h('img', {
|
|
class: "q-carousel__thumbnail q-carousel__thumbnail--" + (slide.name === this$1.value ? '' : 'in') + "active" + color,
|
|
attrs: {
|
|
src: slide.imgSrc
|
|
},
|
|
key: 'tmb#' + slide.name,
|
|
on: cache(this$1, 'tmb#' + slide.name, { click: function () { this$1.goTo(slide.name); } })
|
|
})
|
|
}));
|
|
}
|
|
|
|
if (this.arrows === true && this.panelIndex >= 0) {
|
|
if (this.infinite === true || this.panelIndex > 0) {
|
|
node.push(
|
|
h('div', {
|
|
key: 'prev',
|
|
staticClass: ("q-carousel__control q-carousel__arrow q-carousel__prev-arrow q-carousel__prev-arrow--" + (this.direction) + " absolute flex flex-center")
|
|
}, [
|
|
h(QBtn, {
|
|
props: Object.assign({}, {icon: this.arrowIcons[0]}, this.controlProps),
|
|
on: cache(this, 'prev', { click: this.previous })
|
|
})
|
|
])
|
|
);
|
|
}
|
|
|
|
if (this.infinite === true || this.panelIndex < this.panels.length - 1) {
|
|
node.push(
|
|
h('div', {
|
|
key: 'next',
|
|
staticClass: ("q-carousel__control q-carousel__arrow q-carousel__next-arrow q-carousel__next-arrow--" + (this.direction) + " absolute flex flex-center")
|
|
}, [
|
|
h(QBtn, {
|
|
props: Object.assign({}, {icon: this.arrowIcons[1]}, this.controlProps),
|
|
on: cache(this, 'next', { click: this.next })
|
|
})
|
|
])
|
|
);
|
|
}
|
|
}
|
|
|
|
return mergeSlot(node, this, 'control')
|
|
},
|
|
|
|
__renderPanels: function __renderPanels (h) {
|
|
return h('div', {
|
|
style: this.style,
|
|
class: this.classes,
|
|
on: Object.assign({}, this.qListeners)
|
|
}, [
|
|
h('div', {
|
|
staticClass: 'q-carousel__slides-container',
|
|
directives: this.panelDirectives
|
|
}, this.__getPanelContent(h))
|
|
].concat(this.__getContent(h)))
|
|
}
|
|
},
|
|
|
|
mounted: function mounted () {
|
|
this.autoplay && this.__startTimer();
|
|
},
|
|
|
|
beforeDestroy: function beforeDestroy () {
|
|
clearInterval(this.timer);
|
|
}
|
|
});
|
|
|
|
var QCarouselSlide = Vue.extend({
|
|
name: 'QCarouselSlide',
|
|
|
|
mixins: [ PanelChildMixin ],
|
|
|
|
props: {
|
|
imgSrc: String
|
|
},
|
|
|
|
computed: {
|
|
style: function style () {
|
|
if (this.imgSrc) {
|
|
return {
|
|
backgroundImage: ("url(\"" + (this.imgSrc) + "\")")
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
render: function render (h) {
|
|
return h('div', {
|
|
staticClass: 'q-carousel__slide',
|
|
style: this.style,
|
|
on: Object.assign({}, this.qListeners)
|
|
}, slot(this, 'default'))
|
|
}
|
|
});
|
|
|
|
var QCarouselControl = Vue.extend({
|
|
name: 'QCarouselControl',
|
|
|
|
mixins: [ ListenersMixin ],
|
|
|
|
props: {
|
|
position: {
|
|
type: String,
|
|
default: 'bottom-right',
|
|
validator: function (v) { return [
|
|
'top-right', 'top-left',
|
|
'bottom-right', 'bottom-left',
|
|
'top', 'right', 'bottom', 'left'
|
|
].includes(v); }
|
|
},
|
|
offset: {
|
|
type: Array,
|
|
default: function () { return [18, 18]; },
|
|
validator: function (v) { return v.length === 2; }
|
|
}
|
|
},
|
|
|
|
computed: {
|
|
classes: function classes () {
|
|
return ("absolute-" + (this.position))
|
|
},
|
|
|
|
style: function style () {
|
|
return {
|
|
margin: ((this.offset[1]) + "px " + (this.offset[0]) + "px")
|
|
}
|
|
}
|
|
},
|
|
|
|
render: function render (h) {
|
|
return h('div', {
|
|
staticClass: 'q-carousel__control absolute',
|
|
style: this.style,
|
|
class: this.classes,
|
|
on: Object.assign({}, this.qListeners)
|
|
}, slot(this, 'default'))
|
|
}
|
|
});
|
|
|
|
var QChatMessage = Vue.extend({
|
|
name: 'QChatMessage',
|
|
|
|
mixins: [ ListenersMixin ],
|
|
|
|
props: {
|
|
sent: Boolean,
|
|
label: String,
|
|
bgColor: String,
|
|
textColor: String,
|
|
name: String,
|
|
avatar: String,
|
|
text: Array,
|
|
stamp: String,
|
|
size: String,
|
|
labelSanitize: Boolean,
|
|
nameSanitize: Boolean,
|
|
textSanitize: Boolean,
|
|
stampSanitize: Boolean
|
|
},
|
|
|
|
computed: {
|
|
textClass: function textClass () {
|
|
return "q-message-text-content q-message-text-content--" + (this.op) +
|
|
(this.textColor !== void 0 ? (" text-" + (this.textColor)) : '')
|
|
},
|
|
|
|
messageClass: function messageClass () {
|
|
return "q-message-text q-message-text--" + (this.op) +
|
|
(this.bgColor !== void 0 ? (" text-" + (this.bgColor)) : '')
|
|
},
|
|
|
|
containerClass: function containerClass () {
|
|
return "q-message-container row items-end no-wrap" +
|
|
(this.sent === true ? ' reverse' : '')
|
|
},
|
|
|
|
sizeClass: function sizeClass () {
|
|
if (this.size !== void 0) {
|
|
return ("col-" + (this.size))
|
|
}
|
|
},
|
|
|
|
op: function op () {
|
|
return this.sent === true ? 'sent' : 'received'
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
__getText: function __getText (h) {
|
|
var this$1 = this;
|
|
|
|
var
|
|
domPropText = this.textSanitize === true ? 'textContent' : 'innerHTML',
|
|
domPropStamp = this.stampSanitize === true ? 'textContent' : 'innerHTML';
|
|
|
|
return this.text.map(function (msg, index) {
|
|
var obj, obj$1;
|
|
|
|
return h('div', {
|
|
key: index,
|
|
class: this$1.messageClass
|
|
}, [
|
|
h('div', { class: this$1.textClass }, [
|
|
h('div', { domProps: ( obj = {}, obj[domPropText] = msg, obj ) }),
|
|
this$1.stamp
|
|
? h('div', {
|
|
staticClass: 'q-message-stamp',
|
|
domProps: ( obj$1 = {}, obj$1[domPropStamp] = this$1.stamp, obj$1 )
|
|
})
|
|
: null
|
|
])
|
|
]);
|
|
})
|
|
},
|
|
|
|
__getMessage: function __getMessage (h) {
|
|
var obj;
|
|
|
|
var content = uniqueSlot(this, 'default', []);
|
|
|
|
this.stamp !== void 0 && content.push(
|
|
h('div', {
|
|
staticClass: 'q-message-stamp',
|
|
domProps: ( obj = {}, obj[this.stampSanitize === true ? 'textContent' : 'innerHTML'] = this.stamp, obj )
|
|
})
|
|
);
|
|
|
|
return h('div', { class: this.messageClass }, [
|
|
h('div', {
|
|
staticClass: 'q-message-text-content',
|
|
class: this.textClass
|
|
}, content)
|
|
])
|
|
}
|
|
},
|
|
|
|
render: function render (h) {
|
|
var obj, obj$1;
|
|
|
|
var container = [];
|
|
|
|
if (this.$scopedSlots.avatar !== void 0) {
|
|
container.push(this.$scopedSlots.avatar());
|
|
}
|
|
else if (this.avatar !== void 0) {
|
|
container.push(
|
|
h('img', {
|
|
class: ("q-message-avatar q-message-avatar--" + (this.op)),
|
|
attrs: { src: this.avatar, 'aria-hidden': 'true' }
|
|
})
|
|
);
|
|
}
|
|
|
|
var msg = [];
|
|
|
|
this.name !== void 0 && msg.push(
|
|
h('div', {
|
|
class: ("q-message-name q-message-name--" + (this.op)),
|
|
domProps: ( obj = {}, obj[this.nameSanitize === true ? 'textContent' : 'innerHTML'] = this.name, obj )
|
|
})
|
|
);
|
|
|
|
this.text !== void 0 && msg.push(
|
|
this.__getText(h)
|
|
);
|
|
|
|
this.$scopedSlots.default !== void 0 && msg.push(
|
|
this.__getMessage(h)
|
|
);
|
|
|
|
container.push(
|
|
h('div', { class: this.sizeClass }, msg)
|
|
);
|
|
|
|
var child = [];
|
|
|
|
this.label && child.push(
|
|
h('div', {
|
|
staticClass: 'q-message-label text-center',
|
|
domProps: ( obj$1 = {}, obj$1[this.labelSanitize === true ? 'textContent' : 'innerHTML'] = this.label, obj$1 )
|
|
})
|
|
);
|
|
|
|
child.push(
|
|
h('div', { class: this.containerClass }, container)
|
|
);
|
|
|
|
return h('div', {
|
|
class: ("q-message q-message-" + (this.op)),
|
|
on: Object.assign({}, this.qListeners)
|
|
}, child)
|
|
}
|
|
});
|
|
|
|
var OptionSizeMixin = getSizeMixin({
|
|
xs: 30,
|
|
sm: 35,
|
|
md: 40,
|
|
lg: 50,
|
|
xl: 60
|
|
});
|
|
|
|
var RefocusTargetMixin = {
|
|
computed: {
|
|
__refocusTargetEl: function __refocusTargetEl () {
|
|
if (this.disable !== true) {
|
|
return this.$createElement('span', {
|
|
ref: 'refocusTarget',
|
|
staticClass: 'no-outline',
|
|
attrs: { tabindex: -1 }
|
|
})
|
|
}
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
__refocusTarget: function __refocusTarget (e) {
|
|
if (e !== void 0 && e.type.indexOf('key') === 0) {
|
|
if (document.activeElement !== this.$el && this.$el.contains(document.activeElement) === true) {
|
|
this.$el.focus();
|
|
}
|
|
}
|
|
else if ((e === void 0 || this.$el.contains(e.target) === true) && this.$refs.refocusTarget !== void 0) {
|
|
this.$refs.refocusTarget.focus();
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
var CheckboxMixin = {
|
|
mixins: [ DarkMixin, OptionSizeMixin, FormMixin, RefocusTargetMixin ],
|
|
|
|
props: {
|
|
value: {
|
|
required: true,
|
|
default: null
|
|
},
|
|
val: {},
|
|
|
|
trueValue: { default: true },
|
|
falseValue: { default: false },
|
|
indeterminateValue: { default: null },
|
|
|
|
toggleOrder: {
|
|
type: String,
|
|
validator: function (v) { return v === 'tf' || v === 'ft'; }
|
|
},
|
|
toggleIndeterminate: Boolean,
|
|
|
|
label: String,
|
|
leftLabel: Boolean,
|
|
fontSize: String,
|
|
|
|
color: String,
|
|
keepColor: Boolean,
|
|
dense: Boolean,
|
|
|
|
disable: Boolean,
|
|
tabindex: [String, Number]
|
|
},
|
|
|
|
computed: {
|
|
isTrue: function isTrue () {
|
|
return this.modelIsArray === true
|
|
? this.index > -1
|
|
: this.value === this.trueValue
|
|
},
|
|
|
|
isFalse: function isFalse () {
|
|
return this.modelIsArray === true
|
|
? this.index === -1
|
|
: this.value === this.falseValue
|
|
},
|
|
|
|
isIndeterminate: function isIndeterminate () {
|
|
return this.isTrue === false && this.isFalse === false
|
|
},
|
|
|
|
index: function index () {
|
|
if (this.modelIsArray === true) {
|
|
return this.value.indexOf(this.val)
|
|
}
|
|
},
|
|
|
|
modelIsArray: function modelIsArray () {
|
|
return this.val !== void 0 && Array.isArray(this.value)
|
|
},
|
|
|
|
computedTabindex: function computedTabindex () {
|
|
return this.disable === true ? -1 : this.tabindex || 0
|
|
},
|
|
|
|
labelStyle: function labelStyle () {
|
|
if (this.fontSize !== void 0) {
|
|
return { fontSize: this.fontSize }
|
|
}
|
|
},
|
|
|
|
classes: function classes () {
|
|
return "q-" + (this.type) + " cursor-pointer no-outline row inline no-wrap items-center" +
|
|
(this.disable === true ? ' disabled' : '') +
|
|
(this.isDark === true ? (" q-" + (this.type) + "--dark") : '') +
|
|
(this.dense === true ? (" q-" + (this.type) + "--dense") : '') +
|
|
(this.leftLabel === true ? ' reverse' : '')
|
|
},
|
|
|
|
innerClass: function innerClass () {
|
|
var state = this.isTrue === true ? 'truthy' : (this.isFalse === true ? 'falsy' : 'indet');
|
|
var color = this.color !== void 0 && (
|
|
this.keepColor === true ||
|
|
(this.type === 'toggle' ? this.isTrue === true : this.isFalse !== true)
|
|
)
|
|
? (" text-" + (this.color))
|
|
: '';
|
|
|
|
return ("q-" + (this.type) + "__inner--" + state + color)
|
|
},
|
|
|
|
formAttrs: function formAttrs () {
|
|
var prop = { type: 'checkbox' };
|
|
|
|
this.name !== void 0 && Object.assign(prop, {
|
|
checked: this.isTrue,
|
|
name: this.name,
|
|
value: this.modelIsArray === true
|
|
? this.val
|
|
: this.trueValue
|
|
});
|
|
|
|
return prop
|
|
},
|
|
|
|
attrs: function attrs () {
|
|
var attrs = {
|
|
tabindex: this.computedTabindex,
|
|
role: 'checkbox',
|
|
'aria-label': this.label,
|
|
'aria-checked': this.isIndeterminate === true
|
|
? 'mixed'
|
|
: (this.isTrue === true ? 'true' : 'false')
|
|
};
|
|
|
|
if (this.disable === true) {
|
|
attrs['aria-disabled'] = 'true';
|
|
}
|
|
|
|
return attrs
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
toggle: function toggle (e) {
|
|
if (e !== void 0) {
|
|
stopAndPrevent(e);
|
|
this.__refocusTarget(e);
|
|
}
|
|
|
|
if (this.disable !== true) {
|
|
this.$emit('input', this.__getNextValue(), e);
|
|
}
|
|
},
|
|
|
|
__getNextValue: function __getNextValue () {
|
|
if (this.modelIsArray === true) {
|
|
if (this.isTrue === true) {
|
|
var val = this.value.slice();
|
|
val.splice(this.index, 1);
|
|
return val
|
|
}
|
|
|
|
return this.value.concat([ this.val ])
|
|
}
|
|
|
|
if (this.isTrue === true) {
|
|
if (this.toggleOrder !== 'ft' || this.toggleIndeterminate === false) {
|
|
return this.falseValue
|
|
}
|
|
}
|
|
else if (this.isFalse === true) {
|
|
if (this.toggleOrder === 'ft' || this.toggleIndeterminate === false) {
|
|
return this.trueValue
|
|
}
|
|
}
|
|
else {
|
|
return this.toggleOrder !== 'ft'
|
|
? this.trueValue
|
|
: this.falseValue
|
|
}
|
|
|
|
return this.indeterminateValue
|
|
},
|
|
|
|
__onKeydown: function __onKeydown (e) {
|
|
if (e.keyCode === 13 || e.keyCode === 32) {
|
|
stopAndPrevent(e);
|
|
}
|
|
},
|
|
|
|
__onKeyup: function __onKeyup (e) {
|
|
if (e.keyCode === 13 || e.keyCode === 32) {
|
|
this.toggle(e);
|
|
}
|
|
}
|
|
},
|
|
|
|
render: function render (h) {
|
|
var inner = this.__getInner(h);
|
|
|
|
this.disable !== true && this.__injectFormInput(
|
|
inner,
|
|
'unshift',
|
|
("q-" + (this.type) + "__native absolute q-ma-none q-pa-none invisible")
|
|
);
|
|
|
|
var child = [
|
|
h('div', {
|
|
staticClass: ("q-" + (this.type) + "__inner relative-position no-pointer-events"),
|
|
class: this.innerClass,
|
|
style: this.sizeStyle
|
|
}, inner)
|
|
];
|
|
|
|
if (this.__refocusTargetEl !== void 0) {
|
|
child.push(this.__refocusTargetEl);
|
|
}
|
|
|
|
var label = this.label !== void 0
|
|
? mergeSlot([ this.label ], this, 'default')
|
|
: slot(this, 'default');
|
|
|
|
label !== void 0 && child.push(
|
|
h('div', {
|
|
staticClass: ("q-" + (this.type) + "__label q-anchor--skip")
|
|
}, label)
|
|
);
|
|
|
|
return h('div', {
|
|
class: this.classes,
|
|
attrs: this.attrs,
|
|
on: cache(this, 'inpExt', {
|
|
click: this.toggle,
|
|
keydown: this.__onKeydown,
|
|
keyup: this.__onKeyup
|
|
})
|
|
}, child)
|
|
}
|
|
};
|
|
|
|
var QCheckbox = Vue.extend({
|
|
name: 'QCheckbox',
|
|
|
|
mixins: [ CheckboxMixin ],
|
|
|
|
methods: {
|
|
__getInner: function __getInner (h) {
|
|
return [
|
|
h('div', {
|
|
staticClass: 'q-checkbox__bg absolute'
|
|
}, [
|
|
h('svg', {
|
|
staticClass: 'q-checkbox__svg fit absolute-full',
|
|
attrs: { focusable: 'false' /* needed for IE11 */, viewBox: '0 0 24 24', 'aria-hidden': 'true' }
|
|
}, [
|
|
h('path', {
|
|
staticClass: 'q-checkbox__truthy',
|
|
attrs: {
|
|
fill: 'none',
|
|
d: 'M1.73,12.91 8.1,19.28 22.79,4.59'
|
|
}
|
|
}),
|
|
|
|
h('path', {
|
|
staticClass: 'q-checkbox__indet',
|
|
attrs: {
|
|
d: 'M4,14H20V10H4'
|
|
}
|
|
})
|
|
])
|
|
])
|
|
]
|
|
}
|
|
},
|
|
|
|
created: function created () {
|
|
this.type = 'checkbox';
|
|
}
|
|
});
|
|
|
|
var QChip = Vue.extend({
|
|
name: 'QChip',
|
|
|
|
mixins: [
|
|
RippleMixin,
|
|
DarkMixin,
|
|
getSizeMixin({
|
|
xs: 8,
|
|
sm: 10,
|
|
md: 14,
|
|
lg: 20,
|
|
xl: 24
|
|
})
|
|
],
|
|
|
|
model: {
|
|
event: 'remove'
|
|
},
|
|
|
|
props: {
|
|
dense: Boolean,
|
|
|
|
icon: String,
|
|
iconRight: String,
|
|
iconRemove: String,
|
|
label: [String, Number],
|
|
|
|
color: String,
|
|
textColor: String,
|
|
|
|
value: {
|
|
type: Boolean,
|
|
default: true
|
|
},
|
|
selected: {
|
|
type: Boolean,
|
|
default: null
|
|
},
|
|
|
|
square: Boolean,
|
|
outline: Boolean,
|
|
clickable: Boolean,
|
|
removable: Boolean,
|
|
|
|
tabindex: [String, Number],
|
|
disable: Boolean
|
|
},
|
|
|
|
computed: {
|
|
classes: function classes () {
|
|
var obj;
|
|
|
|
var text = this.outline === true
|
|
? this.color || this.textColor
|
|
: this.textColor;
|
|
|
|
return ( obj = {}, obj[("bg-" + (this.color))] = this.outline === false && this.color !== void 0, obj[("text-" + text + " q-chip--colored")] = text, obj.disabled = this.disable, obj['q-chip--dense'] = this.dense, obj['q-chip--outline'] = this.outline, obj['q-chip--selected'] = this.selected, obj['q-chip--clickable cursor-pointer non-selectable q-hoverable'] = this.isClickable, obj['q-chip--square'] = this.square, obj['q-chip--dark q-dark'] = this.isDark, obj )
|
|
},
|
|
|
|
hasLeftIcon: function hasLeftIcon () {
|
|
return this.selected === true || this.icon !== void 0
|
|
},
|
|
|
|
isClickable: function isClickable () {
|
|
return this.disable === false && (this.clickable === true || this.selected !== null)
|
|
},
|
|
|
|
attrs: function attrs () {
|
|
return this.disable === true
|
|
? { tabindex: -1, 'aria-disabled': 'true' }
|
|
: { tabindex: this.tabindex || 0 }
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
__onKeyup: function __onKeyup (e) {
|
|
e.keyCode === 13 /* ENTER */ && this.__onClick(e);
|
|
},
|
|
|
|
__onClick: function __onClick (e) {
|
|
if (!this.disable) {
|
|
this.$emit('update:selected', !this.selected);
|
|
this.$emit('click', e);
|
|
}
|
|
},
|
|
|
|
__onRemove: function __onRemove (e) {
|
|
if (e.keyCode === void 0 || e.keyCode === 13) {
|
|
stopAndPrevent(e);
|
|
!this.disable && this.$emit('remove', false);
|
|
}
|
|
},
|
|
|
|
__getContent: function __getContent (h) {
|
|
var child = [];
|
|
|
|
this.isClickable === true && child.push(
|
|
h('div', { staticClass: 'q-focus-helper' })
|
|
);
|
|
|
|
this.hasLeftIcon === true && child.push(
|
|
h(QIcon, {
|
|
staticClass: 'q-chip__icon q-chip__icon--left',
|
|
props: { name: this.selected === true ? this.$q.iconSet.chip.selected : this.icon }
|
|
})
|
|
);
|
|
|
|
var label = this.label !== void 0
|
|
? [ h('div', { staticClass: 'ellipsis' }, [ this.label ]) ]
|
|
: void 0;
|
|
|
|
child.push(
|
|
h('div', {
|
|
staticClass: 'q-chip__content col row no-wrap items-center q-anchor--skip'
|
|
}, mergeSlotSafely(label, this, 'default'))
|
|
);
|
|
|
|
this.iconRight && child.push(
|
|
h(QIcon, {
|
|
staticClass: 'q-chip__icon q-chip__icon--right',
|
|
props: { name: this.iconRight }
|
|
})
|
|
);
|
|
|
|
this.removable === true && child.push(
|
|
h(QIcon, {
|
|
staticClass: 'q-chip__icon q-chip__icon--remove cursor-pointer',
|
|
props: { name: this.iconRemove || this.$q.iconSet.chip.remove },
|
|
attrs: this.attrs,
|
|
on: cache(this, 'non', {
|
|
click: this.__onRemove,
|
|
keyup: this.__onRemove
|
|
})
|
|
})
|
|
);
|
|
|
|
return child
|
|
}
|
|
},
|
|
|
|
render: function render (h) {
|
|
if (this.value === false) { return }
|
|
|
|
var data = {
|
|
staticClass: 'q-chip row inline no-wrap items-center',
|
|
class: this.classes,
|
|
style: this.sizeStyle
|
|
};
|
|
|
|
this.isClickable === true && Object.assign(data, {
|
|
attrs: this.attrs,
|
|
on: cache(this, 'click', {
|
|
click: this.__onClick,
|
|
keyup: this.__onKeyup
|
|
}),
|
|
directives: cache(this, 'dir#' + this.ripple, [
|
|
{ name: 'ripple', value: this.ripple }
|
|
])
|
|
});
|
|
|
|
return h('div', data, this.__getContent(h))
|
|
}
|
|
});
|
|
|
|
var
|
|
radius = 50,
|
|
diameter = 2 * radius,
|
|
circumference = diameter * Math.PI,
|
|
strokeDashArray = Math.round(circumference * 1000) / 1000;
|
|
|
|
var QCircularProgress = Vue.extend({
|
|
name: 'QCircularProgress',
|
|
|
|
mixins: [ ListenersMixin, SizeMixin ],
|
|
|
|
props: {
|
|
value: {
|
|
type: Number,
|
|
default: 0
|
|
},
|
|
|
|
min: {
|
|
type: Number,
|
|
default: 0
|
|
},
|
|
max: {
|
|
type: Number,
|
|
default: 100
|
|
},
|
|
|
|
color: String,
|
|
centerColor: String,
|
|
trackColor: String,
|
|
|
|
fontSize: String,
|
|
|
|
// ratio
|
|
thickness: {
|
|
type: Number,
|
|
default: 0.2,
|
|
validator: function (v) { return v >= 0 && v <= 1; }
|
|
},
|
|
|
|
angle: {
|
|
type: Number,
|
|
default: 0
|
|
},
|
|
|
|
indeterminate: Boolean,
|
|
showValue: Boolean,
|
|
reverse: Boolean,
|
|
|
|
instantFeedback: Boolean
|
|
},
|
|
|
|
computed: {
|
|
normalizedValue: function normalizedValue () {
|
|
return between(this.value, this.min, this.max)
|
|
},
|
|
|
|
svgStyle: function svgStyle () {
|
|
return { transform: ("rotate3d(0, 0, 1, " + (this.angle - 90) + "deg)") }
|
|
},
|
|
|
|
circleStyle: function circleStyle () {
|
|
if (this.instantFeedback !== true && this.indeterminate !== true) {
|
|
return { transition: 'stroke-dashoffset 0.6s ease 0s, stroke 0.6s ease' }
|
|
}
|
|
},
|
|
|
|
dir: function dir () {
|
|
return (this.$q.lang.rtl === true ? -1 : 1) * (this.reverse ? -1 : 1)
|
|
},
|
|
|
|
viewBox: function viewBox () {
|
|
return diameter / (1 - this.thickness / 2)
|
|
},
|
|
|
|
viewBoxAttr: function viewBoxAttr () {
|
|
return ((this.viewBox / 2) + " " + (this.viewBox / 2) + " " + (this.viewBox) + " " + (this.viewBox))
|
|
},
|
|
|
|
strokeDashOffset: function strokeDashOffset () {
|
|
var progress = 1 - (this.normalizedValue - this.min) / (this.max - this.min);
|
|
return (this.dir * progress) * circumference
|
|
},
|
|
|
|
strokeWidth: function strokeWidth () {
|
|
return this.thickness / 2 * this.viewBox
|
|
},
|
|
|
|
attrs: function attrs () {
|
|
return {
|
|
role: 'progressbar',
|
|
'aria-valuemin': this.min,
|
|
'aria-valuemax': this.max,
|
|
'aria-valuenow': this.indeterminate === true ? void 0 : this.normalizedValue
|
|
}
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
__getCircle: function __getCircle (h, ref) {
|
|
var thickness = ref.thickness;
|
|
var offset = ref.offset;
|
|
var color = ref.color;
|
|
var cls = ref.cls;
|
|
|
|
return h('circle', {
|
|
staticClass: 'q-circular-progress__' + cls,
|
|
class: color !== void 0 ? ("text-" + color) : null,
|
|
style: this.circleStyle,
|
|
attrs: {
|
|
fill: 'transparent',
|
|
stroke: 'currentColor',
|
|
'stroke-width': thickness,
|
|
'stroke-dasharray': strokeDashArray,
|
|
'stroke-dashoffset': offset,
|
|
cx: this.viewBox,
|
|
cy: this.viewBox,
|
|
r: radius
|
|
}
|
|
})
|
|
}
|
|
},
|
|
|
|
render: function render (h) {
|
|
var svgChild = [];
|
|
|
|
this.centerColor !== void 0 && this.centerColor !== 'transparent' && svgChild.push(
|
|
h('circle', {
|
|
staticClass: 'q-circular-progress__center',
|
|
class: ("text-" + (this.centerColor)),
|
|
attrs: {
|
|
fill: 'currentColor',
|
|
r: radius - this.strokeWidth / 2,
|
|
cx: this.viewBox,
|
|
cy: this.viewBox
|
|
}
|
|
})
|
|
);
|
|
|
|
this.trackColor !== void 0 && this.trackColor !== 'transparent' && svgChild.push(
|
|
this.__getCircle(h, {
|
|
cls: 'track',
|
|
thickness: this.strokeWidth,
|
|
offset: 0,
|
|
color: this.trackColor
|
|
})
|
|
);
|
|
|
|
svgChild.push(
|
|
this.__getCircle(h, {
|
|
cls: 'circle',
|
|
thickness: this.strokeWidth,
|
|
offset: this.strokeDashOffset,
|
|
color: this.color
|
|
})
|
|
);
|
|
|
|
var child = [
|
|
h('svg', {
|
|
staticClass: 'q-circular-progress__svg',
|
|
style: this.svgStyle,
|
|
attrs: {
|
|
focusable: 'false' /* needed for IE11 */,
|
|
viewBox: this.viewBoxAttr,
|
|
'aria-hidden': 'true'
|
|
}
|
|
}, svgChild)
|
|
];
|
|
|
|
this.showValue === true && child.push(
|
|
h('div', {
|
|
staticClass: 'q-circular-progress__text absolute-full row flex-center content-center',
|
|
style: { fontSize: this.fontSize }
|
|
}, this.$scopedSlots.default !== void 0 ? this.$scopedSlots.default() : [ h('div', [ this.normalizedValue ]) ])
|
|
);
|
|
|
|
return h('div', {
|
|
staticClass: 'q-circular-progress',
|
|
class: ("q-circular-progress--" + (this.indeterminate === true ? 'in' : '') + "determinate"),
|
|
style: this.sizeStyle,
|
|
on: Object.assign({}, this.qListeners),
|
|
attrs: this.attrs
|
|
}, mergeSlotSafely(child, this, 'internal'))
|
|
}
|
|
});
|
|
|
|
// file referenced from docs
|
|
|
|
var
|
|
hex = /^#[0-9a-fA-F]{3}([0-9a-fA-F]{3})?$/,
|
|
hexa = /^#[0-9a-fA-F]{4}([0-9a-fA-F]{4})?$/,
|
|
hexOrHexa = /^#([0-9a-fA-F]{3}|[0-9a-fA-F]{4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/,
|
|
rgb = /^rgb\(((0|[1-9][\d]?|1[\d]{0,2}|2[\d]?|2[0-4][\d]|25[0-5]),){2}(0|[1-9][\d]?|1[\d]{0,2}|2[\d]?|2[0-4][\d]|25[0-5])\)$/,
|
|
rgba = /^rgba\(((0|[1-9][\d]?|1[\d]{0,2}|2[\d]?|2[0-4][\d]|25[0-5]),){2}(0|[1-9][\d]?|1[\d]{0,2}|2[\d]?|2[0-4][\d]|25[0-5]),(0|0\.[0-9]+[1-9]|0\.[1-9]+|1)\)$/;
|
|
|
|
var testPattern = {
|
|
date: function (v) { return /^-?[\d]+\/[0-1]\d\/[0-3]\d$/.test(v); },
|
|
time: function (v) { return /^([0-1]?\d|2[0-3]):[0-5]\d$/.test(v); },
|
|
fulltime: function (v) { return /^([0-1]?\d|2[0-3]):[0-5]\d:[0-5]\d$/.test(v); },
|
|
timeOrFulltime: function (v) { return /^([0-1]?\d|2[0-3]):[0-5]\d(:[0-5]\d)?$/.test(v); },
|
|
|
|
hexColor: function (v) { return hex.test(v); },
|
|
hexaColor: function (v) { return hexa.test(v); },
|
|
hexOrHexaColor: function (v) { return hexOrHexa.test(v); },
|
|
|
|
rgbColor: function (v) { return rgb.test(v); },
|
|
rgbaColor: function (v) { return rgba.test(v); },
|
|
rgbOrRgbaColor: function (v) { return rgb.test(v) || rgba.test(v); },
|
|
|
|
hexOrRgbColor: function (v) { return hex.test(v) || rgb.test(v); },
|
|
hexaOrRgbaColor: function (v) { return hexa.test(v) || rgba.test(v); },
|
|
anyColor: function (v) { return hexOrHexa.test(v) || rgb.test(v) || rgba.test(v); }
|
|
};
|
|
|
|
var patterns = {
|
|
testPattern: testPattern
|
|
};
|
|
|
|
function getChanges (evt, ctx, isFinal) {
|
|
var pos = position(evt);
|
|
var
|
|
dir,
|
|
distX = pos.left - ctx.event.x,
|
|
distY = pos.top - ctx.event.y,
|
|
absX = Math.abs(distX),
|
|
absY = Math.abs(distY);
|
|
|
|
var direction = ctx.direction;
|
|
|
|
if (direction.horizontal === true && direction.vertical !== true) {
|
|
dir = distX < 0 ? 'left' : 'right';
|
|
}
|
|
else if (direction.horizontal !== true && direction.vertical === true) {
|
|
dir = distY < 0 ? 'up' : 'down';
|
|
}
|
|
else if (direction.up === true && distY < 0) {
|
|
dir = 'up';
|
|
if (absX > absY) {
|
|
if (direction.left === true && distX < 0) {
|
|
dir = 'left';
|
|
}
|
|
else if (direction.right === true && distX > 0) {
|
|
dir = 'right';
|
|
}
|
|
}
|
|
}
|
|
else if (direction.down === true && distY > 0) {
|
|
dir = 'down';
|
|
if (absX > absY) {
|
|
if (direction.left === true && distX < 0) {
|
|
dir = 'left';
|
|
}
|
|
else if (direction.right === true && distX > 0) {
|
|
dir = 'right';
|
|
}
|
|
}
|
|
}
|
|
else if (direction.left === true && distX < 0) {
|
|
dir = 'left';
|
|
if (absX < absY) {
|
|
if (direction.up === true && distY < 0) {
|
|
dir = 'up';
|
|
}
|
|
else if (direction.down === true && distY > 0) {
|
|
dir = 'down';
|
|
}
|
|
}
|
|
}
|
|
else if (direction.right === true && distX > 0) {
|
|
dir = 'right';
|
|
if (absX < absY) {
|
|
if (direction.up === true && distY < 0) {
|
|
dir = 'up';
|
|
}
|
|
else if (direction.down === true && distY > 0) {
|
|
dir = 'down';
|
|
}
|
|
}
|
|
}
|
|
|
|
var synthetic = false;
|
|
|
|
if (dir === void 0 && isFinal === false) {
|
|
if (ctx.event.isFirst === true || ctx.event.lastDir === void 0) {
|
|
return {}
|
|
}
|
|
|
|
dir = ctx.event.lastDir;
|
|
synthetic = true;
|
|
|
|
if (dir === 'left' || dir === 'right') {
|
|
pos.left -= distX;
|
|
absX = 0;
|
|
distX = 0;
|
|
}
|
|
else {
|
|
pos.top -= distY;
|
|
absY = 0;
|
|
distY = 0;
|
|
}
|
|
}
|
|
|
|
return {
|
|
synthetic: synthetic,
|
|
payload: {
|
|
evt: evt,
|
|
touch: ctx.event.mouse !== true,
|
|
mouse: ctx.event.mouse === true,
|
|
position: pos,
|
|
direction: dir,
|
|
isFirst: ctx.event.isFirst,
|
|
isFinal: isFinal === true,
|
|
duration: Date.now() - ctx.event.time,
|
|
distance: {
|
|
x: absX,
|
|
y: absY
|
|
},
|
|
offset: {
|
|
x: distX,
|
|
y: distY
|
|
},
|
|
delta: {
|
|
x: pos.left - ctx.event.lastX,
|
|
y: pos.top - ctx.event.lastY
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function destroy$2 (el) {
|
|
var ctx = el.__qtouchpan;
|
|
if (ctx !== void 0) {
|
|
// emit the end event when the directive is destroyed while active
|
|
// this is only needed in TouchPan because the rest of the touch directives do not emit an end event
|
|
// the condition is also checked in the start of function but we avoid the call
|
|
ctx.event !== void 0 && ctx.end();
|
|
|
|
cleanEvt(ctx, 'main');
|
|
cleanEvt(ctx, 'temp');
|
|
|
|
client.is.firefox === true && preventDraggable(el, false);
|
|
ctx.styleCleanup !== void 0 && ctx.styleCleanup();
|
|
|
|
delete el.__qtouchpan;
|
|
}
|
|
}
|
|
|
|
var uid = 0;
|
|
|
|
var TouchPan = {
|
|
name: 'touch-pan',
|
|
|
|
bind: function bind (el, ref) {
|
|
var value = ref.value;
|
|
var modifiers = ref.modifiers;
|
|
|
|
if (el.__qtouchpan !== void 0) {
|
|
destroy$2(el);
|
|
el.__qtouchpan_destroyed = true;
|
|
}
|
|
|
|
// early return, we don't need to do anything
|
|
if (modifiers.mouse !== true && client.has.touch !== true) {
|
|
return
|
|
}
|
|
|
|
function handleEvent (evt, mouseEvent) {
|
|
if (modifiers.mouse === true && mouseEvent === true) {
|
|
stopAndPrevent(evt);
|
|
}
|
|
else {
|
|
modifiers.stop === true && stop(evt);
|
|
modifiers.prevent === true && prevent(evt);
|
|
}
|
|
}
|
|
|
|
var ctx = {
|
|
uid: 'qvtp_' + (uid++),
|
|
handler: value,
|
|
modifiers: modifiers,
|
|
direction: getModifierDirections(modifiers),
|
|
|
|
noop: noop,
|
|
|
|
mouseStart: function mouseStart (evt) {
|
|
if (shouldStart(evt, ctx) && leftClick(evt)) {
|
|
addEvt(ctx, 'temp', [
|
|
[ document, 'mousemove', 'move', 'notPassiveCapture' ],
|
|
[ document, 'mouseup', 'end', 'passiveCapture' ]
|
|
]);
|
|
|
|
ctx.start(evt, true);
|
|
}
|
|
},
|
|
|
|
touchStart: function touchStart (evt) {
|
|
if (shouldStart(evt, ctx)) {
|
|
var target = getTouchTarget(evt.target);
|
|
|
|
addEvt(ctx, 'temp', [
|
|
[ target, 'touchmove', 'move', 'notPassiveCapture' ],
|
|
[ target, 'touchcancel', 'end', 'passiveCapture' ],
|
|
[ target, 'touchend', 'end', 'passiveCapture' ]
|
|
]);
|
|
|
|
ctx.start(evt);
|
|
}
|
|
},
|
|
|
|
start: function start (evt, mouseEvent) {
|
|
client.is.firefox === true && preventDraggable(el, true);
|
|
ctx.lastEvt = evt;
|
|
|
|
var pos = position(evt);
|
|
|
|
/*
|
|
* Stop propagation so possible upper v-touch-pan don't catch this as well;
|
|
* If we're not the target (based on modifiers), we'll re-emit the event later
|
|
*/
|
|
if (mouseEvent === true || modifiers.stop === true) {
|
|
/*
|
|
* are we directly switching to detected state?
|
|
* clone event only otherwise
|
|
*/
|
|
if (
|
|
ctx.direction.all !== true &&
|
|
(mouseEvent !== true || ctx.direction.mouseAllDir !== true)
|
|
) {
|
|
var clone = evt.type.indexOf('mouse') > -1
|
|
? new MouseEvent(evt.type, evt)
|
|
: new TouchEvent(evt.type, evt);
|
|
|
|
evt.defaultPrevented === true && prevent(clone);
|
|
evt.cancelBubble === true && stop(clone);
|
|
|
|
clone.qClonedBy = evt.qClonedBy === void 0
|
|
? [ctx.uid]
|
|
: evt.qClonedBy.concat(ctx.uid);
|
|
clone.qKeyEvent = evt.qKeyEvent;
|
|
clone.qClickOutside = evt.qClickOutside;
|
|
|
|
ctx.initialEvent = {
|
|
target: evt.target,
|
|
event: clone
|
|
};
|
|
}
|
|
|
|
stop(evt);
|
|
}
|
|
|
|
ctx.event = {
|
|
x: pos.left,
|
|
y: pos.top,
|
|
time: Date.now(),
|
|
mouse: mouseEvent === true,
|
|
detected: false,
|
|
isFirst: true,
|
|
isFinal: false,
|
|
lastX: pos.left,
|
|
lastY: pos.top
|
|
};
|
|
},
|
|
|
|
move: function move (evt) {
|
|
if (ctx.event === void 0) {
|
|
return
|
|
}
|
|
|
|
ctx.lastEvt = evt;
|
|
|
|
var isMouseEvt = ctx.event.mouse === true;
|
|
var start = function () {
|
|
handleEvent(evt, isMouseEvt);
|
|
|
|
if (modifiers.preserveCursor !== true) {
|
|
document.documentElement.style.cursor = 'grabbing';
|
|
}
|
|
isMouseEvt === true && document.body.classList.add('no-pointer-events--children');
|
|
document.body.classList.add('non-selectable');
|
|
clearSelection();
|
|
|
|
ctx.styleCleanup = function (withDelayedFn) {
|
|
ctx.styleCleanup = void 0;
|
|
|
|
if (modifiers.preserveCursor !== true) {
|
|
document.documentElement.style.cursor = '';
|
|
}
|
|
document.body.classList.remove('non-selectable');
|
|
|
|
if (isMouseEvt === true) {
|
|
var remove = function () {
|
|
document.body.classList.remove('no-pointer-events--children');
|
|
};
|
|
|
|
if (withDelayedFn !== void 0) {
|
|
setTimeout(function () {
|
|
remove();
|
|
withDelayedFn();
|
|
}, 50);
|
|
}
|
|
else { remove(); }
|
|
}
|
|
else if (withDelayedFn !== void 0) {
|
|
withDelayedFn();
|
|
}
|
|
};
|
|
};
|
|
|
|
if (ctx.event.detected === true) {
|
|
ctx.event.isFirst !== true && handleEvent(evt, ctx.event.mouse);
|
|
|
|
var ref = getChanges(evt, ctx, false);
|
|
var payload = ref.payload;
|
|
var synthetic = ref.synthetic;
|
|
|
|
if (payload !== void 0) {
|
|
if (ctx.handler(payload) === false) {
|
|
ctx.end(evt);
|
|
}
|
|
else {
|
|
if (ctx.styleCleanup === void 0 && ctx.event.isFirst === true) {
|
|
start();
|
|
}
|
|
|
|
ctx.event.lastX = payload.position.left;
|
|
ctx.event.lastY = payload.position.top;
|
|
ctx.event.lastDir = synthetic === true ? void 0 : payload.direction;
|
|
ctx.event.isFirst = false;
|
|
}
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
if (
|
|
ctx.direction.all === true ||
|
|
(isMouseEvt === true && ctx.modifiers.mouseAllDir === true)
|
|
) {
|
|
start();
|
|
ctx.event.detected = true;
|
|
ctx.move(evt);
|
|
return
|
|
}
|
|
|
|
var
|
|
pos = position(evt),
|
|
distX = pos.left - ctx.event.x,
|
|
distY = pos.top - ctx.event.y,
|
|
absX = Math.abs(distX),
|
|
absY = Math.abs(distY);
|
|
|
|
if (absX !== absY) {
|
|
if (
|
|
(ctx.direction.horizontal === true && absX > absY) ||
|
|
(ctx.direction.vertical === true && absX < absY) ||
|
|
(ctx.direction.up === true && absX < absY && distY < 0) ||
|
|
(ctx.direction.down === true && absX < absY && distY > 0) ||
|
|
(ctx.direction.left === true && absX > absY && distX < 0) ||
|
|
(ctx.direction.right === true && absX > absY && distX > 0)
|
|
) {
|
|
ctx.event.detected = true;
|
|
ctx.move(evt);
|
|
}
|
|
else {
|
|
ctx.end(evt, true);
|
|
}
|
|
}
|
|
},
|
|
|
|
end: function end (evt, abort) {
|
|
if (ctx.event === void 0) {
|
|
return
|
|
}
|
|
|
|
cleanEvt(ctx, 'temp');
|
|
client.is.firefox === true && preventDraggable(el, false);
|
|
|
|
if (abort === true) {
|
|
ctx.styleCleanup !== void 0 && ctx.styleCleanup();
|
|
|
|
if (ctx.event.detected !== true && ctx.initialEvent !== void 0) {
|
|
ctx.initialEvent.target.dispatchEvent(ctx.initialEvent.event);
|
|
}
|
|
}
|
|
else if (ctx.event.detected === true) {
|
|
ctx.event.isFirst === true && ctx.handler(getChanges(evt === void 0 ? ctx.lastEvt : evt, ctx).payload);
|
|
|
|
var ref = getChanges(evt === void 0 ? ctx.lastEvt : evt, ctx, true);
|
|
var payload = ref.payload;
|
|
var fn = function () { ctx.handler(payload); };
|
|
|
|
if (ctx.styleCleanup !== void 0) {
|
|
ctx.styleCleanup(fn);
|
|
}
|
|
else {
|
|
fn();
|
|
}
|
|
}
|
|
|
|
ctx.event = void 0;
|
|
ctx.initialEvent = void 0;
|
|
ctx.lastEvt = void 0;
|
|
}
|
|
};
|
|
|
|
el.__qtouchpan = ctx;
|
|
|
|
modifiers.mouse === true && addEvt(ctx, 'main', [
|
|
[ el, 'mousedown', 'mouseStart', ("passive" + (modifiers.mouseCapture === true ? 'Capture' : '')) ]
|
|
]);
|
|
|
|
client.has.touch === true && addEvt(ctx, 'main', [
|
|
[ el, 'touchstart', 'touchStart', ("passive" + (modifiers.capture === true ? 'Capture' : '')) ],
|
|
[ el, 'touchmove', 'noop', 'notPassiveCapture' ]
|
|
]);
|
|
},
|
|
|
|
update: function update (el, ref) {
|
|
var oldValue = ref.oldValue;
|
|
var value = ref.value;
|
|
|
|
var ctx = el.__qtouchpan;
|
|
if (ctx !== void 0 && oldValue !== value) {
|
|
typeof value !== 'function' && ctx.end();
|
|
ctx.handler = value;
|
|
}
|
|
},
|
|
|
|
unbind: function unbind (el) {
|
|
if (el.__qtouchpan_destroyed === void 0) {
|
|
destroy$2(el);
|
|
}
|
|
else {
|
|
delete el.__qtouchpan_destroyed;
|
|
}
|
|
}
|
|
};
|
|
|
|
// PGDOWN, LEFT, DOWN, PGUP, RIGHT, UP
|
|
var keyCodes = [ 34, 37, 40, 33, 39, 38 ];
|
|
|
|
function getRatio (evt, dragging, reverse, vertical) {
|
|
var
|
|
pos = position(evt),
|
|
val = vertical === true
|
|
? between((pos.top - dragging.top) / dragging.height, 0, 1)
|
|
: between((pos.left - dragging.left) / dragging.width, 0, 1);
|
|
|
|
return reverse === true ? 1.0 - val : val
|
|
}
|
|
|
|
function getModel (ratio, min, max, step, decimals) {
|
|
var model = min + ratio * (max - min);
|
|
|
|
if (step > 0) {
|
|
var modulo = (model - min) % step;
|
|
model += (Math.abs(modulo) >= step / 2 ? (modulo < 0 ? -1 : 1) * step : 0) - modulo;
|
|
}
|
|
|
|
if (decimals > 0) {
|
|
model = parseFloat(model.toFixed(decimals));
|
|
}
|
|
|
|
return between(model, min, max)
|
|
}
|
|
|
|
var SliderMixin = {
|
|
mixins: [ DarkMixin, FormMixin ],
|
|
|
|
directives: {
|
|
TouchPan: TouchPan
|
|
},
|
|
|
|
props: {
|
|
min: {
|
|
type: Number,
|
|
default: 0
|
|
},
|
|
max: {
|
|
type: Number,
|
|
default: 100
|
|
},
|
|
step: {
|
|
type: Number,
|
|
default: 1,
|
|
validator: function (v) { return v >= 0; }
|
|
},
|
|
|
|
color: String,
|
|
|
|
labelColor: String,
|
|
labelTextColor: String,
|
|
dense: Boolean,
|
|
|
|
label: Boolean,
|
|
labelAlways: Boolean,
|
|
markers: Boolean,
|
|
snap: Boolean,
|
|
|
|
vertical: Boolean,
|
|
reverse: Boolean,
|
|
|
|
disable: Boolean,
|
|
readonly: Boolean,
|
|
tabindex: [ String, Number ],
|
|
|
|
thumbPath: {
|
|
type: String,
|
|
default: 'M 4, 10 a 6,6 0 1,0 12,0 a 6,6 0 1,0 -12,0'
|
|
}
|
|
},
|
|
|
|
data: function data () {
|
|
return {
|
|
active: false,
|
|
preventFocus: false,
|
|
focus: false
|
|
}
|
|
},
|
|
|
|
computed: {
|
|
axis: function axis () {
|
|
return this.vertical === true ? '--v' : '--h'
|
|
},
|
|
|
|
classes: function classes () {
|
|
return "q-slider q-slider" + (this.axis) + " q-slider--" + (this.active === true ? '' : 'in') + "active" +
|
|
(this.isReversed === true ? ' q-slider--reversed' : '') +
|
|
(this.color !== void 0 ? (" text-" + (this.color)) : '') +
|
|
(this.disable === true ? ' disabled' : ' q-slider--enabled' + (this.editable === true ? ' q-slider--editable' : '')) +
|
|
(this.focus === 'both' ? ' q-slider--focus' : '') +
|
|
(this.label || this.labelAlways === true ? ' q-slider--label' : '') +
|
|
(this.labelAlways === true ? ' q-slider--label-always' : '') +
|
|
(this.isDark === true ? ' q-slider--dark' : '') +
|
|
(this.dense === true ? ' q-slider--dense q-slider--dense' + this.axis : '')
|
|
},
|
|
|
|
editable: function editable () {
|
|
return this.disable !== true && this.readonly !== true
|
|
},
|
|
|
|
decimals: function decimals () {
|
|
return (String(this.step).trim('0').split('.')[1] || '').length
|
|
},
|
|
|
|
computedStep: function computedStep () {
|
|
return this.step === 0 ? 1 : this.step
|
|
},
|
|
|
|
markerStyle: function markerStyle () {
|
|
return {
|
|
backgroundSize: this.vertical === true
|
|
? '2px ' + (100 * this.computedStep / (this.max - this.min)) + '%'
|
|
: (100 * this.computedStep / (this.max - this.min)) + '% 2px'
|
|
}
|
|
},
|
|
|
|
computedTabindex: function computedTabindex () {
|
|
return this.editable === true ? this.tabindex || 0 : -1
|
|
},
|
|
|
|
isReversed: function isReversed () {
|
|
return this.vertical === true
|
|
? this.reverse === true
|
|
: this.reverse !== (this.$q.lang.rtl === true)
|
|
},
|
|
|
|
positionProp: function positionProp () {
|
|
if (this.vertical === true) {
|
|
return this.isReversed === true ? 'bottom' : 'top'
|
|
}
|
|
return this.isReversed === true ? 'right' : 'left'
|
|
},
|
|
|
|
sizeProp: function sizeProp () {
|
|
return this.vertical === true ? 'height' : 'width'
|
|
},
|
|
|
|
orientation: function orientation () {
|
|
return this.vertical === true ? 'vertical' : 'horizontal'
|
|
},
|
|
|
|
attrs: function attrs () {
|
|
var attrs = {
|
|
role: 'slider',
|
|
'aria-valuemin': this.min,
|
|
'aria-valuemax': this.max,
|
|
'aria-orientation': this.orientation,
|
|
'data-step': this.step
|
|
};
|
|
|
|
if (this.disable === true) {
|
|
attrs['aria-disabled'] = 'true';
|
|
}
|
|
else if (this.readonly === true) {
|
|
attrs['aria-readonly'] = 'true';
|
|
}
|
|
|
|
return attrs
|
|
},
|
|
|
|
panDirectives: function panDirectives () {
|
|
var obj;
|
|
|
|
return this.editable === true
|
|
? [{
|
|
name: 'touch-pan',
|
|
value: this.__pan,
|
|
modifiers: ( obj = {}, obj[ this.orientation ] = true, obj.prevent = true, obj.stop = true, obj.mouse = true, obj.mouseAllDir = true, obj )
|
|
}]
|
|
: null
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
__getThumbSvg: function __getThumbSvg (h) {
|
|
return h('svg', {
|
|
staticClass: 'q-slider__thumb absolute',
|
|
attrs: {
|
|
focusable: 'false', /* needed for IE11 */
|
|
viewBox: '0 0 20 20',
|
|
width: '20',
|
|
height: '20',
|
|
'aria-hidden': 'true'
|
|
}
|
|
}, [
|
|
h('path', {
|
|
attrs: {
|
|
d: this.thumbPath
|
|
}
|
|
})
|
|
])
|
|
},
|
|
|
|
__getPinStyle: function __getPinStyle (percent, ratio) {
|
|
var obj;
|
|
|
|
if (this.vertical === true) {
|
|
return {}
|
|
}
|
|
|
|
var offset = (Math.ceil(20 * Math.abs(0.5 - ratio))) + "px";
|
|
return {
|
|
pin: {
|
|
transformOrigin: ((this.$q.lang.rtl === true ? offset : (this.$q.platform.is.ie === true ? '100%' : ("calc(100% - " + offset + ")"))) + " 50%")
|
|
},
|
|
|
|
pinTextContainer: ( obj = {}, obj[this.$q.lang.rtl === true ? 'left' : 'right'] = ((percent * 100) + "%"), obj.transform = ("translateX(" + (Math.ceil((this.$q.lang.rtl === true ? -1 : 1) * 20 * percent)) + "px)"), obj )
|
|
}
|
|
},
|
|
|
|
__pan: function __pan (event) {
|
|
if (event.isFinal) {
|
|
if (this.dragging !== void 0) {
|
|
this.__updatePosition(event.evt);
|
|
// only if touch, because we also have mousedown/up:
|
|
event.touch === true && this.__updateValue(true);
|
|
this.dragging = void 0;
|
|
}
|
|
this.active = false;
|
|
}
|
|
else if (event.isFirst) {
|
|
this.dragging = this.__getDragging(event.evt);
|
|
this.__updatePosition(event.evt);
|
|
this.__updateValue();
|
|
this.active = true;
|
|
}
|
|
else {
|
|
this.__updatePosition(event.evt);
|
|
this.__updateValue();
|
|
}
|
|
},
|
|
|
|
__blur: function __blur () {
|
|
this.focus = false;
|
|
},
|
|
|
|
__activate: function __activate (evt) {
|
|
this.__updatePosition(evt, this.__getDragging(evt));
|
|
this.__updateValue();
|
|
|
|
this.preventFocus = true;
|
|
this.active = true;
|
|
|
|
document.addEventListener('mouseup', this.__deactivate, true);
|
|
},
|
|
|
|
__deactivate: function __deactivate () {
|
|
this.preventFocus = false;
|
|
|
|
if (this.dragging === void 0) {
|
|
this.active = false;
|
|
}
|
|
|
|
this.__updateValue(true);
|
|
this.__blur();
|
|
|
|
document.removeEventListener('mouseup', this.__deactivate, true);
|
|
},
|
|
|
|
__mobileClick: function __mobileClick (evt) {
|
|
this.__updatePosition(evt, this.__getDragging(evt));
|
|
this.__updateValue(true);
|
|
},
|
|
|
|
__keyup: function __keyup (evt) {
|
|
if (keyCodes.includes(evt.keyCode)) {
|
|
this.__updateValue(true);
|
|
}
|
|
}
|
|
},
|
|
|
|
beforeDestroy: function beforeDestroy () {
|
|
document.removeEventListener('mouseup', this.__deactivate, true);
|
|
}
|
|
};
|
|
|
|
var QSlider = Vue.extend({
|
|
name: 'QSlider',
|
|
|
|
mixins: [ SliderMixin ],
|
|
|
|
props: {
|
|
value: {
|
|
required: true,
|
|
default: null,
|
|
validator: function (v) { return typeof v === 'number' || v === null; }
|
|
},
|
|
|
|
labelValue: [ String, Number ]
|
|
},
|
|
|
|
data: function data () {
|
|
return {
|
|
model: this.value === null ? this.min : this.value,
|
|
curRatio: 0
|
|
}
|
|
},
|
|
|
|
watch: {
|
|
value: function value (v) {
|
|
this.model = v === null
|
|
? 0
|
|
: between(v, this.min, this.max);
|
|
},
|
|
|
|
min: function min (v) {
|
|
this.model = between(this.model, v, this.max);
|
|
},
|
|
|
|
max: function max (v) {
|
|
this.model = between(this.model, this.min, v);
|
|
}
|
|
},
|
|
|
|
computed: {
|
|
ratio: function ratio () {
|
|
return this.active === true ? this.curRatio : this.modelRatio
|
|
},
|
|
|
|
modelRatio: function modelRatio () {
|
|
return (this.model - this.min) / (this.max - this.min)
|
|
},
|
|
|
|
trackStyle: function trackStyle () {
|
|
var obj;
|
|
|
|
return ( obj = {}, obj[ this.positionProp ] = 0, obj[ this.sizeProp ] = ((100 * this.ratio) + "%"), obj )
|
|
},
|
|
|
|
thumbStyle: function thumbStyle () {
|
|
var obj;
|
|
|
|
return ( obj = {}, obj[ this.positionProp ] = ((100 * this.ratio) + "%"), obj )
|
|
},
|
|
|
|
thumbClass: function thumbClass () {
|
|
if (this.preventFocus === false && this.focus === true) {
|
|
return 'q-slider--focus'
|
|
}
|
|
},
|
|
|
|
pinClass: function pinClass () {
|
|
if (this.labelColor !== void 0) {
|
|
return ("text-" + (this.labelColor))
|
|
}
|
|
},
|
|
|
|
pinTextClass: function pinTextClass () {
|
|
return 'q-slider__pin-value-marker-text' +
|
|
(this.labelTextColor !== void 0 ? (" text-" + (this.labelTextColor)) : '')
|
|
},
|
|
|
|
events: function events () {
|
|
if (this.editable === true) {
|
|
return this.$q.platform.is.mobile === true
|
|
? { click: this.__mobileClick }
|
|
: {
|
|
mousedown: this.__activate,
|
|
focus: this.__focus,
|
|
blur: this.__blur,
|
|
keydown: this.__keydown,
|
|
keyup: this.__keyup
|
|
}
|
|
}
|
|
},
|
|
|
|
computedLabel: function computedLabel () {
|
|
return this.labelValue !== void 0
|
|
? this.labelValue
|
|
: this.model
|
|
},
|
|
|
|
pinStyle: function pinStyle () {
|
|
var percent = (this.reverse === true ? -this.ratio : this.ratio - 1);
|
|
return this.__getPinStyle(percent, this.ratio)
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
__updateValue: function __updateValue (change) {
|
|
if (this.model !== this.value) {
|
|
this.$emit('input', this.model);
|
|
}
|
|
change === true && this.$emit('change', this.model);
|
|
},
|
|
|
|
__getDragging: function __getDragging () {
|
|
return this.$el.getBoundingClientRect()
|
|
},
|
|
|
|
__updatePosition: function __updatePosition (event, dragging) {
|
|
if ( dragging === void 0 ) dragging = this.dragging;
|
|
|
|
var ratio = getRatio(
|
|
event,
|
|
dragging,
|
|
this.isReversed,
|
|
this.vertical
|
|
);
|
|
|
|
this.model = getModel(ratio, this.min, this.max, this.step, this.decimals);
|
|
this.curRatio = this.snap !== true || this.step === 0
|
|
? ratio
|
|
: (this.model - this.min) / (this.max - this.min);
|
|
},
|
|
|
|
__focus: function __focus () {
|
|
this.focus = true;
|
|
},
|
|
|
|
__keydown: function __keydown (evt) {
|
|
if (!keyCodes.includes(evt.keyCode)) {
|
|
return
|
|
}
|
|
|
|
stopAndPrevent(evt);
|
|
|
|
var
|
|
step = ([34, 33].includes(evt.keyCode) ? 10 : 1) * this.computedStep,
|
|
offset = [34, 37, 40].includes(evt.keyCode) ? -step : step;
|
|
|
|
this.model = between(
|
|
parseFloat((this.model + offset).toFixed(this.decimals)),
|
|
this.min,
|
|
this.max
|
|
);
|
|
|
|
this.__updateValue();
|
|
}
|
|
},
|
|
|
|
render: function render (h) {
|
|
var child = [
|
|
this.__getThumbSvg(h),
|
|
h('div', { staticClass: 'q-slider__focus-ring' })
|
|
];
|
|
|
|
if (this.label === true || this.labelAlways === true) {
|
|
child.push(
|
|
h('div', {
|
|
staticClass: ("q-slider__pin q-slider__pin" + (this.axis) + " absolute"),
|
|
style: this.pinStyle.pin,
|
|
class: this.pinClass
|
|
}, [
|
|
h('div', {
|
|
staticClass: ("q-slider__pin-text-container q-slider__pin-text-container" + (this.axis)),
|
|
style: this.pinStyle.pinTextContainer
|
|
}, [
|
|
h('span', {
|
|
staticClass: 'q-slider__pin-text',
|
|
class: this.pinTextClass
|
|
}, [
|
|
this.computedLabel
|
|
])
|
|
])
|
|
]),
|
|
|
|
h('div', {
|
|
staticClass: ("q-slider__arrow q-slider__arrow" + (this.axis)),
|
|
class: this.pinClass
|
|
})
|
|
);
|
|
}
|
|
|
|
if (this.name !== void 0 && this.disable !== true) {
|
|
this.__injectFormInput(child, 'push');
|
|
}
|
|
|
|
var track = [
|
|
h('div', {
|
|
staticClass: ("q-slider__track q-slider__track" + (this.axis) + " absolute"),
|
|
style: this.trackStyle
|
|
})
|
|
];
|
|
|
|
this.markers === true && track.push(
|
|
h('div', {
|
|
staticClass: ("q-slider__track-markers q-slider__track-markers" + (this.axis) + " absolute-full fit"),
|
|
style: this.markerStyle
|
|
})
|
|
);
|
|
|
|
return h('div', {
|
|
staticClass: this.value === null ? ' q-slider--no-value' : '',
|
|
attrs: Object.assign({}, this.attrs,
|
|
{'aria-valuenow': this.value,
|
|
tabindex: this.computedTabindex}),
|
|
class: this.classes,
|
|
on: this.events,
|
|
directives: this.panDirectives
|
|
}, [
|
|
h('div', {
|
|
staticClass: ("q-slider__track-container q-slider__track-container" + (this.axis) + " absolute")
|
|
}, track),
|
|
|
|
h('div', {
|
|
staticClass: ("q-slider__thumb-container q-slider__thumb-container" + (this.axis) + " absolute non-selectable"),
|
|
class: this.thumbClass,
|
|
style: this.thumbStyle
|
|
}, child)
|
|
])
|
|
}
|
|
});
|
|
|
|
// using it to manage SSR rendering with best performance
|
|
|
|
var CanRenderMixin = {
|
|
data: function data () {
|
|
return {
|
|
canRender: !onSSR
|
|
}
|
|
},
|
|
|
|
mounted: function mounted () {
|
|
this.canRender === false && (this.canRender = true);
|
|
}
|
|
};
|
|
|
|
var QResizeObserver = Vue.extend({
|
|
name: 'QResizeObserver',
|
|
|
|
mixins: [ CanRenderMixin ],
|
|
|
|
props: {
|
|
debounce: {
|
|
type: [ String, Number ],
|
|
default: 100
|
|
}
|
|
},
|
|
|
|
data: function data () {
|
|
return this.hasObserver === true
|
|
? {}
|
|
: { url: this.$q.platform.is.ie === true ? null : 'about:blank' }
|
|
},
|
|
|
|
methods: {
|
|
trigger: function trigger (now) {
|
|
if (now === true || this.debounce === 0 || this.debounce === '0') {
|
|
this.__onResize();
|
|
}
|
|
else if (!this.timer) {
|
|
this.timer = setTimeout(this.__onResize, this.debounce);
|
|
}
|
|
},
|
|
|
|
__onResize: function __onResize () {
|
|
this.timer = null;
|
|
|
|
if (!this.$el || !this.$el.parentNode) {
|
|
return
|
|
}
|
|
|
|
var
|
|
parent = this.$el.parentNode,
|
|
size = {
|
|
width: parent.offsetWidth,
|
|
height: parent.offsetHeight
|
|
};
|
|
|
|
if (size.width === this.size.width && size.height === this.size.height) {
|
|
return
|
|
}
|
|
|
|
this.size = size;
|
|
this.$emit('resize', this.size);
|
|
},
|
|
|
|
__cleanup: function __cleanup () {
|
|
if (this.curDocView !== void 0) {
|
|
// iOS is fuzzy, need to check it first
|
|
if (this.curDocView.removeEventListener !== void 0) {
|
|
this.curDocView.removeEventListener('resize', this.trigger, listenOpts.passive);
|
|
}
|
|
this.curDocView = void 0;
|
|
}
|
|
},
|
|
|
|
__onObjLoad: function __onObjLoad () {
|
|
this.__cleanup();
|
|
|
|
if (this.$el.contentDocument) {
|
|
this.curDocView = this.$el.contentDocument.defaultView;
|
|
this.curDocView.addEventListener('resize', this.trigger, listenOpts.passive);
|
|
}
|
|
|
|
this.__onResize();
|
|
}
|
|
},
|
|
|
|
render: function render (h) {
|
|
if (this.canRender === false || this.hasObserver === true) {
|
|
return
|
|
}
|
|
|
|
return h('object', {
|
|
style: this.style,
|
|
attrs: {
|
|
tabindex: -1, // fix for Firefox
|
|
type: 'text/html',
|
|
data: this.url,
|
|
'aria-hidden': 'true'
|
|
},
|
|
on: cache(this, 'load', {
|
|
load: this.__onObjLoad
|
|
})
|
|
})
|
|
},
|
|
|
|
beforeCreate: function beforeCreate () {
|
|
this.size = { width: -1, height: -1 };
|
|
if (isSSR === true) { return }
|
|
|
|
this.hasObserver = typeof ResizeObserver !== 'undefined';
|
|
|
|
if (this.hasObserver !== true) {
|
|
this.style = (this.$q.platform.is.ie ? 'visibility:hidden;' : '') + "display:block;position:absolute;top:0;left:0;right:0;bottom:0;height:100%;width:100%;overflow:hidden;pointer-events:none;z-index:-1;";
|
|
}
|
|
},
|
|
|
|
mounted: function mounted () {
|
|
if (this.hasObserver === true) {
|
|
this.observer = new ResizeObserver(this.trigger);
|
|
this.observer.observe(this.$el.parentNode);
|
|
this.__onResize();
|
|
return
|
|
}
|
|
|
|
if (this.$q.platform.is.ie === true) {
|
|
this.url = 'about:blank';
|
|
this.__onResize();
|
|
}
|
|
else {
|
|
this.__onObjLoad();
|
|
}
|
|
},
|
|
|
|
beforeDestroy: function beforeDestroy () {
|
|
clearTimeout(this.timer);
|
|
|
|
if (this.hasObserver === true) {
|
|
if (this.observer !== void 0 && this.$el.parentNode) {
|
|
this.observer.unobserve(this.$el.parentNode);
|
|
}
|
|
return
|
|
}
|
|
|
|
this.__cleanup();
|
|
}
|
|
});
|
|
|
|
function getIndicatorClass (color, top, vertical) {
|
|
var pos = vertical === true
|
|
? ['left', 'right']
|
|
: ['top', 'bottom'];
|
|
|
|
return ("absolute-" + (top === true ? pos[0] : pos[1]) + (color ? (" text-" + color) : ''))
|
|
}
|
|
|
|
function bufferPrioritySort (t1, t2) {
|
|
if (t1.priorityMatched === t2.priorityMatched) {
|
|
return t2.priorityHref - t1.priorityHref
|
|
}
|
|
return t2.priorityMatched - t1.priorityMatched
|
|
}
|
|
|
|
function bufferCleanSelected (t) {
|
|
t.selected = false;
|
|
return t
|
|
}
|
|
|
|
var
|
|
bufferFilters = [
|
|
function (t) { return t.selected === true && t.exact === true && t.redirected !== true; },
|
|
function (t) { return t.selected === true && t.exact === true; },
|
|
function (t) { return t.selected === true && t.redirected !== true; },
|
|
function (t) { return t.selected === true; },
|
|
function (t) { return t.exact === true && t.redirected !== true; },
|
|
function (t) { return t.redirected !== true; },
|
|
function (t) { return t.exact === true; },
|
|
function (t) { return true; }
|
|
],
|
|
bufferFiltersLen = bufferFilters.length;
|
|
|
|
var QTabs = Vue.extend({
|
|
name: 'QTabs',
|
|
|
|
mixins: [ TimeoutMixin, ListenersMixin ],
|
|
|
|
provide: function provide () {
|
|
return {
|
|
tabs: this.tabs,
|
|
__recalculateScroll: this.__recalculateScroll,
|
|
__activateTab: this.__activateTab,
|
|
__activateRoute: this.__activateRoute
|
|
}
|
|
},
|
|
|
|
props: {
|
|
value: [Number, String],
|
|
|
|
align: {
|
|
type: String,
|
|
default: 'center',
|
|
validator: function (v) { return ['left', 'center', 'right', 'justify'].includes(v); }
|
|
},
|
|
breakpoint: {
|
|
type: [String, Number],
|
|
default: 600
|
|
},
|
|
|
|
vertical: Boolean,
|
|
shrink: Boolean,
|
|
stretch: Boolean,
|
|
|
|
activeColor: String,
|
|
activeBgColor: String,
|
|
indicatorColor: String,
|
|
leftIcon: String,
|
|
rightIcon: String,
|
|
|
|
outsideArrows: Boolean,
|
|
mobileArrows: Boolean,
|
|
|
|
switchIndicator: Boolean,
|
|
|
|
narrowIndicator: Boolean,
|
|
inlineLabel: Boolean,
|
|
noCaps: Boolean,
|
|
|
|
dense: Boolean,
|
|
|
|
contentClass: String
|
|
},
|
|
|
|
data: function data () {
|
|
return {
|
|
tabs: {
|
|
current: this.value,
|
|
activeColor: this.activeColor,
|
|
activeBgColor: this.activeBgColor,
|
|
indicatorClass: getIndicatorClass(
|
|
this.indicatorColor,
|
|
this.switchIndicator,
|
|
this.vertical
|
|
),
|
|
narrowIndicator: this.narrowIndicator,
|
|
inlineLabel: this.inlineLabel,
|
|
noCaps: this.noCaps
|
|
},
|
|
scrollable: false,
|
|
leftArrow: true,
|
|
rightArrow: false,
|
|
justify: false
|
|
}
|
|
},
|
|
|
|
watch: {
|
|
value: function value (name) {
|
|
this.__activateTab(name, true, true);
|
|
},
|
|
|
|
activeColor: function activeColor (v) {
|
|
this.tabs.activeColor = v;
|
|
},
|
|
|
|
activeBgColor: function activeBgColor (v) {
|
|
this.tabs.activeBgColor = v;
|
|
},
|
|
|
|
vertical: function vertical (v) {
|
|
this.tabs.indicatorClass = getIndicatorClass(this.indicatorColor, this.switchIndicator, v);
|
|
},
|
|
|
|
indicatorColor: function indicatorColor (v) {
|
|
this.tabs.indicatorClass = getIndicatorClass(v, this.switchIndicator, this.vertical);
|
|
},
|
|
|
|
switchIndicator: function switchIndicator (v) {
|
|
this.tabs.indicatorClass = getIndicatorClass(this.indicatorColor, v, this.vertical);
|
|
},
|
|
|
|
narrowIndicator: function narrowIndicator (v) {
|
|
this.tabs.narrowIndicator = v;
|
|
},
|
|
|
|
inlineLabel: function inlineLabel (v) {
|
|
this.tabs.inlineLabel = v;
|
|
},
|
|
|
|
noCaps: function noCaps (v) {
|
|
this.tabs.noCaps = v;
|
|
},
|
|
|
|
outsideArrows: function outsideArrows () {
|
|
this.$nextTick(this.__recalculateScroll());
|
|
},
|
|
|
|
arrowsEnabled: function arrowsEnabled (v) {
|
|
this.__updateArrows = v === true
|
|
? this.__updateArrowsFn
|
|
: noop;
|
|
|
|
this.$nextTick(this.__recalculateScroll());
|
|
}
|
|
},
|
|
|
|
computed: {
|
|
arrowsEnabled: function arrowsEnabled () {
|
|
return this.$q.platform.is.desktop === true || this.mobileArrows === true
|
|
},
|
|
|
|
alignClass: function alignClass () {
|
|
var align = this.scrollable === true
|
|
? 'left'
|
|
: (this.justify === true ? 'justify' : this.align);
|
|
|
|
return ("q-tabs__content--align-" + align)
|
|
},
|
|
|
|
classes: function classes () {
|
|
return "q-tabs--" + (this.scrollable === true ? '' : 'not-') + "scrollable" +
|
|
" q-tabs--" + (this.vertical === true ? 'vertical' : 'horizontal') +
|
|
" q-tabs__arrows--" + (this.arrowsEnabled === true && this.outsideArrows === true ? 'outside' : 'inside') +
|
|
(this.dense === true ? ' q-tabs--dense' : '') +
|
|
(this.shrink === true ? ' col-shrink' : '') +
|
|
(this.stretch === true ? ' self-stretch' : '')
|
|
},
|
|
|
|
innerClass: function innerClass () {
|
|
return this.alignClass + (this.contentClass !== void 0 ? (" " + (this.contentClass)) : '')
|
|
},
|
|
|
|
domProps: function domProps () {
|
|
return this.vertical === true
|
|
? { container: 'height', content: 'scrollHeight', posLeft: 'top', posRight: 'bottom' }
|
|
: { container: 'width', content: 'scrollWidth', posLeft: 'left', posRight: 'right' }
|
|
},
|
|
|
|
onEvents: function onEvents () {
|
|
return Object.assign({}, {input: stop},
|
|
this.qListeners)
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
__activateTab: function __activateTab (name, setCurrent, skipEmit) {
|
|
if (this.tabs.current !== name) {
|
|
skipEmit !== true && this.$emit('input', name);
|
|
if (setCurrent === true || this.qListeners.input === void 0) {
|
|
this.__animate(this.tabs.current, name);
|
|
this.tabs.current = name;
|
|
}
|
|
}
|
|
},
|
|
|
|
__activateRoute: function __activateRoute (params) {
|
|
var this$1 = this;
|
|
|
|
if (this.bufferRoute !== this.$route && this.buffer.length > 0) {
|
|
clearTimeout(this.bufferTimer);
|
|
this.bufferTimer = void 0;
|
|
this.buffer.length = 0;
|
|
}
|
|
this.bufferRoute = this.$route;
|
|
|
|
if (params !== void 0) {
|
|
if (params.remove === true) {
|
|
this.buffer = this.buffer.filter(function (t) { return t.name !== params.name; });
|
|
}
|
|
else {
|
|
this.buffer.push(params);
|
|
}
|
|
}
|
|
|
|
if (this.bufferTimer === void 0) {
|
|
this.bufferTimer = setTimeout(function () {
|
|
var tabs = [];
|
|
|
|
for (var i = 0; i < bufferFiltersLen && tabs.length === 0; i++) {
|
|
tabs = this$1.buffer.filter(bufferFilters[i]);
|
|
}
|
|
|
|
tabs.sort(bufferPrioritySort);
|
|
this$1.__activateTab(tabs.length === 0 ? null : tabs[0].name, true);
|
|
this$1.buffer = this$1.buffer.map(bufferCleanSelected);
|
|
this$1.bufferTimer = void 0;
|
|
}, 1);
|
|
}
|
|
},
|
|
|
|
__recalculateScroll: function __recalculateScroll () {
|
|
var this$1 = this;
|
|
|
|
this.__nextTick(function () {
|
|
this$1._isDestroyed !== true && this$1.__updateContainer({
|
|
width: this$1.$el.offsetWidth,
|
|
height: this$1.$el.offsetHeight
|
|
});
|
|
});
|
|
|
|
this.__prepareTick();
|
|
},
|
|
|
|
__updateContainer: function __updateContainer (domSize) {
|
|
var this$1 = this;
|
|
|
|
var
|
|
size = domSize[this.domProps.container],
|
|
scrollSize = this.$refs.content[this.domProps.content],
|
|
scroll = size > 0 && scrollSize > size; // when there is no tab, in Chrome, size === 0 and scrollSize === 1
|
|
|
|
if (this.scrollable !== scroll) {
|
|
this.scrollable = scroll;
|
|
}
|
|
|
|
// Arrows need to be updated even if the scroll status was already true
|
|
scroll === true && this.$nextTick(function () { return this$1.__updateArrows(); });
|
|
|
|
var justify = size < parseInt(this.breakpoint, 10);
|
|
|
|
if (this.justify !== justify) {
|
|
this.justify = justify;
|
|
}
|
|
},
|
|
|
|
__animate: function __animate (oldName, newName) {
|
|
var this$1 = this;
|
|
|
|
var
|
|
oldTab = oldName !== void 0 && oldName !== null && oldName !== ''
|
|
? this.$children.find(function (tab) { return tab.name === oldName; })
|
|
: null,
|
|
newTab = newName !== void 0 && newName !== null && newName !== ''
|
|
? this.$children.find(function (tab) { return tab.name === newName; })
|
|
: null;
|
|
|
|
if (oldTab && newTab) {
|
|
var
|
|
oldEl = oldTab.$el.getElementsByClassName('q-tab__indicator')[0],
|
|
newEl = newTab.$el.getElementsByClassName('q-tab__indicator')[0];
|
|
|
|
clearTimeout(this.animateTimer);
|
|
|
|
oldEl.style.transition = 'none';
|
|
oldEl.style.transform = 'none';
|
|
newEl.style.transition = 'none';
|
|
newEl.style.transform = 'none';
|
|
|
|
var
|
|
oldPos = oldEl.getBoundingClientRect(),
|
|
newPos = newEl.getBoundingClientRect();
|
|
|
|
newEl.style.transform = this.vertical === true
|
|
? ("translate3d(0," + (oldPos.top - newPos.top) + "px,0) scale3d(1," + (newPos.height ? oldPos.height / newPos.height : 1) + ",1)")
|
|
: ("translate3d(" + (oldPos.left - newPos.left) + "px,0,0) scale3d(" + (newPos.width ? oldPos.width / newPos.width : 1) + ",1,1)");
|
|
|
|
// allow scope updates to kick in (QRouteTab needs more time)
|
|
this.$nextTick(function () {
|
|
this$1.animateTimer = setTimeout(function () {
|
|
newEl.style.transition = 'transform .25s cubic-bezier(.4, 0, .2, 1)';
|
|
newEl.style.transform = 'none';
|
|
}, 70);
|
|
});
|
|
}
|
|
|
|
if (newTab && this.scrollable === true) {
|
|
var ref = this.$refs.content.getBoundingClientRect();
|
|
var left = ref.left;
|
|
var width = ref.width;
|
|
var top = ref.top;
|
|
var height = ref.height;
|
|
var newPos$1 = newTab.$el.getBoundingClientRect();
|
|
|
|
var offset = this.vertical === true ? newPos$1.top - top : newPos$1.left - left;
|
|
|
|
if (offset < 0) {
|
|
this.$refs.content[this.vertical === true ? 'scrollTop' : 'scrollLeft'] += Math.floor(offset);
|
|
this.__updateArrows();
|
|
return
|
|
}
|
|
|
|
offset += this.vertical === true ? newPos$1.height - height : newPos$1.width - width;
|
|
if (offset > 0) {
|
|
this.$refs.content[this.vertical === true ? 'scrollTop' : 'scrollLeft'] += Math.ceil(offset);
|
|
this.__updateArrows();
|
|
}
|
|
}
|
|
},
|
|
|
|
__updateArrowsFn: function __updateArrowsFn () {
|
|
var
|
|
content = this.$refs.content,
|
|
rect = content.getBoundingClientRect(),
|
|
pos = this.vertical === true ? content.scrollTop : content.scrollLeft;
|
|
|
|
this.leftArrow = pos > 0;
|
|
this.rightArrow = this.vertical === true
|
|
? Math.ceil(pos + rect.height) < content.scrollHeight
|
|
: Math.ceil(pos + rect.width) < content.scrollWidth;
|
|
},
|
|
|
|
__animScrollTo: function __animScrollTo (value) {
|
|
var this$1 = this;
|
|
|
|
this.__stopAnimScroll();
|
|
this.__scrollTowards(value);
|
|
|
|
this.scrollTimer = setInterval(function () {
|
|
if (this$1.__scrollTowards(value)) {
|
|
this$1.__stopAnimScroll();
|
|
}
|
|
}, 5);
|
|
},
|
|
|
|
__scrollToStart: function __scrollToStart () {
|
|
this.__animScrollTo(0);
|
|
},
|
|
|
|
__scrollToEnd: function __scrollToEnd () {
|
|
this.__animScrollTo(9999);
|
|
},
|
|
|
|
__stopAnimScroll: function __stopAnimScroll () {
|
|
clearInterval(this.scrollTimer);
|
|
},
|
|
|
|
__scrollTowards: function __scrollTowards (value) {
|
|
var content = this.$refs.content;
|
|
var
|
|
pos = this.vertical === true ? content.scrollTop : content.scrollLeft,
|
|
done = false;
|
|
var direction = value < pos ? -1 : 1;
|
|
|
|
pos += direction * 5;
|
|
if (pos < 0) {
|
|
done = true;
|
|
pos = 0;
|
|
}
|
|
else if (
|
|
(direction === -1 && pos <= value) ||
|
|
(direction === 1 && pos >= value)
|
|
) {
|
|
done = true;
|
|
pos = value;
|
|
}
|
|
|
|
content[this.vertical === true ? 'scrollTop' : 'scrollLeft'] = pos;
|
|
this.__updateArrows();
|
|
return done
|
|
}
|
|
},
|
|
|
|
created: function created () {
|
|
this.buffer = [];
|
|
this.__updateArrows = this.arrowsEnabled === true
|
|
? this.__updateArrowsFn
|
|
: noop;
|
|
},
|
|
|
|
beforeDestroy: function beforeDestroy () {
|
|
clearTimeout(this.bufferTimer);
|
|
clearTimeout(this.animateTimer);
|
|
},
|
|
|
|
render: function render (h) {
|
|
var child = [
|
|
h(QResizeObserver, {
|
|
on: cache(this, 'resize', { resize: this.__updateContainer })
|
|
}),
|
|
|
|
h('div', {
|
|
ref: 'content',
|
|
staticClass: 'q-tabs__content row no-wrap items-center self-stretch hide-scrollbar',
|
|
class: this.innerClass
|
|
}, slot(this, 'default'))
|
|
];
|
|
|
|
this.arrowsEnabled === true && child.push(
|
|
h(QIcon, {
|
|
staticClass: 'q-tabs__arrow q-tabs__arrow--left absolute q-tab__icon',
|
|
class: this.leftArrow === true ? '' : 'q-tabs__arrow--faded',
|
|
props: { name: this.leftIcon || (this.vertical === true ? this.$q.iconSet.tabs.up : this.$q.iconSet.tabs.left) },
|
|
on: cache(this, 'onL', {
|
|
mousedown: this.__scrollToStart,
|
|
touchstart: this.__scrollToStart,
|
|
mouseup: this.__stopAnimScroll,
|
|
mouseleave: this.__stopAnimScroll,
|
|
touchend: this.__stopAnimScroll
|
|
})
|
|
}),
|
|
|
|
h(QIcon, {
|
|
staticClass: 'q-tabs__arrow q-tabs__arrow--right absolute q-tab__icon',
|
|
class: this.rightArrow === true ? '' : 'q-tabs__arrow--faded',
|
|
props: { name: this.rightIcon || (this.vertical === true ? this.$q.iconSet.tabs.down : this.$q.iconSet.tabs.right) },
|
|
on: cache(this, 'onR', {
|
|
mousedown: this.__scrollToEnd,
|
|
touchstart: this.__scrollToEnd,
|
|
mouseup: this.__stopAnimScroll,
|
|
mouseleave: this.__stopAnimScroll,
|
|
touchend: this.__stopAnimScroll
|
|
})
|
|
})
|
|
);
|
|
|
|
return h('div', {
|
|
staticClass: 'q-tabs row no-wrap items-center',
|
|
class: this.classes,
|
|
on: this.onEvents,
|
|
attrs: { role: 'tablist' }
|
|
}, child)
|
|
}
|
|
});
|
|
|
|
var uid$1 = 0;
|
|
|
|
var QTab = Vue.extend({
|
|
name: 'QTab',
|
|
|
|
mixins: [ RippleMixin, ListenersMixin ],
|
|
|
|
inject: {
|
|
tabs: {
|
|
default: function default$1 () {
|
|
console.error('QTab/QRouteTab components need to be child of QTabs');
|
|
}
|
|
},
|
|
__activateTab: {},
|
|
__recalculateScroll: {}
|
|
},
|
|
|
|
props: {
|
|
icon: String,
|
|
label: [Number, String],
|
|
|
|
alert: [Boolean, String],
|
|
alertIcon: String,
|
|
|
|
name: {
|
|
type: [Number, String],
|
|
default: function () { return ("t_" + (uid$1++)); }
|
|
},
|
|
|
|
noCaps: Boolean,
|
|
|
|
tabindex: [String, Number],
|
|
disable: Boolean,
|
|
|
|
contentClass: String
|
|
},
|
|
|
|
computed: {
|
|
isActive: function isActive () {
|
|
return this.tabs.current === this.name
|
|
},
|
|
|
|
classes: function classes () {
|
|
var obj;
|
|
|
|
return ( obj = {}, obj[("q-tab--" + (this.isActive ? '' : 'in') + "active")] = true, obj[("text-" + (this.tabs.activeColor))] = this.isActive && this.tabs.activeColor, obj[("bg-" + (this.tabs.activeBgColor))] = this.isActive && this.tabs.activeBgColor, obj['q-tab--full'] = this.icon && this.label && !this.tabs.inlineLabel, obj['q-tab--no-caps'] = this.noCaps === true || this.tabs.noCaps === true, obj['q-focusable q-hoverable cursor-pointer'] = !this.disable, obj.disabled = this.disable, obj )
|
|
},
|
|
|
|
innerClass: function innerClass () {
|
|
return (this.tabs.inlineLabel === true ? 'row no-wrap q-tab__content--inline' : 'column') +
|
|
(this.contentClass !== void 0 ? (" " + (this.contentClass)) : '')
|
|
},
|
|
|
|
computedTabIndex: function computedTabIndex () {
|
|
return this.disable === true || this.isActive === true ? -1 : this.tabindex || 0
|
|
},
|
|
|
|
onEvents: function onEvents () {
|
|
return Object.assign({}, {input: stop},
|
|
this.qListeners,
|
|
{click: this.__activate,
|
|
keyup: this.__onKeyup})
|
|
},
|
|
|
|
attrs: function attrs () {
|
|
var attrs = {
|
|
tabindex: this.computedTabIndex,
|
|
role: 'tab',
|
|
'aria-selected': this.isActive
|
|
};
|
|
|
|
if (this.disable === true) {
|
|
attrs['aria-disabled'] = 'true';
|
|
}
|
|
|
|
return attrs
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
__activate: function __activate (e, keyboard) {
|
|
keyboard !== true && this.$refs.blurTarget !== void 0 && this.$refs.blurTarget.focus();
|
|
|
|
if (this.disable !== true) {
|
|
this.qListeners.click !== void 0 && this.$emit('click', e);
|
|
this.__activateTab(this.name);
|
|
}
|
|
},
|
|
|
|
__onKeyup: function __onKeyup (e) {
|
|
isKeyCode(e, 13) === true && this.__activate(e, true);
|
|
},
|
|
|
|
__getContent: function __getContent (h) {
|
|
var
|
|
narrow = this.tabs.narrowIndicator,
|
|
content = [],
|
|
indicator = h('div', {
|
|
staticClass: 'q-tab__indicator',
|
|
class: this.tabs.indicatorClass
|
|
});
|
|
|
|
this.icon !== void 0 && content.push(
|
|
h(QIcon, {
|
|
staticClass: 'q-tab__icon',
|
|
props: { name: this.icon }
|
|
})
|
|
);
|
|
|
|
this.label !== void 0 && content.push(
|
|
h('div', {
|
|
staticClass: 'q-tab__label'
|
|
}, [ this.label ])
|
|
);
|
|
|
|
this.alert !== false && content.push(
|
|
this.alertIcon !== void 0
|
|
? h(QIcon, {
|
|
staticClass: 'q-tab__alert-icon',
|
|
props: {
|
|
color: this.alert !== true
|
|
? this.alert
|
|
: void 0,
|
|
name: this.alertIcon
|
|
}
|
|
})
|
|
: h('div', {
|
|
staticClass: 'q-tab__alert',
|
|
class: this.alert !== true
|
|
? ("text-" + (this.alert))
|
|
: null
|
|
})
|
|
);
|
|
|
|
narrow === true && content.push(indicator);
|
|
|
|
var node = [
|
|
h('div', { staticClass: 'q-focus-helper', attrs: { tabindex: -1 }, ref: 'blurTarget' }),
|
|
|
|
h('div', {
|
|
staticClass: 'q-tab__content self-stretch flex-center relative-position q-anchor--skip non-selectable',
|
|
class: this.innerClass
|
|
}, mergeSlot(content, this, 'default'))
|
|
];
|
|
|
|
narrow === false && node.push(indicator);
|
|
|
|
return node
|
|
},
|
|
|
|
__renderTab: function __renderTab (h, tag, props) {
|
|
var data = {
|
|
staticClass: 'q-tab relative-position self-stretch flex flex-center text-center',
|
|
class: this.classes,
|
|
attrs: this.attrs,
|
|
directives: this.ripple !== false && this.disable === true ? null : [
|
|
{ name: 'ripple', value: this.ripple }
|
|
]
|
|
};
|
|
data[ tag === 'div' ? 'on' : 'nativeOn' ] = this.onEvents;
|
|
|
|
if (props !== void 0) {
|
|
data.props = props;
|
|
}
|
|
|
|
return h(tag, data, this.__getContent(h))
|
|
}
|
|
},
|
|
|
|
mounted: function mounted () {
|
|
this.__recalculateScroll();
|
|
},
|
|
|
|
beforeDestroy: function beforeDestroy () {
|
|
this.__recalculateScroll();
|
|
},
|
|
|
|
render: function render (h) {
|
|
return this.__renderTab(h, 'div')
|
|
}
|
|
});
|
|
|
|
var QTabPanels = Vue.extend({
|
|
name: 'QTabPanels',
|
|
|
|
mixins: [ DarkMixin, PanelParentMixin ],
|
|
|
|
computed: {
|
|
classes: function classes () {
|
|
return 'q-tab-panels q-panel-parent' +
|
|
(this.isDark === true ? ' q-tab-panels--dark q-dark' : '')
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
__renderPanels: function __renderPanels (h) {
|
|
return h('div', {
|
|
class: this.classes,
|
|
directives: this.panelDirectives,
|
|
on: Object.assign({}, this.qListeners)
|
|
}, this.__getPanelContent(h))
|
|
}
|
|
}
|
|
});
|
|
|
|
var QTabPanel = Vue.extend({
|
|
name: 'QTabPanel',
|
|
|
|
mixins: [ PanelChildMixin ],
|
|
|
|
render: function render (h) {
|
|
return h('div', {
|
|
staticClass: 'q-tab-panel',
|
|
on: Object.assign({}, this.qListeners)
|
|
}, slot(this, 'default'))
|
|
}
|
|
});
|
|
|
|
var palette = [
|
|
'rgb(255,204,204)', 'rgb(255,230,204)', 'rgb(255,255,204)', 'rgb(204,255,204)', 'rgb(204,255,230)', 'rgb(204,255,255)', 'rgb(204,230,255)', 'rgb(204,204,255)', 'rgb(230,204,255)', 'rgb(255,204,255)',
|
|
'rgb(255,153,153)', 'rgb(255,204,153)', 'rgb(255,255,153)', 'rgb(153,255,153)', 'rgb(153,255,204)', 'rgb(153,255,255)', 'rgb(153,204,255)', 'rgb(153,153,255)', 'rgb(204,153,255)', 'rgb(255,153,255)',
|
|
'rgb(255,102,102)', 'rgb(255,179,102)', 'rgb(255,255,102)', 'rgb(102,255,102)', 'rgb(102,255,179)', 'rgb(102,255,255)', 'rgb(102,179,255)', 'rgb(102,102,255)', 'rgb(179,102,255)', 'rgb(255,102,255)',
|
|
'rgb(255,51,51)', 'rgb(255,153,51)', 'rgb(255,255,51)', 'rgb(51,255,51)', 'rgb(51,255,153)', 'rgb(51,255,255)', 'rgb(51,153,255)', 'rgb(51,51,255)', 'rgb(153,51,255)', 'rgb(255,51,255)',
|
|
'rgb(255,0,0)', 'rgb(255,128,0)', 'rgb(255,255,0)', 'rgb(0,255,0)', 'rgb(0,255,128)', 'rgb(0,255,255)', 'rgb(0,128,255)', 'rgb(0,0,255)', 'rgb(128,0,255)', 'rgb(255,0,255)',
|
|
'rgb(245,0,0)', 'rgb(245,123,0)', 'rgb(245,245,0)', 'rgb(0,245,0)', 'rgb(0,245,123)', 'rgb(0,245,245)', 'rgb(0,123,245)', 'rgb(0,0,245)', 'rgb(123,0,245)', 'rgb(245,0,245)',
|
|
'rgb(214,0,0)', 'rgb(214,108,0)', 'rgb(214,214,0)', 'rgb(0,214,0)', 'rgb(0,214,108)', 'rgb(0,214,214)', 'rgb(0,108,214)', 'rgb(0,0,214)', 'rgb(108,0,214)', 'rgb(214,0,214)',
|
|
'rgb(163,0,0)', 'rgb(163,82,0)', 'rgb(163,163,0)', 'rgb(0,163,0)', 'rgb(0,163,82)', 'rgb(0,163,163)', 'rgb(0,82,163)', 'rgb(0,0,163)', 'rgb(82,0,163)', 'rgb(163,0,163)',
|
|
'rgb(92,0,0)', 'rgb(92,46,0)', 'rgb(92,92,0)', 'rgb(0,92,0)', 'rgb(0,92,46)', 'rgb(0,92,92)', 'rgb(0,46,92)', 'rgb(0,0,92)', 'rgb(46,0,92)', 'rgb(92,0,92)',
|
|
'rgb(255,255,255)', 'rgb(205,205,205)', 'rgb(178,178,178)', 'rgb(153,153,153)', 'rgb(127,127,127)', 'rgb(102,102,102)', 'rgb(76,76,76)', 'rgb(51,51,51)', 'rgb(25,25,25)', 'rgb(0,0,0)'
|
|
];
|
|
|
|
var QColor = Vue.extend({
|
|
name: 'QColor',
|
|
|
|
mixins: [ ListenersMixin, DarkMixin, FormMixin ],
|
|
|
|
directives: {
|
|
TouchPan: TouchPan
|
|
},
|
|
|
|
props: {
|
|
value: String,
|
|
|
|
defaultValue: String,
|
|
defaultView: {
|
|
type: String,
|
|
default: 'spectrum',
|
|
validator: function (v) { return ['spectrum', 'tune', 'palette'].includes(v); }
|
|
},
|
|
|
|
formatModel: {
|
|
type: String,
|
|
default: 'auto',
|
|
validator: function (v) { return ['auto', 'hex', 'rgb', 'hexa', 'rgba'].includes(v); }
|
|
},
|
|
|
|
palette: Array,
|
|
|
|
noHeader: Boolean,
|
|
noFooter: Boolean,
|
|
|
|
square: Boolean,
|
|
flat: Boolean,
|
|
bordered: Boolean,
|
|
|
|
disable: Boolean,
|
|
readonly: Boolean
|
|
},
|
|
|
|
data: function data () {
|
|
return {
|
|
topView: this.formatModel === 'auto'
|
|
? (
|
|
(this.value === void 0 || this.value === null || this.value === '' || this.value.startsWith('#'))
|
|
? 'hex'
|
|
: 'rgb'
|
|
)
|
|
: (this.formatModel.startsWith('hex') ? 'hex' : 'rgb'),
|
|
view: this.defaultView,
|
|
model: this.__parseModel(this.value || this.defaultValue)
|
|
}
|
|
},
|
|
|
|
watch: {
|
|
value: function value (v) {
|
|
var model = this.__parseModel(v || this.defaultValue);
|
|
if (model.hex !== this.model.hex) {
|
|
this.model = model;
|
|
}
|
|
},
|
|
|
|
defaultValue: function defaultValue (v) {
|
|
if (!this.value && v) {
|
|
var model = this.__parseModel(v);
|
|
if (model.hex !== this.model.hex) {
|
|
this.model = model;
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
computed: {
|
|
editable: function editable () {
|
|
return this.disable !== true && this.readonly !== true
|
|
},
|
|
|
|
forceHex: function forceHex () {
|
|
return this.formatModel === 'auto'
|
|
? null
|
|
: this.formatModel.indexOf('hex') > -1
|
|
},
|
|
|
|
forceAlpha: function forceAlpha () {
|
|
return this.formatModel === 'auto'
|
|
? null
|
|
: this.formatModel.indexOf('a') > -1
|
|
},
|
|
|
|
isHex: function isHex () {
|
|
return this.value === void 0 ||
|
|
this.value === null ||
|
|
this.value === '' ||
|
|
this.value.startsWith('#')
|
|
},
|
|
|
|
isOutputHex: function isOutputHex () {
|
|
return this.forceHex !== null
|
|
? this.forceHex
|
|
: this.isHex
|
|
},
|
|
|
|
formAttrs: function formAttrs () {
|
|
return {
|
|
type: 'hidden',
|
|
name: this.name,
|
|
value: this.model[ this.isOutputHex === true ? 'hex' : 'rgb' ]
|
|
}
|
|
},
|
|
|
|
hasAlpha: function hasAlpha () {
|
|
if (this.forceAlpha !== null) {
|
|
return this.forceAlpha
|
|
}
|
|
return this.model.a !== void 0
|
|
},
|
|
|
|
currentBgColor: function currentBgColor () {
|
|
return {
|
|
backgroundColor: this.model.rgb || '#000'
|
|
}
|
|
},
|
|
|
|
headerClass: function headerClass () {
|
|
var light = this.model.a !== void 0 && this.model.a < 65
|
|
? true
|
|
: luminosity(this.model) > 0.4;
|
|
|
|
return ("q-color-picker__header-content--" + (light ? 'light' : 'dark'))
|
|
},
|
|
|
|
spectrumStyle: function spectrumStyle () {
|
|
return {
|
|
background: ("hsl(" + (this.model.h) + ",100%,50%)")
|
|
}
|
|
},
|
|
|
|
spectrumPointerStyle: function spectrumPointerStyle () {
|
|
var obj;
|
|
|
|
return ( obj = {
|
|
top: ((100 - this.model.v) + "%")
|
|
}, obj[this.$q.lang.rtl === true ? 'right' : 'left'] = ((this.model.s) + "%"), obj )
|
|
},
|
|
|
|
inputsArray: function inputsArray () {
|
|
var inp = ['r', 'g', 'b'];
|
|
if (this.hasAlpha === true) {
|
|
inp.push('a');
|
|
}
|
|
return inp
|
|
},
|
|
|
|
computedPalette: function computedPalette () {
|
|
return this.palette !== void 0 && this.palette.length > 0
|
|
? this.palette
|
|
: palette
|
|
},
|
|
|
|
classes: function classes () {
|
|
return 'q-color-picker' +
|
|
(this.bordered === true ? ' q-color-picker--bordered' : '') +
|
|
(this.square === true ? ' q-color-picker--square no-border-radius' : '') +
|
|
(this.flat === true ? ' q-color-picker--flat no-shadow' : '') +
|
|
(this.disable === true ? ' disabled' : '') +
|
|
(this.isDark === true ? ' q-color-picker--dark q-dark' : '')
|
|
},
|
|
|
|
attrs: function attrs () {
|
|
if (this.disable === true) {
|
|
return { 'aria-disabled': 'true' }
|
|
}
|
|
if (this.readonly === true) {
|
|
return { 'aria-readonly': 'true' }
|
|
}
|
|
}
|
|
},
|
|
|
|
created: function created () {
|
|
this.__spectrumChange = throttle(this.__spectrumChange, 20);
|
|
},
|
|
|
|
render: function render (h) {
|
|
var child = [ this.__getContent(h) ];
|
|
|
|
if (this.name !== void 0 && this.disable !== true) {
|
|
this.__injectFormInput(child, 'push');
|
|
}
|
|
|
|
this.noHeader !== true && child.unshift(
|
|
this.__getHeader(h)
|
|
);
|
|
|
|
this.noFooter !== true && child.push(
|
|
this.__getFooter(h)
|
|
);
|
|
|
|
return h('div', {
|
|
class: this.classes,
|
|
attrs: this.attrs,
|
|
on: Object.assign({}, this.qListeners)
|
|
}, child)
|
|
},
|
|
|
|
methods: {
|
|
__getHeader: function __getHeader (h) {
|
|
var this$1 = this;
|
|
|
|
return h('div', {
|
|
staticClass: 'q-color-picker__header relative-position overflow-hidden'
|
|
}, [
|
|
h('div', { staticClass: 'q-color-picker__header-bg absolute-full' }),
|
|
|
|
h('div', {
|
|
staticClass: 'q-color-picker__header-content absolute-full',
|
|
class: this.headerClass,
|
|
style: this.currentBgColor
|
|
}, [
|
|
h(QTabs, {
|
|
props: {
|
|
value: this.topView,
|
|
dense: true,
|
|
align: 'justify'
|
|
},
|
|
on: cache(this, 'topVTab', {
|
|
input: function (val) { this$1.topView = val; }
|
|
})
|
|
}, [
|
|
h(QTab, {
|
|
props: {
|
|
label: 'HEX' + (this.hasAlpha === true ? 'A' : ''),
|
|
name: 'hex',
|
|
ripple: false
|
|
}
|
|
}),
|
|
|
|
h(QTab, {
|
|
props: {
|
|
label: 'RGB' + (this.hasAlpha === true ? 'A' : ''),
|
|
name: 'rgb',
|
|
ripple: false
|
|
}
|
|
})
|
|
]),
|
|
|
|
h('div', {
|
|
staticClass: 'q-color-picker__header-banner row flex-center no-wrap'
|
|
}, [
|
|
h('input', {
|
|
staticClass: 'fit',
|
|
domProps: { value: this.model[this.topView] },
|
|
attrs: this.editable !== true ? {
|
|
readonly: true
|
|
} : null,
|
|
on: cache(this, 'topIn', {
|
|
input: function (evt) {
|
|
this$1.__updateErrorIcon(this$1.__onEditorChange(evt) === true);
|
|
},
|
|
change: stop,
|
|
blur: function (evt) {
|
|
this$1.__onEditorChange(evt, true) === true && this$1.$forceUpdate();
|
|
this$1.__updateErrorIcon(false);
|
|
}
|
|
})
|
|
}),
|
|
|
|
h(QIcon, {
|
|
ref: 'errorIcon',
|
|
staticClass: 'q-color-picker__error-icon absolute no-pointer-events',
|
|
props: { name: this.$q.iconSet.type.negative }
|
|
})
|
|
])
|
|
])
|
|
])
|
|
},
|
|
|
|
__getContent: function __getContent (h) {
|
|
return h(QTabPanels, {
|
|
props: {
|
|
value: this.view,
|
|
animated: true
|
|
}
|
|
}, [
|
|
h(QTabPanel, {
|
|
staticClass: 'q-color-picker__spectrum-tab overflow-hidden',
|
|
props: { name: 'spectrum' }
|
|
}, this.__getSpectrumTab(h)),
|
|
|
|
h(QTabPanel, {
|
|
staticClass: 'q-pa-md q-color-picker__tune-tab',
|
|
props: { name: 'tune' }
|
|
}, this.__getTuneTab(h)),
|
|
|
|
h(QTabPanel, {
|
|
staticClass: 'q-color-picker__palette-tab',
|
|
props: { name: 'palette' }
|
|
}, this.__getPaletteTab(h))
|
|
])
|
|
},
|
|
|
|
__getFooter: function __getFooter (h) {
|
|
var this$1 = this;
|
|
|
|
return h('div', {
|
|
staticClass: 'q-color-picker__footer relative-position overflow-hidden'
|
|
}, [
|
|
h(QTabs, {
|
|
staticClass: 'absolute-full',
|
|
props: {
|
|
value: this.view,
|
|
dense: true,
|
|
align: 'justify'
|
|
},
|
|
on: cache(this, 'ftIn', {
|
|
input: function (val) { this$1.view = val; }
|
|
})
|
|
}, [
|
|
h(QTab, {
|
|
props: {
|
|
icon: this.$q.iconSet.colorPicker.spectrum,
|
|
name: 'spectrum',
|
|
ripple: false
|
|
}
|
|
}),
|
|
|
|
h(QTab, {
|
|
props: {
|
|
icon: this.$q.iconSet.colorPicker.tune,
|
|
name: 'tune',
|
|
ripple: false
|
|
}
|
|
}),
|
|
|
|
h(QTab, {
|
|
props: {
|
|
icon: this.$q.iconSet.colorPicker.palette,
|
|
name: 'palette',
|
|
ripple: false
|
|
}
|
|
})
|
|
])
|
|
])
|
|
},
|
|
|
|
__getSpectrumTab: function __getSpectrumTab (h) {
|
|
var this$1 = this;
|
|
|
|
var thumbPath = 'M5 5 h10 v10 h-10 v-10 z';
|
|
|
|
return [
|
|
h('div', {
|
|
ref: 'spectrum',
|
|
staticClass: 'q-color-picker__spectrum non-selectable relative-position cursor-pointer',
|
|
style: this.spectrumStyle,
|
|
class: { readonly: this.editable !== true },
|
|
on: this.editable === true
|
|
? cache(this, 'spectrT', {
|
|
click: this.__spectrumClick,
|
|
mousedown: this.__activate
|
|
})
|
|
: null,
|
|
directives: this.editable === true
|
|
? cache(this, 'spectrDir', [{
|
|
name: 'touch-pan',
|
|
modifiers: {
|
|
prevent: true,
|
|
stop: true,
|
|
mouse: true
|
|
},
|
|
value: this.__spectrumPan
|
|
}])
|
|
: null
|
|
}, [
|
|
h('div', { style: { paddingBottom: '100%' } }),
|
|
h('div', { staticClass: 'q-color-picker__spectrum-white absolute-full' }),
|
|
h('div', { staticClass: 'q-color-picker__spectrum-black absolute-full' }),
|
|
h('div', {
|
|
staticClass: 'absolute',
|
|
style: this.spectrumPointerStyle
|
|
}, [
|
|
this.model.hex !== void 0 ? h('div', { staticClass: 'q-color-picker__spectrum-circle' }) : null
|
|
])
|
|
]),
|
|
|
|
h('div', {
|
|
staticClass: 'q-color-picker__sliders'
|
|
}, [
|
|
h('div', { staticClass: 'q-color-picker__hue non-selectable' }, [
|
|
h(QSlider, {
|
|
props: {
|
|
value: this.model.h,
|
|
min: 0,
|
|
max: 360,
|
|
fillHandleAlways: true,
|
|
readonly: this.editable !== true,
|
|
thumbPath: thumbPath
|
|
},
|
|
on: cache(this, 'hueSlide', {
|
|
input: this.__onHueChange,
|
|
change: function (val) { return this$1.__onHueChange(val, true); }
|
|
})
|
|
})
|
|
]),
|
|
this.hasAlpha === true
|
|
? h('div', { staticClass: 'q-color-picker__alpha non-selectable' }, [
|
|
h(QSlider, {
|
|
props: {
|
|
value: this.model.a,
|
|
min: 0,
|
|
max: 100,
|
|
fillHandleAlways: true,
|
|
readonly: this.editable !== true,
|
|
thumbPath: thumbPath
|
|
},
|
|
on: cache(this, 'alphaSlide', {
|
|
input: function (value) { return this$1.__onNumericChange(value, 'a', 100); },
|
|
change: function (value) { return this$1.__onNumericChange(value, 'a', 100, void 0, true); }
|
|
})
|
|
})
|
|
])
|
|
: null
|
|
])
|
|
]
|
|
},
|
|
|
|
__getTuneTab: function __getTuneTab (h) {
|
|
var this$1 = this;
|
|
|
|
return [
|
|
h('div', { staticClass: 'row items-center no-wrap' }, [
|
|
h('div', ['R']),
|
|
h(QSlider, {
|
|
props: {
|
|
value: this.model.r,
|
|
min: 0,
|
|
max: 255,
|
|
color: 'red',
|
|
dark: this.isDark,
|
|
readonly: this.editable !== true
|
|
},
|
|
on: cache(this, 'rSlide', {
|
|
input: function (value) { return this$1.__onNumericChange(value, 'r', 255); },
|
|
change: function (value) { return this$1.__onNumericChange(value, 'r', 255, void 0, true); }
|
|
})
|
|
}),
|
|
h('input', {
|
|
domProps: {
|
|
value: this.model.r
|
|
},
|
|
attrs: {
|
|
maxlength: 3,
|
|
readonly: this.editable !== true
|
|
},
|
|
on: cache(this, 'rIn', {
|
|
input: function (evt) { return this$1.__onNumericChange(evt.target.value, 'r', 255, evt); },
|
|
change: stop,
|
|
blur: function (evt) { return this$1.__onNumericChange(evt.target.value, 'r', 255, evt, true); }
|
|
})
|
|
})
|
|
]),
|
|
|
|
h('div', { staticClass: 'row items-center no-wrap' }, [
|
|
h('div', ['G']),
|
|
h(QSlider, {
|
|
props: {
|
|
value: this.model.g,
|
|
min: 0,
|
|
max: 255,
|
|
color: 'green',
|
|
dark: this.isDark,
|
|
readonly: this.editable !== true
|
|
},
|
|
on: cache(this, 'gSlide', {
|
|
input: function (value) { return this$1.__onNumericChange(value, 'g', 255); },
|
|
change: function (value) { return this$1.__onNumericChange(value, 'g', 255, void 0, true); }
|
|
})
|
|
}),
|
|
h('input', {
|
|
domProps: {
|
|
value: this.model.g
|
|
},
|
|
attrs: {
|
|
maxlength: 3,
|
|
readonly: this.editable !== true
|
|
},
|
|
on: cache(this, 'gIn', {
|
|
input: function (evt) { return this$1.__onNumericChange(evt.target.value, 'g', 255, evt); },
|
|
change: stop,
|
|
blur: function (evt) { return this$1.__onNumericChange(evt.target.value, 'g', 255, evt, true); }
|
|
})
|
|
})
|
|
]),
|
|
|
|
h('div', { staticClass: 'row items-center no-wrap' }, [
|
|
h('div', ['B']),
|
|
h(QSlider, {
|
|
props: {
|
|
value: this.model.b,
|
|
min: 0,
|
|
max: 255,
|
|
color: 'blue',
|
|
readonly: this.editable !== true,
|
|
dark: this.isDark
|
|
},
|
|
on: cache(this, 'bSlide', {
|
|
input: function (value) { return this$1.__onNumericChange(value, 'b', 255); },
|
|
change: function (value) { return this$1.__onNumericChange(value, 'b', 255, void 0, true); }
|
|
})
|
|
}),
|
|
h('input', {
|
|
domProps: {
|
|
value: this.model.b
|
|
},
|
|
attrs: {
|
|
maxlength: 3,
|
|
readonly: this.editable !== true
|
|
},
|
|
on: cache(this, 'bIn', {
|
|
input: function (evt) { return this$1.__onNumericChange(evt.target.value, 'b', 255, evt); },
|
|
change: stop,
|
|
blur: function (evt) { return this$1.__onNumericChange(evt.target.value, 'b', 255, evt, true); }
|
|
})
|
|
})
|
|
]),
|
|
|
|
this.hasAlpha === true ? h('div', { staticClass: 'row items-center no-wrap' }, [
|
|
h('div', ['A']),
|
|
h(QSlider, {
|
|
props: {
|
|
value: this.model.a,
|
|
color: 'grey',
|
|
readonly: this.editable !== true,
|
|
dark: this.isDark
|
|
},
|
|
on: cache(this, 'aSlide', {
|
|
input: function (value) { return this$1.__onNumericChange(value, 'a', 100); },
|
|
change: function (value) { return this$1.__onNumericChange(value, 'a', 100, void 0, true); }
|
|
})
|
|
}),
|
|
h('input', {
|
|
domProps: {
|
|
value: this.model.a
|
|
},
|
|
attrs: {
|
|
maxlength: 3,
|
|
readonly: this.editable !== true
|
|
},
|
|
on: cache(this, 'aIn', {
|
|
input: function (evt) { return this$1.__onNumericChange(evt.target.value, 'a', 100, evt); },
|
|
change: stop,
|
|
blur: function (evt) { return this$1.__onNumericChange(evt.target.value, 'a', 100, evt, true); }
|
|
})
|
|
})
|
|
]) : null
|
|
]
|
|
},
|
|
|
|
__getPaletteTab: function __getPaletteTab (h) {
|
|
var this$1 = this;
|
|
|
|
return [
|
|
h('div', {
|
|
staticClass: 'row items-center q-color-picker__palette-rows',
|
|
class: this.editable === true
|
|
? 'q-color-picker__palette-rows--editable'
|
|
: ''
|
|
}, this.computedPalette.map(function (color) { return h('div', {
|
|
staticClass: 'q-color-picker__cube col-auto',
|
|
style: { backgroundColor: color },
|
|
on: this$1.editable === true ? cache(this$1, 'palette#' + color, {
|
|
click: function () {
|
|
this$1.__onPalettePick(color);
|
|
}
|
|
}) : null
|
|
}); }))
|
|
]
|
|
},
|
|
|
|
__onSpectrumChange: function __onSpectrumChange (left, top, change) {
|
|
var panel = this.$refs.spectrum;
|
|
if (panel === void 0) { return }
|
|
|
|
var
|
|
width = panel.clientWidth,
|
|
height = panel.clientHeight,
|
|
rect = panel.getBoundingClientRect();
|
|
|
|
var x = Math.min(width, Math.max(0, left - rect.left));
|
|
|
|
if (this.$q.lang.rtl === true) {
|
|
x = width - x;
|
|
}
|
|
|
|
var
|
|
y = Math.min(height, Math.max(0, top - rect.top)),
|
|
s = Math.round(100 * x / width),
|
|
v = Math.round(100 * Math.max(0, Math.min(1, -(y / height) + 1))),
|
|
rgb = hsvToRgb({
|
|
h: this.model.h,
|
|
s: s,
|
|
v: v,
|
|
a: this.hasAlpha === true ? this.model.a : void 0
|
|
});
|
|
|
|
this.model.s = s;
|
|
this.model.v = v;
|
|
this.__update(rgb, change);
|
|
},
|
|
|
|
__onHueChange: function __onHueChange (h, change) {
|
|
h = Math.round(h);
|
|
var rgb = hsvToRgb({
|
|
h: h,
|
|
s: this.model.s,
|
|
v: this.model.v,
|
|
a: this.hasAlpha === true ? this.model.a : void 0
|
|
});
|
|
|
|
this.model.h = h;
|
|
this.__update(rgb, change);
|
|
},
|
|
|
|
__onNumericChange: function __onNumericChange (value, formatModel, max, evt, change) {
|
|
evt !== void 0 && stop(evt);
|
|
|
|
if (!/^[0-9]+$/.test(value)) {
|
|
change && this.$forceUpdate();
|
|
return
|
|
}
|
|
|
|
var val = Math.floor(Number(value));
|
|
|
|
if (val < 0 || val > max) {
|
|
change === true && this.$forceUpdate();
|
|
return
|
|
}
|
|
|
|
var rgb = {
|
|
r: formatModel === 'r' ? val : this.model.r,
|
|
g: formatModel === 'g' ? val : this.model.g,
|
|
b: formatModel === 'b' ? val : this.model.b,
|
|
a: this.hasAlpha === true
|
|
? (formatModel === 'a' ? val : this.model.a)
|
|
: void 0
|
|
};
|
|
|
|
if (formatModel !== 'a') {
|
|
var hsv = rgbToHsv(rgb);
|
|
this.model.h = hsv.h;
|
|
this.model.s = hsv.s;
|
|
this.model.v = hsv.v;
|
|
}
|
|
|
|
this.__update(rgb, change);
|
|
|
|
if (evt !== void 0 && change !== true && evt.target.selectionEnd !== void 0) {
|
|
var index = evt.target.selectionEnd;
|
|
this.$nextTick(function () {
|
|
evt.target.setSelectionRange(index, index);
|
|
});
|
|
}
|
|
},
|
|
|
|
__onEditorChange: function __onEditorChange (evt, change) {
|
|
var rgb;
|
|
var inp = evt.target.value;
|
|
|
|
stop(evt);
|
|
|
|
if (this.topView === 'hex') {
|
|
if (
|
|
inp.length !== (this.hasAlpha === true ? 9 : 7) ||
|
|
!/^#[0-9A-Fa-f]+$/.test(inp)
|
|
) {
|
|
return true
|
|
}
|
|
|
|
rgb = hexToRgb(inp);
|
|
}
|
|
else {
|
|
var model;
|
|
|
|
if (!inp.endsWith(')')) {
|
|
return true
|
|
}
|
|
else if (this.hasAlpha !== true && inp.startsWith('rgb(')) {
|
|
model = inp.substring(4, inp.length - 1).split(',').map(function (n) { return parseInt(n, 10); });
|
|
|
|
if (
|
|
model.length !== 3 ||
|
|
!/^rgb\([0-9]{1,3},[0-9]{1,3},[0-9]{1,3}\)$/.test(inp)
|
|
) {
|
|
return true
|
|
}
|
|
}
|
|
else if (this.hasAlpha === true && inp.startsWith('rgba(')) {
|
|
model = inp.substring(5, inp.length - 1).split(',');
|
|
|
|
if (
|
|
model.length !== 4 ||
|
|
!/^rgba\([0-9]{1,3},[0-9]{1,3},[0-9]{1,3},(0|0\.[0-9]+[1-9]|0\.[1-9]+|1)\)$/.test(inp)
|
|
) {
|
|
return true
|
|
}
|
|
|
|
for (var i = 0; i < 3; i++) {
|
|
var v = parseInt(model[i], 10);
|
|
if (v < 0 || v > 255) {
|
|
return true
|
|
}
|
|
model[i] = v;
|
|
}
|
|
|
|
var v$1 = parseFloat(model[3]);
|
|
if (v$1 < 0 || v$1 > 1) {
|
|
return true
|
|
}
|
|
model[3] = v$1;
|
|
}
|
|
else {
|
|
return true
|
|
}
|
|
|
|
if (
|
|
model[0] < 0 || model[0] > 255 ||
|
|
model[1] < 0 || model[1] > 255 ||
|
|
model[2] < 0 || model[2] > 255 ||
|
|
(this.hasAlpha === true && (model[3] < 0 || model[3] > 1))
|
|
) {
|
|
return true
|
|
}
|
|
|
|
rgb = {
|
|
r: model[0],
|
|
g: model[1],
|
|
b: model[2],
|
|
a: this.hasAlpha === true
|
|
? model[3] * 100
|
|
: void 0
|
|
};
|
|
}
|
|
|
|
var hsv = rgbToHsv(rgb);
|
|
this.model.h = hsv.h;
|
|
this.model.s = hsv.s;
|
|
this.model.v = hsv.v;
|
|
|
|
this.__update(rgb, change);
|
|
|
|
if (change !== true) {
|
|
var index = evt.target.selectionEnd;
|
|
this.$nextTick(function () {
|
|
evt.target.setSelectionRange(index, index);
|
|
});
|
|
}
|
|
},
|
|
|
|
__onPalettePick: function __onPalettePick (color) {
|
|
var def = this.__parseModel(color);
|
|
var rgb = { r: def.r, g: def.g, b: def.b, a: def.a };
|
|
|
|
if (rgb.a === void 0) {
|
|
rgb.a = this.model.a;
|
|
}
|
|
|
|
this.model.h = def.h;
|
|
this.model.s = def.s;
|
|
this.model.v = def.v;
|
|
|
|
this.__update(rgb, true);
|
|
},
|
|
|
|
__update: function __update (rgb, change) {
|
|
// update internally
|
|
this.model.hex = rgbToHex(rgb);
|
|
this.model.rgb = rgbToString(rgb);
|
|
this.model.r = rgb.r;
|
|
this.model.g = rgb.g;
|
|
this.model.b = rgb.b;
|
|
this.model.a = rgb.a;
|
|
|
|
var value = this.model[this.isOutputHex === true ? 'hex' : 'rgb'];
|
|
|
|
// emit new value
|
|
this.$emit('input', value);
|
|
change === true && this.$emit('change', value);
|
|
},
|
|
|
|
__updateErrorIcon: function __updateErrorIcon (val) {
|
|
// we MUST avoid vue triggering a render,
|
|
// so manually changing this
|
|
if (this.$refs.errorIcon !== void 0) {
|
|
this.$refs.errorIcon.$el.style.opacity = val ? 1 : 0;
|
|
}
|
|
},
|
|
|
|
__parseModel: function __parseModel (v) {
|
|
var forceAlpha = this.forceAlpha !== void 0
|
|
? this.forceAlpha
|
|
: (
|
|
this.formatModel === 'auto'
|
|
? null
|
|
: this.formatModel.indexOf('a') > -1
|
|
);
|
|
|
|
if (typeof v !== 'string' || v.length === 0 || testPattern.anyColor(v.replace(/ /g, '')) !== true) {
|
|
return {
|
|
h: 0,
|
|
s: 0,
|
|
v: 0,
|
|
r: 0,
|
|
g: 0,
|
|
b: 0,
|
|
a: forceAlpha === true ? 100 : void 0,
|
|
hex: void 0,
|
|
rgb: void 0
|
|
}
|
|
}
|
|
|
|
var model = textToRgb(v);
|
|
|
|
if (forceAlpha === true && model.a === void 0) {
|
|
model.a = 100;
|
|
}
|
|
|
|
model.hex = rgbToHex(model);
|
|
model.rgb = rgbToString(model);
|
|
|
|
return Object.assign(model, rgbToHsv(model))
|
|
},
|
|
|
|
__spectrumPan: function __spectrumPan (evt) {
|
|
if (evt.isFinal) {
|
|
this.__onSpectrumChange(
|
|
evt.position.left,
|
|
evt.position.top,
|
|
true
|
|
);
|
|
}
|
|
else {
|
|
this.__spectrumChange(evt);
|
|
}
|
|
},
|
|
|
|
// throttled in created()
|
|
__spectrumChange: function __spectrumChange (evt) {
|
|
this.__onSpectrumChange(
|
|
evt.position.left,
|
|
evt.position.top
|
|
);
|
|
},
|
|
|
|
__spectrumClick: function __spectrumClick (evt) {
|
|
this.__onSpectrumChange(
|
|
evt.pageX - window.pageXOffset,
|
|
evt.pageY - window.pageYOffset,
|
|
true
|
|
);
|
|
},
|
|
|
|
__activate: function __activate (evt) {
|
|
this.__onSpectrumChange(
|
|
evt.pageX - window.pageXOffset,
|
|
evt.pageY - window.pageYOffset
|
|
);
|
|
}
|
|
}
|
|
});
|
|
|
|
// taken from https://github.com/jalaali/jalaali-js
|
|
|
|
/*
|
|
Jalaali years starting the 33-year rule.
|
|
*/
|
|
var breaks = [ -61, 9, 38, 199, 426, 686, 756, 818, 1111, 1181, 1210,
|
|
1635, 2060, 2097, 2192, 2262, 2324, 2394, 2456, 3178
|
|
];
|
|
|
|
/*
|
|
Converts a Gregorian date to Jalaali.
|
|
*/
|
|
function toJalaali (gy, gm, gd) {
|
|
if (Object.prototype.toString.call(gy) === '[object Date]') {
|
|
gd = gy.getDate();
|
|
gm = gy.getMonth() + 1;
|
|
gy = gy.getFullYear();
|
|
}
|
|
return d2j(g2d(gy, gm, gd))
|
|
}
|
|
|
|
/*
|
|
Converts a Jalaali date to Gregorian.
|
|
*/
|
|
function toGregorian (jy, jm, jd) {
|
|
return d2g(j2d(jy, jm, jd))
|
|
}
|
|
|
|
/*
|
|
Is this a leap year or not?
|
|
*/
|
|
function isLeapJalaaliYear (jy) {
|
|
return jalCalLeap(jy) === 0
|
|
}
|
|
|
|
/*
|
|
Number of days in a given month in a Jalaali year.
|
|
*/
|
|
function jalaaliMonthLength (jy, jm) {
|
|
if (jm <= 6) { return 31 }
|
|
if (jm <= 11) { return 30 }
|
|
if (isLeapJalaaliYear(jy)) { return 30 }
|
|
return 29
|
|
}
|
|
|
|
/*
|
|
This function determines if the Jalaali (Persian) year is
|
|
leap (366-day long) or is the common year (365 days)
|
|
|
|
@param jy Jalaali calendar year (-61 to 3177)
|
|
@returns number of years since the last leap year (0 to 4)
|
|
*/
|
|
function jalCalLeap (jy) {
|
|
var bl = breaks.length;
|
|
var
|
|
jp = breaks[0],
|
|
jm,
|
|
jump,
|
|
leap,
|
|
n,
|
|
i;
|
|
|
|
if (jy < jp || jy >= breaks[bl - 1]) { throw new Error('Invalid Jalaali year ' + jy) }
|
|
|
|
for (i = 1; i < bl; i += 1) {
|
|
jm = breaks[i];
|
|
jump = jm - jp;
|
|
if (jy < jm) { break }
|
|
jp = jm;
|
|
}
|
|
n = jy - jp;
|
|
|
|
if (jump - n < 6) { n = n - jump + div(jump + 4, 33) * 33; }
|
|
leap = mod(mod(n + 1, 33) - 1, 4);
|
|
if (leap === -1) {
|
|
leap = 4;
|
|
}
|
|
|
|
return leap
|
|
}
|
|
|
|
/*
|
|
This function determines if the Jalaali (Persian) year is
|
|
leap (366-day long) or is the common year (365 days), and
|
|
finds the day in March (Gregorian calendar) of the first
|
|
day of the Jalaali year (jy).
|
|
|
|
@param jy Jalaali calendar year (-61 to 3177)
|
|
@param withoutLeap when don't need leap (true or false) default is false
|
|
@return
|
|
leap: number of years since the last leap year (0 to 4)
|
|
gy: Gregorian year of the beginning of Jalaali year
|
|
march: the March day of Farvardin the 1st (1st day of jy)
|
|
@see: http://www.astro.uni.torun.pl/~kb/Papers/EMP/PersianC-EMP.htm
|
|
@see: http://www.fourmilab.ch/documents/calendar/
|
|
*/
|
|
function jalCal (jy, withoutLeap) {
|
|
var
|
|
bl = breaks.length,
|
|
gy = jy + 621;
|
|
var
|
|
leapJ = -14,
|
|
jp = breaks[0],
|
|
jm,
|
|
jump,
|
|
leap,
|
|
n,
|
|
i;
|
|
|
|
if (jy < jp || jy >= breaks[bl - 1]) { throw new Error('Invalid Jalaali year ' + jy) }
|
|
|
|
// Find the limiting years for the Jalaali year jy.
|
|
for (i = 1; i < bl; i += 1) {
|
|
jm = breaks[i];
|
|
jump = jm - jp;
|
|
if (jy < jm) { break }
|
|
leapJ = leapJ + div(jump, 33) * 8 + div(mod(jump, 33), 4);
|
|
jp = jm;
|
|
}
|
|
n = jy - jp;
|
|
|
|
// Find the number of leap years from AD 621 to the beginning
|
|
// of the current Jalaali year in the Persian calendar.
|
|
leapJ = leapJ + div(n, 33) * 8 + div(mod(n, 33) + 3, 4);
|
|
if (mod(jump, 33) === 4 && jump - n === 4) { leapJ += 1; }
|
|
|
|
// And the same in the Gregorian calendar (until the year gy).
|
|
var leapG = div(gy, 4) - div((div(gy, 100) + 1) * 3, 4) - 150;
|
|
|
|
// Determine the Gregorian date of Farvardin the 1st.
|
|
var march = 20 + leapJ - leapG;
|
|
|
|
// Find how many years have passed since the last leap year.
|
|
if (!withoutLeap) {
|
|
if (jump - n < 6) { n = n - jump + div(jump + 4, 33) * 33; }
|
|
leap = mod(mod(n + 1, 33) - 1, 4);
|
|
if (leap === -1) {
|
|
leap = 4;
|
|
}
|
|
}
|
|
|
|
return {
|
|
leap: leap,
|
|
gy: gy,
|
|
march: march
|
|
}
|
|
}
|
|
|
|
/*
|
|
Converts a date of the Jalaali calendar to the Julian Day number.
|
|
|
|
@param jy Jalaali year (1 to 3100)
|
|
@param jm Jalaali month (1 to 12)
|
|
@param jd Jalaali day (1 to 29/31)
|
|
@return Julian Day number
|
|
*/
|
|
function j2d (jy, jm, jd) {
|
|
var r = jalCal(jy, true);
|
|
return g2d(r.gy, 3, r.march) + (jm - 1) * 31 - div(jm, 7) * (jm - 7) + jd - 1
|
|
}
|
|
|
|
/*
|
|
Converts the Julian Day number to a date in the Jalaali calendar.
|
|
|
|
@param jdn Julian Day number
|
|
@return
|
|
jy: Jalaali year (1 to 3100)
|
|
jm: Jalaali month (1 to 12)
|
|
jd: Jalaali day (1 to 29/31)
|
|
*/
|
|
function d2j (jdn) {
|
|
var gy = d2g(jdn).gy; // Calculate Gregorian year (gy).
|
|
var
|
|
jy = gy - 621,
|
|
jd,
|
|
jm,
|
|
k;
|
|
var
|
|
r = jalCal(jy, false),
|
|
jdn1f = g2d(gy, 3, r.march);
|
|
|
|
// Find number of days that passed since 1 Farvardin.
|
|
k = jdn - jdn1f;
|
|
if (k >= 0) {
|
|
if (k <= 185) {
|
|
// The first 6 months.
|
|
jm = 1 + div(k, 31);
|
|
jd = mod(k, 31) + 1;
|
|
return { jy: jy,
|
|
jm: jm,
|
|
jd: jd
|
|
}
|
|
}
|
|
else {
|
|
// The remaining months.
|
|
k -= 186;
|
|
}
|
|
}
|
|
else {
|
|
// Previous Jalaali year.
|
|
jy -= 1;
|
|
k += 179;
|
|
if (r.leap === 1) { k += 1; }
|
|
}
|
|
jm = 7 + div(k, 30);
|
|
jd = mod(k, 30) + 1;
|
|
return { jy: jy,
|
|
jm: jm,
|
|
jd: jd
|
|
}
|
|
}
|
|
|
|
/*
|
|
Calculates the Julian Day number from Gregorian or Julian
|
|
calendar dates. This integer number corresponds to the noon of
|
|
the date (i.e. 12 hours of Universal Time).
|
|
The procedure was tested to be good since 1 March, -100100 (of both
|
|
calendars) up to a few million years into the future.
|
|
|
|
@param gy Calendar year (years BC numbered 0, -1, -2, ...)
|
|
@param gm Calendar month (1 to 12)
|
|
@param gd Calendar day of the month (1 to 28/29/30/31)
|
|
@return Julian Day number
|
|
*/
|
|
function g2d (gy, gm, gd) {
|
|
var d = div((gy + div(gm - 8, 6) + 100100) * 1461, 4) +
|
|
div(153 * mod(gm + 9, 12) + 2, 5) +
|
|
gd - 34840408;
|
|
d = d - div(div(gy + 100100 + div(gm - 8, 6), 100) * 3, 4) + 752;
|
|
return d
|
|
}
|
|
|
|
/*
|
|
Calculates Gregorian and Julian calendar dates from the Julian Day number
|
|
(jdn) for the period since jdn=-34839655 (i.e. the year -100100 of both
|
|
calendars) to some millions years ahead of the present.
|
|
|
|
@param jdn Julian Day number
|
|
@return
|
|
gy: Calendar year (years BC numbered 0, -1, -2, ...)
|
|
gm: Calendar month (1 to 12)
|
|
gd: Calendar day of the month M (1 to 28/29/30/31)
|
|
*/
|
|
function d2g (jdn) {
|
|
var j = 4 * jdn + 139361631;
|
|
j = j + div(div(4 * jdn + 183187720, 146097) * 3, 4) * 4 - 3908;
|
|
var
|
|
i = div(mod(j, 1461), 4) * 5 + 308,
|
|
gd = div(mod(i, 153), 5) + 1,
|
|
gm = mod(div(i, 153), 12) + 1,
|
|
gy = div(j, 1461) - 100100 + div(8 - gm, 6);
|
|
return {
|
|
gy: gy,
|
|
gm: gm,
|
|
gd: gd
|
|
}
|
|
}
|
|
|
|
/*
|
|
Utility helper functions.
|
|
*/
|
|
|
|
function div (a, b) {
|
|
return ~~(a / b)
|
|
}
|
|
|
|
function mod (a, b) {
|
|
return a - ~~(a / b) * b
|
|
}
|
|
|
|
var calendars = [ 'gregorian', 'persian' ];
|
|
|
|
var DateTimeMixin = {
|
|
mixins: [ DarkMixin, FormMixin, ListenersMixin ],
|
|
|
|
props: {
|
|
value: {
|
|
required: true
|
|
},
|
|
|
|
mask: {
|
|
type: String
|
|
},
|
|
locale: Object,
|
|
|
|
calendar: {
|
|
type: String,
|
|
validator: function (v) { return calendars.includes(v); },
|
|
default: 'gregorian'
|
|
},
|
|
|
|
landscape: Boolean,
|
|
|
|
color: String,
|
|
textColor: String,
|
|
|
|
square: Boolean,
|
|
flat: Boolean,
|
|
bordered: Boolean,
|
|
|
|
readonly: Boolean,
|
|
disable: Boolean
|
|
},
|
|
|
|
computed: {
|
|
computedMask: function computedMask () {
|
|
return this.__getMask()
|
|
},
|
|
|
|
computedLocale: function computedLocale () {
|
|
return this.__getLocale()
|
|
},
|
|
|
|
editable: function editable () {
|
|
return this.disable !== true && this.readonly !== true
|
|
},
|
|
|
|
computedColor: function computedColor () {
|
|
return this.color || 'primary'
|
|
},
|
|
|
|
computedTextColor: function computedTextColor () {
|
|
return this.textColor || 'white'
|
|
},
|
|
|
|
computedTabindex: function computedTabindex () {
|
|
return this.editable === true ? 0 : -1
|
|
},
|
|
|
|
headerClass: function headerClass () {
|
|
var cls = [];
|
|
this.color !== void 0 && cls.push(("bg-" + (this.color)));
|
|
this.textColor !== void 0 && cls.push(("text-" + (this.textColor)));
|
|
return cls.join(' ')
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
__getLocale: function __getLocale () {
|
|
return this.locale || this.$q.lang.date
|
|
},
|
|
|
|
__getCurrentDate: function __getCurrentDate () {
|
|
var d = new Date();
|
|
|
|
if (this.calendar === 'persian') {
|
|
var jDate = toJalaali(d);
|
|
return {
|
|
year: jDate.jy,
|
|
month: jDate.jm,
|
|
day: jDate.jd
|
|
}
|
|
}
|
|
|
|
return {
|
|
year: d.getFullYear(),
|
|
month: d.getMonth() + 1,
|
|
day: d.getDate(),
|
|
hour: 0,
|
|
minute: 0,
|
|
second: 0,
|
|
millisecond: 0
|
|
}
|
|
},
|
|
|
|
__getCurrentTime: function __getCurrentTime () {
|
|
var d = new Date();
|
|
|
|
return {
|
|
hour: d.getHours(),
|
|
minute: d.getMinutes(),
|
|
second: d.getSeconds(),
|
|
millisecond: d.getMilliseconds()
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
/* eslint no-fallthrough: 0 */
|
|
|
|
var
|
|
MILLISECONDS_IN_DAY = 86400000,
|
|
MILLISECONDS_IN_HOUR = 3600000,
|
|
MILLISECONDS_IN_MINUTE = 60000,
|
|
defaultMask = 'YYYY-MM-DDTHH:mm:ss.SSSZ',
|
|
token = /\[((?:[^\]\\]|\\]|\\)*)\]|d{1,4}|M{1,4}|m{1,2}|w{1,2}|Qo|Do|D{1,4}|YY(?:YY)?|H{1,2}|h{1,2}|s{1,2}|S{1,3}|Z{1,2}|a{1,2}|[AQExX]/g,
|
|
reverseToken = /(\[[^\]]*\])|d{1,4}|M{1,4}|m{1,2}|w{1,2}|Qo|Do|D{1,4}|YY(?:YY)?|H{1,2}|h{1,2}|s{1,2}|S{1,3}|Z{1,2}|a{1,2}|[AQExX]|([.*+:?^,\s${}()|\\]+)/g,
|
|
regexStore = {};
|
|
|
|
function getRegexData (mask, dateLocale) {
|
|
var
|
|
days = '(' + dateLocale.days.join('|') + ')',
|
|
key = mask + days;
|
|
|
|
if (regexStore[key] !== void 0) {
|
|
return regexStore[key]
|
|
}
|
|
|
|
var
|
|
daysShort = '(' + dateLocale.daysShort.join('|') + ')',
|
|
months = '(' + dateLocale.months.join('|') + ')',
|
|
monthsShort = '(' + dateLocale.monthsShort.join('|') + ')';
|
|
|
|
var map = {};
|
|
var index = 0;
|
|
|
|
var regexText = mask.replace(reverseToken, function (match) {
|
|
index++;
|
|
switch (match) {
|
|
case 'YY':
|
|
map.YY = index;
|
|
return '(-?\\d{1,2})'
|
|
case 'YYYY':
|
|
map.YYYY = index;
|
|
return '(-?\\d{1,4})'
|
|
case 'M':
|
|
map.M = index;
|
|
return '(\\d{1,2})'
|
|
case 'MM':
|
|
map.M = index; // bumping to M
|
|
return '(\\d{2})'
|
|
case 'MMM':
|
|
map.MMM = index;
|
|
return monthsShort
|
|
case 'MMMM':
|
|
map.MMMM = index;
|
|
return months
|
|
case 'D':
|
|
map.D = index;
|
|
return '(\\d{1,2})'
|
|
case 'Do':
|
|
map.D = index++; // bumping to D
|
|
return '(\\d{1,2}(st|nd|rd|th))'
|
|
case 'DD':
|
|
map.D = index; // bumping to D
|
|
return '(\\d{2})'
|
|
case 'H':
|
|
map.H = index;
|
|
return '(\\d{1,2})'
|
|
case 'HH':
|
|
map.H = index; // bumping to H
|
|
return '(\\d{2})'
|
|
case 'h':
|
|
map.h = index;
|
|
return '(\\d{1,2})'
|
|
case 'hh':
|
|
map.h = index; // bumping to h
|
|
return '(\\d{2})'
|
|
case 'm':
|
|
map.m = index;
|
|
return '(\\d{1,2})'
|
|
case 'mm':
|
|
map.m = index; // bumping to m
|
|
return '(\\d{2})'
|
|
case 's':
|
|
map.s = index;
|
|
return '(\\d{1,2})'
|
|
case 'ss':
|
|
map.s = index; // bumping to s
|
|
return '(\\d{2})'
|
|
case 'S':
|
|
map.S = index;
|
|
return '(\\d{1})'
|
|
case 'SS':
|
|
map.S = index; // bump to S
|
|
return '(\\d{2})'
|
|
case 'SSS':
|
|
map.S = index; // bump to S
|
|
return '(\\d{3})'
|
|
case 'A':
|
|
map.A = index;
|
|
return '(AM|PM)'
|
|
case 'a':
|
|
map.a = index;
|
|
return '(am|pm)'
|
|
case 'aa':
|
|
map.aa = index;
|
|
return '(a\\.m\\.|p\\.m\\.)'
|
|
|
|
case 'ddd':
|
|
return daysShort
|
|
case 'dddd':
|
|
return days
|
|
case 'Q':
|
|
case 'd':
|
|
case 'E':
|
|
return '(\\d{1})'
|
|
case 'Qo':
|
|
return '(1st|2nd|3rd|4th)'
|
|
case 'DDD':
|
|
case 'DDDD':
|
|
return '(\\d{1,3})'
|
|
case 'w':
|
|
return '(\\d{1,2})'
|
|
case 'ww':
|
|
return '(\\d{2})'
|
|
|
|
case 'Z': // to split: (?:(Z)()()|([+-])?(\\d{2}):?(\\d{2}))
|
|
map.Z = index;
|
|
return '(Z|[+-]\\d{2}:\\d{2})'
|
|
case 'ZZ':
|
|
map.ZZ = index;
|
|
return '(Z|[+-]\\d{2}\\d{2})'
|
|
|
|
case 'X':
|
|
map.X = index;
|
|
return '(-?\\d+)'
|
|
case 'x':
|
|
map.x = index;
|
|
return '(-?\\d{4,})'
|
|
|
|
default:
|
|
index--;
|
|
if (match[0] === '[') {
|
|
match = match.substring(1, match.length - 1);
|
|
}
|
|
return match.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
|
|
}
|
|
});
|
|
|
|
var res = { map: map, regex: new RegExp('^' + regexText) };
|
|
regexStore[key] = res;
|
|
|
|
return res
|
|
}
|
|
|
|
function extractDate (str, mask, dateLocale) {
|
|
var d = __splitDate(str, mask, dateLocale);
|
|
|
|
var date = new Date(
|
|
d.year,
|
|
d.month === null ? null : d.month - 1,
|
|
d.day,
|
|
d.hour,
|
|
d.minute,
|
|
d.second,
|
|
d.millisecond
|
|
);
|
|
|
|
var tzOffset = date.getTimezoneOffset();
|
|
|
|
return d.timezoneOffset === null || d.timezoneOffset === tzOffset
|
|
? date
|
|
: getChange(date, { minutes: d.timezoneOffset - tzOffset }, true)
|
|
}
|
|
|
|
function __splitDate (str, mask, dateLocale, calendar, defaultModel) {
|
|
var date = {
|
|
year: null,
|
|
month: null,
|
|
day: null,
|
|
hour: null,
|
|
minute: null,
|
|
second: null,
|
|
millisecond: null,
|
|
timezoneOffset: null,
|
|
dateHash: null,
|
|
timeHash: null
|
|
};
|
|
|
|
defaultModel !== void 0 && Object.assign(date, defaultModel);
|
|
|
|
if (
|
|
str === void 0 ||
|
|
str === null ||
|
|
str === '' ||
|
|
typeof str !== 'string'
|
|
) {
|
|
return date
|
|
}
|
|
|
|
if (mask === void 0) {
|
|
mask = defaultMask;
|
|
}
|
|
|
|
var
|
|
langOpts = dateLocale !== void 0 ? dateLocale : lang.props.date,
|
|
months = langOpts.months,
|
|
monthsShort = langOpts.monthsShort;
|
|
|
|
var ref = getRegexData(mask, langOpts);
|
|
var regex = ref.regex;
|
|
var map = ref.map;
|
|
|
|
var match = str.match(regex);
|
|
|
|
if (match === null) {
|
|
return date
|
|
}
|
|
|
|
var tzString = '';
|
|
|
|
if (map.X !== void 0 || map.x !== void 0) {
|
|
var stamp = parseInt(match[map.X !== void 0 ? map.X : map.x], 10);
|
|
|
|
if (isNaN(stamp) === true || stamp < 0) {
|
|
return date
|
|
}
|
|
|
|
var d = new Date(stamp * (map.X !== void 0 ? 1000 : 1));
|
|
|
|
date.year = d.getFullYear();
|
|
date.month = d.getMonth() + 1;
|
|
date.day = d.getDate();
|
|
date.hour = d.getHours();
|
|
date.minute = d.getMinutes();
|
|
date.second = d.getSeconds();
|
|
date.millisecond = d.getMilliseconds();
|
|
}
|
|
else {
|
|
if (map.YYYY !== void 0) {
|
|
date.year = parseInt(match[map.YYYY], 10);
|
|
}
|
|
else if (map.YY !== void 0) {
|
|
var y = parseInt(match[map.YY], 10);
|
|
date.year = y < 0 ? y : 2000 + y;
|
|
}
|
|
|
|
if (map.M !== void 0) {
|
|
date.month = parseInt(match[map.M], 10);
|
|
if (date.month < 1 || date.month > 12) {
|
|
return date
|
|
}
|
|
}
|
|
else if (map.MMM !== void 0) {
|
|
date.month = monthsShort.indexOf(match[map.MMM]) + 1;
|
|
}
|
|
else if (map.MMMM !== void 0) {
|
|
date.month = months.indexOf(match[map.MMMM]) + 1;
|
|
}
|
|
|
|
if (map.D !== void 0) {
|
|
date.day = parseInt(match[map.D], 10);
|
|
|
|
if (date.year === null || date.month === null || date.day < 1) {
|
|
return date
|
|
}
|
|
|
|
var maxDay = calendar !== 'persian'
|
|
? (new Date(date.year, date.month, 0)).getDate()
|
|
: jalaaliMonthLength(date.year, date.month);
|
|
|
|
if (date.day > maxDay) {
|
|
return date
|
|
}
|
|
}
|
|
|
|
if (map.H !== void 0) {
|
|
date.hour = parseInt(match[map.H], 10) % 24;
|
|
}
|
|
else if (map.h !== void 0) {
|
|
date.hour = parseInt(match[map.h], 10) % 12;
|
|
if (
|
|
(map.A && match[map.A] === 'PM') ||
|
|
(map.a && match[map.a] === 'pm') ||
|
|
(map.aa && match[map.aa] === 'p.m.')
|
|
) {
|
|
date.hour += 12;
|
|
}
|
|
date.hour = date.hour % 24;
|
|
}
|
|
|
|
if (map.m !== void 0) {
|
|
date.minute = parseInt(match[map.m], 10) % 60;
|
|
}
|
|
|
|
if (map.s !== void 0) {
|
|
date.second = parseInt(match[map.s], 10) % 60;
|
|
}
|
|
|
|
if (map.S !== void 0) {
|
|
date.millisecond = parseInt(match[map.S], 10) * Math.pow( 10, (3 - match[map.S].length) );
|
|
}
|
|
|
|
if (map.Z !== void 0 || map.ZZ !== void 0) {
|
|
tzString = (map.Z !== void 0 ? match[map.Z].replace(':', '') : match[map.ZZ]);
|
|
date.timezoneOffset = (tzString[0] === '+' ? -1 : 1) * (60 * tzString.slice(1, 3) + 1 * tzString.slice(3, 5));
|
|
}
|
|
}
|
|
|
|
date.dateHash = date.year + '/' + pad(date.month) + '/' + pad(date.day);
|
|
date.timeHash = pad(date.hour) + ':' + pad(date.minute) + ':' + pad(date.second) + tzString;
|
|
|
|
return date
|
|
}
|
|
|
|
function formatTimezone (offset, delimeter) {
|
|
if ( delimeter === void 0 ) delimeter = '';
|
|
|
|
var
|
|
sign = offset > 0 ? '-' : '+',
|
|
absOffset = Math.abs(offset),
|
|
hours = Math.floor(absOffset / 60),
|
|
minutes = absOffset % 60;
|
|
|
|
return sign + pad(hours) + delimeter + pad(minutes)
|
|
}
|
|
|
|
function setMonth (date, newMonth /* 1-based */) {
|
|
var
|
|
test = new Date(date.getFullYear(), newMonth, 0, 0, 0, 0, 0),
|
|
days = test.getDate();
|
|
|
|
date.setMonth(newMonth - 1, Math.min(days, date.getDate()));
|
|
}
|
|
|
|
function getChange (date, mod, add) {
|
|
var
|
|
t = new Date(date),
|
|
sign = (add ? 1 : -1);
|
|
|
|
Object.keys(mod).forEach(function (key) {
|
|
if (key === 'month') {
|
|
setMonth(t, t.getMonth() + 1 + sign * mod.month);
|
|
return
|
|
}
|
|
|
|
var op = key === 'year'
|
|
? 'FullYear'
|
|
: capitalize(key === 'days' ? 'date' : key);
|
|
t[("set" + op)](t[("get" + op)]() + sign * mod[key]);
|
|
});
|
|
return t
|
|
}
|
|
|
|
function isValid (date) {
|
|
return typeof date === 'number'
|
|
? true
|
|
: isNaN(Date.parse(date)) === false
|
|
}
|
|
|
|
function buildDate (mod, utc) {
|
|
return adjustDate(new Date(), mod, utc)
|
|
}
|
|
|
|
function getDayOfWeek (date) {
|
|
var dow = new Date(date).getDay();
|
|
return dow === 0 ? 7 : dow
|
|
}
|
|
|
|
function getWeekOfYear (date) {
|
|
// Remove time components of date
|
|
var thursday = new Date(date.getFullYear(), date.getMonth(), date.getDate());
|
|
|
|
// Change date to Thursday same week
|
|
thursday.setDate(thursday.getDate() - ((thursday.getDay() + 6) % 7) + 3);
|
|
|
|
// Take January 4th as it is always in week 1 (see ISO 8601)
|
|
var firstThursday = new Date(thursday.getFullYear(), 0, 4);
|
|
|
|
// Change date to Thursday same week
|
|
firstThursday.setDate(firstThursday.getDate() - ((firstThursday.getDay() + 6) % 7) + 3);
|
|
|
|
// Check if daylight-saving-time-switch occurred and correct for it
|
|
var ds = thursday.getTimezoneOffset() - firstThursday.getTimezoneOffset();
|
|
thursday.setHours(thursday.getHours() - ds);
|
|
|
|
// Number of weeks between target Thursday and first Thursday
|
|
var weekDiff = (thursday - firstThursday) / (MILLISECONDS_IN_DAY * 7);
|
|
return 1 + Math.floor(weekDiff)
|
|
}
|
|
|
|
function getDayIdentifier (date) {
|
|
return date.getFullYear() * 10000 + date.getMonth() * 100 + date.getDate()
|
|
}
|
|
|
|
function getDateIdentifier (date, onlyDate /* = false */) {
|
|
var d = new Date(date);
|
|
return onlyDate === true ? getDayIdentifier(d) : d.getTime()
|
|
}
|
|
|
|
function isBetweenDates (date, from, to, opts) {
|
|
if ( opts === void 0 ) opts = {};
|
|
|
|
var
|
|
d1 = getDateIdentifier(from, opts.onlyDate),
|
|
d2 = getDateIdentifier(to, opts.onlyDate),
|
|
cur = getDateIdentifier(date, opts.onlyDate);
|
|
|
|
return (cur > d1 || (opts.inclusiveFrom === true && cur === d1)) &&
|
|
(cur < d2 || (opts.inclusiveTo === true && cur === d2))
|
|
}
|
|
|
|
function addToDate (date, mod) {
|
|
return getChange(date, mod, true)
|
|
}
|
|
function subtractFromDate (date, mod) {
|
|
return getChange(date, mod, false)
|
|
}
|
|
|
|
function adjustDate (date, mod, utc) {
|
|
var
|
|
t = new Date(date),
|
|
prefix = "set" + (utc ? 'UTC' : '');
|
|
|
|
Object.keys(mod).forEach(function (key) {
|
|
if (key === 'month') {
|
|
setMonth(t, mod.month);
|
|
return
|
|
}
|
|
|
|
var op = key === 'year'
|
|
? 'FullYear'
|
|
: key.charAt(0).toUpperCase() + key.slice(1);
|
|
t[("" + prefix + op)](mod[key]);
|
|
});
|
|
|
|
return t
|
|
}
|
|
|
|
function startOfDate (date, unit) {
|
|
var t = new Date(date);
|
|
switch (unit) {
|
|
case 'year':
|
|
t.setMonth(0);
|
|
case 'month':
|
|
t.setDate(1);
|
|
case 'day':
|
|
t.setHours(0);
|
|
case 'hour':
|
|
t.setMinutes(0);
|
|
case 'minute':
|
|
t.setSeconds(0);
|
|
case 'second':
|
|
t.setMilliseconds(0);
|
|
}
|
|
return t
|
|
}
|
|
|
|
function endOfDate (date, unit) {
|
|
var t = new Date(date);
|
|
switch (unit) {
|
|
case 'year':
|
|
t.setMonth(11);
|
|
case 'month':
|
|
t.setDate(daysInMonth(t));
|
|
case 'day':
|
|
t.setHours(23);
|
|
case 'hour':
|
|
t.setMinutes(59);
|
|
case 'minute':
|
|
t.setSeconds(59);
|
|
case 'second':
|
|
t.setMilliseconds(59);
|
|
}
|
|
return t
|
|
}
|
|
|
|
function getMaxDate (date /* , ...args */) {
|
|
var t = new Date(date);
|
|
Array.prototype.slice.call(arguments, 1).forEach(function (d) {
|
|
t = Math.max(t, new Date(d));
|
|
});
|
|
return t
|
|
}
|
|
|
|
function getMinDate (date /*, ...args */) {
|
|
var t = new Date(date);
|
|
Array.prototype.slice.call(arguments, 1).forEach(function (d) {
|
|
t = Math.min(t, new Date(d));
|
|
});
|
|
return t
|
|
}
|
|
|
|
function getDiff (t, sub, interval) {
|
|
return (
|
|
(t.getTime() - t.getTimezoneOffset() * MILLISECONDS_IN_MINUTE) -
|
|
(sub.getTime() - sub.getTimezoneOffset() * MILLISECONDS_IN_MINUTE)
|
|
) / interval
|
|
}
|
|
|
|
function getDateDiff (date, subtract, unit) {
|
|
if ( unit === void 0 ) unit = 'days';
|
|
|
|
var
|
|
t = new Date(date),
|
|
sub = new Date(subtract);
|
|
|
|
switch (unit) {
|
|
case 'years':
|
|
return (t.getFullYear() - sub.getFullYear())
|
|
|
|
case 'months':
|
|
return (t.getFullYear() - sub.getFullYear()) * 12 + t.getMonth() - sub.getMonth()
|
|
|
|
case 'days':
|
|
return getDiff(startOfDate(t, 'day'), startOfDate(sub, 'day'), MILLISECONDS_IN_DAY)
|
|
|
|
case 'hours':
|
|
return getDiff(startOfDate(t, 'hour'), startOfDate(sub, 'hour'), MILLISECONDS_IN_HOUR)
|
|
|
|
case 'minutes':
|
|
return getDiff(startOfDate(t, 'minute'), startOfDate(sub, 'minute'), MILLISECONDS_IN_MINUTE)
|
|
|
|
case 'seconds':
|
|
return getDiff(startOfDate(t, 'second'), startOfDate(sub, 'second'), 1000)
|
|
}
|
|
}
|
|
|
|
function getDayOfYear (date) {
|
|
return getDateDiff(date, startOfDate(date, 'year'), 'days') + 1
|
|
}
|
|
|
|
function inferDateFormat (date) {
|
|
return isDate(date) === true
|
|
? 'date'
|
|
: (typeof date === 'number' ? 'number' : 'string')
|
|
}
|
|
|
|
function getDateBetween (date, min, max) {
|
|
var t = new Date(date);
|
|
|
|
if (min) {
|
|
var low = new Date(min);
|
|
if (t < low) {
|
|
return low
|
|
}
|
|
}
|
|
|
|
if (max) {
|
|
var high = new Date(max);
|
|
if (t > high) {
|
|
return high
|
|
}
|
|
}
|
|
|
|
return t
|
|
}
|
|
|
|
function isSameDate (date, date2, unit) {
|
|
var
|
|
t = new Date(date),
|
|
d = new Date(date2);
|
|
|
|
if (unit === void 0) {
|
|
return t.getTime() === d.getTime()
|
|
}
|
|
|
|
switch (unit) {
|
|
case 'second':
|
|
if (t.getSeconds() !== d.getSeconds()) {
|
|
return false
|
|
}
|
|
case 'minute': // intentional fall-through
|
|
if (t.getMinutes() !== d.getMinutes()) {
|
|
return false
|
|
}
|
|
case 'hour': // intentional fall-through
|
|
if (t.getHours() !== d.getHours()) {
|
|
return false
|
|
}
|
|
case 'day': // intentional fall-through
|
|
if (t.getDate() !== d.getDate()) {
|
|
return false
|
|
}
|
|
case 'month': // intentional fall-through
|
|
if (t.getMonth() !== d.getMonth()) {
|
|
return false
|
|
}
|
|
case 'year': // intentional fall-through
|
|
if (t.getFullYear() !== d.getFullYear()) {
|
|
return false
|
|
}
|
|
break
|
|
default:
|
|
throw new Error(("date isSameDate unknown unit " + unit))
|
|
}
|
|
|
|
return true
|
|
}
|
|
|
|
function daysInMonth (date) {
|
|
return (new Date(date.getFullYear(), date.getMonth() + 1, 0)).getDate()
|
|
}
|
|
|
|
function getOrdinal (n) {
|
|
if (n >= 11 && n <= 13) {
|
|
return (n + "th")
|
|
}
|
|
switch (n % 10) {
|
|
case 1: return (n + "st")
|
|
case 2: return (n + "nd")
|
|
case 3: return (n + "rd")
|
|
}
|
|
return (n + "th")
|
|
}
|
|
|
|
var formatter = {
|
|
// Year: 00, 01, ..., 99
|
|
YY: function YY (date, _, forcedYear) {
|
|
// workaround for < 1900 with new Date()
|
|
var y = this.YYYY(date, _, forcedYear) % 100;
|
|
return y > 0
|
|
? pad(y)
|
|
: '-' + pad(Math.abs(y))
|
|
},
|
|
|
|
// Year: 1900, 1901, ..., 2099
|
|
YYYY: function YYYY (date, _, forcedYear) {
|
|
// workaround for < 1900 with new Date()
|
|
return forcedYear !== void 0 && forcedYear !== null
|
|
? forcedYear
|
|
: date.getFullYear()
|
|
},
|
|
|
|
// Month: 1, 2, ..., 12
|
|
M: function M (date) {
|
|
return date.getMonth() + 1
|
|
},
|
|
|
|
// Month: 01, 02, ..., 12
|
|
MM: function MM (date) {
|
|
return pad(date.getMonth() + 1)
|
|
},
|
|
|
|
// Month Short Name: Jan, Feb, ...
|
|
MMM: function MMM (date, dateLocale) {
|
|
return dateLocale.monthsShort[date.getMonth()]
|
|
},
|
|
|
|
// Month Name: January, February, ...
|
|
MMMM: function MMMM (date, dateLocale) {
|
|
return dateLocale.months[date.getMonth()]
|
|
},
|
|
|
|
// Quarter: 1, 2, 3, 4
|
|
Q: function Q (date) {
|
|
return Math.ceil((date.getMonth() + 1) / 3)
|
|
},
|
|
|
|
// Quarter: 1st, 2nd, 3rd, 4th
|
|
Qo: function Qo (date) {
|
|
return getOrdinal(this.Q(date))
|
|
},
|
|
|
|
// Day of month: 1, 2, ..., 31
|
|
D: function D (date) {
|
|
return date.getDate()
|
|
},
|
|
|
|
// Day of month: 1st, 2nd, ..., 31st
|
|
Do: function Do (date) {
|
|
return getOrdinal(date.getDate())
|
|
},
|
|
|
|
// Day of month: 01, 02, ..., 31
|
|
DD: function DD (date) {
|
|
return pad(date.getDate())
|
|
},
|
|
|
|
// Day of year: 1, 2, ..., 366
|
|
DDD: function DDD (date) {
|
|
return getDayOfYear(date)
|
|
},
|
|
|
|
// Day of year: 001, 002, ..., 366
|
|
DDDD: function DDDD (date) {
|
|
return pad(getDayOfYear(date), 3)
|
|
},
|
|
|
|
// Day of week: 0, 1, ..., 6
|
|
d: function d (date) {
|
|
return date.getDay()
|
|
},
|
|
|
|
// Day of week: Su, Mo, ...
|
|
dd: function dd (date, dateLocale) {
|
|
return this.dddd(date, dateLocale).slice(0, 2)
|
|
},
|
|
|
|
// Day of week: Sun, Mon, ...
|
|
ddd: function ddd (date, dateLocale) {
|
|
return dateLocale.daysShort[date.getDay()]
|
|
},
|
|
|
|
// Day of week: Sunday, Monday, ...
|
|
dddd: function dddd (date, dateLocale) {
|
|
return dateLocale.days[date.getDay()]
|
|
},
|
|
|
|
// Day of ISO week: 1, 2, ..., 7
|
|
E: function E (date) {
|
|
return date.getDay() || 7
|
|
},
|
|
|
|
// Week of Year: 1 2 ... 52 53
|
|
w: function w (date) {
|
|
return getWeekOfYear(date)
|
|
},
|
|
|
|
// Week of Year: 01 02 ... 52 53
|
|
ww: function ww (date) {
|
|
return pad(getWeekOfYear(date))
|
|
},
|
|
|
|
// Hour: 0, 1, ... 23
|
|
H: function H (date) {
|
|
return date.getHours()
|
|
},
|
|
|
|
// Hour: 00, 01, ..., 23
|
|
HH: function HH (date) {
|
|
return pad(date.getHours())
|
|
},
|
|
|
|
// Hour: 1, 2, ..., 12
|
|
h: function h (date) {
|
|
var hours = date.getHours();
|
|
if (hours === 0) {
|
|
return 12
|
|
}
|
|
if (hours > 12) {
|
|
return hours % 12
|
|
}
|
|
return hours
|
|
},
|
|
|
|
// Hour: 01, 02, ..., 12
|
|
hh: function hh (date) {
|
|
return pad(this.h(date))
|
|
},
|
|
|
|
// Minute: 0, 1, ..., 59
|
|
m: function m (date) {
|
|
return date.getMinutes()
|
|
},
|
|
|
|
// Minute: 00, 01, ..., 59
|
|
mm: function mm (date) {
|
|
return pad(date.getMinutes())
|
|
},
|
|
|
|
// Second: 0, 1, ..., 59
|
|
s: function s (date) {
|
|
return date.getSeconds()
|
|
},
|
|
|
|
// Second: 00, 01, ..., 59
|
|
ss: function ss (date) {
|
|
return pad(date.getSeconds())
|
|
},
|
|
|
|
// 1/10 of second: 0, 1, ..., 9
|
|
S: function S (date) {
|
|
return Math.floor(date.getMilliseconds() / 100)
|
|
},
|
|
|
|
// 1/100 of second: 00, 01, ..., 99
|
|
SS: function SS (date) {
|
|
return pad(Math.floor(date.getMilliseconds() / 10))
|
|
},
|
|
|
|
// Millisecond: 000, 001, ..., 999
|
|
SSS: function SSS (date) {
|
|
return pad(date.getMilliseconds(), 3)
|
|
},
|
|
|
|
// Meridiem: AM, PM
|
|
A: function A (date) {
|
|
return this.H(date) < 12 ? 'AM' : 'PM'
|
|
},
|
|
|
|
// Meridiem: am, pm
|
|
a: function a (date) {
|
|
return this.H(date) < 12 ? 'am' : 'pm'
|
|
},
|
|
|
|
// Meridiem: a.m., p.m.
|
|
aa: function aa (date) {
|
|
return this.H(date) < 12 ? 'a.m.' : 'p.m.'
|
|
},
|
|
|
|
// Timezone: -01:00, +00:00, ... +12:00
|
|
Z: function Z (date, dateLocale, forcedYear, forcedTimezoneOffset) {
|
|
var tzOffset = forcedTimezoneOffset === void 0 || forcedTimezoneOffset === null
|
|
? date.getTimezoneOffset()
|
|
: forcedTimezoneOffset;
|
|
|
|
return formatTimezone(tzOffset, ':')
|
|
},
|
|
|
|
// Timezone: -0100, +0000, ... +1200
|
|
ZZ: function ZZ (date, dateLocale, forcedYear, forcedTimezoneOffset) {
|
|
var tzOffset = forcedTimezoneOffset === void 0 || forcedTimezoneOffset === null
|
|
? date.getTimezoneOffset()
|
|
: forcedTimezoneOffset;
|
|
|
|
return formatTimezone(tzOffset)
|
|
},
|
|
|
|
// Seconds timestamp: 512969520
|
|
X: function X (date) {
|
|
return Math.floor(date.getTime() / 1000)
|
|
},
|
|
|
|
// Milliseconds timestamp: 512969520900
|
|
x: function x (date) {
|
|
return date.getTime()
|
|
}
|
|
};
|
|
|
|
function formatDate (val, mask, dateLocale, __forcedYear, __forcedTimezoneOffset) {
|
|
if (
|
|
(val !== 0 && !val) ||
|
|
val === Infinity ||
|
|
val === -Infinity
|
|
) {
|
|
return
|
|
}
|
|
|
|
var date = new Date(val);
|
|
|
|
if (isNaN(date)) {
|
|
return
|
|
}
|
|
|
|
if (mask === void 0) {
|
|
mask = defaultMask;
|
|
}
|
|
|
|
var locale = dateLocale !== void 0
|
|
? dateLocale
|
|
: lang.props.date;
|
|
|
|
return mask.replace(
|
|
token,
|
|
function (match, text) { return match in formatter
|
|
? formatter[match](date, locale, __forcedYear, __forcedTimezoneOffset)
|
|
: (text === void 0 ? match : text.split('\\]').join(']')); }
|
|
)
|
|
}
|
|
|
|
function clone (date) {
|
|
return isDate(date) === true
|
|
? new Date(date.getTime())
|
|
: date
|
|
}
|
|
|
|
var date = {
|
|
isValid: isValid,
|
|
extractDate: extractDate,
|
|
buildDate: buildDate,
|
|
getDayOfWeek: getDayOfWeek,
|
|
getWeekOfYear: getWeekOfYear,
|
|
isBetweenDates: isBetweenDates,
|
|
addToDate: addToDate,
|
|
subtractFromDate: subtractFromDate,
|
|
adjustDate: adjustDate,
|
|
startOfDate: startOfDate,
|
|
endOfDate: endOfDate,
|
|
getMaxDate: getMaxDate,
|
|
getMinDate: getMinDate,
|
|
getDateDiff: getDateDiff,
|
|
getDayOfYear: getDayOfYear,
|
|
inferDateFormat: inferDateFormat,
|
|
getDateBetween: getDateBetween,
|
|
isSameDate: isSameDate,
|
|
daysInMonth: daysInMonth,
|
|
formatDate: formatDate,
|
|
clone: clone
|
|
};
|
|
|
|
var yearsInterval = 20;
|
|
var views = [ 'Calendar', 'Years', 'Months' ];
|
|
var viewIsValid = function (v) { return views.includes(v); };
|
|
var yearMonthValidator = function (v) { return /^-?[\d]+\/[0-1]\d$/.test(v); };
|
|
var lineStr = ' \u2014 ';
|
|
|
|
var QDate = Vue.extend({
|
|
name: 'QDate',
|
|
|
|
mixins: [ DateTimeMixin ],
|
|
|
|
props: {
|
|
multiple: Boolean,
|
|
range: Boolean,
|
|
|
|
title: String,
|
|
subtitle: String,
|
|
|
|
mask: {
|
|
// this mask is forced
|
|
// when using persian calendar
|
|
default: 'YYYY/MM/DD'
|
|
},
|
|
|
|
defaultYearMonth: {
|
|
type: String,
|
|
validator: yearMonthValidator
|
|
},
|
|
|
|
yearsInMonthView: Boolean,
|
|
|
|
events: [ Array, Function ],
|
|
eventColor: [ String, Function ],
|
|
|
|
// DEPRECATED; TODO: remove in v2
|
|
emitImmediately: Boolean,
|
|
|
|
options: [ Array, Function ],
|
|
|
|
navigationMinYearMonth: {
|
|
type: String,
|
|
validator: yearMonthValidator
|
|
},
|
|
|
|
navigationMaxYearMonth: {
|
|
type: String,
|
|
validator: yearMonthValidator
|
|
},
|
|
|
|
noUnset: Boolean,
|
|
|
|
firstDayOfWeek: [ String, Number ],
|
|
todayBtn: Boolean,
|
|
minimal: Boolean,
|
|
defaultView: {
|
|
type: String,
|
|
default: 'Calendar',
|
|
validator: viewIsValid
|
|
}
|
|
},
|
|
|
|
data: function data () {
|
|
var
|
|
innerMask = this.__getMask(),
|
|
innerLocale = this.__getLocale(),
|
|
viewModel = this.__getViewModel(innerMask, innerLocale),
|
|
year = viewModel.year,
|
|
direction = this.$q.lang.rtl === true ? 'right' : 'left';
|
|
|
|
return {
|
|
view: this.defaultView,
|
|
monthDirection: direction,
|
|
yearDirection: direction,
|
|
startYear: year - (year % yearsInterval) - (year < 0 ? yearsInterval : 0),
|
|
editRange: void 0,
|
|
innerMask: innerMask,
|
|
innerLocale: innerLocale,
|
|
viewModel: viewModel // model of current calendar view
|
|
}
|
|
},
|
|
|
|
watch: {
|
|
value: function value (v) {
|
|
if (this.lastEmitValue === v) {
|
|
this.lastEmitValue = 0;
|
|
}
|
|
else {
|
|
var ref = this.__getViewModel(this.innerMask, this.innerLocale);
|
|
var year = ref.year;
|
|
var month = ref.month;
|
|
this.__updateViewModel(year, month);
|
|
}
|
|
},
|
|
|
|
view: function view () {
|
|
this.$refs.blurTarget !== void 0 && this.$refs.blurTarget.focus();
|
|
},
|
|
|
|
'viewModel.year': function viewModel_year (year) {
|
|
this.$emit('navigation', { year: year, month: this.viewModel.month });
|
|
},
|
|
|
|
'viewModel.month': function viewModel_month (month) {
|
|
this.$emit('navigation', { year: this.viewModel.year, month: month });
|
|
},
|
|
|
|
computedMask: function computedMask (val) {
|
|
this.__updateValue(val, this.innerLocale, 'mask');
|
|
this.innerMask = val;
|
|
},
|
|
|
|
computedLocale: function computedLocale (val) {
|
|
this.__updateValue(this.innerMask, val, 'locale');
|
|
this.innerLocale = val;
|
|
}
|
|
},
|
|
|
|
computed: {
|
|
classes: function classes () {
|
|
var type = this.landscape === true ? 'landscape' : 'portrait';
|
|
return "q-date q-date--" + type + " q-date--" + type + "-" + (this.minimal === true ? 'minimal' : 'standard') +
|
|
(this.isDark === true ? ' q-date--dark q-dark' : '') +
|
|
(this.bordered === true ? " q-date--bordered" : '') +
|
|
(this.square === true ? " q-date--square no-border-radius" : '') +
|
|
(this.flat === true ? " q-date--flat no-shadow" : '') +
|
|
(this.disable === true ? ' disabled' : (this.readonly === true ? ' q-date--readonly' : ''))
|
|
},
|
|
|
|
// DEPRECATED; TODO: remove in v2
|
|
isImmediate: function isImmediate () {
|
|
return this.emitImmediately === true &&
|
|
this.daysModel[0] !== void 0 &&
|
|
this.daysModel[0].dateHash !== null
|
|
},
|
|
|
|
normalizedModel: function normalizedModel () {
|
|
return Array.isArray(this.value) === true
|
|
? this.value
|
|
: (this.value !== null && this.value !== void 0 ? [ this.value ] : [])
|
|
},
|
|
|
|
daysModel: function daysModel () {
|
|
var this$1 = this;
|
|
|
|
return this.normalizedModel
|
|
.filter(function (date) { return typeof date === 'string'; })
|
|
.map(function (date) { return this$1.__decodeString(date, this$1.innerMask, this$1.innerLocale); })
|
|
.filter(function (date) { return date.dateHash !== null; })
|
|
},
|
|
|
|
rangeModel: function rangeModel () {
|
|
var this$1 = this;
|
|
|
|
var fn = function (date) { return this$1.__decodeString(date, this$1.innerMask, this$1.innerLocale); };
|
|
return this.normalizedModel
|
|
.filter(function (date) { return Object(date) === date && date.from !== void 0 && date.to !== void 0; })
|
|
.map(function (range) { return ({ from: fn(range.from), to: fn(range.to) }); })
|
|
.filter(function (range) { return range.from.dateHash !== null && range.to.dateHash !== null && range.from.dateHash < range.to.dateHash; })
|
|
},
|
|
|
|
getNativeDateFn: function getNativeDateFn () {
|
|
return this.calendar !== 'persian'
|
|
? function (model) { return new Date(model.year, model.month - 1, model.day); }
|
|
: function (model) {
|
|
var gDate = toGregorian(model.year, model.month, model.day);
|
|
return new Date(gDate.gy, gDate.gm - 1, gDate.gd)
|
|
}
|
|
},
|
|
|
|
encodeObjectFn: function encodeObjectFn () {
|
|
var this$1 = this;
|
|
|
|
return this.calendar === 'persian'
|
|
? this.__getDayHash
|
|
: function (date, mask, locale) { return formatDate(
|
|
new Date(
|
|
date.year,
|
|
date.month - 1,
|
|
date.day,
|
|
date.hour,
|
|
date.minute,
|
|
date.second,
|
|
date.millisecond
|
|
),
|
|
mask === void 0 ? this$1.innerMask : mask,
|
|
locale === void 0 ? this$1.innerLocale : locale,
|
|
date.year,
|
|
date.timezoneOffset
|
|
); }
|
|
},
|
|
|
|
daysInModel: function daysInModel () {
|
|
var this$1 = this;
|
|
|
|
return this.daysModel.length + this.rangeModel.reduce(
|
|
function (acc, range) { return acc + 1 + getDateDiff(
|
|
this$1.getNativeDateFn(range.to),
|
|
this$1.getNativeDateFn(range.from)
|
|
); },
|
|
0
|
|
)
|
|
},
|
|
|
|
headerTitle: function headerTitle () {
|
|
if (this.title !== void 0 && this.title !== null && this.title.length > 0) {
|
|
return this.title
|
|
}
|
|
|
|
if (this.editRange !== void 0) {
|
|
var model$1 = this.editRange.init;
|
|
var date$1 = this.getNativeDateFn(model$1);
|
|
|
|
return this.innerLocale.daysShort[ date$1.getDay() ] + ', ' +
|
|
this.innerLocale.monthsShort[ model$1.month - 1 ] + ' ' +
|
|
model$1.day + lineStr + '?'
|
|
}
|
|
|
|
if (this.daysInModel === 0) {
|
|
return lineStr
|
|
}
|
|
|
|
if (this.daysInModel > 1) {
|
|
return ((this.daysInModel) + " " + (this.innerLocale.pluralDay))
|
|
}
|
|
|
|
var model = this.daysModel[0];
|
|
var date = this.getNativeDateFn(model);
|
|
|
|
if (isNaN(date.valueOf()) === true) {
|
|
return lineStr
|
|
}
|
|
|
|
if (this.innerLocale.headerTitle !== void 0) {
|
|
return this.innerLocale.headerTitle(date, model)
|
|
}
|
|
|
|
return this.innerLocale.daysShort[ date.getDay() ] + ', ' +
|
|
this.innerLocale.monthsShort[ model.month - 1 ] + ' ' +
|
|
model.day
|
|
},
|
|
|
|
headerSubtitle: function headerSubtitle () {
|
|
if (this.subtitle !== void 0 && this.subtitle !== null && this.subtitle.length > 0) {
|
|
return this.subtitle
|
|
}
|
|
|
|
if (this.daysInModel === 0) {
|
|
return lineStr
|
|
}
|
|
|
|
if (this.daysInModel > 1) {
|
|
var from = this.minSelectedModel;
|
|
var to = this.maxSelectedModel;
|
|
var month = this.innerLocale.monthsShort;
|
|
|
|
return month[from.month - 1] + (
|
|
from.year !== to.year
|
|
? ' ' + from.year + lineStr + month[to.month - 1] + ' '
|
|
: (
|
|
from.month !== to.month
|
|
? lineStr + month[to.month - 1]
|
|
: ''
|
|
)
|
|
) + ' ' + to.year
|
|
}
|
|
|
|
return this.daysModel[0].year
|
|
},
|
|
|
|
minSelectedModel: function minSelectedModel () {
|
|
var model = this.daysModel.concat(this.rangeModel.map(function (range) { return range.from; }))
|
|
.sort(function (a, b) { return a.year - b.year || a.month - b.month; });
|
|
|
|
return model[0]
|
|
},
|
|
|
|
maxSelectedModel: function maxSelectedModel () {
|
|
var model = this.daysModel.concat(this.rangeModel.map(function (range) { return range.to; }))
|
|
.sort(function (a, b) { return b.year - a.year || b.month - a.month; });
|
|
|
|
return model[0]
|
|
},
|
|
|
|
dateArrow: function dateArrow () {
|
|
var val = [ this.$q.iconSet.datetime.arrowLeft, this.$q.iconSet.datetime.arrowRight ];
|
|
return this.$q.lang.rtl === true ? val.reverse() : val
|
|
},
|
|
|
|
computedFirstDayOfWeek: function computedFirstDayOfWeek () {
|
|
return this.firstDayOfWeek !== void 0
|
|
? Number(this.firstDayOfWeek)
|
|
: this.innerLocale.firstDayOfWeek
|
|
},
|
|
|
|
daysOfWeek: function daysOfWeek () {
|
|
var
|
|
days = this.innerLocale.daysShort,
|
|
first = this.computedFirstDayOfWeek;
|
|
|
|
return first > 0
|
|
? days.slice(first, 7).concat(days.slice(0, first))
|
|
: days
|
|
},
|
|
|
|
daysInMonth: function daysInMonth () {
|
|
var date = this.viewModel;
|
|
return this.calendar !== 'persian'
|
|
? (new Date(date.year, date.month, 0)).getDate()
|
|
: jalaaliMonthLength(date.year, date.month)
|
|
},
|
|
|
|
today: function today () {
|
|
return this.__getCurrentDate()
|
|
},
|
|
|
|
evtColor: function evtColor () {
|
|
var this$1 = this;
|
|
|
|
return typeof this.eventColor === 'function'
|
|
? this.eventColor
|
|
: function () { return this$1.eventColor; }
|
|
},
|
|
|
|
minNav: function minNav () {
|
|
if (this.navigationMinYearMonth !== void 0) {
|
|
var data = this.navigationMinYearMonth.split('/');
|
|
return { year: parseInt(data[0], 10), month: parseInt(data[1], 10) }
|
|
}
|
|
},
|
|
|
|
maxNav: function maxNav () {
|
|
if (this.navigationMaxYearMonth !== void 0) {
|
|
var data = this.navigationMaxYearMonth.split('/');
|
|
return { year: parseInt(data[0], 10), month: parseInt(data[1], 10) }
|
|
}
|
|
},
|
|
|
|
navBoundaries: function navBoundaries () {
|
|
var data = {
|
|
month: { prev: true, next: true },
|
|
year: { prev: true, next: true }
|
|
};
|
|
|
|
if (this.minNav !== void 0 && this.minNav.year >= this.viewModel.year) {
|
|
data.year.prev = false;
|
|
if (this.minNav.year === this.viewModel.year && this.minNav.month >= this.viewModel.month) {
|
|
data.month.prev = false;
|
|
}
|
|
}
|
|
|
|
if (this.maxNav !== void 0 && this.maxNav.year <= this.viewModel.year) {
|
|
data.year.next = false;
|
|
if (this.maxNav.year === this.viewModel.year && this.maxNav.month <= this.viewModel.month) {
|
|
data.month.next = false;
|
|
}
|
|
}
|
|
|
|
return data
|
|
},
|
|
|
|
daysMap: function daysMap () {
|
|
var this$1 = this;
|
|
|
|
var map = {};
|
|
|
|
this.daysModel.forEach(function (entry) {
|
|
var hash = this$1.__getMonthHash(entry);
|
|
|
|
if (map[hash] === void 0) {
|
|
map[hash] = [];
|
|
}
|
|
|
|
map[hash].push(entry.day);
|
|
});
|
|
|
|
return map
|
|
},
|
|
|
|
rangeMap: function rangeMap () {
|
|
var this$1 = this;
|
|
|
|
var map = {};
|
|
|
|
this.rangeModel.forEach(function (entry) {
|
|
var hashFrom = this$1.__getMonthHash(entry.from);
|
|
var hashTo = this$1.__getMonthHash(entry.to);
|
|
|
|
if (map[hashFrom] === void 0) {
|
|
map[hashFrom] = [];
|
|
}
|
|
|
|
map[hashFrom].push({
|
|
from: entry.from.day,
|
|
to: hashFrom === hashTo ? entry.to.day : void 0,
|
|
range: entry
|
|
});
|
|
|
|
if (hashFrom < hashTo) {
|
|
var hash;
|
|
var ref = entry.from;
|
|
var year = ref.year;
|
|
var month = ref.month;
|
|
var cur = month < 12
|
|
? { year: year, month: month + 1 }
|
|
: { year: year + 1, month: 1 };
|
|
|
|
while ((hash = this$1.__getMonthHash(cur)) <= hashTo) {
|
|
if (map[hash] === void 0) {
|
|
map[hash] = [];
|
|
}
|
|
|
|
map[hash].push({
|
|
from: void 0,
|
|
to: hash === hashTo ? entry.to.day : void 0,
|
|
range: entry
|
|
});
|
|
|
|
cur.month++;
|
|
if (cur.month > 12) {
|
|
cur.year++;
|
|
cur.month = 1;
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
return map
|
|
},
|
|
|
|
rangeView: function rangeView () {
|
|
if (this.editRange === void 0) {
|
|
return
|
|
}
|
|
|
|
var ref = this.editRange;
|
|
var init = ref.init;
|
|
var initHash = ref.initHash;
|
|
var final = ref.final;
|
|
var finalHash = ref.finalHash;
|
|
|
|
var ref$1 = initHash <= finalHash
|
|
? [ init, final ]
|
|
: [ final, init ];
|
|
var from = ref$1[0];
|
|
var to = ref$1[1];
|
|
|
|
var fromHash = this.__getMonthHash(from);
|
|
var toHash = this.__getMonthHash(to);
|
|
|
|
if (fromHash !== this.viewMonthHash && toHash !== this.viewMonthHash) {
|
|
return
|
|
}
|
|
|
|
var view = {};
|
|
|
|
if (fromHash === this.viewMonthHash) {
|
|
view.from = from.day;
|
|
view.includeFrom = true;
|
|
}
|
|
else {
|
|
view.from = 1;
|
|
}
|
|
|
|
if (toHash === this.viewMonthHash) {
|
|
view.to = to.day;
|
|
view.includeTo = true;
|
|
}
|
|
else {
|
|
view.to = this.daysInMonth;
|
|
}
|
|
|
|
return view
|
|
},
|
|
|
|
viewMonthHash: function viewMonthHash () {
|
|
return this.__getMonthHash(this.viewModel)
|
|
},
|
|
|
|
selectionDaysMap: function selectionDaysMap () {
|
|
var this$1 = this;
|
|
|
|
var map = {};
|
|
|
|
if (this.options === void 0) {
|
|
for (var i = 1; i <= this.daysInMonth; i++) {
|
|
map[i] = true;
|
|
}
|
|
|
|
return map
|
|
}
|
|
|
|
var fn = typeof this.options === 'function'
|
|
? this.options
|
|
: function (date) { return this$1.options.includes(date); };
|
|
|
|
for (var i$1 = 1; i$1 <= this.daysInMonth; i$1++) {
|
|
var dayHash = this.viewMonthHash + '/' + pad(i$1);
|
|
map[i$1] = fn(dayHash);
|
|
}
|
|
|
|
return map
|
|
},
|
|
|
|
eventDaysMap: function eventDaysMap () {
|
|
var this$1 = this;
|
|
|
|
var map = {};
|
|
|
|
if (this.events === void 0) {
|
|
for (var i = 1; i <= this.daysInMonth; i++) {
|
|
map[i] = false;
|
|
}
|
|
}
|
|
else {
|
|
var fn = typeof this.events === 'function'
|
|
? this.events
|
|
: function (date) { return this$1.events.includes(date); };
|
|
|
|
for (var i$1 = 1; i$1 <= this.daysInMonth; i$1++) {
|
|
var dayHash = this.viewMonthHash + '/' + pad(i$1);
|
|
map[i$1] = fn(dayHash) === true && this.evtColor(dayHash);
|
|
}
|
|
}
|
|
|
|
return map
|
|
},
|
|
|
|
viewDays: function viewDays () {
|
|
var date, endDay;
|
|
var ref = this.viewModel;
|
|
var year = ref.year;
|
|
var month = ref.month;
|
|
|
|
if (this.calendar !== 'persian') {
|
|
date = new Date(year, month - 1, 1);
|
|
endDay = (new Date(year, month - 1, 0)).getDate();
|
|
}
|
|
else {
|
|
var gDate = toGregorian(year, month, 1);
|
|
date = new Date(gDate.gy, gDate.gm - 1, gDate.gd);
|
|
var prevJM = month - 1;
|
|
var prevJY = year;
|
|
if (prevJM === 0) {
|
|
prevJM = 12;
|
|
prevJY--;
|
|
}
|
|
endDay = jalaaliMonthLength(prevJY, prevJM);
|
|
}
|
|
|
|
return {
|
|
days: date.getDay() - this.computedFirstDayOfWeek - 1,
|
|
endDay: endDay
|
|
}
|
|
},
|
|
|
|
days: function days () {
|
|
var this$1 = this;
|
|
|
|
var res = [];
|
|
var ref = this.viewDays;
|
|
var days = ref.days;
|
|
var endDay = ref.endDay;
|
|
|
|
var len = days < 0 ? days + 7 : days;
|
|
if (len < 6) {
|
|
for (var i = endDay - len; i <= endDay; i++) {
|
|
res.push({ i: i, fill: true });
|
|
}
|
|
}
|
|
|
|
var index = res.length;
|
|
|
|
for (var i$1 = 1; i$1 <= this.daysInMonth; i$1++) {
|
|
var day = { i: i$1, event: this.eventDaysMap[i$1], classes: [] };
|
|
|
|
if (this.selectionDaysMap[i$1] === true) {
|
|
day.in = true;
|
|
day.flat = true;
|
|
}
|
|
|
|
res.push(day);
|
|
}
|
|
|
|
// if current view has days in model
|
|
if (this.daysMap[this.viewMonthHash] !== void 0) {
|
|
this.daysMap[this.viewMonthHash].forEach(function (day) {
|
|
var i = index + day - 1;
|
|
Object.assign(res[i], {
|
|
selected: true,
|
|
unelevated: true,
|
|
flat: false,
|
|
color: this$1.computedColor,
|
|
textColor: this$1.computedTextColor
|
|
});
|
|
});
|
|
}
|
|
|
|
// if current view has ranges in model
|
|
if (this.rangeMap[this.viewMonthHash] !== void 0) {
|
|
this.rangeMap[this.viewMonthHash].forEach(function (entry) {
|
|
if (entry.from !== void 0) {
|
|
var from = index + entry.from - 1;
|
|
var to = index + (entry.to || this$1.daysInMonth) - 1;
|
|
|
|
for (var day = from; day <= to; day++) {
|
|
Object.assign(res[day], {
|
|
range: entry.range,
|
|
unelevated: true,
|
|
color: this$1.computedColor,
|
|
textColor: this$1.computedTextColor
|
|
});
|
|
}
|
|
|
|
Object.assign(res[from], {
|
|
rangeFrom: true,
|
|
flat: false
|
|
});
|
|
|
|
entry.to !== void 0 && Object.assign(res[to], {
|
|
rangeTo: true,
|
|
flat: false
|
|
});
|
|
}
|
|
else if (entry.to !== void 0) {
|
|
var to$1 = index + entry.to - 1;
|
|
|
|
for (var day$1 = index; day$1 <= to$1; day$1++) {
|
|
Object.assign(res[day$1], {
|
|
range: entry.range,
|
|
unelevated: true,
|
|
color: this$1.computedColor,
|
|
textColor: this$1.computedTextColor
|
|
});
|
|
}
|
|
|
|
Object.assign(res[to$1], {
|
|
flat: false,
|
|
rangeTo: true
|
|
});
|
|
}
|
|
else {
|
|
var to$2 = index + this$1.daysInMonth - 1;
|
|
for (var day$2 = index; day$2 <= to$2; day$2++) {
|
|
Object.assign(res[day$2], {
|
|
range: entry.range,
|
|
unelevated: true,
|
|
color: this$1.computedColor,
|
|
textColor: this$1.computedTextColor
|
|
});
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
if (this.rangeView !== void 0) {
|
|
var from = index + this.rangeView.from - 1;
|
|
var to = index + this.rangeView.to - 1;
|
|
|
|
for (var day$1 = from; day$1 <= to; day$1++) {
|
|
res[day$1].color = this.computedColor;
|
|
res[day$1].editRange = true;
|
|
}
|
|
|
|
if (this.rangeView.includeFrom === true) {
|
|
res[from].editRangeFrom = true;
|
|
}
|
|
if (this.rangeView.includeTo === true) {
|
|
res[to].editRangeTo = true;
|
|
}
|
|
}
|
|
|
|
if (this.viewModel.year === this.today.year && this.viewModel.month === this.today.month) {
|
|
res[index + this.today.day - 1].today = true;
|
|
}
|
|
|
|
var left = res.length % 7;
|
|
if (left > 0) {
|
|
var afterDays = 7 - left;
|
|
for (var i$2 = 1; i$2 <= afterDays; i$2++) {
|
|
res.push({ i: i$2, fill: true });
|
|
}
|
|
}
|
|
|
|
res.forEach(function (day) {
|
|
var cls = "q-date__calendar-item ";
|
|
|
|
if (day.fill === true) {
|
|
cls += 'q-date__calendar-item--fill';
|
|
}
|
|
else {
|
|
cls += "q-date__calendar-item--" + (day.in === true ? 'in' : 'out');
|
|
|
|
if (day.range !== void 0) {
|
|
cls += " q-date__range" + (day.rangeTo === true ? '-to' : (day.rangeFrom === true ? '-from' : ''));
|
|
}
|
|
|
|
if (day.editRange === true) {
|
|
cls += " q-date__edit-range" + (day.editRangeFrom === true ? '-from' : '') + (day.editRangeTo === true ? '-to' : '');
|
|
}
|
|
|
|
if (day.range !== void 0 || day.editRange === true) {
|
|
cls += " text-" + (day.color);
|
|
}
|
|
}
|
|
|
|
day.classes = cls;
|
|
});
|
|
|
|
return res
|
|
},
|
|
|
|
attrs: function attrs () {
|
|
if (this.disable === true) {
|
|
return { 'aria-disabled': 'true' }
|
|
}
|
|
if (this.readonly === true) {
|
|
return { 'aria-readonly': 'true' }
|
|
}
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
setToday: function setToday () {
|
|
this.__toggleDate(this.today, this.__getMonthHash(this.today));
|
|
this.setCalendarTo(this.today.year, this.today.month);
|
|
},
|
|
|
|
setView: function setView (view) {
|
|
if (viewIsValid(view) === true) {
|
|
this.view = view;
|
|
}
|
|
},
|
|
|
|
offsetCalendar: function offsetCalendar (type, descending) {
|
|
if (['month', 'year'].includes(type)) {
|
|
this[("__goTo" + (type === 'month' ? 'Month' : 'Year'))](
|
|
descending === true ? -1 : 1
|
|
);
|
|
}
|
|
},
|
|
|
|
setCalendarTo: function setCalendarTo (year, month) {
|
|
this.view = 'Calendar';
|
|
this.__updateViewModel(year, month);
|
|
},
|
|
|
|
setEditingRange: function setEditingRange (from, to) {
|
|
if (this.range === false || !from) {
|
|
this.editRange = void 0;
|
|
return
|
|
}
|
|
|
|
var init = Object.assign(Object.assign({}, this.viewModel), from);
|
|
var final = to !== void 0
|
|
? Object.assign(Object.assign({}, this.viewModel), to)
|
|
: init;
|
|
|
|
this.editRange = {
|
|
init: init,
|
|
initHash: this.__getDayHash(init),
|
|
final: final,
|
|
finalHash: this.__getDayHash(final)
|
|
};
|
|
|
|
this.setCalendarTo(init.year, init.month);
|
|
},
|
|
|
|
__getMask: function __getMask () {
|
|
return this.calendar === 'persian' ? 'YYYY/MM/DD' : this.mask
|
|
},
|
|
|
|
__decodeString: function __decodeString (date, mask, locale) {
|
|
return __splitDate(
|
|
date,
|
|
mask,
|
|
locale,
|
|
this.calendar,
|
|
{
|
|
hour: 0,
|
|
minute: 0,
|
|
second: 0,
|
|
millisecond: 0
|
|
}
|
|
)
|
|
},
|
|
|
|
__getViewModel: function __getViewModel (mask, locale) {
|
|
var model = Array.isArray(this.value) === true
|
|
? this.value
|
|
: (this.value ? [ this.value ] : []);
|
|
|
|
if (model.length === 0) {
|
|
return this.__getDefaultViewModel()
|
|
}
|
|
|
|
var decoded = this.__decodeString(
|
|
model[0].from !== void 0 ? model[0].from : model[0],
|
|
mask,
|
|
locale
|
|
);
|
|
|
|
return decoded.dateHash === null
|
|
? this.__getDefaultViewModel()
|
|
: decoded
|
|
},
|
|
|
|
__getDefaultViewModel: function __getDefaultViewModel () {
|
|
var year, month;
|
|
|
|
if (this.defaultYearMonth !== void 0) {
|
|
var d = this.defaultYearMonth.split('/');
|
|
year = parseInt(d[0], 10);
|
|
month = parseInt(d[1], 10);
|
|
}
|
|
else {
|
|
// may come from data() where computed
|
|
// props are not yet available
|
|
var d$1 = this.today !== void 0
|
|
? this.today
|
|
: this.__getCurrentDate();
|
|
|
|
year = d$1.year;
|
|
month = d$1.month;
|
|
}
|
|
|
|
return {
|
|
year: year,
|
|
month: month,
|
|
day: 1,
|
|
hour: 0,
|
|
minute: 0,
|
|
second: 0,
|
|
millisecond: 0,
|
|
dateHash: year + '/' + pad(month) + '/01'
|
|
}
|
|
},
|
|
|
|
__getHeader: function __getHeader (h) {
|
|
var this$1 = this;
|
|
|
|
if (this.minimal === true) { return }
|
|
|
|
return h('div', {
|
|
staticClass: 'q-date__header',
|
|
class: this.headerClass
|
|
}, [
|
|
h('div', {
|
|
staticClass: 'relative-position'
|
|
}, [
|
|
h('transition', {
|
|
props: {
|
|
name: 'q-transition--fade'
|
|
}
|
|
}, [
|
|
h('div', {
|
|
key: 'h-yr-' + this.headerSubtitle,
|
|
staticClass: 'q-date__header-subtitle q-date__header-link',
|
|
class: this.view === 'Years' ? 'q-date__header-link--active' : 'cursor-pointer',
|
|
attrs: { tabindex: this.computedTabindex },
|
|
on: cache(this, 'vY', {
|
|
click: function () { this$1.view = 'Years'; },
|
|
keyup: function (e) { e.keyCode === 13 && (this$1.view = 'Years'); }
|
|
})
|
|
}, [ this.headerSubtitle ])
|
|
])
|
|
]),
|
|
|
|
h('div', {
|
|
staticClass: 'q-date__header-title relative-position flex no-wrap'
|
|
}, [
|
|
h('div', {
|
|
staticClass: 'relative-position col'
|
|
}, [
|
|
h('transition', {
|
|
props: {
|
|
name: 'q-transition--fade'
|
|
}
|
|
}, [
|
|
h('div', {
|
|
key: 'h-sub' + this.headerTitle,
|
|
staticClass: 'q-date__header-title-label q-date__header-link',
|
|
class: this.view === 'Calendar' ? 'q-date__header-link--active' : 'cursor-pointer',
|
|
attrs: { tabindex: this.computedTabindex },
|
|
on: cache(this, 'vC', {
|
|
click: function () { this$1.view = 'Calendar'; },
|
|
keyup: function (e) { e.keyCode === 13 && (this$1.view = 'Calendar'); }
|
|
})
|
|
}, [ this.headerTitle ])
|
|
])
|
|
]),
|
|
|
|
this.todayBtn === true ? h(QBtn, {
|
|
staticClass: 'q-date__header-today self-start',
|
|
props: {
|
|
icon: this.$q.iconSet.datetime.today,
|
|
flat: true,
|
|
size: 'sm',
|
|
round: true,
|
|
tabindex: this.computedTabindex
|
|
},
|
|
on: cache(this, 'today', { click: this.setToday })
|
|
}) : null
|
|
])
|
|
])
|
|
},
|
|
|
|
__getNavigation: function __getNavigation (h, ref) {
|
|
var this$1 = this;
|
|
var label = ref.label;
|
|
var view = ref.view;
|
|
var key = ref.key;
|
|
var dir = ref.dir;
|
|
var goTo = ref.goTo;
|
|
var boundaries = ref.boundaries;
|
|
var cls = ref.cls;
|
|
|
|
return [
|
|
h('div', {
|
|
staticClass: 'row items-center q-date__arrow'
|
|
}, [
|
|
h(QBtn, {
|
|
props: {
|
|
round: true,
|
|
dense: true,
|
|
size: 'sm',
|
|
flat: true,
|
|
icon: this.dateArrow[0],
|
|
tabindex: this.computedTabindex,
|
|
disable: boundaries.prev === false
|
|
},
|
|
on: cache(this, 'go-#' + view, { click: function click () { goTo(-1); } })
|
|
})
|
|
]),
|
|
|
|
h('div', {
|
|
staticClass: 'relative-position overflow-hidden flex flex-center' + cls
|
|
}, [
|
|
h('transition', {
|
|
props: {
|
|
name: 'q-transition--jump-' + dir
|
|
}
|
|
}, [
|
|
h('div', { key: key }, [
|
|
h(QBtn, {
|
|
props: {
|
|
flat: true,
|
|
dense: true,
|
|
noCaps: true,
|
|
label: label,
|
|
tabindex: this.computedTabindex
|
|
},
|
|
on: cache(this, 'view#' + view, { click: function () { this$1.view = view; } })
|
|
})
|
|
])
|
|
])
|
|
]),
|
|
|
|
h('div', {
|
|
staticClass: 'row items-center q-date__arrow'
|
|
}, [
|
|
h(QBtn, {
|
|
props: {
|
|
round: true,
|
|
dense: true,
|
|
size: 'sm',
|
|
flat: true,
|
|
icon: this.dateArrow[1],
|
|
tabindex: this.computedTabindex,
|
|
disable: boundaries.next === false
|
|
},
|
|
on: cache(this, 'go+#' + view, { click: function click () { goTo(1); } })
|
|
})
|
|
])
|
|
]
|
|
},
|
|
|
|
__getCalendarView: function __getCalendarView (h) {
|
|
var this$1 = this;
|
|
|
|
return [
|
|
h('div', {
|
|
key: 'calendar-view',
|
|
staticClass: 'q-date__view q-date__calendar'
|
|
}, [
|
|
h('div', {
|
|
staticClass: 'q-date__navigation row items-center no-wrap'
|
|
}, this.__getNavigation(h, {
|
|
label: this.innerLocale.months[ this.viewModel.month - 1 ],
|
|
view: 'Months',
|
|
key: this.viewModel.month,
|
|
dir: this.monthDirection,
|
|
goTo: this.__goToMonth,
|
|
boundaries: this.navBoundaries.month,
|
|
cls: ' col'
|
|
}).concat(this.__getNavigation(h, {
|
|
label: this.viewModel.year,
|
|
view: 'Years',
|
|
key: this.viewModel.year,
|
|
dir: this.yearDirection,
|
|
goTo: this.__goToYear,
|
|
boundaries: this.navBoundaries.year,
|
|
cls: ''
|
|
}))),
|
|
|
|
h('div', {
|
|
staticClass: 'q-date__calendar-weekdays row items-center no-wrap'
|
|
}, this.daysOfWeek.map(function (day) { return h('div', { staticClass: 'q-date__calendar-item' }, [ h('div', [ day ]) ]); })),
|
|
|
|
h('div', {
|
|
staticClass: 'q-date__calendar-days-container relative-position overflow-hidden'
|
|
}, [
|
|
h('transition', {
|
|
props: {
|
|
name: 'q-transition--slide-' + this.monthDirection
|
|
}
|
|
}, [
|
|
h('div', {
|
|
key: this.viewMonthHash,
|
|
staticClass: 'q-date__calendar-days fit'
|
|
}, this.days.map(function (day) { return h('div', { staticClass: day.classes }, [
|
|
day.in === true
|
|
? h(QBtn, {
|
|
staticClass: day.today === true ? 'q-date__today' : null,
|
|
props: {
|
|
dense: true,
|
|
flat: day.flat,
|
|
unelevated: day.unelevated,
|
|
color: day.color,
|
|
textColor: day.textColor,
|
|
label: day.i,
|
|
tabindex: this$1.computedTabindex
|
|
},
|
|
on: cache(this$1, 'day#' + day.i, {
|
|
click: function () { this$1.__onDayClick(day.i); },
|
|
mouseover: function () { this$1.__onDayMouseover(day.i); }
|
|
})
|
|
}, day.event !== false ? [
|
|
h('div', { staticClass: 'q-date__event bg-' + day.event })
|
|
] : null)
|
|
: h('div', [ day.i ])
|
|
]); }))
|
|
])
|
|
])
|
|
])
|
|
]
|
|
},
|
|
|
|
__getMonthsView: function __getMonthsView (h) {
|
|
var this$1 = this;
|
|
|
|
var currentYear = this.viewModel.year === this.today.year;
|
|
var isDisabled = function (month) {
|
|
return (
|
|
(this$1.minNav !== void 0 && this$1.viewModel.year === this$1.minNav.year && this$1.minNav.month > month) ||
|
|
(this$1.maxNav !== void 0 && this$1.viewModel.year === this$1.maxNav.year && this$1.maxNav.month < month)
|
|
)
|
|
};
|
|
|
|
var content = this.innerLocale.monthsShort.map(function (month, i) {
|
|
var active = this$1.viewModel.month === i + 1;
|
|
|
|
return h('div', {
|
|
staticClass: 'q-date__months-item flex flex-center'
|
|
}, [
|
|
h(QBtn, {
|
|
staticClass: currentYear === true && this$1.today.month === i + 1 ? 'q-date__today' : null,
|
|
props: {
|
|
flat: active !== true,
|
|
label: month,
|
|
unelevated: active,
|
|
color: active === true ? this$1.computedColor : null,
|
|
textColor: active === true ? this$1.computedTextColor : null,
|
|
tabindex: this$1.computedTabindex,
|
|
disable: isDisabled(i + 1)
|
|
},
|
|
on: cache(this$1, 'month#' + i, { click: function () { this$1.__setMonth(i + 1); } })
|
|
})
|
|
])
|
|
});
|
|
|
|
this.yearsInMonthView === true && content.unshift(
|
|
h('div', { staticClass: 'row no-wrap full-width' }, [
|
|
this.__getNavigation(h, {
|
|
label: this.viewModel.year,
|
|
view: 'Years',
|
|
key: this.viewModel.year,
|
|
dir: this.yearDirection,
|
|
goTo: this.__goToYear,
|
|
boundaries: this.navBoundaries.year,
|
|
cls: ' col'
|
|
})
|
|
])
|
|
);
|
|
|
|
return h('div', {
|
|
key: 'months-view',
|
|
staticClass: 'q-date__view q-date__months flex flex-center'
|
|
}, content)
|
|
},
|
|
|
|
__getYearsView: function __getYearsView (h) {
|
|
var this$1 = this;
|
|
|
|
var
|
|
start = this.startYear,
|
|
stop = start + yearsInterval,
|
|
years = [];
|
|
|
|
var isDisabled = function (year) {
|
|
return (
|
|
(this$1.minNav !== void 0 && this$1.minNav.year > year) ||
|
|
(this$1.maxNav !== void 0 && this$1.maxNav.year < year)
|
|
)
|
|
};
|
|
|
|
var loop = function ( i ) {
|
|
var active = this$1.viewModel.year === i;
|
|
|
|
years.push(
|
|
h('div', {
|
|
staticClass: 'q-date__years-item flex flex-center'
|
|
}, [
|
|
h(QBtn, {
|
|
key: 'yr' + i,
|
|
staticClass: this$1.today.year === i ? 'q-date__today' : null,
|
|
props: {
|
|
flat: !active,
|
|
label: i,
|
|
dense: true,
|
|
unelevated: active,
|
|
color: active === true ? this$1.computedColor : null,
|
|
textColor: active === true ? this$1.computedTextColor : null,
|
|
tabindex: this$1.computedTabindex,
|
|
disable: isDisabled(i)
|
|
},
|
|
on: cache(this$1, 'yr#' + i, { click: function () { this$1.__setYear(i); } })
|
|
})
|
|
])
|
|
);
|
|
};
|
|
|
|
for (var i = start; i <= stop; i++) loop( i );
|
|
|
|
return h('div', {
|
|
staticClass: 'q-date__view q-date__years flex flex-center'
|
|
}, [
|
|
h('div', {
|
|
staticClass: 'col-auto'
|
|
}, [
|
|
h(QBtn, {
|
|
props: {
|
|
round: true,
|
|
dense: true,
|
|
flat: true,
|
|
icon: this.dateArrow[0],
|
|
tabindex: this.computedTabindex,
|
|
disable: isDisabled(start)
|
|
},
|
|
on: cache(this, 'y-', { click: function () { this$1.startYear -= yearsInterval; } })
|
|
})
|
|
]),
|
|
|
|
h('div', {
|
|
staticClass: 'q-date__years-content col self-stretch row items-center'
|
|
}, years),
|
|
|
|
h('div', {
|
|
staticClass: 'col-auto'
|
|
}, [
|
|
h(QBtn, {
|
|
props: {
|
|
round: true,
|
|
dense: true,
|
|
flat: true,
|
|
icon: this.dateArrow[1],
|
|
tabindex: this.computedTabindex,
|
|
disable: isDisabled(stop)
|
|
},
|
|
on: cache(this, 'y+', { click: function () { this$1.startYear += yearsInterval; } })
|
|
})
|
|
])
|
|
])
|
|
},
|
|
|
|
__goToMonth: function __goToMonth (offset) {
|
|
var year = this.viewModel.year;
|
|
var month = Number(this.viewModel.month) + offset;
|
|
|
|
if (month === 13) {
|
|
month = 1;
|
|
year++;
|
|
}
|
|
else if (month === 0) {
|
|
month = 12;
|
|
year--;
|
|
}
|
|
|
|
this.__updateViewModel(year, month);
|
|
this.isImmediate === true && this.__emitImmediately('month');
|
|
},
|
|
|
|
__goToYear: function __goToYear (offset) {
|
|
var year = Number(this.viewModel.year) + offset;
|
|
this.__updateViewModel(year, this.viewModel.month);
|
|
this.isImmediate === true && this.__emitImmediately('year');
|
|
},
|
|
|
|
__setYear: function __setYear (year) {
|
|
this.__updateViewModel(year, this.viewModel.month);
|
|
this.view = this.defaultView === 'Years' ? 'Months' : 'Calendar';
|
|
this.isImmediate === true && this.__emitImmediately('year');
|
|
},
|
|
|
|
__setMonth: function __setMonth (month) {
|
|
this.__updateViewModel(this.viewModel.year, month);
|
|
this.view = 'Calendar';
|
|
this.isImmediate === true && this.__emitImmediately('month');
|
|
},
|
|
|
|
__getMonthHash: function __getMonthHash (date) {
|
|
return date.year + '/' + pad(date.month)
|
|
},
|
|
|
|
__getDayHash: function __getDayHash (date) {
|
|
return date.year + '/' + pad(date.month) + '/' + pad(date.day)
|
|
},
|
|
|
|
__toggleDate: function __toggleDate (date, monthHash) {
|
|
var month = this.daysMap[monthHash];
|
|
var fn = month !== void 0 && month.includes(date.day) === true
|
|
? this.__removeFromModel
|
|
: this.__addToModel;
|
|
|
|
fn(date);
|
|
},
|
|
|
|
__getShortDate: function __getShortDate (date) {
|
|
return { year: date.year, month: date.month, day: date.day }
|
|
},
|
|
|
|
__onDayClick: function __onDayClick (dayIndex) {
|
|
var day = Object.assign({}, this.viewModel, {day: dayIndex});
|
|
|
|
if (this.range === false) {
|
|
this.__toggleDate(day, this.viewMonthHash);
|
|
return
|
|
}
|
|
|
|
if (this.editRange === void 0) {
|
|
var dayProps = this.days.find(function (day) { return day.fill !== true && day.i === dayIndex; });
|
|
|
|
if (dayProps.range !== void 0) {
|
|
this.__removeFromModel({ target: day, from: dayProps.range.from, to: dayProps.range.to });
|
|
return
|
|
}
|
|
|
|
if (dayProps.selected === true) {
|
|
this.__removeFromModel(day);
|
|
return
|
|
}
|
|
|
|
var initHash = this.__getDayHash(day);
|
|
|
|
this.editRange = {
|
|
init: day,
|
|
initHash: initHash,
|
|
final: day,
|
|
finalHash: initHash
|
|
};
|
|
|
|
this.$emit('range-start', this.__getShortDate(day));
|
|
}
|
|
else {
|
|
var
|
|
initHash$1 = this.editRange.initHash,
|
|
finalHash = this.__getDayHash(day),
|
|
payload = initHash$1 <= finalHash
|
|
? { from: this.editRange.init, to: day }
|
|
: { from: day, to: this.editRange.init };
|
|
|
|
this.editRange = void 0;
|
|
this.__addToModel(initHash$1 === finalHash ? day : Object.assign({}, {target: day}, payload));
|
|
|
|
this.$emit('range-end', {
|
|
from: this.__getShortDate(payload.from),
|
|
to: this.__getShortDate(payload.to)
|
|
});
|
|
}
|
|
},
|
|
|
|
__onDayMouseover: function __onDayMouseover (dayIndex) {
|
|
if (this.editRange !== void 0) {
|
|
var final = Object.assign({}, this.viewModel, {day: dayIndex});
|
|
|
|
Object.assign(this.editRange, {
|
|
final: final,
|
|
finalHash: this.__getDayHash(final)
|
|
});
|
|
}
|
|
},
|
|
|
|
__updateViewModel: function __updateViewModel (year, month) {
|
|
var this$1 = this;
|
|
|
|
if (this.minNav !== void 0 && year <= this.minNav.year) {
|
|
year = this.minNav.year;
|
|
if (month < this.minNav.month) {
|
|
month = this.minNav.month;
|
|
}
|
|
}
|
|
|
|
if (this.maxNav !== void 0 && year >= this.maxNav.year) {
|
|
year = this.maxNav.year;
|
|
if (month > this.maxNav.month) {
|
|
month = this.maxNav.month;
|
|
}
|
|
}
|
|
|
|
var newHash = year + '/' + pad(month) + '/01';
|
|
|
|
if (newHash !== this.viewModel.dateHash) {
|
|
this.monthDirection = (this.viewModel.dateHash < newHash) === (this.$q.lang.rtl !== true) ? 'left' : 'right';
|
|
if (year !== this.viewModel.year) {
|
|
this.yearDirection = this.monthDirection;
|
|
}
|
|
|
|
this.$nextTick(function () {
|
|
this$1.startYear = year - year % yearsInterval - (year < 0 ? yearsInterval : 0);
|
|
Object.assign(this$1.viewModel, {
|
|
year: year,
|
|
month: month,
|
|
day: 1,
|
|
dateHash: newHash
|
|
});
|
|
});
|
|
}
|
|
},
|
|
|
|
__emitValue: function __emitValue (val, action, date) {
|
|
var value = val !== null && val.length === 1 && this.multiple === false
|
|
? val[0]
|
|
: val;
|
|
|
|
this.lastEmitValue = value;
|
|
|
|
var ref = this.__getEmitParams(action, date);
|
|
var reason = ref.reason;
|
|
var details = ref.details;
|
|
this.$emit('input', value, reason, details);
|
|
},
|
|
|
|
// DEPRECATED - TODO: remove in v2
|
|
__emitImmediately: function __emitImmediately (reason) {
|
|
var this$1 = this;
|
|
|
|
var date = this.daysModel[0];
|
|
|
|
// nextTick required because of animation delay in viewModel
|
|
this.$nextTick(function () {
|
|
date.year = this$1.viewModel.year;
|
|
date.month = this$1.viewModel.month;
|
|
|
|
var maxDay = this$1.calendar !== 'persian'
|
|
? (new Date(date.year, date.month, 0)).getDate()
|
|
: jalaaliMonthLength(date.year, date.month);
|
|
|
|
date.day = Math.min(Math.max(1, date.day), maxDay);
|
|
|
|
var value = this$1.__encodeEntry(date);
|
|
this$1.lastEmitValue = value;
|
|
|
|
var ref = this$1.__getEmitParams('', date);
|
|
var details = ref.details;
|
|
this$1.$emit('input', value, reason, details);
|
|
});
|
|
},
|
|
|
|
__getEmitParams: function __getEmitParams (action, date) {
|
|
return date.from !== void 0
|
|
? {
|
|
reason: (action + "-range"),
|
|
details: Object.assign({}, this.__getShortDate(date.target),
|
|
{from: this.__getShortDate(date.from),
|
|
to: this.__getShortDate(date.to),
|
|
changed: true})
|
|
}
|
|
: {
|
|
reason: (action + "-day"),
|
|
details: Object.assign({}, this.__getShortDate(date),
|
|
{changed: true})
|
|
}
|
|
},
|
|
|
|
__encodeEntry: function __encodeEntry (date, mask, locale) {
|
|
return date.from !== void 0
|
|
? { from: this.encodeObjectFn(date.from, mask, locale), to: this.encodeObjectFn(date.to, mask, locale) }
|
|
: this.encodeObjectFn(date, mask, locale)
|
|
},
|
|
|
|
__addToModel: function __addToModel (date) {
|
|
var this$1 = this;
|
|
|
|
var value;
|
|
|
|
if (this.multiple === true) {
|
|
if (date.from !== void 0) {
|
|
// we also need to filter out intersections
|
|
|
|
var fromHash = this.__getDayHash(date.from);
|
|
var toHash = this.__getDayHash(date.to);
|
|
|
|
var days = this.daysModel
|
|
.filter(function (day) { return day.dateHash < fromHash || day.dateHash > toHash; });
|
|
|
|
var ranges = this.rangeModel
|
|
.filter(function (ref) {
|
|
var from = ref.from;
|
|
var to = ref.to;
|
|
|
|
return to.dateHash < fromHash || from.dateHash > toHash;
|
|
});
|
|
|
|
value = days.concat(ranges).concat(date).map(function (entry) { return this$1.__encodeEntry(entry); });
|
|
}
|
|
else {
|
|
var model = this.normalizedModel.slice();
|
|
model.push(this.__encodeEntry(date));
|
|
value = model;
|
|
}
|
|
}
|
|
else {
|
|
value = this.__encodeEntry(date);
|
|
}
|
|
|
|
this.__emitValue(value, 'add', date);
|
|
},
|
|
|
|
__removeFromModel: function __removeFromModel (date) {
|
|
if (this.noUnset === true) {
|
|
return
|
|
}
|
|
|
|
var model = null;
|
|
|
|
if (this.multiple === true && Array.isArray(this.value) === true) {
|
|
var val = this.__encodeEntry(date);
|
|
|
|
if (date.from !== void 0) {
|
|
model = this.value.filter(
|
|
function (date) { return date.from !== void 0
|
|
? (date.from !== val.from && date.to !== val.to)
|
|
: true; }
|
|
);
|
|
}
|
|
else {
|
|
model = this.value.filter(function (date) { return date !== val; });
|
|
}
|
|
|
|
if (model.length === 0) {
|
|
model = null;
|
|
}
|
|
}
|
|
|
|
this.__emitValue(model, 'remove', date);
|
|
},
|
|
|
|
__updateValue: function __updateValue (mask, locale, reason) {
|
|
var this$1 = this;
|
|
|
|
var model = this.daysModel
|
|
.concat(this.rangeModel)
|
|
.map(function (entry) { return this$1.__encodeEntry(entry, mask, locale); })
|
|
.filter(function (entry) {
|
|
return entry.from !== void 0
|
|
? entry.from.dateHash !== null && entry.to.dateHash !== null
|
|
: entry.dateHash !== null
|
|
});
|
|
|
|
this.$emit('input', (this.multiple === true ? model : model[0]) || null, reason);
|
|
}
|
|
},
|
|
|
|
render: function render (h) {
|
|
var content = [
|
|
h('div', {
|
|
staticClass: 'q-date__content col relative-position'
|
|
}, [
|
|
h('transition', {
|
|
props: { name: 'q-transition--fade' }
|
|
}, [
|
|
this[("__get" + (this.view) + "View")](h)
|
|
])
|
|
])
|
|
];
|
|
|
|
var def = slot(this, 'default');
|
|
def !== void 0 && content.push(
|
|
h('div', { staticClass: 'q-date__actions' }, def)
|
|
);
|
|
|
|
if (this.name !== void 0 && this.disable !== true) {
|
|
this.__injectFormInput(content, 'push');
|
|
}
|
|
|
|
return h('div', {
|
|
class: this.classes,
|
|
attrs: this.attrs,
|
|
on: Object.assign({}, this.qListeners)
|
|
}, [
|
|
this.__getHeader(h),
|
|
|
|
h('div', {
|
|
staticClass: 'q-date__main col column',
|
|
attrs: { tabindex: -1 },
|
|
ref: 'blurTarget'
|
|
}, content)
|
|
])
|
|
}
|
|
});
|
|
|
|
var HistoryMixin = {
|
|
methods: {
|
|
__addHistory: function __addHistory () {
|
|
var this$1 = this;
|
|
|
|
this.__historyEntry = {
|
|
condition: function () { return this$1.hideOnRouteChange === true },
|
|
handler: this.hide
|
|
};
|
|
History.add(this.__historyEntry);
|
|
},
|
|
|
|
__removeHistory: function __removeHistory () {
|
|
if (this.__historyEntry !== void 0) {
|
|
History.remove(this.__historyEntry);
|
|
this.__historyEntry = void 0;
|
|
}
|
|
}
|
|
},
|
|
|
|
beforeDestroy: function beforeDestroy () {
|
|
this.showing === true && this.__removeHistory();
|
|
}
|
|
};
|
|
|
|
var
|
|
registered = 0,
|
|
scrollPositionX,
|
|
scrollPositionY,
|
|
maxScrollTop,
|
|
vpPendingUpdate = false,
|
|
bodyLeft,
|
|
bodyTop,
|
|
closeTimer;
|
|
|
|
function onWheel (e) {
|
|
if (shouldPreventScroll(e)) {
|
|
stopAndPrevent(e);
|
|
}
|
|
}
|
|
|
|
function shouldPreventScroll (e) {
|
|
if (e.target === document.body || e.target.classList.contains('q-layout__backdrop')) {
|
|
return true
|
|
}
|
|
|
|
var
|
|
path = getEventPath(e),
|
|
shift = e.shiftKey && !e.deltaX,
|
|
scrollY = !shift && Math.abs(e.deltaX) <= Math.abs(e.deltaY),
|
|
delta = shift || scrollY ? e.deltaY : e.deltaX;
|
|
|
|
for (var index = 0; index < path.length; index++) {
|
|
var el = path[index];
|
|
|
|
if (hasScrollbar(el, scrollY)) {
|
|
return scrollY
|
|
? (
|
|
delta < 0 && el.scrollTop === 0
|
|
? true
|
|
: delta > 0 && el.scrollTop + el.clientHeight === el.scrollHeight
|
|
)
|
|
: (
|
|
delta < 0 && el.scrollLeft === 0
|
|
? true
|
|
: delta > 0 && el.scrollLeft + el.clientWidth === el.scrollWidth
|
|
)
|
|
}
|
|
}
|
|
|
|
return true
|
|
}
|
|
|
|
function onAppleScroll (e) {
|
|
if (e.target === document) {
|
|
// required, otherwise iOS blocks further scrolling
|
|
// until the mobile scrollbar dissappears
|
|
document.scrollingElement.scrollTop = document.scrollingElement.scrollTop; // eslint-disable-line
|
|
}
|
|
}
|
|
|
|
function onAppleResize (evt) {
|
|
if (vpPendingUpdate === true) {
|
|
return
|
|
}
|
|
|
|
vpPendingUpdate = true;
|
|
|
|
requestAnimationFrame(function () {
|
|
vpPendingUpdate = false;
|
|
|
|
var ref = evt.target;
|
|
var height = ref.height;
|
|
var ref$1 = document.scrollingElement;
|
|
var clientHeight = ref$1.clientHeight;
|
|
var scrollTop = ref$1.scrollTop;
|
|
|
|
if (maxScrollTop === void 0 || height !== window.innerHeight) {
|
|
maxScrollTop = clientHeight - height;
|
|
document.scrollingElement.scrollTop = scrollTop;
|
|
}
|
|
|
|
if (scrollTop > maxScrollTop) {
|
|
document.scrollingElement.scrollTop -= Math.ceil((scrollTop - maxScrollTop) / 8);
|
|
}
|
|
});
|
|
}
|
|
|
|
function apply (action) {
|
|
var
|
|
body = document.body,
|
|
hasViewport = window.visualViewport !== void 0;
|
|
|
|
if (action === 'add') {
|
|
var overflowY = window.getComputedStyle(body).overflowY;
|
|
|
|
scrollPositionX = getHorizontalScrollPosition(window);
|
|
scrollPositionY = getScrollPosition(window);
|
|
bodyLeft = body.style.left;
|
|
bodyTop = body.style.top;
|
|
|
|
body.style.left = "-" + scrollPositionX + "px";
|
|
body.style.top = "-" + scrollPositionY + "px";
|
|
if (overflowY !== 'hidden' && (overflowY === 'scroll' || body.scrollHeight > window.innerHeight)) {
|
|
body.classList.add('q-body--force-scrollbar');
|
|
}
|
|
|
|
body.classList.add('q-body--prevent-scroll');
|
|
document.qScrollPrevented = true;
|
|
if (client.is.ios === true) {
|
|
if (hasViewport === true) {
|
|
window.scrollTo(0, 0);
|
|
window.visualViewport.addEventListener('resize', onAppleResize, listenOpts.passiveCapture);
|
|
window.visualViewport.addEventListener('scroll', onAppleResize, listenOpts.passiveCapture);
|
|
window.scrollTo(0, 0);
|
|
}
|
|
else {
|
|
window.addEventListener('scroll', onAppleScroll, listenOpts.passiveCapture);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (client.is.desktop === true && client.is.mac === true) {
|
|
// ref. https://developers.google.com/web/updates/2017/01/scrolling-intervention
|
|
window[(action + "EventListener")]('wheel', onWheel, listenOpts.notPassive);
|
|
}
|
|
|
|
if (action === 'remove') {
|
|
if (client.is.ios === true) {
|
|
if (hasViewport === true) {
|
|
window.visualViewport.removeEventListener('resize', onAppleResize, listenOpts.passiveCapture);
|
|
window.visualViewport.removeEventListener('scroll', onAppleResize, listenOpts.passiveCapture);
|
|
}
|
|
else {
|
|
window.removeEventListener('scroll', onAppleScroll, listenOpts.passiveCapture);
|
|
}
|
|
}
|
|
|
|
body.classList.remove('q-body--prevent-scroll');
|
|
body.classList.remove('q-body--force-scrollbar');
|
|
document.qScrollPrevented = false;
|
|
|
|
body.style.left = bodyLeft;
|
|
body.style.top = bodyTop;
|
|
|
|
window.scrollTo(scrollPositionX, scrollPositionY);
|
|
maxScrollTop = void 0;
|
|
}
|
|
}
|
|
|
|
function preventScroll (state) {
|
|
var action = 'add';
|
|
|
|
if (state === true) {
|
|
registered++;
|
|
|
|
if (closeTimer !== void 0) {
|
|
clearTimeout(closeTimer);
|
|
closeTimer = void 0;
|
|
return
|
|
}
|
|
|
|
if (registered > 1) {
|
|
return
|
|
}
|
|
}
|
|
else {
|
|
if (registered === 0) {
|
|
return
|
|
}
|
|
|
|
registered--;
|
|
|
|
if (registered > 0) {
|
|
return
|
|
}
|
|
|
|
action = 'remove';
|
|
|
|
if (client.is.ios === true && client.is.nativeMobile === true) {
|
|
clearTimeout(closeTimer);
|
|
|
|
closeTimer = setTimeout(function () {
|
|
apply(action);
|
|
closeTimer = void 0;
|
|
}, 100);
|
|
return
|
|
}
|
|
}
|
|
|
|
apply(action);
|
|
}
|
|
|
|
var PreventScrollMixin = {
|
|
methods: {
|
|
__preventScroll: function __preventScroll (state) {
|
|
if (
|
|
state !== this.preventedScroll &&
|
|
(this.preventedScroll !== void 0 || state === true)
|
|
) {
|
|
this.preventedScroll = state;
|
|
preventScroll(state);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
var maximizedModals = 0;
|
|
|
|
var positionClass = {
|
|
standard: 'fixed-full flex-center',
|
|
top: 'fixed-top justify-center',
|
|
bottom: 'fixed-bottom justify-center',
|
|
right: 'fixed-right items-center',
|
|
left: 'fixed-left items-center'
|
|
};
|
|
|
|
var transitions = {
|
|
standard: ['scale', 'scale'],
|
|
top: ['slide-down', 'slide-up'],
|
|
bottom: ['slide-up', 'slide-down'],
|
|
right: ['slide-left', 'slide-right'],
|
|
left: ['slide-right', 'slide-left']
|
|
};
|
|
|
|
var QDialog = Vue.extend({
|
|
name: 'QDialog',
|
|
|
|
mixins: [
|
|
AttrsMixin,
|
|
HistoryMixin,
|
|
ModelToggleMixin,
|
|
Portal,
|
|
PreventScrollMixin
|
|
],
|
|
|
|
props: {
|
|
persistent: Boolean,
|
|
autoClose: Boolean,
|
|
|
|
noEscDismiss: Boolean,
|
|
noBackdropDismiss: Boolean,
|
|
noRouteDismiss: Boolean,
|
|
noRefocus: Boolean,
|
|
noFocus: Boolean,
|
|
|
|
seamless: Boolean,
|
|
|
|
maximized: Boolean,
|
|
fullWidth: Boolean,
|
|
fullHeight: Boolean,
|
|
|
|
square: Boolean,
|
|
|
|
position: {
|
|
type: String,
|
|
default: 'standard',
|
|
validator: function (val) { return val === 'standard' ||
|
|
['top', 'bottom', 'left', 'right'].includes(val); }
|
|
},
|
|
|
|
transitionShow: String,
|
|
transitionHide: String
|
|
},
|
|
|
|
data: function data () {
|
|
return {
|
|
transitionState: this.showing
|
|
}
|
|
},
|
|
|
|
watch: {
|
|
showing: function showing (val) {
|
|
var this$1 = this;
|
|
|
|
if (this.transitionShowComputed !== this.transitionHideComputed) {
|
|
this.$nextTick(function () {
|
|
this$1.transitionState = val;
|
|
});
|
|
}
|
|
},
|
|
|
|
maximized: function maximized (state) {
|
|
this.showing === true && this.__updateMaximized(state);
|
|
},
|
|
|
|
useBackdrop: function useBackdrop (v) {
|
|
this.__preventScroll(v);
|
|
this.__preventFocusout(v);
|
|
}
|
|
},
|
|
|
|
computed: {
|
|
classes: function classes () {
|
|
return "q-dialog__inner--" + (this.maximized === true ? 'maximized' : 'minimized') + " " +
|
|
"q-dialog__inner--" + (this.position) + " " + (positionClass[this.position]) +
|
|
(this.fullWidth === true ? ' q-dialog__inner--fullwidth' : '') +
|
|
(this.fullHeight === true ? ' q-dialog__inner--fullheight' : '') +
|
|
(this.square === true ? ' q-dialog__inner--square' : '')
|
|
},
|
|
|
|
transitionShowComputed: function transitionShowComputed () {
|
|
return 'q-transition--' + (this.transitionShow === void 0 ? transitions[this.position][0] : this.transitionShow)
|
|
},
|
|
|
|
transitionHideComputed: function transitionHideComputed () {
|
|
return 'q-transition--' + (this.transitionHide === void 0 ? transitions[this.position][1] : this.transitionHide)
|
|
},
|
|
|
|
transition: function transition () {
|
|
return this.transitionState === true
|
|
? this.transitionHideComputed
|
|
: this.transitionShowComputed
|
|
},
|
|
|
|
useBackdrop: function useBackdrop () {
|
|
return this.showing === true && this.seamless !== true
|
|
},
|
|
|
|
hideOnRouteChange: function hideOnRouteChange () {
|
|
return this.persistent !== true &&
|
|
this.noRouteDismiss !== true &&
|
|
this.seamless !== true
|
|
},
|
|
|
|
onEvents: function onEvents () {
|
|
var on = Object.assign({}, this.qListeners,
|
|
// stop propagating these events from children
|
|
{input: stop,
|
|
'popup-show': stop,
|
|
'popup-hide': stop});
|
|
|
|
if (this.autoClose === true) {
|
|
on.click = this.__onAutoClose;
|
|
}
|
|
|
|
return on
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
focus: function focus () {
|
|
var node = this.__getInnerNode();
|
|
|
|
if (node === void 0 || node.contains(document.activeElement) === true) {
|
|
return
|
|
}
|
|
|
|
node = node.querySelector('[autofocus], [data-autofocus]') || node;
|
|
node.focus();
|
|
},
|
|
|
|
shake: function shake () {
|
|
this.focus();
|
|
this.$emit('shake');
|
|
|
|
var node = this.__getInnerNode();
|
|
|
|
if (node !== void 0) {
|
|
node.classList.remove('q-animate--scale');
|
|
node.classList.add('q-animate--scale');
|
|
clearTimeout(this.shakeTimeout);
|
|
this.shakeTimeout = setTimeout(function () {
|
|
node.classList.remove('q-animate--scale');
|
|
}, 170);
|
|
}
|
|
},
|
|
|
|
__getInnerNode: function __getInnerNode () {
|
|
return this.__portal !== void 0 && this.__portal.$refs !== void 0
|
|
? this.__portal.$refs.inner
|
|
: void 0
|
|
},
|
|
|
|
__show: function __show (evt) {
|
|
var this$1 = this;
|
|
|
|
this.__addHistory();
|
|
|
|
// IE can have null document.activeElement
|
|
this.__refocusTarget = this.noRefocus === false && document.activeElement !== null
|
|
? document.activeElement
|
|
: void 0;
|
|
|
|
this.$el.dispatchEvent(create('popup-show', { bubbles: true }));
|
|
this.__updateMaximized(this.maximized);
|
|
|
|
EscapeKey.register(this, function () {
|
|
if (this$1.seamless !== true) {
|
|
if (this$1.persistent === true || this$1.noEscDismiss === true) {
|
|
this$1.maximized !== true && this$1.shake();
|
|
}
|
|
else {
|
|
this$1.$emit('escape-key');
|
|
this$1.hide();
|
|
}
|
|
}
|
|
});
|
|
|
|
this.__showPortal();
|
|
|
|
if (this.noFocus !== true) {
|
|
// IE can have null document.activeElement
|
|
document.activeElement !== null && document.activeElement.blur();
|
|
this.__nextTick(this.focus);
|
|
}
|
|
|
|
this.__setTimeout(function () {
|
|
if (this$1.$q.platform.is.ios === true) {
|
|
if (this$1.seamless !== true && document.activeElement) {
|
|
var ref = document.activeElement.getBoundingClientRect();
|
|
var top = ref.top;
|
|
var bottom = ref.bottom;
|
|
var innerHeight = window.innerHeight;
|
|
var height = window.visualViewport !== void 0
|
|
? window.visualViewport.height
|
|
: innerHeight;
|
|
|
|
if (top > 0 && bottom > height / 2) {
|
|
var scrollTop = Math.min(
|
|
document.scrollingElement.scrollHeight - height,
|
|
bottom >= innerHeight
|
|
? Infinity
|
|
: Math.ceil(document.scrollingElement.scrollTop + bottom - height / 2)
|
|
);
|
|
|
|
var fn = function () {
|
|
requestAnimationFrame(function () {
|
|
document.scrollingElement.scrollTop += Math.ceil((scrollTop - document.scrollingElement.scrollTop) / 8);
|
|
if (document.scrollingElement.scrollTop !== scrollTop) {
|
|
fn();
|
|
}
|
|
});
|
|
};
|
|
|
|
fn();
|
|
}
|
|
document.activeElement.scrollIntoView();
|
|
}
|
|
|
|
// required in order to avoid the "double-tap needed" issue
|
|
this$1.__portal.$el.click();
|
|
}
|
|
|
|
this$1.$emit('show', evt);
|
|
}, 300);
|
|
},
|
|
|
|
__hide: function __hide (evt) {
|
|
var this$1 = this;
|
|
|
|
this.__removeHistory();
|
|
this.__cleanup(true);
|
|
|
|
// check null for IE
|
|
if (this.__refocusTarget !== void 0 && this.__refocusTarget !== null) {
|
|
this.__refocusTarget.focus();
|
|
}
|
|
|
|
this.$el.dispatchEvent(create('popup-hide', { bubbles: true }));
|
|
|
|
this.__setTimeout(function () {
|
|
this$1.__hidePortal();
|
|
this$1.$emit('hide', evt);
|
|
}, 300);
|
|
},
|
|
|
|
__cleanup: function __cleanup (hiding) {
|
|
clearTimeout(this.shakeTimeout);
|
|
|
|
if (hiding === true || this.showing === true) {
|
|
EscapeKey.pop(this);
|
|
this.__updateMaximized(false);
|
|
|
|
if (this.seamless !== true) {
|
|
this.__preventScroll(false);
|
|
this.__preventFocusout(false);
|
|
}
|
|
}
|
|
},
|
|
|
|
__updateMaximized: function __updateMaximized (active) {
|
|
if (active === true) {
|
|
if (this.isMaximized !== true) {
|
|
maximizedModals < 1 && document.body.classList.add('q-body--dialog');
|
|
maximizedModals++;
|
|
|
|
this.isMaximized = true;
|
|
}
|
|
}
|
|
else if (this.isMaximized === true) {
|
|
if (maximizedModals < 2) {
|
|
document.body.classList.remove('q-body--dialog');
|
|
}
|
|
|
|
maximizedModals--;
|
|
this.isMaximized = false;
|
|
}
|
|
},
|
|
|
|
__preventFocusout: function __preventFocusout (state) {
|
|
if (this.$q.platform.is.desktop === true) {
|
|
var action = (state === true ? 'add' : 'remove') + "EventListener";
|
|
document.body[action]('focusin', this.__onFocusChange);
|
|
}
|
|
},
|
|
|
|
__onAutoClose: function __onAutoClose (e) {
|
|
this.hide(e);
|
|
this.qListeners.click !== void 0 && this.$emit('click', e);
|
|
},
|
|
|
|
__onBackdropClick: function __onBackdropClick (e) {
|
|
if (this.persistent !== true && this.noBackdropDismiss !== true) {
|
|
this.hide(e);
|
|
}
|
|
else {
|
|
this.shake();
|
|
}
|
|
},
|
|
|
|
__onFocusChange: function __onFocusChange (e) {
|
|
// the focus is not in a vue child component
|
|
if (
|
|
this.showing === true &&
|
|
this.__portal !== void 0 &&
|
|
childHasFocus(this.__portal.$el, e.target) !== true
|
|
) {
|
|
this.focus();
|
|
}
|
|
},
|
|
|
|
__renderPortal: function __renderPortal (h) {
|
|
return h('div', {
|
|
staticClass: 'q-dialog fullscreen no-pointer-events',
|
|
class: this.contentClass,
|
|
style: this.contentStyle,
|
|
attrs: this.qAttrs
|
|
}, [
|
|
h('transition', {
|
|
props: { name: 'q-transition--fade' }
|
|
}, this.useBackdrop === true ? [
|
|
h('div', {
|
|
staticClass: 'q-dialog__backdrop fixed-full',
|
|
attrs: ariaHidden,
|
|
on: cache(this, 'bkdrop', {
|
|
click: this.__onBackdropClick
|
|
})
|
|
})
|
|
] : null),
|
|
|
|
h('transition', {
|
|
props: { name: this.transition }
|
|
}, [
|
|
this.showing === true ? h('div', {
|
|
ref: 'inner',
|
|
staticClass: 'q-dialog__inner flex no-pointer-events',
|
|
class: this.classes,
|
|
attrs: { tabindex: -1 },
|
|
on: this.onEvents
|
|
}, slot(this, 'default')) : null
|
|
])
|
|
])
|
|
}
|
|
},
|
|
|
|
mounted: function mounted () {
|
|
this.__processModelChange(this.value);
|
|
},
|
|
|
|
beforeDestroy: function beforeDestroy () {
|
|
this.__cleanup();
|
|
}
|
|
});
|
|
|
|
var duration = 150;
|
|
|
|
var mouseEvents = [
|
|
'mouseover', 'mouseout', 'mouseenter', 'mouseleave'
|
|
];
|
|
|
|
var QDrawer = Vue.extend({
|
|
name: 'QDrawer',
|
|
|
|
inject: {
|
|
layout: {
|
|
default: function default$1 () {
|
|
console.error('QDrawer needs to be child of QLayout');
|
|
}
|
|
}
|
|
},
|
|
|
|
mixins: [ DarkMixin, HistoryMixin, ModelToggleMixin, PreventScrollMixin ],
|
|
|
|
directives: {
|
|
TouchPan: TouchPan
|
|
},
|
|
|
|
props: {
|
|
side: {
|
|
type: String,
|
|
default: 'left',
|
|
validator: function (v) { return ['left', 'right'].includes(v); }
|
|
},
|
|
|
|
width: {
|
|
type: Number,
|
|
default: 300
|
|
},
|
|
|
|
mini: Boolean,
|
|
miniToOverlay: Boolean,
|
|
miniWidth: {
|
|
type: Number,
|
|
default: 57
|
|
},
|
|
|
|
breakpoint: {
|
|
type: Number,
|
|
default: 1023
|
|
},
|
|
showIfAbove: Boolean,
|
|
|
|
behavior: {
|
|
type: String,
|
|
validator: function (v) { return ['default', 'desktop', 'mobile'].includes(v); },
|
|
default: 'default'
|
|
},
|
|
|
|
bordered: Boolean,
|
|
elevated: Boolean,
|
|
contentStyle: [String, Object, Array],
|
|
contentClass: [String, Object, Array],
|
|
|
|
overlay: Boolean,
|
|
persistent: Boolean,
|
|
noSwipeOpen: Boolean,
|
|
noSwipeClose: Boolean,
|
|
noSwipeBackdrop: Boolean
|
|
},
|
|
|
|
data: function data () {
|
|
var belowBreakpoint = (
|
|
this.behavior === 'mobile' ||
|
|
(this.behavior !== 'desktop' && this.layout.totalWidth <= this.breakpoint)
|
|
);
|
|
|
|
return {
|
|
belowBreakpoint: belowBreakpoint,
|
|
showing: this.showIfAbove === true && belowBreakpoint === false
|
|
? true
|
|
: this.value === true
|
|
}
|
|
},
|
|
|
|
watch: {
|
|
belowBreakpoint: function belowBreakpoint (val) {
|
|
if (val === true) { // from lg to xs
|
|
this.lastDesktopState = this.showing;
|
|
this.showing === true && this.hide(false);
|
|
}
|
|
else if (
|
|
this.overlay === false &&
|
|
this.behavior !== 'mobile' &&
|
|
this.lastDesktopState !== false
|
|
) { // from xs to lg
|
|
if (this.showing === true) {
|
|
this.__applyPosition(0);
|
|
this.__applyBackdrop(0);
|
|
this.__cleanup();
|
|
}
|
|
else {
|
|
this.show(false);
|
|
}
|
|
}
|
|
},
|
|
|
|
'layout.totalWidth': function layout_totalWidth (val) {
|
|
this.__updateLocal('belowBreakpoint', (
|
|
this.behavior === 'mobile' ||
|
|
(this.behavior !== 'desktop' && val <= this.breakpoint)
|
|
));
|
|
},
|
|
|
|
side: function side (newSide, oldSide) {
|
|
if (this.layout.instances[oldSide] === this) {
|
|
this.layout.instances[oldSide] = void 0;
|
|
this.layout[oldSide].space = false;
|
|
this.layout[oldSide].offset = 0;
|
|
}
|
|
|
|
this.layout.instances[newSide] = this;
|
|
this.layout[newSide].size = this.size;
|
|
this.layout[newSide].space = this.onLayout;
|
|
this.layout[newSide].offset = this.offset;
|
|
},
|
|
|
|
behavior: function behavior (val) {
|
|
this.__updateLocal('belowBreakpoint', (
|
|
val === 'mobile' ||
|
|
(val !== 'desktop' && this.layout.totalWidth <= this.breakpoint)
|
|
));
|
|
},
|
|
|
|
breakpoint: function breakpoint (val) {
|
|
this.__updateLocal('belowBreakpoint', (
|
|
this.behavior === 'mobile' ||
|
|
(this.behavior !== 'desktop' && this.layout.totalWidth <= val)
|
|
));
|
|
},
|
|
|
|
'layout.container': function layout_container (val) {
|
|
this.showing === true && this.__preventScroll(val !== true);
|
|
},
|
|
|
|
'layout.scrollbarWidth': function layout_scrollbarWidth () {
|
|
this.__applyPosition(this.showing === true ? 0 : void 0);
|
|
},
|
|
|
|
offset: function offset (val) {
|
|
this.__update('offset', val);
|
|
},
|
|
|
|
onLayout: function onLayout (val) {
|
|
this.$emit('on-layout', val);
|
|
this.__update('space', val);
|
|
},
|
|
|
|
rightSide: function rightSide () {
|
|
this.__applyPosition();
|
|
},
|
|
|
|
size: function size (val) {
|
|
this.__applyPosition();
|
|
this.__updateSizeOnLayout(this.miniToOverlay, val);
|
|
},
|
|
|
|
miniToOverlay: function miniToOverlay (val) {
|
|
this.__updateSizeOnLayout(val, this.size);
|
|
},
|
|
|
|
'$q.lang.rtl': function $q_lang_rtl () {
|
|
this.__applyPosition();
|
|
},
|
|
|
|
mini: function mini () {
|
|
if (this.value === true) {
|
|
this.__animateMini();
|
|
this.layout.__animate();
|
|
}
|
|
},
|
|
|
|
isMini: function isMini (val) {
|
|
this.$emit('mini-state', val);
|
|
}
|
|
},
|
|
|
|
computed: {
|
|
rightSide: function rightSide () {
|
|
return this.side === 'right'
|
|
},
|
|
|
|
otherSide: function otherSide () {
|
|
return this.rightSide === true ? 'left' : 'right'
|
|
},
|
|
|
|
offset: function offset () {
|
|
return this.showing === true && this.belowBreakpoint === false && this.overlay === false
|
|
? (this.miniToOverlay === true ? this.miniWidth : this.size)
|
|
: 0
|
|
},
|
|
|
|
size: function size () {
|
|
return this.isMini === true
|
|
? this.miniWidth
|
|
: this.width
|
|
},
|
|
|
|
fixed: function fixed () {
|
|
return this.overlay === true ||
|
|
this.miniToOverlay === true ||
|
|
this.layout.view.indexOf(this.rightSide ? 'R' : 'L') > -1 ||
|
|
(this.$q.platform.is.ios && this.layout.container === true)
|
|
},
|
|
|
|
onLayout: function onLayout () {
|
|
return this.showing === true && this.belowBreakpoint === false && this.overlay === false
|
|
},
|
|
|
|
onScreenOverlay: function onScreenOverlay () {
|
|
return this.showing === true && this.belowBreakpoint === false && this.overlay === true
|
|
},
|
|
|
|
backdropClass: function backdropClass () {
|
|
return this.showing === false ? 'hidden' : null
|
|
},
|
|
|
|
headerSlot: function headerSlot () {
|
|
return this.rightSide === true
|
|
? this.layout.rows.top[2] === 'r'
|
|
: this.layout.rows.top[0] === 'l'
|
|
},
|
|
|
|
footerSlot: function footerSlot () {
|
|
return this.rightSide === true
|
|
? this.layout.rows.bottom[2] === 'r'
|
|
: this.layout.rows.bottom[0] === 'l'
|
|
},
|
|
|
|
aboveStyle: function aboveStyle () {
|
|
var css = {};
|
|
|
|
if (this.layout.header.space === true && this.headerSlot === false) {
|
|
if (this.fixed === true) {
|
|
css.top = (this.layout.header.offset) + "px";
|
|
}
|
|
else if (this.layout.header.space === true) {
|
|
css.top = (this.layout.header.size) + "px";
|
|
}
|
|
}
|
|
|
|
if (this.layout.footer.space === true && this.footerSlot === false) {
|
|
if (this.fixed === true) {
|
|
css.bottom = (this.layout.footer.offset) + "px";
|
|
}
|
|
else if (this.layout.footer.space === true) {
|
|
css.bottom = (this.layout.footer.size) + "px";
|
|
}
|
|
}
|
|
|
|
return css
|
|
},
|
|
|
|
style: function style () {
|
|
var style = { width: ((this.size) + "px") };
|
|
return this.belowBreakpoint === true
|
|
? style
|
|
: Object.assign(style, this.aboveStyle)
|
|
},
|
|
|
|
classes: function classes () {
|
|
return "q-drawer--" + (this.side) +
|
|
(this.bordered === true ? ' q-drawer--bordered' : '') +
|
|
(this.isDark === true ? ' q-drawer--dark q-dark' : '') +
|
|
(this.showing !== true ? ' q-layout--prevent-focus' : '') +
|
|
(
|
|
this.belowBreakpoint === true
|
|
? ' fixed q-drawer--on-top q-drawer--mobile q-drawer--top-padding'
|
|
: " q-drawer--" + (this.isMini === true ? 'mini' : 'standard') +
|
|
(this.fixed === true || this.onLayout !== true ? ' fixed' : '') +
|
|
(this.overlay === true || this.miniToOverlay === true ? ' q-drawer--on-top' : '') +
|
|
(this.headerSlot === true ? ' q-drawer--top-padding' : '')
|
|
)
|
|
},
|
|
|
|
stateDirection: function stateDirection () {
|
|
return (this.$q.lang.rtl === true ? -1 : 1) * (this.rightSide === true ? 1 : -1)
|
|
},
|
|
|
|
isMini: function isMini () {
|
|
return this.mini === true && this.belowBreakpoint !== true
|
|
},
|
|
|
|
onNativeEvents: function onNativeEvents () {
|
|
var this$1 = this;
|
|
|
|
if (this.belowBreakpoint !== true) {
|
|
var evt = {
|
|
'!click': function (e) { this$1.$emit('click', e); }
|
|
};
|
|
|
|
mouseEvents.forEach(function (name) {
|
|
evt[name] = function (e) {
|
|
this$1.qListeners[name] !== void 0 && this$1.$emit(name, e);
|
|
};
|
|
});
|
|
|
|
return evt
|
|
}
|
|
},
|
|
|
|
hideOnRouteChange: function hideOnRouteChange () {
|
|
return this.persistent !== true &&
|
|
(this.belowBreakpoint === true || this.onScreenOverlay === true)
|
|
},
|
|
|
|
openDirective: function openDirective () {
|
|
var obj;
|
|
|
|
var dir = this.$q.lang.rtl === true ? this.side : this.otherSide;
|
|
|
|
return [{
|
|
name: 'touch-pan',
|
|
value: this.__openByTouch,
|
|
modifiers: ( obj = {}, obj[ dir ] = true, obj.mouse = true, obj )
|
|
}]
|
|
},
|
|
|
|
contentCloseDirective: function contentCloseDirective () {
|
|
var obj;
|
|
|
|
if (this.noSwipeClose !== true) {
|
|
var dir = this.$q.lang.rtl === true ? this.otherSide : this.side;
|
|
|
|
return [{
|
|
name: 'touch-pan',
|
|
value: this.__closeByTouch,
|
|
modifiers: ( obj = {}, obj[ dir ] = true, obj.mouse = true, obj )
|
|
}]
|
|
}
|
|
},
|
|
|
|
backdropCloseDirective: function backdropCloseDirective () {
|
|
var obj;
|
|
|
|
if (this.noSwipeBackdrop !== true) {
|
|
var dir = this.$q.lang.rtl === true ? this.otherSide : this.side;
|
|
|
|
return [{
|
|
name: 'touch-pan',
|
|
value: this.__closeByTouch,
|
|
modifiers: ( obj = {}, obj[ dir ] = true, obj.mouse = true, obj.mouseAllDir = true, obj )
|
|
}]
|
|
}
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
__applyPosition: function __applyPosition (position) {
|
|
var this$1 = this;
|
|
|
|
if (position === void 0) {
|
|
this.$nextTick(function () {
|
|
position = this$1.showing === true ? 0 : this$1.size;
|
|
this$1.__applyPosition(this$1.stateDirection * position);
|
|
});
|
|
}
|
|
else if (this.$refs.content !== void 0) {
|
|
if (
|
|
this.layout.container === true &&
|
|
this.rightSide === true &&
|
|
(this.belowBreakpoint === true || Math.abs(position) === this.size)
|
|
) {
|
|
position += this.stateDirection * this.layout.scrollbarWidth;
|
|
}
|
|
|
|
if (this.__lastPosition !== position) {
|
|
this.$refs.content.style.transform = "translateX(" + position + "px)";
|
|
this.__lastPosition = position;
|
|
}
|
|
}
|
|
},
|
|
|
|
__applyBackdrop: function __applyBackdrop (x, retry) {
|
|
var this$1 = this;
|
|
|
|
if (this.$refs.backdrop !== void 0) {
|
|
this.$refs.backdrop.style.backgroundColor =
|
|
this.lastBackdropBg = "rgba(0,0,0," + (x * 0.4) + ")";
|
|
}
|
|
else {
|
|
// rendered nodes might not have
|
|
// picked up this.showing change yet,
|
|
// so we need one retry
|
|
retry !== true && this.$nextTick(function () {
|
|
this$1.__applyBackdrop(x, true);
|
|
});
|
|
}
|
|
},
|
|
|
|
__setBackdropVisible: function __setBackdropVisible (v) {
|
|
if (this.$refs.backdrop !== void 0) {
|
|
this.$refs.backdrop.classList[v === true ? 'remove' : 'add']('hidden');
|
|
}
|
|
},
|
|
|
|
__setScrollable: function __setScrollable (v) {
|
|
var action = v === true
|
|
? 'remove'
|
|
: (this.layout.container !== true ? 'add' : '');
|
|
|
|
action !== '' && document.body.classList[action]('q-body--drawer-toggle');
|
|
},
|
|
|
|
__animateMini: function __animateMini () {
|
|
var this$1 = this;
|
|
|
|
if (this.timerMini !== void 0) {
|
|
clearTimeout(this.timerMini);
|
|
}
|
|
else if (this.$el !== void 0) {
|
|
this.$el.classList.add('q-drawer--mini-animate');
|
|
}
|
|
this.timerMini = setTimeout(function () {
|
|
this$1.$el !== void 0 && this$1.$el.classList.remove('q-drawer--mini-animate');
|
|
this$1.timerMini = void 0;
|
|
}, 150);
|
|
},
|
|
|
|
__openByTouch: function __openByTouch (evt) {
|
|
if (this.showing !== false) {
|
|
// some browsers might capture and trigger this
|
|
// even if Drawer has just been opened (but animation is still pending)
|
|
return
|
|
}
|
|
|
|
var
|
|
width = this.size,
|
|
position = between(evt.distance.x, 0, width);
|
|
|
|
if (evt.isFinal === true) {
|
|
var
|
|
el = this.$refs.content,
|
|
opened = position >= Math.min(75, width);
|
|
|
|
el.classList.remove('no-transition');
|
|
|
|
if (opened === true) {
|
|
this.show();
|
|
}
|
|
else {
|
|
this.layout.__animate();
|
|
this.__applyBackdrop(0);
|
|
this.__applyPosition(this.stateDirection * width);
|
|
el.classList.remove('q-drawer--delimiter');
|
|
el.classList.add('q-layout--prevent-focus');
|
|
this.__setBackdropVisible(false);
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
this.__applyPosition(
|
|
(this.$q.lang.rtl === true ? this.rightSide !== true : this.rightSide)
|
|
? Math.max(width - position, 0)
|
|
: Math.min(0, position - width)
|
|
);
|
|
this.__applyBackdrop(
|
|
between(position / width, 0, 1)
|
|
);
|
|
|
|
if (evt.isFirst === true) {
|
|
var el$1 = this.$refs.content;
|
|
el$1.classList.add('no-transition');
|
|
el$1.classList.add('q-drawer--delimiter');
|
|
el$1.classList.remove('q-layout--prevent-focus');
|
|
this.__setBackdropVisible(true);
|
|
}
|
|
},
|
|
|
|
__closeByTouch: function __closeByTouch (evt) {
|
|
if (this.showing !== true) {
|
|
// some browsers might capture and trigger this
|
|
// even if Drawer has just been closed (but animation is still pending)
|
|
return
|
|
}
|
|
|
|
var
|
|
width = this.size,
|
|
dir = evt.direction === this.side,
|
|
position = (this.$q.lang.rtl === true ? dir !== true : dir)
|
|
? between(evt.distance.x, 0, width)
|
|
: 0;
|
|
|
|
if (evt.isFinal === true) {
|
|
var opened = Math.abs(position) < Math.min(75, width);
|
|
this.$refs.content.classList.remove('no-transition');
|
|
|
|
if (opened === true) {
|
|
this.layout.__animate();
|
|
this.__applyBackdrop(1);
|
|
this.__applyPosition(0);
|
|
}
|
|
else {
|
|
this.hide();
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
this.__applyPosition(this.stateDirection * position);
|
|
this.__applyBackdrop(between(1 - position / width, 0, 1));
|
|
|
|
if (evt.isFirst === true) {
|
|
this.$refs.content.classList.add('no-transition');
|
|
}
|
|
},
|
|
|
|
__show: function __show (evt, noEvent) {
|
|
var this$1 = this;
|
|
|
|
this.__addHistory();
|
|
|
|
this.__setBackdropVisible(true);
|
|
evt !== false && this.layout.__animate();
|
|
this.__applyPosition(0);
|
|
|
|
if (this.belowBreakpoint === true) {
|
|
var otherSide = this.layout.instances[this.otherSide];
|
|
if (otherSide !== void 0 && otherSide.belowBreakpoint === true) {
|
|
otherSide.hide(false);
|
|
}
|
|
|
|
this.__applyBackdrop(1);
|
|
this.layout.container !== true && this.__preventScroll(true);
|
|
}
|
|
else {
|
|
this.__applyBackdrop(0);
|
|
evt !== false && this.__setScrollable(false);
|
|
}
|
|
|
|
this.__setTimeout(function () {
|
|
evt !== false && this$1.__setScrollable(true);
|
|
noEvent !== true && this$1.$emit('show', evt);
|
|
}, duration);
|
|
},
|
|
|
|
__hide: function __hide (evt, noEvent) {
|
|
var this$1 = this;
|
|
|
|
this.__removeHistory();
|
|
|
|
evt !== false && this.layout.__animate();
|
|
|
|
this.__applyBackdrop(0);
|
|
this.__applyPosition(this.stateDirection * this.size);
|
|
this.__setBackdropVisible(false);
|
|
|
|
this.__cleanup();
|
|
|
|
noEvent !== true && this.__setTimeout(function () {
|
|
this$1.$emit('hide', evt);
|
|
}, duration);
|
|
},
|
|
|
|
__cleanup: function __cleanup () {
|
|
this.__preventScroll(false);
|
|
this.__setScrollable(true);
|
|
},
|
|
|
|
__update: function __update (prop, val) {
|
|
if (this.layout[this.side][prop] !== val) {
|
|
this.layout[this.side][prop] = val;
|
|
}
|
|
},
|
|
|
|
__updateLocal: function __updateLocal (prop, val) {
|
|
if (this[prop] !== val) {
|
|
this[prop] = val;
|
|
}
|
|
},
|
|
|
|
__updateSizeOnLayout: function __updateSizeOnLayout (miniToOverlay, size) {
|
|
this.__update('size', miniToOverlay === true ? this.miniWidth : size);
|
|
}
|
|
},
|
|
|
|
created: function created () {
|
|
this.layout.instances[this.side] = this;
|
|
this.__updateSizeOnLayout(this.miniToOverlay, this.size);
|
|
this.__update('space', this.onLayout);
|
|
this.__update('offset', this.offset);
|
|
|
|
if (
|
|
this.showIfAbove === true &&
|
|
this.value !== true &&
|
|
this.showing === true &&
|
|
this.qListeners.input !== void 0
|
|
) {
|
|
this.$emit('input', true);
|
|
}
|
|
},
|
|
|
|
mounted: function mounted () {
|
|
var this$1 = this;
|
|
|
|
this.$emit('on-layout', this.onLayout);
|
|
this.$emit('mini-state', this.isMini);
|
|
|
|
this.lastDesktopState = this.showIfAbove === true;
|
|
|
|
var fn = function () {
|
|
var action = this$1.showing === true ? 'show' : 'hide';
|
|
this$1[("__" + action)](false, true);
|
|
};
|
|
|
|
if (this.layout.totalWidth !== 0) {
|
|
// make sure that all computed properties
|
|
// have been updated before calling __show/__hide()
|
|
this.$nextTick(fn);
|
|
return
|
|
}
|
|
|
|
this.watcher = this.$watch('layout.totalWidth', function () {
|
|
this$1.watcher();
|
|
this$1.watcher = void 0;
|
|
|
|
if (this$1.showing === false && this$1.showIfAbove === true && this$1.belowBreakpoint === false) {
|
|
this$1.show(false);
|
|
}
|
|
else {
|
|
fn();
|
|
}
|
|
});
|
|
},
|
|
|
|
beforeDestroy: function beforeDestroy () {
|
|
this.watcher !== void 0 && this.watcher();
|
|
clearTimeout(this.timerMini);
|
|
|
|
this.showing === true && this.__cleanup();
|
|
|
|
if (this.layout.instances[this.side] === this) {
|
|
this.layout.instances[this.side] = void 0;
|
|
this.__update('size', 0);
|
|
this.__update('offset', 0);
|
|
this.__update('space', false);
|
|
}
|
|
},
|
|
|
|
render: function render (h) {
|
|
var child = [];
|
|
|
|
if (this.belowBreakpoint === true) {
|
|
this.noSwipeOpen !== true && child.push(
|
|
h('div', {
|
|
staticClass: ("q-drawer__opener fixed-" + (this.side)),
|
|
attrs: ariaHidden,
|
|
directives: this.openDirective
|
|
})
|
|
);
|
|
|
|
child.push(
|
|
h('div', {
|
|
ref: 'backdrop',
|
|
staticClass: 'fullscreen q-drawer__backdrop',
|
|
class: this.backdropClass,
|
|
attrs: ariaHidden,
|
|
style: this.lastBackdropBg !== void 0
|
|
? { backgroundColor: this.lastBackdropBg }
|
|
: null,
|
|
on: cache(this, 'bkdrop', { click: this.hide }),
|
|
directives: this.showing === false
|
|
? void 0
|
|
: this.backdropCloseDirective
|
|
})
|
|
);
|
|
}
|
|
|
|
var content = [
|
|
h('div', {
|
|
staticClass: 'q-drawer__content fit ' + (this.layout.container === true ? 'overflow-auto' : 'scroll'),
|
|
class: this.contentClass,
|
|
style: this.contentStyle
|
|
}, this.isMini === true && this.$scopedSlots.mini !== void 0
|
|
? this.$scopedSlots.mini()
|
|
: slot(this, 'default')
|
|
)
|
|
];
|
|
|
|
if (this.elevated === true && this.showing === true) {
|
|
content.push(
|
|
h('div', {
|
|
staticClass: 'q-layout__shadow absolute-full overflow-hidden no-pointer-events'
|
|
})
|
|
);
|
|
}
|
|
|
|
child.push(
|
|
h('aside', {
|
|
ref: 'content',
|
|
staticClass: "q-drawer",
|
|
class: this.classes,
|
|
style: this.style,
|
|
on: this.onNativeEvents,
|
|
directives: this.belowBreakpoint === true
|
|
? this.contentCloseDirective
|
|
: void 0
|
|
}, content)
|
|
);
|
|
|
|
return h('div', { staticClass: 'q-drawer-container' }, child)
|
|
}
|
|
});
|
|
|
|
var lazyRulesValues = [ true, false, 'ondemand' ];
|
|
|
|
var ValidateMixin = {
|
|
props: {
|
|
value: {},
|
|
|
|
error: {
|
|
type: Boolean,
|
|
default: null
|
|
},
|
|
errorMessage: String,
|
|
noErrorIcon: Boolean,
|
|
|
|
rules: Array,
|
|
reactiveRules: Boolean,
|
|
lazyRules: {
|
|
type: [ Boolean, String ],
|
|
validator: function (v) { return lazyRulesValues.includes(v); }
|
|
}
|
|
},
|
|
|
|
data: function data () {
|
|
return {
|
|
isDirty: null,
|
|
innerError: false,
|
|
innerErrorMessage: void 0
|
|
}
|
|
},
|
|
|
|
watch: {
|
|
value: function value () {
|
|
this.__validateIfNeeded();
|
|
},
|
|
|
|
reactiveRules: {
|
|
handler: function handler (val) {
|
|
var this$1 = this;
|
|
|
|
if (val === true) {
|
|
if (this.unwatchRules === void 0) {
|
|
this.unwatchRules = this.$watch('rules', function () {
|
|
this$1.__validateIfNeeded(true);
|
|
});
|
|
}
|
|
}
|
|
else if (this.unwatchRules !== void 0) {
|
|
this.unwatchRules();
|
|
this.unwatchRules = void 0;
|
|
}
|
|
},
|
|
immediate: true
|
|
},
|
|
|
|
focused: function focused (focused$1) {
|
|
if (this.lazyRules !== 'ondemand') {
|
|
if (focused$1 === true) {
|
|
if (this.isDirty === null) {
|
|
this.isDirty = false;
|
|
}
|
|
}
|
|
else if (this.isDirty === false && this.hasRules === true) {
|
|
this.isDirty = true;
|
|
this.validate();
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
computed: {
|
|
hasRules: function hasRules () {
|
|
return this.rules !== void 0 &&
|
|
this.rules !== null &&
|
|
this.rules.length > 0
|
|
},
|
|
|
|
hasError: function hasError () {
|
|
return this.error === true || this.innerError === true
|
|
},
|
|
|
|
computedErrorMessage: function computedErrorMessage () {
|
|
return typeof this.errorMessage === 'string' && this.errorMessage.length > 0
|
|
? this.errorMessage
|
|
: this.innerErrorMessage
|
|
}
|
|
},
|
|
|
|
mounted: function mounted () {
|
|
this.validateIndex = 0;
|
|
},
|
|
|
|
beforeDestroy: function beforeDestroy () {
|
|
this.unwatchRules !== void 0 && this.unwatchRules();
|
|
},
|
|
|
|
methods: {
|
|
resetValidation: function resetValidation () {
|
|
this.validateIndex++;
|
|
this.innerLoading = false;
|
|
this.isDirty = null;
|
|
this.innerError = false;
|
|
this.innerErrorMessage = void 0;
|
|
},
|
|
|
|
/*
|
|
* Return value
|
|
* - true (validation succeeded)
|
|
* - false (validation failed)
|
|
* - Promise (pending async validation)
|
|
*/
|
|
validate: function validate (val) {
|
|
var this$1 = this;
|
|
if ( val === void 0 ) val = this.value;
|
|
|
|
if (this.hasRules !== true) {
|
|
return true
|
|
}
|
|
|
|
this.validateIndex++;
|
|
|
|
if (this.innerLoading !== true && this.lazyRules !== true) {
|
|
this.isDirty = true;
|
|
}
|
|
|
|
var update = function (err, msg) {
|
|
if (this$1.innerError !== err) {
|
|
this$1.innerError = err;
|
|
}
|
|
|
|
var m = msg || void 0;
|
|
|
|
if (this$1.innerErrorMessage !== m) {
|
|
this$1.innerErrorMessage = m;
|
|
}
|
|
|
|
if (this$1.innerLoading !== false) {
|
|
this$1.innerLoading = false;
|
|
}
|
|
};
|
|
|
|
var promises = [];
|
|
|
|
for (var i = 0; i < this.rules.length; i++) {
|
|
var rule = this.rules[i];
|
|
var res = (void 0);
|
|
|
|
if (typeof rule === 'function') {
|
|
res = rule(val);
|
|
}
|
|
else if (typeof rule === 'string' && testPattern[rule] !== void 0) {
|
|
res = testPattern[rule](val);
|
|
}
|
|
|
|
if (res === false || typeof res === 'string') {
|
|
update(true, res);
|
|
return false
|
|
}
|
|
else if (res !== true && res !== void 0) {
|
|
promises.push(res);
|
|
}
|
|
}
|
|
|
|
if (promises.length === 0) {
|
|
update(false);
|
|
return true
|
|
}
|
|
|
|
if (this.innerLoading !== true) {
|
|
this.innerLoading = true;
|
|
}
|
|
|
|
var index = this.validateIndex;
|
|
|
|
return Promise.all(promises).then(
|
|
function (res) {
|
|
if (index !== this$1.validateIndex) {
|
|
return true
|
|
}
|
|
|
|
if (res === void 0 || Array.isArray(res) === false || res.length === 0) {
|
|
update(false);
|
|
return true
|
|
}
|
|
|
|
var msg = res.find(function (r) { return r === false || typeof r === 'string'; });
|
|
update(msg !== void 0, msg);
|
|
return msg === void 0
|
|
},
|
|
function (e) {
|
|
if (index === this$1.validateIndex) {
|
|
console.error(e);
|
|
update(true);
|
|
return false
|
|
}
|
|
|
|
return true
|
|
}
|
|
)
|
|
},
|
|
|
|
__validateIfNeeded: function __validateIfNeeded (changedRules) {
|
|
if (
|
|
this.hasRules === true &&
|
|
this.lazyRules !== 'ondemand' &&
|
|
(this.isDirty === true || (this.lazyRules !== true && changedRules !== true))
|
|
) {
|
|
this.validate();
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Based on the work of https://github.com/jchook/uuid-random
|
|
*/
|
|
|
|
var
|
|
buf,
|
|
bufIdx = 0;
|
|
var hexBytes = new Array(256);
|
|
|
|
// Pre-calculate toString(16) for speed
|
|
for (var i = 0; i < 256; i++) {
|
|
hexBytes[i] = (i + 0x100).toString(16).substr(1);
|
|
}
|
|
|
|
// Use best available PRNG
|
|
var randomBytes = (function () {
|
|
// Node & Browser support
|
|
var lib = typeof crypto !== 'undefined'
|
|
? crypto
|
|
: (
|
|
typeof window !== 'undefined'
|
|
? window.msCrypto // IE11
|
|
: void 0
|
|
);
|
|
|
|
if (lib !== void 0) {
|
|
if (lib.randomBytes !== void 0) {
|
|
return lib.randomBytes
|
|
}
|
|
if (lib.getRandomValues !== void 0) {
|
|
return function (n) {
|
|
var bytes = new Uint8Array(n);
|
|
lib.getRandomValues(bytes);
|
|
return bytes
|
|
}
|
|
}
|
|
}
|
|
|
|
return function (n) {
|
|
var r = [];
|
|
for (var i = n; i > 0; i--) {
|
|
r.push(Math.floor(Math.random() * 256));
|
|
}
|
|
return r
|
|
}
|
|
})();
|
|
|
|
// Buffer random numbers for speed
|
|
// Reduce memory usage by decreasing this number (min 16)
|
|
// or improve speed by increasing this number (try 16384)
|
|
var BUFFER_SIZE = 4096;
|
|
|
|
function uid$2 () {
|
|
// Buffer some random bytes for speed
|
|
if (buf === void 0 || (bufIdx + 16 > BUFFER_SIZE)) {
|
|
bufIdx = 0;
|
|
buf = randomBytes(BUFFER_SIZE);
|
|
}
|
|
|
|
var b = Array.prototype.slice.call(buf, bufIdx, (bufIdx += 16));
|
|
b[6] = (b[6] & 0x0f) | 0x40;
|
|
b[8] = (b[8] & 0x3f) | 0x80;
|
|
|
|
return hexBytes[b[0]] + hexBytes[b[1]] +
|
|
hexBytes[b[2]] + hexBytes[b[3]] + '-' +
|
|
hexBytes[b[4]] + hexBytes[b[5]] + '-' +
|
|
hexBytes[b[6]] + hexBytes[b[7]] + '-' +
|
|
hexBytes[b[8]] + hexBytes[b[9]] + '-' +
|
|
hexBytes[b[10]] + hexBytes[b[11]] +
|
|
hexBytes[b[12]] + hexBytes[b[13]] +
|
|
hexBytes[b[14]] + hexBytes[b[15]]
|
|
}
|
|
|
|
function getTargetUid (val) {
|
|
return val === void 0 ? ("f_" + (uid$2())) : val
|
|
}
|
|
|
|
var QField = Vue.extend({
|
|
name: 'QField',
|
|
|
|
mixins: [ DarkMixin, ValidateMixin, AttrsMixin ],
|
|
|
|
inheritAttrs: false,
|
|
|
|
props: {
|
|
label: String,
|
|
stackLabel: Boolean,
|
|
hint: String,
|
|
hideHint: Boolean,
|
|
prefix: String,
|
|
suffix: String,
|
|
|
|
labelColor: String,
|
|
color: String,
|
|
bgColor: String,
|
|
|
|
filled: Boolean,
|
|
outlined: Boolean,
|
|
borderless: Boolean,
|
|
standout: [Boolean, String],
|
|
|
|
square: Boolean,
|
|
|
|
loading: Boolean,
|
|
|
|
labelSlot: Boolean,
|
|
|
|
bottomSlots: Boolean,
|
|
hideBottomSpace: Boolean,
|
|
|
|
rounded: Boolean,
|
|
dense: Boolean,
|
|
itemAligned: Boolean,
|
|
|
|
counter: Boolean,
|
|
|
|
clearable: Boolean,
|
|
clearIcon: String,
|
|
|
|
disable: Boolean,
|
|
readonly: Boolean,
|
|
|
|
autofocus: Boolean,
|
|
|
|
for: String,
|
|
|
|
maxlength: [Number, String],
|
|
maxValues: [Number, String] // private, do not add to JSON; internally needed by QSelect
|
|
},
|
|
|
|
data: function data () {
|
|
return {
|
|
focused: false,
|
|
targetUid: getTargetUid(this.for),
|
|
|
|
// used internally by validation for QInput
|
|
// or menu handling for QSelect
|
|
innerLoading: false
|
|
}
|
|
},
|
|
|
|
watch: {
|
|
for: function for$1 (val) {
|
|
// don't transform targetUid into a computed
|
|
// prop as it will break SSR
|
|
this.targetUid = getTargetUid(val);
|
|
}
|
|
},
|
|
|
|
computed: {
|
|
editable: function editable () {
|
|
return this.disable !== true && this.readonly !== true
|
|
},
|
|
|
|
hasValue: function hasValue () {
|
|
var value = this.__getControl === void 0 ? this.value : this.innerValue;
|
|
|
|
return value !== void 0 &&
|
|
value !== null &&
|
|
('' + value).length > 0
|
|
},
|
|
|
|
computedCounter: function computedCounter () {
|
|
if (this.counter !== false) {
|
|
var len = typeof this.value === 'string' || typeof this.value === 'number'
|
|
? ('' + this.value).length
|
|
: (Array.isArray(this.value) === true ? this.value.length : 0);
|
|
|
|
var max = this.maxlength !== void 0
|
|
? this.maxlength
|
|
: this.maxValues;
|
|
|
|
return len + (max !== void 0 ? ' / ' + max : '')
|
|
}
|
|
},
|
|
|
|
floatingLabel: function floatingLabel () {
|
|
return this.stackLabel === true ||
|
|
this.focused === true ||
|
|
(
|
|
this.inputValue !== void 0 && this.hideSelected === true
|
|
? this.inputValue.length > 0
|
|
: this.hasValue === true
|
|
) ||
|
|
(
|
|
this.displayValue !== void 0 &&
|
|
this.displayValue !== null &&
|
|
('' + this.displayValue).length > 0
|
|
)
|
|
},
|
|
|
|
shouldRenderBottom: function shouldRenderBottom () {
|
|
return this.bottomSlots === true ||
|
|
this.hint !== void 0 ||
|
|
this.hasRules === true ||
|
|
this.counter === true ||
|
|
this.error !== null
|
|
},
|
|
|
|
classes: function classes () {
|
|
var obj;
|
|
|
|
return ( obj = {}, obj[this.fieldClass] = this.fieldClass !== void 0, obj[("q-field--" + (this.styleType))] = true, obj['q-field--rounded'] = this.rounded, obj['q-field--square'] = this.square, obj['q-field--focused'] = this.focused === true || this.hasError === true, obj['q-field--float'] = this.floatingLabel, obj['q-field--labeled'] = this.hasLabel, obj['q-field--dense'] = this.dense, obj['q-field--item-aligned q-item-type'] = this.itemAligned, obj['q-field--dark'] = this.isDark, obj['q-field--auto-height'] = this.__getControl === void 0, obj['q-field--with-bottom'] = this.hideBottomSpace !== true && this.shouldRenderBottom === true, obj['q-field--error'] = this.hasError, obj['q-field--readonly'] = this.readonly === true && this.disable !== true, obj['q-field--disabled'] = this.disable, obj )
|
|
},
|
|
|
|
styleType: function styleType () {
|
|
if (this.filled === true) { return 'filled' }
|
|
if (this.outlined === true) { return 'outlined' }
|
|
if (this.borderless === true) { return 'borderless' }
|
|
if (this.standout) { return 'standout' }
|
|
return 'standard'
|
|
},
|
|
|
|
contentClass: function contentClass () {
|
|
var cls = [];
|
|
|
|
if (this.hasError === true) {
|
|
cls.push('text-negative');
|
|
}
|
|
else if (typeof this.standout === 'string' && this.standout.length > 0 && this.focused === true) {
|
|
return this.standout
|
|
}
|
|
else if (this.color !== void 0) {
|
|
cls.push('text-' + this.color);
|
|
}
|
|
|
|
if (this.bgColor !== void 0) {
|
|
cls.push(("bg-" + (this.bgColor)));
|
|
}
|
|
|
|
return cls
|
|
},
|
|
|
|
hasLabel: function hasLabel () {
|
|
return this.labelSlot === true || this.label !== void 0
|
|
},
|
|
|
|
labelClass: function labelClass () {
|
|
if (
|
|
this.labelColor !== void 0 &&
|
|
this.hasError !== true
|
|
) {
|
|
return 'text-' + this.labelColor
|
|
}
|
|
},
|
|
|
|
controlSlotScope: function controlSlotScope () {
|
|
return {
|
|
id: this.targetUid,
|
|
field: this.$el,
|
|
editable: this.editable,
|
|
focused: this.focused,
|
|
floatingLabel: this.floatingLabel,
|
|
value: this.value,
|
|
emitValue: this.__emitValue
|
|
}
|
|
},
|
|
|
|
attrs: function attrs () {
|
|
var attrs = {
|
|
for: this.targetUid
|
|
};
|
|
|
|
if (this.disable === true) {
|
|
attrs['aria-disabled'] = 'true';
|
|
}
|
|
else if (this.readonly === true) {
|
|
attrs['aria-readonly'] = 'true';
|
|
}
|
|
|
|
return attrs
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
focus: function focus () {
|
|
if (this.showPopup !== void 0 && this.hasDialog === true) {
|
|
this.showPopup();
|
|
return
|
|
}
|
|
|
|
this.__focus();
|
|
},
|
|
|
|
blur: function blur () {
|
|
var el = document.activeElement;
|
|
// IE can have null document.activeElement
|
|
if (el !== null && this.$el.contains(el)) {
|
|
el.blur();
|
|
}
|
|
},
|
|
|
|
__focus: function __focus () {
|
|
var el = document.activeElement;
|
|
var target = this.$refs.target;
|
|
// IE can have null document.activeElement
|
|
if (target !== void 0 && (el === null || el.id !== this.targetUid)) {
|
|
target.hasAttribute('tabindex') === true || (target = target.querySelector('[tabindex]'));
|
|
target !== null && target !== el && target.focus();
|
|
}
|
|
},
|
|
|
|
__getContent: function __getContent (h) {
|
|
var node = [];
|
|
|
|
this.$scopedSlots.prepend !== void 0 && node.push(
|
|
h('div', {
|
|
staticClass: 'q-field__prepend q-field__marginal row no-wrap items-center',
|
|
key: 'prepend',
|
|
on: this.slotsEvents
|
|
}, this.$scopedSlots.prepend())
|
|
);
|
|
|
|
node.push(
|
|
h('div', {
|
|
staticClass: 'q-field__control-container col relative-position row no-wrap q-anchor--skip'
|
|
}, this.__getControlContainer(h))
|
|
);
|
|
|
|
this.$scopedSlots.append !== void 0 && node.push(
|
|
h('div', {
|
|
staticClass: 'q-field__append q-field__marginal row no-wrap items-center',
|
|
key: 'append',
|
|
on: this.slotsEvents
|
|
}, this.$scopedSlots.append())
|
|
);
|
|
|
|
this.hasError === true && this.noErrorIcon === false && node.push(
|
|
this.__getInnerAppendNode(h, 'error', [
|
|
h(QIcon, { props: { name: this.$q.iconSet.field.error, color: 'negative' } })
|
|
])
|
|
);
|
|
|
|
if (this.loading === true || this.innerLoading === true) {
|
|
node.push(
|
|
this.__getInnerAppendNode(
|
|
h,
|
|
'inner-loading-append',
|
|
this.$scopedSlots.loading !== void 0
|
|
? this.$scopedSlots.loading()
|
|
: [ h(QSpinner, { props: { color: this.color } }) ]
|
|
)
|
|
);
|
|
}
|
|
else if (this.clearable === true && this.hasValue === true && this.editable === true) {
|
|
node.push(
|
|
this.__getInnerAppendNode(h, 'inner-clearable-append', [
|
|
h(QIcon, {
|
|
staticClass: 'q-field__focusable-action',
|
|
props: { tag: 'button', name: this.clearIcon || this.$q.iconSet.field.clear },
|
|
attrs: { tabindex: 0, type: 'button' },
|
|
on: this.clearableEvents
|
|
})
|
|
])
|
|
);
|
|
}
|
|
|
|
this.__getInnerAppend !== void 0 && node.push(
|
|
this.__getInnerAppendNode(h, 'inner-append', this.__getInnerAppend(h))
|
|
);
|
|
|
|
this.__getControlChild !== void 0 && node.push(
|
|
this.__getControlChild(h)
|
|
);
|
|
|
|
return node
|
|
},
|
|
|
|
__getControlContainer: function __getControlContainer (h) {
|
|
var node = [];
|
|
|
|
this.prefix !== void 0 && this.prefix !== null && node.push(
|
|
h('div', {
|
|
staticClass: 'q-field__prefix no-pointer-events row items-center'
|
|
}, [ this.prefix ])
|
|
);
|
|
|
|
if (this.hasShadow === true && this.__getShadowControl !== void 0) {
|
|
node.push(
|
|
this.__getShadowControl(h)
|
|
);
|
|
}
|
|
|
|
if (this.__getControl !== void 0) {
|
|
node.push(this.__getControl(h));
|
|
}
|
|
// internal usage only:
|
|
else if (this.$scopedSlots.rawControl !== void 0) {
|
|
node.push(this.$scopedSlots.rawControl());
|
|
}
|
|
else if (this.$scopedSlots.control !== void 0) {
|
|
node.push(
|
|
h('div', {
|
|
ref: 'target',
|
|
staticClass: 'q-field__native row',
|
|
attrs: Object.assign({}, this.qAttrs,
|
|
{'data-autofocus': this.autofocus})
|
|
}, this.$scopedSlots.control(this.controlSlotScope))
|
|
);
|
|
}
|
|
|
|
this.hasLabel === true && node.push(
|
|
h('div', {
|
|
staticClass: 'q-field__label no-pointer-events absolute ellipsis',
|
|
class: this.labelClass
|
|
}, [ slot(this, 'label', this.label) ])
|
|
);
|
|
|
|
this.suffix !== void 0 && this.suffix !== null && node.push(
|
|
h('div', {
|
|
staticClass: 'q-field__suffix no-pointer-events row items-center'
|
|
}, [ this.suffix ])
|
|
);
|
|
|
|
return node.concat(
|
|
this.__getDefaultSlot !== void 0
|
|
? this.__getDefaultSlot(h)
|
|
: slot(this, 'default')
|
|
)
|
|
},
|
|
|
|
__getBottom: function __getBottom (h) {
|
|
var msg, key;
|
|
|
|
if (this.hasError === true) {
|
|
if (this.computedErrorMessage !== void 0) {
|
|
msg = [ h('div', [ this.computedErrorMessage ]) ];
|
|
key = this.computedErrorMessage;
|
|
}
|
|
else {
|
|
msg = slot(this, 'error');
|
|
key = 'q--slot-error';
|
|
}
|
|
}
|
|
else if (this.hideHint !== true || this.focused === true) {
|
|
if (this.hint !== void 0) {
|
|
msg = [ h('div', [ this.hint ]) ];
|
|
key = this.hint;
|
|
}
|
|
else {
|
|
msg = slot(this, 'hint');
|
|
key = 'q--slot-hint';
|
|
}
|
|
}
|
|
|
|
var hasCounter = this.counter === true || this.$scopedSlots.counter !== void 0;
|
|
|
|
if (this.hideBottomSpace === true && hasCounter === false && msg === void 0) {
|
|
return
|
|
}
|
|
|
|
var main = h('div', {
|
|
key: key,
|
|
staticClass: 'q-field__messages col'
|
|
}, msg);
|
|
|
|
return h('div', {
|
|
staticClass: 'q-field__bottom row items-start q-field__bottom--' +
|
|
(this.hideBottomSpace !== true ? 'animated' : 'stale')
|
|
}, [
|
|
this.hideBottomSpace === true
|
|
? main
|
|
: h('transition', { props: { name: 'q-transition--field-message' } }, [
|
|
main
|
|
]),
|
|
|
|
hasCounter === true
|
|
? h('div', {
|
|
staticClass: 'q-field__counter'
|
|
}, this.$scopedSlots.counter !== void 0 ? this.$scopedSlots.counter() : [ this.computedCounter ])
|
|
: null
|
|
])
|
|
},
|
|
|
|
__getInnerAppendNode: function __getInnerAppendNode (h, key, content) {
|
|
return content === null ? null : h('div', {
|
|
staticClass: 'q-field__append q-field__marginal row no-wrap items-center q-anchor--skip',
|
|
key: key
|
|
}, content)
|
|
},
|
|
|
|
__onControlPopupShow: function __onControlPopupShow (e) {
|
|
e !== void 0 && stop(e);
|
|
this.$emit('popup-show', e);
|
|
this.hasPopupOpen = true;
|
|
this.__onControlFocusin(e);
|
|
},
|
|
|
|
__onControlPopupHide: function __onControlPopupHide (e) {
|
|
e !== void 0 && stop(e);
|
|
this.$emit('popup-hide', e);
|
|
this.hasPopupOpen = false;
|
|
this.__onControlFocusout(e);
|
|
},
|
|
|
|
__onControlFocusin: function __onControlFocusin (e) {
|
|
if (this.editable === true && this.focused === false) {
|
|
this.focused = true;
|
|
this.$emit('focus', e);
|
|
}
|
|
},
|
|
|
|
__onControlFocusout: function __onControlFocusout (e, then) {
|
|
var this$1 = this;
|
|
|
|
clearTimeout(this.focusoutTimer);
|
|
this.focusoutTimer = setTimeout(function () {
|
|
if (
|
|
document.hasFocus() === true && (
|
|
this$1.hasPopupOpen === true ||
|
|
this$1.$refs === void 0 ||
|
|
this$1.$refs.control === void 0 ||
|
|
this$1.$refs.control.contains(document.activeElement) !== false
|
|
)
|
|
) {
|
|
return
|
|
}
|
|
|
|
if (this$1.focused === true) {
|
|
this$1.focused = false;
|
|
this$1.$emit('blur', e);
|
|
}
|
|
|
|
then !== void 0 && then();
|
|
});
|
|
},
|
|
|
|
__clearValue: function __clearValue (e) {
|
|
// prevent activating the field but keep focus on desktop
|
|
stopAndPrevent(e);
|
|
var el = this.$refs.target || this.$el;
|
|
el.focus();
|
|
|
|
if (this.type === 'file') {
|
|
// do not let focus be triggered
|
|
// as it will make the native file dialog
|
|
// appear for another selection
|
|
this.$refs.input.value = null;
|
|
}
|
|
|
|
this.$emit('input', null);
|
|
this.$emit('clear', this.value);
|
|
},
|
|
|
|
__emitValue: function __emitValue (value) {
|
|
this.$emit('input', value);
|
|
}
|
|
},
|
|
|
|
render: function render (h) {
|
|
this.__onPreRender !== void 0 && this.__onPreRender();
|
|
this.__onPostRender !== void 0 && this.$nextTick(this.__onPostRender);
|
|
|
|
return h('label', {
|
|
staticClass: 'q-field q-validation-component row no-wrap items-start',
|
|
class: this.classes,
|
|
attrs: this.attrs
|
|
}, [
|
|
this.$scopedSlots.before !== void 0 ? h('div', {
|
|
staticClass: 'q-field__before q-field__marginal row no-wrap items-center',
|
|
on: this.slotsEvents
|
|
}, this.$scopedSlots.before()) : null,
|
|
|
|
h('div', {
|
|
staticClass: 'q-field__inner relative-position col self-stretch column justify-center'
|
|
}, [
|
|
h('div', {
|
|
ref: 'control',
|
|
staticClass: 'q-field__control relative-position row no-wrap',
|
|
class: this.contentClass,
|
|
attrs: { tabindex: -1 },
|
|
on: this.controlEvents
|
|
}, this.__getContent(h)),
|
|
|
|
this.shouldRenderBottom === true
|
|
? this.__getBottom(h)
|
|
: null
|
|
]),
|
|
|
|
this.$scopedSlots.after !== void 0 ? h('div', {
|
|
staticClass: 'q-field__after q-field__marginal row no-wrap items-center',
|
|
on: this.slotsEvents
|
|
}, this.$scopedSlots.after()) : null
|
|
])
|
|
},
|
|
|
|
created: function created () {
|
|
this.__onPreRender !== void 0 && this.__onPreRender();
|
|
|
|
this.slotsEvents = { click: prevent };
|
|
|
|
this.clearableEvents = { click: this.__clearValue };
|
|
|
|
this.controlEvents = this.__getControlEvents !== void 0
|
|
? this.__getControlEvents()
|
|
: {
|
|
focusin: this.__onControlFocusin,
|
|
focusout: this.__onControlFocusout,
|
|
'popup-show': this.__onControlPopupShow,
|
|
'popup-hide': this.__onControlPopupHide
|
|
};
|
|
},
|
|
|
|
mounted: function mounted () {
|
|
if (fromSSR === true && this.for === void 0) {
|
|
this.targetUid = getTargetUid();
|
|
}
|
|
|
|
this.autofocus === true && this.focus();
|
|
},
|
|
|
|
beforeDestroy: function beforeDestroy () {
|
|
clearTimeout(this.focusoutTimer);
|
|
}
|
|
});
|
|
|
|
function filterFiles (files, rejectedFiles, failedPropValidation, filterFn) {
|
|
var acceptedFiles = [];
|
|
|
|
files.forEach(function (file) {
|
|
if (filterFn(file) === true) {
|
|
acceptedFiles.push(file);
|
|
}
|
|
else {
|
|
rejectedFiles.push({ failedPropValidation: failedPropValidation, file: file });
|
|
}
|
|
});
|
|
|
|
return acceptedFiles
|
|
}
|
|
|
|
var FileMixin = {
|
|
props: {
|
|
multiple: Boolean,
|
|
accept: String,
|
|
capture: String,
|
|
maxFileSize: [ Number, String ],
|
|
maxTotalSize: [ Number, String ],
|
|
maxFiles: [ Number, String ],
|
|
filter: Function
|
|
},
|
|
|
|
computed: {
|
|
extensions: function extensions () {
|
|
if (this.accept !== void 0) {
|
|
return this.accept.split(',').map(function (ext) {
|
|
ext = ext.trim();
|
|
if (ext === '*') { // support "*"
|
|
return '*/'
|
|
}
|
|
else if (ext.endsWith('/*')) { // support "image/*" or "*/*"
|
|
ext = ext.slice(0, ext.length - 1);
|
|
}
|
|
return ext.toUpperCase()
|
|
})
|
|
}
|
|
},
|
|
|
|
maxFilesNumber: function maxFilesNumber () {
|
|
return parseInt(this.maxFiles, 10)
|
|
},
|
|
|
|
maxTotalSizeNumber: function maxTotalSizeNumber () {
|
|
return parseInt(this.maxTotalSize, 10)
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
pickFiles: function pickFiles (e) {
|
|
if (this.editable) {
|
|
var input = this.__getFileInput();
|
|
input && input.click(e);
|
|
}
|
|
},
|
|
|
|
addFiles: function addFiles (files) {
|
|
if (this.editable && files) {
|
|
this.__addFiles(null, files);
|
|
}
|
|
},
|
|
|
|
__processFiles: function __processFiles (e, filesToProcess, currentFileList, append) {
|
|
var this$1 = this;
|
|
|
|
var files = Array.from(filesToProcess || e.target.files);
|
|
var rejectedFiles = [];
|
|
|
|
var done = function () {
|
|
if (rejectedFiles.length > 0) {
|
|
this$1.$emit('rejected', rejectedFiles);
|
|
}
|
|
};
|
|
|
|
// filter file types
|
|
if (this.accept !== void 0 && this.extensions.indexOf('*/') === -1) {
|
|
files = filterFiles(files, rejectedFiles, 'accept', function (file) {
|
|
return this$1.extensions.some(function (ext) { return (
|
|
file.type.toUpperCase().startsWith(ext) ||
|
|
file.name.toUpperCase().endsWith(ext)
|
|
); })
|
|
});
|
|
|
|
if (files.length === 0) { return done() }
|
|
}
|
|
|
|
// filter max file size
|
|
if (this.maxFileSize !== void 0) {
|
|
var maxFileSize = parseInt(this.maxFileSize, 10);
|
|
files = filterFiles(files, rejectedFiles, 'max-file-size', function (file) {
|
|
return file.size <= maxFileSize
|
|
});
|
|
|
|
if (files.length === 0) { return done() }
|
|
}
|
|
|
|
// Cordova/iOS allows selecting multiple files even when the
|
|
// multiple attribute is not specified. We also normalize drag'n'dropped
|
|
// files here:
|
|
if (this.multiple !== true) {
|
|
files = [ files[0] ];
|
|
}
|
|
|
|
if (this.maxTotalSize !== void 0) {
|
|
var size = append === true
|
|
? currentFileList.reduce(function (total, file) { return total + file.size; }, 0)
|
|
: 0;
|
|
|
|
files = filterFiles(files, rejectedFiles, 'max-total-size', function (file) {
|
|
size += file.size;
|
|
return size <= this$1.maxTotalSizeNumber
|
|
});
|
|
|
|
if (files.length === 0) { return done() }
|
|
}
|
|
|
|
// do we have custom filter function?
|
|
if (typeof this.filter === 'function') {
|
|
var filteredFiles = this.filter(files);
|
|
files = filterFiles(files, rejectedFiles, 'filter', function (file) {
|
|
return filteredFiles.includes(file)
|
|
});
|
|
}
|
|
|
|
if (this.maxFiles !== void 0) {
|
|
var filesNumber = append === true
|
|
? currentFileList.length
|
|
: 0;
|
|
|
|
files = filterFiles(files, rejectedFiles, 'max-files', function () {
|
|
filesNumber++;
|
|
return filesNumber <= this$1.maxFilesNumber
|
|
});
|
|
|
|
if (files.length === 0) { return done() }
|
|
}
|
|
|
|
done();
|
|
|
|
if (files.length > 0) {
|
|
return files
|
|
}
|
|
},
|
|
|
|
__onDragOver: function __onDragOver (e) {
|
|
stopAndPrevent(e);
|
|
this.dnd = true;
|
|
},
|
|
|
|
__onDragLeave: function __onDragLeave (e) {
|
|
stopAndPrevent(e);
|
|
this.dnd = false;
|
|
},
|
|
|
|
__onDrop: function __onDrop (e) {
|
|
stopAndPrevent(e);
|
|
var files = e.dataTransfer.files;
|
|
|
|
if (files.length > 0) {
|
|
this.__addFiles(null, files);
|
|
}
|
|
|
|
this.dnd = false;
|
|
},
|
|
|
|
__getDnd: function __getDnd (h, type) {
|
|
if (this.dnd === true) {
|
|
return h('div', {
|
|
staticClass: ("q-" + type + "__dnd absolute-full"),
|
|
on: cache(this, 'dnd', {
|
|
dragenter: stopAndPrevent,
|
|
dragover: stopAndPrevent,
|
|
dragleave: this.__onDragLeave,
|
|
drop: this.__onDrop
|
|
})
|
|
})
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
var FileValueMixin = {
|
|
computed: {
|
|
formDomProps: function formDomProps () {
|
|
if (this.type !== 'file') {
|
|
return
|
|
}
|
|
|
|
try {
|
|
var dt = 'DataTransfer' in window
|
|
? new DataTransfer()
|
|
: ('ClipboardEvent' in window
|
|
? new ClipboardEvent('').clipboardData
|
|
: void 0
|
|
);
|
|
|
|
if (Object(this.value) === this.value) {
|
|
('length' in this.value
|
|
? Array.from(this.value)
|
|
: [ this.value ]
|
|
).forEach(function (file) {
|
|
dt.items.add(file);
|
|
});
|
|
}
|
|
|
|
return {
|
|
files: dt.files
|
|
}
|
|
}
|
|
catch (e) {
|
|
return {
|
|
files: void 0
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
// leave NAMED_MASKS at top of file (code referenced from docs)
|
|
var NAMED_MASKS = {
|
|
date: '####/##/##',
|
|
datetime: '####/##/## ##:##',
|
|
time: '##:##',
|
|
fulltime: '##:##:##',
|
|
phone: '(###) ### - ####',
|
|
card: '#### #### #### ####'
|
|
};
|
|
|
|
var TOKENS = {
|
|
'#': { pattern: '[\\d]', negate: '[^\\d]' },
|
|
|
|
S: { pattern: '[a-zA-Z]', negate: '[^a-zA-Z]' },
|
|
N: { pattern: '[0-9a-zA-Z]', negate: '[^0-9a-zA-Z]' },
|
|
|
|
A: { pattern: '[a-zA-Z]', negate: '[^a-zA-Z]', transform: function (v) { return v.toLocaleUpperCase(); } },
|
|
a: { pattern: '[a-zA-Z]', negate: '[^a-zA-Z]', transform: function (v) { return v.toLocaleLowerCase(); } },
|
|
|
|
X: { pattern: '[0-9a-zA-Z]', negate: '[^0-9a-zA-Z]', transform: function (v) { return v.toLocaleUpperCase(); } },
|
|
x: { pattern: '[0-9a-zA-Z]', negate: '[^0-9a-zA-Z]', transform: function (v) { return v.toLocaleLowerCase(); } }
|
|
};
|
|
|
|
var KEYS = Object.keys(TOKENS);
|
|
KEYS.forEach(function (key) {
|
|
TOKENS[key].regex = new RegExp(TOKENS[key].pattern);
|
|
});
|
|
|
|
var
|
|
tokenRegexMask = new RegExp('\\\\([^.*+?^${}()|([\\]])|([.*+?^${}()|[\\]])|([' + KEYS.join('') + '])|(.)', 'g'),
|
|
escRegex = /[.*+?^${}()|[\]\\]/g;
|
|
|
|
var MARKER = String.fromCharCode(1);
|
|
|
|
var MaskMixin = {
|
|
props: {
|
|
mask: String,
|
|
reverseFillMask: Boolean,
|
|
fillMask: [Boolean, String],
|
|
unmaskedValue: Boolean
|
|
},
|
|
|
|
watch: {
|
|
type: function type () {
|
|
this.__updateMaskInternals();
|
|
},
|
|
|
|
mask: function mask (v) {
|
|
if (v !== void 0) {
|
|
this.__updateMaskValue(this.innerValue, true);
|
|
}
|
|
else {
|
|
var val = this.__unmask(this.innerValue);
|
|
this.__updateMaskInternals();
|
|
this.value !== val && this.$emit('input', val);
|
|
}
|
|
},
|
|
|
|
fillMask: function fillMask () {
|
|
this.hasMask === true && this.__updateMaskValue(this.innerValue, true);
|
|
},
|
|
|
|
reverseFillMask: function reverseFillMask () {
|
|
this.hasMask === true && this.__updateMaskValue(this.innerValue, true);
|
|
},
|
|
|
|
unmaskedValue: function unmaskedValue () {
|
|
this.hasMask === true && this.__updateMaskValue(this.innerValue);
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
__getInitialMaskedValue: function __getInitialMaskedValue () {
|
|
this.__updateMaskInternals();
|
|
|
|
if (this.hasMask === true) {
|
|
var masked = this.__mask(this.__unmask(this.value));
|
|
|
|
return this.fillMask !== false
|
|
? this.__fillWithMask(masked)
|
|
: masked
|
|
}
|
|
|
|
return this.value
|
|
},
|
|
|
|
__getPaddedMaskMarked: function __getPaddedMaskMarked (size) {
|
|
if (size < this.maskMarked.length) {
|
|
return this.maskMarked.slice(-size)
|
|
}
|
|
|
|
var
|
|
maskMarked = this.maskMarked,
|
|
pad = '';
|
|
var
|
|
padPos = maskMarked.indexOf(MARKER);
|
|
|
|
if (padPos > -1) {
|
|
for (var i = size - maskMarked.length; i > 0; i--) {
|
|
pad += MARKER;
|
|
}
|
|
|
|
maskMarked = maskMarked.slice(0, padPos) + pad + maskMarked.slice(padPos);
|
|
}
|
|
|
|
return maskMarked
|
|
},
|
|
|
|
__updateMaskInternals: function __updateMaskInternals () {
|
|
var this$1 = this;
|
|
|
|
this.hasMask = this.mask !== void 0 &&
|
|
this.mask.length > 0 &&
|
|
['text', 'search', 'url', 'tel', 'password'].includes(this.type);
|
|
|
|
if (this.hasMask === false) {
|
|
this.computedUnmask = void 0;
|
|
this.maskMarked = '';
|
|
this.maskReplaced = '';
|
|
return
|
|
}
|
|
|
|
var
|
|
computedMask = NAMED_MASKS[this.mask] === void 0
|
|
? this.mask
|
|
: NAMED_MASKS[this.mask],
|
|
fillChar = typeof this.fillMask === 'string' && this.fillMask.length > 0
|
|
? this.fillMask.slice(0, 1)
|
|
: '_',
|
|
fillCharEscaped = fillChar.replace(escRegex, '\\$&'),
|
|
unmask = [],
|
|
extract = [],
|
|
mask = [];
|
|
|
|
var
|
|
firstMatch = this.reverseFillMask === true,
|
|
unmaskChar = '',
|
|
negateChar = '';
|
|
|
|
computedMask.replace(tokenRegexMask, function (_, char1, esc, token, char2) {
|
|
if (token !== void 0) {
|
|
var c = TOKENS[token];
|
|
mask.push(c);
|
|
negateChar = c.negate;
|
|
if (firstMatch === true) {
|
|
extract.push('(?:' + negateChar + '+)?(' + c.pattern + '+)?(?:' + negateChar + '+)?(' + c.pattern + '+)?');
|
|
firstMatch = false;
|
|
}
|
|
extract.push('(?:' + negateChar + '+)?(' + c.pattern + ')?');
|
|
}
|
|
else if (esc !== void 0) {
|
|
unmaskChar = '\\' + (esc === '\\' ? '' : esc);
|
|
mask.push(esc);
|
|
unmask.push('([^' + unmaskChar + ']+)?' + unmaskChar + '?');
|
|
}
|
|
else {
|
|
var c$1 = char1 !== void 0 ? char1 : char2;
|
|
unmaskChar = c$1 === '\\' ? '\\\\\\\\' : c$1.replace(escRegex, '\\\\$&');
|
|
mask.push(c$1);
|
|
unmask.push('([^' + unmaskChar + ']+)?' + unmaskChar + '?');
|
|
}
|
|
});
|
|
|
|
var
|
|
unmaskMatcher = new RegExp(
|
|
'^' +
|
|
unmask.join('') +
|
|
'(' + (unmaskChar === '' ? '.' : '[^' + unmaskChar + ']') + '+)?' +
|
|
'$'
|
|
),
|
|
extractLast = extract.length - 1,
|
|
extractMatcher = extract.map(function (re, index) {
|
|
if (index === 0 && this$1.reverseFillMask === true) {
|
|
return new RegExp('^' + fillCharEscaped + '*' + re)
|
|
}
|
|
else if (index === extractLast) {
|
|
return new RegExp(
|
|
'^' + re +
|
|
'(' + (negateChar === '' ? '.' : negateChar) + '+)?' +
|
|
(this$1.reverseFillMask === true ? '$' : fillCharEscaped + '*')
|
|
)
|
|
}
|
|
|
|
return new RegExp('^' + re)
|
|
});
|
|
|
|
this.computedMask = mask;
|
|
this.computedUnmask = function (val) {
|
|
var unmaskMatch = unmaskMatcher.exec(val);
|
|
if (unmaskMatch !== null) {
|
|
val = unmaskMatch.slice(1).join('');
|
|
}
|
|
|
|
var
|
|
extractMatch = [],
|
|
extractMatcherLength = extractMatcher.length;
|
|
|
|
for (var i = 0, str = val; i < extractMatcherLength; i++) {
|
|
var m = extractMatcher[i].exec(str);
|
|
|
|
if (m === null) {
|
|
break
|
|
}
|
|
|
|
str = str.slice(m.shift().length);
|
|
extractMatch.push.apply(extractMatch, m);
|
|
}
|
|
if (extractMatch.length > 0) {
|
|
return extractMatch.join('')
|
|
}
|
|
|
|
return val
|
|
};
|
|
this.maskMarked = mask.map(function (v) { return typeof v === 'string' ? v : MARKER; }).join('');
|
|
this.maskReplaced = this.maskMarked.split(MARKER).join(fillChar);
|
|
},
|
|
|
|
__updateMaskValue: function __updateMaskValue (rawVal, updateMaskInternals, inputType) {
|
|
var this$1 = this;
|
|
|
|
var
|
|
inp = this.$refs.input,
|
|
end = inp.selectionEnd,
|
|
endReverse = inp.value.length - end,
|
|
unmasked = this.__unmask(rawVal);
|
|
|
|
// Update here so unmask uses the original fillChar
|
|
updateMaskInternals === true && this.__updateMaskInternals();
|
|
|
|
var
|
|
preMasked = this.__mask(unmasked),
|
|
masked = this.fillMask !== false
|
|
? this.__fillWithMask(preMasked)
|
|
: preMasked,
|
|
changed = this.innerValue !== masked;
|
|
|
|
// We want to avoid "flickering" so we set value immediately
|
|
inp.value !== masked && (inp.value = masked);
|
|
|
|
changed === true && (this.innerValue = masked);
|
|
|
|
document.activeElement === inp && this.$nextTick(function () {
|
|
if (masked === this$1.maskReplaced) {
|
|
var cursor = this$1.reverseFillMask === true ? this$1.maskReplaced.length : 0;
|
|
inp.setSelectionRange(cursor, cursor, 'forward');
|
|
|
|
return
|
|
}
|
|
|
|
if (inputType === 'insertFromPaste' && this$1.reverseFillMask !== true) {
|
|
var cursor$1 = end - 1;
|
|
this$1.__moveCursorRight(inp, cursor$1, cursor$1);
|
|
|
|
return
|
|
}
|
|
|
|
if (['deleteContentBackward', 'deleteContentForward'].indexOf(inputType) > -1) {
|
|
var cursor$2 = this$1.reverseFillMask === true
|
|
? Math.max(0, masked.length - (masked === this$1.maskReplaced ? 0 : Math.min(preMasked.length, endReverse) + 1)) + 1
|
|
: end;
|
|
inp.setSelectionRange(cursor$2, cursor$2, 'forward');
|
|
|
|
return
|
|
}
|
|
|
|
if (this$1.reverseFillMask === true) {
|
|
if (changed === true) {
|
|
var cursor$3 = Math.max(0, masked.length - (masked === this$1.maskReplaced ? 0 : Math.min(preMasked.length, endReverse + 1)));
|
|
this$1.__moveCursorRightReverse(inp, cursor$3, cursor$3);
|
|
}
|
|
else {
|
|
var cursor$4 = masked.length - endReverse;
|
|
inp.setSelectionRange(cursor$4, cursor$4, 'backward');
|
|
}
|
|
}
|
|
else {
|
|
if (changed === true) {
|
|
var cursor$5 = Math.max(0, this$1.maskMarked.indexOf(MARKER), Math.min(preMasked.length, end) - 1);
|
|
this$1.__moveCursorRight(inp, cursor$5, cursor$5);
|
|
}
|
|
else {
|
|
var cursor$6 = end - 1;
|
|
this$1.__moveCursorRight(inp, cursor$6, cursor$6);
|
|
}
|
|
}
|
|
});
|
|
|
|
var val = this.unmaskedValue === true
|
|
? this.__unmask(masked)
|
|
: masked;
|
|
|
|
this.value !== val && this.__emitValue(val, true);
|
|
},
|
|
|
|
__moveCursorForPaste: function __moveCursorForPaste (inp, start, end) {
|
|
var preMasked = this.__mask(this.__unmask(inp.value));
|
|
|
|
start = Math.max(0, this.maskMarked.indexOf(MARKER), Math.min(preMasked.length, start));
|
|
|
|
inp.setSelectionRange(start, end, 'forward');
|
|
},
|
|
|
|
__moveCursorLeft: function __moveCursorLeft (inp, start, end, selection) {
|
|
var noMarkBefore = this.maskMarked.slice(start - 1).indexOf(MARKER) === -1;
|
|
var i = Math.max(0, start - 1);
|
|
|
|
for (; i >= 0; i--) {
|
|
if (this.maskMarked[i] === MARKER) {
|
|
start = i;
|
|
noMarkBefore === true && start++;
|
|
break
|
|
}
|
|
}
|
|
|
|
if (
|
|
i < 0 &&
|
|
this.maskMarked[start] !== void 0 &&
|
|
this.maskMarked[start] !== MARKER
|
|
) {
|
|
return this.__moveCursorRight(inp, 0, 0)
|
|
}
|
|
|
|
start >= 0 && inp.setSelectionRange(
|
|
start,
|
|
selection === true ? end : start, 'backward'
|
|
);
|
|
},
|
|
|
|
__moveCursorRight: function __moveCursorRight (inp, start, end, selection) {
|
|
var limit = inp.value.length;
|
|
var i = Math.min(limit, end + 1);
|
|
|
|
for (; i <= limit; i++) {
|
|
if (this.maskMarked[i] === MARKER) {
|
|
end = i;
|
|
break
|
|
}
|
|
else if (this.maskMarked[i - 1] === MARKER) {
|
|
end = i;
|
|
}
|
|
}
|
|
|
|
if (
|
|
i > limit &&
|
|
this.maskMarked[end - 1] !== void 0 &&
|
|
this.maskMarked[end - 1] !== MARKER
|
|
) {
|
|
return this.__moveCursorLeft(inp, limit, limit)
|
|
}
|
|
|
|
inp.setSelectionRange(selection ? start : end, end, 'forward');
|
|
},
|
|
|
|
__moveCursorLeftReverse: function __moveCursorLeftReverse (inp, start, end, selection) {
|
|
var
|
|
maskMarked = this.__getPaddedMaskMarked(inp.value.length);
|
|
var i = Math.max(0, start - 1);
|
|
|
|
for (; i >= 0; i--) {
|
|
if (maskMarked[i - 1] === MARKER) {
|
|
start = i;
|
|
break
|
|
}
|
|
else if (maskMarked[i] === MARKER) {
|
|
start = i;
|
|
if (i === 0) {
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
if (
|
|
i < 0 &&
|
|
maskMarked[start] !== void 0 &&
|
|
maskMarked[start] !== MARKER
|
|
) {
|
|
return this.__moveCursorRightReverse(inp, 0, 0)
|
|
}
|
|
|
|
start >= 0 && inp.setSelectionRange(
|
|
start,
|
|
selection === true ? end : start, 'backward'
|
|
);
|
|
},
|
|
|
|
__moveCursorRightReverse: function __moveCursorRightReverse (inp, start, end, selection) {
|
|
var
|
|
limit = inp.value.length,
|
|
maskMarked = this.__getPaddedMaskMarked(limit),
|
|
noMarkBefore = maskMarked.slice(0, end + 1).indexOf(MARKER) === -1;
|
|
var i = Math.min(limit, end + 1);
|
|
|
|
for (; i <= limit; i++) {
|
|
if (maskMarked[i - 1] === MARKER) {
|
|
end = i;
|
|
end > 0 && noMarkBefore === true && end--;
|
|
break
|
|
}
|
|
}
|
|
|
|
if (
|
|
i > limit &&
|
|
maskMarked[end - 1] !== void 0 &&
|
|
maskMarked[end - 1] !== MARKER
|
|
) {
|
|
return this.__moveCursorLeftReverse(inp, limit, limit)
|
|
}
|
|
|
|
inp.setSelectionRange(selection === true ? start : end, end, 'forward');
|
|
},
|
|
|
|
__onMaskedKeydown: function __onMaskedKeydown (e) {
|
|
if (shouldIgnoreKey(e) === true) {
|
|
return
|
|
}
|
|
|
|
var
|
|
inp = this.$refs.input,
|
|
start = inp.selectionStart,
|
|
end = inp.selectionEnd;
|
|
|
|
if (e.keyCode === 37 || e.keyCode === 39) { // Left / Right
|
|
var fn = this['__moveCursor' + (e.keyCode === 39 ? 'Right' : 'Left') + (this.reverseFillMask === true ? 'Reverse' : '')];
|
|
|
|
e.preventDefault();
|
|
fn(inp, start, end, e.shiftKey);
|
|
}
|
|
else if (
|
|
e.keyCode === 8 && // Backspace
|
|
this.reverseFillMask !== true &&
|
|
start === end
|
|
) {
|
|
this.__moveCursorLeft(inp, start, end, true);
|
|
}
|
|
else if (
|
|
e.keyCode === 46 && // Delete
|
|
this.reverseFillMask === true &&
|
|
start === end
|
|
) {
|
|
this.__moveCursorRightReverse(inp, start, end, true);
|
|
}
|
|
|
|
this.$emit('keydown', e);
|
|
},
|
|
|
|
__mask: function __mask (val) {
|
|
if (val === void 0 || val === null || val === '') { return '' }
|
|
|
|
if (this.reverseFillMask === true) {
|
|
return this.__maskReverse(val)
|
|
}
|
|
|
|
var mask = this.computedMask;
|
|
|
|
var valIndex = 0, output = '';
|
|
|
|
for (var maskIndex = 0; maskIndex < mask.length; maskIndex++) {
|
|
var
|
|
valChar = val[valIndex],
|
|
maskDef = mask[maskIndex];
|
|
|
|
if (typeof maskDef === 'string') {
|
|
output += maskDef;
|
|
valChar === maskDef && valIndex++;
|
|
}
|
|
else if (valChar !== void 0 && maskDef.regex.test(valChar)) {
|
|
output += maskDef.transform !== void 0
|
|
? maskDef.transform(valChar)
|
|
: valChar;
|
|
valIndex++;
|
|
}
|
|
else {
|
|
return output
|
|
}
|
|
}
|
|
|
|
return output
|
|
},
|
|
|
|
__maskReverse: function __maskReverse (val) {
|
|
var
|
|
mask = this.computedMask,
|
|
firstTokenIndex = this.maskMarked.indexOf(MARKER);
|
|
|
|
var valIndex = val.length - 1, output = '';
|
|
|
|
for (var maskIndex = mask.length - 1; maskIndex >= 0; maskIndex--) {
|
|
var maskDef = mask[maskIndex];
|
|
|
|
var valChar = val[valIndex];
|
|
|
|
if (typeof maskDef === 'string') {
|
|
output = maskDef + output;
|
|
valChar === maskDef && valIndex--;
|
|
}
|
|
else if (valChar !== void 0 && maskDef.regex.test(valChar)) {
|
|
do {
|
|
output = (maskDef.transform !== void 0 ? maskDef.transform(valChar) : valChar) + output;
|
|
valIndex--;
|
|
valChar = val[valIndex];
|
|
// eslint-disable-next-line no-unmodified-loop-condition
|
|
} while (firstTokenIndex === maskIndex && valChar !== void 0 && maskDef.regex.test(valChar))
|
|
}
|
|
else {
|
|
return output
|
|
}
|
|
}
|
|
|
|
return output
|
|
},
|
|
|
|
__unmask: function __unmask (val) {
|
|
return typeof val !== 'string' || this.computedUnmask === void 0
|
|
? (typeof val === 'number' ? this.computedUnmask('' + val) : val)
|
|
: this.computedUnmask(val)
|
|
},
|
|
|
|
__fillWithMask: function __fillWithMask (val) {
|
|
if (this.maskReplaced.length - val.length <= 0) {
|
|
return val
|
|
}
|
|
|
|
return this.reverseFillMask === true && val.length > 0
|
|
? this.maskReplaced.slice(0, -val.length) + val
|
|
: val + this.maskReplaced.slice(val.length)
|
|
}
|
|
}
|
|
};
|
|
|
|
var isJapanese = /[\u3000-\u303f\u3040-\u309f\u30a0-\u30ff\uff00-\uff9f\u4e00-\u9faf\u3400-\u4dbf]/;
|
|
var isChinese = /(?:[\u3300-\u4DBF\u4E00-\u9FFF\uF900-\uFAFF\uFE30-\uFE4F]|[\uD840-\uD868\uD86A-\uD872][\uDC00-\uDFFF]|\uD869[\uDC00-\uDEDF\uDF00-\uDFFF]|\uD873[\uDC00-\uDEAF]|\uD87E[\uDC00-\uDE1F])/;
|
|
var isKorean = /[\u3131-\u314e\u314f-\u3163\uac00-\ud7a3]/;
|
|
|
|
var CompositionMixin = {
|
|
methods: {
|
|
__onComposition: function __onComposition (e) {
|
|
if (e.type === 'compositionend' || e.type === 'change') {
|
|
if (e.target.composing !== true) { return }
|
|
e.target.composing = false;
|
|
this.__onInput(e);
|
|
}
|
|
else if (e.type === 'compositionupdate') {
|
|
if (
|
|
typeof e.data === 'string' &&
|
|
isJapanese.test(e.data) === false &&
|
|
isChinese.test(e.data) === false &&
|
|
isKorean.test(e.data) === false
|
|
) {
|
|
e.target.composing = false;
|
|
}
|
|
}
|
|
else {
|
|
e.target.composing = true;
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
var QInput = Vue.extend({
|
|
name: 'QInput',
|
|
|
|
mixins: [
|
|
QField,
|
|
MaskMixin,
|
|
CompositionMixin,
|
|
FormFieldMixin,
|
|
FileValueMixin,
|
|
ListenersMixin
|
|
],
|
|
|
|
props: {
|
|
value: { required: false },
|
|
|
|
shadowText: String,
|
|
|
|
type: {
|
|
type: String,
|
|
default: 'text'
|
|
},
|
|
|
|
debounce: [String, Number],
|
|
|
|
autogrow: Boolean, // makes a textarea
|
|
|
|
inputClass: [Array, String, Object],
|
|
inputStyle: [Array, String, Object]
|
|
},
|
|
|
|
watch: {
|
|
value: function value (v) {
|
|
if (this.hasMask === true) {
|
|
if (this.stopValueWatcher === true) {
|
|
this.stopValueWatcher = false;
|
|
return
|
|
}
|
|
|
|
this.__updateMaskValue(v);
|
|
}
|
|
else if (this.innerValue !== v) {
|
|
this.innerValue = v;
|
|
|
|
if (
|
|
this.type === 'number' &&
|
|
this.hasOwnProperty('tempValue') === true
|
|
) {
|
|
if (this.typedNumber === true) {
|
|
this.typedNumber = false;
|
|
}
|
|
else {
|
|
delete this.tempValue;
|
|
}
|
|
}
|
|
}
|
|
|
|
// textarea only
|
|
this.autogrow === true && this.$nextTick(this.__adjustHeight);
|
|
},
|
|
|
|
autogrow: function autogrow (autogrow$1) {
|
|
// textarea only
|
|
if (autogrow$1 === true) {
|
|
this.$nextTick(this.__adjustHeight);
|
|
}
|
|
// if it has a number of rows set respect it
|
|
else if (this.qAttrs.rows > 0 && this.$refs.input !== void 0) {
|
|
var inp = this.$refs.input;
|
|
inp.style.height = 'auto';
|
|
}
|
|
},
|
|
|
|
dense: function dense () {
|
|
this.autogrow === true && this.$nextTick(this.__adjustHeight);
|
|
}
|
|
},
|
|
|
|
data: function data () {
|
|
return { innerValue: this.__getInitialMaskedValue() }
|
|
},
|
|
|
|
computed: {
|
|
isTextarea: function isTextarea () {
|
|
return this.type === 'textarea' || this.autogrow === true
|
|
},
|
|
|
|
fieldClass: function fieldClass () {
|
|
return "q-" + (this.isTextarea === true ? 'textarea' : 'input') +
|
|
(this.autogrow === true ? ' q-textarea--autogrow' : '')
|
|
},
|
|
|
|
hasShadow: function hasShadow () {
|
|
return this.type !== 'file' &&
|
|
typeof this.shadowText === 'string' &&
|
|
this.shadowText.length > 0
|
|
},
|
|
|
|
onEvents: function onEvents () {
|
|
var on = Object.assign({}, this.qListeners,
|
|
{input: this.__onInput,
|
|
paste: this.__onPaste,
|
|
// Safari < 10.2 & UIWebView doesn't fire compositionend when
|
|
// switching focus before confirming composition choice
|
|
// this also fixes the issue where some browsers e.g. iOS Chrome
|
|
// fires "change" instead of "input" on autocomplete.
|
|
change: this.__onChange,
|
|
blur: this.__onFinishEditing,
|
|
focus: stop});
|
|
|
|
on.compositionstart = on.compositionupdate = on.compositionend = this.__onComposition;
|
|
|
|
if (this.hasMask === true) {
|
|
on.keydown = this.__onMaskedKeydown;
|
|
}
|
|
|
|
if (this.autogrow === true) {
|
|
on.animationend = this.__adjustHeight;
|
|
}
|
|
|
|
return on
|
|
},
|
|
|
|
inputAttrs: function inputAttrs () {
|
|
var attrs = Object.assign({}, {tabindex: 0,
|
|
'data-autofocus': this.autofocus,
|
|
rows: this.type === 'textarea' ? 6 : void 0,
|
|
'aria-label': this.label,
|
|
name: this.nameProp},
|
|
this.qAttrs,
|
|
{id: this.targetUid,
|
|
type: this.type,
|
|
maxlength: this.maxlength,
|
|
disabled: this.disable === true,
|
|
readonly: this.readonly === true});
|
|
|
|
if (this.autogrow === true) {
|
|
attrs.rows = 1;
|
|
}
|
|
|
|
return attrs
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
focus: function focus () {
|
|
var el = document.activeElement;
|
|
if (
|
|
this.$refs.input !== void 0 &&
|
|
this.$refs.input !== el &&
|
|
// IE can have null document.activeElement
|
|
(el === null || el.id !== this.targetUid)
|
|
) {
|
|
this.$refs.input.focus();
|
|
}
|
|
},
|
|
|
|
select: function select () {
|
|
this.$refs.input !== void 0 && this.$refs.input.select();
|
|
},
|
|
|
|
__onPaste: function __onPaste (e) {
|
|
if (this.hasMask === true && this.reverseFillMask !== true) {
|
|
var inp = e.target;
|
|
this.__moveCursorForPaste(inp, inp.selectionStart, inp.selectionEnd);
|
|
}
|
|
|
|
this.$emit('paste', e);
|
|
},
|
|
|
|
__onInput: function __onInput (e) {
|
|
if (e && e.target && e.target.composing === true) {
|
|
return
|
|
}
|
|
|
|
if (this.type === 'file') {
|
|
this.$emit('input', e.target.files);
|
|
return
|
|
}
|
|
|
|
var val = e.target.value;
|
|
|
|
if (this.hasMask === true) {
|
|
this.__updateMaskValue(val, false, e.inputType);
|
|
}
|
|
else {
|
|
this.__emitValue(val);
|
|
}
|
|
|
|
// we need to trigger it immediately too,
|
|
// to avoid "flickering"
|
|
this.autogrow === true && this.__adjustHeight();
|
|
},
|
|
|
|
__emitValue: function __emitValue (val, stopWatcher) {
|
|
var this$1 = this;
|
|
|
|
this.emitValueFn = function () {
|
|
if (
|
|
this$1.type !== 'number' &&
|
|
this$1.hasOwnProperty('tempValue') === true
|
|
) {
|
|
delete this$1.tempValue;
|
|
}
|
|
|
|
if (this$1.value !== val) {
|
|
stopWatcher === true && (this$1.stopValueWatcher = true);
|
|
this$1.$emit('input', val);
|
|
}
|
|
|
|
this$1.emitValueFn = void 0;
|
|
};
|
|
|
|
if (this.type === 'number') {
|
|
this.typedNumber = true;
|
|
this.tempValue = val;
|
|
}
|
|
|
|
if (this.debounce !== void 0) {
|
|
clearTimeout(this.emitTimer);
|
|
this.tempValue = val;
|
|
this.emitTimer = setTimeout(this.emitValueFn, this.debounce);
|
|
}
|
|
else {
|
|
this.emitValueFn();
|
|
}
|
|
},
|
|
|
|
// textarea only
|
|
__adjustHeight: function __adjustHeight () {
|
|
var inp = this.$refs.input;
|
|
if (inp !== void 0) {
|
|
var parentStyle = inp.parentNode.style;
|
|
|
|
// reset height of textarea to a small size to detect the real height
|
|
// but keep the total control size the same
|
|
parentStyle.marginBottom = (inp.scrollHeight - 1) + 'px';
|
|
inp.style.height = '1px';
|
|
|
|
inp.style.height = inp.scrollHeight + 'px';
|
|
parentStyle.marginBottom = '';
|
|
}
|
|
},
|
|
|
|
__onChange: function __onChange (e) {
|
|
this.__onComposition(e);
|
|
|
|
clearTimeout(this.emitTimer);
|
|
this.emitValueFn !== void 0 && this.emitValueFn();
|
|
|
|
this.$emit('change', e);
|
|
},
|
|
|
|
__onFinishEditing: function __onFinishEditing (e) {
|
|
var this$1 = this;
|
|
|
|
e !== void 0 && stop(e);
|
|
|
|
clearTimeout(this.emitTimer);
|
|
this.emitValueFn !== void 0 && this.emitValueFn();
|
|
|
|
this.typedNumber = false;
|
|
this.stopValueWatcher = false;
|
|
delete this.tempValue;
|
|
|
|
this.type !== 'file' && this.$nextTick(function () {
|
|
if (this$1.$refs.input !== void 0) {
|
|
this$1.$refs.input.value = this$1.innerValue !== void 0 ? this$1.innerValue : '';
|
|
}
|
|
});
|
|
},
|
|
|
|
__getCurValue: function __getCurValue () {
|
|
return this.hasOwnProperty('tempValue') === true
|
|
? this.tempValue
|
|
: (this.innerValue !== void 0 ? this.innerValue : '')
|
|
},
|
|
|
|
__getShadowControl: function __getShadowControl (h) {
|
|
return h('div', {
|
|
staticClass: 'q-field__native q-field__shadow absolute-full no-pointer-events'
|
|
}, [
|
|
h('span', { staticClass: 'invisible' }, this.__getCurValue()),
|
|
h('span', this.shadowText)
|
|
])
|
|
},
|
|
|
|
__getControl: function __getControl (h) {
|
|
return h(this.isTextarea === true ? 'textarea' : 'input', {
|
|
ref: 'input',
|
|
staticClass: 'q-field__native q-placeholder',
|
|
style: this.inputStyle,
|
|
class: this.inputClass,
|
|
attrs: this.inputAttrs,
|
|
on: this.onEvents,
|
|
domProps: this.type !== 'file'
|
|
? { value: this.__getCurValue() }
|
|
: this.formDomProps
|
|
})
|
|
}
|
|
},
|
|
|
|
mounted: function mounted () {
|
|
// textarea only
|
|
this.autogrow === true && this.__adjustHeight();
|
|
},
|
|
|
|
beforeDestroy: function beforeDestroy () {
|
|
this.__onFinishEditing();
|
|
}
|
|
});
|
|
|
|
var QTooltip = Vue.extend({
|
|
name: 'QTooltip',
|
|
|
|
mixins: [ AnchorMixin, ModelToggleMixin, Portal, TransitionMixin ],
|
|
|
|
props: {
|
|
maxHeight: {
|
|
type: String,
|
|
default: null
|
|
},
|
|
maxWidth: {
|
|
type: String,
|
|
default: null
|
|
},
|
|
|
|
transitionShow: {
|
|
default: 'jump-down'
|
|
},
|
|
transitionHide: {
|
|
default: 'jump-up'
|
|
},
|
|
|
|
anchor: {
|
|
type: String,
|
|
default: 'bottom middle',
|
|
validator: validatePosition
|
|
},
|
|
self: {
|
|
type: String,
|
|
default: 'top middle',
|
|
validator: validatePosition
|
|
},
|
|
offset: {
|
|
type: Array,
|
|
default: function () { return [14, 14]; },
|
|
validator: validateOffset
|
|
},
|
|
|
|
scrollTarget: {
|
|
default: void 0
|
|
},
|
|
|
|
delay: {
|
|
type: Number,
|
|
default: 0
|
|
},
|
|
|
|
hideDelay: {
|
|
type: Number,
|
|
default: 0
|
|
}
|
|
},
|
|
|
|
computed: {
|
|
anchorOrigin: function anchorOrigin () {
|
|
return parsePosition(this.anchor)
|
|
},
|
|
|
|
selfOrigin: function selfOrigin () {
|
|
return parsePosition(this.self)
|
|
},
|
|
|
|
hideOnRouteChange: function hideOnRouteChange () {
|
|
return this.persistent !== true
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
__show: function __show (evt) {
|
|
var this$1 = this;
|
|
|
|
this.__showPortal();
|
|
|
|
this.__nextTick(function () {
|
|
this$1.observer = new MutationObserver(function () { return this$1.updatePosition(); });
|
|
this$1.observer.observe(this$1.__portal.$el, { attributes: false, childList: true, characterData: true, subtree: true });
|
|
this$1.updatePosition();
|
|
this$1.__configureScrollTarget();
|
|
});
|
|
|
|
this.__setTimeout(function () {
|
|
this$1.$emit('show', evt);
|
|
}, 300);
|
|
},
|
|
|
|
__hide: function __hide (evt) {
|
|
var this$1 = this;
|
|
|
|
this.__anchorCleanup();
|
|
|
|
this.__setTimeout(function () {
|
|
this$1.__hidePortal();
|
|
this$1.$emit('hide', evt);
|
|
}, 300);
|
|
},
|
|
|
|
__anchorCleanup: function __anchorCleanup () {
|
|
if (this.observer !== void 0) {
|
|
this.observer.disconnect();
|
|
this.observer = void 0;
|
|
}
|
|
|
|
this.__unconfigureScrollTarget();
|
|
cleanEvt(this, 'tooltipTemp');
|
|
},
|
|
|
|
updatePosition: function updatePosition () {
|
|
if (this.anchorEl === void 0 || this.__portal === void 0) {
|
|
return
|
|
}
|
|
|
|
var el = this.__portal.$el;
|
|
|
|
if (el.nodeType === 8) { // IE replaces the comment with delay
|
|
setTimeout(this.updatePosition, 25);
|
|
return
|
|
}
|
|
|
|
setPosition({
|
|
el: el,
|
|
offset: this.offset,
|
|
anchorEl: this.anchorEl,
|
|
anchorOrigin: this.anchorOrigin,
|
|
selfOrigin: this.selfOrigin,
|
|
maxHeight: this.maxHeight,
|
|
maxWidth: this.maxWidth
|
|
});
|
|
},
|
|
|
|
__delayShow: function __delayShow (evt) {
|
|
var this$1 = this;
|
|
|
|
if (this.$q.platform.is.mobile === true) {
|
|
clearSelection();
|
|
document.body.classList.add('non-selectable');
|
|
|
|
var target = getTouchTarget(this.anchorEl);
|
|
var evts = ['touchmove', 'touchcancel', 'touchend', 'click']
|
|
.map(function (e) { return ([ target, e, '__delayHide', 'passiveCapture' ]); });
|
|
|
|
addEvt(this, 'tooltipTemp', evts);
|
|
}
|
|
|
|
this.__setTimeout(function () {
|
|
this$1.show(evt);
|
|
}, this.delay);
|
|
},
|
|
|
|
__delayHide: function __delayHide (evt) {
|
|
var this$1 = this;
|
|
|
|
this.__clearTimeout();
|
|
|
|
if (this.$q.platform.is.mobile === true) {
|
|
cleanEvt(this, 'tooltipTemp');
|
|
clearSelection();
|
|
// delay needed otherwise selection still occurs
|
|
setTimeout(function () {
|
|
document.body.classList.remove('non-selectable');
|
|
}, 10);
|
|
}
|
|
|
|
this.__setTimeout(function () {
|
|
this$1.hide(evt);
|
|
}, this.hideDelay);
|
|
},
|
|
|
|
__configureAnchorEl: function __configureAnchorEl () {
|
|
if (this.noParentEvent === true || this.anchorEl === void 0) { return }
|
|
|
|
var evts = this.$q.platform.is.mobile === true
|
|
? [
|
|
[ this.anchorEl, 'touchstart', '__delayShow', 'passive' ]
|
|
]
|
|
: [
|
|
[ this.anchorEl, 'mouseenter', '__delayShow', 'passive' ],
|
|
[ this.anchorEl, 'mouseleave', '__delayHide', 'passive' ]
|
|
];
|
|
|
|
addEvt(this, 'anchor', evts);
|
|
},
|
|
|
|
__unconfigureScrollTarget: function __unconfigureScrollTarget () {
|
|
if (this.__scrollTarget !== void 0) {
|
|
this.__changeScrollEvent(this.__scrollTarget);
|
|
this.__scrollTarget = void 0;
|
|
}
|
|
},
|
|
|
|
__configureScrollTarget: function __configureScrollTarget () {
|
|
if (this.anchorEl !== void 0 || this.scrollTarget !== void 0) {
|
|
this.__scrollTarget = getScrollTarget(this.anchorEl, this.scrollTarget);
|
|
var fn = this.noParentEvent === true
|
|
? this.updatePosition
|
|
: this.hide;
|
|
|
|
this.__changeScrollEvent(this.__scrollTarget, fn);
|
|
}
|
|
},
|
|
|
|
__renderPortal: function __renderPortal (h) {
|
|
return h('transition', {
|
|
props: { name: this.transition }
|
|
}, [
|
|
this.showing === true ? h('div', {
|
|
staticClass: 'q-tooltip q-tooltip--style q-position-engine no-pointer-events',
|
|
class: this.contentClass,
|
|
style: this.contentStyle,
|
|
attrs: {
|
|
role: 'complementary'
|
|
}
|
|
}, slot(this, 'default')) : null
|
|
])
|
|
}
|
|
},
|
|
|
|
mounted: function mounted () {
|
|
this.__processModelChange(this.value);
|
|
}
|
|
});
|
|
|
|
var QList = Vue.extend({
|
|
name: 'QList',
|
|
|
|
mixins: [ ListenersMixin, DarkMixin ],
|
|
|
|
props: {
|
|
bordered: Boolean,
|
|
dense: Boolean,
|
|
separator: Boolean,
|
|
padding: Boolean
|
|
},
|
|
|
|
computed: {
|
|
classes: function classes () {
|
|
return 'q-list' +
|
|
(this.bordered === true ? ' q-list--bordered' : '') +
|
|
(this.dense === true ? ' q-list--dense' : '') +
|
|
(this.separator === true ? ' q-list--separator' : '') +
|
|
(this.isDark === true ? ' q-list--dark' : '') +
|
|
(this.padding === true ? ' q-list--padding' : '')
|
|
}
|
|
},
|
|
|
|
render: function render (h) {
|
|
return h('div', {
|
|
class: this.classes,
|
|
on: Object.assign({}, this.qListeners)
|
|
}, slot(this, 'default'))
|
|
}
|
|
});
|
|
|
|
var QItem = Vue.extend({
|
|
name: 'QItem',
|
|
|
|
mixins: [ DarkMixin, RouterLinkMixin, TagMixin, ListenersMixin ],
|
|
|
|
props: {
|
|
active: Boolean,
|
|
|
|
clickable: Boolean,
|
|
dense: Boolean,
|
|
insetLevel: Number,
|
|
|
|
tabindex: [ String, Number ],
|
|
|
|
focused: Boolean,
|
|
manualFocus: Boolean
|
|
},
|
|
|
|
computed: {
|
|
isActionable: function isActionable () {
|
|
return this.clickable === true ||
|
|
this.hasRouterLink === true ||
|
|
this.tag === 'a' ||
|
|
this.tag === 'label'
|
|
},
|
|
|
|
isClickable: function isClickable () {
|
|
return this.disable !== true && this.isActionable === true
|
|
},
|
|
|
|
classes: function classes () {
|
|
var obj;
|
|
|
|
return ( obj = {
|
|
'q-item--clickable q-link cursor-pointer': this.isClickable,
|
|
'q-focusable q-hoverable': this.isClickable === true && this.manualFocus === false,
|
|
|
|
'q-manual-focusable': this.isClickable === true && this.manualFocus === true,
|
|
'q-manual-focusable--focused': this.isClickable === true && this.focused === true,
|
|
|
|
'q-item--dense': this.dense,
|
|
'q-item--dark': this.isDark,
|
|
'q-item--active': this.active
|
|
}, obj[this.activeClass] = this.active === true && this.hasRouterLink !== true && this.activeClass !== void 0, obj['disabled'] = this.disable, obj )
|
|
},
|
|
|
|
style: function style () {
|
|
var obj;
|
|
|
|
if (this.insetLevel !== void 0) {
|
|
var dir = this.$q.lang.rtl === true ? 'Right' : 'Left';
|
|
return ( obj = {}, obj['padding' + dir] = (16 + this.insetLevel * 56) + 'px', obj )
|
|
}
|
|
},
|
|
|
|
onEvents: function onEvents () {
|
|
return Object.assign({}, this.qListeners,
|
|
{click: this.__onClick,
|
|
keyup: this.__onKeyup})
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
__getContent: function __getContent (h) {
|
|
var child = uniqueSlot(this, 'default', []);
|
|
this.isClickable === true && child.unshift(
|
|
h('div', { staticClass: 'q-focus-helper', attrs: { tabindex: -1 }, ref: 'blurTarget' })
|
|
);
|
|
return child
|
|
},
|
|
|
|
__onClick: function __onClick (e) {
|
|
if (this.isClickable === true) {
|
|
if (this.$refs.blurTarget !== void 0) {
|
|
if (e.qKeyEvent !== true && document.activeElement === this.$el) {
|
|
this.$refs.blurTarget.focus();
|
|
}
|
|
else if (document.activeElement === this.$refs.blurTarget) {
|
|
this.$el.focus();
|
|
}
|
|
}
|
|
|
|
this.$emit('click', e);
|
|
}
|
|
},
|
|
|
|
__onKeyup: function __onKeyup (e) {
|
|
if (this.isClickable === true && isKeyCode(e, 13) === true) {
|
|
stopAndPrevent(e);
|
|
|
|
// for ripple
|
|
e.qKeyEvent = true;
|
|
|
|
// for click trigger
|
|
var evt = new MouseEvent('click', e);
|
|
evt.qKeyEvent = true;
|
|
this.$el.dispatchEvent(evt);
|
|
}
|
|
|
|
this.$emit('keyup', e);
|
|
}
|
|
},
|
|
|
|
render: function render (h) {
|
|
var data = {
|
|
staticClass: 'q-item q-item-type row no-wrap',
|
|
class: this.classes,
|
|
style: this.style
|
|
};
|
|
data[ this.hasRouterLink === true ? 'nativeOn' : 'on' ] = this.onEvents;
|
|
|
|
if (this.isClickable === true) {
|
|
data.attrs = {
|
|
tabindex: this.tabindex || '0'
|
|
};
|
|
}
|
|
else if (this.isActionable === true) {
|
|
data.attrs = {
|
|
'aria-disabled': 'true'
|
|
};
|
|
}
|
|
|
|
if (this.hasRouterLink === true) {
|
|
data.tag = 'a';
|
|
data.props = this.routerLinkProps;
|
|
|
|
return h('router-link', data, this.__getContent(h))
|
|
}
|
|
|
|
return h(
|
|
this.tag,
|
|
data,
|
|
this.__getContent(h)
|
|
)
|
|
}
|
|
});
|
|
|
|
var QItemSection = Vue.extend({
|
|
name: 'QItemSection',
|
|
|
|
mixins: [ ListenersMixin ],
|
|
|
|
props: {
|
|
avatar: Boolean,
|
|
thumbnail: Boolean,
|
|
side: Boolean,
|
|
top: Boolean,
|
|
noWrap: Boolean
|
|
},
|
|
|
|
computed: {
|
|
classes: function classes () {
|
|
var obj;
|
|
|
|
var side = this.avatar || this.side || this.thumbnail;
|
|
|
|
return ( obj = {
|
|
'q-item__section--top': this.top,
|
|
'q-item__section--avatar': this.avatar,
|
|
'q-item__section--thumbnail': this.thumbnail,
|
|
'q-item__section--side': side,
|
|
'q-item__section--nowrap': this.noWrap,
|
|
'q-item__section--main': !side
|
|
}, obj[("justify-" + (this.top ? 'start' : 'center'))] = true, obj )
|
|
}
|
|
},
|
|
|
|
render: function render (h) {
|
|
return h('div', {
|
|
staticClass: 'q-item__section column',
|
|
class: this.classes,
|
|
on: Object.assign({}, this.qListeners)
|
|
}, slot(this, 'default'))
|
|
}
|
|
});
|
|
|
|
function run (e, btn, vm) {
|
|
if (btn.handler) {
|
|
btn.handler(e, vm, vm.caret);
|
|
}
|
|
else {
|
|
vm.runCmd(btn.cmd, btn.param);
|
|
}
|
|
}
|
|
|
|
function __getGroup (h, children) {
|
|
return h('div', {
|
|
staticClass: 'q-editor__toolbar-group'
|
|
}, children)
|
|
}
|
|
|
|
function getBtn (h, vm, btn, clickHandler, active) {
|
|
if ( active === void 0 ) active = false;
|
|
|
|
var
|
|
toggled = active || (btn.type === 'toggle'
|
|
? (btn.toggled ? btn.toggled(vm) : btn.cmd && vm.caret.is(btn.cmd, btn.param))
|
|
: false),
|
|
child = [],
|
|
events = {
|
|
click: function click (e) {
|
|
clickHandler && clickHandler();
|
|
run(e, btn, vm);
|
|
}
|
|
};
|
|
|
|
if (btn.tip && vm.$q.platform.is.desktop) {
|
|
var Key = btn.key
|
|
? h('div', [h('small', ("(CTRL + " + (String.fromCharCode(btn.key)) + ")"))])
|
|
: null;
|
|
child.push(
|
|
h(QTooltip, { props: { delay: 1000 } }, [
|
|
h('div', { domProps: { innerHTML: btn.tip } }),
|
|
Key
|
|
])
|
|
);
|
|
}
|
|
|
|
return h(QBtn, {
|
|
props: Object.assign({}, vm.buttonProps,
|
|
{icon: btn.icon,
|
|
color: toggled ? btn.toggleColor || vm.toolbarToggleColor : btn.color || vm.toolbarColor,
|
|
textColor: toggled && !vm.toolbarPush ? null : btn.textColor || vm.toolbarTextColor,
|
|
label: btn.label,
|
|
disable: btn.disable ? (typeof btn.disable === 'function' ? btn.disable(vm) : true) : false,
|
|
size: 'sm'}),
|
|
on: events
|
|
}, child)
|
|
}
|
|
|
|
function getDropdown (h, vm, btn) {
|
|
var onlyIcons = btn.list === 'only-icons';
|
|
var
|
|
label = btn.label,
|
|
icon = btn.icon,
|
|
contentClass,
|
|
Items;
|
|
|
|
function closeDropdown () {
|
|
Dropdown.componentInstance.hide();
|
|
}
|
|
|
|
if (onlyIcons) {
|
|
Items = btn.options.map(function (btn) {
|
|
var active = btn.type === void 0
|
|
? vm.caret.is(btn.cmd, btn.param)
|
|
: false;
|
|
|
|
if (active) {
|
|
label = btn.tip;
|
|
icon = btn.icon;
|
|
}
|
|
return getBtn(h, vm, btn, closeDropdown, active)
|
|
});
|
|
contentClass = vm.toolbarBackgroundClass;
|
|
Items = [
|
|
__getGroup(h, Items)
|
|
];
|
|
}
|
|
else {
|
|
var activeClass = vm.toolbarToggleColor !== void 0
|
|
? ("text-" + (vm.toolbarToggleColor))
|
|
: null;
|
|
var inactiveClass = vm.toolbarTextColor !== void 0
|
|
? ("text-" + (vm.toolbarTextColor))
|
|
: null;
|
|
|
|
Items = btn.options.map(function (btn) {
|
|
var disable = btn.disable ? btn.disable(vm) : false;
|
|
var active = btn.type === void 0
|
|
? vm.caret.is(btn.cmd, btn.param)
|
|
: false;
|
|
|
|
if (active) {
|
|
label = btn.tip;
|
|
icon = btn.icon;
|
|
}
|
|
|
|
var htmlTip = btn.htmlTip;
|
|
|
|
return h(
|
|
QItem,
|
|
{
|
|
props: { active: active, activeClass: activeClass, clickable: true, disable: disable, dense: true },
|
|
on: {
|
|
click: function click (e) {
|
|
closeDropdown();
|
|
vm.$refs.content && vm.$refs.content.focus();
|
|
vm.caret.restore();
|
|
run(e, btn, vm);
|
|
}
|
|
}
|
|
},
|
|
[
|
|
btn.list === 'no-icons'
|
|
? null
|
|
: h(QItemSection, {
|
|
class: active ? activeClass : inactiveClass,
|
|
props: { side: true }
|
|
}, [
|
|
h(QIcon, { props: { name: btn.icon } })
|
|
]),
|
|
|
|
h(QItemSection, [
|
|
htmlTip
|
|
? h('div', {
|
|
domProps: { innerHTML: btn.htmlTip }
|
|
})
|
|
: (btn.tip ? h('div', [ btn.tip ]) : null)
|
|
])
|
|
]
|
|
)
|
|
});
|
|
contentClass = [vm.toolbarBackgroundClass, inactiveClass];
|
|
Items = [
|
|
h(QList, [ Items ])
|
|
];
|
|
}
|
|
|
|
var highlight = btn.highlight && label !== btn.label;
|
|
var Dropdown = h(
|
|
QBtnDropdown,
|
|
{
|
|
props: Object.assign({}, vm.buttonProps,
|
|
{noCaps: true,
|
|
noWrap: true,
|
|
color: highlight ? vm.toolbarToggleColor : vm.toolbarColor,
|
|
textColor: highlight && !vm.toolbarPush ? null : vm.toolbarTextColor,
|
|
label: btn.fixedLabel ? btn.label : label,
|
|
icon: btn.fixedIcon ? btn.icon : icon,
|
|
contentClass: contentClass})
|
|
},
|
|
Items
|
|
);
|
|
return Dropdown
|
|
}
|
|
|
|
function getToolbar (h, vm) {
|
|
if (vm.caret) {
|
|
return vm.buttons
|
|
.filter(function (f) {
|
|
return !vm.isViewingSource || f.find(function (fb) { return fb.cmd === 'viewsource'; })
|
|
})
|
|
.map(function (group) { return __getGroup(
|
|
h,
|
|
group.map(function (btn) {
|
|
if (vm.isViewingSource && btn.cmd !== 'viewsource') {
|
|
return false
|
|
}
|
|
|
|
if (btn.type === 'slot') {
|
|
return slot(vm, btn.slot)
|
|
}
|
|
|
|
if (btn.type === 'dropdown') {
|
|
return getDropdown(h, vm, btn)
|
|
}
|
|
|
|
return getBtn(h, vm, btn)
|
|
})
|
|
); })
|
|
}
|
|
}
|
|
|
|
function getFonts (defaultFont, defaultFontLabel, defaultFontIcon, fonts) {
|
|
if ( fonts === void 0 ) fonts = {};
|
|
|
|
var aliases = Object.keys(fonts);
|
|
if (aliases.length === 0) {
|
|
return {}
|
|
}
|
|
|
|
var def = {
|
|
default_font: {
|
|
cmd: 'fontName',
|
|
param: defaultFont,
|
|
icon: defaultFontIcon,
|
|
tip: defaultFontLabel
|
|
}
|
|
};
|
|
|
|
aliases.forEach(function (alias) {
|
|
var name = fonts[alias];
|
|
def[alias] = {
|
|
cmd: 'fontName',
|
|
param: name,
|
|
icon: defaultFontIcon,
|
|
tip: name,
|
|
htmlTip: ("<font face=\"" + name + "\">" + name + "</font>")
|
|
};
|
|
});
|
|
|
|
return def
|
|
}
|
|
|
|
function getLinkEditor (h, vm, ie11) {
|
|
if (vm.caret) {
|
|
var color = vm.toolbarColor || vm.toolbarTextColor;
|
|
var link = vm.editLinkUrl;
|
|
var updateLink = function () {
|
|
vm.caret.restore();
|
|
|
|
if (link !== vm.editLinkUrl) {
|
|
document.execCommand('createLink', false, link === '' ? ' ' : link);
|
|
}
|
|
|
|
vm.editLinkUrl = null;
|
|
|
|
ie11 === true && vm.$nextTick(vm.__onInput);
|
|
};
|
|
|
|
return [
|
|
h('div', { staticClass: 'q-mx-xs', 'class': ("text-" + color) }, [((vm.$q.lang.editor.url) + ": ")]),
|
|
h(QInput, {
|
|
key: 'qedt_btm_input',
|
|
staticClass: 'q-ma-none q-pa-none col q-editor-input',
|
|
props: {
|
|
value: link,
|
|
color: color,
|
|
autofocus: true,
|
|
borderless: true,
|
|
dense: true
|
|
},
|
|
on: {
|
|
input: function (val) { link = val; },
|
|
keydown: function (event) {
|
|
if (shouldIgnoreKey(event) === true) {
|
|
return
|
|
}
|
|
|
|
switch (event.keyCode) {
|
|
case 13: // ENTER key
|
|
prevent(event);
|
|
return updateLink()
|
|
case 27: // ESCAPE key
|
|
prevent(event);
|
|
vm.caret.restore();
|
|
if (!vm.editLinkUrl || vm.editLinkUrl === 'https://') {
|
|
document.execCommand('unlink');
|
|
}
|
|
vm.editLinkUrl = null;
|
|
break
|
|
}
|
|
}
|
|
}
|
|
}),
|
|
__getGroup(h, [
|
|
h(QBtn, {
|
|
key: 'qedt_btm_rem',
|
|
attrs: { tabindex: -1 },
|
|
props: Object.assign({}, vm.buttonProps,
|
|
{label: vm.$q.lang.label.remove,
|
|
noCaps: true}),
|
|
on: {
|
|
click: function () {
|
|
vm.caret.restore();
|
|
document.execCommand('unlink');
|
|
vm.editLinkUrl = null;
|
|
|
|
ie11 === true && vm.$nextTick(vm.__onInput);
|
|
}
|
|
}
|
|
}),
|
|
h(QBtn, {
|
|
key: 'qedt_btm_upd',
|
|
props: Object.assign({}, vm.buttonProps,
|
|
{label: vm.$q.lang.label.update,
|
|
noCaps: true}),
|
|
on: {
|
|
click: updateLink
|
|
}
|
|
})
|
|
])
|
|
]
|
|
}
|
|
}
|
|
|
|
function getBlockElement (el, parent) {
|
|
if (parent && el === parent) {
|
|
return null
|
|
}
|
|
|
|
var nodeName = el.nodeName.toLowerCase();
|
|
|
|
if (['div', 'li', 'ul', 'ol', 'blockquote'].includes(nodeName) === true) {
|
|
return el
|
|
}
|
|
|
|
var
|
|
style = window.getComputedStyle
|
|
? window.getComputedStyle(el)
|
|
: el.currentStyle,
|
|
display = style.display;
|
|
|
|
if (display === 'block' || display === 'table') {
|
|
return el
|
|
}
|
|
|
|
return getBlockElement(el.parentNode)
|
|
}
|
|
|
|
function isChildOf (el, parent) {
|
|
return !el || el === document.body
|
|
? false
|
|
: (parent === document ? document.body : parent).contains(el.parentNode)
|
|
}
|
|
|
|
function createRange (node, chars, range) {
|
|
if (!range) {
|
|
range = document.createRange();
|
|
range.selectNode(node);
|
|
range.setStart(node, 0);
|
|
}
|
|
|
|
if (chars.count === 0) {
|
|
range.setEnd(node, chars.count);
|
|
}
|
|
else if (chars.count > 0) {
|
|
if (node.nodeType === Node.TEXT_NODE) {
|
|
if (node.textContent.length < chars.count) {
|
|
chars.count -= node.textContent.length;
|
|
}
|
|
else {
|
|
range.setEnd(node, chars.count);
|
|
chars.count = 0;
|
|
}
|
|
}
|
|
else {
|
|
for (var lp = 0; chars.count !== 0 && lp < node.childNodes.length; lp++) {
|
|
range = createRange(node.childNodes[lp], chars, range);
|
|
}
|
|
}
|
|
}
|
|
|
|
return range
|
|
}
|
|
|
|
var urlRegex = /^https?:\/\//;
|
|
|
|
var Caret = function Caret (el, vm) {
|
|
this.el = el;
|
|
this.vm = vm;
|
|
this._range = null;
|
|
};
|
|
|
|
var prototypeAccessors = { selection: { configurable: true },hasSelection: { configurable: true },range: { configurable: true },parent: { configurable: true },blockParent: { configurable: true } };
|
|
|
|
prototypeAccessors.selection.get = function () {
|
|
if (this.el) {
|
|
var sel = document.getSelection();
|
|
|
|
// only when the selection in element
|
|
if (isChildOf(sel.anchorNode, this.el) && isChildOf(sel.focusNode, this.el)) {
|
|
return sel
|
|
}
|
|
}
|
|
|
|
return null
|
|
};
|
|
|
|
prototypeAccessors.hasSelection.get = function () {
|
|
return this.selection !== null
|
|
? this.selection.toString().length > 0
|
|
: false
|
|
};
|
|
|
|
prototypeAccessors.range.get = function () {
|
|
var sel = this.selection;
|
|
|
|
if (sel !== null && sel.rangeCount) {
|
|
return sel.getRangeAt(0)
|
|
}
|
|
|
|
return this._range
|
|
};
|
|
|
|
prototypeAccessors.parent.get = function () {
|
|
var range = this.range;
|
|
|
|
if (range !== null) {
|
|
var node = range.startContainer;
|
|
|
|
return node.nodeType === document.ELEMENT_NODE
|
|
? node
|
|
: node.parentNode
|
|
}
|
|
|
|
return null
|
|
};
|
|
|
|
prototypeAccessors.blockParent.get = function () {
|
|
var parent = this.parent;
|
|
|
|
if (parent !== null) {
|
|
return getBlockElement(parent, this.el)
|
|
}
|
|
|
|
return null
|
|
};
|
|
|
|
Caret.prototype.save = function save (range) {
|
|
if ( range === void 0 ) range = this.range;
|
|
|
|
if (range !== null) {
|
|
this._range = range;
|
|
}
|
|
};
|
|
|
|
Caret.prototype.restore = function restore (range) {
|
|
if ( range === void 0 ) range = this._range;
|
|
|
|
var
|
|
r = document.createRange(),
|
|
sel = document.getSelection();
|
|
|
|
if (range !== null) {
|
|
r.setStart(range.startContainer, range.startOffset);
|
|
r.setEnd(range.endContainer, range.endOffset);
|
|
sel.removeAllRanges();
|
|
sel.addRange(r);
|
|
}
|
|
else {
|
|
sel.selectAllChildren(this.el);
|
|
sel.collapseToEnd();
|
|
}
|
|
};
|
|
|
|
Caret.prototype.savePosition = function savePosition () {
|
|
var charCount = -1, node;
|
|
var
|
|
selection = document.getSelection(),
|
|
parentEl = this.el.parentNode;
|
|
|
|
if (selection.focusNode && isChildOf(selection.focusNode, parentEl)) {
|
|
node = selection.focusNode;
|
|
charCount = selection.focusOffset;
|
|
|
|
while (node && node !== parentEl) {
|
|
if (node !== this.el && node.previousSibling) {
|
|
node = node.previousSibling;
|
|
charCount += node.textContent.length;
|
|
}
|
|
else {
|
|
node = node.parentNode;
|
|
}
|
|
}
|
|
}
|
|
|
|
this.savedPos = charCount;
|
|
};
|
|
|
|
Caret.prototype.restorePosition = function restorePosition () {
|
|
if (this.savedPos >= 0) {
|
|
var
|
|
selection = window.getSelection(),
|
|
range = createRange(this.el, { count: this.savedPos });
|
|
|
|
if (range) {
|
|
range.collapse(false);
|
|
selection.removeAllRanges();
|
|
selection.addRange(range);
|
|
}
|
|
}
|
|
};
|
|
|
|
Caret.prototype.hasParent = function hasParent (name, spanLevel) {
|
|
var el = spanLevel
|
|
? this.parent
|
|
: this.blockParent;
|
|
|
|
return el !== null
|
|
? el.nodeName.toLowerCase() === name.toLowerCase()
|
|
: false
|
|
};
|
|
|
|
Caret.prototype.hasParents = function hasParents (list, recursive, el) {
|
|
if ( el === void 0 ) el = this.parent;
|
|
|
|
if (el === null) {
|
|
return false
|
|
}
|
|
|
|
if (el !== null && list.includes(el.nodeName.toLowerCase()) === true) {
|
|
return true
|
|
}
|
|
|
|
return recursive === true
|
|
? this.hasParents(list, recursive, el.parentNode)
|
|
: false
|
|
};
|
|
|
|
Caret.prototype.is = function is (cmd, param) {
|
|
switch (cmd) {
|
|
case 'formatBlock':
|
|
if (param === 'DIV' && this.parent === this.el) {
|
|
return true
|
|
}
|
|
return this.hasParent(param, param === 'PRE')
|
|
case 'link':
|
|
return this.hasParent('A', true)
|
|
case 'fontSize':
|
|
return document.queryCommandValue(cmd) === param
|
|
case 'fontName':
|
|
var res = document.queryCommandValue(cmd);
|
|
return res === ("\"" + param + "\"") || res === param
|
|
case 'fullscreen':
|
|
return this.vm.inFullscreen
|
|
case 'viewsource':
|
|
return this.vm.isViewingSource
|
|
case void 0:
|
|
return false
|
|
default:
|
|
var state = document.queryCommandState(cmd);
|
|
return param !== void 0 ? state === param : state
|
|
}
|
|
};
|
|
|
|
Caret.prototype.getParentAttribute = function getParentAttribute (attrib) {
|
|
if (this.parent !== null) {
|
|
return this.parent.getAttribute(attrib)
|
|
}
|
|
|
|
return null
|
|
};
|
|
|
|
Caret.prototype.can = function can (name) {
|
|
if (name === 'outdent') {
|
|
return this.hasParents(['blockquote', 'li'], true)
|
|
}
|
|
|
|
if (name === 'indent') {
|
|
return this.hasParents(['li'], true)
|
|
}
|
|
|
|
if (name === 'link') {
|
|
return this.selection !== null || this.is('link')
|
|
}
|
|
};
|
|
|
|
Caret.prototype.apply = function apply (cmd, param, done) {
|
|
if ( done === void 0 ) done = noop;
|
|
|
|
if (cmd === 'formatBlock') {
|
|
if (['BLOCKQUOTE', 'H1', 'H2', 'H3', 'H4', 'H5', 'H6'].includes(param) && this.is(cmd, param)) {
|
|
cmd = 'outdent';
|
|
param = null;
|
|
}
|
|
|
|
if (param === 'PRE' && this.is(cmd, 'PRE')) {
|
|
param = 'P';
|
|
}
|
|
}
|
|
else if (cmd === 'print') {
|
|
done();
|
|
|
|
var win = window.open();
|
|
|
|
win.document.write(("\n <!doctype html>\n <html>\n <head>\n <title>Print - " + (document.title) + "</title>\n </head>\n <body>\n <div>" + (this.el.innerHTML) + "</div>\n </body>\n </html>\n "));
|
|
win.print();
|
|
win.close();
|
|
|
|
return
|
|
}
|
|
else if (cmd === 'link') {
|
|
var link = this.getParentAttribute('href');
|
|
|
|
if (link === null) {
|
|
var selection = this.selectWord(this.selection);
|
|
var url = selection ? selection.toString() : '';
|
|
|
|
if (!url.length) {
|
|
return
|
|
}
|
|
|
|
this.vm.editLinkUrl = urlRegex.test(url) ? url : 'https://';
|
|
document.execCommand('createLink', false, this.vm.editLinkUrl);
|
|
|
|
this.save(selection.getRangeAt(0));
|
|
}
|
|
else {
|
|
this.vm.editLinkUrl = link;
|
|
|
|
this.range.selectNodeContents(this.parent);
|
|
this.save();
|
|
}
|
|
|
|
return
|
|
}
|
|
else if (cmd === 'fullscreen') {
|
|
this.vm.toggleFullscreen();
|
|
done();
|
|
|
|
return
|
|
}
|
|
else if (cmd === 'viewsource') {
|
|
this.vm.isViewingSource = this.vm.isViewingSource === false;
|
|
this.vm.__setContent(this.vm.value);
|
|
done();
|
|
|
|
return
|
|
}
|
|
|
|
document.execCommand(cmd, false, param);
|
|
|
|
done();
|
|
};
|
|
|
|
Caret.prototype.selectWord = function selectWord (sel) {
|
|
if (sel === null || sel.isCollapsed !== true || /* IE 11 */ sel.modify === void 0) {
|
|
return sel
|
|
}
|
|
|
|
// Detect if selection is backwards
|
|
var range = document.createRange();
|
|
range.setStart(sel.anchorNode, sel.anchorOffset);
|
|
range.setEnd(sel.focusNode, sel.focusOffset);
|
|
var direction = range.collapsed ? ['backward', 'forward'] : ['forward', 'backward'];
|
|
range.detach();
|
|
|
|
// modify() works on the focus of the selection
|
|
var
|
|
endNode = sel.focusNode,
|
|
endOffset = sel.focusOffset;
|
|
sel.collapse(sel.anchorNode, sel.anchorOffset);
|
|
sel.modify('move', direction[0], 'character');
|
|
sel.modify('move', direction[1], 'word');
|
|
sel.extend(endNode, endOffset);
|
|
sel.modify('extend', direction[1], 'character');
|
|
sel.modify('extend', direction[0], 'word');
|
|
|
|
return sel
|
|
};
|
|
|
|
Object.defineProperties( Caret.prototype, prototypeAccessors );
|
|
|
|
var
|
|
toString = Object.prototype.toString,
|
|
hasOwn = Object.prototype.hasOwnProperty,
|
|
class2type = {};
|
|
|
|
'Boolean Number String Function Array Date RegExp Object'.split(' ').forEach(function (name) {
|
|
class2type['[object ' + name + ']'] = name.toLowerCase();
|
|
});
|
|
|
|
function type (obj) {
|
|
return obj === null ? String(obj) : class2type[toString.call(obj)] || 'object'
|
|
}
|
|
|
|
function isPlainObject (obj) {
|
|
if (!obj || type(obj) !== 'object') {
|
|
return false
|
|
}
|
|
|
|
if (obj.constructor &&
|
|
!hasOwn.call(obj, 'constructor') &&
|
|
!hasOwn.call(obj.constructor.prototype, 'isPrototypeOf')) {
|
|
return false
|
|
}
|
|
|
|
var key;
|
|
for (key in obj) {}
|
|
|
|
return key === undefined || hasOwn.call(obj, key)
|
|
}
|
|
|
|
function extend () {
|
|
var arguments$1 = arguments;
|
|
|
|
var
|
|
options, name, src, copy, copyIsArray, clone,
|
|
target = arguments[0] || {},
|
|
i = 1,
|
|
deep = false;
|
|
var length = arguments.length;
|
|
|
|
if (typeof target === 'boolean') {
|
|
deep = target;
|
|
target = arguments[1] || {};
|
|
i = 2;
|
|
}
|
|
|
|
if (Object(target) !== target && type(target) !== 'function') {
|
|
target = {};
|
|
}
|
|
|
|
if (length === i) {
|
|
target = this;
|
|
i--;
|
|
}
|
|
|
|
for (; i < length; i++) {
|
|
if ((options = arguments$1[i]) !== null) {
|
|
for (name in options) {
|
|
src = target[name];
|
|
copy = options[name];
|
|
|
|
if (target === copy) {
|
|
continue
|
|
}
|
|
|
|
if (deep && copy && (isPlainObject(copy) || (copyIsArray = type(copy) === 'array'))) {
|
|
if (copyIsArray) {
|
|
copyIsArray = false;
|
|
clone = src && type(src) === 'array' ? src : [];
|
|
}
|
|
else {
|
|
clone = src && isPlainObject(src) ? src : {};
|
|
}
|
|
|
|
target[name] = extend(deep, clone, copy);
|
|
}
|
|
else if (copy !== undefined) {
|
|
target[name] = copy;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return target
|
|
}
|
|
|
|
var QEditor = Vue.extend({
|
|
name: 'QEditor',
|
|
|
|
mixins: [ ListenersMixin, FullscreenMixin, DarkMixin ],
|
|
|
|
props: {
|
|
value: {
|
|
type: String,
|
|
required: true
|
|
},
|
|
readonly: Boolean,
|
|
disable: Boolean,
|
|
minHeight: {
|
|
type: String,
|
|
default: '10rem'
|
|
},
|
|
maxHeight: String,
|
|
height: String,
|
|
definitions: Object,
|
|
fonts: Object,
|
|
placeholder: String,
|
|
|
|
toolbar: {
|
|
type: Array,
|
|
validator: function (v) { return v.length === 0 || v.every(function (group) { return group.length; }); },
|
|
default: function default$1 () {
|
|
return [
|
|
['left', 'center', 'right', 'justify'],
|
|
['bold', 'italic', 'underline', 'strike'],
|
|
['undo', 'redo']
|
|
]
|
|
}
|
|
},
|
|
toolbarColor: String,
|
|
toolbarBg: String,
|
|
toolbarTextColor: String,
|
|
toolbarToggleColor: {
|
|
type: String,
|
|
default: 'primary'
|
|
},
|
|
toolbarOutline: Boolean,
|
|
toolbarPush: Boolean,
|
|
toolbarRounded: Boolean,
|
|
|
|
contentStyle: Object,
|
|
contentClass: [Object, Array, String],
|
|
|
|
square: Boolean,
|
|
flat: Boolean,
|
|
dense: Boolean
|
|
},
|
|
|
|
computed: {
|
|
editable: function editable () {
|
|
return !this.readonly && !this.disable
|
|
},
|
|
|
|
hasToolbar: function hasToolbar () {
|
|
return this.toolbar && this.toolbar.length > 0
|
|
},
|
|
|
|
toolbarBackgroundClass: function toolbarBackgroundClass () {
|
|
if (this.toolbarBg) {
|
|
return ("bg-" + (this.toolbarBg))
|
|
}
|
|
},
|
|
|
|
buttonProps: function buttonProps () {
|
|
var flat = this.toolbarOutline !== true &&
|
|
this.toolbarPush !== true;
|
|
|
|
return {
|
|
type: 'a',
|
|
flat: flat,
|
|
noWrap: true,
|
|
outline: this.toolbarOutline,
|
|
push: this.toolbarPush,
|
|
rounded: this.toolbarRounded,
|
|
dense: true,
|
|
color: this.toolbarColor,
|
|
disable: !this.editable,
|
|
size: 'sm'
|
|
}
|
|
},
|
|
|
|
buttonDef: function buttonDef () {
|
|
var
|
|
e = this.$q.lang.editor,
|
|
i = this.$q.iconSet.editor;
|
|
|
|
return {
|
|
bold: { cmd: 'bold', icon: i.bold, tip: e.bold, key: 66 },
|
|
italic: { cmd: 'italic', icon: i.italic, tip: e.italic, key: 73 },
|
|
strike: { cmd: 'strikeThrough', icon: i.strikethrough, tip: e.strikethrough, key: 83 },
|
|
underline: { cmd: 'underline', icon: i.underline, tip: e.underline, key: 85 },
|
|
unordered: { cmd: 'insertUnorderedList', icon: i.unorderedList, tip: e.unorderedList },
|
|
ordered: { cmd: 'insertOrderedList', icon: i.orderedList, tip: e.orderedList },
|
|
subscript: { cmd: 'subscript', icon: i.subscript, tip: e.subscript, htmlTip: 'x<subscript>2</subscript>' },
|
|
superscript: { cmd: 'superscript', icon: i.superscript, tip: e.superscript, htmlTip: 'x<superscript>2</superscript>' },
|
|
link: { cmd: 'link', disable: function (vm) { return vm.caret && !vm.caret.can('link'); }, icon: i.hyperlink, tip: e.hyperlink, key: 76 },
|
|
fullscreen: { cmd: 'fullscreen', icon: i.toggleFullscreen, tip: e.toggleFullscreen, key: 70 },
|
|
viewsource: { cmd: 'viewsource', icon: i.viewSource, tip: e.viewSource },
|
|
|
|
quote: { cmd: 'formatBlock', param: 'BLOCKQUOTE', icon: i.quote, tip: e.quote, key: 81 },
|
|
left: { cmd: 'justifyLeft', icon: i.left, tip: e.left },
|
|
center: { cmd: 'justifyCenter', icon: i.center, tip: e.center },
|
|
right: { cmd: 'justifyRight', icon: i.right, tip: e.right },
|
|
justify: { cmd: 'justifyFull', icon: i.justify, tip: e.justify },
|
|
|
|
print: { type: 'no-state', cmd: 'print', icon: i.print, tip: e.print, key: 80 },
|
|
outdent: { type: 'no-state', disable: function (vm) { return vm.caret && !vm.caret.can('outdent'); }, cmd: 'outdent', icon: i.outdent, tip: e.outdent },
|
|
indent: { type: 'no-state', disable: function (vm) { return vm.caret && !vm.caret.can('indent'); }, cmd: 'indent', icon: i.indent, tip: e.indent },
|
|
removeFormat: { type: 'no-state', cmd: 'removeFormat', icon: i.removeFormat, tip: e.removeFormat },
|
|
hr: { type: 'no-state', cmd: 'insertHorizontalRule', icon: i.hr, tip: e.hr },
|
|
undo: { type: 'no-state', cmd: 'undo', icon: i.undo, tip: e.undo, key: 90 },
|
|
redo: { type: 'no-state', cmd: 'redo', icon: i.redo, tip: e.redo, key: 89 },
|
|
|
|
h1: { cmd: 'formatBlock', param: 'H1', icon: i.heading1 || i.heading, tip: e.heading1, htmlTip: ("<h1 class=\"q-ma-none\">" + (e.heading1) + "</h1>") },
|
|
h2: { cmd: 'formatBlock', param: 'H2', icon: i.heading2 || i.heading, tip: e.heading2, htmlTip: ("<h2 class=\"q-ma-none\">" + (e.heading2) + "</h2>") },
|
|
h3: { cmd: 'formatBlock', param: 'H3', icon: i.heading3 || i.heading, tip: e.heading3, htmlTip: ("<h3 class=\"q-ma-none\">" + (e.heading3) + "</h3>") },
|
|
h4: { cmd: 'formatBlock', param: 'H4', icon: i.heading4 || i.heading, tip: e.heading4, htmlTip: ("<h4 class=\"q-ma-none\">" + (e.heading4) + "</h4>") },
|
|
h5: { cmd: 'formatBlock', param: 'H5', icon: i.heading5 || i.heading, tip: e.heading5, htmlTip: ("<h5 class=\"q-ma-none\">" + (e.heading5) + "</h5>") },
|
|
h6: { cmd: 'formatBlock', param: 'H6', icon: i.heading6 || i.heading, tip: e.heading6, htmlTip: ("<h6 class=\"q-ma-none\">" + (e.heading6) + "</h6>") },
|
|
p: { cmd: 'formatBlock', param: 'DIV', icon: i.heading, tip: e.paragraph },
|
|
code: { cmd: 'formatBlock', param: 'PRE', icon: i.code, htmlTip: ("<code>" + (e.code) + "</code>") },
|
|
|
|
'size-1': { cmd: 'fontSize', param: '1', icon: i.size1 || i.size, tip: e.size1, htmlTip: ("<font size=\"1\">" + (e.size1) + "</font>") },
|
|
'size-2': { cmd: 'fontSize', param: '2', icon: i.size2 || i.size, tip: e.size2, htmlTip: ("<font size=\"2\">" + (e.size2) + "</font>") },
|
|
'size-3': { cmd: 'fontSize', param: '3', icon: i.size3 || i.size, tip: e.size3, htmlTip: ("<font size=\"3\">" + (e.size3) + "</font>") },
|
|
'size-4': { cmd: 'fontSize', param: '4', icon: i.size4 || i.size, tip: e.size4, htmlTip: ("<font size=\"4\">" + (e.size4) + "</font>") },
|
|
'size-5': { cmd: 'fontSize', param: '5', icon: i.size5 || i.size, tip: e.size5, htmlTip: ("<font size=\"5\">" + (e.size5) + "</font>") },
|
|
'size-6': { cmd: 'fontSize', param: '6', icon: i.size6 || i.size, tip: e.size6, htmlTip: ("<font size=\"6\">" + (e.size6) + "</font>") },
|
|
'size-7': { cmd: 'fontSize', param: '7', icon: i.size7 || i.size, tip: e.size7, htmlTip: ("<font size=\"7\">" + (e.size7) + "</font>") }
|
|
}
|
|
},
|
|
|
|
buttons: function buttons () {
|
|
var this$1 = this;
|
|
|
|
var userDef = this.definitions || {};
|
|
var def = this.definitions || this.fonts
|
|
? extend(
|
|
true,
|
|
{},
|
|
this.buttonDef,
|
|
userDef,
|
|
getFonts(
|
|
this.defaultFont,
|
|
this.$q.lang.editor.defaultFont,
|
|
this.$q.iconSet.editor.font,
|
|
this.fonts
|
|
)
|
|
)
|
|
: this.buttonDef;
|
|
|
|
return this.toolbar.map(
|
|
function (group) { return group.map(function (token) {
|
|
if (token.options) {
|
|
return {
|
|
type: 'dropdown',
|
|
icon: token.icon,
|
|
label: token.label,
|
|
size: 'sm',
|
|
dense: true,
|
|
fixedLabel: token.fixedLabel,
|
|
fixedIcon: token.fixedIcon,
|
|
highlight: token.highlight,
|
|
list: token.list,
|
|
options: token.options.map(function (item) { return def[item]; })
|
|
}
|
|
}
|
|
|
|
var obj = def[token];
|
|
|
|
if (obj) {
|
|
return obj.type === 'no-state' || (userDef[token] && (
|
|
obj.cmd === void 0 || (this$1.buttonDef[obj.cmd] && this$1.buttonDef[obj.cmd].type === 'no-state')
|
|
))
|
|
? obj
|
|
: Object.assign({ type: 'toggle' }, obj)
|
|
}
|
|
else {
|
|
return {
|
|
type: 'slot',
|
|
slot: token
|
|
}
|
|
}
|
|
}); }
|
|
)
|
|
},
|
|
|
|
keys: function keys () {
|
|
var
|
|
k = {},
|
|
add = function (btn) {
|
|
if (btn.key) {
|
|
k[btn.key] = {
|
|
cmd: btn.cmd,
|
|
param: btn.param
|
|
};
|
|
}
|
|
};
|
|
|
|
this.buttons.forEach(function (group) {
|
|
group.forEach(function (token) {
|
|
if (token.options) {
|
|
token.options.forEach(add);
|
|
}
|
|
else {
|
|
add(token);
|
|
}
|
|
});
|
|
});
|
|
return k
|
|
},
|
|
|
|
innerStyle: function innerStyle () {
|
|
return this.inFullscreen
|
|
? this.contentStyle
|
|
: [
|
|
{
|
|
minHeight: this.minHeight,
|
|
height: this.height,
|
|
maxHeight: this.maxHeight
|
|
},
|
|
this.contentStyle
|
|
]
|
|
},
|
|
|
|
classes: function classes () {
|
|
return "q-editor q-editor--" + (this.isViewingSource === true ? 'source' : 'default') +
|
|
(this.disable === true ? ' disabled' : '') +
|
|
(this.inFullscreen === true ? ' fullscreen column' : '') +
|
|
(this.square === true ? ' q-editor--square no-border-radius' : '') +
|
|
(this.flat === true ? ' q-editor--flat' : '') +
|
|
(this.dense === true ? ' q-editor--dense' : '') +
|
|
(this.isDark === true ? ' q-editor--dark q-dark' : '')
|
|
},
|
|
|
|
innerClass: function innerClass () {
|
|
return [
|
|
this.contentClass,
|
|
{ col: this.inFullscreen, 'overflow-auto': this.inFullscreen || this.maxHeight }
|
|
]
|
|
},
|
|
|
|
attrs: function attrs () {
|
|
if (this.disable === true) {
|
|
return { 'aria-disabled': 'true' }
|
|
}
|
|
if (this.readonly === true) {
|
|
return { 'aria-readonly': 'true' }
|
|
}
|
|
}
|
|
},
|
|
|
|
data: function data () {
|
|
return {
|
|
lastEmit: this.value,
|
|
editLinkUrl: null,
|
|
isViewingSource: false
|
|
}
|
|
},
|
|
|
|
watch: {
|
|
value: function value (v) {
|
|
if (this.lastEmit !== v) {
|
|
this.__setContent(v, true);
|
|
}
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
__onInput: function __onInput () {
|
|
if (this.$refs.content !== void 0) {
|
|
var val = this.isViewingSource === true
|
|
? this.$refs.content.innerText
|
|
: this.$refs.content.innerHTML;
|
|
|
|
if (val !== this.value) {
|
|
this.lastEmit = val;
|
|
this.$emit('input', val);
|
|
}
|
|
}
|
|
},
|
|
|
|
__onKeydown: function __onKeydown (e) {
|
|
this.$emit('keydown', e);
|
|
|
|
if (e.ctrlKey !== true || shouldIgnoreKey(e) === true) {
|
|
this.refreshToolbar();
|
|
this.$q.platform.is.ie && this.$nextTick(this.__onInput);
|
|
return
|
|
}
|
|
|
|
var key = e.keyCode;
|
|
var target = this.keys[key];
|
|
if (target !== void 0) {
|
|
var cmd = target.cmd;
|
|
var param = target.param;
|
|
stopAndPrevent(e);
|
|
this.runCmd(cmd, param, false);
|
|
}
|
|
},
|
|
|
|
__onClick: function __onClick (e) {
|
|
this.refreshToolbar();
|
|
this.$emit('click', e);
|
|
},
|
|
|
|
__onBlur: function __onBlur (e) {
|
|
if (this.$refs.content !== void 0) {
|
|
var ref = this.$refs.content;
|
|
var scrollTop = ref.scrollTop;
|
|
var scrollHeight = ref.scrollHeight;
|
|
this.__offsetBottom = scrollHeight - scrollTop;
|
|
}
|
|
this.$q.platform.is.ie !== true && this.caret.save();
|
|
this.$emit('blur', e);
|
|
},
|
|
|
|
__onFocus: function __onFocus (e) {
|
|
var this$1 = this;
|
|
|
|
this.$nextTick(function () {
|
|
if (this$1.$refs.content !== void 0 && this$1.__offsetBottom !== void 0) {
|
|
this$1.$refs.content.scrollTop = this$1.$refs.content.scrollHeight - this$1.__offsetBottom;
|
|
}
|
|
});
|
|
this.$emit('focus', e);
|
|
},
|
|
|
|
__onMouseup: function __onMouseup (e) {
|
|
this.caret.save();
|
|
if (this.qListeners.mouseup !== void 0) {
|
|
this.$emit('mouseup', e);
|
|
}
|
|
},
|
|
|
|
__onKeyup: function __onKeyup (e) {
|
|
this.caret.save();
|
|
if (this.qListeners.keyup !== void 0) {
|
|
this.$emit('keyup', e);
|
|
}
|
|
},
|
|
|
|
__onTouchend: function __onTouchend (e) {
|
|
this.caret.save();
|
|
if (this.qListeners.touchend !== void 0) {
|
|
this.$emit('touchend', e);
|
|
}
|
|
},
|
|
|
|
runCmd: function runCmd (cmd, param, update) {
|
|
var this$1 = this;
|
|
if ( update === void 0 ) update = true;
|
|
|
|
this.focus();
|
|
this.caret.restore();
|
|
this.caret.apply(cmd, param, function () {
|
|
this$1.focus();
|
|
this$1.caret.save();
|
|
if (this$1.$q.platform.is.ie === true || this$1.$q.platform.is.edge === true) {
|
|
this$1.$nextTick(this$1.__onInput);
|
|
}
|
|
if (update) {
|
|
this$1.refreshToolbar();
|
|
}
|
|
});
|
|
},
|
|
|
|
refreshToolbar: function refreshToolbar () {
|
|
var this$1 = this;
|
|
|
|
setTimeout(function () {
|
|
this$1.editLinkUrl = null;
|
|
this$1.$forceUpdate();
|
|
}, 1);
|
|
},
|
|
|
|
focus: function focus () {
|
|
this.$refs.content !== void 0 && this.$refs.content.focus();
|
|
},
|
|
|
|
getContentEl: function getContentEl () {
|
|
return this.$refs.content
|
|
},
|
|
|
|
__setContent: function __setContent (v, restorePosition) {
|
|
if (this.$refs.content !== void 0) {
|
|
if (restorePosition === true) {
|
|
this.caret.savePosition();
|
|
}
|
|
|
|
var prop = "inner" + (this.isViewingSource === true ? 'Text' : 'HTML');
|
|
this.$refs.content[prop] = v;
|
|
|
|
if (restorePosition === true) {
|
|
this.caret.restorePosition();
|
|
this.refreshToolbar();
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
created: function created () {
|
|
if (isSSR === false) {
|
|
document.execCommand('defaultParagraphSeparator', false, 'div');
|
|
this.defaultFont = window.getComputedStyle(document.body).fontFamily;
|
|
}
|
|
},
|
|
|
|
mounted: function mounted () {
|
|
this.caret = new Caret(this.$refs.content, this);
|
|
this.__setContent(this.value);
|
|
this.refreshToolbar();
|
|
},
|
|
|
|
render: function render (h) {
|
|
var toolbars;
|
|
|
|
if (this.hasToolbar) {
|
|
var bars = [
|
|
h('div', {
|
|
key: 'qedt_top',
|
|
staticClass: 'q-editor__toolbar row no-wrap scroll-x',
|
|
class: this.toolbarBackgroundClass
|
|
}, getToolbar(h, this))
|
|
];
|
|
|
|
this.editLinkUrl !== null && bars.push(
|
|
h('div', {
|
|
key: 'qedt_btm',
|
|
staticClass: 'q-editor__toolbar row no-wrap items-center scroll-x',
|
|
class: this.toolbarBackgroundClass
|
|
}, getLinkEditor(h, this, this.$q.platform.is.ie))
|
|
);
|
|
|
|
toolbars = h('div', {
|
|
key: 'toolbar_ctainer',
|
|
staticClass: 'q-editor__toolbars-container'
|
|
}, bars);
|
|
}
|
|
|
|
var on = Object.assign({}, this.qListeners,
|
|
{input: this.__onInput,
|
|
keydown: this.__onKeydown,
|
|
click: this.__onClick,
|
|
blur: this.__onBlur,
|
|
focus: this.__onFocus,
|
|
|
|
// save caret
|
|
mouseup: this.__onMouseup,
|
|
keyup: this.__onKeyup,
|
|
touchend: this.__onTouchend});
|
|
|
|
return h('div', {
|
|
style: {
|
|
height: this.inFullscreen === true ? '100vh' : null
|
|
},
|
|
class: this.classes,
|
|
attrs: this.attrs
|
|
}, [
|
|
toolbars,
|
|
|
|
h(
|
|
'div',
|
|
{
|
|
ref: 'content',
|
|
staticClass: "q-editor__content",
|
|
style: this.innerStyle,
|
|
class: this.innerClass,
|
|
attrs: {
|
|
contenteditable: this.editable,
|
|
placeholder: this.placeholder
|
|
},
|
|
domProps: isSSR
|
|
? { innerHTML: this.value }
|
|
: undefined,
|
|
on: on
|
|
}
|
|
)
|
|
])
|
|
}
|
|
});
|
|
|
|
var QItemLabel = Vue.extend({
|
|
name: 'QItemLabel',
|
|
|
|
mixins: [ ListenersMixin ],
|
|
|
|
props: {
|
|
overline: Boolean,
|
|
caption: Boolean,
|
|
header: Boolean,
|
|
lines: [ Number, String ]
|
|
},
|
|
|
|
computed: {
|
|
classes: function classes () {
|
|
return {
|
|
'q-item__label--overline text-overline': this.overline,
|
|
'q-item__label--caption text-caption': this.caption,
|
|
'q-item__label--header': this.header,
|
|
'ellipsis': parseInt(this.lines, 10) === 1
|
|
}
|
|
},
|
|
|
|
style: function style () {
|
|
if (this.lines !== void 0 && parseInt(this.lines, 10) > 1) {
|
|
return {
|
|
overflow: 'hidden',
|
|
display: '-webkit-box',
|
|
'-webkit-box-orient': 'vertical',
|
|
'-webkit-line-clamp': this.lines
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
render: function render (h) {
|
|
return h('div', {
|
|
staticClass: 'q-item__label',
|
|
style: this.style,
|
|
class: this.classes,
|
|
on: Object.assign({}, this.qListeners)
|
|
}, slot(this, 'default'))
|
|
}
|
|
});
|
|
|
|
var QSlideTransition = Vue.extend({
|
|
name: 'QSlideTransition',
|
|
|
|
props: {
|
|
appear: Boolean,
|
|
duration: {
|
|
type: Number,
|
|
default: 300
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
__begin: function __begin (el, height, done) {
|
|
el.style.overflowY = 'hidden';
|
|
if (height !== void 0) {
|
|
el.style.height = height + "px";
|
|
}
|
|
el.style.transition = "height " + (this.duration) + "ms cubic-bezier(.25, .8, .50, 1)";
|
|
|
|
this.animating = true;
|
|
this.done = done;
|
|
},
|
|
|
|
__end: function __end (el, event) {
|
|
el.style.overflowY = null;
|
|
el.style.height = null;
|
|
el.style.transition = null;
|
|
this.__cleanup();
|
|
event !== this.lastEvent && this.$emit(event);
|
|
},
|
|
|
|
__cleanup: function __cleanup () {
|
|
this.done && this.done();
|
|
this.done = null;
|
|
this.animating = false;
|
|
|
|
clearTimeout(this.timer);
|
|
clearTimeout(this.timerFallback);
|
|
this.el !== void 0 && this.el.removeEventListener('transitionend', this.animListener);
|
|
this.animListener = null;
|
|
}
|
|
},
|
|
|
|
beforeDestroy: function beforeDestroy () {
|
|
this.animating && this.__cleanup();
|
|
},
|
|
|
|
render: function render (h) {
|
|
var this$1 = this;
|
|
|
|
return h('transition', {
|
|
props: {
|
|
css: false,
|
|
appear: this.appear
|
|
},
|
|
on: cache(this, 'tr', {
|
|
enter: function (el, done) {
|
|
var pos = 0;
|
|
this$1.el = el;
|
|
|
|
if (this$1.animating === true) {
|
|
this$1.__cleanup();
|
|
pos = el.offsetHeight === el.scrollHeight ? 0 : void 0;
|
|
}
|
|
else {
|
|
this$1.lastEvent = 'hide';
|
|
}
|
|
|
|
this$1.__begin(el, pos, done);
|
|
|
|
this$1.timer = setTimeout(function () {
|
|
el.style.height = (el.scrollHeight) + "px";
|
|
this$1.animListener = function (ev) {
|
|
if (Object(ev) !== ev || ev.target === el) {
|
|
this$1.__end(el, 'show');
|
|
}
|
|
};
|
|
el.addEventListener('transitionend', this$1.animListener);
|
|
this$1.timerFallback = setTimeout(this$1.animListener, this$1.duration * 1.1);
|
|
}, 100);
|
|
},
|
|
|
|
leave: function (el, done) {
|
|
var pos;
|
|
this$1.el = el;
|
|
|
|
if (this$1.animating === true) {
|
|
this$1.__cleanup();
|
|
}
|
|
else {
|
|
this$1.lastEvent = 'show';
|
|
pos = el.scrollHeight;
|
|
}
|
|
|
|
this$1.__begin(el, pos, done);
|
|
|
|
this$1.timer = setTimeout(function () {
|
|
el.style.height = 0;
|
|
this$1.animListener = function (ev) {
|
|
if (Object(ev) !== ev || ev.target === el) {
|
|
this$1.__end(el, 'hide');
|
|
}
|
|
};
|
|
el.addEventListener('transitionend', this$1.animListener);
|
|
this$1.timerFallback = setTimeout(this$1.animListener, this$1.duration * 1.1);
|
|
}, 100);
|
|
}
|
|
})
|
|
}, slot(this, 'default'))
|
|
}
|
|
});
|
|
|
|
var insetMap = {
|
|
true: 'inset',
|
|
item: 'item-inset',
|
|
'item-thumbnail': 'item-thumbnail-inset'
|
|
};
|
|
|
|
var margins = {
|
|
xs: 2,
|
|
sm: 4,
|
|
md: 8,
|
|
lg: 16,
|
|
xl: 24
|
|
};
|
|
|
|
var QSeparator = Vue.extend({
|
|
name: 'QSeparator',
|
|
|
|
mixins: [ DarkMixin, ListenersMixin ],
|
|
|
|
props: {
|
|
spaced: [ Boolean, String ],
|
|
inset: [ Boolean, String ],
|
|
vertical: Boolean,
|
|
color: String,
|
|
size: String
|
|
},
|
|
|
|
computed: {
|
|
orientation: function orientation () {
|
|
return this.vertical === true
|
|
? 'vertical'
|
|
: 'horizontal'
|
|
},
|
|
|
|
classPrefix: function classPrefix () {
|
|
return (" q-separator--" + (this.orientation))
|
|
},
|
|
|
|
insetClass: function insetClass () {
|
|
return this.inset !== false
|
|
? ((this.classPrefix) + "-" + (insetMap[this.inset]))
|
|
: ''
|
|
},
|
|
|
|
classes: function classes () {
|
|
return "q-separator" + (this.classPrefix) + (this.insetClass) +
|
|
(this.color !== void 0 ? (" bg-" + (this.color)) : '') +
|
|
(this.isDark === true ? ' q-separator--dark' : '')
|
|
},
|
|
|
|
style: function style () {
|
|
var style = {};
|
|
|
|
if (this.size !== void 0) {
|
|
style[ this.vertical === true ? 'width' : 'height' ] = this.size;
|
|
}
|
|
|
|
if (this.spaced !== false) {
|
|
var size = this.spaced === true
|
|
? ((margins.md) + "px")
|
|
: this.spaced in margins ? ((margins[this.spaced]) + "px") : this.spaced;
|
|
|
|
var props = this.vertical === true
|
|
? [ 'Left', 'Right' ]
|
|
: [ 'Top', 'Bottom' ];
|
|
|
|
style[("margin" + (props[0]))] = style[("margin" + (props[1]))] = size;
|
|
}
|
|
|
|
return style
|
|
},
|
|
|
|
attrs: function attrs () {
|
|
return {
|
|
role: 'separator',
|
|
'aria-orientation': this.orientation
|
|
}
|
|
}
|
|
},
|
|
|
|
render: function render (h) {
|
|
return h('hr', {
|
|
staticClass: 'q-separator',
|
|
class: this.classes,
|
|
style: this.style,
|
|
attrs: this.attrs,
|
|
on: Object.assign({}, this.qListeners)
|
|
})
|
|
}
|
|
});
|
|
|
|
var eventName = 'q:expansion-item:close';
|
|
|
|
var QExpansionItem = Vue.extend({
|
|
name: 'QExpansionItem',
|
|
|
|
mixins: [ DarkMixin, RouterLinkMixin, ModelToggleMixin ],
|
|
|
|
props: {
|
|
icon: String,
|
|
|
|
label: String,
|
|
labelLines: [ Number, String ],
|
|
|
|
caption: String,
|
|
captionLines: [ Number, String ],
|
|
|
|
dense: Boolean,
|
|
|
|
expandIcon: String,
|
|
expandedIcon: String,
|
|
expandIconClass: [ Array, String, Object ],
|
|
duration: Number,
|
|
|
|
headerInsetLevel: Number,
|
|
contentInsetLevel: Number,
|
|
|
|
expandSeparator: Boolean,
|
|
defaultOpened: Boolean,
|
|
expandIconToggle: Boolean,
|
|
switchToggleSide: Boolean,
|
|
denseToggle: Boolean,
|
|
group: String,
|
|
popup: Boolean,
|
|
|
|
headerStyle: [Array, String, Object],
|
|
headerClass: [Array, String, Object]
|
|
},
|
|
|
|
data: function data () {
|
|
return {
|
|
showing: this.value !== void 0
|
|
? this.value
|
|
: this.defaultOpened
|
|
}
|
|
},
|
|
|
|
watch: {
|
|
showing: function showing (val) {
|
|
val === true && this.group !== void 0 && this.$root.$emit(eventName, this);
|
|
},
|
|
|
|
group: function group (newVal, oldVal) {
|
|
if (newVal !== void 0 && oldVal === void 0) {
|
|
this.$root.$on(eventName, this.__eventHandler);
|
|
}
|
|
else if (newVal === void 0 && oldVal !== void 0) {
|
|
this.$root.$off(eventName, this.__eventHandler);
|
|
}
|
|
}
|
|
},
|
|
|
|
computed: {
|
|
classes: function classes () {
|
|
return "q-expansion-item--" + (this.showing === true ? 'expanded' : 'collapsed') +
|
|
" q-expansion-item--" + (this.popup === true ? 'popup' : 'standard')
|
|
},
|
|
|
|
contentStyle: function contentStyle () {
|
|
var obj;
|
|
|
|
if (this.contentInsetLevel !== void 0) {
|
|
var dir = this.$q.lang.rtl === true ? 'Right' : 'Left';
|
|
return ( obj = {}, obj['padding' + dir] = (this.contentInsetLevel * 56) + 'px', obj )
|
|
}
|
|
},
|
|
|
|
isClickable: function isClickable () {
|
|
return this.hasRouterLink === true || this.expandIconToggle !== true
|
|
},
|
|
|
|
expansionIcon: function expansionIcon () {
|
|
return this.expandedIcon !== void 0 && this.showing === true
|
|
? this.expandedIcon
|
|
: this.expandIcon || this.$q.iconSet.expansionItem[this.denseToggle === true ? 'denseIcon' : 'icon']
|
|
},
|
|
|
|
activeToggleIcon: function activeToggleIcon () {
|
|
return this.disable !== true && (this.hasRouterLink === true || this.expandIconToggle === true)
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
__onHeaderClick: function __onHeaderClick (e) {
|
|
this.hasRouterLink !== true && this.toggle(e);
|
|
this.$emit('click', e);
|
|
},
|
|
|
|
__toggleIconKeyboard: function __toggleIconKeyboard (e) {
|
|
e.keyCode === 13 && this.__toggleIcon(e, true);
|
|
},
|
|
|
|
__toggleIcon: function __toggleIcon (e, keyboard) {
|
|
keyboard !== true && this.$refs.blurTarget !== void 0 && this.$refs.blurTarget.focus();
|
|
this.toggle(e);
|
|
stopAndPrevent(e);
|
|
},
|
|
|
|
__eventHandler: function __eventHandler (comp) {
|
|
this !== comp && this.group === comp.group && this.hide();
|
|
},
|
|
|
|
__getToggleIcon: function __getToggleIcon (h) {
|
|
var data = {
|
|
staticClass: ("q-focusable relative-position cursor-pointer" + (this.denseToggle === true && this.switchToggleSide === true ? ' items-end' : '')),
|
|
class: this.expandIconClass,
|
|
props: {
|
|
side: this.switchToggleSide !== true,
|
|
avatar: this.switchToggleSide
|
|
}
|
|
};
|
|
|
|
var child = [
|
|
h(QIcon, {
|
|
staticClass: 'q-expansion-item__toggle-icon',
|
|
class: this.expandedIcon === void 0 && this.showing === true
|
|
? 'q-expansion-item__toggle-icon--rotated'
|
|
: void 0,
|
|
props: { name: this.expansionIcon }
|
|
})
|
|
];
|
|
|
|
if (this.activeToggleIcon === true) {
|
|
Object.assign(data, {
|
|
attrs: { tabindex: 0 },
|
|
on: cache(this, 'inpExt', {
|
|
click: this.__toggleIcon,
|
|
keyup: this.__toggleIconKeyboard
|
|
})
|
|
});
|
|
|
|
child.unshift(
|
|
h('div', {
|
|
ref: 'blurTarget',
|
|
staticClass: 'q-expansion-item__toggle-focus q-icon q-focus-helper q-focus-helper--rounded',
|
|
attrs: { tabindex: -1 }
|
|
})
|
|
);
|
|
}
|
|
|
|
return h(QItemSection, data, child)
|
|
},
|
|
|
|
__getHeader: function __getHeader (h) {
|
|
var child;
|
|
|
|
if (this.$scopedSlots.header !== void 0) {
|
|
child = this.$scopedSlots.header().slice();
|
|
}
|
|
else {
|
|
child = [
|
|
h(QItemSection, [
|
|
h(QItemLabel, {
|
|
props: { lines: this.labelLines }
|
|
}, [ this.label || '' ]),
|
|
|
|
this.caption
|
|
? h(QItemLabel, {
|
|
props: { lines: this.captionLines, caption: true }
|
|
}, [ this.caption ])
|
|
: null
|
|
])
|
|
];
|
|
|
|
this.icon && child[this.switchToggleSide === true ? 'push' : 'unshift'](
|
|
h(QItemSection, {
|
|
props: {
|
|
side: this.switchToggleSide === true,
|
|
avatar: this.switchToggleSide !== true
|
|
}
|
|
}, [
|
|
h(QIcon, {
|
|
props: { name: this.icon }
|
|
})
|
|
])
|
|
);
|
|
}
|
|
|
|
this.disable !== true && child[this.switchToggleSide === true ? 'unshift' : 'push'](
|
|
this.__getToggleIcon(h)
|
|
);
|
|
|
|
var data = {
|
|
ref: 'item',
|
|
style: this.headerStyle,
|
|
class: this.headerClass,
|
|
props: {
|
|
dark: this.isDark,
|
|
disable: this.disable,
|
|
dense: this.dense,
|
|
insetLevel: this.headerInsetLevel
|
|
}
|
|
};
|
|
|
|
if (this.isClickable === true) {
|
|
var evtProp = this.hasRouterLink === true ? 'nativeOn' : 'on';
|
|
|
|
data.props.clickable = true;
|
|
data[evtProp] = Object.assign({}, this.qListeners,
|
|
{click: this.__onHeaderClick});
|
|
|
|
this.hasRouterLink === true && Object.assign(
|
|
data.props,
|
|
this.routerLinkProps
|
|
);
|
|
}
|
|
|
|
return h(QItem, data, child)
|
|
},
|
|
|
|
__getContent: function __getContent (h) {
|
|
var this$1 = this;
|
|
|
|
var node = [
|
|
this.__getHeader(h),
|
|
|
|
h(QSlideTransition, {
|
|
props: { duration: this.duration },
|
|
on: cache(this, 'slide', {
|
|
show: function () { this$1.$emit('after-show'); },
|
|
hide: function () { this$1.$emit('after-hide'); }
|
|
})
|
|
}, [
|
|
h('div', {
|
|
staticClass: 'q-expansion-item__content relative-position',
|
|
style: this.contentStyle,
|
|
directives: [{ name: 'show', value: this.showing }]
|
|
}, slot(this, 'default'))
|
|
])
|
|
];
|
|
|
|
if (this.expandSeparator) {
|
|
node.push(
|
|
h(QSeparator, {
|
|
staticClass: 'q-expansion-item__border q-expansion-item__border--top absolute-top',
|
|
props: { dark: this.isDark }
|
|
}),
|
|
h(QSeparator, {
|
|
staticClass: 'q-expansion-item__border q-expansion-item__border--bottom absolute-bottom',
|
|
props: { dark: this.isDark }
|
|
})
|
|
);
|
|
}
|
|
|
|
return node
|
|
}
|
|
},
|
|
|
|
render: function render (h) {
|
|
return h('div', {
|
|
staticClass: 'q-expansion-item q-item-type',
|
|
class: this.classes
|
|
}, [
|
|
h(
|
|
'div',
|
|
{ staticClass: 'q-expansion-item__container relative-position' },
|
|
this.__getContent(h)
|
|
)
|
|
])
|
|
},
|
|
|
|
created: function created () {
|
|
this.group !== void 0 && this.$root.$on(eventName, this.__eventHandler);
|
|
},
|
|
|
|
beforeDestroy: function beforeDestroy () {
|
|
this.group !== void 0 && this.$root.$off(eventName, this.__eventHandler);
|
|
}
|
|
});
|
|
|
|
var labelPositions = ['top', 'right', 'bottom', 'left'];
|
|
|
|
var FabMixin = {
|
|
mixins: [ ListenersMixin ],
|
|
|
|
props: {
|
|
type: {
|
|
type: String,
|
|
default: 'a'
|
|
},
|
|
|
|
outline: Boolean,
|
|
push: Boolean,
|
|
flat: Boolean,
|
|
unelevated: Boolean,
|
|
|
|
color: String,
|
|
textColor: String,
|
|
glossy: Boolean,
|
|
|
|
square: Boolean,
|
|
padding: String,
|
|
|
|
label: {
|
|
type: [ String, Number ],
|
|
default: ''
|
|
},
|
|
labelPosition: {
|
|
type: String,
|
|
default: 'right',
|
|
validator: function (v) { return labelPositions.includes(v); }
|
|
},
|
|
externalLabel: Boolean,
|
|
hideLabel: {
|
|
type: Boolean
|
|
},
|
|
labelClass: [ Array, String, Object ],
|
|
labelStyle: [ Array, String, Object ],
|
|
|
|
disable: Boolean,
|
|
|
|
tabindex: [ Number, String ]
|
|
},
|
|
|
|
computed: {
|
|
formClass: function formClass () {
|
|
return ("q-fab--form-" + (this.square === true ? 'square' : 'rounded'))
|
|
},
|
|
|
|
stacked: function stacked () {
|
|
return this.externalLabel === false && ['top', 'bottom'].includes(this.labelPosition)
|
|
},
|
|
|
|
labelProps: function labelProps () {
|
|
if (this.externalLabel === true) {
|
|
var hideLabel = this.hideLabel === null
|
|
? this.showing === false
|
|
: this.hideLabel;
|
|
|
|
return {
|
|
action: 'push',
|
|
data: {
|
|
staticClass: "q-fab__label q-tooltip--style q-fab__label--external" +
|
|
" q-fab__label--external-" + (this.labelPosition) +
|
|
(hideLabel === true ? ' q-fab__label--external-hidden' : ''),
|
|
style: this.labelStyle,
|
|
class: this.labelClass
|
|
}
|
|
}
|
|
}
|
|
|
|
return {
|
|
action: [ 'left', 'top' ].includes(this.labelPosition)
|
|
? 'unshift'
|
|
: 'push',
|
|
data: {
|
|
staticClass: "q-fab__label q-fab__label--internal q-fab__label--internal-" + (this.labelPosition) +
|
|
(this.hideLabel === true ? ' q-fab__label--internal-hidden' : ''),
|
|
style: this.labelStyle,
|
|
class: this.labelClass
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
var directions$1 = ['up', 'right', 'down', 'left'];
|
|
var alignValues$1 = [ 'left', 'center', 'right' ];
|
|
|
|
var QFab = Vue.extend({
|
|
name: 'QFab',
|
|
|
|
inheritAttrs: false,
|
|
|
|
mixins: [ FabMixin, AttrsMixin, ModelToggleMixin ],
|
|
|
|
provide: function provide () {
|
|
return {
|
|
__qFab: this
|
|
}
|
|
},
|
|
|
|
props: {
|
|
icon: String,
|
|
activeIcon: String,
|
|
|
|
hideIcon: Boolean,
|
|
hideLabel: {
|
|
default: null
|
|
},
|
|
|
|
direction: {
|
|
type: String,
|
|
default: 'right',
|
|
validator: function (v) { return directions$1.includes(v); }
|
|
},
|
|
|
|
persistent: Boolean,
|
|
|
|
verticalActionsAlign: {
|
|
type: String,
|
|
default: 'center',
|
|
validator: function (v) { return alignValues$1.includes(v); }
|
|
}
|
|
},
|
|
|
|
data: function data () {
|
|
return {
|
|
showing: this.value === true
|
|
}
|
|
},
|
|
|
|
computed: {
|
|
hideOnRouteChange: function hideOnRouteChange () {
|
|
return this.persistent !== true
|
|
},
|
|
|
|
classes: function classes () {
|
|
return "q-fab--align-" + (this.verticalActionsAlign) + " " + (this.formClass) +
|
|
(this.showing === true ? ' q-fab--opened' : '')
|
|
},
|
|
|
|
attrs: function attrs () {
|
|
return Object.assign({}, {'aria-expanded': this.showing === true ? 'true' : 'false',
|
|
'aria-haspopup': 'true'},
|
|
this.qAttrs)
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
__onChildClick: function __onChildClick (evt) {
|
|
this.hide(evt);
|
|
|
|
if (this.$refs.trigger && this.$refs.trigger.$el) {
|
|
this.$refs.trigger.$el.focus();
|
|
}
|
|
}
|
|
},
|
|
|
|
render: function render (h) {
|
|
var child = [];
|
|
|
|
this.hideIcon !== true && child.push(
|
|
h('div', { staticClass: 'q-fab__icon-holder' }, [
|
|
h(QIcon, {
|
|
staticClass: 'q-fab__icon absolute-full',
|
|
props: { name: this.icon || this.$q.iconSet.fab.icon }
|
|
}),
|
|
h(QIcon, {
|
|
staticClass: 'q-fab__active-icon absolute-full',
|
|
props: { name: this.activeIcon || this.$q.iconSet.fab.activeIcon }
|
|
})
|
|
])
|
|
);
|
|
|
|
this.label !== '' && child[this.labelProps.action](
|
|
h('div', this.labelProps.data, [ this.label ])
|
|
);
|
|
|
|
return h('div', {
|
|
staticClass: 'q-fab z-fab row inline justify-center',
|
|
class: this.classes,
|
|
on: Object.assign({}, this.qListeners)
|
|
}, [
|
|
h(QBtn, {
|
|
ref: 'trigger',
|
|
class: this.formClass,
|
|
props: Object.assign({}, this.$props,
|
|
{noWrap: true,
|
|
stack: this.stacked,
|
|
align: void 0,
|
|
icon: void 0,
|
|
label: void 0,
|
|
noCaps: true,
|
|
fab: true}),
|
|
attrs: this.attrs,
|
|
on: cache(this, 'tog', {
|
|
click: this.toggle
|
|
})
|
|
}, mergeSlot(child, this, 'tooltip')),
|
|
|
|
h('div', {
|
|
staticClass: 'q-fab__actions flex no-wrap inline',
|
|
class: ("q-fab__actions--" + (this.direction))
|
|
}, slot(this, 'default'))
|
|
])
|
|
}
|
|
});
|
|
|
|
var anchorMap = {
|
|
start: 'self-end',
|
|
center: 'self-center',
|
|
end: 'self-start'
|
|
};
|
|
|
|
var anchorValues = Object.keys(anchorMap);
|
|
|
|
var QFabAction = Vue.extend({
|
|
name: 'QFabAction',
|
|
|
|
mixins: [ FabMixin ],
|
|
|
|
props: {
|
|
icon: {
|
|
type: String,
|
|
default: ''
|
|
},
|
|
|
|
anchor: {
|
|
type: String,
|
|
validator: function (v) { return anchorValues.includes(v); }
|
|
},
|
|
|
|
to: [ String, Object ],
|
|
replace: Boolean
|
|
},
|
|
|
|
inject: {
|
|
__qFab: {
|
|
default: function default$1 () {
|
|
console.error('QFabAction needs to be child of QFab');
|
|
}
|
|
}
|
|
},
|
|
|
|
computed: {
|
|
classes: function classes () {
|
|
var align = anchorMap[this.anchor];
|
|
return this.formClass + (align !== void 0 ? (" " + align) : '')
|
|
},
|
|
|
|
onEvents: function onEvents () {
|
|
return Object.assign({}, this.qListeners,
|
|
{click: this.click})
|
|
},
|
|
|
|
isDisabled: function isDisabled () {
|
|
return this.__qFab.showing !== true || this.disable === true
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
click: function click (e) {
|
|
this.__qFab.__onChildClick(e);
|
|
this.$emit('click', e);
|
|
}
|
|
},
|
|
|
|
render: function render (h) {
|
|
var child = [];
|
|
|
|
this.icon !== '' && child.push(
|
|
h(QIcon, {
|
|
props: { name: this.icon }
|
|
})
|
|
);
|
|
|
|
this.label !== '' && child[this.labelProps.action](
|
|
h('div', this.labelProps.data, [ this.label ])
|
|
);
|
|
|
|
return h(QBtn, {
|
|
class: this.classes,
|
|
props: Object.assign({}, this.$props,
|
|
{noWrap: true,
|
|
stack: this.stacked,
|
|
icon: void 0,
|
|
label: void 0,
|
|
noCaps: true,
|
|
fabMini: true,
|
|
disable: this.isDisabled}),
|
|
on: this.onEvents
|
|
}, mergeSlot(child, this, 'default'))
|
|
}
|
|
});
|
|
|
|
var QFile = Vue.extend({
|
|
name: 'QFile',
|
|
|
|
mixins: [ QField, FileMixin, FormFieldMixin, FileValueMixin ],
|
|
|
|
props: {
|
|
/* SSR does not know about File & FileList */
|
|
value: isSSR === true
|
|
? {}
|
|
: [ File, FileList, Array ],
|
|
|
|
append: Boolean,
|
|
useChips: Boolean,
|
|
displayValue: [ String, Number ],
|
|
|
|
tabindex: {
|
|
type: [ String, Number ],
|
|
default: 0
|
|
},
|
|
|
|
counterLabel: Function,
|
|
|
|
inputClass: [ Array, String, Object ],
|
|
inputStyle: [ Array, String, Object ]
|
|
},
|
|
|
|
data: function data () {
|
|
return {
|
|
dnd: false
|
|
}
|
|
},
|
|
|
|
computed: {
|
|
innerValue: function innerValue () {
|
|
return Object(this.value) === this.value
|
|
? ('length' in this.value ? Array.from(this.value) : [ this.value ])
|
|
: []
|
|
},
|
|
|
|
selectedString: function selectedString () {
|
|
return this.innerValue
|
|
.map(function (file) { return file.name; })
|
|
.join(', ')
|
|
},
|
|
|
|
totalSize: function totalSize () {
|
|
return humanStorageSize(
|
|
this.innerValue.reduce(function (acc, file) { return acc + file.size; }, 0)
|
|
)
|
|
},
|
|
|
|
counterProps: function counterProps () {
|
|
return {
|
|
totalSize: this.totalSize,
|
|
filesNumber: this.innerValue.length,
|
|
maxFiles: this.maxFiles
|
|
}
|
|
},
|
|
|
|
computedCounter: function computedCounter () {
|
|
if (this.counterLabel !== void 0) {
|
|
return this.counterLabel(this.counterProps)
|
|
}
|
|
|
|
var max = this.maxFiles;
|
|
return ("" + (this.innerValue.length) + (max !== void 0 ? ' / ' + max : '') + " (" + (this.totalSize) + ")")
|
|
},
|
|
|
|
inputAttrs: function inputAttrs () {
|
|
return Object.assign({}, {tabindex: -1,
|
|
type: 'file',
|
|
title: '', // try to remove default tooltip,
|
|
accept: this.accept,
|
|
capture: this.capture,
|
|
name: this.nameProp},
|
|
this.qAttrs,
|
|
{id: this.targetUid,
|
|
disabled: this.editable !== true})
|
|
},
|
|
|
|
isAppending: function isAppending () {
|
|
return this.multiple === true && this.append === true
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
removeAtIndex: function removeAtIndex (index) {
|
|
var files = this.innerValue.slice();
|
|
files.splice(index, 1);
|
|
this.__emitValue(files);
|
|
},
|
|
|
|
removeFile: function removeFile (file) {
|
|
var index = this.innerValue.findIndex(file);
|
|
if (index > -1) {
|
|
this.removeAtIndex(index);
|
|
}
|
|
},
|
|
|
|
__emitValue: function __emitValue (files) {
|
|
this.$emit('input', this.multiple === true ? files : files[0]);
|
|
},
|
|
|
|
__onKeyup: function __onKeyup (e) {
|
|
// only on ENTER
|
|
e.keyCode === 13 && this.pickFiles(e);
|
|
},
|
|
|
|
__getFileInput: function __getFileInput () {
|
|
return this.$refs.input
|
|
},
|
|
|
|
__addFiles: function __addFiles (e, fileList) {
|
|
var files = this.__processFiles(e, fileList, this.innerValue, this.isAppending);
|
|
|
|
files !== void 0 && this.__emitValue(
|
|
this.isAppending === true
|
|
? this.innerValue.concat(files)
|
|
: files
|
|
);
|
|
},
|
|
|
|
__getControl: function __getControl (h) {
|
|
var data = {
|
|
ref: 'target',
|
|
staticClass: 'q-field__native row items-center cursor-pointer',
|
|
attrs: {
|
|
tabindex: this.tabindex
|
|
}
|
|
};
|
|
|
|
if (this.editable === true) {
|
|
data.on = cache(this, 'native', {
|
|
dragover: this.__onDragOver,
|
|
keyup: this.__onKeyup
|
|
});
|
|
}
|
|
|
|
return h('div', data, [ this.__getInput(h) ].concat(this.__getSelection(h)))
|
|
},
|
|
|
|
__getControlChild: function __getControlChild (h) {
|
|
return this.__getDnd(h, 'file')
|
|
},
|
|
|
|
__getSelection: function __getSelection (h) {
|
|
var this$1 = this;
|
|
|
|
if (this.$scopedSlots.file !== void 0) {
|
|
return this.innerValue.map(function (file, index) { return this$1.$scopedSlots.file({ index: index, file: file, ref: this$1 }); })
|
|
}
|
|
|
|
if (this.$scopedSlots.selected !== void 0) {
|
|
return this.$scopedSlots.selected({ files: this.innerValue, ref: this })
|
|
}
|
|
|
|
if (this.useChips === true) {
|
|
return this.innerValue.map(function (file, i) { return h(QChip, {
|
|
key: 'file-' + i,
|
|
props: {
|
|
removable: this$1.editable,
|
|
dense: true,
|
|
textColor: this$1.color,
|
|
tabindex: this$1.tabindex
|
|
},
|
|
on: cache(this$1, 'rem#' + i, {
|
|
remove: function () { this$1.removeAtIndex(i); }
|
|
})
|
|
}, [
|
|
h('span', {
|
|
staticClass: 'ellipsis',
|
|
domProps: {
|
|
textContent: file.name
|
|
}
|
|
})
|
|
]); })
|
|
}
|
|
|
|
return [
|
|
h('div', {
|
|
style: this.inputStyle,
|
|
class: this.inputClass,
|
|
domProps: {
|
|
textContent: this.displayValue !== void 0
|
|
? this.displayValue
|
|
: this.selectedString
|
|
}
|
|
})
|
|
]
|
|
},
|
|
|
|
__getInput: function __getInput (h) {
|
|
var data = {
|
|
ref: 'input',
|
|
staticClass: 'q-field__input fit absolute-full cursor-pointer',
|
|
attrs: this.inputAttrs,
|
|
domProps: this.formDomProps,
|
|
on: cache(this, 'input', {
|
|
change: this.__addFiles
|
|
})
|
|
};
|
|
|
|
if (this.multiple === true) {
|
|
data.attrs.multiple = true;
|
|
}
|
|
|
|
return h('input', data)
|
|
}
|
|
},
|
|
|
|
created: function created () {
|
|
this.fieldClass = 'q-file q-field--auto-height';
|
|
|
|
// necessary for QField's clearable
|
|
// and FileValueMixin
|
|
this.type = 'file';
|
|
}
|
|
});
|
|
|
|
var QFooter = Vue.extend({
|
|
name: 'QFooter',
|
|
|
|
mixins: [ ListenersMixin ],
|
|
|
|
inject: {
|
|
layout: {
|
|
default: function default$1 () {
|
|
console.error('QFooter needs to be child of QLayout');
|
|
}
|
|
}
|
|
},
|
|
|
|
props: {
|
|
value: {
|
|
type: Boolean,
|
|
default: true
|
|
},
|
|
reveal: Boolean,
|
|
bordered: Boolean,
|
|
elevated: Boolean,
|
|
|
|
heightHint: {
|
|
type: [String, Number],
|
|
default: 50
|
|
}
|
|
},
|
|
|
|
data: function data () {
|
|
return {
|
|
size: parseInt(this.heightHint, 10),
|
|
revealed: true,
|
|
windowHeight: onSSR || this.layout.container ? 0 : window.innerHeight
|
|
}
|
|
},
|
|
|
|
watch: {
|
|
value: function value (val) {
|
|
this.__update('space', val);
|
|
this.__updateLocal('revealed', true);
|
|
this.layout.__animate();
|
|
},
|
|
|
|
offset: function offset (val) {
|
|
this.__update('offset', val);
|
|
},
|
|
|
|
reveal: function reveal (val) {
|
|
val === false && this.__updateLocal('revealed', this.value);
|
|
},
|
|
|
|
revealed: function revealed (val) {
|
|
this.layout.__animate();
|
|
this.$emit('reveal', val);
|
|
},
|
|
|
|
'layout.scroll': function layout_scroll () {
|
|
this.__updateRevealed();
|
|
},
|
|
|
|
'layout.height': function layout_height () {
|
|
this.__updateRevealed();
|
|
},
|
|
|
|
size: function size () {
|
|
this.__updateRevealed();
|
|
},
|
|
|
|
'$q.screen.height': function $q_screen_height (val) {
|
|
this.layout.container !== true && this.__updateLocal('windowHeight', val);
|
|
}
|
|
},
|
|
|
|
computed: {
|
|
fixed: function fixed () {
|
|
return this.reveal === true ||
|
|
this.layout.view.indexOf('F') > -1 ||
|
|
this.layout.container === true
|
|
},
|
|
|
|
containerHeight: function containerHeight () {
|
|
return this.layout.container === true
|
|
? this.layout.containerHeight
|
|
: this.windowHeight
|
|
},
|
|
|
|
offset: function offset () {
|
|
if (this.value !== true) {
|
|
return 0
|
|
}
|
|
if (this.fixed === true) {
|
|
return this.revealed === true ? this.size : 0
|
|
}
|
|
var offset = this.layout.scroll.position + this.containerHeight + this.size - this.layout.height;
|
|
return offset > 0 ? offset : 0
|
|
},
|
|
|
|
hidden: function hidden () {
|
|
return this.value !== true || (this.fixed === true && this.revealed !== true)
|
|
},
|
|
|
|
revealOnFocus: function revealOnFocus () {
|
|
return this.value === true && this.hidden === true && this.reveal === true
|
|
},
|
|
|
|
classes: function classes () {
|
|
return (this.fixed === true ? 'fixed' : 'absolute') + '-bottom' +
|
|
(this.bordered === true ? ' q-footer--bordered' : '') +
|
|
(this.hidden === true ? ' q-footer--hidden' : '') +
|
|
(this.value !== true ? ' q-layout--prevent-focus' : '') +
|
|
(this.value !== true && this.fixed !== true ? ' hidden' : '')
|
|
},
|
|
|
|
style: function style () {
|
|
var
|
|
view = this.layout.rows.bottom,
|
|
css = {};
|
|
|
|
if (view[0] === 'l' && this.layout.left.space === true) {
|
|
css[this.$q.lang.rtl === true ? 'right' : 'left'] = (this.layout.left.size) + "px";
|
|
}
|
|
if (view[2] === 'r' && this.layout.right.space === true) {
|
|
css[this.$q.lang.rtl === true ? 'left' : 'right'] = (this.layout.right.size) + "px";
|
|
}
|
|
|
|
return css
|
|
},
|
|
|
|
onEvents: function onEvents () {
|
|
return Object.assign({}, this.qListeners,
|
|
{focusin: this.__onFocusin,
|
|
input: stop})
|
|
}
|
|
},
|
|
|
|
render: function render (h) {
|
|
var child = mergeSlot([
|
|
h(QResizeObserver, {
|
|
props: { debounce: 0 },
|
|
on: cache(this, 'resize', { resize: this.__onResize })
|
|
})
|
|
], this, 'default');
|
|
|
|
this.elevated === true && child.push(
|
|
h('div', {
|
|
staticClass: 'q-layout__shadow absolute-full overflow-hidden no-pointer-events'
|
|
})
|
|
);
|
|
|
|
return h('footer', {
|
|
staticClass: 'q-footer q-layout__section--marginal',
|
|
class: this.classes,
|
|
style: this.style,
|
|
on: this.onEvents
|
|
}, child)
|
|
},
|
|
|
|
created: function created () {
|
|
this.layout.instances.footer = this;
|
|
this.value === true && this.__update('size', this.size);
|
|
this.__update('space', this.value);
|
|
this.__update('offset', this.offset);
|
|
},
|
|
|
|
beforeDestroy: function beforeDestroy () {
|
|
if (this.layout.instances.footer === this) {
|
|
this.layout.instances.footer = void 0;
|
|
this.__update('size', 0);
|
|
this.__update('offset', 0);
|
|
this.__update('space', false);
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
__onResize: function __onResize (ref) {
|
|
var height = ref.height;
|
|
|
|
this.__updateLocal('size', height);
|
|
this.__update('size', height);
|
|
},
|
|
|
|
__update: function __update (prop, val) {
|
|
if (this.layout.footer[prop] !== val) {
|
|
this.layout.footer[prop] = val;
|
|
}
|
|
},
|
|
|
|
__updateLocal: function __updateLocal (prop, val) {
|
|
if (this[prop] !== val) {
|
|
this[prop] = val;
|
|
}
|
|
},
|
|
|
|
__updateRevealed: function __updateRevealed () {
|
|
if (this.reveal !== true) { return }
|
|
|
|
var ref = this.layout.scroll;
|
|
var direction = ref.direction;
|
|
var position = ref.position;
|
|
var inflexionPosition = ref.inflexionPosition;
|
|
|
|
this.__updateLocal('revealed', (
|
|
direction === 'up' ||
|
|
position - inflexionPosition < 100 ||
|
|
this.layout.height - this.containerHeight - position - this.size < 300
|
|
));
|
|
},
|
|
|
|
__onFocusin: function __onFocusin (evt) {
|
|
if (this.revealOnFocus === true) {
|
|
this.__updateLocal('revealed', true);
|
|
}
|
|
|
|
this.$emit('focusin', evt);
|
|
}
|
|
}
|
|
});
|
|
|
|
var QForm = Vue.extend({
|
|
name: 'QForm',
|
|
|
|
mixins: [ ListenersMixin ],
|
|
|
|
props: {
|
|
autofocus: Boolean,
|
|
noErrorFocus: Boolean,
|
|
noResetFocus: Boolean,
|
|
greedy: Boolean
|
|
},
|
|
|
|
computed: {
|
|
onEvents: function onEvents () {
|
|
return Object.assign({}, this.qListeners,
|
|
{submit: this.submit,
|
|
reset: this.reset})
|
|
}
|
|
},
|
|
|
|
mounted: function mounted () {
|
|
this.validateIndex = 0;
|
|
this.autofocus === true && this.focus();
|
|
},
|
|
|
|
methods: {
|
|
validate: function validate (shouldFocus) {
|
|
var this$1 = this;
|
|
|
|
var promises = [];
|
|
var focus = typeof shouldFocus === 'boolean'
|
|
? shouldFocus
|
|
: this.noErrorFocus !== true;
|
|
|
|
this.validateIndex++;
|
|
|
|
var components = this.getValidationComponents();
|
|
|
|
var emit = function (res, ref) {
|
|
this$1.$emit('validation-' + (res === true ? 'success' : 'error'), ref);
|
|
};
|
|
|
|
var loop = function ( i ) {
|
|
var comp = components[i];
|
|
var valid = comp.validate();
|
|
|
|
if (typeof valid.then === 'function') {
|
|
promises.push(
|
|
valid.then(
|
|
function (valid) { return ({ valid: valid, comp: comp }); },
|
|
function (error) { return ({ valid: false, comp: comp, error: error }); }
|
|
)
|
|
);
|
|
}
|
|
else if (valid !== true) {
|
|
if (this$1.greedy === false) {
|
|
emit(false, comp);
|
|
|
|
if (focus === true && typeof comp.focus === 'function') {
|
|
comp.focus();
|
|
}
|
|
|
|
return { v: Promise.resolve(false) }
|
|
}
|
|
|
|
promises.push({ valid: false, comp: comp });
|
|
}
|
|
};
|
|
|
|
for (var i = 0; i < components.length; i++) {
|
|
var returned = loop( i );
|
|
|
|
if ( returned ) return returned.v;
|
|
}
|
|
|
|
if (promises.length === 0) {
|
|
emit(true);
|
|
return Promise.resolve(true)
|
|
}
|
|
|
|
var index = this.validateIndex;
|
|
|
|
return Promise.all(promises).then(
|
|
function (res) {
|
|
if (index === this$1.validateIndex) {
|
|
var errors = res.filter(function (r) { return r.valid !== true; });
|
|
|
|
if (errors.length === 0) {
|
|
emit(true);
|
|
return true
|
|
}
|
|
|
|
var ref = errors[0];
|
|
var valid = ref.valid;
|
|
var comp = ref.comp;
|
|
|
|
emit(false, comp);
|
|
|
|
if (
|
|
focus === true &&
|
|
valid !== true &&
|
|
typeof comp.focus === 'function'
|
|
) {
|
|
comp.focus();
|
|
}
|
|
|
|
return false
|
|
}
|
|
}
|
|
)
|
|
},
|
|
|
|
resetValidation: function resetValidation () {
|
|
this.validateIndex++;
|
|
|
|
this.getValidationComponents().forEach(function (comp) {
|
|
comp.resetValidation();
|
|
});
|
|
},
|
|
|
|
submit: function submit (evt) {
|
|
var this$1 = this;
|
|
|
|
evt !== void 0 && stopAndPrevent(evt);
|
|
|
|
this.validate().then(function (val) {
|
|
if (val === true) {
|
|
if (this$1.qListeners.submit !== void 0) {
|
|
this$1.$emit('submit', evt);
|
|
}
|
|
else if (evt !== void 0 && evt.target !== void 0 && typeof evt.target.submit === 'function') {
|
|
evt.target.submit();
|
|
}
|
|
}
|
|
});
|
|
},
|
|
|
|
reset: function reset (evt) {
|
|
var this$1 = this;
|
|
|
|
evt !== void 0 && stopAndPrevent(evt);
|
|
|
|
this.$emit('reset');
|
|
|
|
this.$nextTick(function () { // allow userland to reset values before
|
|
this$1.resetValidation();
|
|
if (this$1.autofocus === true && this$1.noResetFocus !== true) {
|
|
this$1.focus();
|
|
}
|
|
});
|
|
},
|
|
|
|
focus: function focus () {
|
|
var target = this.$el.querySelector('[autofocus], [data-autofocus]') ||
|
|
Array.prototype.find.call(this.$el.querySelectorAll('[tabindex]'), function (el) { return el.tabIndex > -1; });
|
|
|
|
target !== null && target !== void 0 && target.focus();
|
|
},
|
|
|
|
getValidationComponents: function getValidationComponents () {
|
|
return Array.prototype.map.call(
|
|
this.$el.getElementsByClassName('q-validation-component'),
|
|
function (field) { return field.__vue__; }
|
|
).filter(function (c) { return c !== void 0 && typeof c.validate === 'function'; })
|
|
}
|
|
},
|
|
|
|
render: function render (h) {
|
|
return h('form', {
|
|
staticClass: 'q-form',
|
|
on: this.onEvents
|
|
}, slot(this, 'default'))
|
|
}
|
|
});
|
|
|
|
var QHeader = Vue.extend({
|
|
name: 'QHeader',
|
|
|
|
mixins: [ ListenersMixin ],
|
|
|
|
inject: {
|
|
layout: {
|
|
default: function default$1 () {
|
|
console.error('QHeader needs to be child of QLayout');
|
|
}
|
|
}
|
|
},
|
|
|
|
props: {
|
|
value: {
|
|
type: Boolean,
|
|
default: true
|
|
},
|
|
reveal: Boolean,
|
|
revealOffset: {
|
|
type: Number,
|
|
default: 250
|
|
},
|
|
bordered: Boolean,
|
|
elevated: Boolean,
|
|
|
|
heightHint: {
|
|
type: [String, Number],
|
|
default: 50
|
|
}
|
|
},
|
|
|
|
data: function data () {
|
|
return {
|
|
size: parseInt(this.heightHint, 10),
|
|
revealed: true
|
|
}
|
|
},
|
|
|
|
watch: {
|
|
value: function value (val) {
|
|
this.__update('space', val);
|
|
this.__updateLocal('revealed', true);
|
|
this.layout.__animate();
|
|
},
|
|
|
|
offset: function offset (val) {
|
|
this.__update('offset', val);
|
|
},
|
|
|
|
reveal: function reveal (val) {
|
|
val === false && this.__updateLocal('revealed', this.value);
|
|
},
|
|
|
|
revealed: function revealed (val) {
|
|
this.layout.__animate();
|
|
this.$emit('reveal', val);
|
|
},
|
|
|
|
'layout.scroll': function layout_scroll (scroll) {
|
|
this.reveal === true && this.__updateLocal('revealed',
|
|
scroll.direction === 'up' ||
|
|
scroll.position <= this.revealOffset ||
|
|
scroll.position - scroll.inflexionPosition < 100
|
|
);
|
|
}
|
|
},
|
|
|
|
computed: {
|
|
fixed: function fixed () {
|
|
return this.reveal === true ||
|
|
this.layout.view.indexOf('H') > -1 ||
|
|
this.layout.container === true
|
|
},
|
|
|
|
offset: function offset () {
|
|
if (this.value !== true) {
|
|
return 0
|
|
}
|
|
if (this.fixed === true) {
|
|
return this.revealed === true ? this.size : 0
|
|
}
|
|
var offset = this.size - this.layout.scroll.position;
|
|
return offset > 0 ? offset : 0
|
|
},
|
|
|
|
hidden: function hidden () {
|
|
return this.value !== true || (this.fixed === true && this.revealed !== true)
|
|
},
|
|
|
|
revealOnFocus: function revealOnFocus () {
|
|
return this.value === true && this.hidden === true && this.reveal === true
|
|
},
|
|
|
|
classes: function classes () {
|
|
return (this.fixed === true ? 'fixed' : 'absolute') + '-top' +
|
|
(this.bordered === true ? ' q-header--bordered' : '') +
|
|
(this.hidden === true ? ' q-header--hidden' : '') +
|
|
(this.value !== true ? ' q-layout--prevent-focus' : '')
|
|
},
|
|
|
|
style: function style () {
|
|
var
|
|
view = this.layout.rows.top,
|
|
css = {};
|
|
|
|
if (view[0] === 'l' && this.layout.left.space === true) {
|
|
css[this.$q.lang.rtl === true ? 'right' : 'left'] = (this.layout.left.size) + "px";
|
|
}
|
|
if (view[2] === 'r' && this.layout.right.space === true) {
|
|
css[this.$q.lang.rtl === true ? 'left' : 'right'] = (this.layout.right.size) + "px";
|
|
}
|
|
|
|
return css
|
|
},
|
|
|
|
onEvents: function onEvents () {
|
|
return Object.assign({}, this.qListeners,
|
|
{focusin: this.__onFocusin,
|
|
input: stop})
|
|
}
|
|
},
|
|
|
|
render: function render (h) {
|
|
var child = uniqueSlot(this, 'default', []);
|
|
|
|
this.elevated === true && child.push(
|
|
h('div', {
|
|
staticClass: 'q-layout__shadow absolute-full overflow-hidden no-pointer-events'
|
|
})
|
|
);
|
|
|
|
child.push(
|
|
h(QResizeObserver, {
|
|
props: { debounce: 0 },
|
|
on: cache(this, 'resize', { resize: this.__onResize })
|
|
})
|
|
);
|
|
|
|
return h('header', {
|
|
staticClass: 'q-header q-layout__section--marginal',
|
|
class: this.classes,
|
|
style: this.style,
|
|
on: this.onEvents
|
|
}, child)
|
|
},
|
|
|
|
created: function created () {
|
|
this.layout.instances.header = this;
|
|
this.value === true && this.__update('size', this.size);
|
|
this.__update('space', this.value);
|
|
this.__update('offset', this.offset);
|
|
},
|
|
|
|
beforeDestroy: function beforeDestroy () {
|
|
if (this.layout.instances.header === this) {
|
|
this.layout.instances.header = void 0;
|
|
this.__update('size', 0);
|
|
this.__update('offset', 0);
|
|
this.__update('space', false);
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
__onResize: function __onResize (ref) {
|
|
var height = ref.height;
|
|
|
|
this.__updateLocal('size', height);
|
|
this.__update('size', height);
|
|
},
|
|
|
|
__update: function __update (prop, val) {
|
|
if (this.layout.header[prop] !== val) {
|
|
this.layout.header[prop] = val;
|
|
}
|
|
},
|
|
|
|
__updateLocal: function __updateLocal (prop, val) {
|
|
if (this[prop] !== val) {
|
|
this[prop] = val;
|
|
}
|
|
},
|
|
|
|
__onFocusin: function __onFocusin (evt) {
|
|
if (this.revealOnFocus === true) {
|
|
this.__updateLocal('revealed', true);
|
|
}
|
|
|
|
this.$emit('focusin', evt);
|
|
}
|
|
}
|
|
});
|
|
|
|
var RatioMixin = {
|
|
props: {
|
|
ratio: [ String, Number ]
|
|
},
|
|
|
|
computed: {
|
|
ratioStyle: function ratioStyle () {
|
|
var ratio = this.ratio || this.naturalRatio;
|
|
|
|
if (ratio !== void 0) {
|
|
return { paddingBottom: ((100 / ratio) + "%") }
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
var QImg = Vue.extend({
|
|
name: 'QImg',
|
|
|
|
mixins: [ ListenersMixin, RatioMixin ],
|
|
|
|
props: {
|
|
src: String,
|
|
srcset: String,
|
|
sizes: String,
|
|
alt: String,
|
|
width: String,
|
|
height: String,
|
|
|
|
placeholderSrc: String,
|
|
|
|
basic: Boolean,
|
|
contain: Boolean,
|
|
position: {
|
|
type: String,
|
|
default: '50% 50%'
|
|
},
|
|
|
|
transition: {
|
|
type: String,
|
|
default: 'fade'
|
|
},
|
|
|
|
imgClass: [ Array, String, Object ],
|
|
imgStyle: Object,
|
|
|
|
nativeContextMenu: Boolean,
|
|
|
|
noDefaultSpinner: Boolean,
|
|
spinnerColor: String,
|
|
spinnerSize: String
|
|
},
|
|
|
|
data: function data () {
|
|
return {
|
|
currentSrc: '',
|
|
image: null,
|
|
isLoading: !!this.src,
|
|
hasError: false,
|
|
naturalRatio: void 0
|
|
}
|
|
},
|
|
|
|
watch: {
|
|
src: function src () {
|
|
this.__load();
|
|
},
|
|
|
|
srcset: function srcset (val) {
|
|
this.__updateWatcher(val);
|
|
}
|
|
},
|
|
|
|
computed: {
|
|
url: function url () {
|
|
return this.currentSrc || this.placeholderSrc || void 0
|
|
},
|
|
|
|
attrs: function attrs () {
|
|
var att = { role: 'img' };
|
|
if (this.alt !== void 0) {
|
|
att['aria-label'] = this.alt;
|
|
}
|
|
return att
|
|
},
|
|
|
|
imgContainerStyle: function imgContainerStyle () {
|
|
return Object.assign(
|
|
{
|
|
backgroundSize: this.contain === true ? 'contain' : 'cover',
|
|
backgroundPosition: this.position
|
|
},
|
|
this.imgStyle,
|
|
{ backgroundImage: ("url(\"" + (this.url) + "\")") })
|
|
},
|
|
|
|
style: function style () {
|
|
return {
|
|
width: this.width,
|
|
height: this.height
|
|
}
|
|
},
|
|
|
|
classes: function classes () {
|
|
return 'q-img overflow-hidden' +
|
|
(this.nativeContextMenu === true ? ' q-img--menu' : '')
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
__onLoad: function __onLoad (img) {
|
|
this.isLoading = false;
|
|
this.hasError = false;
|
|
this.__computeRatio(img);
|
|
this.__updateSrc();
|
|
this.__updateWatcher(this.srcset);
|
|
this.$emit('load', this.currentSrc);
|
|
},
|
|
|
|
__onError: function __onError (err) {
|
|
clearTimeout(this.ratioTimer);
|
|
this.isLoading = false;
|
|
this.hasError = true;
|
|
this.currentSrc = '';
|
|
this.$emit('error', err);
|
|
},
|
|
|
|
__updateSrc: function __updateSrc () {
|
|
if (this.image !== void 0 && this.isLoading === false) {
|
|
var src = this.image.currentSrc || this.image.src;
|
|
if (this.currentSrc !== src) {
|
|
this.currentSrc = src;
|
|
}
|
|
}
|
|
},
|
|
|
|
__updateWatcher: function __updateWatcher (srcset) {
|
|
if (srcset) {
|
|
if (this.unwatch === void 0) {
|
|
this.unwatch = this.$watch('$q.screen.width', this.__updateSrc);
|
|
}
|
|
}
|
|
else if (this.unwatch !== void 0) {
|
|
this.unwatch();
|
|
this.unwatch = void 0;
|
|
}
|
|
},
|
|
|
|
__load: function __load () {
|
|
var this$1 = this;
|
|
|
|
clearTimeout(this.ratioTimer);
|
|
this.hasError = false;
|
|
|
|
if (!this.src) {
|
|
this.isLoading = false;
|
|
this.image = void 0;
|
|
this.currentSrc = '';
|
|
return
|
|
}
|
|
|
|
this.isLoading = true;
|
|
|
|
var img = new Image();
|
|
this.image = img;
|
|
|
|
img.onerror = function (err) {
|
|
// if we are still rendering same image
|
|
if (this$1.image === img && this$1.destroyed !== true) {
|
|
this$1.__onError(err);
|
|
}
|
|
};
|
|
|
|
img.onload = function () {
|
|
if (this$1.destroyed === true) {
|
|
return
|
|
}
|
|
|
|
// if we are still rendering same image
|
|
if (this$1.image === img) {
|
|
if (img.decode !== void 0) {
|
|
img
|
|
.decode()
|
|
.catch(function (err) {
|
|
if (this$1.image === img && this$1.destroyed !== true) {
|
|
this$1.__onError(err);
|
|
}
|
|
})
|
|
.then(function () {
|
|
if (this$1.image === img && this$1.destroyed !== true) {
|
|
this$1.__onLoad(img);
|
|
}
|
|
});
|
|
}
|
|
else {
|
|
this$1.__onLoad(img);
|
|
}
|
|
}
|
|
};
|
|
|
|
img.src = this.src;
|
|
|
|
if (this.srcset) {
|
|
img.srcset = this.srcset;
|
|
}
|
|
|
|
if (this.sizes !== void 0) {
|
|
img.sizes = this.sizes;
|
|
}
|
|
else {
|
|
Object.assign(img, {
|
|
height: this.height,
|
|
width: this.width
|
|
});
|
|
}
|
|
},
|
|
|
|
__computeRatio: function __computeRatio (img) {
|
|
var this$1 = this;
|
|
|
|
var naturalHeight = img.naturalHeight;
|
|
var naturalWidth = img.naturalWidth;
|
|
|
|
if (naturalHeight || naturalWidth) {
|
|
this.naturalRatio = naturalHeight === 0
|
|
? 1
|
|
: naturalWidth / naturalHeight;
|
|
}
|
|
else {
|
|
this.ratioTimer = setTimeout(function () {
|
|
if (this$1.image === img && this$1.destroyed !== true) {
|
|
this$1.__computeRatio(img);
|
|
}
|
|
}, 100);
|
|
}
|
|
},
|
|
|
|
__getImage: function __getImage (h) {
|
|
var nativeImg = this.nativeContextMenu === true
|
|
? [
|
|
h('img', {
|
|
staticClass: 'absolute-full fit',
|
|
attrs: { src: this.url, 'aria-hidden': 'true' }
|
|
})
|
|
]
|
|
: void 0;
|
|
|
|
var content = this.url !== void 0
|
|
? h('div', {
|
|
key: this.url,
|
|
staticClass: 'q-img__image absolute-full',
|
|
class: this.imgClass,
|
|
style: this.imgContainerStyle
|
|
}, nativeImg)
|
|
: null;
|
|
|
|
return this.basic === true
|
|
? content
|
|
: h('transition', {
|
|
props: { name: 'q-transition--' + this.transition }
|
|
}, [ content ])
|
|
},
|
|
|
|
__getContent: function __getContent (h) {
|
|
var slotVm = slot(this, this.hasError === true ? 'error' : 'default');
|
|
|
|
if (this.basic === true) {
|
|
return h('div', {
|
|
key: 'content',
|
|
staticClass: 'q-img__content absolute-full'
|
|
}, slotVm)
|
|
}
|
|
|
|
var content = this.isLoading === true
|
|
? h('div', {
|
|
key: 'placeholder',
|
|
staticClass: 'q-img__loading absolute-full flex flex-center'
|
|
}, this.$scopedSlots.loading !== void 0
|
|
? this.$scopedSlots.loading()
|
|
: (
|
|
this.noDefaultSpinner === false
|
|
? [
|
|
h(QSpinner, {
|
|
props: {
|
|
color: this.spinnerColor,
|
|
size: this.spinnerSize
|
|
}
|
|
})
|
|
]
|
|
: void 0
|
|
)
|
|
)
|
|
: h('div', {
|
|
key: 'content',
|
|
staticClass: 'q-img__content absolute-full'
|
|
}, slotVm);
|
|
|
|
return h('transition', {
|
|
props: { name: 'q-transition--fade' }
|
|
}, [ content ])
|
|
}
|
|
},
|
|
|
|
render: function render (h) {
|
|
return h('div', {
|
|
class: this.classes,
|
|
style: this.style,
|
|
attrs: this.attrs,
|
|
on: Object.assign({}, this.qListeners)
|
|
}, [
|
|
h('div', { style: this.ratioStyle }),
|
|
this.__getImage(h),
|
|
this.__getContent(h)
|
|
])
|
|
},
|
|
|
|
beforeMount: function beforeMount () {
|
|
if (this.placeholderSrc !== void 0 && this.ratio === void 0) {
|
|
var img = new Image();
|
|
img.src = this.placeholderSrc;
|
|
this.__computeRatio(img);
|
|
}
|
|
this.isLoading === true && this.__load();
|
|
},
|
|
|
|
beforeDestroy: function beforeDestroy () {
|
|
this.destroyed = true;
|
|
clearTimeout(this.ratioTimer);
|
|
this.unwatch !== void 0 && this.unwatch();
|
|
}
|
|
});
|
|
|
|
var QInfiniteScroll = Vue.extend({
|
|
name: 'QInfiniteScroll',
|
|
|
|
mixins: [ ListenersMixin ],
|
|
|
|
props: {
|
|
offset: {
|
|
type: Number,
|
|
default: 500
|
|
},
|
|
|
|
debounce: {
|
|
type: [ String, Number ],
|
|
default: 100
|
|
},
|
|
|
|
scrollTarget: {
|
|
default: void 0
|
|
},
|
|
|
|
initialIndex: Number,
|
|
|
|
disable: Boolean,
|
|
reverse: Boolean
|
|
},
|
|
|
|
data: function data () {
|
|
return {
|
|
index: this.initialIndex || 0,
|
|
fetching: false,
|
|
working: true
|
|
}
|
|
},
|
|
|
|
watch: {
|
|
disable: function disable (val) {
|
|
if (val === true) {
|
|
this.stop();
|
|
}
|
|
else {
|
|
this.resume();
|
|
}
|
|
},
|
|
|
|
scrollTarget: function scrollTarget () {
|
|
this.updateScrollTarget();
|
|
},
|
|
|
|
debounce: function debounce (val) {
|
|
this.__setDebounce(val);
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
poll: function poll () {
|
|
if (this.disable === true || this.fetching === true || this.working === false) {
|
|
return
|
|
}
|
|
|
|
var
|
|
scrollHeight = getScrollHeight(this.__scrollTarget),
|
|
scrollPosition = getScrollPosition(this.__scrollTarget),
|
|
containerHeight = height(this.__scrollTarget);
|
|
|
|
if (this.reverse === false) {
|
|
if (scrollPosition + containerHeight + this.offset >= scrollHeight) {
|
|
this.trigger();
|
|
}
|
|
}
|
|
else {
|
|
if (scrollPosition < this.offset) {
|
|
this.trigger();
|
|
}
|
|
}
|
|
},
|
|
|
|
trigger: function trigger () {
|
|
var this$1 = this;
|
|
|
|
if (this.disable === true || this.fetching === true || this.working === false) {
|
|
return
|
|
}
|
|
|
|
this.index++;
|
|
this.fetching = true;
|
|
|
|
var heightBefore = getScrollHeight(this.__scrollTarget);
|
|
|
|
this.$emit('load', this.index, function (stop) {
|
|
if (this$1.working === true) {
|
|
this$1.fetching = false;
|
|
this$1.$nextTick(function () {
|
|
if (this$1.reverse === true) {
|
|
var
|
|
heightAfter = getScrollHeight(this$1.__scrollTarget),
|
|
scrollPosition = getScrollPosition(this$1.__scrollTarget),
|
|
heightDifference = heightAfter - heightBefore;
|
|
|
|
setScrollPosition(this$1.__scrollTarget, scrollPosition + heightDifference);
|
|
}
|
|
|
|
if (stop === true) {
|
|
this$1.stop();
|
|
}
|
|
else {
|
|
this$1.$el.closest('body') && this$1.poll();
|
|
}
|
|
});
|
|
}
|
|
});
|
|
},
|
|
|
|
reset: function reset () {
|
|
this.index = 0;
|
|
},
|
|
|
|
resume: function resume () {
|
|
if (this.working === false) {
|
|
this.working = true;
|
|
this.__scrollTarget.addEventListener('scroll', this.poll, listenOpts.passive);
|
|
}
|
|
this.immediatePoll();
|
|
},
|
|
|
|
stop: function stop () {
|
|
if (this.working === true) {
|
|
this.working = false;
|
|
this.fetching = false;
|
|
this.__scrollTarget.removeEventListener('scroll', this.poll, listenOpts.passive);
|
|
}
|
|
},
|
|
|
|
updateScrollTarget: function updateScrollTarget () {
|
|
if (this.__scrollTarget && this.working === true) {
|
|
this.__scrollTarget.removeEventListener('scroll', this.poll, listenOpts.passive);
|
|
}
|
|
|
|
this.__scrollTarget = getScrollTarget(this.$el, this.scrollTarget);
|
|
|
|
if (this.working === true) {
|
|
this.__scrollTarget.addEventListener('scroll', this.poll, listenOpts.passive);
|
|
}
|
|
},
|
|
|
|
setIndex: function setIndex (index) {
|
|
this.index = index;
|
|
},
|
|
|
|
__setDebounce: function __setDebounce (val) {
|
|
val = parseInt(val, 10);
|
|
if (val <= 0) {
|
|
this.poll = this.immediatePoll;
|
|
}
|
|
else {
|
|
this.poll = debounce(this.immediatePoll, isNaN(val) === true ? 100 : val);
|
|
}
|
|
}
|
|
},
|
|
|
|
mounted: function mounted () {
|
|
this.immediatePoll = this.poll;
|
|
this.__setDebounce(this.debounce);
|
|
|
|
this.updateScrollTarget();
|
|
this.immediatePoll();
|
|
|
|
if (this.reverse === true) {
|
|
var
|
|
scrollHeight = getScrollHeight(this.__scrollTarget),
|
|
containerHeight = height(this.__scrollTarget);
|
|
|
|
setScrollPosition(this.__scrollTarget, scrollHeight - containerHeight);
|
|
}
|
|
},
|
|
|
|
beforeDestroy: function beforeDestroy () {
|
|
if (this.working === true) {
|
|
this.__scrollTarget.removeEventListener('scroll', this.poll, listenOpts.passive);
|
|
}
|
|
},
|
|
|
|
render: function render (h) {
|
|
var child = uniqueSlot(this, 'default', []);
|
|
|
|
if (this.disable !== true && this.working === true) {
|
|
child[this.reverse === false ? 'push' : 'unshift'](
|
|
h('div', {
|
|
staticClass: 'q-infinite-scroll__loading',
|
|
class: this.fetching === true ? '' : 'invisible'
|
|
}, slot(this, 'loading'))
|
|
);
|
|
}
|
|
|
|
return h('div', {
|
|
staticClass: 'q-infinite-scroll',
|
|
on: Object.assign({}, this.qListeners)
|
|
}, child)
|
|
}
|
|
});
|
|
|
|
var QInnerLoading = Vue.extend({
|
|
name: 'QInnerLoading',
|
|
|
|
mixins: [ ListenersMixin, DarkMixin, TransitionMixin ],
|
|
|
|
props: {
|
|
showing: Boolean,
|
|
color: String,
|
|
|
|
size: {
|
|
type: [String, Number],
|
|
default: 42
|
|
}
|
|
},
|
|
|
|
render: function render (h) {
|
|
var child = this.showing === true
|
|
? [
|
|
h('div',
|
|
{
|
|
staticClass: 'q-inner-loading absolute-full column flex-center',
|
|
class: this.isDark === true ? 'q-inner-loading--dark' : null,
|
|
on: Object.assign({}, this.qListeners)
|
|
},
|
|
this.$scopedSlots.default !== void 0
|
|
? this.$scopedSlots.default()
|
|
: [
|
|
h(QSpinner, {
|
|
props: {
|
|
size: this.size,
|
|
color: this.color
|
|
}
|
|
})
|
|
]
|
|
)
|
|
]
|
|
: void 0;
|
|
|
|
return h('transition', {
|
|
props: {
|
|
name: this.transition,
|
|
appear: true
|
|
}
|
|
}, child)
|
|
}
|
|
});
|
|
|
|
var defaultCfg = {
|
|
threshold: 0,
|
|
root: null,
|
|
rootMargin: '0px'
|
|
};
|
|
|
|
function update (el, ctx, value) {
|
|
var handler, cfg, changed;
|
|
|
|
if (typeof value === 'function') {
|
|
handler = value;
|
|
cfg = defaultCfg;
|
|
changed = ctx.cfg === void 0;
|
|
}
|
|
else {
|
|
handler = value.handler;
|
|
cfg = Object.assign({}, defaultCfg, value.cfg);
|
|
changed = ctx.cfg === void 0 || isDeepEqual(ctx.cfg, cfg) === false;
|
|
}
|
|
|
|
if (ctx.handler !== handler) {
|
|
ctx.handler = handler;
|
|
}
|
|
|
|
if (changed === true) {
|
|
ctx.cfg = cfg;
|
|
ctx.observer !== void 0 && ctx.observer.unobserve(el);
|
|
|
|
ctx.observer = new IntersectionObserver(function (ref) {
|
|
var entry = ref[0];
|
|
|
|
if (typeof ctx.handler === 'function') {
|
|
// if observed element is part of a vue transition
|
|
// then we need to be careful...
|
|
if (
|
|
entry.rootBounds === null &&
|
|
(el.__vue__ !== void 0 ? el.__vue__._inactive !== true : document.body.contains(el) === true)
|
|
) {
|
|
ctx.observer.unobserve(el);
|
|
ctx.observer.observe(el);
|
|
return
|
|
}
|
|
|
|
var res = ctx.handler(entry, ctx.observer);
|
|
|
|
if (
|
|
res === false ||
|
|
(ctx.once === true && entry.isIntersecting === true)
|
|
) {
|
|
destroy$3(el);
|
|
}
|
|
}
|
|
}, cfg);
|
|
|
|
ctx.observer.observe(el);
|
|
}
|
|
}
|
|
|
|
function destroy$3 (el) {
|
|
var ctx = el.__qvisible;
|
|
|
|
if (ctx !== void 0) {
|
|
ctx.observer !== void 0 && ctx.observer.unobserve(el);
|
|
delete el.__qvisible;
|
|
}
|
|
}
|
|
|
|
var Intersection = {
|
|
name: 'intersection',
|
|
|
|
inserted: function inserted (el, ref) {
|
|
var modifiers = ref.modifiers;
|
|
var value = ref.value;
|
|
|
|
if (el.__qvisible !== void 0) {
|
|
destroy$3(el);
|
|
el.__qvisible_destroyed = true;
|
|
}
|
|
|
|
var ctx = {
|
|
once: modifiers.once === true
|
|
};
|
|
|
|
update(el, ctx, value);
|
|
|
|
el.__qvisible = ctx;
|
|
},
|
|
|
|
update: function update$1 (el, binding) {
|
|
var ctx = el.__qvisible;
|
|
ctx !== void 0 && update(el, ctx, binding.value);
|
|
},
|
|
|
|
unbind: function unbind (el) {
|
|
if (el.__qvisible_destroyed === void 0) {
|
|
destroy$3(el);
|
|
}
|
|
else {
|
|
delete el.__qvisible_destroyed;
|
|
}
|
|
}
|
|
};
|
|
|
|
var QIntersection = Vue.extend({
|
|
name: 'QIntersection',
|
|
|
|
mixins: [ TagMixin, ListenersMixin ],
|
|
|
|
directives: {
|
|
Intersection: Intersection
|
|
},
|
|
|
|
props: {
|
|
once: Boolean,
|
|
transition: String,
|
|
|
|
ssrPrerender: Boolean,
|
|
|
|
margin: String,
|
|
threshold: [ Number, Array ],
|
|
|
|
disable: Boolean
|
|
},
|
|
|
|
data: function data () {
|
|
return {
|
|
showing: onSSR === true ? this.ssrPrerender : false
|
|
}
|
|
},
|
|
|
|
computed: {
|
|
value: function value () {
|
|
return this.margin !== void 0 || this.threshold !== void 0
|
|
? {
|
|
handler: this.__trigger,
|
|
cfg: {
|
|
rootMargin: this.margin,
|
|
threshold: this.threshold
|
|
}
|
|
}
|
|
: this.__trigger
|
|
},
|
|
|
|
directives: function directives () {
|
|
if (this.disable !== true && (onSSR !== true || this.once !== true || this.ssrPrerender !== true)) {
|
|
return [{
|
|
name: 'intersection',
|
|
value: this.value,
|
|
modifiers: {
|
|
once: this.once
|
|
}
|
|
}]
|
|
}
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
__trigger: function __trigger (entry) {
|
|
if (this.showing !== entry.isIntersecting) {
|
|
this.showing = entry.isIntersecting;
|
|
|
|
if (this.qListeners.visibility !== void 0) {
|
|
this.$emit('visibility', this.showing);
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
render: function render (h) {
|
|
var content = this.showing === true
|
|
? [ h('div', { key: 'content' }, slot(this, 'default')) ]
|
|
: void 0;
|
|
|
|
return h(this.tag, {
|
|
staticClass: 'q-intersection',
|
|
on: Object.assign({}, this.qListeners),
|
|
directives: this.directives
|
|
}, this.transition
|
|
? [
|
|
h('transition', {
|
|
props: { name: 'q-transition--' + this.transition }
|
|
}, content)
|
|
]
|
|
: content
|
|
)
|
|
}
|
|
});
|
|
|
|
// PGDOWN, LEFT, DOWN, PGUP, RIGHT, UP
|
|
var keyCodes$1 = [34, 37, 40, 33, 39, 38];
|
|
|
|
var QKnob = Vue.extend({
|
|
name: 'QKnob',
|
|
|
|
mixins: [
|
|
{ props: QCircularProgress.options.props },
|
|
FormMixin
|
|
],
|
|
|
|
directives: {
|
|
TouchPan: TouchPan
|
|
},
|
|
|
|
props: {
|
|
step: {
|
|
type: Number,
|
|
default: 1,
|
|
validator: function (v) { return v >= 0; }
|
|
},
|
|
|
|
tabindex: {
|
|
type: [Number, String],
|
|
default: 0
|
|
},
|
|
|
|
disable: Boolean,
|
|
readonly: Boolean
|
|
},
|
|
|
|
data: function data () {
|
|
return {
|
|
model: this.value,
|
|
dragging: false
|
|
}
|
|
},
|
|
|
|
watch: {
|
|
value: function value (value$1) {
|
|
if (value$1 < this.min) {
|
|
this.model = this.min;
|
|
}
|
|
else if (value$1 > this.max) {
|
|
this.model = this.max;
|
|
}
|
|
else {
|
|
if (value$1 !== this.model) {
|
|
this.model = value$1;
|
|
}
|
|
return
|
|
}
|
|
|
|
if (this.model !== this.value) {
|
|
this.$emit('input', this.model);
|
|
this.$emit('change', this.model);
|
|
}
|
|
}
|
|
},
|
|
|
|
computed: {
|
|
classes: function classes () {
|
|
return 'q-knob non-selectable' + (
|
|
this.editable === true
|
|
? ' q-knob--editable'
|
|
: (this.disable === true ? ' disabled' : '')
|
|
)
|
|
},
|
|
|
|
editable: function editable () {
|
|
return this.disable === false && this.readonly === false
|
|
},
|
|
|
|
decimals: function decimals () {
|
|
return (String(this.step).trim('0').split('.')[1] || '').length
|
|
},
|
|
|
|
computedStep: function computedStep () {
|
|
return this.step === 0 ? 1 : this.step
|
|
},
|
|
|
|
computedInstantFeedback: function computedInstantFeedback () {
|
|
return this.instantFeedback === true ||
|
|
this.dragging === true
|
|
},
|
|
|
|
onEvents: function onEvents () {
|
|
return this.$q.platform.is.mobile === true
|
|
? { click: this.__click }
|
|
: {
|
|
mousedown: this.__activate,
|
|
click: this.__click,
|
|
keydown: this.__keydown,
|
|
keyup: this.__keyup
|
|
}
|
|
},
|
|
|
|
attrs: function attrs () {
|
|
var attrs = {
|
|
role: 'slider',
|
|
'aria-valuemin': this.min,
|
|
'aria-valuemax': this.max,
|
|
'aria-valuenow': this.value
|
|
};
|
|
|
|
if (this.editable === true) {
|
|
attrs.tabindex = this.tabindex;
|
|
}
|
|
else {
|
|
attrs[("aria-" + (this.disable === true ? 'disabled' : 'readonly'))] = '';
|
|
}
|
|
|
|
return attrs
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
__updateCenterPosition: function __updateCenterPosition () {
|
|
var ref = this.$el.getBoundingClientRect();
|
|
var top = ref.top;
|
|
var left = ref.left;
|
|
var width = ref.width;
|
|
var height = ref.height;
|
|
this.centerPosition = {
|
|
top: top + height / 2,
|
|
left: left + width / 2
|
|
};
|
|
},
|
|
|
|
__pan: function __pan (event) {
|
|
if (event.isFinal) {
|
|
this.__updatePosition(event.evt, true);
|
|
this.dragging = false;
|
|
}
|
|
else if (event.isFirst) {
|
|
this.__updateCenterPosition();
|
|
this.dragging = true;
|
|
this.__updatePosition(event.evt);
|
|
}
|
|
else {
|
|
this.__updatePosition(event.evt);
|
|
}
|
|
},
|
|
|
|
__click: function __click (evt) {
|
|
this.__updateCenterPosition();
|
|
this.__updatePosition(evt, true);
|
|
},
|
|
|
|
__keydown: function __keydown (evt) {
|
|
if (!keyCodes$1.includes(evt.keyCode)) {
|
|
return
|
|
}
|
|
|
|
stopAndPrevent(evt);
|
|
|
|
var
|
|
step = ([34, 33].includes(evt.keyCode) ? 10 : 1) * this.computedStep,
|
|
offset = [34, 37, 40].includes(evt.keyCode) ? -step : step;
|
|
|
|
this.model = between(
|
|
parseFloat((this.model + offset).toFixed(this.decimals)),
|
|
this.min,
|
|
this.max
|
|
);
|
|
|
|
this.__updateValue();
|
|
},
|
|
|
|
__keyup: function __keyup (evt) {
|
|
if (keyCodes$1.includes(evt.keyCode)) {
|
|
this.__updateValue(true);
|
|
}
|
|
},
|
|
|
|
__activate: function __activate (evt) {
|
|
this.__updateCenterPosition();
|
|
this.__updatePosition(evt);
|
|
},
|
|
|
|
__updatePosition: function __updatePosition (evt, change) {
|
|
var
|
|
center = this.centerPosition,
|
|
pos = position(evt),
|
|
height = Math.abs(pos.top - center.top),
|
|
distance = Math.sqrt(
|
|
Math.pow( height, 2 ) +
|
|
Math.pow( Math.abs(pos.left - center.left), 2 )
|
|
);
|
|
|
|
var angle = Math.asin(height / distance) * (180 / Math.PI);
|
|
|
|
if (pos.top < center.top) {
|
|
angle = center.left < pos.left ? 90 - angle : 270 + angle;
|
|
}
|
|
else {
|
|
angle = center.left < pos.left ? angle + 90 : 270 - angle;
|
|
}
|
|
|
|
if (this.angle) {
|
|
angle = normalizeToInterval(angle - this.angle, 0, 360);
|
|
}
|
|
|
|
if (this.$q.lang.rtl === true) {
|
|
angle = 360 - angle;
|
|
}
|
|
|
|
var model = this.min + (angle / 360) * (this.max - this.min);
|
|
|
|
if (this.step !== 0) {
|
|
var
|
|
step = this.computedStep,
|
|
modulo = model % step;
|
|
|
|
model = model - modulo +
|
|
(Math.abs(modulo) >= step / 2 ? (modulo < 0 ? -1 : 1) * step : 0);
|
|
|
|
model = parseFloat(model.toFixed(this.decimals));
|
|
}
|
|
|
|
model = between(model, this.min, this.max);
|
|
|
|
this.$emit('drag-value', model);
|
|
|
|
if (this.model !== model) {
|
|
this.model = model;
|
|
}
|
|
|
|
this.__updateValue(change);
|
|
},
|
|
|
|
__updateValue: function __updateValue (change) {
|
|
this.value !== this.model && this.$emit('input', this.model);
|
|
change === true && this.$emit('change', this.model);
|
|
},
|
|
|
|
__getNameInput: function __getNameInput () {
|
|
return this.$createElement('input', { attrs: this.formAttrs })
|
|
}
|
|
},
|
|
|
|
render: function render (h) {
|
|
var data = {
|
|
class: this.classes,
|
|
attrs: this.attrs,
|
|
props: Object.assign({}, this.$props,
|
|
{value: this.model,
|
|
instantFeedback: this.computedInstantFeedback})
|
|
};
|
|
|
|
if (this.editable === true) {
|
|
data.on = this.onEvents;
|
|
data.directives = cache(this, 'dir', [{
|
|
name: 'touch-pan',
|
|
value: this.__pan,
|
|
modifiers: {
|
|
prevent: true,
|
|
stop: true,
|
|
mouse: true
|
|
}
|
|
}]);
|
|
|
|
if (this.name !== void 0) {
|
|
data.scopedSlots = {
|
|
internal: this.__getNameInput
|
|
};
|
|
}
|
|
}
|
|
|
|
return h(QCircularProgress, data, slot(this, 'default'))
|
|
}
|
|
});
|
|
|
|
var passive$1 = listenOpts.passive;
|
|
|
|
var QScrollObserver = Vue.extend({
|
|
name: 'QScrollObserver',
|
|
|
|
props: {
|
|
debounce: [ String, Number ],
|
|
horizontal: Boolean,
|
|
|
|
scrollTarget: {
|
|
default: void 0
|
|
}
|
|
},
|
|
|
|
render: noop, // eslint-disable-line
|
|
|
|
data: function data () {
|
|
return {
|
|
pos: 0,
|
|
dir: this.horizontal === true ? 'right' : 'down',
|
|
dirChanged: false,
|
|
dirChangePos: 0
|
|
}
|
|
},
|
|
|
|
watch: {
|
|
scrollTarget: function scrollTarget () {
|
|
this.__unconfigureScrollTarget();
|
|
this.__configureScrollTarget();
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
getPosition: function getPosition () {
|
|
return {
|
|
position: this.pos,
|
|
direction: this.dir,
|
|
directionChanged: this.dirChanged,
|
|
inflexionPosition: this.dirChangePos
|
|
}
|
|
},
|
|
|
|
trigger: function trigger (immediately) {
|
|
if (immediately === true || this.debounce === 0 || this.debounce === '0') {
|
|
this.__emit();
|
|
}
|
|
else if (!this.timer) {
|
|
this.timer = this.debounce
|
|
? setTimeout(this.__emit, this.debounce)
|
|
: requestAnimationFrame(this.__emit);
|
|
}
|
|
},
|
|
|
|
__emit: function __emit () {
|
|
var fn = this.horizontal === true
|
|
? getHorizontalScrollPosition
|
|
: getScrollPosition;
|
|
|
|
var
|
|
pos = Math.max(0, fn(this.__scrollTarget)),
|
|
delta = pos - this.pos,
|
|
dir = this.horizontal === true
|
|
? delta < 0 ? 'left' : 'right'
|
|
: delta < 0 ? 'up' : 'down';
|
|
|
|
this.dirChanged = this.dir !== dir;
|
|
|
|
if (this.dirChanged) {
|
|
this.dir = dir;
|
|
this.dirChangePos = this.pos;
|
|
}
|
|
|
|
this.timer = null;
|
|
this.pos = pos;
|
|
this.$emit('scroll', this.getPosition());
|
|
},
|
|
|
|
__configureScrollTarget: function __configureScrollTarget () {
|
|
this.__scrollTarget = getScrollTarget(this.$el.parentNode, this.scrollTarget);
|
|
this.__scrollTarget.addEventListener('scroll', this.trigger, passive$1);
|
|
this.trigger(true);
|
|
},
|
|
|
|
__unconfigureScrollTarget: function __unconfigureScrollTarget () {
|
|
if (this.__scrollTarget !== void 0) {
|
|
this.__scrollTarget.removeEventListener('scroll', this.trigger, passive$1);
|
|
this.__scrollTarget = void 0;
|
|
}
|
|
}
|
|
},
|
|
|
|
mounted: function mounted () {
|
|
this.__configureScrollTarget();
|
|
},
|
|
|
|
beforeDestroy: function beforeDestroy () {
|
|
clearTimeout(this.timer);
|
|
cancelAnimationFrame(this.timer);
|
|
this.__unconfigureScrollTarget();
|
|
}
|
|
});
|
|
|
|
var QLayout = Vue.extend({
|
|
name: 'QLayout',
|
|
|
|
mixins: [ ListenersMixin ],
|
|
|
|
provide: function provide () {
|
|
return {
|
|
layout: this
|
|
}
|
|
},
|
|
|
|
props: {
|
|
container: Boolean,
|
|
view: {
|
|
type: String,
|
|
default: 'hhh lpr fff',
|
|
validator: function (v) { return /^(h|l)h(h|r) lpr (f|l)f(f|r)$/.test(v.toLowerCase()); }
|
|
}
|
|
},
|
|
|
|
data: function data () {
|
|
return {
|
|
// page related
|
|
height: this.$q.screen.height,
|
|
width: this.container === true ? 0 : this.$q.screen.width,
|
|
|
|
// container only prop
|
|
containerHeight: 0,
|
|
scrollbarWidth: onSSR === true ? 0 : getScrollbarWidth(),
|
|
|
|
header: {
|
|
size: 0,
|
|
offset: 0,
|
|
space: false
|
|
},
|
|
right: {
|
|
size: 300,
|
|
offset: 0,
|
|
space: false
|
|
},
|
|
footer: {
|
|
size: 0,
|
|
offset: 0,
|
|
space: false
|
|
},
|
|
left: {
|
|
size: 300,
|
|
offset: 0,
|
|
space: false
|
|
},
|
|
|
|
scroll: {
|
|
position: 0,
|
|
direction: 'down'
|
|
}
|
|
}
|
|
},
|
|
|
|
computed: {
|
|
rows: function rows () {
|
|
var rows = this.view.toLowerCase().split(' ');
|
|
return {
|
|
top: rows[0].split(''),
|
|
middle: rows[1].split(''),
|
|
bottom: rows[2].split('')
|
|
}
|
|
},
|
|
|
|
style: function style () {
|
|
return this.container === true
|
|
? null
|
|
: { minHeight: this.$q.screen.height + 'px' }
|
|
},
|
|
|
|
// used by container only
|
|
targetStyle: function targetStyle () {
|
|
var obj;
|
|
|
|
if (this.scrollbarWidth !== 0) {
|
|
return ( obj = {}, obj[this.$q.lang.rtl === true ? 'left' : 'right'] = ((this.scrollbarWidth) + "px"), obj )
|
|
}
|
|
},
|
|
|
|
targetChildStyle: function targetChildStyle () {
|
|
var obj;
|
|
|
|
if (this.scrollbarWidth !== 0) {
|
|
return ( obj = {}, obj[this.$q.lang.rtl === true ? 'right' : 'left'] = 0, obj[this.$q.lang.rtl === true ? 'left' : 'right'] = ("-" + (this.scrollbarWidth) + "px"), obj.width = ("calc(100% + " + (this.scrollbarWidth) + "px)"), obj )
|
|
}
|
|
},
|
|
|
|
totalWidth: function totalWidth () {
|
|
return this.width + this.scrollbarWidth
|
|
},
|
|
|
|
classes: function classes () {
|
|
return 'q-layout q-layout--' +
|
|
(this.container === true ? 'containerized' : 'standard')
|
|
}
|
|
},
|
|
|
|
created: function created () {
|
|
this.instances = {};
|
|
},
|
|
|
|
render: function render (h) {
|
|
var layout = h('div', {
|
|
class: this.classes,
|
|
style: this.style,
|
|
on: Object.assign({}, this.qListeners)
|
|
}, mergeSlot([
|
|
h(QScrollObserver, {
|
|
on: cache(this, 'scroll', { scroll: this.__onPageScroll })
|
|
}),
|
|
|
|
h(QResizeObserver, {
|
|
on: cache(this, 'resizeOut', { resize: this.__onPageResize })
|
|
})
|
|
], this, 'default'));
|
|
|
|
return this.container === true
|
|
? h('div', {
|
|
staticClass: 'q-layout-container overflow-hidden'
|
|
}, [
|
|
h(QResizeObserver, {
|
|
on: cache(this, 'resizeIn', { resize: this.__onContainerResize })
|
|
}),
|
|
h('div', {
|
|
staticClass: 'absolute-full',
|
|
style: this.targetStyle
|
|
}, [
|
|
h('div', {
|
|
staticClass: 'scroll',
|
|
style: this.targetChildStyle
|
|
}, [ layout ])
|
|
])
|
|
])
|
|
: layout
|
|
},
|
|
|
|
methods: {
|
|
__animate: function __animate () {
|
|
var this$1 = this;
|
|
|
|
if (this.timer !== void 0) {
|
|
clearTimeout(this.timer);
|
|
}
|
|
else {
|
|
document.body.classList.add('q-body--layout-animate');
|
|
}
|
|
this.timer = setTimeout(function () {
|
|
document.body.classList.remove('q-body--layout-animate');
|
|
this$1.timer = void 0;
|
|
}, 150);
|
|
},
|
|
|
|
__onPageScroll: function __onPageScroll (data) {
|
|
if (this.container === true || document.qScrollPrevented !== true) {
|
|
this.scroll = data;
|
|
}
|
|
this.qListeners.scroll !== void 0 && this.$emit('scroll', data);
|
|
},
|
|
|
|
__onPageResize: function __onPageResize (ref) {
|
|
var height = ref.height;
|
|
var width = ref.width;
|
|
|
|
var resized = false;
|
|
|
|
if (this.height !== height) {
|
|
resized = true;
|
|
this.height = height;
|
|
if (this.qListeners['scroll-height'] !== void 0) {
|
|
this.$emit('scroll-height', height);
|
|
}
|
|
this.__updateScrollbarWidth();
|
|
}
|
|
if (this.width !== width) {
|
|
resized = true;
|
|
this.width = width;
|
|
}
|
|
|
|
if (resized === true && this.qListeners.resize !== void 0) {
|
|
this.$emit('resize', { height: height, width: width });
|
|
}
|
|
},
|
|
|
|
__onContainerResize: function __onContainerResize (ref) {
|
|
var height = ref.height;
|
|
|
|
if (this.containerHeight !== height) {
|
|
this.containerHeight = height;
|
|
this.__updateScrollbarWidth();
|
|
}
|
|
},
|
|
|
|
__updateScrollbarWidth: function __updateScrollbarWidth () {
|
|
if (this.container === true) {
|
|
var width = this.height > this.containerHeight
|
|
? getScrollbarWidth()
|
|
: 0;
|
|
|
|
if (this.scrollbarWidth !== width) {
|
|
this.scrollbarWidth = width;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
var QMarkupTable = Vue.extend({
|
|
name: 'QMarkupTable',
|
|
|
|
mixins: [ DarkMixin, ListenersMixin ],
|
|
|
|
props: {
|
|
dense: Boolean,
|
|
flat: Boolean,
|
|
bordered: Boolean,
|
|
square: Boolean,
|
|
separator: {
|
|
type: String,
|
|
default: 'horizontal',
|
|
validator: function (v) { return ['horizontal', 'vertical', 'cell', 'none'].includes(v); }
|
|
},
|
|
wrapCells: Boolean
|
|
},
|
|
|
|
computed: {
|
|
classes: function classes () {
|
|
return "q-table--" + (this.separator) + "-separator" +
|
|
(this.isDark === true ? " q-table--dark q-table__card--dark q-dark" : '') +
|
|
(this.dense === true ? " q-table--dense" : '') +
|
|
(this.flat === true ? " q-table--flat" : '') +
|
|
(this.bordered === true ? " q-table--bordered" : '') +
|
|
(this.square === true ? " q-table--square" : '') +
|
|
(this.wrapCells === false ? " q-table--no-wrap" : '')
|
|
}
|
|
},
|
|
|
|
render: function render (h) {
|
|
return h('div', {
|
|
staticClass: 'q-markup-table q-table__container q-table__card',
|
|
class: this.classes,
|
|
on: Object.assign({}, this.qListeners)
|
|
}, [
|
|
h('table', { staticClass: 'q-table' }, slot(this, 'default'))
|
|
])
|
|
}
|
|
});
|
|
|
|
var QNoSsr = Vue.extend({
|
|
name: 'QNoSsr',
|
|
|
|
mixins: [ CanRenderMixin, TagMixin, ListenersMixin ],
|
|
|
|
props: {
|
|
placeholder: String
|
|
},
|
|
|
|
render: function render (h) {
|
|
var data = {
|
|
on: Object.assign({}, this.qListeners)
|
|
};
|
|
|
|
if (this.canRender === true) {
|
|
var node$1 = slot(this, 'default');
|
|
return node$1 === void 0
|
|
? node$1
|
|
: (node$1.length > 1 ? h(this.tag, data, node$1) : node$1[0])
|
|
}
|
|
|
|
data.staticClass = 'q-no-ssr-placeholder';
|
|
|
|
var node = slot(this, 'placeholder');
|
|
if (node !== void 0) {
|
|
return node.length > 1
|
|
? h(this.tag, data, node)
|
|
: node[0]
|
|
}
|
|
|
|
if (this.placeholder !== void 0) {
|
|
return h(this.tag, data, [
|
|
this.placeholder
|
|
])
|
|
}
|
|
}
|
|
});
|
|
|
|
var QRadio = Vue.extend({
|
|
name: 'QRadio',
|
|
|
|
mixins: [ DarkMixin, OptionSizeMixin, FormMixin, RefocusTargetMixin ],
|
|
|
|
props: {
|
|
value: {
|
|
required: true
|
|
},
|
|
val: {
|
|
required: true
|
|
},
|
|
|
|
label: String,
|
|
leftLabel: Boolean,
|
|
|
|
color: String,
|
|
keepColor: Boolean,
|
|
dense: Boolean,
|
|
|
|
disable: Boolean,
|
|
tabindex: [String, Number]
|
|
},
|
|
|
|
computed: {
|
|
isTrue: function isTrue () {
|
|
return this.value === this.val
|
|
},
|
|
|
|
classes: function classes () {
|
|
return 'q-radio cursor-pointer no-outline row inline no-wrap items-center' +
|
|
(this.disable === true ? ' disabled' : '') +
|
|
(this.isDark === true ? ' q-radio--dark' : '') +
|
|
(this.dense === true ? ' q-radio--dense' : '') +
|
|
(this.leftLabel === true ? ' reverse' : '')
|
|
},
|
|
|
|
innerClass: function innerClass () {
|
|
var color = this.color !== void 0 && (
|
|
this.keepColor === true ||
|
|
this.isTrue === true
|
|
)
|
|
? (" text-" + (this.color))
|
|
: '';
|
|
|
|
return ("q-radio__inner--" + (this.isTrue === true ? 'truthy' : 'falsy') + color)
|
|
},
|
|
|
|
computedTabindex: function computedTabindex () {
|
|
return this.disable === true ? -1 : this.tabindex || 0
|
|
},
|
|
|
|
formAttrs: function formAttrs () {
|
|
var prop = { type: 'radio' };
|
|
|
|
this.name !== void 0 && Object.assign(prop, {
|
|
name: this.name,
|
|
value: this.val
|
|
});
|
|
|
|
return prop
|
|
},
|
|
|
|
formDomProps: function formDomProps () {
|
|
if (this.name !== void 0 && this.isTrue === true) {
|
|
return { checked: true }
|
|
}
|
|
},
|
|
|
|
attrs: function attrs () {
|
|
var attrs = {
|
|
tabindex: this.computedTabindex,
|
|
role: 'radio',
|
|
'aria-label': this.label,
|
|
'aria-checked': this.isTrue === true ? 'true' : 'false'
|
|
};
|
|
|
|
if (this.disable === true) {
|
|
attrs['aria-disabled'] = 'true';
|
|
}
|
|
|
|
return attrs
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
set: function set (e) {
|
|
if (e !== void 0) {
|
|
stopAndPrevent(e);
|
|
this.__refocusTarget(e);
|
|
}
|
|
|
|
if (this.disable !== true && this.isTrue !== true) {
|
|
this.$emit('input', this.val, e);
|
|
}
|
|
}
|
|
},
|
|
|
|
render: function render (h) {
|
|
var this$1 = this;
|
|
|
|
var content = [
|
|
h('svg', {
|
|
staticClass: 'q-radio__bg absolute',
|
|
attrs: { focusable: 'false' /* needed for IE11 */, viewBox: '0 0 24 24', 'aria-hidden': 'true' }
|
|
}, [
|
|
h('path', {
|
|
attrs: {
|
|
d: 'M12,22a10,10 0 0 1 -10,-10a10,10 0 0 1 10,-10a10,10 0 0 1 10,10a10,10 0 0 1 -10,10m0,-22a12,12 0 0 0 -12,12a12,12 0 0 0 12,12a12,12 0 0 0 12,-12a12,12 0 0 0 -12,-12'
|
|
}
|
|
}),
|
|
|
|
h('path', {
|
|
staticClass: 'q-radio__check',
|
|
attrs: {
|
|
d: 'M12,6a6,6 0 0 0 -6,6a6,6 0 0 0 6,6a6,6 0 0 0 6,-6a6,6 0 0 0 -6,-6'
|
|
}
|
|
})
|
|
])
|
|
];
|
|
|
|
this.disable !== true && this.__injectFormInput(
|
|
content,
|
|
'unshift',
|
|
'q-radio__native q-ma-none q-pa-none invisible'
|
|
);
|
|
|
|
var child = [
|
|
h('div', {
|
|
staticClass: 'q-radio__inner relative-position no-pointer-events',
|
|
class: this.innerClass,
|
|
style: this.sizeStyle
|
|
}, content)
|
|
];
|
|
|
|
if (this.__refocusTargetEl !== void 0) {
|
|
child.push(this.__refocusTargetEl);
|
|
}
|
|
|
|
var label = this.label !== void 0
|
|
? mergeSlot([ this.label ], this, 'default')
|
|
: slot(this, 'default');
|
|
|
|
label !== void 0 && child.push(
|
|
h('div', {
|
|
staticClass: 'q-radio__label q-anchor--skip'
|
|
}, label)
|
|
);
|
|
|
|
return h('div', {
|
|
class: this.classes,
|
|
attrs: this.attrs,
|
|
on: cache(this, 'inpExt', {
|
|
click: this.set,
|
|
keydown: function (e) {
|
|
if (e.keyCode === 13 || e.keyCode === 32) {
|
|
stopAndPrevent(e);
|
|
}
|
|
},
|
|
keyup: function (e) {
|
|
if (e.keyCode === 13 || e.keyCode === 32) {
|
|
this$1.set(e);
|
|
}
|
|
}
|
|
})
|
|
}, child)
|
|
}
|
|
});
|
|
|
|
var QToggle = Vue.extend({
|
|
name: 'QToggle',
|
|
|
|
mixins: [ CheckboxMixin ],
|
|
|
|
props: {
|
|
icon: String,
|
|
checkedIcon: String,
|
|
uncheckedIcon: String,
|
|
indeterminateIcon: String,
|
|
|
|
iconColor: String
|
|
},
|
|
|
|
computed: {
|
|
computedIcon: function computedIcon () {
|
|
return (
|
|
this.isTrue === true
|
|
? this.checkedIcon
|
|
: (this.isIndeterminate === true ? this.indeterminateIcon : this.uncheckedIcon)
|
|
) || this.icon
|
|
},
|
|
|
|
computedIconColor: function computedIconColor () {
|
|
if (this.isTrue === true) {
|
|
return this.iconColor
|
|
}
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
__getInner: function __getInner (h) {
|
|
return [
|
|
h('div', { staticClass: 'q-toggle__track' }),
|
|
|
|
h('div', {
|
|
staticClass: 'q-toggle__thumb absolute flex flex-center no-wrap'
|
|
}, this.computedIcon !== void 0
|
|
? [
|
|
h(QIcon, {
|
|
props: {
|
|
name: this.computedIcon,
|
|
color: this.computedIconColor
|
|
}
|
|
})
|
|
]
|
|
: void 0
|
|
)
|
|
]
|
|
}
|
|
},
|
|
|
|
created: function created () {
|
|
this.type = 'toggle';
|
|
}
|
|
});
|
|
|
|
var components = {
|
|
radio: QRadio,
|
|
checkbox: QCheckbox,
|
|
toggle: QToggle
|
|
};
|
|
|
|
var typeValues = Object.keys(components);
|
|
|
|
var QOptionGroup = Vue.extend({
|
|
name: 'QOptionGroup',
|
|
|
|
mixins: [ DarkMixin, ListenersMixin ],
|
|
|
|
props: {
|
|
value: {
|
|
required: true
|
|
},
|
|
options: {
|
|
type: Array,
|
|
validator: function validator (opts) {
|
|
return opts.every(function (opt) { return 'value' in opt && 'label' in opt; })
|
|
}
|
|
},
|
|
|
|
name: String,
|
|
|
|
type: {
|
|
default: 'radio',
|
|
validator: function (v) { return typeValues.includes(v); }
|
|
},
|
|
|
|
color: String,
|
|
keepColor: Boolean,
|
|
dense: Boolean,
|
|
|
|
size: String,
|
|
|
|
leftLabel: Boolean,
|
|
inline: Boolean,
|
|
disable: Boolean
|
|
},
|
|
|
|
computed: {
|
|
component: function component () {
|
|
return components[this.type]
|
|
},
|
|
|
|
model: function model () {
|
|
return Array.isArray(this.value)
|
|
? this.value.slice()
|
|
: this.value
|
|
},
|
|
|
|
classes: function classes () {
|
|
return 'q-option-group q-gutter-x-sm' +
|
|
(this.inline === true ? ' q-option-group--inline' : '')
|
|
},
|
|
|
|
attrs: function attrs () {
|
|
if (this.type === 'radio') {
|
|
var attrs = {
|
|
role: 'radiogroup'
|
|
};
|
|
|
|
if (this.disable === true) {
|
|
attrs['aria-disabled'] = 'true';
|
|
}
|
|
|
|
return attrs
|
|
}
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
__update: function __update (value) {
|
|
this.$emit('input', value);
|
|
}
|
|
},
|
|
|
|
created: function created () {
|
|
var isArray = Array.isArray(this.value);
|
|
|
|
if (this.type === 'radio') {
|
|
if (isArray) {
|
|
console.error('q-option-group: model should not be array');
|
|
}
|
|
}
|
|
else if (isArray === false) {
|
|
console.error('q-option-group: model should be array in your case');
|
|
}
|
|
},
|
|
|
|
render: function render (h) {
|
|
var this$1 = this;
|
|
|
|
return h('div', {
|
|
class: this.classes,
|
|
attrs: this.attrs,
|
|
on: Object.assign({}, this.qListeners)
|
|
}, this.options.map(function (opt) { return h('div', [
|
|
h(this$1.component, {
|
|
props: {
|
|
value: this$1.value,
|
|
val: opt.value,
|
|
name: this$1.name || opt.name,
|
|
disable: this$1.disable || opt.disable,
|
|
label: opt.label,
|
|
leftLabel: this$1.leftLabel || opt.leftLabel,
|
|
color: opt.color || this$1.color,
|
|
checkedIcon: opt.checkedIcon,
|
|
uncheckedIcon: opt.uncheckedIcon,
|
|
dark: opt.dark || this$1.isDark,
|
|
size: opt.size || this$1.size,
|
|
dense: this$1.dense,
|
|
keepColor: opt.keepColor || this$1.keepColor
|
|
},
|
|
on: cache(this$1, 'inp', {
|
|
input: this$1.__update
|
|
})
|
|
})
|
|
]); }))
|
|
}
|
|
});
|
|
|
|
var QPage = Vue.extend({
|
|
name: 'QPage',
|
|
|
|
mixins: [ ListenersMixin ],
|
|
|
|
inject: {
|
|
pageContainer: {
|
|
default: function default$1 () {
|
|
console.error('QPage needs to be child of QPageContainer');
|
|
}
|
|
},
|
|
layout: {}
|
|
},
|
|
|
|
props: {
|
|
padding: Boolean,
|
|
styleFn: Function
|
|
},
|
|
|
|
computed: {
|
|
style: function style () {
|
|
var offset =
|
|
(this.layout.header.space === true ? this.layout.header.size : 0) +
|
|
(this.layout.footer.space === true ? this.layout.footer.size : 0);
|
|
|
|
if (typeof this.styleFn === 'function') {
|
|
var height = this.layout.container === true
|
|
? this.layout.containerHeight
|
|
: this.$q.screen.height;
|
|
|
|
return this.styleFn(offset, height)
|
|
}
|
|
|
|
return {
|
|
minHeight: this.layout.container === true
|
|
? (this.layout.containerHeight - offset) + 'px'
|
|
: (
|
|
this.$q.screen.height === 0
|
|
? ("calc(100vh - " + offset + "px)")
|
|
: (this.$q.screen.height - offset) + 'px'
|
|
)
|
|
}
|
|
},
|
|
|
|
classes: function classes () {
|
|
if (this.padding === true) {
|
|
return 'q-layout-padding'
|
|
}
|
|
}
|
|
},
|
|
|
|
render: function render (h) {
|
|
return h('main', {
|
|
staticClass: 'q-page',
|
|
style: this.style,
|
|
class: this.classes,
|
|
on: Object.assign({}, this.qListeners)
|
|
}, slot(this, 'default'))
|
|
}
|
|
});
|
|
|
|
var QPageContainer = Vue.extend({
|
|
name: 'QPageContainer',
|
|
|
|
mixins: [ ListenersMixin ],
|
|
|
|
inject: {
|
|
layout: {
|
|
default: function default$1 () {
|
|
console.error('QPageContainer needs to be child of QLayout');
|
|
}
|
|
}
|
|
},
|
|
|
|
provide: {
|
|
pageContainer: true
|
|
},
|
|
|
|
computed: {
|
|
style: function style () {
|
|
var css = {};
|
|
|
|
if (this.layout.header.space === true) {
|
|
css.paddingTop = (this.layout.header.size) + "px";
|
|
}
|
|
if (this.layout.right.space === true) {
|
|
css[("padding" + (this.$q.lang.rtl === true ? 'Left' : 'Right'))] = (this.layout.right.size) + "px";
|
|
}
|
|
if (this.layout.footer.space === true) {
|
|
css.paddingBottom = (this.layout.footer.size) + "px";
|
|
}
|
|
if (this.layout.left.space === true) {
|
|
css[("padding" + (this.$q.lang.rtl === true ? 'Right' : 'Left'))] = (this.layout.left.size) + "px";
|
|
}
|
|
|
|
return css
|
|
}
|
|
},
|
|
|
|
render: function render (h) {
|
|
return h('div', {
|
|
staticClass: 'q-page-container',
|
|
style: this.style,
|
|
on: Object.assign({}, this.qListeners)
|
|
}, slot(this, 'default'))
|
|
}
|
|
});
|
|
|
|
var QPageSticky = Vue.extend({
|
|
name: 'QPageSticky',
|
|
|
|
mixins: [ ListenersMixin ],
|
|
|
|
inject: {
|
|
layout: {
|
|
default: function default$1 () {
|
|
console.error('QPageSticky needs to be child of QLayout');
|
|
}
|
|
}
|
|
},
|
|
|
|
props: {
|
|
position: {
|
|
type: String,
|
|
default: 'bottom-right',
|
|
validator: function (v) { return [
|
|
'top-right', 'top-left',
|
|
'bottom-right', 'bottom-left',
|
|
'top', 'right', 'bottom', 'left'
|
|
].includes(v); }
|
|
},
|
|
offset: {
|
|
type: Array,
|
|
validator: function (v) { return v.length === 2; }
|
|
},
|
|
expand: Boolean
|
|
},
|
|
|
|
computed: {
|
|
attach: function attach () {
|
|
var pos = this.position;
|
|
|
|
return {
|
|
top: pos.indexOf('top') > -1,
|
|
right: pos.indexOf('right') > -1,
|
|
bottom: pos.indexOf('bottom') > -1,
|
|
left: pos.indexOf('left') > -1,
|
|
vertical: pos === 'top' || pos === 'bottom',
|
|
horizontal: pos === 'left' || pos === 'right'
|
|
}
|
|
},
|
|
|
|
top: function top () {
|
|
return this.layout.header.offset
|
|
},
|
|
|
|
right: function right () {
|
|
return this.layout.right.offset
|
|
},
|
|
|
|
bottom: function bottom () {
|
|
return this.layout.footer.offset
|
|
},
|
|
|
|
left: function left () {
|
|
return this.layout.left.offset
|
|
},
|
|
|
|
style: function style () {
|
|
var
|
|
posX = 0,
|
|
posY = 0;
|
|
|
|
var
|
|
attach = this.attach,
|
|
dir = this.$q.lang.rtl === true ? -1 : 1;
|
|
|
|
if (attach.top === true && this.top !== 0) {
|
|
posY = (this.top) + "px";
|
|
}
|
|
else if (attach.bottom === true && this.bottom !== 0) {
|
|
posY = (-this.bottom) + "px";
|
|
}
|
|
|
|
if (attach.left === true && this.left !== 0) {
|
|
posX = (dir * this.left) + "px";
|
|
}
|
|
else if (attach.right === true && this.right !== 0) {
|
|
posX = (-dir * this.right) + "px";
|
|
}
|
|
|
|
var css = { transform: ("translate(" + posX + ", " + posY + ")") };
|
|
|
|
if (this.offset) {
|
|
css.margin = (this.offset[1]) + "px " + (this.offset[0]) + "px";
|
|
}
|
|
|
|
if (attach.vertical === true) {
|
|
if (this.left !== 0) {
|
|
css[this.$q.lang.rtl === true ? 'right' : 'left'] = (this.left) + "px";
|
|
}
|
|
if (this.right !== 0) {
|
|
css[this.$q.lang.rtl === true ? 'left' : 'right'] = (this.right) + "px";
|
|
}
|
|
}
|
|
else if (attach.horizontal === true) {
|
|
if (this.top !== 0) {
|
|
css.top = (this.top) + "px";
|
|
}
|
|
if (this.bottom !== 0) {
|
|
css.bottom = (this.bottom) + "px";
|
|
}
|
|
}
|
|
|
|
return css
|
|
},
|
|
|
|
classes: function classes () {
|
|
return ("fixed-" + (this.position) + " q-page-sticky--" + (this.expand === true ? 'expand' : 'shrink'))
|
|
}
|
|
},
|
|
|
|
render: function render (h) {
|
|
var content = slot(this, 'default');
|
|
|
|
return h('div', {
|
|
staticClass: 'q-page-sticky row flex-center',
|
|
class: this.classes,
|
|
style: this.style,
|
|
on: Object.assign({}, this.qListeners)
|
|
},
|
|
this.expand === true
|
|
? content
|
|
: [ h('div', content) ]
|
|
)
|
|
}
|
|
});
|
|
|
|
var QPageScroller = Vue.extend({
|
|
name: 'QPageScroller',
|
|
|
|
mixins: [ QPageSticky ],
|
|
|
|
props: {
|
|
scrollOffset: {
|
|
type: Number,
|
|
default: 1000
|
|
},
|
|
|
|
reverse: Boolean,
|
|
|
|
duration: {
|
|
type: Number,
|
|
default: 300
|
|
},
|
|
|
|
offset: {
|
|
default: function () { return [18, 18]; }
|
|
}
|
|
},
|
|
|
|
inject: {
|
|
layout: {
|
|
default: function default$1 () {
|
|
console.error('QPageScroller needs to be used within a QLayout');
|
|
}
|
|
}
|
|
},
|
|
|
|
data: function data () {
|
|
return {
|
|
showing: this.__isVisible()
|
|
}
|
|
},
|
|
|
|
computed: {
|
|
height: function height () {
|
|
return this.layout.container === true
|
|
? this.layout.containerHeight
|
|
: this.layout.height
|
|
},
|
|
|
|
onEvents: function onEvents () {
|
|
return Object.assign({}, this.qListeners,
|
|
{click: this.__onClick})
|
|
}
|
|
},
|
|
|
|
watch: {
|
|
'layout.scroll.position': function layout_scroll_position () {
|
|
this.__updateVisibility();
|
|
},
|
|
|
|
reverse: {
|
|
handler: function handler (val) {
|
|
if (val === true) {
|
|
if (this.heightWatcher === void 0) {
|
|
this.heightWatcher = this.$watch('height', this.__updateVisibility);
|
|
}
|
|
}
|
|
else if (this.heightWatcher !== void 0) {
|
|
this.__cleanup();
|
|
}
|
|
},
|
|
immediate: true
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
__isVisible: function __isVisible () {
|
|
return this.reverse === true
|
|
? this.height - this.layout.scroll.position > this.scrollOffset
|
|
: this.layout.scroll.position > this.scrollOffset
|
|
},
|
|
|
|
__onClick: function __onClick (e) {
|
|
var target = this.layout.container === true
|
|
? getScrollTarget(this.$el)
|
|
: getScrollTarget(this.layout.$el);
|
|
|
|
setScrollPosition(target, this.reverse === true ? this.layout.height : 0, this.duration);
|
|
this.$emit('click', e);
|
|
},
|
|
|
|
__updateVisibility: function __updateVisibility () {
|
|
var newVal = this.__isVisible();
|
|
if (this.showing !== newVal) {
|
|
this.showing = newVal;
|
|
}
|
|
},
|
|
|
|
__cleanup: function __cleanup () {
|
|
this.heightWatcher();
|
|
this.heightWatcher = void 0;
|
|
}
|
|
},
|
|
|
|
render: function render (h) {
|
|
return h('transition', {
|
|
props: { name: 'q-transition--fade' }
|
|
},
|
|
this.showing === true
|
|
? [
|
|
h('div', {
|
|
staticClass: 'q-page-scroller',
|
|
on: this.onEvents
|
|
}, [
|
|
QPageSticky.options.render.call(this, h)
|
|
])
|
|
]
|
|
: null
|
|
)
|
|
},
|
|
|
|
beforeDestroy: function beforeDestroy () {
|
|
this.heightWatcher !== void 0 && this.__cleanup();
|
|
}
|
|
});
|
|
|
|
var QPagination = Vue.extend({
|
|
name: 'QPagination',
|
|
|
|
mixins: [ DarkMixin, ListenersMixin ],
|
|
|
|
props: {
|
|
value: {
|
|
type: Number,
|
|
required: true
|
|
},
|
|
min: {
|
|
type: Number,
|
|
default: 1
|
|
},
|
|
max: {
|
|
type: Number,
|
|
required: true
|
|
},
|
|
|
|
color: {
|
|
type: String,
|
|
default: 'primary'
|
|
},
|
|
textColor: String,
|
|
|
|
inputStyle: [Array, String, Object],
|
|
inputClass: [Array, String, Object],
|
|
|
|
size: String,
|
|
|
|
disable: Boolean,
|
|
|
|
input: Boolean,
|
|
|
|
iconPrev: String,
|
|
iconNext: String,
|
|
iconFirst: String,
|
|
iconLast: String,
|
|
|
|
toFn: Function,
|
|
|
|
boundaryLinks: {
|
|
type: Boolean,
|
|
default: null
|
|
},
|
|
boundaryNumbers: {
|
|
type: Boolean,
|
|
default: null
|
|
},
|
|
directionLinks: {
|
|
type: Boolean,
|
|
default: null
|
|
},
|
|
ellipses: {
|
|
type: Boolean,
|
|
default: null
|
|
},
|
|
maxPages: {
|
|
type: Number,
|
|
default: 0,
|
|
validator: function (v) { return v >= 0; }
|
|
},
|
|
|
|
ripple: {
|
|
type: [Boolean, Object],
|
|
default: null
|
|
}
|
|
},
|
|
|
|
data: function data () {
|
|
return {
|
|
newPage: null
|
|
}
|
|
},
|
|
|
|
watch: {
|
|
min: function min () {
|
|
this.model = this.value;
|
|
},
|
|
|
|
max: function max () {
|
|
this.model = this.value;
|
|
}
|
|
},
|
|
|
|
computed: {
|
|
model: {
|
|
get: function get () {
|
|
return this.value
|
|
},
|
|
set: function set (val) {
|
|
val = parseInt(val, 10);
|
|
if (this.disable || isNaN(val) || val === 0) {
|
|
return
|
|
}
|
|
var value = between(val, this.min, this.max);
|
|
this.$emit('input', value);
|
|
}
|
|
},
|
|
|
|
inputPlaceholder: function inputPlaceholder () {
|
|
return this.model + ' / ' + this.max
|
|
},
|
|
|
|
__boundaryLinks: function __boundaryLinks () {
|
|
return this.__getBool(this.boundaryLinks, this.input)
|
|
},
|
|
|
|
__boundaryNumbers: function __boundaryNumbers () {
|
|
return this.__getBool(this.boundaryNumbers, !this.input)
|
|
},
|
|
|
|
__directionLinks: function __directionLinks () {
|
|
return this.__getBool(this.directionLinks, this.input)
|
|
},
|
|
|
|
__ellipses: function __ellipses () {
|
|
return this.__getBool(this.ellipses, !this.input)
|
|
},
|
|
|
|
icons: function icons () {
|
|
var ico = [
|
|
this.iconFirst || this.$q.iconSet.pagination.first,
|
|
this.iconPrev || this.$q.iconSet.pagination.prev,
|
|
this.iconNext || this.$q.iconSet.pagination.next,
|
|
this.iconLast || this.$q.iconSet.pagination.last
|
|
];
|
|
return this.$q.lang.rtl === true ? ico.reverse() : ico
|
|
},
|
|
|
|
attrs: function attrs () {
|
|
if (this.disable === true) {
|
|
return {
|
|
'aria-disabled': 'true'
|
|
}
|
|
}
|
|
},
|
|
|
|
btnProps: function btnProps () {
|
|
return {
|
|
color: this.color,
|
|
flat: true,
|
|
size: this.size,
|
|
ripple: this.ripple !== null
|
|
? this.ripple
|
|
: true
|
|
}
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
set: function set (value) {
|
|
this.model = value;
|
|
},
|
|
|
|
setByOffset: function setByOffset (offset) {
|
|
this.model = this.model + offset;
|
|
},
|
|
|
|
__update: function __update () {
|
|
this.model = this.newPage;
|
|
this.newPage = null;
|
|
},
|
|
|
|
__getBool: function __getBool (val, otherwise) {
|
|
return [true, false].includes(val)
|
|
? val
|
|
: otherwise
|
|
},
|
|
|
|
__getBtn: function __getBtn (h, data, props, page) {
|
|
var this$1 = this;
|
|
|
|
data.props = Object.assign({}, this.btnProps,
|
|
props);
|
|
|
|
if (page !== void 0) {
|
|
if (this.toFn !== void 0) {
|
|
data.props.to = this.toFn(page);
|
|
}
|
|
else {
|
|
data.on = { click: function () { return this$1.set(page); } };
|
|
}
|
|
}
|
|
|
|
return h(QBtn, data)
|
|
}
|
|
},
|
|
|
|
render: function render (h) {
|
|
var this$1 = this;
|
|
|
|
var
|
|
contentStart = [],
|
|
contentEnd = [],
|
|
contentMiddle = [];
|
|
|
|
if (this.__boundaryLinks) {
|
|
contentStart.push(this.__getBtn(h, {
|
|
key: 'bls'
|
|
}, {
|
|
disable: this.disable || this.value <= this.min,
|
|
icon: this.icons[0]
|
|
}, this.min));
|
|
contentEnd.unshift(this.__getBtn(h, {
|
|
key: 'ble'
|
|
}, {
|
|
disable: this.disable || this.value >= this.max,
|
|
icon: this.icons[3]
|
|
}, this.max));
|
|
}
|
|
|
|
if (this.__directionLinks) {
|
|
contentStart.push(this.__getBtn(h, {
|
|
key: 'bdp'
|
|
}, {
|
|
disable: this.disable || this.value <= this.min,
|
|
icon: this.icons[1]
|
|
}, this.value - 1));
|
|
contentEnd.unshift(this.__getBtn(h, {
|
|
key: 'bdn'
|
|
}, {
|
|
disable: this.disable || this.value >= this.max,
|
|
icon: this.icons[2]
|
|
}, this.value + 1));
|
|
}
|
|
|
|
if (this.input === true) {
|
|
contentMiddle.push(h(QInput, {
|
|
staticClass: 'inline',
|
|
style: {
|
|
width: ((this.inputPlaceholder.length / 1.5) + "em")
|
|
},
|
|
props: {
|
|
type: 'number',
|
|
dense: true,
|
|
value: this.newPage,
|
|
disable: this.disable,
|
|
dark: this.isDark,
|
|
borderless: true,
|
|
inputClass: this.inputClass,
|
|
inputStyle: this.inputStyle
|
|
},
|
|
attrs: {
|
|
placeholder: this.inputPlaceholder,
|
|
min: this.min,
|
|
max: this.max
|
|
},
|
|
on: cache(this, 'inp', {
|
|
input: function (value) { this$1.newPage = value; },
|
|
keyup: function (e) { isKeyCode(e, 13) === true && this$1.__update(); },
|
|
blur: this.__update
|
|
})
|
|
}));
|
|
}
|
|
else { // is type select
|
|
var
|
|
maxPages = Math.max(
|
|
this.maxPages,
|
|
1 + (this.__ellipses ? 2 : 0) + (this.__boundaryNumbers ? 2 : 0)
|
|
),
|
|
pgFrom = this.min,
|
|
pgTo = this.max,
|
|
ellipsesStart = false,
|
|
ellipsesEnd = false,
|
|
boundaryStart = false,
|
|
boundaryEnd = false;
|
|
|
|
if (this.maxPages && maxPages < (this.max - this.min + 1)) {
|
|
maxPages = 1 + Math.floor(maxPages / 2) * 2;
|
|
pgFrom = Math.max(this.min, Math.min(this.max - maxPages + 1, this.value - Math.floor(maxPages / 2)));
|
|
pgTo = Math.min(this.max, pgFrom + maxPages - 1);
|
|
if (this.__boundaryNumbers) {
|
|
boundaryStart = true;
|
|
pgFrom += 1;
|
|
}
|
|
if (this.__ellipses && pgFrom > (this.min + (this.__boundaryNumbers ? 1 : 0))) {
|
|
ellipsesStart = true;
|
|
pgFrom += 1;
|
|
}
|
|
if (this.__boundaryNumbers) {
|
|
boundaryEnd = true;
|
|
pgTo -= 1;
|
|
}
|
|
if (this.__ellipses && pgTo < (this.max - (this.__boundaryNumbers ? 1 : 0))) {
|
|
ellipsesEnd = true;
|
|
pgTo -= 1;
|
|
}
|
|
}
|
|
var style = {
|
|
minWidth: ((Math.max(2, String(this.max).length)) + "em")
|
|
};
|
|
if (boundaryStart) {
|
|
var active = this.min === this.value;
|
|
contentStart.push(this.__getBtn(h, {
|
|
key: 'bns',
|
|
style: style
|
|
}, {
|
|
disable: this.disable,
|
|
flat: !active,
|
|
textColor: active ? this.textColor : null,
|
|
label: this.min
|
|
}, this.min));
|
|
}
|
|
if (boundaryEnd) {
|
|
var active$1 = this.max === this.value;
|
|
contentEnd.unshift(this.__getBtn(h, {
|
|
key: 'bne',
|
|
style: style
|
|
}, {
|
|
disable: this.disable,
|
|
flat: !active$1,
|
|
textColor: active$1 ? this.textColor : null,
|
|
label: this.max
|
|
}, this.max));
|
|
}
|
|
if (ellipsesStart) {
|
|
contentStart.push(this.__getBtn(h, {
|
|
key: 'bes',
|
|
style: style
|
|
}, {
|
|
disable: this.disable,
|
|
label: '…',
|
|
ripple: false
|
|
}, pgFrom - 1));
|
|
}
|
|
if (ellipsesEnd) {
|
|
contentEnd.unshift(this.__getBtn(h, {
|
|
key: 'bee',
|
|
style: style
|
|
}, {
|
|
disable: this.disable,
|
|
label: '…',
|
|
ripple: false
|
|
}, pgTo + 1));
|
|
}
|
|
for (var i = pgFrom; i <= pgTo; i++) {
|
|
var active$2 = i === this.value;
|
|
contentMiddle.push(this.__getBtn(h, {
|
|
key: ("bpg" + i),
|
|
style: style
|
|
}, {
|
|
disable: this.disable,
|
|
flat: !active$2,
|
|
textColor: active$2 ? this.textColor : null,
|
|
label: i
|
|
}, i));
|
|
}
|
|
}
|
|
|
|
return h('div', {
|
|
staticClass: 'q-pagination row no-wrap items-center',
|
|
class: { disabled: this.disable },
|
|
attrs: this.attrs,
|
|
on: Object.assign({}, this.qListeners)
|
|
}, [
|
|
contentStart,
|
|
|
|
h('div', {
|
|
staticClass: 'row justify-center',
|
|
on: this.input === true
|
|
? cache(this, 'stop', { input: stop })
|
|
: null
|
|
}, [
|
|
contentMiddle
|
|
]),
|
|
|
|
contentEnd
|
|
])
|
|
}
|
|
});
|
|
|
|
function frameDebounce (fn) {
|
|
var wait = false, frame, callArgs;
|
|
|
|
function debounced (/* ...args */) {
|
|
var this$1 = this;
|
|
|
|
callArgs = arguments;
|
|
if (wait === true) { return }
|
|
|
|
wait = true;
|
|
frame = requestAnimationFrame(function () {
|
|
fn.apply(this$1, callArgs);
|
|
callArgs = void 0;
|
|
wait = false;
|
|
});
|
|
}
|
|
|
|
debounced.cancel = function () {
|
|
window.cancelAnimationFrame(frame);
|
|
wait = false;
|
|
};
|
|
|
|
return debounced
|
|
}
|
|
|
|
var passive$2 = listenOpts.passive;
|
|
|
|
var QParallax = Vue.extend({
|
|
name: 'QParallax',
|
|
|
|
mixins: [ ListenersMixin ],
|
|
|
|
props: {
|
|
src: String,
|
|
height: {
|
|
type: Number,
|
|
default: 500
|
|
},
|
|
speed: {
|
|
type: Number,
|
|
default: 1,
|
|
validator: function (v) { return v >= 0 && v <= 1; }
|
|
},
|
|
|
|
scrollTarget: {
|
|
default: void 0
|
|
}
|
|
},
|
|
|
|
data: function data () {
|
|
return {
|
|
scrolling: false,
|
|
percentScrolled: 0
|
|
}
|
|
},
|
|
|
|
watch: {
|
|
height: function height () {
|
|
this.working === true && this.__updatePos();
|
|
},
|
|
|
|
scrollTarget: function scrollTarget () {
|
|
if (this.working === true) {
|
|
this.__stop();
|
|
this.__start();
|
|
}
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
__update: function __update (percentage) {
|
|
this.percentScrolled = percentage;
|
|
this.qListeners.scroll !== void 0 && this.$emit('scroll', percentage);
|
|
},
|
|
|
|
__updatePos: function __updatePos () {
|
|
var containerTop, containerHeight, containerBottom;
|
|
|
|
if (this.__scrollTarget === window) {
|
|
containerTop = 0;
|
|
containerHeight = window.innerHeight;
|
|
containerBottom = containerHeight;
|
|
}
|
|
else {
|
|
containerTop = offset(this.__scrollTarget).top;
|
|
containerHeight = height(this.__scrollTarget);
|
|
containerBottom = containerTop + containerHeight;
|
|
}
|
|
|
|
var top = offset(this.$el).top;
|
|
var bottom = top + this.height;
|
|
|
|
if (this.observer !== void 0 || (bottom > containerTop && top < containerBottom)) {
|
|
var percent = (containerBottom - top) / (this.height + containerHeight);
|
|
this.__setPos((this.mediaHeight - this.height) * percent * this.speed);
|
|
this.__update(percent);
|
|
}
|
|
},
|
|
|
|
__setPos: function __setPos (offset) {
|
|
// apply it immediately without any delay
|
|
this.media.style.transform = "translate3D(-50%," + (Math.round(offset)) + "px, 0)";
|
|
},
|
|
|
|
__onResize: function __onResize () {
|
|
this.mediaHeight = this.media.naturalHeight || this.media.videoHeight || height(this.media);
|
|
this.working === true && this.__updatePos();
|
|
},
|
|
|
|
__start: function __start () {
|
|
this.working = true;
|
|
this.__scrollTarget = getScrollTarget(this.$el, this.scrollTarget);
|
|
this.__scrollTarget.addEventListener('scroll', this.__updatePos, passive$2);
|
|
window.addEventListener('resize', this.__resizeHandler, passive$2);
|
|
this.__updatePos();
|
|
},
|
|
|
|
__stop: function __stop () {
|
|
if (this.working === true) {
|
|
this.working = false;
|
|
this.__scrollTarget.removeEventListener('scroll', this.__updatePos, passive$2);
|
|
window.removeEventListener('resize', this.__resizeHandler, passive$2);
|
|
this.__scrollTarget = void 0;
|
|
}
|
|
}
|
|
},
|
|
|
|
render: function render (h) {
|
|
return h('div', {
|
|
staticClass: 'q-parallax',
|
|
style: { height: ((this.height) + "px") },
|
|
on: Object.assign({}, this.qListeners)
|
|
}, [
|
|
h('div', {
|
|
ref: 'mediaParent',
|
|
staticClass: 'q-parallax__media absolute-full'
|
|
}, this.$scopedSlots.media !== void 0 ? this.$scopedSlots.media() : [
|
|
h('img', {
|
|
ref: 'media',
|
|
attrs: {
|
|
src: this.src
|
|
}
|
|
})
|
|
]),
|
|
|
|
h(
|
|
'div',
|
|
{ staticClass: 'q-parallax__content absolute-full column flex-center' },
|
|
this.$scopedSlots.content !== void 0
|
|
? this.$scopedSlots.content({ percentScrolled: this.percentScrolled })
|
|
: slot(this, 'default')
|
|
)
|
|
])
|
|
},
|
|
|
|
mounted: function mounted () {
|
|
var this$1 = this;
|
|
|
|
this.__setPos = frameDebounce(this.__setPos);
|
|
this.__update = frameDebounce(this.__update);
|
|
this.__resizeHandler = frameDebounce(this.__onResize);
|
|
|
|
this.media = this.$scopedSlots.media !== void 0
|
|
? this.$refs.mediaParent.children[0]
|
|
: this.$refs.media;
|
|
|
|
this.media.onload = this.media.onloadstart = this.media.loadedmetadata = this.__onResize;
|
|
this.__onResize();
|
|
this.media.style.display = 'initial';
|
|
|
|
if (window.IntersectionObserver !== void 0) {
|
|
this.observer = new IntersectionObserver(function (entries) {
|
|
this$1[entries[0].isIntersecting === true ? '__start' : '__stop']();
|
|
});
|
|
|
|
this.observer.observe(this.$el);
|
|
}
|
|
else {
|
|
this.__start();
|
|
}
|
|
},
|
|
|
|
beforeDestroy: function beforeDestroy () {
|
|
this.__stop();
|
|
this.observer !== void 0 && this.observer.disconnect();
|
|
this.media.onload = this.media.onloadstart = this.media.loadedmetadata = null;
|
|
}
|
|
});
|
|
|
|
function clone$1 (data) {
|
|
var s = JSON.stringify(data);
|
|
if (s) {
|
|
return JSON.parse(s)
|
|
}
|
|
}
|
|
|
|
var QPopupEdit = Vue.extend({
|
|
name: 'QPopupEdit',
|
|
|
|
mixins: [ AttrsMixin ],
|
|
|
|
props: {
|
|
value: {
|
|
required: true
|
|
},
|
|
title: String,
|
|
buttons: Boolean,
|
|
labelSet: String,
|
|
labelCancel: String,
|
|
|
|
color: {
|
|
type: String,
|
|
default: 'primary'
|
|
},
|
|
validate: {
|
|
type: Function,
|
|
default: function () { return true; }
|
|
},
|
|
|
|
autoSave: Boolean,
|
|
|
|
/* menu props overrides */
|
|
cover: {
|
|
type: Boolean,
|
|
default: true
|
|
},
|
|
contentClass: String,
|
|
/* end of menu props */
|
|
|
|
disable: Boolean
|
|
},
|
|
|
|
data: function data () {
|
|
return {
|
|
initialValue: ''
|
|
}
|
|
},
|
|
|
|
computed: {
|
|
classes: function classes () {
|
|
return 'q-popup-edit' +
|
|
(this.contentClass !== void 0 ? (" " + (this.contentClass)) : '')
|
|
},
|
|
|
|
defaultSlotScope: function defaultSlotScope () {
|
|
return {
|
|
initialValue: this.initialValue,
|
|
value: this.value,
|
|
emitValue: this.__emitValue,
|
|
validate: this.validate,
|
|
set: this.set,
|
|
cancel: this.cancel
|
|
}
|
|
},
|
|
|
|
menuProps: function menuProps () {
|
|
return Object.assign({}, this.qAttrs,
|
|
{cover: this.cover,
|
|
contentClass: this.classes})
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
set: function set () {
|
|
if (this.__hasChanged() === true) {
|
|
if (this.validate(this.value) === false) {
|
|
return
|
|
}
|
|
this.$emit('save', this.value, this.initialValue);
|
|
}
|
|
this.__close();
|
|
},
|
|
|
|
cancel: function cancel () {
|
|
if (this.__hasChanged() === true) {
|
|
this.$emit('input', this.initialValue);
|
|
this.$emit('cancel', this.value, this.initialValue);
|
|
}
|
|
this.__close();
|
|
},
|
|
|
|
show: function show (e) {
|
|
this.$refs.menu !== void 0 && this.$refs.menu.show(e);
|
|
},
|
|
|
|
hide: function hide (e) {
|
|
this.$refs.menu !== void 0 && this.$refs.menu.hide(e);
|
|
},
|
|
|
|
__hasChanged: function __hasChanged () {
|
|
return isDeepEqual(this.value, this.initialValue) === false
|
|
},
|
|
|
|
__emitValue: function __emitValue (val) {
|
|
if (this.disable !== true) {
|
|
this.$emit('input', val);
|
|
}
|
|
},
|
|
|
|
__close: function __close () {
|
|
this.validated = true;
|
|
this.$refs.menu.showing === true && this.$refs.menu.hide();
|
|
},
|
|
|
|
__reposition: function __reposition () {
|
|
var this$1 = this;
|
|
|
|
this.$nextTick(function () {
|
|
this$1.$refs.menu.updatePosition();
|
|
});
|
|
},
|
|
|
|
__getContent: function __getContent (h) {
|
|
var
|
|
title = slot(this, 'title', this.title),
|
|
child = this.$scopedSlots.default === void 0
|
|
? []
|
|
: this.$scopedSlots.default(this.defaultSlotScope).slice();
|
|
|
|
title && child.unshift(
|
|
h('div', { staticClass: 'q-dialog__title q-mt-sm q-mb-sm' }, [ title ])
|
|
);
|
|
|
|
this.buttons === true && child.push(
|
|
h('div', { staticClass: 'q-popup-edit__buttons row justify-center no-wrap' }, [
|
|
h(QBtn, {
|
|
props: {
|
|
flat: true,
|
|
color: this.color,
|
|
label: this.labelCancel || this.$q.lang.label.cancel
|
|
},
|
|
on: cache(this, 'cancel', { click: this.cancel })
|
|
}),
|
|
h(QBtn, {
|
|
props: {
|
|
flat: true,
|
|
color: this.color,
|
|
label: this.labelSet || this.$q.lang.label.set
|
|
},
|
|
on: cache(this, 'ok', { click: this.set })
|
|
})
|
|
])
|
|
);
|
|
|
|
return child
|
|
}
|
|
},
|
|
|
|
render: function render (h) {
|
|
var this$1 = this;
|
|
|
|
if (this.disable === true) { return }
|
|
|
|
return h(QMenu, {
|
|
ref: 'menu',
|
|
props: this.menuProps,
|
|
on: cache(this, 'menu', {
|
|
'before-show': function () {
|
|
this$1.validated = false;
|
|
this$1.initialValue = clone$1(this$1.value);
|
|
this$1.watcher = this$1.$watch('value', this$1.__reposition);
|
|
this$1.$emit('before-show');
|
|
},
|
|
show: function () {
|
|
this$1.$emit('show');
|
|
},
|
|
'escape-key': this.cancel,
|
|
'before-hide': function () {
|
|
this$1.watcher();
|
|
|
|
if (this$1.validated === false && this$1.__hasChanged() === true) {
|
|
if (this$1.autoSave === true && this$1.validate(this$1.value) === true) {
|
|
this$1.$emit('save', this$1.value, this$1.initialValue);
|
|
}
|
|
else {
|
|
this$1.$emit('cancel', this$1.value, this$1.initialValue);
|
|
this$1.$emit('input', this$1.initialValue);
|
|
}
|
|
}
|
|
|
|
this$1.$emit('before-hide');
|
|
},
|
|
hide: function () {
|
|
this$1.$emit('hide');
|
|
},
|
|
keyup: function (e) {
|
|
isKeyCode(e, 13) === true && this$1.set();
|
|
}
|
|
})
|
|
}, this.__getContent(h))
|
|
}
|
|
});
|
|
|
|
var QPopupProxy = Vue.extend({
|
|
name: 'QPopupProxy',
|
|
|
|
mixins: [ AttrsMixin, ListenersMixin, AnchorMixin ],
|
|
|
|
props: {
|
|
breakpoint: {
|
|
type: [String, Number],
|
|
default: 450
|
|
}
|
|
},
|
|
|
|
data: function data () {
|
|
var breakpoint = parseInt(this.breakpoint, 10);
|
|
return {
|
|
type: this.$q.screen.width < breakpoint || this.$q.screen.height < breakpoint
|
|
? 'dialog'
|
|
: 'menu'
|
|
}
|
|
},
|
|
|
|
computed: {
|
|
parsedBreakpoint: function parsedBreakpoint () {
|
|
return parseInt(this.breakpoint, 10)
|
|
},
|
|
|
|
onEvents: function onEvents () {
|
|
return Object.assign({}, this.qListeners,
|
|
{hide: this.__onHide})
|
|
}
|
|
},
|
|
|
|
watch: {
|
|
'$q.screen.width': function $q_screen_width (width) {
|
|
if (this.$refs.popup.showing !== true) {
|
|
this.__updateType(width, this.$q.screen.height, this.parsedBreakpoint);
|
|
}
|
|
},
|
|
|
|
'$q.screen.height': function $q_screen_height (height) {
|
|
if (this.$refs.popup.showing !== true) {
|
|
this.__updateType(this.$q.screen.width, height, this.parsedBreakpoint);
|
|
}
|
|
},
|
|
|
|
breakpoint: function breakpoint (breakpoint$1) {
|
|
if (this.$refs.popup.showing !== true) {
|
|
this.__updateType(this.$q.screen.width, this.$q.screen.height, parseInt(breakpoint$1, 10));
|
|
}
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
toggle: function toggle (evt) {
|
|
this.$refs.popup.toggle(evt);
|
|
},
|
|
|
|
show: function show (evt) {
|
|
this.$refs.popup.show(evt);
|
|
},
|
|
|
|
hide: function hide (evt) {
|
|
this.$refs.popup.hide(evt);
|
|
},
|
|
|
|
__onHide: function __onHide (evt) {
|
|
this.__updateType(this.$q.screen.width, this.$q.screen.height, this.parsedBreakpoint);
|
|
this.$emit('hide', evt);
|
|
},
|
|
|
|
__updateType: function __updateType (width, height, breakpoint) {
|
|
var type = width < breakpoint || height < breakpoint
|
|
? 'dialog'
|
|
: 'menu';
|
|
|
|
if (this.type !== type) {
|
|
this.type = type;
|
|
}
|
|
}
|
|
},
|
|
|
|
render: function render (h) {
|
|
var def = slot(this, 'default');
|
|
|
|
var props = (
|
|
this.type === 'menu' &&
|
|
def !== void 0 &&
|
|
def[0] !== void 0 &&
|
|
def[0].componentOptions !== void 0 &&
|
|
def[0].componentOptions.Ctor !== void 0 &&
|
|
def[0].componentOptions.Ctor.sealedOptions !== void 0 &&
|
|
['QDate', 'QTime', 'QCarousel', 'QColor'].includes(
|
|
def[0].componentOptions.Ctor.sealedOptions.name
|
|
)
|
|
) ? { cover: true, maxHeight: '99vh' } : {};
|
|
|
|
var data = {
|
|
ref: 'popup',
|
|
props: Object.assign({}, props, this.qAttrs),
|
|
on: this.onEvents
|
|
};
|
|
|
|
var component;
|
|
|
|
if (this.type === 'dialog') {
|
|
component = QDialog;
|
|
}
|
|
else {
|
|
component = QMenu;
|
|
data.props.target = this.target;
|
|
data.props.contextMenu = this.contextMenu;
|
|
data.props.noParentEvent = true;
|
|
data.props.separateClosePopup = true;
|
|
}
|
|
|
|
return h(component, data, def)
|
|
}
|
|
});
|
|
|
|
function width$1 (val, reverse) {
|
|
if (reverse === true) {
|
|
return { transform: ("translateX(100%) scale3d(" + (-val) + ",1,1)") }
|
|
}
|
|
return { transform: ("scale3d(" + val + ",1,1)") }
|
|
}
|
|
|
|
var QLinearProgress = Vue.extend({
|
|
name: 'QLinearProgress',
|
|
|
|
mixins: [
|
|
ListenersMixin,
|
|
DarkMixin,
|
|
getSizeMixin({
|
|
xs: 2,
|
|
sm: 4,
|
|
md: 6,
|
|
lg: 10,
|
|
xl: 14
|
|
})
|
|
],
|
|
|
|
props: {
|
|
value: {
|
|
type: Number,
|
|
default: 0
|
|
},
|
|
buffer: Number,
|
|
|
|
color: String,
|
|
trackColor: String,
|
|
|
|
reverse: Boolean,
|
|
stripe: Boolean,
|
|
indeterminate: Boolean,
|
|
query: Boolean,
|
|
rounded: Boolean,
|
|
|
|
instantFeedback: Boolean
|
|
},
|
|
|
|
computed: {
|
|
motion: function motion () {
|
|
return this.indeterminate === true || this.query === true
|
|
},
|
|
|
|
classes: function classes () {
|
|
return 'q-linear-progress' +
|
|
(this.color !== void 0 ? (" text-" + (this.color)) : '') +
|
|
(this.reverse === true || this.query === true ? ' q-linear-progress--reverse' : '') +
|
|
(this.rounded === true ? ' rounded-borders' : '')
|
|
},
|
|
|
|
trackStyle: function trackStyle () {
|
|
return width$1(this.buffer !== void 0 ? this.buffer : 1, this.reverse)
|
|
},
|
|
|
|
trackClass: function trackClass () {
|
|
return "q-linear-progress__track--with" + (this.instantFeedback === true ? 'out' : '') + "-transition" +
|
|
" q-linear-progress__track--" + (this.isDark === true ? 'dark' : 'light') +
|
|
(this.trackColor !== void 0 ? (" bg-" + (this.trackColor)) : '')
|
|
},
|
|
|
|
modelStyle: function modelStyle () {
|
|
return width$1(this.motion === true ? 1 : this.value, this.reverse)
|
|
},
|
|
|
|
modelClasses: function modelClasses () {
|
|
return "q-linear-progress__model--with" + (this.instantFeedback === true ? 'out' : '') + "-transition" +
|
|
" q-linear-progress__model--" + (this.motion === true ? 'in' : '') + "determinate"
|
|
},
|
|
|
|
stripeStyle: function stripeStyle () {
|
|
return { width: (this.value * 100) + '%' }
|
|
},
|
|
|
|
attrs: function attrs () {
|
|
return {
|
|
role: 'progressbar',
|
|
'aria-valuemin': 0,
|
|
'aria-valuemax': 1,
|
|
'aria-valuenow': this.indeterminate === true ? void 0 : this.value
|
|
}
|
|
}
|
|
},
|
|
|
|
render: function render (h) {
|
|
var child = [
|
|
h('div', {
|
|
staticClass: 'q-linear-progress__track absolute-full',
|
|
style: this.trackStyle,
|
|
class: this.trackClass
|
|
}),
|
|
|
|
h('div', {
|
|
staticClass: 'q-linear-progress__model absolute-full',
|
|
style: this.modelStyle,
|
|
class: this.modelClasses
|
|
})
|
|
];
|
|
|
|
this.stripe === true && this.motion === false && child.push(
|
|
h('div', {
|
|
staticClass: 'q-linear-progress__stripe absolute-full',
|
|
style: this.stripeStyle
|
|
})
|
|
);
|
|
|
|
return h('div', {
|
|
style: this.sizeStyle,
|
|
class: this.classes,
|
|
attrs: this.attrs,
|
|
on: Object.assign({}, this.qListeners)
|
|
}, mergeSlot(child, this, 'default'))
|
|
}
|
|
});
|
|
|
|
var
|
|
PULLER_HEIGHT = 40,
|
|
OFFSET_TOP = 20;
|
|
|
|
var QPullToRefresh = Vue.extend({
|
|
name: 'QPullToRefresh',
|
|
|
|
mixins: [ ListenersMixin ],
|
|
|
|
directives: {
|
|
TouchPan: TouchPan
|
|
},
|
|
|
|
props: {
|
|
color: String,
|
|
bgColor: String,
|
|
icon: String,
|
|
noMouse: Boolean,
|
|
disable: Boolean,
|
|
|
|
scrollTarget: {
|
|
default: void 0
|
|
}
|
|
},
|
|
|
|
data: function data () {
|
|
return {
|
|
state: 'pull',
|
|
pullRatio: 0,
|
|
pulling: false,
|
|
pullPosition: -PULLER_HEIGHT,
|
|
animating: false,
|
|
positionCSS: {}
|
|
}
|
|
},
|
|
|
|
computed: {
|
|
style: function style () {
|
|
return {
|
|
opacity: this.pullRatio,
|
|
transform: ("translateY(" + (this.pullPosition) + "px) rotate(" + (this.pullRatio * 360) + "deg)")
|
|
}
|
|
},
|
|
|
|
classes: function classes () {
|
|
return 'q-pull-to-refresh__puller row flex-center' +
|
|
(this.animating === true ? ' q-pull-to-refresh__puller--animating' : '') +
|
|
(this.bgColor !== void 0 ? (" bg-" + (this.bgColor)) : '')
|
|
},
|
|
|
|
directives: function directives () {
|
|
if (this.disable !== true) {
|
|
var modifiers = {
|
|
down: true,
|
|
mightPrevent: true
|
|
};
|
|
|
|
if (this.noMouse !== true) {
|
|
modifiers.mouse = true;
|
|
}
|
|
|
|
return [{
|
|
name: 'touch-pan',
|
|
modifiers: modifiers,
|
|
value: this.__pull
|
|
}]
|
|
}
|
|
},
|
|
|
|
contentClass: function contentClass () {
|
|
return ("q-pull-to-refresh__content" + (this.pulling === true ? ' no-pointer-events' : ''))
|
|
}
|
|
},
|
|
|
|
watch: {
|
|
scrollTarget: function scrollTarget () {
|
|
this.updateScrollTarget();
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
trigger: function trigger () {
|
|
var this$1 = this;
|
|
|
|
this.$emit('refresh', function () {
|
|
this$1.__animateTo({ pos: -PULLER_HEIGHT, ratio: 0 }, function () {
|
|
this$1.state = 'pull';
|
|
});
|
|
});
|
|
},
|
|
|
|
updateScrollTarget: function updateScrollTarget () {
|
|
this.__scrollTarget = getScrollTarget(this.$el, this.scrollTarget);
|
|
},
|
|
|
|
__pull: function __pull (event) {
|
|
if (event.isFinal === true) {
|
|
if (this.pulling === true) {
|
|
this.pulling = false;
|
|
|
|
if (this.state === 'pulled') {
|
|
this.state = 'refreshing';
|
|
this.__animateTo({ pos: OFFSET_TOP });
|
|
this.trigger();
|
|
}
|
|
else if (this.state === 'pull') {
|
|
this.__animateTo({ pos: -PULLER_HEIGHT, ratio: 0 });
|
|
}
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
if (this.animating === true || this.state === 'refreshing') {
|
|
return false
|
|
}
|
|
|
|
if (event.isFirst === true) {
|
|
if (getScrollPosition(this.__scrollTarget) !== 0) {
|
|
if (this.pulling === true) {
|
|
this.pulling = false;
|
|
this.state = 'pull';
|
|
this.__animateTo({ pos: -PULLER_HEIGHT, ratio: 0 });
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
this.pulling = true;
|
|
|
|
var ref = this.$el.getBoundingClientRect();
|
|
var top = ref.top;
|
|
var left = ref.left;
|
|
this.positionCSS = {
|
|
top: top + 'px',
|
|
left: left + 'px',
|
|
width: window.getComputedStyle(this.$el).getPropertyValue('width')
|
|
};
|
|
}
|
|
|
|
prevent(event.evt);
|
|
|
|
var distance = Math.min(140, Math.max(0, event.distance.y));
|
|
this.pullPosition = distance - PULLER_HEIGHT;
|
|
this.pullRatio = between(distance / (OFFSET_TOP + PULLER_HEIGHT), 0, 1);
|
|
|
|
var state = this.pullPosition > OFFSET_TOP ? 'pulled' : 'pull';
|
|
|
|
if (this.state !== state) {
|
|
this.state = state;
|
|
}
|
|
},
|
|
|
|
__animateTo: function __animateTo (ref, done) {
|
|
var this$1 = this;
|
|
var pos = ref.pos;
|
|
var ratio = ref.ratio;
|
|
|
|
this.animating = true;
|
|
this.pullPosition = pos;
|
|
|
|
if (ratio !== void 0) {
|
|
this.pullRatio = ratio;
|
|
}
|
|
|
|
clearTimeout(this.timer);
|
|
this.timer = setTimeout(function () {
|
|
this$1.animating = false;
|
|
done && done();
|
|
}, 300);
|
|
}
|
|
},
|
|
|
|
mounted: function mounted () {
|
|
this.updateScrollTarget();
|
|
},
|
|
|
|
beforeDestroy: function beforeDestroy () {
|
|
clearTimeout(this.timer);
|
|
},
|
|
|
|
render: function render (h) {
|
|
return h('div', {
|
|
staticClass: 'q-pull-to-refresh',
|
|
on: Object.assign({}, this.qListeners),
|
|
directives: this.directives
|
|
}, [
|
|
h('div', {
|
|
class: this.contentClass
|
|
}, slot(this, 'default')),
|
|
|
|
h('div', {
|
|
staticClass: 'q-pull-to-refresh__puller-container fixed row flex-center no-pointer-events z-top',
|
|
style: this.positionCSS
|
|
}, [
|
|
h('div', {
|
|
style: this.style,
|
|
class: this.classes
|
|
}, [
|
|
this.state !== 'refreshing'
|
|
? h(QIcon, {
|
|
props: {
|
|
name: this.icon || this.$q.iconSet.pullToRefresh.icon,
|
|
color: this.color,
|
|
size: '32px'
|
|
}
|
|
})
|
|
: h(QSpinner, {
|
|
props: {
|
|
size: '24px',
|
|
color: this.color
|
|
}
|
|
})
|
|
])
|
|
])
|
|
])
|
|
}
|
|
});
|
|
|
|
var dragType = {
|
|
MIN: 0,
|
|
RANGE: 1,
|
|
MAX: 2
|
|
};
|
|
|
|
var QRange = Vue.extend({
|
|
name: 'QRange',
|
|
|
|
mixins: [ SliderMixin ],
|
|
|
|
props: {
|
|
value: {
|
|
type: Object,
|
|
default: function () { return ({
|
|
min: null,
|
|
max: null
|
|
}); },
|
|
validator: function validator (val) {
|
|
return 'min' in val && 'max' in val
|
|
}
|
|
},
|
|
|
|
name: String,
|
|
|
|
dragRange: Boolean,
|
|
dragOnlyRange: Boolean,
|
|
|
|
leftLabelColor: String,
|
|
leftLabelTextColor: String,
|
|
rightLabelColor: String,
|
|
rightLabelTextColor: String,
|
|
|
|
leftLabelValue: [ String, Number ],
|
|
rightLabelValue: [ String, Number ]
|
|
},
|
|
|
|
data: function data () {
|
|
return {
|
|
model: {
|
|
min: this.value.min === null ? this.min : this.value.min,
|
|
max: this.value.max === null ? this.max : this.value.max
|
|
},
|
|
curMinRatio: 0,
|
|
curMaxRatio: 0
|
|
}
|
|
},
|
|
|
|
watch: {
|
|
'value.min': function value_min (val) {
|
|
this.model.min = val === null
|
|
? this.min
|
|
: val;
|
|
},
|
|
|
|
'value.max': function value_max (val) {
|
|
this.model.max = val === null
|
|
? this.max
|
|
: val;
|
|
},
|
|
|
|
min: function min (value) {
|
|
if (this.model.min < value) {
|
|
this.model.min = value;
|
|
}
|
|
if (this.model.max < value) {
|
|
this.model.max = value;
|
|
}
|
|
},
|
|
|
|
max: function max (value) {
|
|
if (this.model.min > value) {
|
|
this.model.min = value;
|
|
}
|
|
if (this.model.max > value) {
|
|
this.model.max = value;
|
|
}
|
|
}
|
|
},
|
|
|
|
computed: {
|
|
ratioMin: function ratioMin () {
|
|
return this.active === true ? this.curMinRatio : this.modelMinRatio
|
|
},
|
|
|
|
ratioMax: function ratioMax () {
|
|
return this.active === true ? this.curMaxRatio : this.modelMaxRatio
|
|
},
|
|
|
|
modelMinRatio: function modelMinRatio () {
|
|
return (this.model.min - this.min) / (this.max - this.min)
|
|
},
|
|
|
|
modelMaxRatio: function modelMaxRatio () {
|
|
return (this.model.max - this.min) / (this.max - this.min)
|
|
},
|
|
|
|
trackStyle: function trackStyle () {
|
|
var obj;
|
|
|
|
return ( obj = {}, obj[ this.positionProp ] = ((100 * this.ratioMin) + "%"), obj[ this.sizeProp ] = ((100 * (this.ratioMax - this.ratioMin)) + "%"), obj )
|
|
},
|
|
|
|
minThumbStyle: function minThumbStyle () {
|
|
var obj;
|
|
|
|
return ( obj = {}, obj[ this.positionProp ] = ((100 * this.ratioMin) + "%"), obj['z-index'] = this.__nextFocus === 'min' ? 2 : void 0, obj )
|
|
},
|
|
|
|
maxThumbStyle: function maxThumbStyle () {
|
|
var obj;
|
|
|
|
return ( obj = {}, obj[ this.positionProp ] = ((100 * this.ratioMax) + "%"), obj )
|
|
},
|
|
|
|
minThumbClass: function minThumbClass () {
|
|
if (this.preventFocus === false && this.focus === 'min') {
|
|
return 'q-slider--focus'
|
|
}
|
|
},
|
|
|
|
maxThumbClass: function maxThumbClass () {
|
|
if (this.preventFocus === false && this.focus === 'max') {
|
|
return 'q-slider--focus'
|
|
}
|
|
},
|
|
|
|
events: function events () {
|
|
var this$1 = this;
|
|
|
|
if (this.editable === true) {
|
|
if (this.$q.platform.is.mobile === true) {
|
|
return { click: this.__mobileClick }
|
|
}
|
|
|
|
var evt = { mousedown: this.__activate };
|
|
|
|
this.dragOnlyRange === true && Object.assign(evt, {
|
|
focus: function () { this$1.__focus('both'); },
|
|
blur: this.__blur,
|
|
keydown: this.__keydown,
|
|
keyup: this.__keyup
|
|
});
|
|
|
|
return evt
|
|
}
|
|
},
|
|
|
|
minEvents: function minEvents () {
|
|
var this$1 = this;
|
|
|
|
if (this.editable === true && this.$q.platform.is.mobile !== true && this.dragOnlyRange !== true) {
|
|
return {
|
|
focus: function () { this$1.__focus('min'); },
|
|
blur: this.__blur,
|
|
keydown: this.__keydown,
|
|
keyup: this.__keyup
|
|
}
|
|
}
|
|
},
|
|
|
|
maxEvents: function maxEvents () {
|
|
var this$1 = this;
|
|
|
|
if (this.editable === true && this.$q.platform.is.mobile !== true && this.dragOnlyRange !== true) {
|
|
return {
|
|
focus: function () { this$1.__focus('max'); },
|
|
blur: this.__blur,
|
|
keydown: this.__keydown,
|
|
keyup: this.__keyup
|
|
}
|
|
}
|
|
},
|
|
|
|
minPinClass: function minPinClass () {
|
|
var color = this.leftLabelColor || this.labelColor;
|
|
if (color) {
|
|
return ("text-" + color)
|
|
}
|
|
},
|
|
|
|
minPinTextClass: function minPinTextClass () {
|
|
var color = this.leftLabelTextColor || this.labelTextColor;
|
|
if (color) {
|
|
return ("text-" + color)
|
|
}
|
|
},
|
|
|
|
maxPinClass: function maxPinClass () {
|
|
var color = this.rightLabelColor || this.labelColor;
|
|
if (color) {
|
|
return ("text-" + color)
|
|
}
|
|
},
|
|
|
|
maxPinTextClass: function maxPinTextClass () {
|
|
var color = this.rightLabelTextColor || this.labelTextColor;
|
|
if (color) {
|
|
return ("text-" + color)
|
|
}
|
|
},
|
|
|
|
minLabel: function minLabel () {
|
|
return this.leftLabelValue !== void 0
|
|
? this.leftLabelValue
|
|
: this.model.min
|
|
},
|
|
|
|
maxLabel: function maxLabel () {
|
|
return this.rightLabelValue !== void 0
|
|
? this.rightLabelValue
|
|
: this.model.max
|
|
},
|
|
|
|
minPinStyle: function minPinStyle () {
|
|
var percent = (this.reverse === true ? -this.ratioMin : this.ratioMin - 1);
|
|
return this.__getPinStyle(percent, this.ratioMin)
|
|
},
|
|
|
|
maxPinStyle: function maxPinStyle () {
|
|
var percent = (this.reverse === true ? -this.ratioMax : this.ratioMax - 1);
|
|
return this.__getPinStyle(percent, this.ratioMax)
|
|
},
|
|
|
|
formAttrs: function formAttrs () {
|
|
return {
|
|
type: 'hidden',
|
|
name: this.name,
|
|
value: ((this.value.min) + "|" + (this.value.max))
|
|
}
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
__updateValue: function __updateValue (change) {
|
|
if (this.model.min !== this.value.min || this.model.max !== this.value.max) {
|
|
this.$emit('input', this.model);
|
|
}
|
|
change === true && this.$emit('change', this.model);
|
|
},
|
|
|
|
__getDragging: function __getDragging (event) {
|
|
var ref = this.$el.getBoundingClientRect();
|
|
var left = ref.left;
|
|
var top = ref.top;
|
|
var width = ref.width;
|
|
var height = ref.height;
|
|
var sensitivity = this.dragOnlyRange === true
|
|
? 0
|
|
: (this.vertical === true
|
|
? this.$refs.minThumb.offsetHeight / (2 * height)
|
|
: this.$refs.minThumb.offsetWidth / (2 * width)
|
|
),
|
|
diff = this.max - this.min;
|
|
|
|
var dragging = {
|
|
left: left,
|
|
top: top,
|
|
width: width,
|
|
height: height,
|
|
valueMin: this.model.min,
|
|
valueMax: this.model.max,
|
|
ratioMin: (this.model.min - this.min) / diff,
|
|
ratioMax: (this.model.max - this.min) / diff
|
|
};
|
|
|
|
var ratio = getRatio(event, dragging, this.isReversed, this.vertical);
|
|
var type;
|
|
|
|
if (this.dragOnlyRange !== true && ratio < dragging.ratioMin + sensitivity) {
|
|
type = dragType.MIN;
|
|
}
|
|
else if (this.dragOnlyRange === true || ratio < dragging.ratioMax - sensitivity) {
|
|
if (this.dragRange === true || this.dragOnlyRange === true) {
|
|
type = dragType.RANGE;
|
|
Object.assign(dragging, {
|
|
offsetRatio: ratio,
|
|
offsetModel: getModel(ratio, this.min, this.max, this.step, this.decimals),
|
|
rangeValue: dragging.valueMax - dragging.valueMin,
|
|
rangeRatio: dragging.ratioMax - dragging.ratioMin
|
|
});
|
|
}
|
|
else {
|
|
type = dragging.ratioMax - ratio < ratio - dragging.ratioMin
|
|
? dragType.MAX
|
|
: dragType.MIN;
|
|
}
|
|
}
|
|
else {
|
|
type = dragType.MAX;
|
|
}
|
|
|
|
dragging.type = type;
|
|
this.__nextFocus = void 0;
|
|
|
|
return dragging
|
|
},
|
|
|
|
__updatePosition: function __updatePosition (event, dragging) {
|
|
if ( dragging === void 0 ) dragging = this.dragging;
|
|
|
|
var
|
|
ratio = getRatio(event, dragging, this.isReversed, this.vertical),
|
|
model = getModel(ratio, this.min, this.max, this.step, this.decimals);
|
|
var pos;
|
|
|
|
switch (dragging.type) {
|
|
case dragType.MIN:
|
|
if (ratio <= dragging.ratioMax) {
|
|
pos = {
|
|
minR: ratio,
|
|
maxR: dragging.ratioMax,
|
|
min: model,
|
|
max: dragging.valueMax
|
|
};
|
|
this.__nextFocus = 'min';
|
|
}
|
|
else {
|
|
pos = {
|
|
minR: dragging.ratioMax,
|
|
maxR: ratio,
|
|
min: dragging.valueMax,
|
|
max: model
|
|
};
|
|
this.__nextFocus = 'max';
|
|
}
|
|
break
|
|
|
|
case dragType.MAX:
|
|
if (ratio >= dragging.ratioMin) {
|
|
pos = {
|
|
minR: dragging.ratioMin,
|
|
maxR: ratio,
|
|
min: dragging.valueMin,
|
|
max: model
|
|
};
|
|
this.__nextFocus = 'max';
|
|
}
|
|
else {
|
|
pos = {
|
|
minR: ratio,
|
|
maxR: dragging.ratioMin,
|
|
min: model,
|
|
max: dragging.valueMin
|
|
};
|
|
this.__nextFocus = 'min';
|
|
}
|
|
break
|
|
|
|
case dragType.RANGE:
|
|
var
|
|
ratioDelta = ratio - dragging.offsetRatio,
|
|
minR = between(dragging.ratioMin + ratioDelta, 0, 1 - dragging.rangeRatio),
|
|
modelDelta = model - dragging.offsetModel,
|
|
min = between(dragging.valueMin + modelDelta, this.min, this.max - dragging.rangeValue);
|
|
|
|
pos = {
|
|
minR: minR,
|
|
maxR: minR + dragging.rangeRatio,
|
|
min: parseFloat(min.toFixed(this.decimals)),
|
|
max: parseFloat((min + dragging.rangeValue).toFixed(this.decimals))
|
|
};
|
|
break
|
|
}
|
|
|
|
this.model = {
|
|
min: pos.min,
|
|
max: pos.max
|
|
};
|
|
|
|
// If either of the values to be emitted are null, set them to the defaults the user has entered.
|
|
if (this.model.min === null || this.model.max === null) {
|
|
this.model.min = pos.min || this.min;
|
|
this.model.max = pos.max || this.max;
|
|
}
|
|
|
|
if (this.snap !== true || this.step === 0) {
|
|
this.curMinRatio = pos.minR;
|
|
this.curMaxRatio = pos.maxR;
|
|
}
|
|
else {
|
|
var diff = this.max - this.min;
|
|
this.curMinRatio = (this.model.min - this.min) / diff;
|
|
this.curMaxRatio = (this.model.max - this.min) / diff;
|
|
}
|
|
},
|
|
|
|
__focus: function __focus (which) {
|
|
this.focus = which;
|
|
},
|
|
|
|
__keydown: function __keydown (evt) {
|
|
var obj;
|
|
|
|
if (!keyCodes.includes(evt.keyCode)) {
|
|
return
|
|
}
|
|
|
|
stopAndPrevent(evt);
|
|
|
|
var
|
|
step = ([34, 33].includes(evt.keyCode) ? 10 : 1) * this.computedStep,
|
|
offset = [34, 37, 40].includes(evt.keyCode) ? -step : step;
|
|
|
|
if (this.dragOnlyRange) {
|
|
var interval = this.dragOnlyRange
|
|
? this.model.max - this.model.min
|
|
: 0;
|
|
|
|
var min = between(
|
|
parseFloat((this.model.min + offset).toFixed(this.decimals)),
|
|
this.min,
|
|
this.max - interval
|
|
);
|
|
|
|
this.model = {
|
|
min: min,
|
|
max: parseFloat((min + interval).toFixed(this.decimals))
|
|
};
|
|
}
|
|
else if (this.focus === false) {
|
|
return
|
|
}
|
|
else {
|
|
var which = this.focus;
|
|
|
|
this.model = Object.assign({}, this.model,
|
|
( obj = {}, obj[which] = between(
|
|
parseFloat((this.model[which] + offset).toFixed(this.decimals)),
|
|
which === 'min' ? this.min : this.model.min,
|
|
which === 'max' ? this.max : this.model.max
|
|
), obj ));
|
|
}
|
|
|
|
this.__updateValue();
|
|
},
|
|
|
|
__getThumb: function __getThumb (h, which) {
|
|
var child = [
|
|
this.__getThumbSvg(h),
|
|
h('div', { staticClass: 'q-slider__focus-ring' })
|
|
];
|
|
|
|
if (this.label === true || this.labelAlways === true) {
|
|
child.push(
|
|
h('div', {
|
|
staticClass: ("q-slider__pin q-slider__pin" + (this.axis) + " absolute"),
|
|
style: this[which + 'PinStyle'].pin,
|
|
class: this[which + 'PinClass']
|
|
}, [
|
|
h('div', {
|
|
staticClass: ("q-slider__pin-text-container q-slider__pin-text-container" + (this.axis)),
|
|
style: this[which + 'PinStyle'].pinTextContainer
|
|
}, [
|
|
h('span', {
|
|
staticClass: 'q-slider__pin-text',
|
|
class: this[which + 'PinTextClass']
|
|
}, [
|
|
this[which + 'Label']
|
|
])
|
|
])
|
|
]),
|
|
|
|
h('div', {
|
|
staticClass: ("q-slider__arrow q-slider__arrow" + (this.axis)),
|
|
class: this[which + 'PinClass']
|
|
})
|
|
);
|
|
}
|
|
|
|
return h('div', {
|
|
ref: which + 'Thumb',
|
|
staticClass: ("q-slider__thumb-container q-slider__thumb-container" + (this.axis) + " absolute non-selectable"),
|
|
style: this[which + 'ThumbStyle'],
|
|
class: this[which + 'ThumbClass'],
|
|
on: this[which + 'Events'],
|
|
attrs: { tabindex: this.dragOnlyRange !== true ? this.computedTabindex : null }
|
|
}, child)
|
|
}
|
|
},
|
|
|
|
render: function render (h) {
|
|
var track = [
|
|
h('div', {
|
|
staticClass: ("q-slider__track q-slider__track" + (this.axis) + " absolute"),
|
|
style: this.trackStyle
|
|
})
|
|
];
|
|
|
|
this.markers === true && track.push(
|
|
h('div', {
|
|
staticClass: ("q-slider__track-markers q-slider__track-markers" + (this.axis) + " absolute-full fit"),
|
|
style: this.markerStyle
|
|
})
|
|
);
|
|
|
|
var child = [
|
|
h('div', {
|
|
staticClass: ("q-slider__track-container q-slider__track-container" + (this.axis) + " absolute")
|
|
}, track),
|
|
|
|
this.__getThumb(h, 'min'),
|
|
this.__getThumb(h, 'max')
|
|
];
|
|
|
|
if (this.name !== void 0 && this.disable !== true) {
|
|
this.__injectFormInput(child, 'push');
|
|
}
|
|
|
|
return h('div', {
|
|
staticClass: this.value.min === null || this.value.max === null
|
|
? 'q-slider--no-value'
|
|
: void 0,
|
|
attrs: Object.assign({}, this.attrs,
|
|
{'aria-valuenow': this.value.min + '|' + this.value.max,
|
|
tabindex: this.dragOnlyRange === true && this.$q.platform.is.mobile !== true
|
|
? this.computedTabindex
|
|
: null}),
|
|
class: this.classes,
|
|
on: this.events,
|
|
directives: this.panDirectives
|
|
}, child)
|
|
}
|
|
});
|
|
|
|
var QRating = Vue.extend({
|
|
name: 'QRating',
|
|
|
|
mixins: [ SizeMixin, FormMixin, ListenersMixin ],
|
|
|
|
props: {
|
|
value: {
|
|
type: Number,
|
|
required: true
|
|
},
|
|
|
|
max: {
|
|
type: [String, Number],
|
|
default: 5
|
|
},
|
|
|
|
icon: [String, Array],
|
|
iconHalf: [String, Array],
|
|
iconSelected: [String, Array],
|
|
|
|
color: [String, Array],
|
|
colorHalf: [String, Array],
|
|
colorSelected: [String, Array],
|
|
|
|
noReset: Boolean,
|
|
noDimming: Boolean,
|
|
|
|
readonly: Boolean,
|
|
disable: Boolean
|
|
},
|
|
|
|
data: function data () {
|
|
return {
|
|
mouseModel: 0
|
|
}
|
|
},
|
|
|
|
computed: {
|
|
editable: function editable () {
|
|
return this.readonly !== true && this.disable !== true
|
|
},
|
|
|
|
classes: function classes () {
|
|
return "q-rating--" + (this.editable === true ? '' : 'non-') + "editable" +
|
|
(this.noDimming === true ? ' q-rating--no-dimming' : '') +
|
|
(this.disable === true ? ' disabled' : '') +
|
|
(this.color !== void 0 && Array.isArray(this.color) === false ? (" text-" + (this.color)) : '')
|
|
},
|
|
|
|
iconData: function iconData () {
|
|
var
|
|
iconLen = Array.isArray(this.icon) === true ? this.icon.length : 0,
|
|
selIconLen = Array.isArray(this.iconSelected) === true ? this.iconSelected.length : 0,
|
|
halfIconLen = Array.isArray(this.iconHalf) === true ? this.iconHalf.length : 0,
|
|
colorLen = Array.isArray(this.color) === true ? this.color.length : 0,
|
|
selColorLen = Array.isArray(this.colorSelected) === true ? this.colorSelected.length : 0,
|
|
halfColorLen = Array.isArray(this.colorHalf) === true ? this.colorHalf.length : 0;
|
|
|
|
return {
|
|
iconLen: iconLen,
|
|
icon: iconLen > 0 ? this.icon[iconLen - 1] : this.icon,
|
|
selIconLen: selIconLen,
|
|
selIcon: selIconLen > 0 ? this.iconSelected[selIconLen - 1] : this.iconSelected,
|
|
halfIconLen: halfIconLen,
|
|
halfIcon: halfIconLen > 0 ? this.iconHalf[selIconLen - 1] : this.iconHalf,
|
|
colorLen: colorLen,
|
|
color: colorLen > 0 ? this.color[colorLen - 1] : this.color,
|
|
selColorLen: selColorLen,
|
|
selColor: selColorLen > 0 ? this.colorSelected[selColorLen - 1] : this.colorSelected,
|
|
halfColorLen: halfColorLen,
|
|
halfColor: halfColorLen > 0 ? this.colorHalf[halfColorLen - 1] : this.colorHalf
|
|
}
|
|
},
|
|
|
|
attrs: function attrs () {
|
|
if (this.disable === true) {
|
|
return { 'aria-disabled': 'true' }
|
|
}
|
|
if (this.readonly === true) {
|
|
return { 'aria-readonly': 'true' }
|
|
}
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
__set: function __set (value) {
|
|
if (this.editable === true) {
|
|
var
|
|
model = between(parseInt(value, 10), 1, parseInt(this.max, 10)),
|
|
newVal = this.noReset !== true && this.value === model ? 0 : model;
|
|
|
|
newVal !== this.value && this.$emit('input', newVal);
|
|
this.mouseModel = 0;
|
|
}
|
|
},
|
|
|
|
__setHoverValue: function __setHoverValue (value) {
|
|
if (this.editable === true) {
|
|
this.mouseModel = value;
|
|
}
|
|
},
|
|
|
|
__keyup: function __keyup (e, i) {
|
|
switch (e.keyCode) {
|
|
case 13:
|
|
case 32:
|
|
this.__set(i);
|
|
return stopAndPrevent(e)
|
|
case 37: // LEFT ARROW
|
|
case 40: // DOWN ARROW
|
|
if (this.$refs[("rt" + (i - 1))]) {
|
|
this.$refs[("rt" + (i - 1))].focus();
|
|
}
|
|
return stopAndPrevent(e)
|
|
case 39: // RIGHT ARROW
|
|
case 38: // UP ARROW
|
|
if (this.$refs[("rt" + (i + 1))]) {
|
|
this.$refs[("rt" + (i + 1))].focus();
|
|
}
|
|
return stopAndPrevent(e)
|
|
}
|
|
}
|
|
},
|
|
|
|
render: function render (h) {
|
|
var this$1 = this;
|
|
var obj;
|
|
|
|
var
|
|
child = [],
|
|
tabindex = this.editable === true ? 0 : null,
|
|
icons = this.iconData,
|
|
ceil = Math.ceil(this.value);
|
|
|
|
var halfIndex = this.iconHalf === void 0 || ceil === this.value
|
|
? -1
|
|
: ceil;
|
|
|
|
var loop = function ( i ) {
|
|
var
|
|
active = (this$1.mouseModel === 0 && this$1.value >= i) || (this$1.mouseModel > 0 && this$1.mouseModel >= i),
|
|
half = halfIndex === i && this$1.mouseModel < i,
|
|
exSelected = this$1.mouseModel > 0 && (half === true ? ceil : this$1.value) >= i && this$1.mouseModel < i,
|
|
name = half === true
|
|
? (i <= icons.halfIconLen ? this$1.iconHalf[i - 1] : icons.halfIcon)
|
|
: (
|
|
icons.selIcon !== void 0 && (active === true || exSelected === true)
|
|
? (i <= icons.selIconLen ? this$1.iconSelected[i - 1] : icons.selIcon)
|
|
: (i <= icons.iconLen ? this$1.icon[i - 1] : icons.icon)
|
|
),
|
|
color = half === true
|
|
? (i <= icons.halfColorLen ? this$1.colorHalf[i - 1] : icons.halfColor)
|
|
: (
|
|
icons.selColor !== void 0 && active === true
|
|
? (i <= icons.selColorLen ? this$1.colorSelected[i - 1] : icons.selColor)
|
|
: (i <= icons.colorLen ? this$1.color[i - 1] : icons.color)
|
|
);
|
|
|
|
child.push(
|
|
h(QIcon, {
|
|
key: i,
|
|
ref: ("rt" + i),
|
|
staticClass: 'q-rating__icon',
|
|
class: ( obj = {
|
|
'q-rating__icon--active': active === true || half === true,
|
|
'q-rating__icon--exselected': exSelected,
|
|
'q-rating__icon--hovered': this$1.mouseModel === i
|
|
}, obj[("text-" + color)] = color !== void 0, obj ),
|
|
props: { name: name || this$1.$q.iconSet.rating.icon },
|
|
attrs: { tabindex: tabindex },
|
|
on: cache(this$1, 'i#' + i, {
|
|
click: function () { this$1.__set(i); },
|
|
mouseover: function () { this$1.__setHoverValue(i); },
|
|
mouseout: function () { this$1.mouseModel = 0; },
|
|
focus: function () { this$1.__setHoverValue(i); },
|
|
blur: function () { this$1.mouseModel = 0; },
|
|
keyup: function (e) { this$1.__keyup(e, i); }
|
|
})
|
|
}, slot(this$1, ("tip-" + i)))
|
|
);
|
|
};
|
|
|
|
for (var i = 1; i <= this$1.max; i++) loop( i );
|
|
|
|
if (this.name !== void 0 && this.disable !== true) {
|
|
this.__injectFormInput(child, 'push');
|
|
}
|
|
|
|
return h('div', {
|
|
staticClass: 'q-rating row inline items-center',
|
|
class: this.classes,
|
|
style: this.sizeStyle,
|
|
attrs: this.attrs,
|
|
on: Object.assign({}, this.qListeners)
|
|
}, child)
|
|
}
|
|
});
|
|
|
|
var QResponsive = Vue.extend({
|
|
name: 'QResponsive',
|
|
|
|
mixins: [ RatioMixin, ListenersMixin ],
|
|
|
|
render: function render (h) {
|
|
return h('div', {
|
|
staticClass: 'q-responsive',
|
|
on: Object.assign({}, this.qListeners)
|
|
}, [
|
|
h('div', {
|
|
staticClass: 'q-responsive__filler overflow-hidden'
|
|
}, [
|
|
h('div', { style: this.ratioStyle })
|
|
]),
|
|
|
|
h('div', {
|
|
staticClass: 'q-responsive__content absolute-full fit'
|
|
}, slot(this, 'default'))
|
|
])
|
|
}
|
|
});
|
|
|
|
var QScrollArea = Vue.extend({
|
|
name: 'QScrollArea',
|
|
|
|
mixins: [ DarkMixin ],
|
|
|
|
directives: {
|
|
TouchPan: TouchPan
|
|
},
|
|
|
|
props: {
|
|
barStyle: [ Array, String, Object ],
|
|
thumbStyle: Object,
|
|
contentStyle: [ Array, String, Object ],
|
|
contentActiveStyle: [ Array, String, Object ],
|
|
|
|
delay: {
|
|
type: [String, Number],
|
|
default: 1000
|
|
},
|
|
|
|
visible: {
|
|
type: Boolean,
|
|
default: null
|
|
},
|
|
|
|
horizontal: Boolean
|
|
},
|
|
|
|
data: function data () {
|
|
return {
|
|
// state management
|
|
tempShowing: false,
|
|
panning: false,
|
|
hover: false,
|
|
|
|
// other...
|
|
containerWidth: 0,
|
|
containerHeight: 0,
|
|
scrollPosition: 0,
|
|
scrollSize: 0
|
|
}
|
|
},
|
|
|
|
computed: {
|
|
classes: function classes () {
|
|
return 'q-scrollarea' +
|
|
(this.isDark === true ? ' q-scrollarea--dark' : '')
|
|
},
|
|
|
|
thumbHidden: function thumbHidden () {
|
|
return (
|
|
(this.visible === null ? this.hover : this.visible) !== true &&
|
|
this.tempShowing === false &&
|
|
this.panning === false
|
|
) || this.scrollSize <= this.containerSize
|
|
},
|
|
|
|
thumbSize: function thumbSize () {
|
|
return Math.round(
|
|
between(
|
|
this.containerSize * this.containerSize / this.scrollSize,
|
|
50,
|
|
this.containerSize
|
|
)
|
|
)
|
|
},
|
|
|
|
style: function style () {
|
|
var pos = this.scrollPercentage * (this.containerSize - this.thumbSize);
|
|
return Object.assign(
|
|
{},
|
|
this.thumbStyle,
|
|
this.horizontal === true
|
|
? {
|
|
left: (pos + "px"),
|
|
width: ((this.thumbSize) + "px")
|
|
}
|
|
: {
|
|
top: (pos + "px"),
|
|
height: ((this.thumbSize) + "px")
|
|
}
|
|
)
|
|
},
|
|
|
|
mainStyle: function mainStyle () {
|
|
return this.thumbHidden === true
|
|
? this.contentStyle
|
|
: this.contentActiveStyle
|
|
},
|
|
|
|
scrollPercentage: function scrollPercentage () {
|
|
var p = between(this.scrollPosition / (this.scrollSize - this.containerSize), 0, 1);
|
|
return Math.round(p * 10000) / 10000
|
|
},
|
|
|
|
containerSize: function containerSize () {
|
|
return this[("container" + (this.dirProps.suffix))]
|
|
},
|
|
|
|
dirProps: function dirProps () {
|
|
return this.horizontal === true
|
|
? { prefix: 'horizontal', suffix: 'Width', scroll: 'scrollLeft', classSuffix: 'h absolute-bottom', dir: 'right', dist: 'x' }
|
|
: { prefix: 'vertical', suffix: 'Height', scroll: 'scrollTop', classSuffix: 'v absolute-right', dir: 'down', dist: 'y' }
|
|
},
|
|
|
|
thumbClass: function thumbClass () {
|
|
return "q-scrollarea__thumb--" + (this.dirProps.classSuffix) +
|
|
(this.thumbHidden === true ? ' q-scrollarea__thumb--invisible' : '')
|
|
},
|
|
|
|
barClass: function barClass () {
|
|
return "q-scrollarea__bar--" + (this.dirProps.classSuffix) +
|
|
(this.thumbHidden === true ? ' q-scrollarea__bar--invisible' : '')
|
|
},
|
|
|
|
thumbDirectives: function thumbDirectives () {
|
|
var obj;
|
|
|
|
return [{
|
|
name: 'touch-pan',
|
|
modifiers: ( obj = {}, obj[ this.horizontal === true ? 'horizontal' : 'vertical' ] = true, obj.prevent = true, obj.mouse = true, obj.mouseAllDir = true, obj ),
|
|
value: this.__panThumb
|
|
}]
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
getScrollTarget: function getScrollTarget () {
|
|
return this.$refs.target
|
|
},
|
|
|
|
getScrollPosition: function getScrollPosition () {
|
|
return this.scrollPosition
|
|
},
|
|
|
|
setScrollPosition: function setScrollPosition$1 (offset, duration) {
|
|
var fn = this.horizontal === true
|
|
? setHorizontalScrollPosition
|
|
: setScrollPosition;
|
|
|
|
fn(this.$refs.target, offset, duration);
|
|
},
|
|
|
|
setScrollPercentage: function setScrollPercentage (percentage, duration) {
|
|
this.setScrollPosition(
|
|
percentage * (this.scrollSize - this.containerSize),
|
|
duration
|
|
);
|
|
},
|
|
|
|
__updateContainer: function __updateContainer (ref) {
|
|
var height = ref.height;
|
|
var width = ref.width;
|
|
|
|
var change = false;
|
|
|
|
if (this.containerWidth !== width) {
|
|
this.containerWidth = width;
|
|
change = true;
|
|
}
|
|
|
|
if (this.containerHeight !== height) {
|
|
this.containerHeight = height;
|
|
change = true;
|
|
}
|
|
|
|
change === true && this.__startTimer();
|
|
},
|
|
|
|
__updateScroll: function __updateScroll (info) {
|
|
if (this.scrollPosition !== info.position) {
|
|
this.scrollPosition = info.position;
|
|
this.__startTimer();
|
|
}
|
|
},
|
|
|
|
__updateScrollSize: function __updateScrollSize (ref) {
|
|
var height = ref.height;
|
|
var width = ref.width;
|
|
|
|
if (this.horizontal === true) {
|
|
if (this.scrollSize !== width) {
|
|
this.scrollSize = width;
|
|
this.__startTimer();
|
|
}
|
|
}
|
|
else if (this.scrollSize !== height) {
|
|
this.scrollSize = height;
|
|
this.__startTimer();
|
|
}
|
|
},
|
|
|
|
__panThumb: function __panThumb (e) {
|
|
if (e.isFirst === true) {
|
|
if (this.thumbHidden === true) {
|
|
return
|
|
}
|
|
|
|
this.refPos = this.scrollPosition;
|
|
this.panning = true;
|
|
}
|
|
else if (this.panning !== true) {
|
|
return
|
|
}
|
|
|
|
if (e.isFinal === true) {
|
|
this.panning = false;
|
|
}
|
|
|
|
var multiplier = (this.scrollSize - this.containerSize) / (this.containerSize - this.thumbSize);
|
|
var distance = e.distance[this.dirProps.dist];
|
|
var pos = this.refPos + (e.direction === this.dirProps.dir ? 1 : -1) * distance * multiplier;
|
|
|
|
this.__setScroll(pos);
|
|
},
|
|
|
|
__mouseDown: function __mouseDown (evt) {
|
|
if (this.thumbHidden !== true) {
|
|
var pos = evt[("offset" + (this.horizontal === true ? 'X' : 'Y'))] - this.thumbSize / 2;
|
|
this.__setScroll(pos / this.containerSize * this.scrollSize);
|
|
|
|
// activate thumb pan
|
|
if (this.$refs.thumb !== void 0) {
|
|
this.$refs.thumb.dispatchEvent(new MouseEvent(evt.type, evt));
|
|
}
|
|
}
|
|
},
|
|
|
|
__startTimer: function __startTimer () {
|
|
var this$1 = this;
|
|
|
|
if (this.tempShowing === true) {
|
|
clearTimeout(this.timer);
|
|
}
|
|
else {
|
|
this.tempShowing = true;
|
|
}
|
|
|
|
this.timer = setTimeout(function () {
|
|
this$1.tempShowing = false;
|
|
}, this.delay);
|
|
|
|
this.__emitScroll();
|
|
},
|
|
|
|
__setScroll: function __setScroll (offset) {
|
|
this.$refs.target[this.dirProps.scroll] = offset;
|
|
}
|
|
},
|
|
|
|
render: function render (h) {
|
|
var this$1 = this;
|
|
|
|
return h('div', {
|
|
class: this.classes,
|
|
on: cache(this, 'desk', {
|
|
mouseenter: function () { this$1.hover = true; },
|
|
mouseleave: function () { this$1.hover = false; }
|
|
})
|
|
}, [
|
|
h('div', {
|
|
ref: 'target',
|
|
staticClass: 'scroll relative-position fit hide-scrollbar'
|
|
}, [
|
|
h('div', {
|
|
staticClass: 'absolute',
|
|
style: this.mainStyle,
|
|
class: ("full-" + (this.horizontal === true ? 'height' : 'width'))
|
|
}, mergeSlot([
|
|
h(QResizeObserver, {
|
|
on: cache(this, 'resizeIn', { resize: this.__updateScrollSize })
|
|
})
|
|
], this, 'default')),
|
|
|
|
h(QScrollObserver, {
|
|
props: { horizontal: this.horizontal },
|
|
on: cache(this, 'scroll', { scroll: this.__updateScroll })
|
|
})
|
|
]),
|
|
|
|
h(QResizeObserver, {
|
|
on: cache(this, 'resizeOut', { resize: this.__updateContainer })
|
|
}),
|
|
|
|
h('div', {
|
|
staticClass: 'q-scrollarea__bar',
|
|
style: this.barStyle,
|
|
class: this.barClass,
|
|
attrs: ariaHidden,
|
|
on: cache(this, 'bar', {
|
|
mousedown: this.__mouseDown
|
|
})
|
|
}),
|
|
|
|
h('div', {
|
|
ref: 'thumb',
|
|
staticClass: 'q-scrollarea__thumb',
|
|
style: this.style,
|
|
class: this.thumbClass,
|
|
attrs: ariaHidden,
|
|
directives: this.thumbDirectives
|
|
})
|
|
])
|
|
},
|
|
|
|
created: function created () {
|
|
var this$1 = this;
|
|
|
|
// we have lots of listeners, so
|
|
// ensure we're not emitting same info
|
|
// multiple times
|
|
this.__emitScroll = debounce(function () {
|
|
if (this$1.$listeners.scroll !== void 0) {
|
|
var info = { ref: this$1 };
|
|
var prefix = this$1.dirProps.prefix;
|
|
|
|
info[prefix + 'Position'] = this$1.scrollPosition;
|
|
info[prefix + 'Percentage'] = this$1.scrollPercentage;
|
|
info[prefix + 'Size'] = this$1.scrollSize;
|
|
info[prefix + 'ContainerSize'] = this$1.containerSize;
|
|
|
|
this$1.$emit('scroll', info);
|
|
}
|
|
}, 0);
|
|
}
|
|
});
|
|
|
|
var aggBucketSize = 1000;
|
|
|
|
var scrollToEdges = [
|
|
'start',
|
|
'center',
|
|
'end',
|
|
'start-force',
|
|
'center-force',
|
|
'end-force'
|
|
];
|
|
|
|
var slice = Array.prototype.slice;
|
|
|
|
var buggyRTL = void 0;
|
|
|
|
// mobile Chrome takes the crown for this
|
|
function detectBuggyRTL () {
|
|
var scroller = document.createElement('div');
|
|
var spacer = document.createElement('div');
|
|
|
|
scroller.setAttribute('dir', 'rtl');
|
|
scroller.style.width = '1px';
|
|
scroller.style.height = '1px';
|
|
scroller.style.overflow = 'auto';
|
|
|
|
spacer.style.width = '1000px';
|
|
spacer.style.height = '1px';
|
|
|
|
document.body.appendChild(scroller);
|
|
scroller.appendChild(spacer);
|
|
scroller.scrollLeft = -1000;
|
|
|
|
buggyRTL = scroller.scrollLeft >= 0;
|
|
|
|
scroller.remove();
|
|
}
|
|
|
|
function sumFn (acc, h) {
|
|
return acc + h
|
|
}
|
|
|
|
function getScrollDetails (
|
|
parent,
|
|
child,
|
|
beforeRef,
|
|
afterRef,
|
|
horizontal,
|
|
rtl,
|
|
stickyStart,
|
|
stickyEnd
|
|
) {
|
|
var
|
|
parentCalc = parent === window ? document.scrollingElement || document.documentElement : parent,
|
|
propElSize = horizontal === true ? 'offsetWidth' : 'offsetHeight',
|
|
details = {
|
|
scrollStart: 0,
|
|
scrollViewSize: -stickyStart - stickyEnd,
|
|
scrollMaxSize: 0,
|
|
offsetStart: -stickyStart,
|
|
offsetEnd: -stickyEnd
|
|
};
|
|
|
|
if (horizontal === true) {
|
|
if (parent === window) {
|
|
details.scrollStart = window.pageXOffset || window.scrollX || document.body.scrollLeft || 0;
|
|
details.scrollViewSize += window.innerWidth;
|
|
}
|
|
else {
|
|
details.scrollStart = parentCalc.scrollLeft;
|
|
details.scrollViewSize += parentCalc.clientWidth;
|
|
}
|
|
details.scrollMaxSize = parentCalc.scrollWidth;
|
|
|
|
if (rtl === true) {
|
|
details.scrollStart = (buggyRTL === true ? details.scrollMaxSize - details.scrollViewSize : 0) - details.scrollStart;
|
|
}
|
|
}
|
|
else {
|
|
if (parent === window) {
|
|
details.scrollStart = window.pageYOffset || window.scrollY || document.body.scrollTop || 0;
|
|
details.scrollViewSize += window.innerHeight;
|
|
}
|
|
else {
|
|
details.scrollStart = parentCalc.scrollTop;
|
|
details.scrollViewSize += parentCalc.clientHeight;
|
|
}
|
|
details.scrollMaxSize = parentCalc.scrollHeight;
|
|
}
|
|
|
|
if (beforeRef !== void 0) {
|
|
for (var el = beforeRef.previousElementSibling; el !== null; el = el.previousElementSibling) {
|
|
if (el.classList.contains('q-virtual-scroll--skip') === false) {
|
|
details.offsetStart += el[propElSize];
|
|
}
|
|
}
|
|
}
|
|
if (afterRef !== void 0) {
|
|
for (var el$1 = afterRef.nextElementSibling; el$1 !== null; el$1 = el$1.nextElementSibling) {
|
|
if (el$1.classList.contains('q-virtual-scroll--skip') === false) {
|
|
details.offsetEnd += el$1[propElSize];
|
|
}
|
|
}
|
|
}
|
|
|
|
if (child !== parent) {
|
|
var
|
|
parentRect = parentCalc.getBoundingClientRect(),
|
|
childRect = child.getBoundingClientRect();
|
|
|
|
if (horizontal === true) {
|
|
details.offsetStart += childRect.left - parentRect.left;
|
|
details.offsetEnd -= childRect.width;
|
|
}
|
|
else {
|
|
details.offsetStart += childRect.top - parentRect.top;
|
|
details.offsetEnd -= childRect.height;
|
|
}
|
|
|
|
if (parent !== window) {
|
|
details.offsetStart += details.scrollStart;
|
|
}
|
|
details.offsetEnd += details.scrollMaxSize - details.offsetStart;
|
|
}
|
|
|
|
return details
|
|
}
|
|
|
|
function setScroll$1 (parent, scroll, horizontal, rtl) {
|
|
if (parent === window) {
|
|
if (horizontal === true) {
|
|
if (rtl === true) {
|
|
scroll = (buggyRTL === true ? document.body.scrollWidth - window.innerWidth : 0) - scroll;
|
|
}
|
|
window.scrollTo(scroll, window.pageYOffset || window.scrollY || document.body.scrollTop || 0);
|
|
}
|
|
else {
|
|
window.scrollTo(window.pageXOffset || window.scrollX || document.body.scrollLeft || 0, scroll);
|
|
}
|
|
}
|
|
else if (horizontal === true) {
|
|
if (rtl === true) {
|
|
scroll = (buggyRTL === true ? parent.scrollWidth - parent.offsetWidth : 0) - scroll;
|
|
}
|
|
parent.scrollLeft = scroll;
|
|
}
|
|
else {
|
|
parent.scrollTop = scroll;
|
|
}
|
|
}
|
|
|
|
function sumSize (sizeAgg, size, from, to) {
|
|
if (from >= to) { return 0 }
|
|
|
|
var
|
|
lastTo = size.length,
|
|
fromAgg = Math.floor(from / aggBucketSize),
|
|
toAgg = Math.floor((to - 1) / aggBucketSize) + 1;
|
|
|
|
var total = sizeAgg.slice(fromAgg, toAgg).reduce(sumFn, 0);
|
|
|
|
if (from % aggBucketSize !== 0) {
|
|
total -= size.slice(fromAgg * aggBucketSize, from).reduce(sumFn, 0);
|
|
}
|
|
if (to % aggBucketSize !== 0 && to !== lastTo) {
|
|
total -= size.slice(to, toAgg * aggBucketSize).reduce(sumFn, 0);
|
|
}
|
|
|
|
return total
|
|
}
|
|
|
|
var commonVirtScrollProps = {
|
|
virtualScrollSliceSize: {
|
|
type: Number,
|
|
default: null
|
|
},
|
|
|
|
virtualScrollItemSize: {
|
|
type: Number,
|
|
default: 24
|
|
},
|
|
|
|
virtualScrollStickySizeStart: {
|
|
type: Number,
|
|
default: 0
|
|
},
|
|
|
|
virtualScrollStickySizeEnd: {
|
|
type: Number,
|
|
default: 0
|
|
},
|
|
|
|
tableColspan: [ Number, String ]
|
|
};
|
|
|
|
var commonVirtPropsList = Object.keys(commonVirtScrollProps);
|
|
|
|
var VirtualScroll = {
|
|
props: Object.assign({}, {virtualScrollHorizontal: Boolean},
|
|
commonVirtScrollProps),
|
|
|
|
data: function data () {
|
|
return {
|
|
virtualScrollSliceRange: { from: 0, to: 0 }
|
|
}
|
|
},
|
|
|
|
watch: {
|
|
virtualScrollHorizontal: function virtualScrollHorizontal () {
|
|
this.__setVirtualScrollSize();
|
|
},
|
|
|
|
needsReset: function needsReset () {
|
|
this.reset();
|
|
}
|
|
},
|
|
|
|
computed: {
|
|
needsReset: function needsReset () {
|
|
var this$1 = this;
|
|
|
|
return ['virtualScrollItemSize', 'virtualScrollHorizontal']
|
|
.map(function (p) { return this$1[p]; }).join(';')
|
|
},
|
|
|
|
colspanAttr: function colspanAttr () {
|
|
return this.tableColspan !== void 0
|
|
? { colspan: this.tableColspan }
|
|
: { colspan: 100 }
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
reset: function reset () {
|
|
this.__resetVirtualScroll(this.prevToIndex, true);
|
|
},
|
|
|
|
refresh: function refresh (toIndex) {
|
|
this.__resetVirtualScroll(toIndex === void 0 ? this.prevToIndex : toIndex);
|
|
},
|
|
|
|
scrollTo: function scrollTo (toIndex, edge) {
|
|
var scrollEl = this.__getVirtualScrollTarget();
|
|
|
|
if (scrollEl === void 0 || scrollEl === null || scrollEl.nodeType === 8) {
|
|
return
|
|
}
|
|
|
|
var scrollDetails = getScrollDetails(
|
|
scrollEl,
|
|
this.__getVirtualScrollEl(),
|
|
this.$refs.before,
|
|
this.$refs.after,
|
|
this.virtualScrollHorizontal,
|
|
this.$q.lang.rtl,
|
|
this.virtualScrollStickySizeStart,
|
|
this.virtualScrollStickySizeEnd
|
|
);
|
|
|
|
this.__scrollViewSize !== scrollDetails.scrollViewSize && this.__setVirtualScrollSize(scrollDetails.scrollViewSize);
|
|
|
|
this.__setVirtualScrollSliceRange(
|
|
scrollEl,
|
|
scrollDetails,
|
|
Math.min(this.virtualScrollLength - 1, Math.max(0, parseInt(toIndex, 10) || 0)),
|
|
0,
|
|
scrollToEdges.indexOf(edge) > -1 ? edge : (this.prevToIndex > -1 && toIndex > this.prevToIndex ? 'end' : 'start')
|
|
);
|
|
},
|
|
|
|
__onVirtualScrollEvt: function __onVirtualScrollEvt () {
|
|
var scrollEl = this.__getVirtualScrollTarget();
|
|
|
|
if (scrollEl === void 0 || scrollEl === null || scrollEl.nodeType === 8) {
|
|
return
|
|
}
|
|
|
|
var
|
|
scrollDetails = getScrollDetails(
|
|
scrollEl,
|
|
this.__getVirtualScrollEl(),
|
|
this.$refs.before,
|
|
this.$refs.after,
|
|
this.virtualScrollHorizontal,
|
|
this.$q.lang.rtl,
|
|
this.virtualScrollStickySizeStart,
|
|
this.virtualScrollStickySizeEnd
|
|
),
|
|
listLastIndex = this.virtualScrollLength - 1,
|
|
listEndOffset = scrollDetails.scrollMaxSize - scrollDetails.offsetStart - scrollDetails.offsetEnd - this.virtualScrollPaddingAfter;
|
|
|
|
if (this.prevScrollStart === scrollDetails.scrollStart) {
|
|
return
|
|
}
|
|
this.prevScrollStart = void 0;
|
|
|
|
if (scrollDetails.scrollMaxSize <= 0) {
|
|
this.__setVirtualScrollSliceRange(scrollEl, scrollDetails, 0, 0);
|
|
return
|
|
}
|
|
|
|
this.__scrollViewSize !== scrollDetails.scrollViewSize && this.__setVirtualScrollSize(scrollDetails.scrollViewSize);
|
|
|
|
this.__updateVirtualScrollSizes(this.virtualScrollSliceRange.from);
|
|
|
|
var scrollMaxStart = scrollDetails.scrollMaxSize - Math.max(scrollDetails.scrollViewSize, scrollDetails.offsetEnd) - this.virtualScrollSizes[listLastIndex];
|
|
|
|
if (scrollMaxStart > 0 && scrollDetails.scrollStart >= scrollMaxStart) {
|
|
this.__setVirtualScrollSliceRange(
|
|
scrollEl,
|
|
scrollDetails,
|
|
listLastIndex,
|
|
scrollDetails.scrollMaxSize - scrollDetails.offsetEnd - this.virtualScrollSizesAgg.reduce(sumFn, 0)
|
|
);
|
|
|
|
return
|
|
}
|
|
|
|
var
|
|
toIndex = 0,
|
|
listOffset = scrollDetails.scrollStart - scrollDetails.offsetStart,
|
|
offset = listOffset;
|
|
|
|
if (listOffset <= listEndOffset && listOffset + scrollDetails.scrollViewSize >= this.virtualScrollPaddingBefore) {
|
|
listOffset -= this.virtualScrollPaddingBefore;
|
|
toIndex = this.virtualScrollSliceRange.from;
|
|
offset = listOffset;
|
|
}
|
|
else {
|
|
for (var j = 0; listOffset >= this.virtualScrollSizesAgg[j] && toIndex < listLastIndex; j++) {
|
|
listOffset -= this.virtualScrollSizesAgg[j];
|
|
toIndex += aggBucketSize;
|
|
}
|
|
}
|
|
|
|
while (listOffset > 0 && toIndex < listLastIndex) {
|
|
listOffset -= this.virtualScrollSizes[toIndex];
|
|
if (listOffset > -scrollDetails.scrollViewSize) {
|
|
toIndex++;
|
|
offset = listOffset;
|
|
}
|
|
else {
|
|
offset = this.virtualScrollSizes[toIndex] + listOffset;
|
|
}
|
|
}
|
|
|
|
this.__setVirtualScrollSliceRange(
|
|
scrollEl,
|
|
scrollDetails,
|
|
toIndex,
|
|
offset
|
|
);
|
|
},
|
|
|
|
__setVirtualScrollSliceRange: function __setVirtualScrollSliceRange (scrollEl, scrollDetails, toIndex, offset, align) {
|
|
var this$1 = this;
|
|
|
|
var alignForce = typeof align === 'string' && align.indexOf('-force') > -1;
|
|
var alignEnd = alignForce === true ? align.replace('-force', '') : align;
|
|
|
|
var
|
|
from = Math.max(0, Math.ceil(toIndex - this.virtualScrollSliceSizeComputed / (alignEnd === void 0 || alignEnd === 'center' ? 2 : (alignEnd === 'start' ? 3 : 1.5)))),
|
|
to = from + this.virtualScrollSliceSizeComputed;
|
|
|
|
if (to > this.virtualScrollLength) {
|
|
to = this.virtualScrollLength;
|
|
from = Math.max(0, to - this.virtualScrollSliceSizeComputed);
|
|
}
|
|
|
|
var rangeChanged = from !== this.virtualScrollSliceRange.from || to !== this.virtualScrollSliceRange.to;
|
|
|
|
if (rangeChanged === false && alignEnd === void 0) {
|
|
this.__emitScroll(toIndex);
|
|
|
|
return
|
|
}
|
|
|
|
var hadFocus = rangeChanged === true && typeof scrollEl.contains === 'function' && scrollEl.contains(document.activeElement);
|
|
var sizeBefore = alignEnd !== void 0 ? this.virtualScrollSizes.slice(from, toIndex).reduce(sumFn, 0) : 0;
|
|
|
|
if (rangeChanged === true) {
|
|
this.virtualScrollSliceRange = { from: from, to: to };
|
|
this.virtualScrollPaddingBefore = sumSize(this.virtualScrollSizesAgg, this.virtualScrollSizes, 0, from);
|
|
this.virtualScrollPaddingAfter = sumSize(this.virtualScrollSizesAgg, this.virtualScrollSizes, to, this.virtualScrollLength);
|
|
}
|
|
|
|
this.__activeScrollStart = scrollDetails.scrollStart;
|
|
|
|
requestAnimationFrame(function () {
|
|
if (hadFocus === true && scrollEl.contains(document.activeElement) !== true) {
|
|
scrollEl.focus();
|
|
}
|
|
|
|
if (this$1.__activeScrollStart !== scrollDetails.scrollStart) {
|
|
return
|
|
}
|
|
|
|
if (rangeChanged === true) {
|
|
this$1.__updateVirtualScrollSizes(from);
|
|
}
|
|
|
|
var
|
|
sizeAfter = this$1.virtualScrollSizes.slice(from, toIndex).reduce(sumFn, 0),
|
|
posStart = sizeAfter + scrollDetails.offsetStart + this$1.virtualScrollPaddingBefore,
|
|
posEnd = posStart + this$1.virtualScrollSizes[toIndex],
|
|
rtl = this$1.$q.lang.rtl === true;
|
|
|
|
var scrollPosition = posStart + offset;
|
|
|
|
if (alignEnd !== void 0) {
|
|
var sizeDiff = sizeAfter - sizeBefore;
|
|
var scrollStart = scrollDetails.scrollStart + sizeDiff;
|
|
|
|
scrollPosition = alignForce !== true && scrollStart < posStart && posEnd < scrollStart + scrollDetails.scrollViewSize
|
|
? scrollStart
|
|
: (
|
|
alignEnd === 'end'
|
|
? posEnd - scrollDetails.scrollViewSize
|
|
: posStart - (alignEnd === 'start' ? 0 : Math.round((scrollDetails.scrollViewSize - this$1.virtualScrollSizes[toIndex]) / 2))
|
|
);
|
|
}
|
|
|
|
this$1.prevScrollStart = scrollPosition;
|
|
|
|
setScroll$1(
|
|
scrollEl,
|
|
scrollPosition,
|
|
this$1.virtualScrollHorizontal,
|
|
rtl
|
|
);
|
|
|
|
this$1.__emitScroll(toIndex);
|
|
});
|
|
},
|
|
|
|
__updateVirtualScrollSizes: function __updateVirtualScrollSizes (from) {
|
|
var contentEl = this.$refs.content;
|
|
|
|
if (contentEl !== void 0) {
|
|
var
|
|
children = slice.call(contentEl.children).filter(function (el) { return el.classList.contains('q-virtual-scroll--skip') === false; }),
|
|
childrenLength = children.length,
|
|
sizeFn = this.virtualScrollHorizontal === true
|
|
? function (el) { return el.getBoundingClientRect().width; }
|
|
: function (el) { return el.offsetHeight; };
|
|
|
|
var
|
|
index = from,
|
|
size, diff;
|
|
|
|
for (var i = 0; i < childrenLength;) {
|
|
size = sizeFn(children[i]);
|
|
i++;
|
|
|
|
while (i < childrenLength && children[i].classList.contains('q-virtual-scroll--with-prev') === true) {
|
|
size += sizeFn(children[i]);
|
|
i++;
|
|
}
|
|
|
|
diff = size - this.virtualScrollSizes[index];
|
|
|
|
if (diff !== 0) {
|
|
this.virtualScrollSizes[index] += diff;
|
|
this.virtualScrollSizesAgg[Math.floor(index / aggBucketSize)] += diff;
|
|
}
|
|
|
|
index++;
|
|
}
|
|
}
|
|
},
|
|
|
|
__resetVirtualScroll: function __resetVirtualScroll (toIndex, fullReset) {
|
|
var this$1 = this;
|
|
|
|
var defaultSize = this.virtualScrollItemSize;
|
|
|
|
if (fullReset === true || Array.isArray(this.virtualScrollSizes) === false) {
|
|
this.virtualScrollSizes = [];
|
|
}
|
|
|
|
var oldVirtualScrollSizesLength = this.virtualScrollSizes.length;
|
|
|
|
this.virtualScrollSizes.length = this.virtualScrollLength;
|
|
|
|
for (var i = this.virtualScrollLength - 1; i >= oldVirtualScrollSizesLength; i--) {
|
|
this.virtualScrollSizes[i] = defaultSize;
|
|
}
|
|
|
|
var jMax = Math.floor((this.virtualScrollLength - 1) / aggBucketSize);
|
|
this.virtualScrollSizesAgg = [];
|
|
for (var j = 0; j <= jMax; j++) {
|
|
var size = 0;
|
|
var iMax = Math.min((j + 1) * aggBucketSize, this.virtualScrollLength);
|
|
for (var i$1 = j * aggBucketSize; i$1 < iMax; i$1++) {
|
|
size += this.virtualScrollSizes[i$1];
|
|
}
|
|
this.virtualScrollSizesAgg.push(size);
|
|
}
|
|
|
|
this.prevToIndex = -1;
|
|
this.prevScrollStart = void 0;
|
|
|
|
if (toIndex >= 0) {
|
|
this.__updateVirtualScrollSizes(this.virtualScrollSliceRange.from);
|
|
|
|
this.$nextTick(function () {
|
|
this$1.scrollTo(toIndex);
|
|
});
|
|
}
|
|
else {
|
|
this.virtualScrollPaddingBefore = sumSize(this.virtualScrollSizesAgg, this.virtualScrollSizes, 0, this.virtualScrollSliceRange.from);
|
|
this.virtualScrollPaddingAfter = sumSize(this.virtualScrollSizesAgg, this.virtualScrollSizes, this.virtualScrollSliceRange.to, this.virtualScrollLength);
|
|
|
|
this.__onVirtualScrollEvt();
|
|
}
|
|
},
|
|
|
|
__setVirtualScrollSize: function __setVirtualScrollSize (scrollViewSize) {
|
|
if (this.virtualScrollSliceSize > 0) {
|
|
this.virtualScrollSliceSizeComputed = this.virtualScrollSliceSize;
|
|
|
|
return
|
|
}
|
|
|
|
if (scrollViewSize === void 0 && typeof window !== 'undefined') {
|
|
var scrollEl = this.__getVirtualScrollTarget();
|
|
|
|
if (scrollEl !== void 0 && scrollEl !== null && scrollEl.nodeType !== 8) {
|
|
scrollViewSize = getScrollDetails(
|
|
scrollEl,
|
|
this.__getVirtualScrollEl(),
|
|
this.$refs.before,
|
|
this.$refs.after,
|
|
this.virtualScrollHorizontal,
|
|
this.$q.lang.rtl,
|
|
this.virtualScrollStickySizeStart,
|
|
this.virtualScrollStickySizeEnd
|
|
).scrollViewSize;
|
|
}
|
|
}
|
|
|
|
this.__scrollViewSize = scrollViewSize;
|
|
|
|
this.virtualScrollSliceSizeComputed = scrollViewSize === void 0 || scrollViewSize <= 0
|
|
? 30
|
|
: Math.ceil(scrollViewSize / this.virtualScrollItemSize * 3);
|
|
},
|
|
|
|
__padVirtualScroll: function __padVirtualScroll (h, tag, content) {
|
|
var obj, obj$1, obj$2, obj$3;
|
|
|
|
var paddingSize = this.virtualScrollHorizontal === true ? 'width' : 'height';
|
|
|
|
return [
|
|
tag === 'tbody'
|
|
? h(tag, {
|
|
staticClass: 'q-virtual-scroll__padding',
|
|
key: 'before',
|
|
ref: 'before'
|
|
}, [
|
|
h('tr', [
|
|
h('td', {
|
|
style: ( obj = {}, obj[paddingSize] = ((this.virtualScrollPaddingBefore) + "px"), obj ),
|
|
attrs: this.colspanAttr
|
|
})
|
|
])
|
|
])
|
|
: h(tag, {
|
|
staticClass: 'q-virtual-scroll__padding',
|
|
key: 'before',
|
|
ref: 'before',
|
|
style: ( obj$1 = {}, obj$1[paddingSize] = ((this.virtualScrollPaddingBefore) + "px"), obj$1 )
|
|
}),
|
|
|
|
h(tag, {
|
|
staticClass: 'q-virtual-scroll__content',
|
|
key: 'content',
|
|
ref: 'content'
|
|
}, content),
|
|
|
|
tag === 'tbody'
|
|
? h(tag, {
|
|
staticClass: 'q-virtual-scroll__padding',
|
|
key: 'after',
|
|
ref: 'after'
|
|
}, [
|
|
h('tr', [
|
|
h('td', {
|
|
style: ( obj$2 = {}, obj$2[paddingSize] = ((this.virtualScrollPaddingAfter) + "px"), obj$2 ),
|
|
attrs: this.colspanAttr
|
|
})
|
|
])
|
|
])
|
|
: h(tag, {
|
|
staticClass: 'q-virtual-scroll__padding',
|
|
key: 'after',
|
|
ref: 'after',
|
|
style: ( obj$3 = {}, obj$3[paddingSize] = ((this.virtualScrollPaddingAfter) + "px"), obj$3 )
|
|
})
|
|
]
|
|
},
|
|
|
|
__emitScroll: function __emitScroll (index) {
|
|
if (this.prevToIndex !== index) {
|
|
this.qListeners['virtual-scroll'] !== void 0 && this.$emit('virtual-scroll', {
|
|
index: index,
|
|
from: this.virtualScrollSliceRange.from,
|
|
to: this.virtualScrollSliceRange.to - 1,
|
|
direction: index < this.prevToIndex ? 'decrease' : 'increase',
|
|
ref: this
|
|
});
|
|
|
|
this.prevToIndex = index;
|
|
}
|
|
}
|
|
},
|
|
|
|
created: function created () {
|
|
this.__setVirtualScrollSize();
|
|
},
|
|
|
|
beforeMount: function beforeMount () {
|
|
buggyRTL === void 0 && detectBuggyRTL();
|
|
this.__onVirtualScrollEvt = debounce(this.__onVirtualScrollEvt, this.$q.platform.is.ios === true ? 120 : 70);
|
|
this.__setVirtualScrollSize();
|
|
}
|
|
};
|
|
|
|
var validateNewValueMode = function (v) { return ['add', 'add-unique', 'toggle'].includes(v); };
|
|
var reEscapeList = '.*+?^${}()|[]\\';
|
|
|
|
var QSelect = Vue.extend({
|
|
name: 'QSelect',
|
|
|
|
mixins: [
|
|
QField,
|
|
VirtualScroll,
|
|
CompositionMixin,
|
|
FormFieldMixin,
|
|
ListenersMixin
|
|
],
|
|
|
|
props: {
|
|
value: {
|
|
required: true
|
|
},
|
|
|
|
multiple: Boolean,
|
|
|
|
displayValue: [String, Number],
|
|
displayValueSanitize: Boolean,
|
|
dropdownIcon: String,
|
|
|
|
options: {
|
|
type: Array,
|
|
default: function () { return []; }
|
|
},
|
|
|
|
optionValue: [Function, String],
|
|
optionLabel: [Function, String],
|
|
optionDisable: [Function, String],
|
|
|
|
hideSelected: Boolean,
|
|
hideDropdownIcon: Boolean,
|
|
fillInput: Boolean,
|
|
|
|
maxValues: [Number, String],
|
|
|
|
optionsDense: Boolean,
|
|
optionsDark: {
|
|
type: Boolean,
|
|
default: null
|
|
},
|
|
optionsSelectedClass: String,
|
|
optionsSanitize: Boolean,
|
|
|
|
optionsCover: Boolean,
|
|
|
|
menuShrink: Boolean,
|
|
menuAnchor: String,
|
|
menuSelf: String,
|
|
menuOffset: Array,
|
|
|
|
popupContentClass: String,
|
|
popupContentStyle: [String, Array, Object],
|
|
|
|
useInput: Boolean,
|
|
useChips: Boolean,
|
|
|
|
newValueMode: {
|
|
type: String,
|
|
validator: validateNewValueMode
|
|
},
|
|
|
|
mapOptions: Boolean,
|
|
emitValue: Boolean,
|
|
|
|
inputDebounce: {
|
|
type: [Number, String],
|
|
default: 500
|
|
},
|
|
|
|
inputClass: [Array, String, Object],
|
|
inputStyle: [Array, String, Object],
|
|
|
|
tabindex: {
|
|
type: [String, Number],
|
|
default: 0
|
|
},
|
|
|
|
transitionShow: String,
|
|
transitionHide: String,
|
|
|
|
behavior: {
|
|
type: String,
|
|
validator: function (v) { return ['default', 'menu', 'dialog'].includes(v); },
|
|
default: 'default'
|
|
}
|
|
},
|
|
|
|
data: function data () {
|
|
return {
|
|
menu: false,
|
|
dialog: false,
|
|
optionIndex: -1,
|
|
inputValue: '',
|
|
dialogFieldFocused: false
|
|
}
|
|
},
|
|
|
|
watch: {
|
|
innerValue: {
|
|
handler: function handler (val) {
|
|
this.innerValueCache = val;
|
|
|
|
if (
|
|
this.useInput === true &&
|
|
this.fillInput === true &&
|
|
this.multiple !== true &&
|
|
// Prevent re-entering in filter while filtering
|
|
// Also prevent clearing inputValue while filtering
|
|
this.innerLoading !== true &&
|
|
((this.dialog !== true && this.menu !== true) || this.hasValue !== true)
|
|
) {
|
|
this.userInputValue !== true && this.__resetInputValue();
|
|
if (this.dialog === true || this.menu === true) {
|
|
this.filter('');
|
|
}
|
|
}
|
|
},
|
|
immediate: true
|
|
},
|
|
|
|
fillInput: function fillInput () {
|
|
this.__resetInputValue();
|
|
},
|
|
|
|
menu: function menu (show) {
|
|
this.__updateMenu(show);
|
|
}
|
|
},
|
|
|
|
computed: {
|
|
isOptionsDark: function isOptionsDark () {
|
|
return this.optionsDark === null
|
|
? this.isDark
|
|
: this.optionsDark
|
|
},
|
|
|
|
virtualScrollLength: function virtualScrollLength () {
|
|
return Array.isArray(this.options)
|
|
? this.options.length
|
|
: 0
|
|
},
|
|
|
|
fieldClass: function fieldClass () {
|
|
return "q-select q-field--auto-height q-select--with" + (this.useInput !== true ? 'out' : '') + "-input" +
|
|
" q-select--with" + (this.useChips !== true ? 'out' : '') + "-chips" +
|
|
" q-select--" + (this.multiple === true ? 'multiple' : 'single')
|
|
},
|
|
|
|
computedInputClass: function computedInputClass () {
|
|
if (this.hideSelected === true || this.innerValue.length === 0) {
|
|
return this.inputClass
|
|
}
|
|
|
|
return this.inputClass === void 0
|
|
? 'q-field__input--padding'
|
|
: [this.inputClass, 'q-field__input--padding']
|
|
},
|
|
|
|
menuContentClass: function menuContentClass () {
|
|
return (this.virtualScrollHorizontal === true ? 'q-virtual-scroll--horizontal' : '') +
|
|
(this.popupContentClass ? ' ' + this.popupContentClass : '')
|
|
},
|
|
|
|
innerValue: function innerValue () {
|
|
var this$1 = this;
|
|
|
|
var
|
|
mapNull = this.mapOptions === true && this.multiple !== true,
|
|
val = this.value !== void 0 && (this.value !== null || mapNull === true)
|
|
? (this.multiple === true && Array.isArray(this.value) ? this.value : [ this.value ])
|
|
: [];
|
|
|
|
if (this.mapOptions === true && Array.isArray(this.options) === true) {
|
|
var cache = this.mapOptions === true && this.innerValueCache !== void 0
|
|
? this.innerValueCache
|
|
: [];
|
|
var values = val.map(function (v) { return this$1.__getOption(v, cache); });
|
|
|
|
return this.value === null && mapNull === true
|
|
? values.filter(function (v) { return v !== null; })
|
|
: values
|
|
}
|
|
|
|
return val
|
|
},
|
|
|
|
noOptions: function noOptions () {
|
|
return this.virtualScrollLength === 0
|
|
},
|
|
|
|
selectedString: function selectedString () {
|
|
var this$1 = this;
|
|
|
|
return this.innerValue
|
|
.map(function (opt) { return this$1.getOptionLabel(opt); })
|
|
.join(', ')
|
|
},
|
|
|
|
sanitizeFn: function sanitizeFn () {
|
|
return this.optionsSanitize === true
|
|
? function () { return true; }
|
|
: function (opt) { return opt !== void 0 && opt !== null && opt.sanitize === true; }
|
|
},
|
|
|
|
displayAsText: function displayAsText () {
|
|
return this.displayValueSanitize === true || (
|
|
this.displayValue === void 0 && (
|
|
this.optionsSanitize === true ||
|
|
this.innerValue.some(this.sanitizeFn)
|
|
)
|
|
)
|
|
},
|
|
|
|
computedTabindex: function computedTabindex () {
|
|
return this.focused === true ? this.tabindex : -1
|
|
},
|
|
|
|
selectedScope: function selectedScope () {
|
|
var this$1 = this;
|
|
|
|
return this.innerValue.map(function (opt, i) { return ({
|
|
index: i,
|
|
opt: opt,
|
|
sanitize: this$1.sanitizeFn(opt),
|
|
selected: true,
|
|
removeAtIndex: this$1.__removeAtIndexAndFocus,
|
|
toggleOption: this$1.toggleOption,
|
|
tabindex: this$1.computedTabindex
|
|
}); })
|
|
},
|
|
|
|
optionScope: function optionScope () {
|
|
var this$1 = this;
|
|
|
|
if (this.virtualScrollLength === 0) {
|
|
return []
|
|
}
|
|
|
|
var ref = this.virtualScrollSliceRange;
|
|
var from = ref.from;
|
|
var to = ref.to;
|
|
|
|
return this.options.slice(from, to).map(function (opt, i) {
|
|
var disable = this$1.isOptionDisabled(opt) === true;
|
|
var index = from + i;
|
|
|
|
var itemProps = {
|
|
clickable: true,
|
|
active: false,
|
|
activeClass: this$1.computedOptionsSelectedClass,
|
|
manualFocus: true,
|
|
focused: false,
|
|
disable: disable,
|
|
tabindex: -1,
|
|
dense: this$1.optionsDense,
|
|
dark: this$1.isOptionsDark
|
|
};
|
|
|
|
if (disable !== true) {
|
|
this$1.isOptionSelected(opt) === true && (itemProps.active = true);
|
|
this$1.optionIndex === index && (itemProps.focused = true);
|
|
}
|
|
|
|
var itemEvents = {
|
|
click: function () { this$1.toggleOption(opt); }
|
|
};
|
|
|
|
if (this$1.$q.platform.is.desktop === true) {
|
|
itemEvents.mousemove = function () { this$1.setOptionIndex(index); };
|
|
}
|
|
|
|
return {
|
|
index: index,
|
|
opt: opt,
|
|
sanitize: this$1.sanitizeFn(opt),
|
|
selected: itemProps.active,
|
|
focused: itemProps.focused,
|
|
toggleOption: this$1.toggleOption,
|
|
setOptionIndex: this$1.setOptionIndex,
|
|
itemProps: itemProps,
|
|
itemEvents: itemEvents
|
|
}
|
|
})
|
|
},
|
|
|
|
dropdownArrowIcon: function dropdownArrowIcon () {
|
|
return this.dropdownIcon !== void 0
|
|
? this.dropdownIcon
|
|
: this.$q.iconSet.arrow.dropdown
|
|
},
|
|
|
|
squaredMenu: function squaredMenu () {
|
|
return this.optionsCover === false &&
|
|
this.outlined !== true &&
|
|
this.standout !== true &&
|
|
this.borderless !== true &&
|
|
this.rounded !== true
|
|
},
|
|
|
|
computedOptionsSelectedClass: function computedOptionsSelectedClass () {
|
|
return this.optionsSelectedClass !== void 0
|
|
? this.optionsSelectedClass
|
|
: (this.color !== void 0 ? ("text-" + (this.color)) : '')
|
|
},
|
|
|
|
innerOptionsValue: function innerOptionsValue () {
|
|
var this$1 = this;
|
|
|
|
return this.innerValue.map(function (opt) { return this$1.getOptionValue(opt); })
|
|
},
|
|
|
|
// returns method to get value of an option;
|
|
// takes into account 'option-value' prop
|
|
getOptionValue: function getOptionValue () {
|
|
return this.__getPropValueFn('optionValue', 'value')
|
|
},
|
|
|
|
// returns method to get label of an option;
|
|
// takes into account 'option-label' prop
|
|
getOptionLabel: function getOptionLabel () {
|
|
return this.__getPropValueFn('optionLabel', 'label')
|
|
},
|
|
|
|
// returns method to tell if an option is disabled;
|
|
// takes into account 'option-disable' prop
|
|
isOptionDisabled: function isOptionDisabled () {
|
|
return this.__getPropValueFn('optionDisable', 'disable')
|
|
},
|
|
|
|
inputControlEvents: function inputControlEvents () {
|
|
var this$1 = this;
|
|
|
|
var on = {
|
|
input: this.__onInput,
|
|
// Safari < 10.2 & UIWebView doesn't fire compositionend when
|
|
// switching focus before confirming composition choice
|
|
// this also fixes the issue where some browsers e.g. iOS Chrome
|
|
// fires "change" instead of "input" on autocomplete.
|
|
change: this.__onChange,
|
|
keydown: this.__onTargetKeydown,
|
|
keyup: this.__onTargetKeyup,
|
|
keypress: this.__onTargetKeypress,
|
|
focus: this.__selectInputText,
|
|
click: function (e) {
|
|
this$1.hasDialog === true && stop(e);
|
|
}
|
|
};
|
|
|
|
on.compositionstart = on.compositionupdate = on.compositionend = this.__onComposition;
|
|
|
|
return on
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
getEmittingOptionValue: function getEmittingOptionValue (opt) {
|
|
return this.emitValue === true
|
|
? this.getOptionValue(opt)
|
|
: opt
|
|
},
|
|
|
|
removeAtIndex: function removeAtIndex (index) {
|
|
if (index > -1 && index < this.innerValue.length) {
|
|
if (this.multiple === true) {
|
|
var model = this.value.slice();
|
|
this.$emit('remove', { index: index, value: model.splice(index, 1)[0] });
|
|
this.$emit('input', model);
|
|
}
|
|
else {
|
|
this.$emit('input', null);
|
|
}
|
|
}
|
|
},
|
|
|
|
__removeAtIndexAndFocus: function __removeAtIndexAndFocus (index) {
|
|
this.removeAtIndex(index);
|
|
this.__focus();
|
|
},
|
|
|
|
add: function add (opt, unique) {
|
|
var val = this.getEmittingOptionValue(opt);
|
|
|
|
if (this.multiple !== true) {
|
|
this.fillInput === true && this.updateInputValue(
|
|
this.getOptionLabel(opt),
|
|
true,
|
|
true
|
|
);
|
|
|
|
this.$emit('input', val);
|
|
return
|
|
}
|
|
|
|
if (this.innerValue.length === 0) {
|
|
this.$emit('add', { index: 0, value: val });
|
|
this.$emit('input', this.multiple === true ? [ val ] : val);
|
|
return
|
|
}
|
|
|
|
if (unique === true && this.isOptionSelected(opt) === true) {
|
|
return
|
|
}
|
|
|
|
if (this.maxValues !== void 0 && this.value.length >= this.maxValues) {
|
|
return
|
|
}
|
|
|
|
var model = this.value.slice();
|
|
|
|
this.$emit('add', { index: model.length, value: val });
|
|
model.push(val);
|
|
this.$emit('input', model);
|
|
},
|
|
|
|
toggleOption: function toggleOption (opt, keepOpen) {
|
|
if (this.editable !== true || opt === void 0 || this.isOptionDisabled(opt) === true) {
|
|
return
|
|
}
|
|
|
|
var optValue = this.getOptionValue(opt);
|
|
|
|
if (this.multiple !== true) {
|
|
if (keepOpen !== true) {
|
|
this.updateInputValue(
|
|
this.fillInput === true ? this.getOptionLabel(opt) : '',
|
|
true,
|
|
true
|
|
);
|
|
|
|
this.hidePopup();
|
|
}
|
|
|
|
this.$refs.target !== void 0 && this.$refs.target.focus();
|
|
|
|
if (isDeepEqual(this.getOptionValue(this.innerValue[0]), optValue) !== true) {
|
|
this.$emit('input', this.emitValue === true ? optValue : opt);
|
|
}
|
|
return
|
|
}
|
|
|
|
(this.hasDialog !== true || this.dialogFieldFocused === true) && this.__focus();
|
|
|
|
this.__selectInputText();
|
|
|
|
if (this.innerValue.length === 0) {
|
|
var val = this.emitValue === true ? optValue : opt;
|
|
this.$emit('add', { index: 0, value: val });
|
|
this.$emit('input', this.multiple === true ? [ val ] : val);
|
|
return
|
|
}
|
|
|
|
var
|
|
model = this.value.slice(),
|
|
index = this.innerOptionsValue.findIndex(function (v) { return isDeepEqual(v, optValue); });
|
|
|
|
if (index > -1) {
|
|
this.$emit('remove', { index: index, value: model.splice(index, 1)[0] });
|
|
}
|
|
else {
|
|
if (this.maxValues !== void 0 && model.length >= this.maxValues) {
|
|
return
|
|
}
|
|
|
|
var val$1 = this.emitValue === true ? optValue : opt;
|
|
|
|
this.$emit('add', { index: model.length, value: val$1 });
|
|
model.push(val$1);
|
|
}
|
|
|
|
this.$emit('input', model);
|
|
},
|
|
|
|
setOptionIndex: function setOptionIndex (index) {
|
|
if (this.$q.platform.is.desktop !== true) { return }
|
|
|
|
var val = index > -1 && index < this.virtualScrollLength
|
|
? index
|
|
: -1;
|
|
|
|
if (this.optionIndex !== val) {
|
|
this.optionIndex = val;
|
|
}
|
|
},
|
|
|
|
moveOptionSelection: function moveOptionSelection (offset, skipInputValue) {
|
|
if ( offset === void 0 ) offset = 1;
|
|
|
|
if (this.menu === true) {
|
|
var index = this.optionIndex;
|
|
do {
|
|
index = normalizeToInterval(
|
|
index + offset,
|
|
-1,
|
|
this.virtualScrollLength - 1
|
|
);
|
|
}
|
|
while (index !== -1 && index !== this.optionIndex && this.isOptionDisabled(this.options[index]) === true)
|
|
|
|
if (this.optionIndex !== index) {
|
|
this.setOptionIndex(index);
|
|
this.scrollTo(index);
|
|
|
|
if (skipInputValue !== true && this.useInput === true && this.fillInput === true) {
|
|
this.__setInputValue(index >= 0
|
|
? this.getOptionLabel(this.options[index])
|
|
: this.defaultInputValue
|
|
);
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
__getOption: function __getOption (value, innerValueCache) {
|
|
var this$1 = this;
|
|
|
|
var fn = function (opt) { return isDeepEqual(this$1.getOptionValue(opt), value); };
|
|
return this.options.find(fn) || innerValueCache.find(fn) || value
|
|
},
|
|
|
|
__getPropValueFn: function __getPropValueFn (propName, defaultVal) {
|
|
var val = this[propName] !== void 0
|
|
? this[propName]
|
|
: defaultVal;
|
|
|
|
return typeof val === 'function'
|
|
? val
|
|
: function (opt) { return Object(opt) === opt && val in opt
|
|
? opt[val]
|
|
: opt; }
|
|
},
|
|
|
|
isOptionSelected: function isOptionSelected (opt) {
|
|
var val = this.getOptionValue(opt);
|
|
return this.innerOptionsValue.find(function (v) { return isDeepEqual(v, val); }) !== void 0
|
|
},
|
|
|
|
__selectInputText: function __selectInputText () {
|
|
if (this.useInput === true && this.$refs.target !== void 0) {
|
|
this.$refs.target.select();
|
|
}
|
|
},
|
|
|
|
__onTargetKeyup: function __onTargetKeyup (e) {
|
|
// if ESC and we have an opened menu
|
|
// then stop propagation (might be caught by a QDialog
|
|
// and so it will also close the QDialog, which is wrong)
|
|
if (isKeyCode(e, 27) === true && this.menu === true) {
|
|
stop(e);
|
|
// on ESC we need to close the dialog also
|
|
this.hidePopup();
|
|
this.__resetInputValue();
|
|
}
|
|
|
|
this.$emit('keyup', e);
|
|
},
|
|
|
|
__onTargetAutocomplete: function __onTargetAutocomplete (e) {
|
|
var this$1 = this;
|
|
|
|
var ref = e.target;
|
|
var value = ref.value;
|
|
|
|
e.target.value = '';
|
|
|
|
if (e.keyCode !== void 0) {
|
|
this.__onTargetKeyup(e);
|
|
return
|
|
}
|
|
|
|
if (typeof value === 'string' && value.length > 0) {
|
|
var needle = value.toLocaleLowerCase();
|
|
|
|
var fn = function (opt) { return this$1.getOptionValue(opt).toLocaleLowerCase() === needle; };
|
|
var option = this.options.find(fn);
|
|
|
|
if (option !== null) {
|
|
this.innerValue.indexOf(option) === -1 && this.toggleOption(option);
|
|
}
|
|
else {
|
|
fn = function (opt) { return this$1.getOptionLabel(opt).toLocaleLowerCase() === needle; };
|
|
option = this.options.find(fn);
|
|
|
|
if (option !== null) {
|
|
this.innerValue.indexOf(option) === -1 && this.toggleOption(option);
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
__onTargetKeypress: function __onTargetKeypress (e) {
|
|
this.$emit('keypress', e);
|
|
},
|
|
|
|
__onTargetKeydown: function __onTargetKeydown (e) {
|
|
var this$1 = this;
|
|
|
|
this.$emit('keydown', e);
|
|
|
|
if (shouldIgnoreKey(e) === true) {
|
|
return
|
|
}
|
|
|
|
var newValueModeValid = this.inputValue.length > 0 &&
|
|
(this.newValueMode !== void 0 || this.qListeners['new-value'] !== void 0);
|
|
var tabShouldSelect = e.shiftKey !== true &&
|
|
this.multiple !== true &&
|
|
(this.optionIndex > -1 || newValueModeValid === true);
|
|
|
|
// escape
|
|
if (e.keyCode === 27) {
|
|
prevent(e); // prevent clearing the inputValue
|
|
return
|
|
}
|
|
|
|
// tab
|
|
if (e.keyCode === 9 && tabShouldSelect === false) {
|
|
this.__closeMenu();
|
|
return
|
|
}
|
|
|
|
if (e.target === void 0 || e.target.id !== this.targetUid) { return }
|
|
|
|
// down
|
|
if (
|
|
e.keyCode === 40 &&
|
|
this.innerLoading !== true &&
|
|
this.menu === false
|
|
) {
|
|
stopAndPrevent(e);
|
|
this.showPopup();
|
|
return
|
|
}
|
|
|
|
// backspace
|
|
if (
|
|
e.keyCode === 8 &&
|
|
this.multiple === true &&
|
|
this.hideSelected !== true &&
|
|
this.inputValue.length === 0 &&
|
|
Array.isArray(this.value)
|
|
) {
|
|
this.removeAtIndex(this.value.length - 1);
|
|
return
|
|
}
|
|
|
|
// up, down
|
|
if (e.keyCode === 38 || e.keyCode === 40) {
|
|
stopAndPrevent(e);
|
|
this.moveOptionSelection(e.keyCode === 38 ? -1 : 1, this.multiple);
|
|
}
|
|
|
|
var optionsLength = this.virtualScrollLength;
|
|
|
|
// clear search buffer if expired
|
|
if (this.searchBuffer === void 0 || this.searchBufferExp < Date.now()) {
|
|
this.searchBuffer = '';
|
|
}
|
|
|
|
// keyboard search when not having use-input
|
|
if (
|
|
optionsLength > 0 &&
|
|
this.useInput !== true &&
|
|
e.key.length === 1 && // printable char
|
|
e.altKey === e.ctrlKey && // not kbd shortcut
|
|
(e.keyCode !== 32 || this.searchBuffer.length > 0) // space in middle of search
|
|
) {
|
|
this.menu !== true && this.showPopup(e);
|
|
|
|
var
|
|
char = e.key.toLocaleLowerCase(),
|
|
keyRepeat = this.searchBuffer.length === 1 && this.searchBuffer[0] === char;
|
|
|
|
this.searchBufferExp = Date.now() + 1500;
|
|
if (keyRepeat === false) {
|
|
stopAndPrevent(e);
|
|
this.searchBuffer += char;
|
|
}
|
|
|
|
var searchRe = new RegExp('^' + this.searchBuffer.split('').map(function (l) { return reEscapeList.indexOf(l) > -1 ? '\\' + l : l; }).join('.*'), 'i');
|
|
|
|
var index = this.optionIndex;
|
|
|
|
if (keyRepeat === true || index < 0 || searchRe.test(this.getOptionLabel(this.options[index])) !== true) {
|
|
do {
|
|
index = normalizeToInterval(index + 1, -1, optionsLength - 1);
|
|
}
|
|
while (index !== this.optionIndex && (
|
|
this.isOptionDisabled(this.options[index]) === true ||
|
|
searchRe.test(this.getOptionLabel(this.options[index])) !== true
|
|
))
|
|
}
|
|
|
|
if (this.optionIndex !== index) {
|
|
this.$nextTick(function () {
|
|
this$1.setOptionIndex(index);
|
|
this$1.scrollTo(index);
|
|
|
|
if (index >= 0 && this$1.useInput === true && this$1.fillInput === true) {
|
|
this$1.__setInputValue(this$1.getOptionLabel(this$1.options[index]));
|
|
}
|
|
});
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
// enter, space (when not using use-input and not in search), or tab (when not using multiple and option selected)
|
|
// same target is checked above
|
|
if (
|
|
e.keyCode !== 13 &&
|
|
(e.keyCode !== 32 || this.useInput === true || this.searchBuffer !== '') &&
|
|
(e.keyCode !== 9 || tabShouldSelect === false)
|
|
) { return }
|
|
|
|
e.keyCode !== 9 && stopAndPrevent(e);
|
|
|
|
if (this.optionIndex > -1 && this.optionIndex < optionsLength) {
|
|
this.toggleOption(this.options[this.optionIndex]);
|
|
return
|
|
}
|
|
|
|
if (newValueModeValid === true) {
|
|
var done = function (val, mode) {
|
|
if (mode) {
|
|
if (validateNewValueMode(mode) !== true) {
|
|
return
|
|
}
|
|
}
|
|
else {
|
|
mode = this$1.newValueMode;
|
|
}
|
|
|
|
if (val === void 0 || val === null) {
|
|
return
|
|
}
|
|
|
|
this$1.updateInputValue('', this$1.multiple !== true, true);
|
|
|
|
this$1[mode === 'toggle' ? 'toggleOption' : 'add'](
|
|
val,
|
|
mode === 'add-unique'
|
|
);
|
|
|
|
if (this$1.multiple !== true) {
|
|
this$1.$refs.target !== void 0 && this$1.$refs.target.focus();
|
|
this$1.hidePopup();
|
|
}
|
|
};
|
|
|
|
if (this.qListeners['new-value'] !== void 0) {
|
|
this.$emit('new-value', this.inputValue, done);
|
|
}
|
|
else {
|
|
done(this.inputValue);
|
|
}
|
|
|
|
if (this.multiple !== true) {
|
|
return
|
|
}
|
|
}
|
|
|
|
if (this.menu === true) {
|
|
this.__closeMenu();
|
|
}
|
|
else if (this.innerLoading !== true) {
|
|
this.showPopup();
|
|
}
|
|
},
|
|
|
|
__getVirtualScrollEl: function __getVirtualScrollEl () {
|
|
return this.hasDialog === true
|
|
? this.$refs.menuContent
|
|
: (
|
|
this.$refs.menu !== void 0 && this.$refs.menu.__portal !== void 0
|
|
? this.$refs.menu.__portal.$el
|
|
: void 0
|
|
)
|
|
},
|
|
|
|
__getVirtualScrollTarget: function __getVirtualScrollTarget () {
|
|
return this.__getVirtualScrollEl()
|
|
},
|
|
|
|
__getSelection: function __getSelection (h, fromDialog) {
|
|
var this$1 = this;
|
|
var obj;
|
|
|
|
if (this.hideSelected === true) {
|
|
return fromDialog === true || this.dialog !== true || this.hasDialog !== true
|
|
? []
|
|
: [
|
|
h('span', {
|
|
domProps: {
|
|
textContent: this.inputValue
|
|
}
|
|
})
|
|
]
|
|
}
|
|
|
|
if (this.$scopedSlots['selected-item'] !== void 0) {
|
|
return this.selectedScope.map(function (scope) { return this$1.$scopedSlots['selected-item'](scope); }).slice()
|
|
}
|
|
|
|
if (this.$scopedSlots.selected !== void 0) {
|
|
return this.$scopedSlots.selected().slice()
|
|
}
|
|
|
|
if (this.useChips === true) {
|
|
return this.selectedScope.map(function (scope, i) {
|
|
var obj;
|
|
|
|
return h(QChip, {
|
|
key: 'option-' + i,
|
|
props: {
|
|
removable: this$1.editable === true && this$1.isOptionDisabled(scope.opt) !== true,
|
|
dense: true,
|
|
textColor: this$1.color,
|
|
tabindex: this$1.computedTabindex
|
|
},
|
|
on: cache(this$1, 'rem#' + i, {
|
|
remove: function remove () { scope.removeAtIndex(i); }
|
|
})
|
|
}, [
|
|
h('span', {
|
|
staticClass: 'ellipsis',
|
|
domProps: ( obj = {}, obj[scope.sanitize === true ? 'textContent' : 'innerHTML'] = this$1.getOptionLabel(scope.opt), obj )
|
|
})
|
|
]);
|
|
})
|
|
}
|
|
|
|
return [
|
|
h('span', {
|
|
domProps: ( obj = {}, obj[this.displayAsText ? 'textContent' : 'innerHTML'] = this.displayValue !== void 0
|
|
? this.displayValue
|
|
: this.selectedString, obj )
|
|
})
|
|
]
|
|
},
|
|
|
|
__getControl: function __getControl (h, fromDialog) {
|
|
var child = this.__getSelection(h, fromDialog);
|
|
var isTarget = fromDialog === true || this.dialog !== true || this.hasDialog !== true;
|
|
|
|
if (isTarget === true && this.useInput === true) {
|
|
child.push(this.__getInput(h, fromDialog));
|
|
}
|
|
else if (this.editable === true) {
|
|
isTarget === true && child.push(
|
|
h('div', {
|
|
// there can be only one (when dialog is opened the control in dialog should be target)
|
|
ref: 'target',
|
|
key: 'd_t',
|
|
staticClass: 'no-outline',
|
|
attrs: {
|
|
id: this.targetUid,
|
|
tabindex: this.tabindex
|
|
},
|
|
on: cache(this, 'f-tget', {
|
|
keydown: this.__onTargetKeydown,
|
|
keyup: this.__onTargetKeyup,
|
|
keypress: this.__onTargetKeypress
|
|
})
|
|
})
|
|
);
|
|
|
|
this.qAttrs.autocomplete !== void 0 && child.push(
|
|
h('input', {
|
|
staticClass: 'q-select__autocomplete-input no-outline',
|
|
attrs: { autocomplete: this.qAttrs.autocomplete },
|
|
on: cache(this, 'autoinp', {
|
|
keyup: this.__onTargetAutocomplete
|
|
})
|
|
})
|
|
);
|
|
}
|
|
|
|
if (this.nameProp !== void 0 && this.disable !== true && this.innerOptionsValue.length > 0) {
|
|
var opts = this.innerOptionsValue.map(function (value) { return h('option', {
|
|
attrs: { value: value, selected: true }
|
|
}); });
|
|
|
|
child.push(
|
|
h('select', {
|
|
staticClass: 'hidden',
|
|
attrs: {
|
|
name: this.nameProp,
|
|
multiple: this.multiple
|
|
}
|
|
}, opts)
|
|
);
|
|
}
|
|
|
|
return h('div', { staticClass: 'q-field__native row items-center', attrs: this.qAttrs }, child)
|
|
},
|
|
|
|
__getOptions: function __getOptions (h) {
|
|
var this$1 = this;
|
|
|
|
if (this.menu !== true) {
|
|
return void 0
|
|
}
|
|
|
|
var fn = this.$scopedSlots.option !== void 0
|
|
? this.$scopedSlots.option
|
|
: function (scope) {
|
|
var obj;
|
|
|
|
return h(QItem, {
|
|
key: scope.index,
|
|
props: scope.itemProps,
|
|
on: scope.itemEvents
|
|
}, [
|
|
h(QItemSection, [
|
|
h(QItemLabel, {
|
|
domProps: ( obj = {}, obj[scope.sanitize === true ? 'textContent' : 'innerHTML'] = this$1.getOptionLabel(scope.opt), obj )
|
|
})
|
|
])
|
|
]);
|
|
};
|
|
|
|
var options = this.__padVirtualScroll(h, 'div', this.optionScope.map(fn));
|
|
|
|
if (this.$scopedSlots['before-options'] !== void 0) {
|
|
options = this.$scopedSlots['before-options']().concat(options);
|
|
}
|
|
|
|
return mergeSlot(options, this, 'after-options')
|
|
},
|
|
|
|
__getInnerAppend: function __getInnerAppend (h) {
|
|
return this.loading !== true && this.innerLoading !== true && this.hideDropdownIcon !== true
|
|
? [
|
|
h(QIcon, {
|
|
staticClass: 'q-select__dropdown-icon',
|
|
props: { name: this.dropdownArrowIcon }
|
|
})
|
|
]
|
|
: null
|
|
},
|
|
|
|
__getInput: function __getInput (h, fromDialog) {
|
|
var options = {
|
|
ref: 'target',
|
|
key: 'i_t',
|
|
staticClass: 'q-field__input q-placeholder col',
|
|
style: this.inputStyle,
|
|
class: this.computedInputClass,
|
|
domProps: { value: this.inputValue !== void 0 ? this.inputValue : '' },
|
|
attrs: Object.assign({}, {type: 'search'},
|
|
this.qAttrs,
|
|
{id: this.targetUid,
|
|
maxlength: this.maxlength, // this is converted to prop by QField
|
|
tabindex: this.tabindex,
|
|
'data-autofocus': fromDialog === true ? false : this.autofocus,
|
|
disabled: this.disable === true,
|
|
readonly: this.readonly === true}),
|
|
on: this.inputControlEvents
|
|
};
|
|
|
|
if (fromDialog !== true && this.hasDialog === true) {
|
|
options.staticClass += ' no-pointer-events';
|
|
options.attrs.readonly = true;
|
|
}
|
|
|
|
return h('input', options)
|
|
},
|
|
|
|
__onChange: function __onChange (e) {
|
|
this.__onComposition(e);
|
|
},
|
|
|
|
__onInput: function __onInput (e) {
|
|
var this$1 = this;
|
|
|
|
clearTimeout(this.inputTimer);
|
|
|
|
if (e && e.target && e.target.composing === true) {
|
|
return
|
|
}
|
|
|
|
this.__setInputValue(e.target.value || '');
|
|
// mark it here as user input so that if updateInputValue is called
|
|
// before filter is called the indicator is reset
|
|
this.userInputValue = true;
|
|
this.defaultInputValue = this.inputValue;
|
|
|
|
if (
|
|
this.focused !== true &&
|
|
(this.hasDialog !== true || this.dialogFieldFocused === true)
|
|
) {
|
|
this.__focus();
|
|
}
|
|
|
|
if (this.qListeners.filter !== void 0) {
|
|
this.inputTimer = setTimeout(function () {
|
|
this$1.filter(this$1.inputValue);
|
|
}, this.inputDebounce);
|
|
}
|
|
},
|
|
|
|
__setInputValue: function __setInputValue (inputValue) {
|
|
if (this.inputValue !== inputValue) {
|
|
this.inputValue = inputValue;
|
|
this.$emit('input-value', inputValue);
|
|
}
|
|
},
|
|
|
|
updateInputValue: function updateInputValue (val, noFiltering, internal) {
|
|
this.userInputValue = internal !== true;
|
|
|
|
if (this.useInput === true) {
|
|
this.__setInputValue(val);
|
|
|
|
if (noFiltering === true || internal !== true) {
|
|
this.defaultInputValue = val;
|
|
}
|
|
|
|
noFiltering !== true && this.filter(val);
|
|
}
|
|
},
|
|
|
|
filter: function filter (val) {
|
|
var this$1 = this;
|
|
|
|
if (this.qListeners.filter === void 0 || this.focused !== true) {
|
|
return
|
|
}
|
|
|
|
if (this.innerLoading === true) {
|
|
this.$emit('filter-abort');
|
|
}
|
|
else {
|
|
this.innerLoading = true;
|
|
}
|
|
|
|
if (
|
|
val !== '' &&
|
|
this.multiple !== true &&
|
|
this.innerValue.length > 0 &&
|
|
this.userInputValue !== true &&
|
|
val === this.getOptionLabel(this.innerValue[0])
|
|
) {
|
|
val = '';
|
|
}
|
|
|
|
var filterId = setTimeout(function () {
|
|
this$1.menu === true && (this$1.menu = false);
|
|
}, 10);
|
|
clearTimeout(this.filterId);
|
|
this.filterId = filterId;
|
|
|
|
this.$emit(
|
|
'filter',
|
|
val,
|
|
function (fn, afterFn) {
|
|
if (this$1.focused === true && this$1.filterId === filterId) {
|
|
clearTimeout(this$1.filterId);
|
|
|
|
typeof fn === 'function' && fn();
|
|
|
|
this$1.$nextTick(function () {
|
|
this$1.innerLoading = false;
|
|
|
|
if (this$1.editable === true) {
|
|
if (this$1.menu === true) {
|
|
this$1.__updateMenu(true);
|
|
}
|
|
else {
|
|
this$1.menu = true;
|
|
}
|
|
}
|
|
|
|
typeof afterFn === 'function' && this$1.$nextTick(function () { afterFn(this$1); });
|
|
});
|
|
}
|
|
},
|
|
function () {
|
|
if (this$1.focused === true && this$1.filterId === filterId) {
|
|
clearTimeout(this$1.filterId);
|
|
this$1.innerLoading = false;
|
|
}
|
|
this$1.menu === true && (this$1.menu = false);
|
|
}
|
|
);
|
|
},
|
|
|
|
__getControlEvents: function __getControlEvents () {
|
|
var this$1 = this;
|
|
|
|
var focusout = function (e) {
|
|
this$1.__onControlFocusout(e, function () {
|
|
this$1.__resetInputValue();
|
|
this$1.__closeMenu();
|
|
});
|
|
};
|
|
|
|
return {
|
|
focusin: this.__onControlFocusin,
|
|
focusout: focusout,
|
|
'popup-show': this.__onControlPopupShow,
|
|
'popup-hide': function (e) {
|
|
e !== void 0 && stop(e);
|
|
this$1.$emit('popup-hide', e);
|
|
this$1.hasPopupOpen = false;
|
|
focusout(e);
|
|
},
|
|
click: function (e) {
|
|
if (this$1.hasDialog !== true) {
|
|
// label from QField will propagate click on the input (except IE)
|
|
if (
|
|
(this$1.useInput === true && e.target.classList.contains('q-field__input') !== true) ||
|
|
(this$1.useInput !== true && e.target.classList.contains('no-outline') === true)
|
|
) {
|
|
return
|
|
}
|
|
|
|
if (this$1.menu === true) {
|
|
this$1.__closeMenu();
|
|
this$1.$refs.target !== void 0 && this$1.$refs.target.focus();
|
|
return
|
|
}
|
|
}
|
|
|
|
this$1.showPopup(e);
|
|
}
|
|
}
|
|
},
|
|
|
|
__getControlChild: function __getControlChild (h) {
|
|
if (
|
|
this.editable !== false && (
|
|
this.dialog === true || // dialog always has menu displayed, so need to render it
|
|
this.noOptions !== true ||
|
|
this.$scopedSlots['no-option'] !== void 0
|
|
)
|
|
) {
|
|
return this[("__get" + (this.hasDialog === true ? 'Dialog' : 'Menu'))](h)
|
|
}
|
|
},
|
|
|
|
__getMenu: function __getMenu (h) {
|
|
var child = this.noOptions === true
|
|
? (
|
|
this.$scopedSlots['no-option'] !== void 0
|
|
? this.$scopedSlots['no-option']({ inputValue: this.inputValue })
|
|
: null
|
|
)
|
|
: this.__getOptions(h);
|
|
|
|
return h(QMenu, {
|
|
ref: 'menu',
|
|
props: {
|
|
value: this.menu,
|
|
fit: this.menuShrink !== true,
|
|
cover: this.optionsCover === true && this.noOptions !== true && this.useInput !== true,
|
|
anchor: this.menuAnchor,
|
|
self: this.menuSelf,
|
|
offset: this.menuOffset,
|
|
contentClass: this.menuContentClass,
|
|
contentStyle: this.popupContentStyle,
|
|
dark: this.isOptionsDark,
|
|
noParentEvent: true,
|
|
noRefocus: true,
|
|
noFocus: true,
|
|
square: this.squaredMenu,
|
|
transitionShow: this.transitionShow,
|
|
transitionHide: this.transitionHide,
|
|
separateClosePopup: true
|
|
},
|
|
on: cache(this, 'menu', {
|
|
'&scroll': this.__onVirtualScrollEvt,
|
|
'before-hide': this.__closeMenu
|
|
})
|
|
}, child)
|
|
},
|
|
|
|
__onDialogFieldFocus: function __onDialogFieldFocus (e) {
|
|
stop(e);
|
|
this.$refs.target !== void 0 && this.$refs.target.focus();
|
|
this.dialogFieldFocused = true;
|
|
window.scrollTo(window.pageXOffset || window.scrollX || document.body.scrollLeft || 0, 0);
|
|
},
|
|
|
|
__onDialogFieldBlur: function __onDialogFieldBlur (e) {
|
|
var this$1 = this;
|
|
|
|
stop(e);
|
|
this.$nextTick(function () {
|
|
this$1.dialogFieldFocused = false;
|
|
});
|
|
},
|
|
|
|
__getDialog: function __getDialog (h) {
|
|
var this$1 = this;
|
|
|
|
var content = [
|
|
h(QField, {
|
|
staticClass: ("col-auto " + (this.fieldClass)),
|
|
props: Object.assign({}, this.$props,
|
|
{for: this.targetUid,
|
|
dark: this.isOptionsDark,
|
|
square: true,
|
|
loading: this.innerLoading,
|
|
filled: true,
|
|
stackLabel: this.inputValue.length > 0}),
|
|
on: Object.assign({}, this.qListeners,
|
|
{focus: this.__onDialogFieldFocus,
|
|
blur: this.__onDialogFieldBlur}),
|
|
scopedSlots: Object.assign({}, this.$scopedSlots,
|
|
{rawControl: function () { return this$1.__getControl(h, true); },
|
|
before: void 0,
|
|
after: void 0})
|
|
})
|
|
];
|
|
|
|
this.menu === true && content.push(
|
|
h('div', {
|
|
ref: 'menuContent',
|
|
staticClass: 'scroll',
|
|
class: this.menuContentClass,
|
|
style: this.popupContentStyle,
|
|
on: cache(this, 'virtMenu', {
|
|
click: prevent,
|
|
'&scroll': this.__onVirtualScrollEvt
|
|
})
|
|
}, (
|
|
this.noOptions === true
|
|
? (
|
|
this.$scopedSlots['no-option'] !== void 0
|
|
? this.$scopedSlots['no-option']({ inputValue: this.inputValue })
|
|
: null
|
|
)
|
|
: this.__getOptions(h)
|
|
))
|
|
);
|
|
|
|
return h(QDialog, {
|
|
ref: 'dialog',
|
|
props: {
|
|
value: this.dialog,
|
|
dark: this.isOptionsDark,
|
|
position: this.useInput === true ? 'top' : void 0,
|
|
transitionShow: this.transitionShowComputed,
|
|
transitionHide: this.transitionHide
|
|
},
|
|
on: cache(this, 'dialog', {
|
|
'before-hide': this.__onDialogBeforeHide,
|
|
hide: this.__onDialogHide,
|
|
show: this.__onDialogShow
|
|
})
|
|
}, [
|
|
h('div', {
|
|
staticClass: 'q-select__dialog' +
|
|
(this.isOptionsDark === true ? ' q-select__dialog--dark q-dark' : '') +
|
|
(this.dialogFieldFocused === true ? ' q-select__dialog--focused' : '')
|
|
}, content)
|
|
])
|
|
},
|
|
|
|
__onDialogBeforeHide: function __onDialogBeforeHide () {
|
|
this.$refs.dialog.__refocusTarget = this.$el.querySelector('.q-field__native > [tabindex]:last-child');
|
|
this.focused = false;
|
|
},
|
|
|
|
__onDialogHide: function __onDialogHide (e) {
|
|
this.hidePopup();
|
|
this.focused === false && this.$emit('blur', e);
|
|
this.__resetInputValue();
|
|
},
|
|
|
|
__onDialogShow: function __onDialogShow () {
|
|
var el = document.activeElement;
|
|
// IE can have null document.activeElement
|
|
if (
|
|
(el === null || el.id !== this.targetUid) &&
|
|
this.$refs.target !== el &&
|
|
this.$refs.target !== void 0
|
|
) {
|
|
this.$refs.target.focus();
|
|
}
|
|
},
|
|
|
|
__closeMenu: function __closeMenu () {
|
|
if (this.dialog === true) {
|
|
return
|
|
}
|
|
|
|
this.optionIndex = -1;
|
|
|
|
if (this.menu === true) {
|
|
this.menu = false;
|
|
}
|
|
|
|
if (this.focused === false) {
|
|
clearTimeout(this.filterId);
|
|
this.filterId = void 0;
|
|
|
|
if (this.innerLoading === true) {
|
|
this.$emit('filter-abort');
|
|
this.innerLoading = false;
|
|
}
|
|
}
|
|
},
|
|
|
|
showPopup: function showPopup (e) {
|
|
var this$1 = this;
|
|
|
|
if (this.editable !== true) {
|
|
return
|
|
}
|
|
|
|
if (this.hasDialog === true) {
|
|
this.__onControlFocusin(e);
|
|
this.dialog = true;
|
|
this.$nextTick(function () {
|
|
this$1.__focus();
|
|
});
|
|
}
|
|
else {
|
|
this.__focus();
|
|
}
|
|
|
|
if (this.qListeners.filter !== void 0) {
|
|
this.filter(this.inputValue);
|
|
}
|
|
else if (this.noOptions !== true || this.$scopedSlots['no-option'] !== void 0) {
|
|
this.menu = true;
|
|
}
|
|
},
|
|
|
|
hidePopup: function hidePopup () {
|
|
this.dialog = false;
|
|
this.__closeMenu();
|
|
},
|
|
|
|
__resetInputValue: function __resetInputValue () {
|
|
this.useInput === true && this.updateInputValue(
|
|
this.multiple !== true && this.fillInput === true && this.innerValue.length > 0
|
|
? this.getOptionLabel(this.innerValue[0]) || ''
|
|
: '',
|
|
true,
|
|
true
|
|
);
|
|
},
|
|
|
|
__updateMenu: function __updateMenu (show) {
|
|
var this$1 = this;
|
|
|
|
var optionIndex = -1;
|
|
|
|
if (show === true) {
|
|
if (this.innerValue.length > 0) {
|
|
var val = this.getOptionValue(this.innerValue[0]);
|
|
optionIndex = this.options.findIndex(function (v) { return isDeepEqual(this$1.getOptionValue(v), val); });
|
|
}
|
|
|
|
this.__resetVirtualScroll(optionIndex);
|
|
}
|
|
|
|
this.setOptionIndex(optionIndex);
|
|
},
|
|
|
|
__onPreRender: function __onPreRender () {
|
|
this.hasDialog = this.$q.platform.is.mobile !== true && this.behavior !== 'dialog'
|
|
? false
|
|
: this.behavior !== 'menu' && (
|
|
this.useInput === true
|
|
? this.$scopedSlots['no-option'] !== void 0 || this.qListeners.filter !== void 0 || this.noOptions === false
|
|
: true
|
|
);
|
|
|
|
this.transitionShowComputed = this.hasDialog === true && this.useInput === true && this.$q.platform.is.ios === true
|
|
? 'fade'
|
|
: this.transitionShow;
|
|
},
|
|
|
|
__onPostRender: function __onPostRender () {
|
|
if (this.dialog === false && this.$refs.menu !== void 0) {
|
|
this.$refs.menu.updatePosition();
|
|
}
|
|
},
|
|
|
|
updateMenuPosition: function updateMenuPosition () {
|
|
this.__onPostRender();
|
|
}
|
|
},
|
|
|
|
beforeDestroy: function beforeDestroy () {
|
|
clearTimeout(this.inputTimer);
|
|
}
|
|
});
|
|
|
|
var skeletonTypes = [
|
|
'text', 'rect', 'circle',
|
|
'QBtn', 'QBadge', 'QChip', 'QToolbar',
|
|
'QCheckbox', 'QRadio', 'QToggle',
|
|
'QSlider', 'QRange', 'QInput',
|
|
'QAvatar'
|
|
];
|
|
|
|
var skeletonAnimations = [
|
|
'wave', 'pulse', 'pulse-x', 'pulse-y', 'fade', 'blink', 'none'
|
|
];
|
|
|
|
var QSkeleton = Vue.extend({
|
|
name: 'QSkeleton',
|
|
|
|
mixins: [ DarkMixin, TagMixin, ListenersMixin ],
|
|
|
|
props: {
|
|
type: {
|
|
type: String,
|
|
validator: function (v) { return skeletonTypes.includes(v); },
|
|
default: 'rect'
|
|
},
|
|
|
|
animation: {
|
|
type: String,
|
|
validator: function (v) { return skeletonAnimations.includes(v); },
|
|
default: 'wave'
|
|
},
|
|
|
|
square: Boolean,
|
|
bordered: Boolean,
|
|
|
|
size: String,
|
|
width: String,
|
|
height: String
|
|
},
|
|
|
|
computed: {
|
|
style: function style () {
|
|
return this.size !== void 0
|
|
? { width: this.size, height: this.size }
|
|
: { width: this.width, height: this.height }
|
|
},
|
|
|
|
classes: function classes () {
|
|
return "q-skeleton--" + (this.isDark === true ? 'dark' : 'light') + " q-skeleton--type-" + (this.type) +
|
|
(this.animation !== 'none' ? (" q-skeleton--anim q-skeleton--anim-" + (this.animation)) : '') +
|
|
(this.square === true ? ' q-skeleton--square' : '') +
|
|
(this.bordered === true ? ' q-skeleton--bordered' : '')
|
|
}
|
|
},
|
|
|
|
render: function render (h) {
|
|
return h(this.tag, {
|
|
staticClass: 'q-skeleton',
|
|
class: this.classes,
|
|
style: this.style,
|
|
on: Object.assign({}, this.qListeners)
|
|
}, slot(this, 'default'))
|
|
}
|
|
});
|
|
|
|
var slotsDef = [
|
|
['left', 'center', 'start', 'width'],
|
|
['right', 'center', 'end', 'width'],
|
|
['top', 'start', 'center', 'height'],
|
|
['bottom', 'end', 'center', 'height']
|
|
];
|
|
|
|
var QSlideItem = Vue.extend({
|
|
name: 'QSlideItem',
|
|
|
|
mixins: [ DarkMixin, ListenersMixin ],
|
|
|
|
props: {
|
|
leftColor: String,
|
|
rightColor: String,
|
|
topColor: String,
|
|
bottomColor: String
|
|
},
|
|
|
|
directives: {
|
|
TouchPan: TouchPan
|
|
},
|
|
|
|
computed: {
|
|
langDir: function langDir () {
|
|
return this.$q.lang.rtl === true
|
|
? { left: 'right', right: 'left' }
|
|
: { left: 'left', right: 'right' }
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
reset: function reset () {
|
|
this.$refs.content.style.transform = "translate(0,0)";
|
|
},
|
|
|
|
__pan: function __pan (evt) {
|
|
var this$1 = this;
|
|
|
|
var node = this.$refs.content;
|
|
|
|
if (evt.isFirst) {
|
|
this.__dir = null;
|
|
this.__size = { left: 0, right: 0, top: 0, bottom: 0 };
|
|
this.__scale = 0;
|
|
|
|
node.classList.add('no-transition');
|
|
|
|
slotsDef.forEach(function (slot) {
|
|
if (this$1.$scopedSlots[slot[0]] !== void 0) {
|
|
var node = this$1.$refs[slot[0] + 'Content'];
|
|
node.style.transform = "scale(1)";
|
|
this$1.__size[slot[0]] = node.getBoundingClientRect()[slot[3]];
|
|
}
|
|
});
|
|
|
|
this.__axis = (evt.direction === 'up' || evt.direction === 'down')
|
|
? 'Y'
|
|
: 'X';
|
|
}
|
|
else if (evt.isFinal) {
|
|
node.classList.remove('no-transition');
|
|
|
|
if (this.__scale === 1) {
|
|
node.style.transform = "translate" + (this.__axis) + "(" + (this.__dir * 100) + "%)";
|
|
|
|
this.timer = setTimeout(function () {
|
|
this$1.$emit(this$1.__showing, { reset: this$1.reset });
|
|
this$1.$emit('action', { side: this$1.__showing, reset: this$1.reset });
|
|
}, 230);
|
|
}
|
|
else {
|
|
node.style.transform = "translate(0,0)";
|
|
}
|
|
|
|
return
|
|
}
|
|
else {
|
|
evt.direction = this.__axis === 'X'
|
|
? evt.offset.x < 0 ? 'left' : 'right'
|
|
: evt.offset.y < 0 ? 'up' : 'down';
|
|
}
|
|
|
|
if (
|
|
(this.$scopedSlots.left === void 0 && evt.direction === this.langDir.right) ||
|
|
(this.$scopedSlots.right === void 0 && evt.direction === this.langDir.left) ||
|
|
(this.$scopedSlots.top === void 0 && evt.direction === 'down') ||
|
|
(this.$scopedSlots.bottom === void 0 && evt.direction === 'up')
|
|
) {
|
|
node.style.transform = "translate(0,0)";
|
|
return
|
|
}
|
|
|
|
var showing, dir, dist;
|
|
|
|
if (this.__axis === 'X') {
|
|
dir = evt.direction === 'left' ? -1 : 1;
|
|
showing = dir === 1 ? this.langDir.left : this.langDir.right;
|
|
dist = evt.distance.x;
|
|
}
|
|
else {
|
|
dir = evt.direction === 'up' ? -2 : 2;
|
|
showing = dir === 2 ? 'top' : 'bottom';
|
|
dist = evt.distance.y;
|
|
}
|
|
|
|
if (this.__dir !== null && Math.abs(dir) !== Math.abs(this.__dir)) {
|
|
return
|
|
}
|
|
|
|
if (this.__dir !== dir) {
|
|
['left', 'right', 'top', 'bottom'].forEach(function (d) {
|
|
if (this$1.$refs[d] !== void 0) {
|
|
this$1.$refs[d].style.visibility = showing === d
|
|
? 'visible'
|
|
: 'hidden';
|
|
}
|
|
});
|
|
this.__showing = showing;
|
|
this.__dir = dir;
|
|
}
|
|
|
|
this.__scale = Math.max(0, Math.min(1, (dist - 40) / this.__size[showing]));
|
|
|
|
node.style.transform = "translate" + (this.__axis) + "(" + (dist * dir / Math.abs(dir)) + "px)";
|
|
this.$refs[(showing + "Content")].style.transform = "scale(" + (this.__scale) + ")";
|
|
}
|
|
},
|
|
|
|
render: function render (h) {
|
|
var this$1 = this;
|
|
|
|
var
|
|
content = [],
|
|
slots = {
|
|
left: this.$scopedSlots[this.langDir.right] !== void 0,
|
|
right: this.$scopedSlots[this.langDir.left] !== void 0,
|
|
up: this.$scopedSlots.bottom !== void 0,
|
|
down: this.$scopedSlots.top !== void 0
|
|
},
|
|
dirs = Object.keys(slots).filter(function (key) { return slots[key] === true; });
|
|
|
|
slotsDef.forEach(function (slot) {
|
|
var dir = slot[0];
|
|
|
|
if (this$1.$scopedSlots[dir] !== void 0) {
|
|
content.push(
|
|
h('div', {
|
|
ref: dir,
|
|
class: "q-slide-item__" + dir + " absolute-full row no-wrap items-" + (slot[1]) + " justify-" + (slot[2]) +
|
|
(this$1[dir + 'Color'] !== void 0 ? (" bg-" + (this$1[dir + 'Color'])) : '')
|
|
}, [
|
|
h('div', { ref: dir + 'Content' }, this$1.$scopedSlots[dir]())
|
|
])
|
|
);
|
|
}
|
|
});
|
|
|
|
content.push(
|
|
h('div', {
|
|
ref: 'content',
|
|
key: 'content',
|
|
staticClass: 'q-slide-item__content',
|
|
directives: dirs.length > 0
|
|
? cacheWithFn(this, 'dir#' + dirs.join(''), function () {
|
|
var modifiers = {
|
|
prevent: true,
|
|
stop: true,
|
|
mouse: true
|
|
};
|
|
|
|
dirs.forEach(function (dir) {
|
|
modifiers[dir] = true;
|
|
});
|
|
|
|
return [{
|
|
name: 'touch-pan',
|
|
value: this$1.__pan,
|
|
modifiers: modifiers
|
|
}]
|
|
})
|
|
: null
|
|
}, slot(this, 'default'))
|
|
);
|
|
|
|
return h('div', {
|
|
staticClass: 'q-slide-item q-item-type overflow-hidden',
|
|
class: this.isDark === true ? "q-slide-item--dark q-dark" : '',
|
|
on: Object.assign({}, this.qListeners)
|
|
}, content)
|
|
},
|
|
|
|
beforeDestroy: function beforeDestroy () {
|
|
clearTimeout(this.timer);
|
|
}
|
|
});
|
|
|
|
var QSpace = Vue.extend({
|
|
name: 'QSpace',
|
|
|
|
mixins: [ ListenersMixin ],
|
|
|
|
render: function render (h) {
|
|
return h('div', {
|
|
staticClass: 'q-space',
|
|
on: Object.assign({}, this.qListeners)
|
|
})
|
|
}
|
|
});
|
|
|
|
var QSpinnerAudio = Vue.extend({
|
|
name: 'QSpinnerAudio',
|
|
|
|
mixins: [mixin],
|
|
|
|
render: function render (h) {
|
|
return h('svg', {
|
|
staticClass: 'q-spinner',
|
|
class: this.classes,
|
|
on: Object.assign({}, this.qListeners),
|
|
attrs: {
|
|
focusable: 'false' /* needed for IE11 */,
|
|
'fill': 'currentColor',
|
|
'width': this.cSize,
|
|
'height': this.cSize,
|
|
'viewBox': '0 0 55 80',
|
|
'xmlns': 'http://www.w3.org/2000/svg'
|
|
}
|
|
}, [
|
|
h('g', {
|
|
attrs: {
|
|
'transform': 'matrix(1 0 0 -1 0 80)'
|
|
}
|
|
}, [
|
|
h('rect', {
|
|
attrs: {
|
|
'width': '10',
|
|
'height': '20',
|
|
'rx': '3'
|
|
}
|
|
}, [
|
|
h('animate', {
|
|
attrs: {
|
|
'attributeName': 'height',
|
|
'begin': '0s',
|
|
'dur': '4.3s',
|
|
'values': '20;45;57;80;64;32;66;45;64;23;66;13;64;56;34;34;2;23;76;79;20',
|
|
'calcMode': 'linear',
|
|
'repeatCount': 'indefinite'
|
|
}
|
|
})
|
|
]),
|
|
h('rect', {
|
|
attrs: {
|
|
'x': '15',
|
|
'width': '10',
|
|
'height': '80',
|
|
'rx': '3'
|
|
}
|
|
}, [
|
|
h('animate', {
|
|
attrs: {
|
|
'attributeName': 'height',
|
|
'begin': '0s',
|
|
'dur': '2s',
|
|
'values': '80;55;33;5;75;23;73;33;12;14;60;80',
|
|
'calcMode': 'linear',
|
|
'repeatCount': 'indefinite'
|
|
}
|
|
})
|
|
]),
|
|
h('rect', {
|
|
attrs: {
|
|
'x': '30',
|
|
'width': '10',
|
|
'height': '50',
|
|
'rx': '3'
|
|
}
|
|
}, [
|
|
h('animate', {
|
|
attrs: {
|
|
'attributeName': 'height',
|
|
'begin': '0s',
|
|
'dur': '1.4s',
|
|
'values': '50;34;78;23;56;23;34;76;80;54;21;50',
|
|
'calcMode': 'linear',
|
|
'repeatCount': 'indefinite'
|
|
}
|
|
})
|
|
]),
|
|
h('rect', {
|
|
attrs: {
|
|
'x': '45',
|
|
'width': '10',
|
|
'height': '30',
|
|
'rx': '3'
|
|
}
|
|
}, [
|
|
h('animate', {
|
|
attrs: {
|
|
'attributeName': 'height',
|
|
'begin': '0s',
|
|
'dur': '2s',
|
|
'values': '30;45;13;80;56;72;45;76;34;23;67;30',
|
|
'calcMode': 'linear',
|
|
'repeatCount': 'indefinite'
|
|
}
|
|
})
|
|
])
|
|
])
|
|
])
|
|
}
|
|
});
|
|
|
|
var QSpinnerBall = Vue.extend({
|
|
name: 'QSpinnerBall',
|
|
|
|
mixins: [mixin],
|
|
|
|
render: function render (h) {
|
|
return h('svg', {
|
|
staticClass: 'q-spinner',
|
|
class: this.classes,
|
|
on: Object.assign({}, this.qListeners),
|
|
attrs: {
|
|
focusable: 'false' /* needed for IE11 */,
|
|
'stroke': 'currentColor',
|
|
'width': this.cSize,
|
|
'height': this.cSize,
|
|
'viewBox': '0 0 57 57',
|
|
'xmlns': 'http://www.w3.org/2000/svg'
|
|
}
|
|
}, [
|
|
h('g', {
|
|
attrs: {
|
|
'transform': 'translate(1 1)',
|
|
'stroke-width': '2',
|
|
'fill': 'none',
|
|
'fill-rule': 'evenodd'
|
|
}
|
|
}, [
|
|
h('circle', {
|
|
attrs: {
|
|
'cx': '5',
|
|
'cy': '50',
|
|
'r': '5'
|
|
}
|
|
}, [
|
|
h('animate', {
|
|
attrs: {
|
|
'attributeName': 'cy',
|
|
'begin': '0s',
|
|
'dur': '2.2s',
|
|
'values': '50;5;50;50',
|
|
'calcMode': 'linear',
|
|
'repeatCount': 'indefinite'
|
|
}
|
|
}),
|
|
h('animate', {
|
|
attrs: {
|
|
'attributeName': 'cx',
|
|
'begin': '0s',
|
|
'dur': '2.2s',
|
|
'values': '5;27;49;5',
|
|
'calcMode': 'linear',
|
|
'repeatCount': 'indefinite'
|
|
}
|
|
})
|
|
]),
|
|
h('circle', {
|
|
attrs: {
|
|
'cx': '27',
|
|
'cy': '5',
|
|
'r': '5'
|
|
}
|
|
}, [
|
|
h('animate', {
|
|
attrs: {
|
|
'attributeName': 'cy',
|
|
'begin': '0s',
|
|
'dur': '2.2s',
|
|
'from': '5',
|
|
'to': '5',
|
|
'values': '5;50;50;5',
|
|
'calcMode': 'linear',
|
|
'repeatCount': 'indefinite'
|
|
}
|
|
}),
|
|
h('animate', {
|
|
attrs: {
|
|
'attributeName': 'cx',
|
|
'begin': '0s',
|
|
'dur': '2.2s',
|
|
'from': '27',
|
|
'to': '27',
|
|
'values': '27;49;5;27',
|
|
'calcMode': 'linear',
|
|
'repeatCount': 'indefinite'
|
|
}
|
|
})
|
|
]),
|
|
h('circle', {
|
|
attrs: {
|
|
'cx': '49',
|
|
'cy': '50',
|
|
'r': '5'
|
|
}
|
|
}, [
|
|
h('animate', {
|
|
attrs: {
|
|
'attributeName': 'cy',
|
|
'begin': '0s',
|
|
'dur': '2.2s',
|
|
'values': '50;50;5;50',
|
|
'calcMode': 'linear',
|
|
'repeatCount': 'indefinite'
|
|
}
|
|
}),
|
|
h('animate', {
|
|
attrs: {
|
|
'attributeName': 'cx',
|
|
'from': '49',
|
|
'to': '49',
|
|
'begin': '0s',
|
|
'dur': '2.2s',
|
|
'values': '49;5;27;49',
|
|
'calcMode': 'linear',
|
|
'repeatCount': 'indefinite'
|
|
}
|
|
})
|
|
])
|
|
])
|
|
])
|
|
}
|
|
});
|
|
|
|
var QSpinnerBars = Vue.extend({
|
|
name: 'QSpinnerBars',
|
|
|
|
mixins: [mixin],
|
|
|
|
render: function render (h) {
|
|
return h('svg', {
|
|
staticClass: 'q-spinner',
|
|
class: this.classes,
|
|
on: Object.assign({}, this.qListeners),
|
|
attrs: {
|
|
focusable: 'false' /* needed for IE11 */,
|
|
'fill': 'currentColor',
|
|
'width': this.cSize,
|
|
'height': this.cSize,
|
|
'viewBox': '0 0 135 140',
|
|
'xmlns': 'http://www.w3.org/2000/svg'
|
|
}
|
|
}, [
|
|
h('rect', {
|
|
attrs: {
|
|
'y': '10',
|
|
'width': '15',
|
|
'height': '120',
|
|
'rx': '6'
|
|
}
|
|
}, [
|
|
h('animate', {
|
|
attrs: {
|
|
'attributeName': 'height',
|
|
'begin': '0.5s',
|
|
'dur': '1s',
|
|
'values': '120;110;100;90;80;70;60;50;40;140;120',
|
|
'calcMode': 'linear',
|
|
'repeatCount': 'indefinite'
|
|
}
|
|
}),
|
|
h('animate', {
|
|
attrs: {
|
|
'attributeName': 'y',
|
|
'begin': '0.5s',
|
|
'dur': '1s',
|
|
'values': '10;15;20;25;30;35;40;45;50;0;10',
|
|
'calcMode': 'linear',
|
|
'repeatCount': 'indefinite'
|
|
}
|
|
})
|
|
]),
|
|
h('rect', {
|
|
attrs: {
|
|
'x': '30',
|
|
'y': '10',
|
|
'width': '15',
|
|
'height': '120',
|
|
'rx': '6'
|
|
}
|
|
}, [
|
|
h('animate', {
|
|
attrs: {
|
|
'attributeName': 'height',
|
|
'begin': '0.25s',
|
|
'dur': '1s',
|
|
'values': '120;110;100;90;80;70;60;50;40;140;120',
|
|
'calcMode': 'linear',
|
|
'repeatCount': 'indefinite'
|
|
}
|
|
}),
|
|
h('animate', {
|
|
attrs: {
|
|
'attributeName': 'y',
|
|
'begin': '0.25s',
|
|
'dur': '1s',
|
|
'values': '10;15;20;25;30;35;40;45;50;0;10',
|
|
'calcMode': 'linear',
|
|
'repeatCount': 'indefinite'
|
|
}
|
|
})
|
|
]),
|
|
h('rect', {
|
|
attrs: {
|
|
'x': '60',
|
|
'width': '15',
|
|
'height': '140',
|
|
'rx': '6'
|
|
}
|
|
}, [
|
|
h('animate', {
|
|
attrs: {
|
|
'attributeName': 'height',
|
|
'begin': '0s',
|
|
'dur': '1s',
|
|
'values': '120;110;100;90;80;70;60;50;40;140;120',
|
|
'calcMode': 'linear',
|
|
'repeatCount': 'indefinite'
|
|
}
|
|
}),
|
|
h('animate', {
|
|
attrs: {
|
|
'attributeName': 'y',
|
|
'begin': '0s',
|
|
'dur': '1s',
|
|
'values': '10;15;20;25;30;35;40;45;50;0;10',
|
|
'calcMode': 'linear',
|
|
'repeatCount': 'indefinite'
|
|
}
|
|
})
|
|
]),
|
|
h('rect', {
|
|
attrs: {
|
|
'x': '90',
|
|
'y': '10',
|
|
'width': '15',
|
|
'height': '120',
|
|
'rx': '6'
|
|
}
|
|
}, [
|
|
h('animate', {
|
|
attrs: {
|
|
'attributeName': 'height',
|
|
'begin': '0.25s',
|
|
'dur': '1s',
|
|
'values': '120;110;100;90;80;70;60;50;40;140;120',
|
|
'calcMode': 'linear',
|
|
'repeatCount': 'indefinite'
|
|
}
|
|
}),
|
|
h('animate', {
|
|
attrs: {
|
|
'attributeName': 'y',
|
|
'begin': '0.25s',
|
|
'dur': '1s',
|
|
'values': '10;15;20;25;30;35;40;45;50;0;10',
|
|
'calcMode': 'linear',
|
|
'repeatCount': 'indefinite'
|
|
}
|
|
})
|
|
]),
|
|
h('rect', {
|
|
attrs: {
|
|
'x': '120',
|
|
'y': '10',
|
|
'width': '15',
|
|
'height': '120',
|
|
'rx': '6'
|
|
}
|
|
}, [
|
|
h('animate', {
|
|
attrs: {
|
|
'attributeName': 'height',
|
|
'begin': '0.5s',
|
|
'dur': '1s',
|
|
'values': '120;110;100;90;80;70;60;50;40;140;120',
|
|
'calcMode': 'linear',
|
|
'repeatCount': 'indefinite'
|
|
}
|
|
}),
|
|
h('animate', {
|
|
attrs: {
|
|
'attributeName': 'y',
|
|
'begin': '0.5s',
|
|
'dur': '1s',
|
|
'values': '10;15;20;25;30;35;40;45;50;0;10',
|
|
'calcMode': 'linear',
|
|
'repeatCount': 'indefinite'
|
|
}
|
|
})
|
|
])
|
|
])
|
|
}
|
|
});
|
|
|
|
var QSpinnerComment = Vue.extend({
|
|
name: 'QSpinnerComment',
|
|
|
|
mixins: [mixin],
|
|
|
|
render: function render (h) {
|
|
return h('svg', {
|
|
staticClass: 'q-spinner',
|
|
class: this.classes,
|
|
on: Object.assign({}, this.qListeners),
|
|
attrs: {
|
|
focusable: 'false' /* needed for IE11 */,
|
|
'width': this.cSize,
|
|
'height': this.cSize,
|
|
'xmlns': 'http://www.w3.org/2000/svg',
|
|
'viewBox': '0 0 100 100',
|
|
'preserveAspectRatio': 'xMidYMid'
|
|
}
|
|
}, [
|
|
h('rect', {
|
|
attrs: {
|
|
'x': '0',
|
|
'y': '0',
|
|
'width': '100',
|
|
'height': '100',
|
|
'fill': 'none'
|
|
}
|
|
}),
|
|
h('path', {
|
|
attrs: {
|
|
'd': 'M78,19H22c-6.6,0-12,5.4-12,12v31c0,6.6,5.4,12,12,12h37.2c0.4,3,1.8,5.6,3.7,7.6c2.4,2.5,5.1,4.1,9.1,4 c-1.4-2.1-2-7.2-2-10.3c0-0.4,0-0.8,0-1.3h8c6.6,0,12-5.4,12-12V31C90,24.4,84.6,19,78,19z',
|
|
'fill': 'currentColor'
|
|
}
|
|
}),
|
|
h('circle', {
|
|
attrs: {
|
|
'cx': '30',
|
|
'cy': '47',
|
|
'r': '5',
|
|
'fill': '#fff'
|
|
}
|
|
}, [
|
|
h('animate', {
|
|
attrs: {
|
|
'attributeName': 'opacity',
|
|
'from': '0',
|
|
'to': '1',
|
|
'values': '0;1;1',
|
|
'keyTimes': '0;0.2;1',
|
|
'dur': '1s',
|
|
'repeatCount': 'indefinite'
|
|
}
|
|
})
|
|
]),
|
|
h('circle', {
|
|
attrs: {
|
|
'cx': '50',
|
|
'cy': '47',
|
|
'r': '5',
|
|
'fill': '#fff'
|
|
}
|
|
}, [
|
|
h('animate', {
|
|
attrs: {
|
|
'attributeName': 'opacity',
|
|
'from': '0',
|
|
'to': '1',
|
|
'values': '0;0;1;1',
|
|
'keyTimes': '0;0.2;0.4;1',
|
|
'dur': '1s',
|
|
'repeatCount': 'indefinite'
|
|
}
|
|
})
|
|
]),
|
|
h('circle', {
|
|
attrs: {
|
|
'cx': '70',
|
|
'cy': '47',
|
|
'r': '5',
|
|
'fill': '#fff'
|
|
}
|
|
}, [
|
|
h('animate', {
|
|
attrs: {
|
|
'attributeName': 'opacity',
|
|
'from': '0',
|
|
'to': '1',
|
|
'values': '0;0;1;1',
|
|
'keyTimes': '0;0.4;0.6;1',
|
|
'dur': '1s',
|
|
'repeatCount': 'indefinite'
|
|
}
|
|
})
|
|
])
|
|
])
|
|
}
|
|
});
|
|
|
|
var QSpinnerCube = Vue.extend({
|
|
name: 'QSpinnerCube',
|
|
|
|
mixins: [mixin],
|
|
|
|
render: function render (h) {
|
|
return h('svg', {
|
|
staticClass: 'q-spinner',
|
|
class: this.classes,
|
|
on: Object.assign({}, this.qListeners),
|
|
attrs: {
|
|
focusable: 'false' /* needed for IE11 */,
|
|
'width': this.cSize,
|
|
'height': this.cSize,
|
|
'xmlns': 'http://www.w3.org/2000/svg',
|
|
'viewBox': '0 0 100 100',
|
|
'preserveAspectRatio': 'xMidYMid'
|
|
}
|
|
}, [
|
|
h('rect', {
|
|
attrs: {
|
|
'x': '0',
|
|
'y': '0',
|
|
'width': '100',
|
|
'height': '100',
|
|
'fill': 'none'
|
|
}
|
|
}),
|
|
h('g', {
|
|
attrs: {
|
|
'transform': 'translate(25 25)'
|
|
}
|
|
}, [
|
|
h('rect', {
|
|
attrs: {
|
|
'x': '-20',
|
|
'y': '-20',
|
|
'width': '40',
|
|
'height': '40',
|
|
'fill': 'currentColor',
|
|
'opacity': '0.9'
|
|
}
|
|
}, [
|
|
h('animateTransform', {
|
|
attrs: {
|
|
'attributeName': 'transform',
|
|
'type': 'scale',
|
|
'from': '1.5',
|
|
'to': '1',
|
|
'repeatCount': 'indefinite',
|
|
'begin': '0s',
|
|
'dur': '1s',
|
|
'calcMode': 'spline',
|
|
'keySplines': '0.2 0.8 0.2 0.8',
|
|
'keyTimes': '0;1'
|
|
}
|
|
})
|
|
])
|
|
]),
|
|
h('g', {
|
|
attrs: {
|
|
'transform': 'translate(75 25)'
|
|
}
|
|
}, [
|
|
h('rect', {
|
|
attrs: {
|
|
'x': '-20',
|
|
'y': '-20',
|
|
'width': '40',
|
|
'height': '40',
|
|
'fill': 'currentColor',
|
|
'opacity': '0.8'
|
|
}
|
|
}, [
|
|
h('animateTransform', {
|
|
attrs: {
|
|
'attributeName': 'transform',
|
|
'type': 'scale',
|
|
'from': '1.5',
|
|
'to': '1',
|
|
'repeatCount': 'indefinite',
|
|
'begin': '0.1s',
|
|
'dur': '1s',
|
|
'calcMode': 'spline',
|
|
'keySplines': '0.2 0.8 0.2 0.8',
|
|
'keyTimes': '0;1'
|
|
}
|
|
})
|
|
])
|
|
]),
|
|
h('g', {
|
|
attrs: {
|
|
'transform': 'translate(25 75)'
|
|
}
|
|
}, [
|
|
h('rect', {
|
|
staticClass: 'cube',
|
|
attrs: {
|
|
'x': '-20',
|
|
'y': '-20',
|
|
'width': '40',
|
|
'height': '40',
|
|
'fill': 'currentColor',
|
|
'opacity': '0.7'
|
|
}
|
|
}, [
|
|
h('animateTransform', {
|
|
attrs: {
|
|
'attributeName': 'transform',
|
|
'type': 'scale',
|
|
'from': '1.5',
|
|
'to': '1',
|
|
'repeatCount': 'indefinite',
|
|
'begin': '0.3s',
|
|
'dur': '1s',
|
|
'calcMode': 'spline',
|
|
'keySplines': '0.2 0.8 0.2 0.8',
|
|
'keyTimes': '0;1'
|
|
}
|
|
})
|
|
])
|
|
]),
|
|
h('g', {
|
|
attrs: {
|
|
'transform': 'translate(75 75)'
|
|
}
|
|
}, [
|
|
h('rect', {
|
|
staticClass: 'cube',
|
|
attrs: {
|
|
'x': '-20',
|
|
'y': '-20',
|
|
'width': '40',
|
|
'height': '40',
|
|
'fill': 'currentColor',
|
|
'opacity': '0.6'
|
|
}
|
|
}, [
|
|
h('animateTransform', {
|
|
attrs: {
|
|
'attributeName': 'transform',
|
|
'type': 'scale',
|
|
'from': '1.5',
|
|
'to': '1',
|
|
'repeatCount': 'indefinite',
|
|
'begin': '0.2s',
|
|
'dur': '1s',
|
|
'calcMode': 'spline',
|
|
'keySplines': '0.2 0.8 0.2 0.8',
|
|
'keyTimes': '0;1'
|
|
}
|
|
})
|
|
])
|
|
])
|
|
])
|
|
}
|
|
});
|
|
|
|
var QSpinnerDots = Vue.extend({
|
|
name: 'QSpinnerDots',
|
|
|
|
mixins: [mixin],
|
|
|
|
render: function render (h) {
|
|
return h('svg', {
|
|
staticClass: 'q-spinner',
|
|
class: this.classes,
|
|
on: Object.assign({}, this.qListeners),
|
|
attrs: {
|
|
focusable: 'false' /* needed for IE11 */,
|
|
'fill': 'currentColor',
|
|
'width': this.cSize,
|
|
'height': this.cSize,
|
|
'viewBox': '0 0 120 30',
|
|
'xmlns': 'http://www.w3.org/2000/svg'
|
|
}
|
|
}, [
|
|
h('circle', {
|
|
attrs: {
|
|
'cx': '15',
|
|
'cy': '15',
|
|
'r': '15'
|
|
}
|
|
}, [
|
|
h('animate', {
|
|
attrs: {
|
|
'attributeName': 'r',
|
|
'from': '15',
|
|
'to': '15',
|
|
'begin': '0s',
|
|
'dur': '0.8s',
|
|
'values': '15;9;15',
|
|
'calcMode': 'linear',
|
|
'repeatCount': 'indefinite'
|
|
}
|
|
}),
|
|
h('animate', {
|
|
attrs: {
|
|
'attributeName': 'fill-opacity',
|
|
'from': '1',
|
|
'to': '1',
|
|
'begin': '0s',
|
|
'dur': '0.8s',
|
|
'values': '1;.5;1',
|
|
'calcMode': 'linear',
|
|
'repeatCount': 'indefinite'
|
|
}
|
|
})
|
|
]),
|
|
h('circle', {
|
|
attrs: {
|
|
'cx': '60',
|
|
'cy': '15',
|
|
'r': '9',
|
|
'fill-opacity': '.3'
|
|
}
|
|
}, [
|
|
h('animate', {
|
|
attrs: {
|
|
'attributeName': 'r',
|
|
'from': '9',
|
|
'to': '9',
|
|
'begin': '0s',
|
|
'dur': '0.8s',
|
|
'values': '9;15;9',
|
|
'calcMode': 'linear',
|
|
'repeatCount': 'indefinite'
|
|
}
|
|
}),
|
|
h('animate', {
|
|
attrs: {
|
|
'attributeName': 'fill-opacity',
|
|
'from': '.5',
|
|
'to': '.5',
|
|
'begin': '0s',
|
|
'dur': '0.8s',
|
|
'values': '.5;1;.5',
|
|
'calcMode': 'linear',
|
|
'repeatCount': 'indefinite'
|
|
}
|
|
})
|
|
]),
|
|
h('circle', {
|
|
attrs: {
|
|
'cx': '105',
|
|
'cy': '15',
|
|
'r': '15'
|
|
}
|
|
}, [
|
|
h('animate', {
|
|
attrs: {
|
|
'attributeName': 'r',
|
|
'from': '15',
|
|
'to': '15',
|
|
'begin': '0s',
|
|
'dur': '0.8s',
|
|
'values': '15;9;15',
|
|
'calcMode': 'linear',
|
|
'repeatCount': 'indefinite'
|
|
}
|
|
}),
|
|
h('animate', {
|
|
attrs: {
|
|
'attributeName': 'fill-opacity',
|
|
'from': '1',
|
|
'to': '1',
|
|
'begin': '0s',
|
|
'dur': '0.8s',
|
|
'values': '1;.5;1',
|
|
'calcMode': 'linear',
|
|
'repeatCount': 'indefinite'
|
|
}
|
|
})
|
|
])
|
|
])
|
|
}
|
|
});
|
|
|
|
var QSpinnerFacebook = Vue.extend({
|
|
name: 'QSpinnerFacebook',
|
|
|
|
mixins: [mixin],
|
|
|
|
render: function render (h) {
|
|
return h('svg', {
|
|
staticClass: 'q-spinner',
|
|
class: this.classes,
|
|
on: Object.assign({}, this.qListeners),
|
|
attrs: {
|
|
focusable: 'false' /* needed for IE11 */,
|
|
'width': this.cSize,
|
|
'height': this.cSize,
|
|
'viewBox': '0 0 100 100',
|
|
'xmlns': 'http://www.w3.org/2000/svg',
|
|
'preserveAspectRatio': 'xMidYMid'
|
|
}
|
|
}, [
|
|
h('g', {
|
|
attrs: {
|
|
'transform': 'translate(20 50)'
|
|
}
|
|
}, [
|
|
h('rect', {
|
|
attrs: {
|
|
'x': '-10',
|
|
'y': '-30',
|
|
'width': '20',
|
|
'height': '60',
|
|
'fill': 'currentColor',
|
|
'opacity': '0.6'
|
|
}
|
|
}, [
|
|
h('animateTransform', {
|
|
attrs: {
|
|
'attributeName': 'transform',
|
|
'type': 'scale',
|
|
'from': '2',
|
|
'to': '1',
|
|
'begin': '0s',
|
|
'repeatCount': 'indefinite',
|
|
'dur': '1s',
|
|
'calcMode': 'spline',
|
|
'keySplines': '0.1 0.9 0.4 1',
|
|
'keyTimes': '0;1',
|
|
'values': '2;1'
|
|
}
|
|
})
|
|
])
|
|
]),
|
|
h('g', {
|
|
attrs: {
|
|
'transform': 'translate(50 50)'
|
|
}
|
|
}, [
|
|
h('rect', {
|
|
attrs: {
|
|
'x': '-10',
|
|
'y': '-30',
|
|
'width': '20',
|
|
'height': '60',
|
|
'fill': 'currentColor',
|
|
'opacity': '0.8'
|
|
}
|
|
}, [
|
|
h('animateTransform', {
|
|
attrs: {
|
|
'attributeName': 'transform',
|
|
'type': 'scale',
|
|
'from': '2',
|
|
'to': '1',
|
|
'begin': '0.1s',
|
|
'repeatCount': 'indefinite',
|
|
'dur': '1s',
|
|
'calcMode': 'spline',
|
|
'keySplines': '0.1 0.9 0.4 1',
|
|
'keyTimes': '0;1',
|
|
'values': '2;1'
|
|
}
|
|
})
|
|
])
|
|
]),
|
|
h('g', {
|
|
attrs: {
|
|
'transform': 'translate(80 50)'
|
|
}
|
|
}, [
|
|
h('rect', {
|
|
attrs: {
|
|
'x': '-10',
|
|
'y': '-30',
|
|
'width': '20',
|
|
'height': '60',
|
|
'fill': 'currentColor',
|
|
'opacity': '0.9'
|
|
}
|
|
}, [
|
|
h('animateTransform', {
|
|
attrs: {
|
|
'attributeName': 'transform',
|
|
'type': 'scale',
|
|
'from': '2',
|
|
'to': '1',
|
|
'begin': '0.2s',
|
|
'repeatCount': 'indefinite',
|
|
'dur': '1s',
|
|
'calcMode': 'spline',
|
|
'keySplines': '0.1 0.9 0.4 1',
|
|
'keyTimes': '0;1',
|
|
'values': '2;1'
|
|
}
|
|
})
|
|
])
|
|
])
|
|
])
|
|
}
|
|
});
|
|
|
|
var QSpinnerGears = Vue.extend({
|
|
name: 'QSpinnerGears',
|
|
|
|
mixins: [mixin],
|
|
|
|
render: function render (h) {
|
|
return h('svg', {
|
|
staticClass: 'q-spinner',
|
|
class: this.classes,
|
|
on: Object.assign({}, this.qListeners),
|
|
attrs: {
|
|
focusable: 'false' /* needed for IE11 */,
|
|
'width': this.cSize,
|
|
'height': this.cSize,
|
|
'viewBox': '0 0 100 100',
|
|
'preserveAspectRatio': 'xMidYMid',
|
|
'xmlns': 'http://www.w3.org/2000/svg'
|
|
}
|
|
}, [
|
|
h('g', {
|
|
attrs: {
|
|
'transform': 'translate(-20,-20)'
|
|
}
|
|
}, [
|
|
h('path', {
|
|
attrs: {
|
|
'd': 'M79.9,52.6C80,51.8,80,50.9,80,50s0-1.8-0.1-2.6l-5.1-0.4c-0.3-2.4-0.9-4.6-1.8-6.7l4.2-2.9c-0.7-1.6-1.6-3.1-2.6-4.5 L70,35c-1.4-1.9-3.1-3.5-4.9-4.9l2.2-4.6c-1.4-1-2.9-1.9-4.5-2.6L59.8,27c-2.1-0.9-4.4-1.5-6.7-1.8l-0.4-5.1C51.8,20,50.9,20,50,20 s-1.8,0-2.6,0.1l-0.4,5.1c-2.4,0.3-4.6,0.9-6.7,1.8l-2.9-4.1c-1.6,0.7-3.1,1.6-4.5,2.6l2.1,4.6c-1.9,1.4-3.5,3.1-5,4.9l-4.5-2.1 c-1,1.4-1.9,2.9-2.6,4.5l4.1,2.9c-0.9,2.1-1.5,4.4-1.8,6.8l-5,0.4C20,48.2,20,49.1,20,50s0,1.8,0.1,2.6l5,0.4 c0.3,2.4,0.9,4.7,1.8,6.8l-4.1,2.9c0.7,1.6,1.6,3.1,2.6,4.5l4.5-2.1c1.4,1.9,3.1,3.5,5,4.9l-2.1,4.6c1.4,1,2.9,1.9,4.5,2.6l2.9-4.1 c2.1,0.9,4.4,1.5,6.7,1.8l0.4,5.1C48.2,80,49.1,80,50,80s1.8,0,2.6-0.1l0.4-5.1c2.3-0.3,4.6-0.9,6.7-1.8l2.9,4.2 c1.6-0.7,3.1-1.6,4.5-2.6L65,69.9c1.9-1.4,3.5-3,4.9-4.9l4.6,2.2c1-1.4,1.9-2.9,2.6-4.5L73,59.8c0.9-2.1,1.5-4.4,1.8-6.7L79.9,52.6 z M50,65c-8.3,0-15-6.7-15-15c0-8.3,6.7-15,15-15s15,6.7,15,15C65,58.3,58.3,65,50,65z',
|
|
'fill': 'currentColor'
|
|
}
|
|
}, [
|
|
h('animateTransform', {
|
|
attrs: {
|
|
'attributeName': 'transform',
|
|
'type': 'rotate',
|
|
'from': '90 50 50',
|
|
'to': '0 50 50',
|
|
'dur': '1s',
|
|
'repeatCount': 'indefinite'
|
|
}
|
|
})
|
|
])
|
|
]),
|
|
h('g', {
|
|
attrs: {
|
|
'transform': 'translate(20,20) rotate(15 50 50)'
|
|
}
|
|
}, [
|
|
h('path', {
|
|
attrs: {
|
|
'd': 'M79.9,52.6C80,51.8,80,50.9,80,50s0-1.8-0.1-2.6l-5.1-0.4c-0.3-2.4-0.9-4.6-1.8-6.7l4.2-2.9c-0.7-1.6-1.6-3.1-2.6-4.5 L70,35c-1.4-1.9-3.1-3.5-4.9-4.9l2.2-4.6c-1.4-1-2.9-1.9-4.5-2.6L59.8,27c-2.1-0.9-4.4-1.5-6.7-1.8l-0.4-5.1C51.8,20,50.9,20,50,20 s-1.8,0-2.6,0.1l-0.4,5.1c-2.4,0.3-4.6,0.9-6.7,1.8l-2.9-4.1c-1.6,0.7-3.1,1.6-4.5,2.6l2.1,4.6c-1.9,1.4-3.5,3.1-5,4.9l-4.5-2.1 c-1,1.4-1.9,2.9-2.6,4.5l4.1,2.9c-0.9,2.1-1.5,4.4-1.8,6.8l-5,0.4C20,48.2,20,49.1,20,50s0,1.8,0.1,2.6l5,0.4 c0.3,2.4,0.9,4.7,1.8,6.8l-4.1,2.9c0.7,1.6,1.6,3.1,2.6,4.5l4.5-2.1c1.4,1.9,3.1,3.5,5,4.9l-2.1,4.6c1.4,1,2.9,1.9,4.5,2.6l2.9-4.1 c2.1,0.9,4.4,1.5,6.7,1.8l0.4,5.1C48.2,80,49.1,80,50,80s1.8,0,2.6-0.1l0.4-5.1c2.3-0.3,4.6-0.9,6.7-1.8l2.9,4.2 c1.6-0.7,3.1-1.6,4.5-2.6L65,69.9c1.9-1.4,3.5-3,4.9-4.9l4.6,2.2c1-1.4,1.9-2.9,2.6-4.5L73,59.8c0.9-2.1,1.5-4.4,1.8-6.7L79.9,52.6 z M50,65c-8.3,0-15-6.7-15-15c0-8.3,6.7-15,15-15s15,6.7,15,15C65,58.3,58.3,65,50,65z',
|
|
'fill': 'currentColor'
|
|
}
|
|
}, [
|
|
h('animateTransform', {
|
|
attrs: {
|
|
'attributeName': 'transform',
|
|
'type': 'rotate',
|
|
'from': '0 50 50',
|
|
'to': '90 50 50',
|
|
'dur': '1s',
|
|
'repeatCount': 'indefinite'
|
|
}
|
|
})
|
|
])
|
|
])
|
|
])
|
|
}
|
|
});
|
|
|
|
var QSpinnerGrid = Vue.extend({
|
|
name: 'QSpinnerGrid',
|
|
|
|
mixins: [mixin],
|
|
|
|
render: function render (h) {
|
|
return h('svg', {
|
|
staticClass: 'q-spinner',
|
|
class: this.classes,
|
|
on: Object.assign({}, this.qListeners),
|
|
attrs: {
|
|
focusable: 'false' /* needed for IE11 */,
|
|
'fill': 'currentColor',
|
|
'width': this.cSize,
|
|
'height': this.cSize,
|
|
'viewBox': '0 0 105 105',
|
|
'xmlns': 'http://www.w3.org/2000/svg'
|
|
}
|
|
}, [
|
|
h('circle', {
|
|
attrs: {
|
|
'cx': '12.5',
|
|
'cy': '12.5',
|
|
'r': '12.5'
|
|
}
|
|
}, [
|
|
h('animate', {
|
|
attrs: {
|
|
'attributeName': 'fill-opacity',
|
|
'begin': '0s',
|
|
'dur': '1s',
|
|
'values': '1;.2;1',
|
|
'calcMode': 'linear',
|
|
'repeatCount': 'indefinite'
|
|
}
|
|
})
|
|
]),
|
|
h('circle', {
|
|
attrs: {
|
|
'cx': '12.5',
|
|
'cy': '52.5',
|
|
'r': '12.5',
|
|
'fill-opacity': '.5'
|
|
}
|
|
}, [
|
|
h('animate', {
|
|
attrs: {
|
|
'attributeName': 'fill-opacity',
|
|
'begin': '100ms',
|
|
'dur': '1s',
|
|
'values': '1;.2;1',
|
|
'calcMode': 'linear',
|
|
'repeatCount': 'indefinite'
|
|
}
|
|
})
|
|
]),
|
|
h('circle', {
|
|
attrs: {
|
|
'cx': '52.5',
|
|
'cy': '12.5',
|
|
'r': '12.5'
|
|
}
|
|
}, [
|
|
h('animate', {
|
|
attrs: {
|
|
'attributeName': 'fill-opacity',
|
|
'begin': '300ms',
|
|
'dur': '1s',
|
|
'values': '1;.2;1',
|
|
'calcMode': 'linear',
|
|
'repeatCount': 'indefinite'
|
|
}
|
|
})
|
|
]),
|
|
h('circle', {
|
|
attrs: {
|
|
'cx': '52.5',
|
|
'cy': '52.5',
|
|
'r': '12.5'
|
|
}
|
|
}, [
|
|
h('animate', {
|
|
attrs: {
|
|
'attributeName': 'fill-opacity',
|
|
'begin': '600ms',
|
|
'dur': '1s',
|
|
'values': '1;.2;1',
|
|
'calcMode': 'linear',
|
|
'repeatCount': 'indefinite'
|
|
}
|
|
})
|
|
]),
|
|
h('circle', {
|
|
attrs: {
|
|
'cx': '92.5',
|
|
'cy': '12.5',
|
|
'r': '12.5'
|
|
}
|
|
}, [
|
|
h('animate', {
|
|
attrs: {
|
|
'attributeName': 'fill-opacity',
|
|
'begin': '800ms',
|
|
'dur': '1s',
|
|
'values': '1;.2;1',
|
|
'calcMode': 'linear',
|
|
'repeatCount': 'indefinite'
|
|
}
|
|
})
|
|
]),
|
|
h('circle', {
|
|
attrs: {
|
|
'cx': '92.5',
|
|
'cy': '52.5',
|
|
'r': '12.5'
|
|
}
|
|
}, [
|
|
h('animate', {
|
|
attrs: {
|
|
'attributeName': 'fill-opacity',
|
|
'begin': '400ms',
|
|
'dur': '1s',
|
|
'values': '1;.2;1',
|
|
'calcMode': 'linear',
|
|
'repeatCount': 'indefinite'
|
|
}
|
|
})
|
|
]),
|
|
h('circle', {
|
|
attrs: {
|
|
'cx': '12.5',
|
|
'cy': '92.5',
|
|
'r': '12.5'
|
|
}
|
|
}, [
|
|
h('animate', {
|
|
attrs: {
|
|
'attributeName': 'fill-opacity',
|
|
'begin': '700ms',
|
|
'dur': '1s',
|
|
'values': '1;.2;1',
|
|
'calcMode': 'linear',
|
|
'repeatCount': 'indefinite'
|
|
}
|
|
})
|
|
]),
|
|
h('circle', {
|
|
attrs: {
|
|
'cx': '52.5',
|
|
'cy': '92.5',
|
|
'r': '12.5'
|
|
}
|
|
}, [
|
|
h('animate', {
|
|
attrs: {
|
|
'attributeName': 'fill-opacity',
|
|
'begin': '500ms',
|
|
'dur': '1s',
|
|
'values': '1;.2;1',
|
|
'calcMode': 'linear',
|
|
'repeatCount': 'indefinite'
|
|
}
|
|
})
|
|
]),
|
|
h('circle', {
|
|
attrs: {
|
|
'cx': '92.5',
|
|
'cy': '92.5',
|
|
'r': '12.5'
|
|
}
|
|
}, [
|
|
h('animate', {
|
|
attrs: {
|
|
'attributeName': 'fill-opacity',
|
|
'begin': '200ms',
|
|
'dur': '1s',
|
|
'values': '1;.2;1',
|
|
'calcMode': 'linear',
|
|
'repeatCount': 'indefinite'
|
|
}
|
|
})
|
|
])
|
|
])
|
|
}
|
|
});
|
|
|
|
var QSpinnerHearts = Vue.extend({
|
|
name: 'QSpinnerHearts',
|
|
|
|
mixins: [mixin],
|
|
|
|
render: function render (h) {
|
|
return h('svg', {
|
|
staticClass: 'q-spinner',
|
|
class: this.classes,
|
|
on: Object.assign({}, this.qListeners),
|
|
attrs: {
|
|
focusable: 'false' /* needed for IE11 */,
|
|
'fill': 'currentColor',
|
|
'width': this.cSize,
|
|
'height': this.cSize,
|
|
'viewBox': '0 0 140 64',
|
|
'xmlns': 'http://www.w3.org/2000/svg'
|
|
}
|
|
}, [
|
|
h('path', {
|
|
attrs: {
|
|
'd': 'M30.262 57.02L7.195 40.723c-5.84-3.976-7.56-12.06-3.842-18.063 3.715-6 11.467-7.65 17.306-3.68l4.52 3.76 2.6-5.274c3.716-6.002 11.47-7.65 17.304-3.68 5.84 3.97 7.56 12.054 3.842 18.062L34.49 56.118c-.897 1.512-2.793 1.915-4.228.9z',
|
|
'fill-opacity': '.5'
|
|
}
|
|
}, [
|
|
h('animate', {
|
|
attrs: {
|
|
'attributeName': 'fill-opacity',
|
|
'begin': '0s',
|
|
'dur': '1.4s',
|
|
'values': '0.5;1;0.5',
|
|
'calcMode': 'linear',
|
|
'repeatCount': 'indefinite'
|
|
}
|
|
})
|
|
]),
|
|
h('path', {
|
|
attrs: {
|
|
'd': 'M105.512 56.12l-14.44-24.272c-3.716-6.008-1.996-14.093 3.843-18.062 5.835-3.97 13.588-2.322 17.306 3.68l2.6 5.274 4.52-3.76c5.84-3.97 13.593-2.32 17.308 3.68 3.718 6.003 1.998 14.088-3.842 18.064L109.74 57.02c-1.434 1.014-3.33.61-4.228-.9z',
|
|
'fill-opacity': '.5'
|
|
}
|
|
}, [
|
|
h('animate', {
|
|
attrs: {
|
|
'attributeName': 'fill-opacity',
|
|
'begin': '0.7s',
|
|
'dur': '1.4s',
|
|
'values': '0.5;1;0.5',
|
|
'calcMode': 'linear',
|
|
'repeatCount': 'indefinite'
|
|
}
|
|
})
|
|
]),
|
|
h('path', {
|
|
attrs: {
|
|
'd': 'M67.408 57.834l-23.01-24.98c-5.864-6.15-5.864-16.108 0-22.248 5.86-6.14 15.37-6.14 21.234 0L70 16.168l4.368-5.562c5.863-6.14 15.375-6.14 21.235 0 5.863 6.14 5.863 16.098 0 22.247l-23.007 24.98c-1.43 1.556-3.757 1.556-5.188 0z'
|
|
}
|
|
})
|
|
])
|
|
}
|
|
});
|
|
|
|
var QSpinnerHourglass = Vue.extend({
|
|
name: 'QSpinnerHourglass',
|
|
|
|
mixins: [mixin],
|
|
|
|
render: function render (h) {
|
|
return h('svg', {
|
|
staticClass: 'q-spinner',
|
|
class: this.classes,
|
|
on: Object.assign({}, this.qListeners),
|
|
attrs: {
|
|
focusable: 'false' /* needed for IE11 */,
|
|
'width': this.cSize,
|
|
'height': this.cSize,
|
|
'viewBox': '0 0 100 100',
|
|
'preserveAspectRatio': 'xMidYMid',
|
|
'xmlns': 'http://www.w3.org/2000/svg'
|
|
}
|
|
}, [
|
|
h('g', [
|
|
h('path', {
|
|
staticClass: 'glass',
|
|
attrs: {
|
|
'fill': 'none',
|
|
'stroke': 'currentColor',
|
|
'stroke-width': '5',
|
|
'stroke-miterlimit': '10',
|
|
'd': 'M58.4,51.7c-0.9-0.9-1.4-2-1.4-2.3s0.5-0.4,1.4-1.4 C70.8,43.8,79.8,30.5,80,15.5H70H30H20c0.2,15,9.2,28.1,21.6,32.3c0.9,0.9,1.4,1.2,1.4,1.5s-0.5,1.6-1.4,2.5 C29.2,56.1,20.2,69.5,20,85.5h10h40h10C79.8,69.5,70.8,55.9,58.4,51.7z'
|
|
}
|
|
}),
|
|
h('clipPath', {
|
|
attrs: {
|
|
'id': 'uil-hourglass-clip1'
|
|
}
|
|
}, [
|
|
h('rect', {
|
|
staticClass: 'clip',
|
|
attrs: {
|
|
'x': '15',
|
|
'y': '20',
|
|
'width': '70',
|
|
'height': '25'
|
|
}
|
|
}, [
|
|
h('animate', {
|
|
attrs: {
|
|
'attributeName': 'height',
|
|
'from': '25',
|
|
'to': '0',
|
|
'dur': '1s',
|
|
'repeatCount': 'indefinite',
|
|
'values': '25;0;0',
|
|
'keyTimes': '0;0.5;1'
|
|
}
|
|
}),
|
|
h('animate', {
|
|
attrs: {
|
|
'attributeName': 'y',
|
|
'from': '20',
|
|
'to': '45',
|
|
'dur': '1s',
|
|
'repeatCount': 'indefinite',
|
|
'values': '20;45;45',
|
|
'keyTimes': '0;0.5;1'
|
|
}
|
|
})
|
|
])
|
|
]),
|
|
h('clipPath', {
|
|
attrs: {
|
|
'id': 'uil-hourglass-clip2'
|
|
}
|
|
}, [
|
|
h('rect', {
|
|
staticClass: 'clip',
|
|
attrs: {
|
|
'x': '15',
|
|
'y': '55',
|
|
'width': '70',
|
|
'height': '25'
|
|
}
|
|
}, [
|
|
h('animate', {
|
|
attrs: {
|
|
'attributeName': 'height',
|
|
'from': '0',
|
|
'to': '25',
|
|
'dur': '1s',
|
|
'repeatCount': 'indefinite',
|
|
'values': '0;25;25',
|
|
'keyTimes': '0;0.5;1'
|
|
}
|
|
}),
|
|
h('animate', {
|
|
attrs: {
|
|
'attributeName': 'y',
|
|
'from': '80',
|
|
'to': '55',
|
|
'dur': '1s',
|
|
'repeatCount': 'indefinite',
|
|
'values': '80;55;55',
|
|
'keyTimes': '0;0.5;1'
|
|
}
|
|
})
|
|
])
|
|
]),
|
|
h('path', {
|
|
staticClass: 'sand',
|
|
attrs: {
|
|
'd': 'M29,23c3.1,11.4,11.3,19.5,21,19.5S67.9,34.4,71,23H29z',
|
|
'clip-path': 'url(#uil-hourglass-clip1)',
|
|
'fill': 'currentColor'
|
|
}
|
|
}),
|
|
h('path', {
|
|
staticClass: 'sand',
|
|
attrs: {
|
|
'd': 'M71.6,78c-3-11.6-11.5-20-21.5-20s-18.5,8.4-21.5,20H71.6z',
|
|
'clip-path': 'url(#uil-hourglass-clip2)',
|
|
'fill': 'currentColor'
|
|
}
|
|
}),
|
|
h('animateTransform', {
|
|
attrs: {
|
|
'attributeName': 'transform',
|
|
'type': 'rotate',
|
|
'from': '0 50 50',
|
|
'to': '180 50 50',
|
|
'repeatCount': 'indefinite',
|
|
'dur': '1s',
|
|
'values': '0 50 50;0 50 50;180 50 50',
|
|
'keyTimes': '0;0.7;1'
|
|
}
|
|
})
|
|
])
|
|
])
|
|
}
|
|
});
|
|
|
|
var QSpinnerInfinity = Vue.extend({
|
|
name: 'QSpinnerInfinity',
|
|
|
|
mixins: [mixin],
|
|
|
|
render: function render (h) {
|
|
return h('svg', {
|
|
staticClass: 'q-spinner',
|
|
class: this.classes,
|
|
on: Object.assign({}, this.qListeners),
|
|
attrs: {
|
|
focusable: 'false' /* needed for IE11 */,
|
|
'width': this.cSize,
|
|
'height': this.cSize,
|
|
'viewBox': '0 0 100 100',
|
|
'preserveAspectRatio': 'xMidYMid'
|
|
}
|
|
}, [
|
|
h('path', {
|
|
attrs: {
|
|
'd': 'M24.3,30C11.4,30,5,43.3,5,50s6.4,20,19.3,20c19.3,0,32.1-40,51.4-40C88.6,30,95,43.3,95,50s-6.4,20-19.3,20C56.4,70,43.6,30,24.3,30z',
|
|
'fill': 'none',
|
|
'stroke': 'currentColor',
|
|
'stroke-width': '8',
|
|
'stroke-dasharray': '10.691205342610678 10.691205342610678',
|
|
'stroke-dashoffset': '0'
|
|
}
|
|
}, [
|
|
h('animate', {
|
|
attrs: {
|
|
'attributeName': 'stroke-dashoffset',
|
|
'from': '0',
|
|
'to': '21.382410685221355',
|
|
'begin': '0',
|
|
'dur': '2s',
|
|
'repeatCount': 'indefinite',
|
|
'fill': 'freeze'
|
|
}
|
|
})
|
|
])
|
|
])
|
|
}
|
|
});
|
|
|
|
var QSpinnerIos = Vue.extend({
|
|
name: 'QSpinnerIos',
|
|
|
|
mixins: [mixin],
|
|
|
|
render: function render (h) {
|
|
return h('svg', {
|
|
staticClass: 'q-spinner',
|
|
class: this.classes,
|
|
on: Object.assign({}, this.qListeners),
|
|
attrs: {
|
|
focusable: 'false' /* needed for IE11 */,
|
|
'width': this.cSize,
|
|
'height': this.cSize,
|
|
'stroke': 'currentColor',
|
|
'fill': 'currentColor',
|
|
'viewBox': '0 0 64 64'
|
|
}
|
|
}, [
|
|
h('g', {
|
|
attrs: {
|
|
'stroke-width': '4',
|
|
'stroke-linecap': 'round'
|
|
}
|
|
}, [
|
|
h('line', {
|
|
attrs: {
|
|
'y1': '17',
|
|
'y2': '29',
|
|
'transform': 'translate(32,32) rotate(180)'
|
|
}
|
|
}, [
|
|
h('animate', {
|
|
attrs: {
|
|
'attributeName': 'stroke-opacity',
|
|
'dur': '750ms',
|
|
'values': '1;.85;.7;.65;.55;.45;.35;.25;.15;.1;0;1',
|
|
'repeatCount': 'indefinite'
|
|
}
|
|
})
|
|
]),
|
|
h('line', {
|
|
attrs: {
|
|
'y1': '17',
|
|
'y2': '29',
|
|
'transform': 'translate(32,32) rotate(210)'
|
|
}
|
|
}, [
|
|
h('animate', {
|
|
attrs: {
|
|
'attributeName': 'stroke-opacity',
|
|
'dur': '750ms',
|
|
'values': '0;1;.85;.7;.65;.55;.45;.35;.25;.15;.1;0',
|
|
'repeatCount': 'indefinite'
|
|
}
|
|
})
|
|
]),
|
|
h('line', {
|
|
attrs: {
|
|
'y1': '17',
|
|
'y2': '29',
|
|
'transform': 'translate(32,32) rotate(240)'
|
|
}
|
|
}, [
|
|
h('animate', {
|
|
attrs: {
|
|
'attributeName': 'stroke-opacity',
|
|
'dur': '750ms',
|
|
'values': '.1;0;1;.85;.7;.65;.55;.45;.35;.25;.15;.1',
|
|
'repeatCount': 'indefinite'
|
|
}
|
|
})
|
|
]),
|
|
h('line', {
|
|
attrs: {
|
|
'y1': '17',
|
|
'y2': '29',
|
|
'transform': 'translate(32,32) rotate(270)'
|
|
}
|
|
}, [
|
|
h('animate', {
|
|
attrs: {
|
|
'attributeName': 'stroke-opacity',
|
|
'dur': '750ms',
|
|
'values': '.15;.1;0;1;.85;.7;.65;.55;.45;.35;.25;.15',
|
|
'repeatCount': 'indefinite'
|
|
}
|
|
})
|
|
]),
|
|
h('line', {
|
|
attrs: {
|
|
'y1': '17',
|
|
'y2': '29',
|
|
'transform': 'translate(32,32) rotate(300)'
|
|
}
|
|
}, [
|
|
h('animate', {
|
|
attrs: {
|
|
'attributeName': 'stroke-opacity',
|
|
'dur': '750ms',
|
|
'values': '.25;.15;.1;0;1;.85;.7;.65;.55;.45;.35;.25',
|
|
'repeatCount': 'indefinite'
|
|
}
|
|
})
|
|
]),
|
|
h('line', {
|
|
attrs: {
|
|
'y1': '17',
|
|
'y2': '29',
|
|
'transform': 'translate(32,32) rotate(330)'
|
|
}
|
|
}, [
|
|
h('animate', {
|
|
attrs: {
|
|
'attributeName': 'stroke-opacity',
|
|
'dur': '750ms',
|
|
'values': '.35;.25;.15;.1;0;1;.85;.7;.65;.55;.45;.35',
|
|
'repeatCount': 'indefinite'
|
|
}
|
|
})
|
|
]),
|
|
h('line', {
|
|
attrs: {
|
|
'y1': '17',
|
|
'y2': '29',
|
|
'transform': 'translate(32,32) rotate(0)'
|
|
}
|
|
}, [
|
|
h('animate', {
|
|
attrs: {
|
|
'attributeName': 'stroke-opacity',
|
|
'dur': '750ms',
|
|
'values': '.45;.35;.25;.15;.1;0;1;.85;.7;.65;.55;.45',
|
|
'repeatCount': 'indefinite'
|
|
}
|
|
})
|
|
]),
|
|
h('line', {
|
|
attrs: {
|
|
'y1': '17',
|
|
'y2': '29',
|
|
'transform': 'translate(32,32) rotate(30)'
|
|
}
|
|
}, [
|
|
h('animate', {
|
|
attrs: {
|
|
'attributeName': 'stroke-opacity',
|
|
'dur': '750ms',
|
|
'values': '.55;.45;.35;.25;.15;.1;0;1;.85;.7;.65;.55',
|
|
'repeatCount': 'indefinite'
|
|
}
|
|
})
|
|
]),
|
|
h('line', {
|
|
attrs: {
|
|
'y1': '17',
|
|
'y2': '29',
|
|
'transform': 'translate(32,32) rotate(60)'
|
|
}
|
|
}, [
|
|
h('animate', {
|
|
attrs: {
|
|
'attributeName': 'stroke-opacity',
|
|
'dur': '750ms',
|
|
'values': '.65;.55;.45;.35;.25;.15;.1;0;1;.85;.7;.65',
|
|
'repeatCount': 'indefinite'
|
|
}
|
|
})
|
|
]),
|
|
h('line', {
|
|
attrs: {
|
|
'y1': '17',
|
|
'y2': '29',
|
|
'transform': 'translate(32,32) rotate(90)'
|
|
}
|
|
}, [
|
|
h('animate', {
|
|
attrs: {
|
|
'attributeName': 'stroke-opacity',
|
|
'dur': '750ms',
|
|
'values': '.7;.65;.55;.45;.35;.25;.15;.1;0;1;.85;.7',
|
|
'repeatCount': 'indefinite'
|
|
}
|
|
})
|
|
]),
|
|
h('line', {
|
|
attrs: {
|
|
'y1': '17',
|
|
'y2': '29',
|
|
'transform': 'translate(32,32) rotate(120)'
|
|
}
|
|
}, [
|
|
h('animate', {
|
|
attrs: {
|
|
'attributeName': 'stroke-opacity',
|
|
'dur': '750ms',
|
|
'values': '.85;.7;.65;.55;.45;.35;.25;.15;.1;0;1;.85',
|
|
'repeatCount': 'indefinite'
|
|
}
|
|
})
|
|
]),
|
|
h('line', {
|
|
attrs: {
|
|
'y1': '17',
|
|
'y2': '29',
|
|
'transform': 'translate(32,32) rotate(150)'
|
|
}
|
|
}, [
|
|
h('animate', {
|
|
attrs: {
|
|
'attributeName': 'stroke-opacity',
|
|
'dur': '750ms',
|
|
'values': '1;.85;.7;.65;.55;.45;.35;.25;.15;.1;0;1',
|
|
'repeatCount': 'indefinite'
|
|
}
|
|
})
|
|
])
|
|
])
|
|
])
|
|
}
|
|
});
|
|
|
|
var QSpinnerOval = Vue.extend({
|
|
name: 'QSpinnerOval',
|
|
|
|
mixins: [mixin],
|
|
|
|
render: function render (h) {
|
|
return h('svg', {
|
|
staticClass: 'q-spinner',
|
|
class: this.classes,
|
|
on: Object.assign({}, this.qListeners),
|
|
attrs: {
|
|
focusable: 'false' /* needed for IE11 */,
|
|
'stroke': 'currentColor',
|
|
'width': this.cSize,
|
|
'height': this.cSize,
|
|
'viewBox': '0 0 38 38',
|
|
'xmlns': 'http://www.w3.org/2000/svg'
|
|
}
|
|
}, [
|
|
h('g', {
|
|
attrs: {
|
|
'transform': 'translate(1 1)',
|
|
'stroke-width': '2',
|
|
'fill': 'none',
|
|
'fill-rule': 'evenodd'
|
|
}
|
|
}, [
|
|
h('circle', {
|
|
attrs: {
|
|
'stroke-opacity': '.5',
|
|
'cx': '18',
|
|
'cy': '18',
|
|
'r': '18'
|
|
}
|
|
}),
|
|
h('path', {
|
|
attrs: {
|
|
'd': 'M36 18c0-9.94-8.06-18-18-18'
|
|
}
|
|
}, [
|
|
h('animateTransform', {
|
|
attrs: {
|
|
'attributeName': 'transform',
|
|
'type': 'rotate',
|
|
'from': '0 18 18',
|
|
'to': '360 18 18',
|
|
'dur': '1s',
|
|
'repeatCount': 'indefinite'
|
|
}
|
|
})
|
|
])
|
|
])
|
|
])
|
|
}
|
|
});
|
|
|
|
var QSpinnerPie = Vue.extend({
|
|
name: 'QSpinnerPie',
|
|
|
|
mixins: [mixin],
|
|
|
|
render: function render (h) {
|
|
return h('svg', {
|
|
staticClass: 'q-spinner',
|
|
class: this.classes,
|
|
on: Object.assign({}, this.qListeners),
|
|
attrs: {
|
|
focusable: 'false' /* needed for IE11 */,
|
|
'width': this.cSize,
|
|
'height': this.cSize,
|
|
'viewBox': '0 0 100 100',
|
|
'preserveAspectRatio': 'xMidYMid',
|
|
'xmlns': 'http://www.w3.org/2000/svg'
|
|
}
|
|
}, [
|
|
h('path', {
|
|
attrs: {
|
|
'd': 'M0 50A50 50 0 0 1 50 0L50 50L0 50',
|
|
'fill': 'currentColor',
|
|
'opacity': '0.5'
|
|
}
|
|
}, [
|
|
h('animateTransform', {
|
|
attrs: {
|
|
'attributeName': 'transform',
|
|
'type': 'rotate',
|
|
'from': '0 50 50',
|
|
'to': '360 50 50',
|
|
'dur': '0.8s',
|
|
'repeatCount': 'indefinite'
|
|
}
|
|
})
|
|
]),
|
|
h('path', {
|
|
attrs: {
|
|
'd': 'M50 0A50 50 0 0 1 100 50L50 50L50 0',
|
|
'fill': 'currentColor',
|
|
'opacity': '0.5'
|
|
}
|
|
}, [
|
|
h('animateTransform', {
|
|
attrs: {
|
|
'attributeName': 'transform',
|
|
'type': 'rotate',
|
|
'from': '0 50 50',
|
|
'to': '360 50 50',
|
|
'dur': '1.6s',
|
|
'repeatCount': 'indefinite'
|
|
}
|
|
})
|
|
]),
|
|
h('path', {
|
|
attrs: {
|
|
'd': 'M100 50A50 50 0 0 1 50 100L50 50L100 50',
|
|
'fill': 'currentColor',
|
|
'opacity': '0.5'
|
|
}
|
|
}, [
|
|
h('animateTransform', {
|
|
attrs: {
|
|
'attributeName': 'transform',
|
|
'type': 'rotate',
|
|
'from': '0 50 50',
|
|
'to': '360 50 50',
|
|
'dur': '2.4s',
|
|
'repeatCount': 'indefinite'
|
|
}
|
|
})
|
|
]),
|
|
h('path', {
|
|
attrs: {
|
|
'd': 'M50 100A50 50 0 0 1 0 50L50 50L50 100',
|
|
'fill': 'currentColor',
|
|
'opacity': '0.5'
|
|
}
|
|
}, [
|
|
h('animateTransform', {
|
|
attrs: {
|
|
'attributeName': 'transform',
|
|
'type': 'rotate',
|
|
'from': '0 50 50',
|
|
'to': '360 50 50',
|
|
'dur': '3.2s',
|
|
'repeatCount': 'indefinite'
|
|
}
|
|
})
|
|
])
|
|
])
|
|
}
|
|
});
|
|
|
|
var QSpinnerPuff = Vue.extend({
|
|
name: 'QSpinnerPuff',
|
|
|
|
mixins: [mixin],
|
|
|
|
render: function render (h) {
|
|
return h('svg', {
|
|
staticClass: 'q-spinner',
|
|
class: this.classes,
|
|
on: Object.assign({}, this.qListeners),
|
|
attrs: {
|
|
focusable: 'false' /* needed for IE11 */,
|
|
'stroke': 'currentColor',
|
|
'width': this.cSize,
|
|
'height': this.cSize,
|
|
'viewBox': '0 0 44 44',
|
|
'xmlns': 'http://www.w3.org/2000/svg'
|
|
}
|
|
}, [
|
|
h('g', {
|
|
attrs: {
|
|
'fill': 'none',
|
|
'fill-rule': 'evenodd',
|
|
'stroke-width': '2'
|
|
}
|
|
}, [
|
|
h('circle', {
|
|
attrs: {
|
|
'cx': '22',
|
|
'cy': '22',
|
|
'r': '1'
|
|
}
|
|
}, [
|
|
h('animate', {
|
|
attrs: {
|
|
'attributeName': 'r',
|
|
'begin': '0s',
|
|
'dur': '1.8s',
|
|
'values': '1; 20',
|
|
'calcMode': 'spline',
|
|
'keyTimes': '0; 1',
|
|
'keySplines': '0.165, 0.84, 0.44, 1',
|
|
'repeatCount': 'indefinite'
|
|
}
|
|
}),
|
|
h('animate', {
|
|
attrs: {
|
|
'attributeName': 'stroke-opacity',
|
|
'begin': '0s',
|
|
'dur': '1.8s',
|
|
'values': '1; 0',
|
|
'calcMode': 'spline',
|
|
'keyTimes': '0; 1',
|
|
'keySplines': '0.3, 0.61, 0.355, 1',
|
|
'repeatCount': 'indefinite'
|
|
}
|
|
})
|
|
]),
|
|
h('circle', {
|
|
attrs: {
|
|
'cx': '22',
|
|
'cy': '22',
|
|
'r': '1'
|
|
}
|
|
}, [
|
|
h('animate', {
|
|
attrs: {
|
|
'attributeName': 'r',
|
|
'begin': '-0.9s',
|
|
'dur': '1.8s',
|
|
'values': '1; 20',
|
|
'calcMode': 'spline',
|
|
'keyTimes': '0; 1',
|
|
'keySplines': '0.165, 0.84, 0.44, 1',
|
|
'repeatCount': 'indefinite'
|
|
}
|
|
}),
|
|
h('animate', {
|
|
attrs: {
|
|
'attributeName': 'stroke-opacity',
|
|
'begin': '-0.9s',
|
|
'dur': '1.8s',
|
|
'values': '1; 0',
|
|
'calcMode': 'spline',
|
|
'keyTimes': '0; 1',
|
|
'keySplines': '0.3, 0.61, 0.355, 1',
|
|
'repeatCount': 'indefinite'
|
|
}
|
|
})
|
|
])
|
|
])
|
|
])
|
|
}
|
|
});
|
|
|
|
var QSpinnerRadio = Vue.extend({
|
|
name: 'QSpinnerRadio',
|
|
|
|
mixins: [mixin],
|
|
|
|
render: function render (h) {
|
|
return h('svg', {
|
|
staticClass: 'q-spinner',
|
|
class: this.classes,
|
|
on: Object.assign({}, this.qListeners),
|
|
attrs: {
|
|
focusable: 'false' /* needed for IE11 */,
|
|
'width': this.cSize,
|
|
'height': this.cSize,
|
|
'viewBox': '0 0 100 100',
|
|
'preserveAspectRatio': 'xMidYMid',
|
|
'xmlns': 'http://www.w3.org/2000/svg'
|
|
}
|
|
}, [
|
|
h('g', {
|
|
attrs: {
|
|
'transform': 'scale(0.55)'
|
|
}
|
|
}, [
|
|
h('circle', {
|
|
attrs: {
|
|
'cx': '30',
|
|
'cy': '150',
|
|
'r': '30',
|
|
'fill': 'currentColor'
|
|
}
|
|
}, [
|
|
h('animate', {
|
|
attrs: {
|
|
'attributeName': 'opacity',
|
|
'from': '0',
|
|
'to': '1',
|
|
'dur': '1s',
|
|
'begin': '0',
|
|
'repeatCount': 'indefinite',
|
|
'keyTimes': '0;0.5;1',
|
|
'values': '0;1;1'
|
|
}
|
|
})
|
|
]),
|
|
h('path', {
|
|
attrs: {
|
|
'd': 'M90,150h30c0-49.7-40.3-90-90-90v30C63.1,90,90,116.9,90,150z',
|
|
'fill': 'currentColor'
|
|
}
|
|
}, [
|
|
h('animate', {
|
|
attrs: {
|
|
'attributeName': 'opacity',
|
|
'from': '0',
|
|
'to': '1',
|
|
'dur': '1s',
|
|
'begin': '0.1',
|
|
'repeatCount': 'indefinite',
|
|
'keyTimes': '0;0.5;1',
|
|
'values': '0;1;1'
|
|
}
|
|
})
|
|
]),
|
|
h('path', {
|
|
attrs: {
|
|
'd': 'M150,150h30C180,67.2,112.8,0,30,0v30C96.3,30,150,83.7,150,150z',
|
|
'fill': 'currentColor'
|
|
}
|
|
}, [
|
|
h('animate', {
|
|
attrs: {
|
|
'attributeName': 'opacity',
|
|
'from': '0',
|
|
'to': '1',
|
|
'dur': '1s',
|
|
'begin': '0.2',
|
|
'repeatCount': 'indefinite',
|
|
'keyTimes': '0;0.5;1',
|
|
'values': '0;1;1'
|
|
}
|
|
})
|
|
])
|
|
])
|
|
])
|
|
}
|
|
});
|
|
|
|
var QSpinnerRings = Vue.extend({
|
|
name: 'QSpinnerRings',
|
|
|
|
mixins: [mixin],
|
|
|
|
render: function render (h) {
|
|
return h('svg', {
|
|
staticClass: 'q-spinner',
|
|
class: this.classes,
|
|
on: Object.assign({}, this.qListeners),
|
|
attrs: {
|
|
focusable: 'false' /* needed for IE11 */,
|
|
'stroke': 'currentColor',
|
|
'width': this.cSize,
|
|
'height': this.cSize,
|
|
'viewBox': '0 0 45 45',
|
|
'xmlns': 'http://www.w3.org/2000/svg'
|
|
}
|
|
}, [
|
|
h('g', {
|
|
attrs: {
|
|
'fill': 'none',
|
|
'fill-rule': 'evenodd',
|
|
'transform': 'translate(1 1)',
|
|
'stroke-width': '2'
|
|
}
|
|
}, [
|
|
h('circle', {
|
|
attrs: {
|
|
'cx': '22',
|
|
'cy': '22',
|
|
'r': '6'
|
|
}
|
|
}, [
|
|
h('animate', {
|
|
attrs: {
|
|
'attributeName': 'r',
|
|
'begin': '1.5s',
|
|
'dur': '3s',
|
|
'values': '6;22',
|
|
'calcMode': 'linear',
|
|
'repeatCount': 'indefinite'
|
|
}
|
|
}),
|
|
h('animate', {
|
|
attrs: {
|
|
'attributeName': 'stroke-opacity',
|
|
'begin': '1.5s',
|
|
'dur': '3s',
|
|
'values': '1;0',
|
|
'calcMode': 'linear',
|
|
'repeatCount': 'indefinite'
|
|
}
|
|
}),
|
|
h('animate', {
|
|
attrs: {
|
|
'attributeName': 'stroke-width',
|
|
'begin': '1.5s',
|
|
'dur': '3s',
|
|
'values': '2;0',
|
|
'calcMode': 'linear',
|
|
'repeatCount': 'indefinite'
|
|
}
|
|
})
|
|
]),
|
|
h('circle', {
|
|
attrs: {
|
|
'cx': '22',
|
|
'cy': '22',
|
|
'r': '6'
|
|
}
|
|
}, [
|
|
h('animate', {
|
|
attrs: {
|
|
'attributeName': 'r',
|
|
'begin': '3s',
|
|
'dur': '3s',
|
|
'values': '6;22',
|
|
'calcMode': 'linear',
|
|
'repeatCount': 'indefinite'
|
|
}
|
|
}),
|
|
h('animate', {
|
|
attrs: {
|
|
'attributeName': 'stroke-opacity',
|
|
'begin': '3s',
|
|
'dur': '3s',
|
|
'values': '1;0',
|
|
'calcMode': 'linear',
|
|
'repeatCount': 'indefinite'
|
|
}
|
|
}),
|
|
h('animate', {
|
|
attrs: {
|
|
'attributeName': 'stroke-width',
|
|
'begin': '3s',
|
|
'dur': '3s',
|
|
'values': '2;0',
|
|
'calcMode': 'linear',
|
|
'repeatCount': 'indefinite'
|
|
}
|
|
})
|
|
]),
|
|
h('circle', {
|
|
attrs: {
|
|
'cx': '22',
|
|
'cy': '22',
|
|
'r': '8'
|
|
}
|
|
}, [
|
|
h('animate', {
|
|
attrs: {
|
|
'attributeName': 'r',
|
|
'begin': '0s',
|
|
'dur': '1.5s',
|
|
'values': '6;1;2;3;4;5;6',
|
|
'calcMode': 'linear',
|
|
'repeatCount': 'indefinite'
|
|
}
|
|
})
|
|
])
|
|
])
|
|
])
|
|
}
|
|
});
|
|
|
|
var QSpinnerTail = Vue.extend({
|
|
name: 'QSpinnerTail',
|
|
|
|
mixins: [mixin],
|
|
|
|
render: function render (h) {
|
|
return h('svg', {
|
|
staticClass: 'q-spinner',
|
|
class: this.classes,
|
|
on: Object.assign({}, this.qListeners),
|
|
attrs: {
|
|
focusable: 'false' /* needed for IE11 */,
|
|
'width': this.cSize,
|
|
'height': this.cSize,
|
|
'viewBox': '0 0 38 38',
|
|
'xmlns': 'http://www.w3.org/2000/svg'
|
|
}
|
|
}, [
|
|
h('defs', [
|
|
h('linearGradient', {
|
|
attrs: {
|
|
'x1': '8.042%',
|
|
'y1': '0%',
|
|
'x2': '65.682%',
|
|
'y2': '23.865%',
|
|
'id': 'a'
|
|
}
|
|
}, [
|
|
h('stop', {
|
|
attrs: {
|
|
'stop-color': 'currentColor',
|
|
'stop-opacity': '0',
|
|
'offset': '0%'
|
|
}
|
|
}),
|
|
h('stop', {
|
|
attrs: {
|
|
'stop-color': 'currentColor',
|
|
'stop-opacity': '.631',
|
|
'offset': '63.146%'
|
|
}
|
|
}),
|
|
h('stop', {
|
|
attrs: {
|
|
'stop-color': 'currentColor',
|
|
'offset': '100%'
|
|
}
|
|
})
|
|
])
|
|
]),
|
|
h('g', {
|
|
attrs: {
|
|
'transform': 'translate(1 1)',
|
|
'fill': 'none',
|
|
'fill-rule': 'evenodd'
|
|
}
|
|
}, [
|
|
h('path', {
|
|
attrs: {
|
|
'd': 'M36 18c0-9.94-8.06-18-18-18',
|
|
'stroke': 'url(#a)',
|
|
'stroke-width': '2'
|
|
}
|
|
}, [
|
|
h('animateTransform', {
|
|
attrs: {
|
|
'attributeName': 'transform',
|
|
'type': 'rotate',
|
|
'from': '0 18 18',
|
|
'to': '360 18 18',
|
|
'dur': '0.9s',
|
|
'repeatCount': 'indefinite'
|
|
}
|
|
})
|
|
]),
|
|
h('circle', {
|
|
attrs: {
|
|
'fill': 'currentColor',
|
|
'cx': '36',
|
|
'cy': '18',
|
|
'r': '1'
|
|
}
|
|
}, [
|
|
h('animateTransform', {
|
|
attrs: {
|
|
'attributeName': 'transform',
|
|
'type': 'rotate',
|
|
'from': '0 18 18',
|
|
'to': '360 18 18',
|
|
'dur': '0.9s',
|
|
'repeatCount': 'indefinite'
|
|
}
|
|
})
|
|
])
|
|
])
|
|
])
|
|
}
|
|
});
|
|
|
|
var QSplitter = Vue.extend({
|
|
name: 'QSplitter',
|
|
|
|
mixins: [ DarkMixin, ListenersMixin ],
|
|
|
|
directives: {
|
|
TouchPan: TouchPan
|
|
},
|
|
|
|
props: {
|
|
value: {
|
|
type: Number,
|
|
required: true
|
|
},
|
|
reverse: Boolean,
|
|
unit: {
|
|
type: String,
|
|
default: '%',
|
|
validator: function (v) { return [ '%', 'px' ].includes(v); }
|
|
},
|
|
|
|
limits: {
|
|
type: Array,
|
|
validator: function (v) {
|
|
if (v.length !== 2) { return false }
|
|
if (typeof v[0] !== 'number' || typeof v[1] !== 'number') { return false }
|
|
return v[0] >= 0 && v[0] <= v[1]
|
|
}
|
|
},
|
|
|
|
emitImmediately: Boolean,
|
|
|
|
horizontal: Boolean,
|
|
disable: Boolean,
|
|
|
|
beforeClass: [Array, String, Object],
|
|
afterClass: [Array, String, Object],
|
|
|
|
separatorClass: [Array, String, Object],
|
|
separatorStyle: [Array, String, Object]
|
|
},
|
|
|
|
watch: {
|
|
value: {
|
|
immediate: true,
|
|
handler: function handler (v) {
|
|
this.__normalize(v, this.computedLimits);
|
|
}
|
|
},
|
|
|
|
limits: {
|
|
deep: true,
|
|
handler: function handler () {
|
|
var this$1 = this;
|
|
|
|
this.$nextTick(function () {
|
|
this$1.__normalize(this$1.value, this$1.computedLimits);
|
|
});
|
|
}
|
|
}
|
|
},
|
|
|
|
computed: {
|
|
classes: function classes () {
|
|
return (this.horizontal === true ? 'column' : 'row') +
|
|
" q-splitter--" + (this.horizontal === true ? 'horizontal' : 'vertical') +
|
|
" q-splitter--" + (this.disable === true ? 'disabled' : 'workable') +
|
|
(this.isDark === true ? ' q-splitter--dark' : '')
|
|
},
|
|
|
|
prop: function prop () {
|
|
return this.horizontal === true ? 'height' : 'width'
|
|
},
|
|
|
|
side: function side () {
|
|
return this.reverse !== true ? 'before' : 'after'
|
|
},
|
|
|
|
computedLimits: function computedLimits () {
|
|
return this.limits !== void 0
|
|
? this.limits
|
|
: (this.unit === '%' ? [ 10, 90 ] : [ 50, Infinity ])
|
|
},
|
|
|
|
styles: function styles () {
|
|
var obj, obj$1;
|
|
|
|
return ( obj$1 = {}, obj$1[this.side] = ( obj = {}, obj[this.prop] = this.__getCSSValue(this.value), obj ), obj$1 )
|
|
},
|
|
|
|
separatorDirectives: function separatorDirectives () {
|
|
var obj;
|
|
|
|
if (this.disable !== true) {
|
|
return [{
|
|
name: 'touch-pan',
|
|
value: this.__pan,
|
|
modifiers: ( obj = {}, obj[ this.horizontal === true ? 'vertical' : 'horizontal' ] = true, obj.prevent = true, obj.stop = true, obj.mouse = true, obj.mouseAllDir = true, obj )
|
|
}]
|
|
}
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
__pan: function __pan (evt) {
|
|
if (evt.isFirst === true) {
|
|
var size = this.$el.getBoundingClientRect()[this.prop];
|
|
|
|
this.__dir = this.horizontal === true ? 'up' : 'left';
|
|
this.__maxValue = this.unit === '%' ? 100 : size;
|
|
this.__value = Math.min(this.__maxValue, this.computedLimits[1], Math.max(this.computedLimits[0], this.value));
|
|
this.__multiplier = (this.reverse !== true ? 1 : -1) *
|
|
(this.horizontal === true ? 1 : (this.$q.lang.rtl === true ? -1 : 1)) *
|
|
(this.unit === '%' ? (size === 0 ? 0 : 100 / size) : 1);
|
|
|
|
this.$el.classList.add('q-splitter--active');
|
|
return
|
|
}
|
|
|
|
if (evt.isFinal === true) {
|
|
if (this.__normalized !== this.value) {
|
|
this.$emit('input', this.__normalized);
|
|
}
|
|
|
|
this.$el.classList.remove('q-splitter--active');
|
|
return
|
|
}
|
|
|
|
var val = this.__value +
|
|
this.__multiplier *
|
|
(evt.direction === this.__dir ? -1 : 1) *
|
|
evt.distance[this.horizontal === true ? 'y' : 'x'];
|
|
|
|
this.__normalized = Math.min(this.__maxValue, this.computedLimits[1], Math.max(this.computedLimits[0], val));
|
|
|
|
this.$refs[this.side].style[this.prop] = this.__getCSSValue(this.__normalized);
|
|
|
|
if (this.emitImmediately === true && this.value !== this.__normalized) {
|
|
this.$emit('input', this.__normalized);
|
|
}
|
|
},
|
|
|
|
__normalize: function __normalize (val, limits) {
|
|
if (val < limits[0]) {
|
|
this.$emit('input', limits[0]);
|
|
}
|
|
else if (val > limits[1]) {
|
|
this.$emit('input', limits[1]);
|
|
}
|
|
},
|
|
|
|
__getCSSValue: function __getCSSValue (value) {
|
|
return (this.unit === '%' ? value : Math.round(value)) + this.unit
|
|
}
|
|
},
|
|
|
|
render: function render (h) {
|
|
var attrs = this.disable === true ? { 'aria-disabled': 'true' } : void 0;
|
|
var child = [
|
|
h('div', {
|
|
ref: 'before',
|
|
staticClass: 'q-splitter__panel q-splitter__before' + (this.reverse === true ? ' col' : ''),
|
|
style: this.styles.before,
|
|
class: this.beforeClass,
|
|
on: cache(this, 'stop', { input: stop })
|
|
}, slot(this, 'before')),
|
|
|
|
h('div', {
|
|
staticClass: 'q-splitter__separator',
|
|
style: this.separatorStyle,
|
|
class: this.separatorClass,
|
|
attrs: attrs
|
|
}, [
|
|
h('div', {
|
|
staticClass: 'absolute-full q-splitter__separator-area',
|
|
directives: this.separatorDirectives
|
|
}, slot(this, 'separator'))
|
|
]),
|
|
|
|
h('div', {
|
|
ref: 'after',
|
|
staticClass: 'q-splitter__panel q-splitter__after' + (this.reverse === true ? '' : ' col'),
|
|
style: this.styles.after,
|
|
class: this.afterClass,
|
|
on: cache(this, 'stop', { input: stop })
|
|
}, slot(this, 'after'))
|
|
];
|
|
|
|
return h('div', {
|
|
staticClass: 'q-splitter no-wrap',
|
|
class: this.classes,
|
|
on: Object.assign({}, this.qListeners)
|
|
}, mergeSlot(child, this, 'default'))
|
|
}
|
|
});
|
|
|
|
var StepHeader = Vue.extend({
|
|
name: 'StepHeader',
|
|
|
|
mixins: [ AttrsMixin ],
|
|
|
|
directives: {
|
|
Ripple: Ripple
|
|
},
|
|
|
|
props: {
|
|
stepper: {},
|
|
step: {}
|
|
},
|
|
|
|
computed: {
|
|
isActive: function isActive () {
|
|
return this.stepper.value === this.step.name
|
|
},
|
|
|
|
isDisable: function isDisable () {
|
|
var opt = this.step.disable;
|
|
return opt === true || opt === ''
|
|
},
|
|
|
|
isError: function isError () {
|
|
var opt = this.step.error;
|
|
return opt === true || opt === ''
|
|
},
|
|
|
|
isDone: function isDone () {
|
|
var opt = this.step.done;
|
|
return this.isDisable === false && (opt === true || opt === '')
|
|
},
|
|
|
|
headerNav: function headerNav () {
|
|
var
|
|
opt = this.step.headerNav,
|
|
nav = opt === true || opt === '' || opt === void 0;
|
|
|
|
return this.isDisable === false &&
|
|
this.stepper.headerNav &&
|
|
nav
|
|
},
|
|
|
|
hasPrefix: function hasPrefix () {
|
|
return this.step.prefix &&
|
|
this.isActive === false &&
|
|
this.isError === false &&
|
|
this.isDone === false
|
|
},
|
|
|
|
icon: function icon () {
|
|
if (this.isActive === true) {
|
|
return this.step.activeIcon || this.stepper.activeIcon || this.$q.iconSet.stepper.active
|
|
}
|
|
if (this.isError === true) {
|
|
return this.step.errorIcon || this.stepper.errorIcon || this.$q.iconSet.stepper.error
|
|
}
|
|
if (this.isDisable === false && this.isDone === true) {
|
|
return this.step.doneIcon || this.stepper.doneIcon || this.$q.iconSet.stepper.done
|
|
}
|
|
|
|
return this.step.icon || this.stepper.inactiveIcon
|
|
},
|
|
|
|
color: function color () {
|
|
var errorColor = this.isError === true
|
|
? this.step.errorColor || this.stepper.errorColor
|
|
: void 0;
|
|
|
|
if (this.isActive === true) {
|
|
var color = this.step.activeColor || this.stepper.activeColor || this.step.color;
|
|
return color !== void 0
|
|
? color
|
|
: errorColor
|
|
}
|
|
if (errorColor !== void 0) {
|
|
return errorColor
|
|
}
|
|
if (this.isDisable === false && this.isDone === true) {
|
|
return this.step.doneColor || this.stepper.doneColor || this.step.color || this.stepper.inactiveColor
|
|
}
|
|
|
|
return this.step.color || this.stepper.inactiveColor
|
|
},
|
|
|
|
classes: function classes () {
|
|
return "q-stepper__tab col-grow flex items-center no-wrap relative-position" +
|
|
(this.color !== void 0 ? (" text-" + (this.color)) : '') +
|
|
(this.isError === true ? ' q-stepper__tab--error' : '') +
|
|
(this.isActive === true ? ' q-stepper__tab--active' : '') +
|
|
(this.isDone === true ? ' q-stepper__tab--done' : '') +
|
|
(this.headerNav === true ? ' q-stepper__tab--navigation q-focusable q-hoverable' : '') +
|
|
(this.isDisable === true ? ' q-stepper__tab--disabled' : '')
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
activate: function activate () {
|
|
this.$refs.blurTarget !== void 0 && this.$refs.blurTarget.focus();
|
|
this.isActive === false && this.stepper.goTo(this.step.name);
|
|
},
|
|
|
|
keyup: function keyup (e) {
|
|
if (e.keyCode === 13 && this.isActive === false) {
|
|
this.stepper.goTo(this.step.name);
|
|
}
|
|
}
|
|
},
|
|
|
|
render: function render (h) {
|
|
var data = { class: this.classes };
|
|
|
|
if (this.stepper.headerNav === true) {
|
|
data.directives = [{
|
|
name: 'ripple',
|
|
value: this.headerNav
|
|
}];
|
|
}
|
|
|
|
this.headerNav === true && Object.assign(data, {
|
|
on: cache(this, 'headnavon', {
|
|
click: this.activate,
|
|
keyup: this.keyup
|
|
}),
|
|
attrs: this.isDisable === true
|
|
? { tabindex: -1, 'aria-disabled': 'true' }
|
|
: { tabindex: this.qAttrs.tabindex || 0 }
|
|
});
|
|
|
|
var child = [
|
|
h('div', { staticClass: 'q-focus-helper', attrs: { tabindex: -1 }, ref: 'blurTarget' }),
|
|
|
|
h('div', { staticClass: 'q-stepper__dot row flex-center q-stepper__line relative-position' }, [
|
|
h('span', { staticClass: 'row flex-center' }, [
|
|
this.hasPrefix === true
|
|
? this.step.prefix
|
|
: h(QIcon, { props: { name: this.icon } })
|
|
])
|
|
])
|
|
];
|
|
|
|
if (this.step.title !== void 0 && this.step.title !== null) {
|
|
var content = [
|
|
h('div', { staticClass: 'q-stepper__title' }, [ this.step.title ])
|
|
];
|
|
|
|
if (this.step.caption !== void 0 && this.step.caption !== null) {
|
|
content.push(
|
|
h('div', { staticClass: 'q-stepper__caption' }, [ this.step.caption ])
|
|
);
|
|
}
|
|
|
|
child.push(
|
|
h('div', {
|
|
staticClass: 'q-stepper__label q-stepper__line relative-position'
|
|
}, content)
|
|
);
|
|
}
|
|
|
|
return h('div', data, child)
|
|
}
|
|
});
|
|
|
|
var StepWrapper = Vue.extend({
|
|
name: 'QStepWrapper',
|
|
|
|
render: function render (h) {
|
|
return h('div', {
|
|
staticClass: 'q-stepper__step-content'
|
|
}, [
|
|
h('div', {
|
|
staticClass: 'q-stepper__step-inner'
|
|
}, slot(this, 'default'))
|
|
])
|
|
}
|
|
});
|
|
|
|
var QStep = Vue.extend({
|
|
name: 'QStep',
|
|
|
|
inject: {
|
|
stepper: {
|
|
default: function default$1 () {
|
|
console.error('QStep needs to be child of QStepper');
|
|
}
|
|
}
|
|
},
|
|
|
|
mixins: [ PanelChildMixin ],
|
|
|
|
props: {
|
|
icon: String,
|
|
color: String,
|
|
title: {
|
|
type: String,
|
|
required: true
|
|
},
|
|
caption: String,
|
|
prefix: [ String, Number ],
|
|
|
|
doneIcon: String,
|
|
doneColor: String,
|
|
activeIcon: String,
|
|
activeColor: String,
|
|
errorIcon: String,
|
|
errorColor: String,
|
|
|
|
headerNav: {
|
|
type: Boolean,
|
|
default: true
|
|
},
|
|
done: Boolean,
|
|
error: Boolean
|
|
},
|
|
|
|
computed: {
|
|
isActive: function isActive () {
|
|
return this.stepper.value === this.name
|
|
}
|
|
},
|
|
|
|
watch: {
|
|
isActive: function isActive (active) {
|
|
var this$1 = this;
|
|
|
|
if (
|
|
active === true &&
|
|
this.stepper.vertical === true
|
|
) {
|
|
this.$nextTick(function () {
|
|
if (this$1.$el !== void 0) {
|
|
this$1.$el.scrollTop = 0;
|
|
}
|
|
});
|
|
}
|
|
}
|
|
},
|
|
|
|
render: function render (h) {
|
|
var vertical = this.stepper.vertical;
|
|
var content = vertical === true && this.stepper.keepAlive === true
|
|
? h(
|
|
'keep-alive',
|
|
this.isActive === true
|
|
? [ h(StepWrapper, { key: this.name }, slot(this, 'default')) ]
|
|
: void 0
|
|
)
|
|
: (
|
|
vertical !== true || this.isActive === true
|
|
? StepWrapper.options.render.call(this, h)
|
|
: void 0
|
|
);
|
|
|
|
return h(
|
|
'div',
|
|
{
|
|
staticClass: 'q-stepper__step',
|
|
on: Object.assign({}, this.qListeners)
|
|
},
|
|
vertical === true
|
|
? [
|
|
h(StepHeader, {
|
|
props: {
|
|
stepper: this.stepper,
|
|
step: this
|
|
}
|
|
}),
|
|
|
|
this.stepper.animated === true
|
|
? h(QSlideTransition, [ content ])
|
|
: content
|
|
]
|
|
: [ content ]
|
|
)
|
|
}
|
|
});
|
|
|
|
var QStepper = Vue.extend({
|
|
name: 'QStepper',
|
|
|
|
provide: function provide () {
|
|
return {
|
|
stepper: this
|
|
}
|
|
},
|
|
|
|
mixins: [ DarkMixin, PanelParentMixin ],
|
|
|
|
props: {
|
|
flat: Boolean,
|
|
bordered: Boolean,
|
|
alternativeLabels: Boolean,
|
|
headerNav: Boolean,
|
|
contracted: Boolean,
|
|
headerClass: String,
|
|
|
|
inactiveColor: String,
|
|
inactiveIcon: String,
|
|
doneIcon: String,
|
|
doneColor: String,
|
|
activeIcon: String,
|
|
activeColor: String,
|
|
errorIcon: String,
|
|
errorColor: String
|
|
},
|
|
|
|
computed: {
|
|
classes: function classes () {
|
|
return "q-stepper q-stepper--" + (this.vertical === true ? 'vertical' : 'horizontal') +
|
|
(this.flat === true || this.isDark === true ? ' q-stepper--flat no-shadow' : '') +
|
|
(this.bordered === true || (this.isDark === true && this.flat === false) ? ' q-stepper--bordered' : '') +
|
|
(this.contracted === true ? ' q-stepper--contracted' : '') +
|
|
(this.isDark === true ? ' q-stepper--dark q-dark' : '')
|
|
},
|
|
|
|
headerClasses: function headerClasses () {
|
|
return 'q-stepper__header row items-stretch justify-between' +
|
|
" q-stepper__header--" + (this.alternativeLabels === true ? 'alternative' : 'standard') + "-labels" +
|
|
(this.flat === false || this.bordered === true ? ' q-stepper__header--border' : '') +
|
|
(this.headerClass !== void 0 ? (" " + (this.headerClass)) : '')
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
__getContent: function __getContent (h) {
|
|
var this$1 = this;
|
|
|
|
var top = slot(this, 'message', []);
|
|
|
|
if (this.vertical === true) {
|
|
this.__isValidPanelName(this.value) && this.__updatePanelIndex();
|
|
|
|
var content = h('div', {
|
|
staticClass: 'q-stepper__content',
|
|
// stop propagation of content emitted @input
|
|
// which would tamper with Panel's model
|
|
on: cache(this, 'stop', { input: stop })
|
|
}, slot(this, 'default'));
|
|
|
|
return top === void 0
|
|
? [ content ]
|
|
: top.concat(content)
|
|
}
|
|
|
|
return [
|
|
h('div', { class: this.headerClasses }, this.__getAllPanels().map(function (panel) {
|
|
var step = panel.componentOptions.propsData;
|
|
|
|
return h(StepHeader, {
|
|
key: step.name,
|
|
props: {
|
|
stepper: this$1,
|
|
step: step
|
|
}
|
|
})
|
|
}))
|
|
].concat(
|
|
top,
|
|
|
|
h('div', {
|
|
staticClass: 'q-stepper__content q-panel-parent',
|
|
directives: this.panelDirectives
|
|
}, this.__getPanelContent(h))
|
|
)
|
|
},
|
|
|
|
__renderPanels: function __renderPanels (h) {
|
|
return h('div', {
|
|
class: this.classes,
|
|
on: Object.assign({}, this.qListeners)
|
|
}, mergeSlot(this.__getContent(h), this, 'navigation'))
|
|
}
|
|
}
|
|
});
|
|
|
|
var QStepperNavigation = Vue.extend({
|
|
name: 'QStepperNavigation',
|
|
|
|
mixins: [ ListenersMixin ],
|
|
|
|
render: function render (h) {
|
|
return h('div', {
|
|
staticClass: 'q-stepper__nav',
|
|
on: Object.assign({}, this.qListeners)
|
|
}, slot(this, 'default'))
|
|
}
|
|
});
|
|
|
|
var Top = {
|
|
computed: {
|
|
marginalsProps: function marginalsProps () {
|
|
return {
|
|
pagination: this.computedPagination,
|
|
pagesNumber: this.pagesNumber,
|
|
isFirstPage: this.isFirstPage,
|
|
isLastPage: this.isLastPage,
|
|
firstPage: this.firstPage,
|
|
prevPage: this.prevPage,
|
|
nextPage: this.nextPage,
|
|
lastPage: this.lastPage,
|
|
|
|
inFullscreen: this.inFullscreen,
|
|
toggleFullscreen: this.toggleFullscreen
|
|
}
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
getTop: function getTop (h) {
|
|
var
|
|
top = this.$scopedSlots.top,
|
|
topLeft = this.$scopedSlots['top-left'],
|
|
topRight = this.$scopedSlots['top-right'],
|
|
topSelection = this.$scopedSlots['top-selection'],
|
|
hasSelection = this.hasSelectionMode === true &&
|
|
topSelection !== void 0 &&
|
|
this.rowsSelectedNumber > 0,
|
|
staticClass = 'q-table__top relative-position row items-center';
|
|
|
|
if (top !== void 0) {
|
|
return h('div', { staticClass: staticClass }, [ top(this.marginalsProps) ])
|
|
}
|
|
|
|
var child;
|
|
|
|
if (hasSelection === true) {
|
|
child = topSelection(this.marginalsProps).slice();
|
|
}
|
|
else {
|
|
child = [];
|
|
|
|
if (topLeft !== void 0) {
|
|
child.push(
|
|
h('div', { staticClass: 'q-table-control' }, [
|
|
topLeft(this.marginalsProps)
|
|
])
|
|
);
|
|
}
|
|
else if (this.title) {
|
|
child.push(
|
|
h('div', { staticClass: 'q-table__control' }, [
|
|
h('div', { staticClass: 'q-table__title', class: this.titleClass }, this.title)
|
|
])
|
|
);
|
|
}
|
|
}
|
|
|
|
if (topRight !== void 0) {
|
|
child.push(h('div', { staticClass: 'q-table__separator col' }));
|
|
child.push(
|
|
h('div', { staticClass: 'q-table__control' }, [
|
|
topRight(this.marginalsProps)
|
|
])
|
|
);
|
|
}
|
|
|
|
if (child.length === 0) {
|
|
return
|
|
}
|
|
|
|
return h('div', { staticClass: staticClass }, child)
|
|
}
|
|
}
|
|
};
|
|
|
|
var QTh = Vue.extend({
|
|
name: 'QTh',
|
|
|
|
mixins: [ ListenersMixin ],
|
|
|
|
props: {
|
|
props: Object,
|
|
autoWidth: Boolean
|
|
},
|
|
|
|
render: function render (h) {
|
|
var this$1 = this;
|
|
|
|
var on = Object.assign({}, this.qListeners);
|
|
|
|
if (this.props === void 0) {
|
|
return h('th', {
|
|
on: on,
|
|
class: this.autoWidth === true ? 'q-table--col-auto-width' : null
|
|
}, slot(this, 'default'))
|
|
}
|
|
|
|
var col, child;
|
|
var name = this.$vnode.key;
|
|
|
|
if (name) {
|
|
col = this.props.colsMap[name];
|
|
if (col === void 0) { return }
|
|
}
|
|
else {
|
|
col = this.props.col;
|
|
}
|
|
|
|
if (col.sortable === true) {
|
|
var action = col.align === 'right'
|
|
? 'unshift'
|
|
: 'push';
|
|
|
|
child = uniqueSlot(this, 'default', []);
|
|
child[action](
|
|
h(QIcon, {
|
|
props: { name: this.$q.iconSet.table.arrowUp },
|
|
staticClass: col.__iconClass
|
|
})
|
|
);
|
|
}
|
|
else {
|
|
child = slot(this, 'default');
|
|
}
|
|
|
|
var evt = col.sortable === true
|
|
? {
|
|
click: function (evt) {
|
|
this$1.props.sort(col);
|
|
this$1.$emit('click', evt);
|
|
}
|
|
}
|
|
: {};
|
|
|
|
return h('th', {
|
|
on: Object.assign({}, on, evt),
|
|
style: col.headerStyle,
|
|
class: col.__thClass +
|
|
(this.autoWidth === true ? ' q-table--col-auto-width' : '')
|
|
}, child)
|
|
}
|
|
});
|
|
|
|
var TableHeader = {
|
|
methods: {
|
|
getTableHeader: function getTableHeader (h) {
|
|
var child = this.getTableHeaderRow(h);
|
|
|
|
if (this.loading === true && this.$scopedSlots.loading === void 0) {
|
|
child.push(
|
|
h('tr', { staticClass: 'q-table__progress' }, [
|
|
h('th', {
|
|
staticClass: 'relative-position',
|
|
attrs: { colspan: this.computedColspan }
|
|
}, this.__getProgress(h))
|
|
])
|
|
);
|
|
}
|
|
|
|
return h('thead', child)
|
|
},
|
|
|
|
getTableHeaderRow: function getTableHeaderRow (h) {
|
|
var this$1 = this;
|
|
|
|
var
|
|
header = this.$scopedSlots.header,
|
|
headerCell = this.$scopedSlots['header-cell'];
|
|
|
|
if (header !== void 0) {
|
|
return header(this.addTableHeaderRowMeta({
|
|
header: true, cols: this.computedCols, sort: this.sort, colsMap: this.computedColsMap
|
|
})).slice()
|
|
}
|
|
|
|
var child = this.computedCols.map(function (col) {
|
|
var
|
|
headerCellCol = this$1.$scopedSlots[("header-cell-" + (col.name))],
|
|
slot = headerCellCol !== void 0 ? headerCellCol : headerCell,
|
|
props = {
|
|
col: col, cols: this$1.computedCols, sort: this$1.sort, colsMap: this$1.computedColsMap
|
|
};
|
|
|
|
return slot !== void 0
|
|
? slot(props)
|
|
: h(QTh, {
|
|
key: col.name,
|
|
props: { props: props },
|
|
style: col.headerStyle,
|
|
class: col.headerClasses
|
|
}, col.label)
|
|
});
|
|
|
|
if (this.singleSelection === true && this.grid !== true) {
|
|
child.unshift(h('th', { staticClass: 'q-table--col-auto-width' }, [' ']));
|
|
}
|
|
else if (this.multipleSelection === true) {
|
|
child.unshift(h('th', { staticClass: 'q-table--col-auto-width' }, [
|
|
h(QCheckbox, {
|
|
props: {
|
|
color: this.color,
|
|
value: this.someRowsSelected === true
|
|
? null
|
|
: this.allRowsSelected,
|
|
dark: this.isDark,
|
|
dense: this.dense
|
|
},
|
|
on: cache(this, 'inp', {
|
|
input: function (val) {
|
|
if (this$1.someRowsSelected === true) {
|
|
val = false;
|
|
}
|
|
this$1.__updateSelection(
|
|
this$1.computedRows.map(this$1.getRowKey),
|
|
this$1.computedRows,
|
|
val
|
|
);
|
|
}
|
|
})
|
|
})
|
|
]));
|
|
}
|
|
|
|
return [
|
|
h('tr', {
|
|
style: this.tableHeaderStyle,
|
|
class: this.tableHeaderClass
|
|
}, child)
|
|
]
|
|
},
|
|
|
|
addTableHeaderRowMeta: function addTableHeaderRowMeta (data) {
|
|
var this$1 = this;
|
|
|
|
if (this.multipleSelection === true) {
|
|
Object.defineProperty(data, 'selected', {
|
|
get: function () { return this$1.someRowsSelected === true
|
|
? 'some'
|
|
: this$1.allRowsSelected; },
|
|
set: function (val) {
|
|
if (this$1.someRowsSelected === true) {
|
|
val = false;
|
|
}
|
|
this$1.__updateSelection(
|
|
this$1.computedRows.map(this$1.getRowKey),
|
|
this$1.computedRows,
|
|
val
|
|
);
|
|
},
|
|
configurable: true,
|
|
enumerable: true
|
|
});
|
|
data.partialSelected = this.someRowsSelected;
|
|
data.multipleSelect = true;
|
|
}
|
|
|
|
return data
|
|
}
|
|
}
|
|
};
|
|
|
|
var TableBody = {
|
|
methods: {
|
|
getTableRowBody: function getTableRowBody (row, body, pageIndex) {
|
|
var
|
|
key = this.getRowKey(row),
|
|
selected = this.isRowSelected(key);
|
|
|
|
return body(this.addBodyRowMeta({
|
|
key: key,
|
|
row: row,
|
|
pageIndex: pageIndex,
|
|
cols: this.computedCols,
|
|
colsMap: this.computedColsMap,
|
|
__trClass: selected ? 'selected' : ''
|
|
}))
|
|
},
|
|
|
|
getTableRow: function getTableRow (h, row, pageIndex) {
|
|
var this$1 = this;
|
|
|
|
var
|
|
bodyCell = this.$scopedSlots['body-cell'],
|
|
key = this.getRowKey(row),
|
|
selected = this.isRowSelected(key),
|
|
child = this.computedCols.map(function (col) {
|
|
var
|
|
bodyCellCol = this$1.$scopedSlots[("body-cell-" + (col.name))],
|
|
slot = bodyCellCol !== void 0 ? bodyCellCol : bodyCell;
|
|
|
|
return slot !== void 0
|
|
? slot(this$1.addBodyCellMetaData({ row: row, pageIndex: pageIndex, col: col }))
|
|
: h('td', {
|
|
class: col.__tdClass,
|
|
style: col.style
|
|
}, this$1.getCellValue(col, row))
|
|
});
|
|
|
|
this.hasSelectionMode === true && child.unshift(
|
|
h('td', { staticClass: 'q-table--col-auto-width' }, [
|
|
h(QCheckbox, {
|
|
props: {
|
|
value: selected,
|
|
color: this.color,
|
|
dark: this.isDark,
|
|
dense: this.dense
|
|
},
|
|
on: {
|
|
input: function (adding, evt) {
|
|
this$1.__updateSelection([ key ], [ row ], adding, evt);
|
|
}
|
|
}
|
|
})
|
|
])
|
|
);
|
|
|
|
var data = { key: key, class: { selected: selected }, on: {} };
|
|
|
|
if (this.qListeners['row-click'] !== void 0) {
|
|
data.class['cursor-pointer'] = true;
|
|
data.on.click = function (evt) {
|
|
this$1.$emit('row-click', evt, row, pageIndex);
|
|
};
|
|
}
|
|
|
|
if (this.qListeners['row-dblclick'] !== void 0) {
|
|
data.class['cursor-pointer'] = true;
|
|
data.on.dblclick = function (evt) {
|
|
this$1.$emit('row-dblclick', evt, row, pageIndex);
|
|
};
|
|
}
|
|
|
|
return h('tr', data, child)
|
|
},
|
|
|
|
getTableBody: function getTableBody (h) {
|
|
var this$1 = this;
|
|
|
|
var
|
|
body = this.$scopedSlots.body,
|
|
topRow = this.$scopedSlots['top-row'],
|
|
bottomRow = this.$scopedSlots['bottom-row'],
|
|
mapFn = body !== void 0
|
|
? function (row, pageIndex) { return this$1.getTableRowBody(row, body, pageIndex); }
|
|
: function (row, pageIndex) { return this$1.getTableRow(h, row, pageIndex); };
|
|
|
|
var child = this.computedRows.map(mapFn);
|
|
|
|
if (topRow !== void 0) {
|
|
child = topRow({ cols: this.computedCols }).concat(child);
|
|
}
|
|
if (bottomRow !== void 0) {
|
|
child = child.concat(bottomRow({ cols: this.computedCols }));
|
|
}
|
|
|
|
return h('tbody', child)
|
|
},
|
|
|
|
getTableRowVirtual: function getTableRowVirtual (h) {
|
|
var this$1 = this;
|
|
|
|
var body = this.$scopedSlots.body;
|
|
|
|
return body !== void 0
|
|
? function (props) { return this$1.getTableRowBody(props.item, body, props.index); }
|
|
: function (props) { return this$1.getTableRow(h, props.item, props.index); }
|
|
},
|
|
|
|
addBodyRowMeta: function addBodyRowMeta (data) {
|
|
var this$1 = this;
|
|
|
|
data.rowIndex = this.firstRowIndex + data.pageIndex;
|
|
|
|
this.hasSelectionMode === true && Object.defineProperty(data, 'selected', {
|
|
get: function () { return this$1.isRowSelected(data.key); },
|
|
set: function (adding) {
|
|
this$1.__updateSelection([ data.key ], [ data.row ], adding);
|
|
},
|
|
configurable: true,
|
|
enumerable: true
|
|
});
|
|
|
|
Object.defineProperty(data, 'expand', {
|
|
get: function () { return this$1.isRowExpanded(data.key); },
|
|
set: function (adding) {
|
|
this$1.__updateExpanded(data.key, adding);
|
|
},
|
|
configurable: true,
|
|
enumerable: true
|
|
});
|
|
|
|
data.cols = data.cols.map(function (col) {
|
|
var c = Object.assign({}, col);
|
|
Object.defineProperty(c, 'value', {
|
|
get: function () { return this$1.getCellValue(col, data.row); },
|
|
configurable: true,
|
|
enumerable: true
|
|
});
|
|
return c
|
|
});
|
|
|
|
return data
|
|
},
|
|
|
|
addBodyCellMetaData: function addBodyCellMetaData (data) {
|
|
var this$1 = this;
|
|
|
|
data.rowIndex = this.firstRowIndex + data.pageIndex;
|
|
|
|
Object.defineProperty(data, 'value', {
|
|
get: function () { return this$1.getCellValue(data.col, data.row); },
|
|
configurable: true,
|
|
enumerable: true
|
|
});
|
|
return data
|
|
},
|
|
|
|
getCellValue: function getCellValue (col, row) {
|
|
var val = typeof col.field === 'function' ? col.field(row) : row[col.field];
|
|
return col.format !== void 0 ? col.format(val, row) : val
|
|
}
|
|
}
|
|
};
|
|
|
|
var staticClass = 'q-table__bottom row items-center';
|
|
|
|
var Bottom = {
|
|
props: {
|
|
hideBottom: Boolean,
|
|
hideSelectedBanner: Boolean,
|
|
hideNoData: Boolean,
|
|
hidePagination: Boolean
|
|
},
|
|
|
|
computed: {
|
|
navIcon: function navIcon () {
|
|
var ico = [
|
|
this.iconFirstPage || this.$q.iconSet.table.firstPage,
|
|
this.iconPrevPage || this.$q.iconSet.table.prevPage,
|
|
this.iconNextPage || this.$q.iconSet.table.nextPage,
|
|
this.iconLastPage || this.$q.iconSet.table.lastPage
|
|
];
|
|
return this.$q.lang.rtl === true ? ico.reverse() : ico
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
getBottom: function getBottom (h) {
|
|
if (this.hideBottom === true) {
|
|
return
|
|
}
|
|
|
|
if (this.nothingToDisplay === true) {
|
|
if (this.hideNoData === true) {
|
|
return
|
|
}
|
|
|
|
var message = this.loading === true
|
|
? this.loadingLabel || this.$q.lang.table.loading
|
|
: (this.filter ? this.noResultsLabel || this.$q.lang.table.noResults : this.noDataLabel || this.$q.lang.table.noData);
|
|
|
|
var noData = this.$scopedSlots['no-data'];
|
|
var children = noData !== void 0
|
|
? [ noData({ message: message, icon: this.$q.iconSet.table.warning, filter: this.filter }) ]
|
|
: [
|
|
h(QIcon, {
|
|
staticClass: 'q-table__bottom-nodata-icon',
|
|
props: { name: this.$q.iconSet.table.warning }
|
|
}),
|
|
message
|
|
];
|
|
|
|
return h('div', {
|
|
staticClass: staticClass + ' q-table__bottom--nodata'
|
|
}, children)
|
|
}
|
|
|
|
var bottom = this.$scopedSlots.bottom;
|
|
|
|
if (bottom !== void 0) {
|
|
return h('div', { staticClass: staticClass }, [ bottom(this.marginalsProps) ])
|
|
}
|
|
|
|
var child = this.hideSelectedBanner !== true && this.hasSelectionMode === true && this.rowsSelectedNumber > 0
|
|
? [
|
|
h('div', { staticClass: 'q-table__control' }, [
|
|
h('div', [
|
|
(this.selectedRowsLabel || this.$q.lang.table.selectedRecords)(this.rowsSelectedNumber)
|
|
])
|
|
])
|
|
]
|
|
: [];
|
|
|
|
if (this.hidePagination !== true) {
|
|
return h('div', {
|
|
staticClass: staticClass + ' justify-end'
|
|
}, this.getPaginationRow(h, child))
|
|
}
|
|
|
|
if (child.length > 0) {
|
|
return h('div', { staticClass: staticClass }, child)
|
|
}
|
|
},
|
|
|
|
getPaginationRow: function getPaginationRow (h, child) {
|
|
var this$1 = this;
|
|
|
|
var control;
|
|
var ref = this.computedPagination;
|
|
var rowsPerPage = ref.rowsPerPage;
|
|
var paginationLabel = this.paginationLabel || this.$q.lang.table.pagination,
|
|
paginationSlot = this.$scopedSlots.pagination,
|
|
hasOpts = this.rowsPerPageOptions.length > 1;
|
|
|
|
child.push(
|
|
h('div', { staticClass: 'q-table__separator col' })
|
|
);
|
|
|
|
if (hasOpts === true) {
|
|
child.push(
|
|
h('div', { staticClass: 'q-table__control' }, [
|
|
h('span', { staticClass: 'q-table__bottom-item' }, [
|
|
this.rowsPerPageLabel || this.$q.lang.table.recordsPerPage
|
|
]),
|
|
h(QSelect, {
|
|
staticClass: 'q-table__select inline q-table__bottom-item',
|
|
props: {
|
|
color: this.color,
|
|
value: rowsPerPage,
|
|
options: this.computedRowsPerPageOptions,
|
|
displayValue: rowsPerPage === 0
|
|
? this.$q.lang.table.allRows
|
|
: rowsPerPage,
|
|
dark: this.isDark,
|
|
borderless: true,
|
|
dense: true,
|
|
optionsDense: true,
|
|
optionsCover: true
|
|
},
|
|
on: cache(this, 'pgSize', {
|
|
input: function (pag) {
|
|
this$1.setPagination({
|
|
page: 1,
|
|
rowsPerPage: pag.value
|
|
});
|
|
}
|
|
})
|
|
})
|
|
])
|
|
);
|
|
}
|
|
|
|
if (paginationSlot !== void 0) {
|
|
control = paginationSlot(this.marginalsProps);
|
|
}
|
|
else {
|
|
control = [
|
|
h('span', rowsPerPage !== 0 ? { staticClass: 'q-table__bottom-item' } : {}, [
|
|
rowsPerPage
|
|
? paginationLabel(this.firstRowIndex + 1, Math.min(this.lastRowIndex, this.computedRowsNumber), this.computedRowsNumber)
|
|
: paginationLabel(1, this.filteredSortedRowsNumber, this.computedRowsNumber)
|
|
])
|
|
];
|
|
|
|
if (rowsPerPage !== 0 && this.pagesNumber > 1) {
|
|
var btnProps = {
|
|
color: this.color,
|
|
round: true,
|
|
dense: true,
|
|
flat: true
|
|
};
|
|
|
|
if (this.dense === true) {
|
|
btnProps.size = 'sm';
|
|
}
|
|
|
|
this.pagesNumber > 2 && control.push(
|
|
h(QBtn, {
|
|
key: 'pgFirst',
|
|
props: Object.assign({}, btnProps,
|
|
{icon: this.navIcon[0],
|
|
disable: this.isFirstPage}),
|
|
on: cache(this, 'pgFirst', { click: this.firstPage })
|
|
})
|
|
);
|
|
|
|
control.push(
|
|
h(QBtn, {
|
|
key: 'pgPrev',
|
|
props: Object.assign({}, btnProps,
|
|
{icon: this.navIcon[1],
|
|
disable: this.isFirstPage}),
|
|
on: cache(this, 'pgPrev', { click: this.prevPage })
|
|
}),
|
|
|
|
h(QBtn, {
|
|
key: 'pgNext',
|
|
props: Object.assign({}, btnProps,
|
|
{icon: this.navIcon[2],
|
|
disable: this.isLastPage}),
|
|
on: cache(this, 'pgNext', { click: this.nextPage })
|
|
})
|
|
);
|
|
|
|
this.pagesNumber > 2 && control.push(
|
|
h(QBtn, {
|
|
key: 'pgLast',
|
|
props: Object.assign({}, btnProps,
|
|
{icon: this.navIcon[3],
|
|
disable: this.isLastPage}),
|
|
on: cache(this, 'pgLast', { click: this.lastPage })
|
|
})
|
|
);
|
|
}
|
|
}
|
|
|
|
child.push(
|
|
h('div', { staticClass: 'q-table__control' }, control)
|
|
);
|
|
|
|
return child
|
|
}
|
|
}
|
|
};
|
|
|
|
var TableGrid = {
|
|
methods: {
|
|
getGridBody: function getGridBody (h) {
|
|
var this$1 = this;
|
|
|
|
var item = this.$scopedSlots.item !== void 0
|
|
? this.$scopedSlots.item
|
|
: function (scope) {
|
|
var child = scope.cols.map(
|
|
function (col) { return h('div', { staticClass: 'q-table__grid-item-row' }, [
|
|
h('div', { staticClass: 'q-table__grid-item-title' }, [ col.label ]),
|
|
h('div', { staticClass: 'q-table__grid-item-value' }, [ col.value ])
|
|
]); }
|
|
);
|
|
|
|
this$1.hasSelectionMode === true && child.unshift(
|
|
h('div', { staticClass: 'q-table__grid-item-row' }, [
|
|
h(QCheckbox, {
|
|
props: {
|
|
value: scope.selected,
|
|
color: this$1.color,
|
|
dark: this$1.isDark,
|
|
dense: true
|
|
},
|
|
on: {
|
|
input: function (adding, evt) {
|
|
this$1.__updateSelection([ scope.key ], [ scope.row ], adding, evt);
|
|
}
|
|
}
|
|
})
|
|
]),
|
|
|
|
h(QSeparator, { props: { dark: this$1.isDark } })
|
|
);
|
|
|
|
var data = {
|
|
staticClass: 'q-table__grid-item-card' + this$1.cardDefaultClass,
|
|
class: this$1.cardClass,
|
|
style: this$1.cardStyle,
|
|
on: {}
|
|
};
|
|
|
|
if (this$1.qListeners['row-click'] !== void 0 || this$1.qListeners['row-dblclick'] !== void 0) {
|
|
data.staticClass += ' cursor-pointer';
|
|
}
|
|
|
|
if (this$1.qListeners['row-click'] !== void 0) {
|
|
data.on.click = function (evt) {
|
|
this$1.$emit('row-click', evt, scope.row, scope.pageIndex);
|
|
};
|
|
}
|
|
|
|
if (this$1.qListeners['row-dblclick'] !== void 0) {
|
|
data.on.dblclick = function (evt) {
|
|
this$1.$emit('row-dblclick', evt, scope.row, scope.pageIndex);
|
|
};
|
|
}
|
|
|
|
return h('div', {
|
|
staticClass: 'q-table__grid-item col-xs-12 col-sm-6 col-md-4 col-lg-3',
|
|
class: scope.selected === true ? 'q-table__grid-item--selected' : ''
|
|
}, [
|
|
h('div', data, child)
|
|
])
|
|
};
|
|
|
|
return h('div', {
|
|
staticClass: 'q-table__grid-content row',
|
|
class: this.cardContainerClass,
|
|
style: this.cardContainerStyle
|
|
}, this.computedRows.map(function (row, pageIndex) {
|
|
var
|
|
key = this$1.getRowKey(row),
|
|
selected = this$1.isRowSelected(key);
|
|
|
|
return item(this$1.addBodyRowMeta({
|
|
key: key,
|
|
row: row,
|
|
pageIndex: pageIndex,
|
|
cols: this$1.computedCols,
|
|
colsMap: this$1.computedColsMap,
|
|
__trClass: selected ? 'selected' : ''
|
|
}))
|
|
}))
|
|
},
|
|
|
|
getGridHeader: function getGridHeader (h) {
|
|
var child = this.gridHeader === true
|
|
? [
|
|
h('table', { staticClass: 'q-table' }, [
|
|
this.getTableHeader(h)
|
|
])
|
|
]
|
|
: (
|
|
this.loading === true && this.$scopedSlots.loading === void 0
|
|
? this.__getProgress(h)
|
|
: void 0
|
|
);
|
|
|
|
return h('div', { staticClass: 'q-table__middle' }, child)
|
|
}
|
|
}
|
|
};
|
|
|
|
function getTableMiddle (h, conf, content) {
|
|
return h('div', Object.assign({}, conf,
|
|
{staticClass: 'q-table__middle' + (conf.staticClass !== void 0 ? ' ' + conf.staticClass : '')}), [
|
|
h('table', { staticClass: 'q-table' }, content)
|
|
])
|
|
}
|
|
|
|
var comps = {
|
|
list: QList,
|
|
table: QMarkupTable
|
|
};
|
|
|
|
var QVirtualScroll = Vue.extend({
|
|
name: 'QVirtualScroll',
|
|
|
|
mixins: [ AttrsMixin, ListenersMixin, VirtualScroll ],
|
|
|
|
props: {
|
|
type: {
|
|
type: String,
|
|
default: 'list',
|
|
validator: function (v) { return ['list', 'table', '__qtable'].includes(v); }
|
|
},
|
|
|
|
items: {
|
|
type: Array,
|
|
default: function () { return []; }
|
|
},
|
|
|
|
itemsFn: Function,
|
|
itemsSize: Number,
|
|
|
|
scrollTarget: {
|
|
default: void 0
|
|
}
|
|
},
|
|
|
|
computed: {
|
|
virtualScrollLength: function virtualScrollLength () {
|
|
return this.itemsSize >= 0 && this.itemsFn !== void 0
|
|
? parseInt(this.itemsSize, 10)
|
|
: (Array.isArray(this.items) ? this.items.length : 0)
|
|
},
|
|
|
|
virtualScrollScope: function virtualScrollScope () {
|
|
var this$1 = this;
|
|
|
|
if (this.virtualScrollLength === 0) {
|
|
return []
|
|
}
|
|
|
|
var mapFn = function (item, i) { return ({
|
|
index: this$1.virtualScrollSliceRange.from + i,
|
|
item: item
|
|
}); };
|
|
|
|
if (this.itemsFn === void 0) {
|
|
return this.items.slice(this.virtualScrollSliceRange.from, this.virtualScrollSliceRange.to).map(mapFn)
|
|
}
|
|
|
|
return this.itemsFn(this.virtualScrollSliceRange.from, this.virtualScrollSliceRange.to - this.virtualScrollSliceRange.from).map(mapFn)
|
|
},
|
|
|
|
classes: function classes () {
|
|
return 'q-virtual-scroll q-virtual-scroll' + (this.virtualScrollHorizontal === true ? '--horizontal' : '--vertical') +
|
|
(this.scrollTarget !== void 0 ? '' : ' scroll')
|
|
},
|
|
|
|
attrs: function attrs () {
|
|
return this.scrollTarget !== void 0 ? void 0 : { tabindex: 0 }
|
|
}
|
|
},
|
|
|
|
watch: {
|
|
virtualScrollLength: function virtualScrollLength () {
|
|
this.__resetVirtualScroll();
|
|
},
|
|
|
|
scrollTarget: function scrollTarget () {
|
|
this.__unconfigureScrollTarget();
|
|
this.__configureScrollTarget();
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
__getVirtualScrollEl: function __getVirtualScrollEl () {
|
|
return this.$el
|
|
},
|
|
|
|
__getVirtualScrollTarget: function __getVirtualScrollTarget () {
|
|
return this.__scrollTarget
|
|
},
|
|
|
|
__configureScrollTarget: function __configureScrollTarget () {
|
|
this.__scrollTarget = getScrollTarget(this.$el, this.scrollTarget);
|
|
this.__scrollTarget.addEventListener('scroll', this.__onVirtualScrollEvt, listenOpts.passive);
|
|
},
|
|
|
|
__unconfigureScrollTarget: function __unconfigureScrollTarget () {
|
|
if (this.__scrollTarget !== void 0) {
|
|
this.__scrollTarget.removeEventListener('scroll', this.__onVirtualScrollEvt, listenOpts.passive);
|
|
this.__scrollTarget = void 0;
|
|
}
|
|
}
|
|
},
|
|
|
|
beforeMount: function beforeMount () {
|
|
this.__resetVirtualScroll();
|
|
},
|
|
|
|
mounted: function mounted () {
|
|
this.__configureScrollTarget();
|
|
},
|
|
|
|
beforeDestroy: function beforeDestroy () {
|
|
this.__unconfigureScrollTarget();
|
|
},
|
|
|
|
render: function render (h) {
|
|
if (this.$scopedSlots.default === void 0) {
|
|
console.error("QVirtualScroll: default scoped slot is required for rendering", this);
|
|
return
|
|
}
|
|
|
|
var child = this.__padVirtualScroll(
|
|
h,
|
|
this.type === 'list' ? 'div' : 'tbody',
|
|
this.virtualScrollScope.map(this.$scopedSlots.default)
|
|
);
|
|
|
|
if (this.$scopedSlots.before !== void 0) {
|
|
child = this.$scopedSlots.before().concat(child);
|
|
}
|
|
|
|
child = mergeSlot(child, this, 'after');
|
|
|
|
return this.type === '__qtable'
|
|
? getTableMiddle(h, { staticClass: this.classes }, child)
|
|
: h(comps[this.type], {
|
|
class: this.classes,
|
|
attrs: this.attrs,
|
|
props: this.qAttrs,
|
|
on: Object.assign({}, this.qListeners)
|
|
}, child)
|
|
}
|
|
});
|
|
|
|
function sortDate (a, b) {
|
|
return (new Date(a)) - (new Date(b))
|
|
}
|
|
|
|
var Sort = {
|
|
props: {
|
|
sortMethod: {
|
|
type: Function,
|
|
default: function default$1 (data, sortBy, descending) {
|
|
var col = this.colList.find(function (def) { return def.name === sortBy; });
|
|
if (col === void 0 || col.field === void 0) {
|
|
return data
|
|
}
|
|
|
|
var
|
|
dir = descending === true ? -1 : 1,
|
|
val = typeof col.field === 'function'
|
|
? function (v) { return col.field(v); }
|
|
: function (v) { return v[col.field]; };
|
|
|
|
return data.sort(function (a, b) {
|
|
var assign;
|
|
|
|
var
|
|
A = val(a),
|
|
B = val(b);
|
|
|
|
if (A === null || A === void 0) {
|
|
return -1 * dir
|
|
}
|
|
if (B === null || B === void 0) {
|
|
return 1 * dir
|
|
}
|
|
if (col.sort !== void 0) {
|
|
return col.sort(A, B, a, b) * dir
|
|
}
|
|
if (isNumber(A) === true && isNumber(B) === true) {
|
|
return (A - B) * dir
|
|
}
|
|
if (isDate(A) === true && isDate(B) === true) {
|
|
return sortDate(A, B) * dir
|
|
}
|
|
if (typeof A === 'boolean' && typeof B === 'boolean') {
|
|
return (A - B) * dir
|
|
}
|
|
|
|
(assign = [A, B].map(function (s) { return (s + '').toLocaleString().toLowerCase(); }), A = assign[0], B = assign[1]);
|
|
|
|
return A < B
|
|
? -1 * dir
|
|
: (A === B ? 0 : dir)
|
|
})
|
|
}
|
|
}
|
|
},
|
|
|
|
computed: {
|
|
columnToSort: function columnToSort () {
|
|
var ref = this.computedPagination;
|
|
var sortBy = ref.sortBy;
|
|
|
|
if (sortBy) {
|
|
return this.colList.find(function (def) { return def.name === sortBy; }) || null
|
|
}
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
sort: function sort (col /* String(col name) or Object(col definition) */) {
|
|
if (col === Object(col)) {
|
|
col = col.name;
|
|
}
|
|
|
|
var ref = this.computedPagination;
|
|
var sortBy = ref.sortBy;
|
|
var descending = ref.descending;
|
|
|
|
if (sortBy !== col) {
|
|
sortBy = col;
|
|
descending = false;
|
|
}
|
|
else if (this.binaryStateSort === true) {
|
|
descending = !descending;
|
|
}
|
|
else if (descending === true) {
|
|
sortBy = null;
|
|
}
|
|
else {
|
|
descending = true;
|
|
}
|
|
|
|
this.setPagination({ sortBy: sortBy, descending: descending, page: 1 });
|
|
}
|
|
}
|
|
};
|
|
|
|
var Filter = {
|
|
props: {
|
|
filter: [String, Object],
|
|
filterMethod: {
|
|
type: Function,
|
|
default: function default$1 (rows, terms, cols, cellValue) {
|
|
if ( cols === void 0 ) cols = this.computedCols;
|
|
if ( cellValue === void 0 ) cellValue = this.getCellValue;
|
|
|
|
var lowerTerms = terms ? terms.toLowerCase() : '';
|
|
return rows.filter(
|
|
function (row) { return cols.some(function (col) {
|
|
var val = cellValue(col, row) + '';
|
|
var haystack = (val === 'undefined' || val === 'null') ? '' : val.toLowerCase();
|
|
return haystack.indexOf(lowerTerms) !== -1
|
|
}); }
|
|
)
|
|
}
|
|
}
|
|
},
|
|
|
|
watch: {
|
|
filter: {
|
|
handler: function handler () {
|
|
var this$1 = this;
|
|
|
|
this.$nextTick(function () {
|
|
this$1.setPagination({ page: 1 }, true);
|
|
});
|
|
},
|
|
deep: true
|
|
}
|
|
}
|
|
};
|
|
|
|
function samePagination (oldPag, newPag) {
|
|
for (var prop in newPag) {
|
|
if (newPag[prop] !== oldPag[prop]) {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
function fixPagination (p) {
|
|
if (p.page < 1) {
|
|
p.page = 1;
|
|
}
|
|
if (p.rowsPerPage !== void 0 && p.rowsPerPage < 1) {
|
|
p.rowsPerPage = 0;
|
|
}
|
|
return p
|
|
}
|
|
|
|
var Pagination = {
|
|
props: {
|
|
pagination: Object,
|
|
rowsPerPageOptions: {
|
|
type: Array,
|
|
default: function () { return [ 5, 7, 10, 15, 20, 25, 50, 0 ]; }
|
|
}
|
|
},
|
|
|
|
computed: {
|
|
computedPagination: function computedPagination () {
|
|
var pag = this.qListeners['update:pagination'] !== void 0
|
|
? Object.assign({}, this.innerPagination, this.pagination)
|
|
: this.innerPagination;
|
|
|
|
return fixPagination(pag)
|
|
},
|
|
|
|
firstRowIndex: function firstRowIndex () {
|
|
var ref = this.computedPagination;
|
|
var page = ref.page;
|
|
var rowsPerPage = ref.rowsPerPage;
|
|
return (page - 1) * rowsPerPage
|
|
},
|
|
|
|
lastRowIndex: function lastRowIndex () {
|
|
var ref = this.computedPagination;
|
|
var page = ref.page;
|
|
var rowsPerPage = ref.rowsPerPage;
|
|
return page * rowsPerPage
|
|
},
|
|
|
|
isFirstPage: function isFirstPage () {
|
|
return this.computedPagination.page === 1
|
|
},
|
|
|
|
pagesNumber: function pagesNumber () {
|
|
return this.computedPagination.rowsPerPage === 0
|
|
? 1
|
|
: Math.max(
|
|
1,
|
|
Math.ceil(this.computedRowsNumber / this.computedPagination.rowsPerPage)
|
|
)
|
|
},
|
|
|
|
isLastPage: function isLastPage () {
|
|
return this.lastRowIndex === 0
|
|
? true
|
|
: this.computedPagination.page >= this.pagesNumber
|
|
},
|
|
|
|
computedRowsPerPageOptions: function computedRowsPerPageOptions () {
|
|
var this$1 = this;
|
|
|
|
var opts = this.rowsPerPageOptions.includes(this.innerPagination.rowsPerPage)
|
|
? this.rowsPerPageOptions
|
|
: [ this.innerPagination.rowsPerPage ].concat(this.rowsPerPageOptions);
|
|
|
|
return opts.map(function (count) { return ({
|
|
label: count === 0 ? this$1.$q.lang.table.allRows : '' + count,
|
|
value: count
|
|
}); })
|
|
}
|
|
},
|
|
|
|
watch: {
|
|
pagesNumber: function pagesNumber (lastPage, oldLastPage) {
|
|
if (lastPage === oldLastPage) {
|
|
return
|
|
}
|
|
|
|
var currentPage = this.computedPagination.page;
|
|
if (lastPage && !currentPage) {
|
|
this.setPagination({ page: 1 });
|
|
}
|
|
else if (lastPage < currentPage) {
|
|
this.setPagination({ page: lastPage });
|
|
}
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
__sendServerRequest: function __sendServerRequest (pagination) {
|
|
this.requestServerInteraction({
|
|
pagination: pagination,
|
|
filter: this.filter
|
|
});
|
|
},
|
|
|
|
setPagination: function setPagination (val, forceServerRequest) {
|
|
var newPagination = fixPagination(Object.assign({}, this.computedPagination,
|
|
val));
|
|
|
|
if (samePagination(this.computedPagination, newPagination)) {
|
|
if (this.isServerSide === true && forceServerRequest === true) {
|
|
this.__sendServerRequest(newPagination);
|
|
}
|
|
return
|
|
}
|
|
|
|
if (this.isServerSide === true) {
|
|
this.__sendServerRequest(newPagination);
|
|
return
|
|
}
|
|
|
|
if (this.pagination !== void 0 && this.qListeners['update:pagination'] !== void 0) {
|
|
this.$emit('update:pagination', newPagination);
|
|
}
|
|
else {
|
|
this.innerPagination = newPagination;
|
|
}
|
|
},
|
|
|
|
firstPage: function firstPage () {
|
|
this.setPagination({ page: 1 });
|
|
},
|
|
|
|
prevPage: function prevPage () {
|
|
var ref = this.computedPagination;
|
|
var page = ref.page;
|
|
if (page > 1) {
|
|
this.setPagination({ page: page - 1 });
|
|
}
|
|
},
|
|
|
|
nextPage: function nextPage () {
|
|
var ref = this.computedPagination;
|
|
var page = ref.page;
|
|
var rowsPerPage = ref.rowsPerPage;
|
|
if (this.lastRowIndex > 0 && page * rowsPerPage < this.computedRowsNumber) {
|
|
this.setPagination({ page: page + 1 });
|
|
}
|
|
},
|
|
|
|
lastPage: function lastPage () {
|
|
this.setPagination({ page: this.pagesNumber });
|
|
}
|
|
},
|
|
|
|
created: function created () {
|
|
if (this.qListeners['update:pagination'] !== void 0) {
|
|
this.$emit('update:pagination', Object.assign({}, this.computedPagination));
|
|
}
|
|
}
|
|
};
|
|
|
|
var RowSelection = {
|
|
props: {
|
|
selection: {
|
|
type: String,
|
|
default: 'none',
|
|
validator: function (v) { return ['single', 'multiple', 'none'].includes(v); }
|
|
},
|
|
selected: {
|
|
type: Array,
|
|
default: function () { return []; }
|
|
}
|
|
},
|
|
|
|
computed: {
|
|
selectedKeys: function selectedKeys () {
|
|
var keys = {};
|
|
this.selected.map(this.getRowKey).forEach(function (key) {
|
|
keys[key] = true;
|
|
});
|
|
return keys
|
|
},
|
|
|
|
hasSelectionMode: function hasSelectionMode () {
|
|
return this.selection !== 'none'
|
|
},
|
|
|
|
singleSelection: function singleSelection () {
|
|
return this.selection === 'single'
|
|
},
|
|
|
|
multipleSelection: function multipleSelection () {
|
|
return this.selection === 'multiple'
|
|
},
|
|
|
|
allRowsSelected: function allRowsSelected () {
|
|
var this$1 = this;
|
|
|
|
return this.computedRows.length > 0 && this.computedRows.every(
|
|
function (row) { return this$1.selectedKeys[ this$1.getRowKey(row) ] === true; }
|
|
)
|
|
},
|
|
|
|
someRowsSelected: function someRowsSelected () {
|
|
var this$1 = this;
|
|
|
|
return this.allRowsSelected !== true &&
|
|
this.computedRows.some(function (row) { return this$1.selectedKeys[ this$1.getRowKey(row) ] === true; })
|
|
},
|
|
|
|
rowsSelectedNumber: function rowsSelectedNumber () {
|
|
return this.selected.length
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
isRowSelected: function isRowSelected (key) {
|
|
return this.selectedKeys[key] === true
|
|
},
|
|
|
|
clearSelection: function clearSelection () {
|
|
this.$emit('update:selected', []);
|
|
},
|
|
|
|
__updateSelection: function __updateSelection (keys, rows, added, evt) {
|
|
var this$1 = this;
|
|
|
|
this.$emit('selection', { rows: rows, added: added, keys: keys, evt: evt });
|
|
|
|
var payload = this.singleSelection === true
|
|
? (added === true ? rows : [])
|
|
: (
|
|
added === true
|
|
? this.selected.concat(rows)
|
|
: this.selected.filter(
|
|
function (row) { return keys.includes(this$1.getRowKey(row)) === false; }
|
|
)
|
|
);
|
|
|
|
this.$emit('update:selected', payload);
|
|
}
|
|
}
|
|
};
|
|
|
|
function getVal (val) {
|
|
return Array.isArray(val)
|
|
? val.slice()
|
|
: []
|
|
}
|
|
|
|
var RowExpand = {
|
|
props: {
|
|
expanded: Array // sync
|
|
},
|
|
|
|
data: function data () {
|
|
return {
|
|
innerExpanded: getVal(this.expanded)
|
|
}
|
|
},
|
|
|
|
watch: {
|
|
expanded: function expanded (val) {
|
|
this.innerExpanded = getVal(val);
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
isRowExpanded: function isRowExpanded (key) {
|
|
return this.innerExpanded.includes(key)
|
|
},
|
|
|
|
setExpanded: function setExpanded (val) {
|
|
if (this.expanded !== void 0) {
|
|
this.$emit('update:expanded', val);
|
|
}
|
|
else {
|
|
this.innerExpanded = val;
|
|
}
|
|
},
|
|
|
|
__updateExpanded: function __updateExpanded (key, add) {
|
|
var target = this.innerExpanded.slice();
|
|
var index = target.indexOf(key);
|
|
|
|
if (add === true) {
|
|
if (index === -1) {
|
|
target.push(key);
|
|
this.setExpanded(target);
|
|
}
|
|
}
|
|
else if (index !== -1) {
|
|
target.splice(index, 1);
|
|
this.setExpanded(target);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
var ColumnSelection = {
|
|
props: {
|
|
visibleColumns: Array
|
|
},
|
|
|
|
computed: {
|
|
colList: function colList () {
|
|
if (this.columns !== void 0) {
|
|
return this.columns
|
|
}
|
|
|
|
// we infer columns from first row
|
|
var row = this.data[0];
|
|
|
|
return row !== void 0
|
|
? Object.keys(row).map(function (name) { return ({
|
|
name: name,
|
|
label: name.toUpperCase(),
|
|
field: name,
|
|
align: isNumber(row[name]) ? 'right' : 'left',
|
|
sortable: true
|
|
}); })
|
|
: []
|
|
},
|
|
|
|
computedCols: function computedCols () {
|
|
var this$1 = this;
|
|
|
|
var ref = this.computedPagination;
|
|
var sortBy = ref.sortBy;
|
|
var descending = ref.descending;
|
|
|
|
var cols = this.visibleColumns !== void 0
|
|
? this.colList.filter(function (col) { return col.required === true || this$1.visibleColumns.includes(col.name) === true; })
|
|
: this.colList;
|
|
|
|
return cols.map(function (col) {
|
|
var align = col.align || 'right';
|
|
|
|
return Object.assign({}, col,
|
|
{align: align,
|
|
__iconClass: ("q-table__sort-icon q-table__sort-icon--" + align),
|
|
__thClass: "text-" + align +
|
|
(col.headerClasses !== void 0 ? ' ' + col.headerClasses : '') +
|
|
(col.sortable === true ? ' sortable' : '') +
|
|
(col.name === sortBy ? (" sorted " + (descending === true ? 'sort-desc' : '')) : ''),
|
|
__tdClass: ("text-" + align + (col.classes !== void 0 ? ' ' + col.classes : ''))})
|
|
})
|
|
},
|
|
|
|
computedColsMap: function computedColsMap () {
|
|
var names = {};
|
|
this.computedCols.forEach(function (col) {
|
|
names[col.name] = col;
|
|
});
|
|
return names
|
|
},
|
|
|
|
computedColspan: function computedColspan () {
|
|
return this.tableColspan !== void 0
|
|
? this.tableColspan
|
|
: this.computedCols.length + (this.hasSelectionMode === true ? 1 : 0)
|
|
}
|
|
}
|
|
};
|
|
|
|
var commonVirtPropsObj = {};
|
|
commonVirtPropsList.forEach(function (p) { commonVirtPropsObj[p] = {}; });
|
|
|
|
var QTable = Vue.extend({
|
|
name: 'QTable',
|
|
|
|
mixins: [
|
|
DarkMixin,
|
|
ListenersMixin,
|
|
|
|
FullscreenMixin,
|
|
Top,
|
|
TableHeader,
|
|
TableBody,
|
|
Bottom,
|
|
TableGrid,
|
|
Sort,
|
|
Filter,
|
|
Pagination,
|
|
RowSelection,
|
|
RowExpand,
|
|
ColumnSelection
|
|
],
|
|
|
|
props: Object.assign({}, {data: {
|
|
type: Array,
|
|
default: function () { return []; }
|
|
},
|
|
rowKey: {
|
|
type: [ String, Function ],
|
|
default: 'id'
|
|
},
|
|
|
|
columns: Array,
|
|
loading: Boolean,
|
|
binaryStateSort: Boolean,
|
|
|
|
iconFirstPage: String,
|
|
iconPrevPage: String,
|
|
iconNextPage: String,
|
|
iconLastPage: String,
|
|
|
|
title: String,
|
|
|
|
hideHeader: Boolean,
|
|
|
|
grid: Boolean,
|
|
gridHeader: Boolean,
|
|
|
|
dense: Boolean,
|
|
flat: Boolean,
|
|
bordered: Boolean,
|
|
square: Boolean,
|
|
separator: {
|
|
type: String,
|
|
default: 'horizontal',
|
|
validator: function (v) { return ['horizontal', 'vertical', 'cell', 'none'].includes(v); }
|
|
},
|
|
wrapCells: Boolean,
|
|
|
|
virtualScroll: Boolean},
|
|
commonVirtPropsObj,
|
|
|
|
{noDataLabel: String,
|
|
noResultsLabel: String,
|
|
loadingLabel: String,
|
|
selectedRowsLabel: Function,
|
|
rowsPerPageLabel: String,
|
|
paginationLabel: Function,
|
|
|
|
color: {
|
|
type: String,
|
|
default: 'grey-8'
|
|
},
|
|
|
|
titleClass: [String, Array, Object],
|
|
tableStyle: [String, Array, Object],
|
|
tableClass: [String, Array, Object],
|
|
tableHeaderStyle: [String, Array, Object],
|
|
tableHeaderClass: [String, Array, Object],
|
|
cardContainerClass: [String, Array, Object],
|
|
cardContainerStyle: [String, Array, Object],
|
|
cardStyle: [String, Array, Object],
|
|
cardClass: [String, Array, Object]}),
|
|
|
|
data: function data () {
|
|
return {
|
|
innerPagination: Object.assign({
|
|
sortBy: null,
|
|
descending: false,
|
|
page: 1,
|
|
rowsPerPage: this.rowsPerPageOptions.length > 0
|
|
? this.rowsPerPageOptions[0]
|
|
: 5
|
|
}, this.pagination)
|
|
}
|
|
},
|
|
|
|
watch: {
|
|
needsReset: function needsReset () {
|
|
this.hasVirtScroll === true && this.$refs.virtScroll !== void 0 && this.$refs.virtScroll.reset();
|
|
}
|
|
},
|
|
|
|
computed: {
|
|
getRowKey: function getRowKey () {
|
|
var this$1 = this;
|
|
|
|
return typeof this.rowKey === 'function'
|
|
? this.rowKey
|
|
: function (row) { return row[this$1.rowKey]; }
|
|
},
|
|
|
|
hasVirtScroll: function hasVirtScroll () {
|
|
return this.grid !== true && this.virtualScroll === true
|
|
},
|
|
|
|
needsReset: function needsReset () {
|
|
var this$1 = this;
|
|
|
|
return ['tableStyle', 'tableClass', 'tableHeaderStyle', 'tableHeaderClass', 'containerClass']
|
|
.map(function (p) { return this$1[p]; }).join(';')
|
|
},
|
|
|
|
filteredSortedRows: function filteredSortedRows () {
|
|
var rows = this.data;
|
|
|
|
if (this.isServerSide === true || rows.length === 0) {
|
|
return rows
|
|
}
|
|
|
|
var ref = this.computedPagination;
|
|
var sortBy = ref.sortBy;
|
|
var descending = ref.descending;
|
|
|
|
if (this.filter) {
|
|
rows = this.filterMethod(rows, this.filter, this.computedCols, this.getCellValue);
|
|
}
|
|
|
|
if (this.columnToSort !== void 0) {
|
|
rows = this.sortMethod(
|
|
this.data === rows ? rows.slice() : rows,
|
|
sortBy,
|
|
descending
|
|
);
|
|
}
|
|
|
|
return rows
|
|
},
|
|
|
|
filteredSortedRowsNumber: function filteredSortedRowsNumber () {
|
|
return this.filteredSortedRows.length
|
|
},
|
|
|
|
computedRows: function computedRows () {
|
|
var rows = this.filteredSortedRows;
|
|
|
|
if (this.isServerSide === true) {
|
|
return rows
|
|
}
|
|
|
|
var ref = this.computedPagination;
|
|
var rowsPerPage = ref.rowsPerPage;
|
|
|
|
if (rowsPerPage !== 0) {
|
|
if (this.firstRowIndex === 0 && this.data !== rows) {
|
|
if (rows.length > this.lastRowIndex) {
|
|
rows.length = this.lastRowIndex;
|
|
}
|
|
}
|
|
else {
|
|
rows = rows.slice(this.firstRowIndex, this.lastRowIndex);
|
|
}
|
|
}
|
|
|
|
return rows
|
|
},
|
|
|
|
computedRowsNumber: function computedRowsNumber () {
|
|
return this.isServerSide === true
|
|
? this.computedPagination.rowsNumber || 0
|
|
: this.filteredSortedRowsNumber
|
|
},
|
|
|
|
nothingToDisplay: function nothingToDisplay () {
|
|
return this.computedRows.length === 0
|
|
},
|
|
|
|
isServerSide: function isServerSide () {
|
|
return this.computedPagination.rowsNumber !== void 0
|
|
},
|
|
|
|
cardDefaultClass: function cardDefaultClass () {
|
|
return " q-table__card" +
|
|
(this.isDark === true ? ' q-table__card--dark q-dark' : '') +
|
|
(this.square === true ? " q-table--square" : '') +
|
|
(this.flat === true ? " q-table--flat" : '') +
|
|
(this.bordered === true ? " q-table--bordered" : '')
|
|
},
|
|
|
|
containerClass: function containerClass () {
|
|
return "q-table__container q-table--" + (this.separator) + "-separator column no-wrap" +
|
|
(this.loading === true ? ' q-table--loading' : '') +
|
|
(this.grid === true ? ' q-table--grid' : this.cardDefaultClass) +
|
|
(this.isDark === true ? " q-table--dark" : '') +
|
|
(this.dense === true ? " q-table--dense" : '') +
|
|
(this.wrapCells === false ? " q-table--no-wrap" : '') +
|
|
(this.inFullscreen === true ? " fullscreen scroll" : '')
|
|
},
|
|
|
|
virtProps: function virtProps () {
|
|
var this$1 = this;
|
|
|
|
var props = {};
|
|
|
|
commonVirtPropsList
|
|
.forEach(function (p) { props[p] = this$1[p]; });
|
|
|
|
if (props.virtualScrollItemSize === void 0) {
|
|
props.virtualScrollItemSize = this.dense === true ? 28 : 48;
|
|
}
|
|
|
|
return props
|
|
}
|
|
},
|
|
|
|
render: function render (h) {
|
|
var child = [ this.getTop(h) ];
|
|
var data = { staticClass: this.containerClass };
|
|
|
|
if (this.grid === true) {
|
|
child.push(this.getGridHeader(h));
|
|
}
|
|
else {
|
|
Object.assign(data, {
|
|
class: this.cardClass,
|
|
style: this.cardStyle
|
|
});
|
|
}
|
|
|
|
child.push(
|
|
this.getBody(h),
|
|
this.getBottom(h)
|
|
);
|
|
|
|
if (this.loading === true && this.$scopedSlots.loading !== void 0) {
|
|
child.push(
|
|
this.$scopedSlots.loading()
|
|
);
|
|
}
|
|
|
|
return h('div', data, child)
|
|
},
|
|
|
|
methods: {
|
|
requestServerInteraction: function requestServerInteraction (prop) {
|
|
var this$1 = this;
|
|
if ( prop === void 0 ) prop = {};
|
|
|
|
this.$nextTick(function () {
|
|
this$1.$emit('request', {
|
|
pagination: prop.pagination || this$1.computedPagination,
|
|
filter: prop.filter || this$1.filter,
|
|
getCellValue: this$1.getCellValue
|
|
});
|
|
});
|
|
},
|
|
|
|
resetVirtualScroll: function resetVirtualScroll () {
|
|
this.hasVirtScroll === true && this.$refs.virtScroll.reset();
|
|
},
|
|
|
|
getBody: function getBody (h) {
|
|
if (this.grid === true) {
|
|
return this.getGridBody(h)
|
|
}
|
|
|
|
var header = this.hideHeader !== true ? this.getTableHeader(h) : null;
|
|
|
|
return this.hasVirtScroll === true
|
|
? h(QVirtualScroll, {
|
|
ref: 'virtScroll',
|
|
props: Object.assign({}, this.virtProps,
|
|
{items: this.computedRows,
|
|
type: '__qtable',
|
|
tableColspan: this.computedColspan}),
|
|
on: cache(this, 'vs', {
|
|
'virtual-scroll': this.__onVScroll
|
|
}),
|
|
class: this.tableClass,
|
|
style: this.tableStyle,
|
|
scopedSlots: {
|
|
before: header === null
|
|
? void 0
|
|
: function () { return header; },
|
|
default: this.getTableRowVirtual(h)
|
|
}
|
|
})
|
|
: getTableMiddle(h, {
|
|
staticClass: 'scroll',
|
|
class: this.tableClass,
|
|
style: this.tableStyle
|
|
}, [
|
|
header,
|
|
this.getTableBody(h)
|
|
])
|
|
},
|
|
|
|
scrollTo: function scrollTo (toIndex) {
|
|
if (this.$refs.virtScroll !== void 0) {
|
|
this.$refs.virtScroll.scrollTo(toIndex);
|
|
return
|
|
}
|
|
|
|
toIndex = parseInt(toIndex, 10);
|
|
var rowEl = this.$el.querySelector(("tbody tr:nth-of-type(" + (toIndex + 1) + ")"));
|
|
|
|
if (rowEl !== null) {
|
|
var scrollTarget = this.$el.querySelector('.q-table__middle.scroll');
|
|
var offsetTop = rowEl.offsetTop;
|
|
var direction = offsetTop < scrollTarget.scrollTop ? 'decrease' : 'increase';
|
|
|
|
scrollTarget.scrollTop = offsetTop;
|
|
|
|
this.$emit('virtual-scroll', {
|
|
index: toIndex,
|
|
from: 0,
|
|
to: this.pagination.rowsPerPage - 1,
|
|
direction: direction
|
|
});
|
|
}
|
|
},
|
|
|
|
__onVScroll: function __onVScroll (info) {
|
|
this.$emit('virtual-scroll', info);
|
|
},
|
|
|
|
__getProgress: function __getProgress (h) {
|
|
return [
|
|
h(QLinearProgress, {
|
|
staticClass: 'q-table__linear-progress',
|
|
props: {
|
|
color: this.color,
|
|
dark: this.isDark,
|
|
indeterminate: true,
|
|
trackColor: 'transparent'
|
|
}
|
|
})
|
|
]
|
|
}
|
|
}
|
|
});
|
|
|
|
var QTr = Vue.extend({
|
|
name: 'QTr',
|
|
|
|
mixins: [ ListenersMixin ],
|
|
|
|
props: {
|
|
props: Object,
|
|
noHover: Boolean
|
|
},
|
|
|
|
computed: {
|
|
classes: function classes () {
|
|
return 'q-tr' + (this.props === void 0 || this.props.header === true ? '' : ' ' + this.props.__trClass) +
|
|
(this.noHover === true ? ' q-tr--no-hover' : '')
|
|
}
|
|
},
|
|
|
|
render: function render (h) {
|
|
return h('tr', {
|
|
on: Object.assign({}, this.qListeners),
|
|
class: this.classes
|
|
}, slot(this, 'default'))
|
|
}
|
|
});
|
|
|
|
var QTd = Vue.extend({
|
|
name: 'QTd',
|
|
|
|
mixins: [ ListenersMixin ],
|
|
|
|
props: {
|
|
props: Object,
|
|
autoWidth: Boolean,
|
|
noHover: Boolean
|
|
},
|
|
|
|
computed: {
|
|
classes: function classes () {
|
|
return 'q-td' + (this.autoWidth === true ? ' q-table--col-auto-width' : '') +
|
|
(this.noHover === true ? ' q-td--no-hover' : '')
|
|
}
|
|
},
|
|
|
|
render: function render (h) {
|
|
var on = this.qListeners;
|
|
|
|
if (this.props === void 0) {
|
|
return h('td', {
|
|
on: on,
|
|
class: this.classes
|
|
}, slot(this, 'default'))
|
|
}
|
|
|
|
var name = this.$vnode.key;
|
|
|
|
var col = this.props.colsMap !== void 0 && name
|
|
? this.props.colsMap[name]
|
|
: this.props.col;
|
|
|
|
if (col === void 0) { return }
|
|
|
|
return h('td', {
|
|
on: on,
|
|
style: col.style,
|
|
class: this.classes + ' ' + col.__tdClass
|
|
}, slot(this, 'default'))
|
|
}
|
|
});
|
|
|
|
var trailingSlashRE = /\/?$/;
|
|
|
|
function queryIncludes (current, target) {
|
|
for (var key in target) {
|
|
if (!(key in current)) {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
function isSameRoute (current, target) {
|
|
if (!target) {
|
|
return false
|
|
}
|
|
if (current.path && target.path) {
|
|
return (
|
|
current.path.replace(trailingSlashRE, '') === target.path.replace(trailingSlashRE, '') &&
|
|
current.hash === target.hash &&
|
|
isDeepEqual(current.query, target.query)
|
|
)
|
|
}
|
|
if (current.name && target.name) {
|
|
return (
|
|
current.name === target.name &&
|
|
current.hash === target.hash &&
|
|
isDeepEqual(current.query, target.query) &&
|
|
isDeepEqual(current.params, target.params)
|
|
)
|
|
}
|
|
return false
|
|
}
|
|
|
|
function isIncludedRoute (current, target) {
|
|
return (
|
|
current.path.replace(trailingSlashRE, '/').indexOf(target.path.replace(trailingSlashRE, '/')) === 0 &&
|
|
(!target.hash || current.hash === target.hash) &&
|
|
queryIncludes(current.query, target.query)
|
|
)
|
|
}
|
|
|
|
var QRouteTab = Vue.extend({
|
|
name: 'QRouteTab',
|
|
|
|
mixins: [ QTab, RouterLinkMixin ],
|
|
|
|
props: {
|
|
to: { required: true }
|
|
},
|
|
|
|
inject: {
|
|
__activateRoute: {},
|
|
__recalculateScroll: {}
|
|
},
|
|
|
|
watch: {
|
|
$route: function $route () {
|
|
this.__checkActivation();
|
|
}
|
|
},
|
|
|
|
computed: {
|
|
onEvents: function onEvents () {
|
|
return Object.assign({}, {input: stop},
|
|
this.qListeners,
|
|
{'!click': this.__activate, // we need capture to intercept before vue-router
|
|
keyup: this.__onKeyup})
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
__activate: function __activate (e, keyboard) {
|
|
var this$1 = this;
|
|
|
|
if (this.disable !== true) {
|
|
if (
|
|
e !== void 0 && (
|
|
e.ctrlKey === true ||
|
|
e.shiftKey === true ||
|
|
e.altKey === true ||
|
|
e.metaKey === true
|
|
)
|
|
) {
|
|
// if it has meta keys, let vue-router link
|
|
// handle this by its own
|
|
this.__checkActivation(true);
|
|
}
|
|
else {
|
|
// we use programatic navigation instead of letting vue-router handle it
|
|
// so we can check for activation when the navigation is complete
|
|
e !== void 0 && stopAndPrevent(e);
|
|
|
|
var go = function (to, append, replace) {
|
|
if ( to === void 0 ) to = this$1.to;
|
|
if ( append === void 0 ) append = this$1.append;
|
|
if ( replace === void 0 ) replace = this$1.replace;
|
|
|
|
var ref = this$1.$router.resolve(to, this$1.$route, append);
|
|
var route = ref.route;
|
|
var checkFn = to === this$1.to && append === this$1.append && replace === this$1.replace
|
|
? this$1.__checkActivation
|
|
: noop;
|
|
|
|
// vue-router now throwing error if navigating
|
|
// to the same route that the user is currently at
|
|
// https://github.com/vuejs/vue-router/issues/2872
|
|
this$1.$router[replace === true ? 'replace' : 'push'](
|
|
route,
|
|
function () { checkFn(true); },
|
|
function (err) {
|
|
if (err && err.name === 'NavigationDuplicated') {
|
|
checkFn(true);
|
|
}
|
|
}
|
|
);
|
|
};
|
|
|
|
this.qListeners.click !== void 0 && this.$emit('click', e, go);
|
|
e.navigate !== false && go();
|
|
}
|
|
}
|
|
|
|
if (keyboard === true) {
|
|
this.$el.focus(e);
|
|
}
|
|
else {
|
|
this.$refs.blurTarget !== void 0 && this.$refs.blurTarget.focus(e);
|
|
}
|
|
},
|
|
|
|
__checkActivation: function __checkActivation (selected) {
|
|
if ( selected === void 0 ) selected = false;
|
|
|
|
var
|
|
current = this.$route;
|
|
var ref = this.$router.resolve(this.to, current, this.append);
|
|
var href = ref.href;
|
|
var location = ref.location;
|
|
var route = ref.route;
|
|
var redirected = route.redirectedFrom !== void 0,
|
|
isSameRouteCheck = isSameRoute(current, route),
|
|
checkFunction = this.exact === true ? isSameRoute : isIncludedRoute,
|
|
params = {
|
|
name: this.name,
|
|
selected: selected,
|
|
exact: this.exact,
|
|
priorityMatched: route.matched.length,
|
|
priorityHref: href.length
|
|
};
|
|
|
|
if (isSameRouteCheck === true || (this.exact !== true && isIncludedRoute(current, route) === true)) {
|
|
this.__activateRoute(Object.assign({}, params,
|
|
{redirected: redirected,
|
|
// if it's an exact match give higher priority
|
|
// even if the tab is not marked as exact
|
|
exact: this.exact === true || isSameRouteCheck === true}));
|
|
}
|
|
|
|
if (
|
|
redirected === true &&
|
|
checkFunction(current, Object.assign({}, {path: route.redirectedFrom},
|
|
location)) === true
|
|
) {
|
|
this.__activateRoute(params);
|
|
}
|
|
|
|
this.isActive === true && this.__activateRoute();
|
|
}
|
|
},
|
|
|
|
mounted: function mounted () {
|
|
this.__recalculateScroll();
|
|
this.$router !== void 0 && this.__checkActivation();
|
|
},
|
|
|
|
beforeDestroy: function beforeDestroy () {
|
|
this.__recalculateScroll();
|
|
this.__activateRoute({ remove: true, name: this.name });
|
|
},
|
|
|
|
render: function render (h) {
|
|
return this.__renderTab(h, 'router-link', this.routerLinkProps)
|
|
}
|
|
});
|
|
|
|
var QTime = Vue.extend({
|
|
name: 'QTime',
|
|
|
|
mixins: [ DateTimeMixin ],
|
|
|
|
directives: {
|
|
TouchPan: TouchPan
|
|
},
|
|
|
|
props: {
|
|
mask: {
|
|
default: null
|
|
},
|
|
|
|
format24h: {
|
|
type: Boolean,
|
|
default: null
|
|
},
|
|
|
|
defaultDate: {
|
|
type: String,
|
|
validator: function (v) { return /^-?[\d]+\/[0-1]\d\/[0-3]\d$/.test(v); }
|
|
},
|
|
|
|
options: Function,
|
|
hourOptions: Array,
|
|
minuteOptions: Array,
|
|
secondOptions: Array,
|
|
|
|
withSeconds: Boolean,
|
|
nowBtn: Boolean
|
|
},
|
|
|
|
data: function data () {
|
|
var model = __splitDate(
|
|
this.value,
|
|
this.__getMask(),
|
|
this.__getLocale(),
|
|
this.calendar,
|
|
this.__getDefaultDateModel()
|
|
);
|
|
|
|
var view = 'Hour';
|
|
|
|
if (model.hour !== null) {
|
|
if (model.minute === null) {
|
|
view = 'Minute';
|
|
}
|
|
else if (this.withSeconds === true && model.second === null) {
|
|
view = 'Second';
|
|
}
|
|
}
|
|
|
|
return {
|
|
view: view,
|
|
isAM: model.hour === null || model.hour < 12,
|
|
innerModel: model
|
|
}
|
|
},
|
|
|
|
watch: {
|
|
value: function value (v) {
|
|
var model = __splitDate(
|
|
v,
|
|
this.computedMask,
|
|
this.computedLocale,
|
|
this.calendar,
|
|
this.defaultDateModel
|
|
);
|
|
|
|
if (
|
|
model.dateHash !== this.innerModel.dateHash ||
|
|
model.timeHash !== this.innerModel.timeHash
|
|
) {
|
|
this.innerModel = model;
|
|
|
|
if (model.hour === null) {
|
|
this.view = 'Hour';
|
|
}
|
|
else {
|
|
this.isAM = model.hour < 12;
|
|
}
|
|
}
|
|
},
|
|
|
|
computedMask: function computedMask () {
|
|
var this$1 = this;
|
|
|
|
this.$nextTick(function () {
|
|
this$1.__updateValue();
|
|
});
|
|
},
|
|
|
|
computedLocale: function computedLocale () {
|
|
var this$1 = this;
|
|
|
|
this.$nextTick(function () {
|
|
this$1.__updateValue();
|
|
});
|
|
}
|
|
},
|
|
|
|
computed: {
|
|
classes: function classes () {
|
|
return "q-time q-time--" + (this.landscape === true ? 'landscape' : 'portrait') +
|
|
(this.isDark === true ? ' q-time--dark q-dark' : '') +
|
|
(this.disable === true ? ' disabled' : (this.readonly === true ? ' q-time--readonly' : '')) +
|
|
(this.bordered === true ? " q-time--bordered" : '') +
|
|
(this.square === true ? " q-time--square no-border-radius" : '') +
|
|
(this.flat === true ? " q-time--flat no-shadow" : '')
|
|
},
|
|
|
|
stringModel: function stringModel () {
|
|
var time = this.innerModel;
|
|
|
|
return {
|
|
hour: time.hour === null
|
|
? '--'
|
|
: (
|
|
this.computedFormat24h === true
|
|
? pad(time.hour)
|
|
: String(
|
|
this.isAM === true
|
|
? (time.hour === 0 ? 12 : time.hour)
|
|
: (time.hour > 12 ? time.hour - 12 : time.hour)
|
|
)
|
|
),
|
|
minute: time.minute === null
|
|
? '--'
|
|
: pad(time.minute),
|
|
second: time.second === null
|
|
? '--'
|
|
: pad(time.second)
|
|
}
|
|
},
|
|
|
|
defaultDateModel: function defaultDateModel () {
|
|
return this.__getDefaultDateModel()
|
|
},
|
|
|
|
computedFormat24h: function computedFormat24h () {
|
|
return this.format24h !== null
|
|
? this.format24h
|
|
: this.$q.lang.date.format24h
|
|
},
|
|
|
|
pointerStyle: function pointerStyle () {
|
|
var
|
|
forHour = this.view === 'Hour',
|
|
divider = forHour === true ? 12 : 60,
|
|
amount = this.innerModel[this.view.toLowerCase()],
|
|
degrees = Math.round(amount * (360 / divider)) - 180;
|
|
|
|
var transform = "rotate(" + degrees + "deg) translateX(-50%)";
|
|
|
|
if (
|
|
forHour === true &&
|
|
this.computedFormat24h === true &&
|
|
this.innerModel.hour >= 12
|
|
) {
|
|
transform += ' scale(.7)';
|
|
}
|
|
|
|
return { transform: transform }
|
|
},
|
|
|
|
minLink: function minLink () {
|
|
return this.innerModel.hour !== null
|
|
},
|
|
|
|
secLink: function secLink () {
|
|
return this.minLink === true && this.innerModel.minute !== null
|
|
},
|
|
|
|
hourInSelection: function hourInSelection () {
|
|
var this$1 = this;
|
|
|
|
return this.hourOptions !== void 0
|
|
? function (val) { return this$1.hourOptions.includes(val); }
|
|
: (
|
|
this.options !== void 0
|
|
? function (val) { return this$1.options(val, null, null); }
|
|
: void 0
|
|
)
|
|
},
|
|
|
|
minuteInSelection: function minuteInSelection () {
|
|
var this$1 = this;
|
|
|
|
return this.minuteOptions !== void 0
|
|
? function (val) { return this$1.minuteOptions.includes(val); }
|
|
: (
|
|
this.options !== void 0
|
|
? function (val) { return this$1.options(this$1.innerModel.hour, val, null); }
|
|
: void 0
|
|
)
|
|
},
|
|
|
|
secondInSelection: function secondInSelection () {
|
|
var this$1 = this;
|
|
|
|
return this.secondOptions !== void 0
|
|
? function (val) { return this$1.secondOptions.includes(val); }
|
|
: (
|
|
this.options !== void 0
|
|
? function (val) { return this$1.options(this$1.innerModel.hour, this$1.innerModel.minute, val); }
|
|
: void 0
|
|
)
|
|
},
|
|
|
|
hourSnappingGrid: function hourSnappingGrid () {
|
|
return this.__getSnapGrid(this.hourInSelection, 24)
|
|
},
|
|
|
|
minuteSnappingGrid: function minuteSnappingGrid () {
|
|
return this.__getSnapGrid(this.minuteInSelection, 60)
|
|
},
|
|
|
|
secondSnappingGrid: function secondSnappingGrid () {
|
|
return this.__getSnapGrid(this.secondInSelection, 60)
|
|
},
|
|
|
|
positions: function positions () {
|
|
var start, end, offset = 0, step = 1, inSel;
|
|
|
|
if (this.view === 'Hour') {
|
|
inSel = this.hourInSelection;
|
|
|
|
if (this.computedFormat24h === true) {
|
|
start = 0;
|
|
end = 23;
|
|
}
|
|
else {
|
|
start = 0;
|
|
end = 11;
|
|
|
|
if (this.isAM === false) {
|
|
offset = 12;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
start = 0;
|
|
end = 55;
|
|
step = 5;
|
|
|
|
if (this.view === 'Minute') {
|
|
inSel = this.minuteInSelection;
|
|
}
|
|
else {
|
|
inSel = this.secondInSelection;
|
|
}
|
|
}
|
|
|
|
var pos = [];
|
|
|
|
for (var val = start, index = start; val <= end; val += step, index++) {
|
|
var
|
|
actualVal = val + offset,
|
|
disable = inSel !== void 0 && inSel(actualVal) === false,
|
|
label = this.view === 'Hour' && val === 0
|
|
? (this.format24h === true ? '00' : '12')
|
|
: val;
|
|
|
|
pos.push({ val: actualVal, index: index, disable: disable, label: label });
|
|
}
|
|
|
|
return pos
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
setNow: function setNow () {
|
|
this.__updateValue(Object.assign({}, this.__getCurrentDate(),
|
|
this.__getCurrentTime()));
|
|
this.view = 'Hour';
|
|
},
|
|
|
|
__getSnapGrid: function __getSnapGrid (inSel, count) {
|
|
if (inSel === void 0) {
|
|
return
|
|
}
|
|
|
|
var snappingGrid = [].concat( Array(count).keys() ).map(inSel);
|
|
|
|
var consecutiveGaps = (count - 1) - snappingGrid.lastIndexOf(true);
|
|
if (consecutiveGaps === -1) {
|
|
return
|
|
}
|
|
|
|
for (var i = 0; i < count; i++) {
|
|
if (snappingGrid[i] === true) {
|
|
if (consecutiveGaps) {
|
|
if (consecutiveGaps > 1) {
|
|
var sideCount = Math.floor(consecutiveGaps / 2);
|
|
|
|
var previousVal = ((i - consecutiveGaps - 1) + count) % count;
|
|
var previousValStart = ((i - consecutiveGaps) + count) % count;
|
|
for (var j = 0, h = previousValStart; j < sideCount; j++, (h = (previousValStart + j + count) % count)) {
|
|
snappingGrid[h] = previousVal;
|
|
}
|
|
|
|
var currentVal = i;
|
|
var currentValStart = ((i - sideCount) + count) % count;
|
|
for (var j$1 = 0, h$1 = currentValStart; j$1 < sideCount; j$1++, (h$1 = (currentValStart + j$1 + count) % count)) {
|
|
snappingGrid[h$1] = currentVal;
|
|
}
|
|
} else {
|
|
var previousPosition = ((i - 1) + count) % count;
|
|
snappingGrid[previousPosition] = previousPosition;
|
|
}
|
|
|
|
consecutiveGaps = 0;
|
|
}
|
|
|
|
snappingGrid[i] = i;
|
|
}
|
|
else if (snappingGrid[i] === false) {
|
|
consecutiveGaps++;
|
|
}
|
|
}
|
|
|
|
return snappingGrid
|
|
},
|
|
|
|
__getMask: function __getMask () {
|
|
return this.calendar !== 'persian' && this.mask !== null
|
|
? this.mask
|
|
: ("HH:mm" + (this.withSeconds === true ? ':ss' : ''))
|
|
},
|
|
|
|
__getDefaultDateModel: function __getDefaultDateModel () {
|
|
if (typeof this.defaultDate !== 'string') {
|
|
var date = this.__getCurrentDate();
|
|
date.dateHash = date.year + '/' + pad(date.month) + '/' + pad(date.day);
|
|
return date
|
|
}
|
|
|
|
return __splitDate(this.defaultDate, 'YYYY/MM/DD', void 0, this.calendar)
|
|
},
|
|
|
|
__click: function __click (evt) {
|
|
if (this._isBeingDestroyed === true || this._isDestroyed === true) {
|
|
return
|
|
}
|
|
|
|
// __activate() has already updated the offset
|
|
// (on desktop only, through mousedown event)
|
|
if (this.$q.platform.is.desktop !== true) {
|
|
this.__updateClock(evt, this.__getClockRect());
|
|
}
|
|
|
|
this.__goToNextView();
|
|
},
|
|
|
|
__activate: function __activate (evt) {
|
|
if (this._isBeingDestroyed !== true && this._isDestroyed !== true) {
|
|
this.__updateClock(evt, this.__getClockRect());
|
|
}
|
|
},
|
|
|
|
__getClockRect: function __getClockRect () {
|
|
var
|
|
clock = this.$refs.clock;
|
|
var ref = clock.getBoundingClientRect();
|
|
var top = ref.top;
|
|
var left = ref.left;
|
|
var width = ref.width;
|
|
var dist = width / 2;
|
|
|
|
return {
|
|
top: top + dist,
|
|
left: left + dist,
|
|
dist: dist * 0.7
|
|
}
|
|
},
|
|
|
|
__goToNextView: function __goToNextView () {
|
|
if (this.view === 'Hour') {
|
|
this.view = 'Minute';
|
|
}
|
|
else if (this.withSeconds && this.view === 'Minute') {
|
|
this.view = 'Second';
|
|
}
|
|
},
|
|
|
|
__drag: function __drag (event) {
|
|
// cases when on a popup getting closed
|
|
// on previously emitted value
|
|
if (this._isBeingDestroyed === true || this._isDestroyed === true) {
|
|
return
|
|
}
|
|
|
|
if (event.isFirst === true) {
|
|
this.draggingClockRect = this.__getClockRect();
|
|
this.dragCache = this.__updateClock(event.evt, this.draggingClockRect);
|
|
return
|
|
}
|
|
|
|
this.dragCache = this.__updateClock(event.evt, this.draggingClockRect, this.dragCache);
|
|
|
|
if (event.isFinal === true) {
|
|
this.draggingClockRect = false;
|
|
this.dragCache = null;
|
|
this.__goToNextView();
|
|
}
|
|
},
|
|
|
|
__updateClock: function __updateClock (evt, clockRect, cacheVal) {
|
|
var
|
|
pos = position(evt),
|
|
height = Math.abs(pos.top - clockRect.top),
|
|
distance = Math.sqrt(
|
|
Math.pow(Math.abs(pos.top - clockRect.top), 2) +
|
|
Math.pow(Math.abs(pos.left - clockRect.left), 2)
|
|
);
|
|
var
|
|
val,
|
|
angle = Math.asin(height / distance) * (180 / Math.PI);
|
|
|
|
if (pos.top < clockRect.top) {
|
|
angle = clockRect.left < pos.left ? 90 - angle : 270 + angle;
|
|
}
|
|
else {
|
|
angle = clockRect.left < pos.left ? angle + 90 : 270 - angle;
|
|
}
|
|
|
|
if (this.view === 'Hour') {
|
|
val = Math.round(angle / 30);
|
|
|
|
if (this.computedFormat24h === true) {
|
|
if (distance < clockRect.dist) {
|
|
if (val < 12) {
|
|
val += 12;
|
|
}
|
|
}
|
|
else if (val === 12) {
|
|
val = 0;
|
|
}
|
|
this.isAM = val < 12;
|
|
}
|
|
else if (this.isAM === true && val === 12) {
|
|
val = 0;
|
|
}
|
|
else if (this.isAM === false && val !== 12) {
|
|
val += 12;
|
|
}
|
|
|
|
if (this.hourSnappingGrid !== void 0) {
|
|
val = this.hourSnappingGrid[val];
|
|
}
|
|
}
|
|
else {
|
|
val = Math.round(angle / 6) % 60;
|
|
|
|
if (this.view === 'Minute' && this.minuteSnappingGrid !== void 0) {
|
|
val = this.minuteSnappingGrid[val];
|
|
}
|
|
else if (this.view === 'Second' && this.secondSnappingGrid !== void 0) {
|
|
val = this.secondSnappingGrid[val];
|
|
}
|
|
}
|
|
|
|
if (cacheVal === val) {
|
|
return val
|
|
}
|
|
|
|
var opt = this[((this.view.toLowerCase()) + "InSelection")];
|
|
|
|
if (opt !== void 0 && opt(val) !== true) {
|
|
return
|
|
}
|
|
|
|
this[("__set" + (this.view))](val);
|
|
return val
|
|
},
|
|
|
|
__onKeyupHour: function __onKeyupHour (e) {
|
|
if (e.keyCode === 13) { // ENTER
|
|
this.view = 'Hour';
|
|
}
|
|
else {
|
|
var
|
|
wrap = this.computedFormat24h === true ? 24 : 12,
|
|
offset = this.computedFormat24h !== true && this.isAM === false ? 12 : 0;
|
|
|
|
if (e.keyCode === 37) { // ARROW LEFT
|
|
this.__setHour(offset + (24 + this.innerModel.hour - 1) % wrap);
|
|
}
|
|
else if (e.keyCode === 39) { // ARROW RIGHT
|
|
this.__setHour(offset + (24 + this.innerModel.hour + 1) % wrap);
|
|
}
|
|
}
|
|
},
|
|
|
|
__onKeyupMinute: function __onKeyupMinute (e) {
|
|
if (e.keyCode === 13) { // ENTER
|
|
this.view = 'Minute';
|
|
}
|
|
else if (e.keyCode === 37) { // ARROW LEFT
|
|
this.__setMinute((60 + this.innerModel.minute - 1) % 60);
|
|
}
|
|
else if (e.keyCode === 39) { // ARROW RIGHT
|
|
this.__setMinute((60 + this.innerModel.minute + 1) % 60);
|
|
}
|
|
},
|
|
|
|
__onKeyupSecond: function __onKeyupSecond (e) {
|
|
if (e.keyCode === 13) { // ENTER
|
|
this.view = 'Second';
|
|
}
|
|
else if (e.keyCode === 37) { // ARROW LEFT
|
|
this.__setSecond((60 + this.innerModel.second - 1) % 60);
|
|
}
|
|
else if (e.keyCode === 39) { // ARROW RIGHT
|
|
this.__setSecond((60 + this.innerModel.second + 1) % 60);
|
|
}
|
|
},
|
|
|
|
__getHeader: function __getHeader (h) {
|
|
var this$1 = this;
|
|
|
|
var label = [
|
|
h('div', {
|
|
staticClass: 'q-time__link',
|
|
class: this.view === 'Hour' ? 'q-time__link--active' : 'cursor-pointer',
|
|
attrs: { tabindex: this.computedTabindex },
|
|
on: cache(this, 'vH', {
|
|
click: function () { this$1.view = 'Hour'; },
|
|
keyup: this.__onKeyupHour
|
|
})
|
|
}, [ this.stringModel.hour ]),
|
|
|
|
h('div', [ ':' ]),
|
|
|
|
h(
|
|
'div',
|
|
this.minLink === true
|
|
? {
|
|
staticClass: 'q-time__link',
|
|
class: this.view === 'Minute' ? 'q-time__link--active' : 'cursor-pointer',
|
|
attrs: { tabindex: this.computedTabindex },
|
|
on: cache(this, 'vM', {
|
|
click: function () { this$1.view = 'Minute'; },
|
|
keyup: this.__onKeyupMinute
|
|
})
|
|
}
|
|
: { staticClass: 'q-time__link' },
|
|
[ this.stringModel.minute ]
|
|
)
|
|
];
|
|
|
|
if (this.withSeconds === true) {
|
|
label.push(
|
|
h('div', [ ':' ]),
|
|
|
|
h(
|
|
'div',
|
|
this.secLink === true
|
|
? {
|
|
staticClass: 'q-time__link',
|
|
class: this.view === 'Second' ? 'q-time__link--active' : 'cursor-pointer',
|
|
attrs: { tabindex: this.computedTabindex },
|
|
on: cache(this, 'vS', {
|
|
click: function () { this$1.view = 'Second'; },
|
|
keyup: this.__onKeyupSecond
|
|
})
|
|
}
|
|
: { staticClass: 'q-time__link' },
|
|
[ this.stringModel.second ]
|
|
)
|
|
);
|
|
}
|
|
|
|
return h('div', {
|
|
staticClass: 'q-time__header flex flex-center no-wrap',
|
|
class: this.headerClass
|
|
}, [
|
|
h('div', {
|
|
staticClass: 'q-time__header-label row items-center no-wrap',
|
|
attrs: { dir: 'ltr' }
|
|
}, label),
|
|
|
|
this.computedFormat24h === false ? h('div', {
|
|
staticClass: 'q-time__header-ampm column items-between no-wrap'
|
|
}, [
|
|
h('div', {
|
|
staticClass: 'q-time__link',
|
|
class: this.isAM === true ? 'q-time__link--active' : 'cursor-pointer',
|
|
attrs: { tabindex: this.computedTabindex },
|
|
on: cache(this, 'AM', {
|
|
click: this.__setAm,
|
|
keyup: function (e) { e.keyCode === 13 && this$1.__setAm(); }
|
|
})
|
|
}, [ 'AM' ]),
|
|
|
|
h('div', {
|
|
staticClass: 'q-time__link',
|
|
class: this.isAM !== true ? 'q-time__link--active' : 'cursor-pointer',
|
|
attrs: { tabindex: this.computedTabindex },
|
|
on: cache(this, 'PM', {
|
|
click: this.__setPm,
|
|
keyup: function (e) { e.keyCode === 13 && this$1.__setPm(); }
|
|
})
|
|
}, [ 'PM' ])
|
|
]) : null
|
|
])
|
|
},
|
|
|
|
__getClock: function __getClock (h) {
|
|
var this$1 = this;
|
|
|
|
var
|
|
view = this.view.toLowerCase(),
|
|
current = this.innerModel[view];
|
|
|
|
return h('div', {
|
|
staticClass: 'q-time__content col relative-position'
|
|
}, [
|
|
h('transition', {
|
|
props: { name: 'q-transition--scale' }
|
|
}, [
|
|
h('div', {
|
|
key: 'clock' + this.view,
|
|
staticClass: 'q-time__container-parent absolute-full'
|
|
}, [
|
|
h('div', {
|
|
ref: 'clock',
|
|
staticClass: 'q-time__container-child fit overflow-hidden'
|
|
}, [
|
|
h('div', {
|
|
staticClass: 'q-time__clock cursor-pointer non-selectable',
|
|
on: cache(this, 'click', {
|
|
click: this.__click,
|
|
mousedown: this.__activate
|
|
}),
|
|
directives: cache(this, 'touch', [{
|
|
name: 'touch-pan',
|
|
value: this.__drag,
|
|
modifiers: {
|
|
stop: true,
|
|
prevent: true,
|
|
mouse: true
|
|
}
|
|
}])
|
|
}, [
|
|
h('div', { staticClass: 'q-time__clock-circle fit' }, [
|
|
h('div', {
|
|
staticClass: 'q-time__clock-pointer',
|
|
style: this.pointerStyle,
|
|
class: this.innerModel[view] === null ? 'hidden' : (this.color !== void 0 ? ("text-" + (this.color)) : '')
|
|
}),
|
|
|
|
this.positions.map(function (pos) { return h('div', {
|
|
staticClass: ("q-time__clock-position row flex-center q-time__clock-pos-" + (pos.index)),
|
|
class: pos.val === current
|
|
? this$1.headerClass.concat(' q-time__clock-position--active')
|
|
: (pos.disable === true ? 'q-time__clock-position--disable' : null)
|
|
}, [ h('span', [ pos.label ]) ]); })
|
|
])
|
|
])
|
|
])
|
|
])
|
|
]),
|
|
|
|
this.nowBtn === true ? h(QBtn, {
|
|
staticClass: 'q-time__now-button absolute',
|
|
props: {
|
|
icon: this.$q.iconSet.datetime.now,
|
|
unelevated: true,
|
|
size: 'sm',
|
|
round: true,
|
|
color: this.color,
|
|
textColor: this.textColor,
|
|
tabindex: this.computedTabindex
|
|
},
|
|
on: cache(this, 'now', {
|
|
click: this.setNow
|
|
})
|
|
}) : null
|
|
])
|
|
},
|
|
|
|
__setHour: function __setHour (hour) {
|
|
if (this.innerModel.hour !== hour) {
|
|
this.innerModel.hour = hour;
|
|
this.innerModel.minute = null;
|
|
this.innerModel.second = null;
|
|
}
|
|
},
|
|
|
|
__setMinute: function __setMinute (minute) {
|
|
if (this.innerModel.minute !== minute) {
|
|
this.innerModel.minute = minute;
|
|
this.innerModel.second = null;
|
|
this.withSeconds !== true && this.__updateValue({ minute: minute });
|
|
}
|
|
},
|
|
|
|
__setSecond: function __setSecond (second) {
|
|
this.innerModel.second !== second && this.__updateValue({ second: second });
|
|
},
|
|
|
|
__setAm: function __setAm () {
|
|
if (this.isAM) { return }
|
|
|
|
this.isAM = true;
|
|
|
|
if (this.innerModel.hour === null) { return }
|
|
this.innerModel.hour -= 12;
|
|
this.__verifyAndUpdate();
|
|
},
|
|
|
|
__setPm: function __setPm () {
|
|
if (!this.isAM) { return }
|
|
|
|
this.isAM = false;
|
|
|
|
if (this.innerModel.hour === null) { return }
|
|
this.innerModel.hour += 12;
|
|
this.__verifyAndUpdate();
|
|
},
|
|
|
|
__verifyAndUpdate: function __verifyAndUpdate () {
|
|
if (this.hourInSelection !== void 0 && this.hourInSelection(this.innerModel.hour) !== true) {
|
|
this.innerModel = __splitDate();
|
|
this.isAM = true;
|
|
this.view = 'Hour';
|
|
return
|
|
}
|
|
|
|
if (this.minuteInSelection !== void 0 && this.minuteInSelection(this.innerModel.minute) !== true) {
|
|
this.innerModel.minute = null;
|
|
this.innerModel.second = null;
|
|
this.view = 'Minute';
|
|
return
|
|
}
|
|
|
|
if (this.withSeconds === true && this.secondInSelection !== void 0 && this.secondInSelection(this.innerModel.second) !== true) {
|
|
this.innerModel.second = null;
|
|
this.view = 'Second';
|
|
return
|
|
}
|
|
|
|
if (this.innerModel.hour === null || this.innerModel.minute === null || (this.withSeconds === true && this.innerModel.second === null)) {
|
|
return
|
|
}
|
|
|
|
this.__updateValue();
|
|
},
|
|
|
|
__updateValue: function __updateValue (obj) {
|
|
var date = Object.assign(Object.assign({}, this.innerModel), obj);
|
|
|
|
var val = this.calendar === 'persian'
|
|
? pad(date.hour) + ':' +
|
|
pad(date.minute) +
|
|
(this.withSeconds === true ? ':' + pad(date.second) : '')
|
|
: formatDate(
|
|
new Date(
|
|
date.year,
|
|
date.month === null ? null : date.month - 1,
|
|
date.day,
|
|
date.hour,
|
|
date.minute,
|
|
date.second,
|
|
date.millisecond
|
|
),
|
|
this.computedMask,
|
|
this.computedLocale,
|
|
date.year,
|
|
date.timezoneOffset
|
|
);
|
|
|
|
date.changed = val !== this.value;
|
|
this.$emit('input', val, date);
|
|
}
|
|
},
|
|
|
|
render: function render (h) {
|
|
var child = [
|
|
this.__getClock(h)
|
|
];
|
|
|
|
var def = slot(this, 'default');
|
|
def !== void 0 && child.push(
|
|
h('div', { staticClass: 'q-time__actions' }, def)
|
|
);
|
|
|
|
if (this.name !== void 0 && this.disable !== true) {
|
|
this.__injectFormInput(child, 'push');
|
|
}
|
|
|
|
return h('div', {
|
|
class: this.classes,
|
|
on: Object.assign({}, this.qListeners),
|
|
attrs: { tabindex: -1 }
|
|
}, [
|
|
this.__getHeader(h),
|
|
h('div', { staticClass: 'q-time__main col overflow-auto' }, child)
|
|
])
|
|
}
|
|
});
|
|
|
|
var QTimeline = Vue.extend({
|
|
name: 'QTimeline',
|
|
|
|
mixins: [ DarkMixin, ListenersMixin ],
|
|
|
|
provide: function provide () {
|
|
return {
|
|
__timeline: this
|
|
}
|
|
},
|
|
|
|
props: {
|
|
color: {
|
|
type: String,
|
|
default: 'primary'
|
|
},
|
|
side: {
|
|
type: String,
|
|
default: 'right',
|
|
validator: function (v) { return ['left', 'right'].includes(v); }
|
|
},
|
|
layout: {
|
|
type: String,
|
|
default: 'dense',
|
|
validator: function (v) { return ['dense', 'comfortable', 'loose'].includes(v); }
|
|
}
|
|
},
|
|
|
|
computed: {
|
|
classes: function classes () {
|
|
return "q-timeline--" + (this.layout) + " q-timeline--" + (this.layout) + "--" + (this.side) +
|
|
(this.isDark === true ? ' q-timeline--dark' : '')
|
|
}
|
|
},
|
|
|
|
render: function render (h) {
|
|
return h('ul', {
|
|
staticClass: 'q-timeline',
|
|
class: this.classes,
|
|
on: Object.assign({}, this.qListeners)
|
|
}, slot(this, 'default'))
|
|
}
|
|
});
|
|
|
|
var QTimelineEntry = Vue.extend({
|
|
name: 'QTimelineEntry',
|
|
|
|
inject: {
|
|
__timeline: {
|
|
default: function default$1 () {
|
|
console.error('QTimelineEntry needs to be child of QTimeline');
|
|
}
|
|
}
|
|
},
|
|
|
|
mixins: [ ListenersMixin ],
|
|
|
|
props: {
|
|
heading: Boolean,
|
|
tag: {
|
|
type: String,
|
|
default: 'h3'
|
|
},
|
|
side: {
|
|
type: String,
|
|
default: 'right',
|
|
validator: function (v) { return ['left', 'right'].includes(v); }
|
|
},
|
|
|
|
icon: String,
|
|
avatar: String,
|
|
|
|
color: String,
|
|
|
|
title: String,
|
|
subtitle: String,
|
|
body: String
|
|
},
|
|
|
|
computed: {
|
|
colorClass: function colorClass () {
|
|
return ("text-" + (this.color || this.__timeline.color))
|
|
},
|
|
|
|
classes: function classes () {
|
|
return "q-timeline__entry--" + (this.side) +
|
|
(this.icon !== void 0 || this.avatar !== void 0 ? ' q-timeline__entry--icon' : '')
|
|
},
|
|
|
|
reverse: function reverse () {
|
|
return this.__timeline.layout === 'comfortable' && this.__timeline.side === 'left'
|
|
}
|
|
},
|
|
|
|
render: function render (h) {
|
|
var child = uniqueSlot(this, 'default', []);
|
|
|
|
if (this.body !== void 0) {
|
|
child.unshift(this.body);
|
|
}
|
|
|
|
if (this.heading === true) {
|
|
var content$1 = [
|
|
h('div'),
|
|
h('div'),
|
|
h(
|
|
this.tag,
|
|
{ staticClass: 'q-timeline__heading-title' },
|
|
child
|
|
)
|
|
];
|
|
|
|
return h('div', {
|
|
staticClass: 'q-timeline__heading',
|
|
on: Object.assign({}, this.qListeners)
|
|
}, this.reverse === true ? content$1.reverse() : content$1)
|
|
}
|
|
|
|
var dot;
|
|
|
|
if (this.icon !== void 0) {
|
|
dot = [
|
|
h(QIcon, {
|
|
staticClass: 'row items-center justify-center',
|
|
props: { name: this.icon }
|
|
})
|
|
];
|
|
}
|
|
else if (this.avatar !== void 0) {
|
|
dot = [
|
|
h('img', {
|
|
staticClass: 'q-timeline__dot-img',
|
|
domProps: { src: this.avatar }
|
|
})
|
|
];
|
|
}
|
|
|
|
var content = [
|
|
h('div', { staticClass: 'q-timeline__subtitle' }, [
|
|
h('span', slot(this, 'subtitle', [ this.subtitle ]))
|
|
]),
|
|
|
|
h('div', {
|
|
staticClass: 'q-timeline__dot',
|
|
class: this.colorClass
|
|
}, dot),
|
|
|
|
h('div', { staticClass: 'q-timeline__content' }, [
|
|
h('h6', { staticClass: 'q-timeline__title' }, slot(this, 'title', [ this.title ]))
|
|
].concat(child))
|
|
];
|
|
|
|
return h('li', {
|
|
staticClass: 'q-timeline__entry',
|
|
class: this.classes,
|
|
on: Object.assign({}, this.qListeners)
|
|
}, this.reverse === true ? content.reverse() : content)
|
|
}
|
|
});
|
|
|
|
var QToolbar = Vue.extend({
|
|
name: 'QToolbar',
|
|
|
|
mixins: [ ListenersMixin ],
|
|
|
|
props: {
|
|
inset: Boolean
|
|
},
|
|
|
|
render: function render (h) {
|
|
return h('div', {
|
|
staticClass: 'q-toolbar row no-wrap items-center',
|
|
class: this.inset ? 'q-toolbar--inset' : null,
|
|
on: Object.assign({}, this.qListeners)
|
|
}, slot(this, 'default'))
|
|
}
|
|
});
|
|
|
|
var QToolbarTitle = Vue.extend({
|
|
name: 'QToolbarTitle',
|
|
|
|
mixins: [ ListenersMixin ],
|
|
|
|
props: {
|
|
shrink: Boolean
|
|
},
|
|
|
|
computed: {
|
|
classes: function classes () {
|
|
return 'q-toolbar__title ellipsis' +
|
|
(this.shrink === true ? ' col-shrink' : '')
|
|
}
|
|
},
|
|
|
|
render: function render (h) {
|
|
return h('div', {
|
|
class: this.classes,
|
|
on: Object.assign({}, this.qListeners)
|
|
}, slot(this, 'default'))
|
|
}
|
|
});
|
|
|
|
var QTree = Vue.extend({
|
|
name: 'QTree',
|
|
|
|
mixins: [ DarkMixin ],
|
|
|
|
props: {
|
|
nodes: {
|
|
type: Array,
|
|
required: true
|
|
},
|
|
nodeKey: {
|
|
type: String,
|
|
required: true
|
|
},
|
|
labelKey: {
|
|
type: String,
|
|
default: 'label'
|
|
},
|
|
childrenKey: {
|
|
type: String,
|
|
default: 'children'
|
|
},
|
|
|
|
color: String,
|
|
controlColor: String,
|
|
textColor: String,
|
|
selectedColor: String,
|
|
|
|
icon: String,
|
|
|
|
tickStrategy: {
|
|
type: String,
|
|
default: 'none',
|
|
validator: function (v) { return ['none', 'strict', 'leaf', 'leaf-filtered'].includes(v); }
|
|
},
|
|
ticked: Array, // sync
|
|
expanded: Array, // sync
|
|
selected: {}, // sync
|
|
|
|
defaultExpandAll: Boolean,
|
|
accordion: Boolean,
|
|
|
|
filter: String,
|
|
filterMethod: {
|
|
type: Function,
|
|
default: function default$1 (node, filter) {
|
|
var filt = filter.toLowerCase();
|
|
return node[this.labelKey] &&
|
|
node[this.labelKey].toLowerCase().indexOf(filt) > -1
|
|
}
|
|
},
|
|
|
|
duration: Number,
|
|
noConnectors: Boolean,
|
|
|
|
noNodesLabel: String,
|
|
noResultsLabel: String
|
|
},
|
|
|
|
computed: {
|
|
classes: function classes () {
|
|
return "q-tree" +
|
|
(this.noConnectors === true ? " q-tree--no-connectors" : '') +
|
|
(this.isDark === true ? " q-tree--dark" : '') +
|
|
(this.color !== void 0 ? (" text-" + (this.color)) : '')
|
|
},
|
|
|
|
hasSelection: function hasSelection () {
|
|
return this.selected !== void 0
|
|
},
|
|
|
|
computedIcon: function computedIcon () {
|
|
return this.icon || this.$q.iconSet.tree.icon
|
|
},
|
|
|
|
computedControlColor: function computedControlColor () {
|
|
return this.controlColor || this.color
|
|
},
|
|
|
|
textColorClass: function textColorClass () {
|
|
if (this.textColor !== void 0) {
|
|
return ("text-" + (this.textColor))
|
|
}
|
|
},
|
|
|
|
selectedColorClass: function selectedColorClass () {
|
|
var color = this.selectedColor || this.color;
|
|
if (color) {
|
|
return ("text-" + color)
|
|
}
|
|
},
|
|
|
|
meta: function meta () {
|
|
var this$1 = this;
|
|
|
|
var meta = {};
|
|
|
|
var travel = function (node, parent) {
|
|
var tickStrategy = node.tickStrategy || (parent ? parent.tickStrategy : this$1.tickStrategy);
|
|
var
|
|
key = node[this$1.nodeKey],
|
|
isParent = node[this$1.childrenKey] && node[this$1.childrenKey].length > 0,
|
|
isLeaf = isParent !== true,
|
|
selectable = node.disabled !== true && this$1.hasSelection === true && node.selectable !== false,
|
|
expandable = node.disabled !== true && node.expandable !== false,
|
|
hasTicking = tickStrategy !== 'none',
|
|
strictTicking = tickStrategy === 'strict',
|
|
leafFilteredTicking = tickStrategy === 'leaf-filtered',
|
|
leafTicking = tickStrategy === 'leaf' || tickStrategy === 'leaf-filtered';
|
|
|
|
var tickable = node.disabled !== true && node.tickable !== false;
|
|
if (leafTicking === true && tickable === true && parent && parent.tickable !== true) {
|
|
tickable = false;
|
|
}
|
|
|
|
var lazy = node.lazy;
|
|
if (lazy && this$1.lazy[key]) {
|
|
lazy = this$1.lazy[key];
|
|
}
|
|
|
|
var m = {
|
|
key: key,
|
|
parent: parent,
|
|
isParent: isParent,
|
|
isLeaf: isLeaf,
|
|
lazy: lazy,
|
|
disabled: node.disabled,
|
|
link: node.disabled !== true && (selectable === true || (expandable === true && (isParent === true || lazy === true))),
|
|
children: [],
|
|
matchesFilter: this$1.filter ? this$1.filterMethod(node, this$1.filter) : true,
|
|
|
|
selected: key === this$1.selected && selectable === true,
|
|
selectable: selectable,
|
|
expanded: isParent === true ? this$1.innerExpanded.includes(key) : false,
|
|
expandable: expandable,
|
|
noTick: node.noTick === true || (strictTicking !== true && lazy && lazy !== 'loaded'),
|
|
tickable: tickable,
|
|
tickStrategy: tickStrategy,
|
|
hasTicking: hasTicking,
|
|
strictTicking: strictTicking,
|
|
leafFilteredTicking: leafFilteredTicking,
|
|
leafTicking: leafTicking,
|
|
ticked: strictTicking === true
|
|
? this$1.innerTicked.includes(key)
|
|
: (isLeaf === true ? this$1.innerTicked.includes(key) : false)
|
|
};
|
|
|
|
meta[key] = m;
|
|
|
|
if (isParent === true) {
|
|
m.children = node[this$1.childrenKey].map(function (n) { return travel(n, m); });
|
|
|
|
if (this$1.filter) {
|
|
if (m.matchesFilter !== true) {
|
|
m.matchesFilter = m.children.some(function (n) { return n.matchesFilter; });
|
|
}
|
|
else if (
|
|
m.noTick !== true &&
|
|
m.disabled !== true &&
|
|
m.tickable === true &&
|
|
leafFilteredTicking === true &&
|
|
m.children.every(function (n) { return n.matchesFilter !== true || n.noTick === true || n.tickable !== true; }) === true
|
|
) {
|
|
m.tickable = false;
|
|
}
|
|
}
|
|
|
|
if (m.matchesFilter === true) {
|
|
if (m.noTick !== true && strictTicking !== true && m.children.every(function (n) { return n.noTick; }) === true) {
|
|
m.noTick = true;
|
|
}
|
|
|
|
if (leafTicking) {
|
|
m.ticked = false;
|
|
m.indeterminate = m.children.some(function (node) { return node.indeterminate === true; });
|
|
m.tickable = m.tickable === true && m.children.some(function (node) { return node.tickable; });
|
|
|
|
if (m.indeterminate !== true) {
|
|
var sel = m.children
|
|
.reduce(function (acc, meta) { return meta.ticked === true ? acc + 1 : acc; }, 0);
|
|
|
|
if (sel === m.children.length) {
|
|
m.ticked = true;
|
|
}
|
|
else if (sel > 0) {
|
|
m.indeterminate = true;
|
|
}
|
|
}
|
|
|
|
if (m.indeterminate === true) {
|
|
m.indeterminateNextState = m.children
|
|
.every(function (meta) { return meta.tickable !== true || meta.ticked !== true; });
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return m
|
|
};
|
|
|
|
this.nodes.forEach(function (node) { return travel(node, null); });
|
|
return meta
|
|
}
|
|
},
|
|
|
|
data: function data () {
|
|
return {
|
|
lazy: {},
|
|
innerTicked: this.ticked || [],
|
|
innerExpanded: this.expanded || []
|
|
}
|
|
},
|
|
|
|
watch: {
|
|
ticked: function ticked (val) {
|
|
this.innerTicked = val;
|
|
},
|
|
|
|
expanded: function expanded (val) {
|
|
this.innerExpanded = val;
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
getNodeByKey: function getNodeByKey (key) {
|
|
var this$1 = this;
|
|
|
|
var reduce = [].reduce;
|
|
|
|
var find = function (result, node) {
|
|
if (result || !node) {
|
|
return result
|
|
}
|
|
if (Array.isArray(node) === true) {
|
|
return reduce.call(Object(node), find, result)
|
|
}
|
|
if (node[this$1.nodeKey] === key) {
|
|
return node
|
|
}
|
|
if (node[this$1.childrenKey]) {
|
|
return find(null, node[this$1.childrenKey])
|
|
}
|
|
};
|
|
|
|
return find(null, this.nodes)
|
|
},
|
|
|
|
getTickedNodes: function getTickedNodes () {
|
|
var this$1 = this;
|
|
|
|
return this.innerTicked.map(function (key) { return this$1.getNodeByKey(key); })
|
|
},
|
|
|
|
getExpandedNodes: function getExpandedNodes () {
|
|
var this$1 = this;
|
|
|
|
return this.innerExpanded.map(function (key) { return this$1.getNodeByKey(key); })
|
|
},
|
|
|
|
isExpanded: function isExpanded (key) {
|
|
return key && this.meta[key]
|
|
? this.meta[key].expanded
|
|
: false
|
|
},
|
|
|
|
collapseAll: function collapseAll () {
|
|
if (this.expanded !== void 0) {
|
|
this.$emit('update:expanded', []);
|
|
}
|
|
else {
|
|
this.innerExpanded = [];
|
|
}
|
|
},
|
|
|
|
expandAll: function expandAll () {
|
|
var this$1 = this;
|
|
|
|
var
|
|
expanded = this.innerExpanded,
|
|
travel = function (node) {
|
|
if (node[this$1.childrenKey] && node[this$1.childrenKey].length > 0) {
|
|
if (node.expandable !== false && node.disabled !== true) {
|
|
expanded.push(node[this$1.nodeKey]);
|
|
node[this$1.childrenKey].forEach(travel);
|
|
}
|
|
}
|
|
};
|
|
|
|
this.nodes.forEach(travel);
|
|
|
|
if (this.expanded !== void 0) {
|
|
this.$emit('update:expanded', expanded);
|
|
}
|
|
else {
|
|
this.innerExpanded = expanded;
|
|
}
|
|
},
|
|
|
|
setExpanded: function setExpanded (key, state, node, meta) {
|
|
var this$1 = this;
|
|
if ( node === void 0 ) node = this.getNodeByKey(key);
|
|
if ( meta === void 0 ) meta = this.meta[key];
|
|
|
|
if (meta.lazy && meta.lazy !== 'loaded') {
|
|
if (meta.lazy === 'loading') {
|
|
return
|
|
}
|
|
|
|
this.$set(this.lazy, key, 'loading');
|
|
this.$emit('lazy-load', {
|
|
node: node,
|
|
key: key,
|
|
done: function (children) {
|
|
this$1.lazy[key] = 'loaded';
|
|
if (children) {
|
|
this$1.$set(node, this$1.childrenKey, children);
|
|
}
|
|
this$1.$nextTick(function () {
|
|
var m = this$1.meta[key];
|
|
if (m && m.isParent === true) {
|
|
this$1.__setExpanded(key, true);
|
|
}
|
|
});
|
|
},
|
|
fail: function () {
|
|
this$1.$delete(this$1.lazy, key);
|
|
}
|
|
});
|
|
}
|
|
else if (meta.isParent === true && meta.expandable === true) {
|
|
this.__setExpanded(key, state);
|
|
}
|
|
},
|
|
|
|
__setExpanded: function __setExpanded (key, state) {
|
|
var this$1 = this;
|
|
|
|
var target = this.innerExpanded;
|
|
var emit = this.expanded !== void 0;
|
|
|
|
if (emit === true) {
|
|
target = target.slice();
|
|
}
|
|
|
|
if (state) {
|
|
if (this.accordion) {
|
|
if (this.meta[key]) {
|
|
var collapse = [];
|
|
if (this.meta[key].parent) {
|
|
this.meta[key].parent.children.forEach(function (m) {
|
|
if (m.key !== key && m.expandable === true) {
|
|
collapse.push(m.key);
|
|
}
|
|
});
|
|
}
|
|
else {
|
|
this.nodes.forEach(function (node) {
|
|
var k = node[this$1.nodeKey];
|
|
if (k !== key) {
|
|
collapse.push(k);
|
|
}
|
|
});
|
|
}
|
|
if (collapse.length > 0) {
|
|
target = target.filter(function (k) { return collapse.includes(k) === false; });
|
|
}
|
|
}
|
|
}
|
|
|
|
target = target.concat([ key ])
|
|
.filter(function (key, index, self) { return self.indexOf(key) === index; });
|
|
}
|
|
else {
|
|
target = target.filter(function (k) { return k !== key; });
|
|
}
|
|
|
|
if (emit === true) {
|
|
this.$emit("update:expanded", target);
|
|
}
|
|
else {
|
|
this.innerExpanded = target;
|
|
}
|
|
},
|
|
|
|
isTicked: function isTicked (key) {
|
|
return key && this.meta[key]
|
|
? this.meta[key].ticked
|
|
: false
|
|
},
|
|
|
|
setTicked: function setTicked (keys, state) {
|
|
var target = this.innerTicked;
|
|
var emit = this.ticked !== void 0;
|
|
|
|
if (emit === true) {
|
|
target = target.slice();
|
|
}
|
|
|
|
if (state) {
|
|
target = target.concat(keys)
|
|
.filter(function (key, index, self) { return self.indexOf(key) === index; });
|
|
}
|
|
else {
|
|
target = target.filter(function (k) { return keys.includes(k) === false; });
|
|
}
|
|
|
|
if (emit === true) {
|
|
this.$emit("update:ticked", target);
|
|
}
|
|
},
|
|
|
|
__getSlotScope: function __getSlotScope (node, meta, key) {
|
|
var this$1 = this;
|
|
|
|
var scope = { tree: this, node: node, key: key, color: this.color, dark: this.isDark };
|
|
|
|
Object.defineProperty(scope, 'expanded', {
|
|
get: function () { return meta.expanded },
|
|
set: function (val) { val !== meta.expanded && this$1.setExpanded(key, val); },
|
|
configurable: true,
|
|
enumerable: true
|
|
});
|
|
Object.defineProperty(scope, 'ticked', {
|
|
get: function () { return meta.ticked },
|
|
set: function (val) { val !== meta.ticked && this$1.setTicked([ key ], val); },
|
|
configurable: true,
|
|
enumerable: true
|
|
});
|
|
|
|
return scope
|
|
},
|
|
|
|
__getChildren: function __getChildren (h, nodes) {
|
|
var this$1 = this;
|
|
|
|
return (
|
|
this.filter
|
|
? nodes.filter(function (n) { return this$1.meta[n[this$1.nodeKey]].matchesFilter; })
|
|
: nodes
|
|
).map(function (child) { return this$1.__getNode(h, child); })
|
|
},
|
|
|
|
__getNodeMedia: function __getNodeMedia (h, node) {
|
|
if (node.icon !== void 0) {
|
|
return h(QIcon, {
|
|
staticClass: "q-tree__icon q-mr-sm",
|
|
props: { name: node.icon, color: node.iconColor }
|
|
})
|
|
}
|
|
var src = node.img || node.avatar;
|
|
if (src) {
|
|
return h('img', {
|
|
staticClass: ("q-tree__" + (node.img ? 'img' : 'avatar') + " q-mr-sm"),
|
|
attrs: { src: src }
|
|
})
|
|
}
|
|
},
|
|
|
|
__getNode: function __getNode (h, node) {
|
|
var this$1 = this;
|
|
|
|
var
|
|
key = node[this.nodeKey],
|
|
meta = this.meta[key],
|
|
header = node.header
|
|
? this.$scopedSlots[("header-" + (node.header))] || this.$scopedSlots['default-header']
|
|
: this.$scopedSlots['default-header'];
|
|
|
|
var children = meta.isParent === true
|
|
? this.__getChildren(h, node[this.childrenKey])
|
|
: [];
|
|
|
|
var isParent = children.length > 0 || (meta.lazy && meta.lazy !== 'loaded');
|
|
|
|
var body = node.body
|
|
? this.$scopedSlots[("body-" + (node.body))] || this.$scopedSlots['default-body']
|
|
: this.$scopedSlots['default-body'];
|
|
var slotScope = header !== void 0 || body !== void 0
|
|
? this.__getSlotScope(node, meta, key)
|
|
: null;
|
|
|
|
if (body !== void 0) {
|
|
body = h('div', { staticClass: 'q-tree__node-body relative-position' }, [
|
|
h('div', { class: this.textColorClass }, [
|
|
body(slotScope)
|
|
])
|
|
]);
|
|
}
|
|
|
|
return h('div', {
|
|
key: key,
|
|
staticClass: 'q-tree__node relative-position',
|
|
class: { 'q-tree__node--parent': isParent, 'q-tree__node--child': !isParent }
|
|
}, [
|
|
h('div', {
|
|
staticClass: 'q-tree__node-header relative-position row no-wrap items-center',
|
|
class: {
|
|
'q-tree__node--link q-hoverable q-focusable': meta.link,
|
|
'q-tree__node--selected': meta.selected,
|
|
'q-tree__node--disabled': meta.disabled
|
|
},
|
|
attrs: { tabindex: meta.link ? 0 : -1 },
|
|
on: {
|
|
click: function (e) {
|
|
this$1.__onClick(node, meta, e);
|
|
},
|
|
keypress: function (e) {
|
|
if (shouldIgnoreKey(e) !== true) {
|
|
if (e.keyCode === 13) { this$1.__onClick(node, meta, e, true); }
|
|
else if (e.keyCode === 32) { this$1.__onExpandClick(node, meta, e, true); }
|
|
}
|
|
}
|
|
}
|
|
}, [
|
|
h('div', { staticClass: 'q-focus-helper', attrs: { tabindex: -1 }, ref: ("blurTarget_" + (meta.key)) }),
|
|
|
|
meta.lazy === 'loading'
|
|
? h(QSpinner, {
|
|
staticClass: 'q-tree__spinner q-mr-xs',
|
|
props: { color: this.computedControlColor }
|
|
})
|
|
: (
|
|
isParent === true
|
|
? h(QIcon, {
|
|
staticClass: 'q-tree__arrow q-mr-xs',
|
|
class: { 'q-tree__arrow--rotate': meta.expanded },
|
|
props: { name: this.computedIcon },
|
|
on: {
|
|
click: function (e) {
|
|
this$1.__onExpandClick(node, meta, e);
|
|
}
|
|
}
|
|
})
|
|
: null
|
|
),
|
|
|
|
meta.hasTicking === true && meta.noTick !== true
|
|
? h(QCheckbox, {
|
|
staticClass: 'q-mr-xs',
|
|
props: {
|
|
value: meta.indeterminate === true ? null : meta.ticked,
|
|
color: this.computedControlColor,
|
|
dark: this.isDark,
|
|
dense: true,
|
|
keepColor: true,
|
|
disable: meta.tickable !== true
|
|
},
|
|
on: {
|
|
keydown: stopAndPrevent,
|
|
input: function (v) {
|
|
this$1.__onTickedClick(meta, v);
|
|
}
|
|
}
|
|
})
|
|
: null,
|
|
|
|
h('div', {
|
|
'staticClass': 'q-tree__node-header-content col row no-wrap items-center',
|
|
class: meta.selected ? this.selectedColorClass : this.textColorClass
|
|
}, [
|
|
header
|
|
? header(slotScope)
|
|
: [
|
|
this.__getNodeMedia(h, node),
|
|
h('div', node[this.labelKey])
|
|
]
|
|
])
|
|
]),
|
|
|
|
isParent === true
|
|
? h(QSlideTransition, {
|
|
props: { duration: this.duration },
|
|
on: cache(this, 'slide', {
|
|
show: function () { this$1.$emit('after-show'); },
|
|
hide: function () { this$1.$emit('after-hide'); }
|
|
})
|
|
}, [
|
|
h('div', {
|
|
staticClass: 'q-tree__node-collapsible',
|
|
class: this.textColorClass,
|
|
directives: [{ name: 'show', value: meta.expanded }]
|
|
}, [
|
|
body,
|
|
|
|
h('div', {
|
|
staticClass: 'q-tree__children',
|
|
class: { 'q-tree__node--disabled': meta.disabled }
|
|
}, children)
|
|
])
|
|
])
|
|
: body
|
|
])
|
|
},
|
|
|
|
__blur: function __blur (key) {
|
|
var blurTarget = this.$refs[("blurTarget_" + key)];
|
|
blurTarget !== void 0 && blurTarget.focus();
|
|
},
|
|
|
|
__onClick: function __onClick (node, meta, e, keyboard) {
|
|
keyboard !== true && this.__blur(meta.key);
|
|
|
|
if (this.hasSelection) {
|
|
if (meta.selectable) {
|
|
this.$emit('update:selected', meta.key !== this.selected ? meta.key : null);
|
|
}
|
|
}
|
|
else {
|
|
this.__onExpandClick(node, meta, e, keyboard);
|
|
}
|
|
|
|
if (typeof node.handler === 'function') {
|
|
node.handler(node);
|
|
}
|
|
},
|
|
|
|
__onExpandClick: function __onExpandClick (node, meta, e, keyboard) {
|
|
if (e !== void 0) {
|
|
stopAndPrevent(e);
|
|
}
|
|
keyboard !== true && this.__blur(meta.key);
|
|
this.setExpanded(meta.key, !meta.expanded, node, meta);
|
|
},
|
|
|
|
__onTickedClick: function __onTickedClick (meta, state) {
|
|
if (meta.indeterminate === true) {
|
|
state = meta.indeterminateNextState;
|
|
}
|
|
if (meta.strictTicking) {
|
|
this.setTicked([ meta.key ], state);
|
|
}
|
|
else if (meta.leafTicking) {
|
|
var keys = [];
|
|
var travel = function (meta) {
|
|
if (meta.isParent) {
|
|
if (state !== true && meta.noTick !== true && meta.tickable === true) {
|
|
keys.push(meta.key);
|
|
}
|
|
if (meta.leafTicking === true) {
|
|
meta.children.forEach(travel);
|
|
}
|
|
}
|
|
else if (
|
|
meta.noTick !== true &&
|
|
meta.tickable === true &&
|
|
(meta.leafFilteredTicking !== true || meta.matchesFilter === true)
|
|
) {
|
|
keys.push(meta.key);
|
|
}
|
|
};
|
|
travel(meta);
|
|
this.setTicked(keys, state);
|
|
}
|
|
}
|
|
},
|
|
|
|
render: function render (h) {
|
|
var children = this.__getChildren(h, this.nodes);
|
|
|
|
return h(
|
|
'div', {
|
|
class: this.classes
|
|
},
|
|
children.length === 0
|
|
? (
|
|
this.filter
|
|
? this.noResultsLabel || this.$q.lang.tree.noResults
|
|
: this.noNodesLabel || this.$q.lang.tree.noNodes
|
|
)
|
|
: children
|
|
)
|
|
},
|
|
|
|
created: function created () {
|
|
this.defaultExpandAll === true && this.expandAll();
|
|
}
|
|
});
|
|
|
|
var QUploaderBase = Vue.extend({
|
|
name: 'QUploaderBase',
|
|
|
|
mixins: [ DarkMixin, FileMixin ],
|
|
|
|
props: {
|
|
label: String,
|
|
|
|
color: String,
|
|
textColor: String,
|
|
|
|
square: Boolean,
|
|
flat: Boolean,
|
|
bordered: Boolean,
|
|
|
|
noThumbnails: Boolean,
|
|
autoUpload: Boolean,
|
|
hideUploadBtn: Boolean,
|
|
|
|
disable: Boolean,
|
|
readonly: Boolean
|
|
},
|
|
|
|
provide: function provide () {
|
|
return {
|
|
__qUploaderGetInput: this.__getInputControl
|
|
}
|
|
},
|
|
|
|
data: function data () {
|
|
return {
|
|
files: [],
|
|
queuedFiles: [],
|
|
uploadedFiles: [],
|
|
dnd: false,
|
|
expanded: false,
|
|
|
|
uploadSize: 0,
|
|
uploadedSize: 0
|
|
}
|
|
},
|
|
|
|
watch: {
|
|
isUploading: function isUploading (newVal, oldVal) {
|
|
if (oldVal === false && newVal === true) {
|
|
this.$emit('start');
|
|
}
|
|
else if (oldVal === true && newVal === false) {
|
|
this.$emit('finish');
|
|
}
|
|
}
|
|
},
|
|
|
|
computed: {
|
|
/*
|
|
* When extending:
|
|
* Required : isUploading
|
|
* Optional: isBusy
|
|
*/
|
|
|
|
canUpload: function canUpload () {
|
|
return this.editable === true &&
|
|
this.isBusy !== true &&
|
|
this.isUploading !== true &&
|
|
this.queuedFiles.length > 0
|
|
},
|
|
|
|
canAddFiles: function canAddFiles () {
|
|
return (
|
|
this.editable === true &&
|
|
this.isUploading !== true &&
|
|
// if single selection and no files are queued:
|
|
(this.multiple === true || this.queuedFiles.length === 0) &&
|
|
// if max-files is set and current number of files does not exceeds it:
|
|
(this.maxFiles === void 0 || this.files.length < this.maxFilesNumber) &&
|
|
// if max-total-size is set and current upload size does not exceeds it:
|
|
(this.maxTotalSize === void 0 || this.uploadSize < this.maxTotalSizeNumber)
|
|
)
|
|
},
|
|
|
|
uploadProgress: function uploadProgress () {
|
|
return this.uploadSize === 0
|
|
? 0
|
|
: this.uploadedSize / this.uploadSize
|
|
},
|
|
|
|
uploadProgressLabel: function uploadProgressLabel () {
|
|
return this.__getProgressLabel(this.uploadProgress)
|
|
},
|
|
|
|
uploadedSizeLabel: function uploadedSizeLabel () {
|
|
return humanStorageSize(this.uploadedSize)
|
|
},
|
|
|
|
uploadSizeLabel: function uploadSizeLabel () {
|
|
return humanStorageSize(this.uploadSize)
|
|
},
|
|
|
|
colorClass: function colorClass () {
|
|
var cls = [];
|
|
this.color !== void 0 && cls.push(("bg-" + (this.color)));
|
|
this.textColor !== void 0 && cls.push(("text-" + (this.textColor)));
|
|
return cls.join(' ')
|
|
},
|
|
|
|
editable: function editable () {
|
|
return this.disable !== true && this.readonly !== true
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
reset: function reset () {
|
|
if (!this.disable) {
|
|
this.abort();
|
|
this.uploadedSize = 0;
|
|
this.uploadSize = 0;
|
|
this.__revokeImgURLs();
|
|
this.files = [];
|
|
this.queuedFiles = [];
|
|
this.uploadedFiles = [];
|
|
}
|
|
},
|
|
|
|
removeUploadedFiles: function removeUploadedFiles () {
|
|
if (!this.disable) {
|
|
this.files = this.files.filter(function (f) {
|
|
if (f.__status !== 'uploaded') {
|
|
return true
|
|
}
|
|
|
|
f._img !== void 0 && window.URL.revokeObjectURL(f._img.src);
|
|
|
|
return false
|
|
});
|
|
this.uploadedFiles = [];
|
|
}
|
|
},
|
|
|
|
removeQueuedFiles: function removeQueuedFiles () {
|
|
var this$1 = this;
|
|
|
|
if (!this.disable) {
|
|
var removedFiles = [];
|
|
|
|
var files = this.files.filter(function (f) {
|
|
if (f.__status !== 'idle' && f.__status !== 'failed') {
|
|
return true
|
|
}
|
|
|
|
this$1.uploadSize -= f.size;
|
|
removedFiles.push(f);
|
|
|
|
f._img !== void 0 && window.URL.revokeObjectURL(f._img.src);
|
|
|
|
return false
|
|
});
|
|
|
|
if (removedFiles.length > 0) {
|
|
this.files = files;
|
|
this.queuedFiles = [];
|
|
this.$emit('removed', removedFiles);
|
|
}
|
|
}
|
|
},
|
|
|
|
removeFile: function removeFile (file) {
|
|
if (this.disable) { return }
|
|
|
|
if (file.__status === 'uploaded') {
|
|
this.uploadedFiles = this.uploadedFiles.filter(function (f) { return f.name !== file.name; });
|
|
}
|
|
else if (file.__status === 'uploading') {
|
|
file.__abort();
|
|
}
|
|
else {
|
|
this.uploadSize -= file.size;
|
|
}
|
|
|
|
this.files = this.files.filter(function (f) {
|
|
if (f.name !== file.name) {
|
|
return true
|
|
}
|
|
|
|
f._img !== void 0 && window.URL.revokeObjectURL(f._img.src);
|
|
|
|
return false
|
|
});
|
|
this.queuedFiles = this.queuedFiles.filter(function (f) { return f.name !== file.name; });
|
|
this.$emit('removed', [ file ]);
|
|
},
|
|
|
|
__revokeImgURLs: function __revokeImgURLs () {
|
|
this.files.forEach(function (f) {
|
|
f._img !== void 0 && window.URL.revokeObjectURL(f._img.src);
|
|
});
|
|
},
|
|
|
|
__getFileInput: function __getFileInput () {
|
|
return this.$refs.input ||
|
|
this.$el.getElementsByClassName('q-uploader__input')[0]
|
|
},
|
|
|
|
__getProgressLabel: function __getProgressLabel (p) {
|
|
return (p * 100).toFixed(2) + '%'
|
|
},
|
|
|
|
__updateFile: function __updateFile (file, status, uploadedSize) {
|
|
file.__status = status;
|
|
|
|
if (status === 'idle') {
|
|
file.__uploaded = 0;
|
|
file.__progress = 0;
|
|
file.__sizeLabel = humanStorageSize(file.size);
|
|
file.__progressLabel = '0.00%';
|
|
return
|
|
}
|
|
if (status === 'failed') {
|
|
this.$forceUpdate();
|
|
return
|
|
}
|
|
|
|
file.__uploaded = status === 'uploaded'
|
|
? file.size
|
|
: uploadedSize;
|
|
|
|
file.__progress = status === 'uploaded'
|
|
? 1
|
|
: Math.min(0.9999, file.__uploaded / file.size);
|
|
|
|
file.__progressLabel = this.__getProgressLabel(file.__progress);
|
|
this.$forceUpdate();
|
|
},
|
|
|
|
__addFiles: function __addFiles (e, fileList) {
|
|
var this$1 = this;
|
|
|
|
var processedFiles = this.__processFiles(e, fileList, this.files, true);
|
|
|
|
if (processedFiles === void 0) { return }
|
|
|
|
var files = processedFiles
|
|
.filter(function (file) { return this$1.files.findIndex(function (f) { return file.name === f.name; }) === -1; });
|
|
|
|
this.__getFileInput().value = '';
|
|
|
|
if (files === void 0) { return }
|
|
|
|
files.forEach(function (file) {
|
|
this$1.__updateFile(file, 'idle');
|
|
this$1.uploadSize += file.size;
|
|
|
|
if (this$1.noThumbnails !== true && file.type.toUpperCase().startsWith('IMAGE')) {
|
|
var img = new Image();
|
|
img.src = window.URL.createObjectURL(file);
|
|
file.__img = img;
|
|
}
|
|
});
|
|
|
|
this.files = this.files.concat(files);
|
|
this.queuedFiles = this.queuedFiles.concat(files);
|
|
this.$emit('added', files);
|
|
this.autoUpload === true && this.upload();
|
|
},
|
|
|
|
__getBtn: function __getBtn (h, show, icon, fn) {
|
|
if (show === true) {
|
|
return h(QBtn, {
|
|
props: {
|
|
type: 'a',
|
|
icon: this.$q.iconSet.uploader[icon],
|
|
flat: true,
|
|
dense: true
|
|
},
|
|
on: icon === 'add' ? null : { click: fn }
|
|
}, icon === 'add' ? this.__getInputControl(h) : null)
|
|
}
|
|
},
|
|
|
|
__getInputControl: function __getInputControl (h) {
|
|
return [
|
|
h('input', {
|
|
ref: 'input',
|
|
staticClass: 'q-uploader__input overflow-hidden absolute-full',
|
|
attrs: Object.assign({}, {tabindex: -1,
|
|
type: 'file',
|
|
title: '', // try to remove default tooltip
|
|
accept: this.accept,
|
|
capture: this.capture},
|
|
(this.multiple === true ? { multiple: true } : {})),
|
|
on: cache(this, 'input', {
|
|
mousedown: stop, // need to stop refocus from QBtn
|
|
change: this.__addFiles
|
|
})
|
|
})
|
|
]
|
|
},
|
|
|
|
__getHeader: function __getHeader (h) {
|
|
if (this.$scopedSlots.header !== void 0) {
|
|
return this.$scopedSlots.header(this)
|
|
}
|
|
|
|
return [
|
|
h('div', {
|
|
staticClass: 'q-uploader__header-content flex flex-center no-wrap q-gutter-xs'
|
|
}, [
|
|
this.__getBtn(h, this.queuedFiles.length > 0, 'removeQueue', this.removeQueuedFiles),
|
|
this.__getBtn(h, this.uploadedFiles.length > 0, 'removeUploaded', this.removeUploadedFiles),
|
|
|
|
this.isUploading === true
|
|
? h(QSpinner, { staticClass: 'q-uploader__spinner' })
|
|
: null,
|
|
|
|
h('div', { staticClass: 'col column justify-center' }, [
|
|
this.label !== void 0
|
|
? h('div', { staticClass: 'q-uploader__title' }, [ this.label ])
|
|
: null,
|
|
|
|
h('div', { staticClass: 'q-uploader__subtitle' }, [
|
|
this.uploadSizeLabel + ' / ' + this.uploadProgressLabel
|
|
])
|
|
]),
|
|
|
|
this.__getBtn(h, this.canAddFiles, 'add', this.pickFiles),
|
|
this.__getBtn(h, this.hideUploadBtn === false && this.canUpload === true, 'upload', this.upload),
|
|
this.__getBtn(h, this.isUploading, 'clear', this.abort)
|
|
])
|
|
]
|
|
},
|
|
|
|
__getList: function __getList (h) {
|
|
var this$1 = this;
|
|
|
|
if (this.$scopedSlots.list !== void 0) {
|
|
return this.$scopedSlots.list(this)
|
|
}
|
|
|
|
return this.files.map(function (file) { return h('div', {
|
|
key: file.name,
|
|
staticClass: 'q-uploader__file relative-position',
|
|
class: {
|
|
'q-uploader__file--img': this$1.noThumbnails !== true && file.__img !== void 0,
|
|
'q-uploader__file--failed': file.__status === 'failed',
|
|
'q-uploader__file--uploaded': file.__status === 'uploaded'
|
|
},
|
|
style: this$1.noThumbnails !== true && file.__img !== void 0 ? {
|
|
backgroundImage: 'url("' + file.__img.src + '")'
|
|
} : null
|
|
}, [
|
|
h('div', {
|
|
staticClass: 'q-uploader__file-header row flex-center no-wrap'
|
|
}, [
|
|
file.__status === 'failed'
|
|
? h(QIcon, {
|
|
staticClass: 'q-uploader__file-status',
|
|
props: {
|
|
name: this$1.$q.iconSet.type.negative,
|
|
color: 'negative'
|
|
}
|
|
})
|
|
: null,
|
|
|
|
h('div', { staticClass: 'q-uploader__file-header-content col' }, [
|
|
h('div', { staticClass: 'q-uploader__title' }, [ file.name ]),
|
|
h('div', {
|
|
staticClass: 'q-uploader__subtitle row items-center no-wrap'
|
|
}, [
|
|
file.__sizeLabel + ' / ' + file.__progressLabel
|
|
])
|
|
]),
|
|
|
|
file.__status === 'uploading'
|
|
? h(QCircularProgress, {
|
|
props: {
|
|
value: file.__progress,
|
|
min: 0,
|
|
max: 1,
|
|
indeterminate: file.__progress === 0
|
|
}
|
|
})
|
|
: h(QBtn, {
|
|
props: {
|
|
round: true,
|
|
dense: true,
|
|
flat: true,
|
|
icon: this$1.$q.iconSet.uploader[file.__status === 'uploaded' ? 'done' : 'clear']
|
|
},
|
|
on: {
|
|
click: function () { this$1.removeFile(file); }
|
|
}
|
|
})
|
|
])
|
|
]); })
|
|
}
|
|
},
|
|
|
|
beforeDestroy: function beforeDestroy () {
|
|
this.isUploading === true && this.abort();
|
|
this.files.length > 0 && this.__revokeImgURLs();
|
|
},
|
|
|
|
render: function render (h) {
|
|
var children = [
|
|
h('div', {
|
|
staticClass: 'q-uploader__header',
|
|
class: this.colorClass
|
|
}, this.__getHeader(h)),
|
|
|
|
h('div', {
|
|
staticClass: 'q-uploader__list scroll'
|
|
}, this.__getList(h)),
|
|
|
|
this.__getDnd(h, 'uploader')
|
|
];
|
|
|
|
this.isBusy === true && children.push(
|
|
h('div', {
|
|
staticClass: 'q-uploader__overlay absolute-full flex flex-center'
|
|
}, [ h(QSpinner) ])
|
|
);
|
|
|
|
return h('div', {
|
|
staticClass: 'q-uploader column no-wrap',
|
|
class: {
|
|
'q-uploader--dark q-dark': this.isDark,
|
|
'q-uploader--bordered': this.bordered,
|
|
'q-uploader--square no-border-radius': this.square,
|
|
'q-uploader--flat no-shadow': this.flat,
|
|
'disabled q-uploader--disable': this.disable
|
|
},
|
|
on: this.canAddFiles === true
|
|
? cache(this, 'drag', { dragover: this.__onDragOver })
|
|
: null
|
|
}, children)
|
|
}
|
|
});
|
|
|
|
function getFn (prop) {
|
|
return typeof prop === 'function'
|
|
? prop
|
|
: function () { return prop; }
|
|
}
|
|
|
|
var UploaderXHRMixin = {
|
|
props: {
|
|
url: [ Function, String ],
|
|
method: {
|
|
type: [ Function, String ],
|
|
default: 'POST'
|
|
},
|
|
fieldName: {
|
|
type: [ Function, String ],
|
|
default: function (file) { return file.name; }
|
|
},
|
|
headers: [ Function, Array ],
|
|
formFields: [ Function, Array ],
|
|
withCredentials: [ Function, Boolean ],
|
|
sendRaw: [ Function, Boolean ],
|
|
|
|
batch: [ Function, Boolean ],
|
|
factory: Function
|
|
},
|
|
|
|
data: function data () {
|
|
return {
|
|
xhrs: [],
|
|
promises: [],
|
|
workingThreads: 0
|
|
}
|
|
},
|
|
|
|
computed: {
|
|
xhrProps: function xhrProps () {
|
|
return {
|
|
url: getFn(this.url),
|
|
method: getFn(this.method),
|
|
headers: getFn(this.headers),
|
|
formFields: getFn(this.formFields),
|
|
fieldName: getFn(this.fieldName),
|
|
withCredentials: getFn(this.withCredentials),
|
|
sendRaw: getFn(this.sendRaw),
|
|
batch: getFn(this.batch)
|
|
}
|
|
},
|
|
|
|
isUploading: function isUploading () {
|
|
return this.workingThreads > 0
|
|
},
|
|
|
|
isBusy: function isBusy () {
|
|
return this.promises.length > 0
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
abort: function abort () {
|
|
this.xhrs.forEach(function (x) { x.abort(); });
|
|
|
|
if (this.promises.length > 0) {
|
|
this.abortPromises = true;
|
|
}
|
|
},
|
|
|
|
upload: function upload () {
|
|
var this$1 = this;
|
|
|
|
if (this.canUpload === false) {
|
|
return
|
|
}
|
|
|
|
var queue = this.queuedFiles.slice(0);
|
|
this.queuedFiles = [];
|
|
|
|
if (this.xhrProps.batch(queue)) {
|
|
this.__runFactory(queue);
|
|
}
|
|
else {
|
|
queue.forEach(function (file) {
|
|
this$1.__runFactory([ file ]);
|
|
});
|
|
}
|
|
},
|
|
|
|
__runFactory: function __runFactory (files) {
|
|
var this$1 = this;
|
|
|
|
this.workingThreads++;
|
|
|
|
if (typeof this.factory !== 'function') {
|
|
this.__uploadFiles(files, {});
|
|
return
|
|
}
|
|
|
|
var res = this.factory(files);
|
|
|
|
if (!res) {
|
|
this.$emit(
|
|
'factory-failed',
|
|
new Error('QUploader: factory() does not return properly'),
|
|
files
|
|
);
|
|
this.workingThreads--;
|
|
}
|
|
else if (typeof res.catch === 'function' && typeof res.then === 'function') {
|
|
this.promises.push(res);
|
|
|
|
var failed = function (err) {
|
|
if (this$1._isBeingDestroyed !== true && this$1._isDestroyed !== true) {
|
|
this$1.promises = this$1.promises.filter(function (p) { return p !== res; });
|
|
|
|
if (this$1.promises.length === 0) {
|
|
this$1.abortPromises = false;
|
|
}
|
|
|
|
this$1.queuedFiles = this$1.queuedFiles.concat(files);
|
|
files.forEach(function (f) { this$1.__updateFile(f, 'failed'); });
|
|
|
|
this$1.$emit('factory-failed', err, files);
|
|
this$1.workingThreads--;
|
|
}
|
|
};
|
|
|
|
res.then(function (factory) {
|
|
if (this$1.abortPromises === true) {
|
|
failed(new Error('Aborted'));
|
|
}
|
|
else if (this$1._isBeingDestroyed !== true && this$1._isDestroyed !== true) {
|
|
this$1.promises = this$1.promises.filter(function (p) { return p !== res; });
|
|
this$1.__uploadFiles(files, factory);
|
|
}
|
|
}).catch(failed);
|
|
}
|
|
else {
|
|
this.__uploadFiles(files, res || {});
|
|
}
|
|
},
|
|
|
|
__uploadFiles: function __uploadFiles (files, factory) {
|
|
var this$1 = this;
|
|
|
|
var
|
|
form = new FormData(),
|
|
xhr = new XMLHttpRequest();
|
|
|
|
var getProp = function (name, arg) {
|
|
return factory[name] !== void 0
|
|
? getFn(factory[name])(arg)
|
|
: this$1.xhrProps[name](arg)
|
|
};
|
|
|
|
var url = getProp('url', files);
|
|
|
|
if (!url) {
|
|
console.error('q-uploader: invalid or no URL specified');
|
|
this.workingThreads--;
|
|
return
|
|
}
|
|
|
|
var fields = getProp('formFields', files);
|
|
fields !== void 0 && fields.forEach(function (field) {
|
|
form.append(field.name, field.value);
|
|
});
|
|
|
|
var
|
|
uploadIndex = 0,
|
|
uploadIndexSize = 0,
|
|
uploadedSize = 0,
|
|
maxUploadSize = 0,
|
|
aborted;
|
|
|
|
xhr.upload.addEventListener('progress', function (e) {
|
|
if (aborted === true) { return }
|
|
|
|
var loaded = Math.min(maxUploadSize, e.loaded);
|
|
|
|
this$1.uploadedSize += loaded - uploadedSize;
|
|
uploadedSize = loaded;
|
|
|
|
var size = uploadedSize - uploadIndexSize;
|
|
for (var i = uploadIndex; size > 0 && i < files.length; i++) {
|
|
var
|
|
file = files[i],
|
|
uploaded = size > file.size;
|
|
|
|
if (uploaded) {
|
|
size -= file.size;
|
|
uploadIndex++;
|
|
uploadIndexSize += file.size;
|
|
this$1.__updateFile(file, 'uploading', file.size);
|
|
}
|
|
else {
|
|
this$1.__updateFile(file, 'uploading', size);
|
|
return
|
|
}
|
|
}
|
|
}, false);
|
|
|
|
xhr.onreadystatechange = function () {
|
|
if (xhr.readyState < 4) {
|
|
return
|
|
}
|
|
|
|
if (xhr.status && xhr.status < 400) {
|
|
this$1.uploadedFiles = this$1.uploadedFiles.concat(files);
|
|
files.forEach(function (f) { this$1.__updateFile(f, 'uploaded'); });
|
|
this$1.$emit('uploaded', { files: files, xhr: xhr });
|
|
}
|
|
else {
|
|
aborted = true;
|
|
this$1.uploadedSize -= uploadedSize;
|
|
this$1.queuedFiles = this$1.queuedFiles.concat(files);
|
|
files.forEach(function (f) { this$1.__updateFile(f, 'failed'); });
|
|
this$1.$emit('failed', { files: files, xhr: xhr });
|
|
}
|
|
|
|
this$1.workingThreads--;
|
|
this$1.xhrs = this$1.xhrs.filter(function (x) { return x !== xhr; });
|
|
};
|
|
|
|
xhr.open(
|
|
getProp('method', files),
|
|
url
|
|
);
|
|
|
|
if (getProp('withCredentials', files) === true) {
|
|
xhr.withCredentials = true;
|
|
}
|
|
|
|
var headers = getProp('headers', files);
|
|
headers !== void 0 && headers.forEach(function (head) {
|
|
xhr.setRequestHeader(head.name, head.value);
|
|
});
|
|
|
|
var sendRaw = getProp('sendRaw', files);
|
|
|
|
files.forEach(function (file) {
|
|
this$1.__updateFile(file, 'uploading', 0);
|
|
if (sendRaw !== true) {
|
|
form.append(getProp('fieldName', file), file, file.name);
|
|
}
|
|
file.xhr = xhr;
|
|
file.__abort = function () { xhr.abort(); };
|
|
maxUploadSize += file.size;
|
|
});
|
|
|
|
this.$emit('uploading', { files: files, xhr: xhr });
|
|
this.xhrs.push(xhr);
|
|
|
|
if (sendRaw === true) {
|
|
xhr.send(new Blob(files));
|
|
}
|
|
else {
|
|
xhr.send(form);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
var QUploader = Vue.extend({
|
|
name: 'QUploader',
|
|
mixins: [ QUploaderBase, UploaderXHRMixin ]
|
|
});
|
|
|
|
var QUploaderAddTrigger = Vue.extend({
|
|
name: 'QUploaderAddTrigger',
|
|
|
|
inject: {
|
|
__qUploaderGetInput: {
|
|
default: function default$1 () {
|
|
console.error('QUploaderAddTrigger needs to be child of QUploader');
|
|
}
|
|
}
|
|
},
|
|
|
|
render: function render (h) {
|
|
return this.__qUploaderGetInput(h)
|
|
}
|
|
});
|
|
|
|
var QVideo = Vue.extend({
|
|
name: 'QVideo',
|
|
|
|
mixins: [ RatioMixin, ListenersMixin ],
|
|
|
|
props: {
|
|
src: {
|
|
type: String,
|
|
required: true
|
|
}
|
|
},
|
|
|
|
computed: {
|
|
iframeData: function iframeData () {
|
|
return {
|
|
attrs: {
|
|
src: this.src,
|
|
frameborder: '0',
|
|
allowfullscreen: true
|
|
}
|
|
}
|
|
},
|
|
|
|
classes: function classes () {
|
|
return 'q-video' +
|
|
(this.ratio !== void 0 ? ' q-video--responsive' : '')
|
|
}
|
|
},
|
|
|
|
render: function render (h) {
|
|
return h('div', {
|
|
class: this.classes,
|
|
style: this.ratioStyle,
|
|
on: Object.assign({}, this.qListeners)
|
|
}, [
|
|
h('iframe', this.iframeData)
|
|
])
|
|
}
|
|
});
|
|
|
|
|
|
|
|
var components$1 = /*#__PURE__*/Object.freeze({
|
|
__proto__: null,
|
|
QAjaxBar: QAjaxBar,
|
|
QAvatar: QAvatar,
|
|
QBadge: QBadge,
|
|
QBanner: QBanner,
|
|
QBar: QBar,
|
|
QBreadcrumbs: QBreadcrumbs,
|
|
QBreadcrumbsEl: QBreadcrumbsEl,
|
|
QBtn: QBtn,
|
|
QBtnDropdown: QBtnDropdown,
|
|
QBtnGroup: QBtnGroup,
|
|
QBtnToggle: QBtnToggle,
|
|
QCard: QCard,
|
|
QCardSection: QCardSection,
|
|
QCardActions: QCardActions,
|
|
QCarousel: QCarousel,
|
|
QCarouselSlide: QCarouselSlide,
|
|
QCarouselControl: QCarouselControl,
|
|
QChatMessage: QChatMessage,
|
|
QCheckbox: QCheckbox,
|
|
QChip: QChip,
|
|
QCircularProgress: QCircularProgress,
|
|
QColor: QColor,
|
|
QDate: QDate,
|
|
QDialog: QDialog,
|
|
QDrawer: QDrawer,
|
|
QEditor: QEditor,
|
|
QExpansionItem: QExpansionItem,
|
|
QFab: QFab,
|
|
QFabAction: QFabAction,
|
|
QField: QField,
|
|
QFile: QFile,
|
|
QFooter: QFooter,
|
|
QForm: QForm,
|
|
QHeader: QHeader,
|
|
QIcon: QIcon,
|
|
QImg: QImg,
|
|
QInfiniteScroll: QInfiniteScroll,
|
|
QInnerLoading: QInnerLoading,
|
|
QInput: QInput,
|
|
QIntersection: QIntersection,
|
|
QList: QList,
|
|
QItem: QItem,
|
|
QItemSection: QItemSection,
|
|
QItemLabel: QItemLabel,
|
|
QKnob: QKnob,
|
|
QLayout: QLayout,
|
|
QMarkupTable: QMarkupTable,
|
|
QMenu: QMenu,
|
|
QNoSsr: QNoSsr,
|
|
QOptionGroup: QOptionGroup,
|
|
QPage: QPage,
|
|
QPageContainer: QPageContainer,
|
|
QPageScroller: QPageScroller,
|
|
QPageSticky: QPageSticky,
|
|
QPagination: QPagination,
|
|
QParallax: QParallax,
|
|
QPopupEdit: QPopupEdit,
|
|
QPopupProxy: QPopupProxy,
|
|
QLinearProgress: QLinearProgress,
|
|
QPullToRefresh: QPullToRefresh,
|
|
QRadio: QRadio,
|
|
QRange: QRange,
|
|
QRating: QRating,
|
|
QResizeObserver: QResizeObserver,
|
|
QResponsive: QResponsive,
|
|
QScrollArea: QScrollArea,
|
|
QScrollObserver: QScrollObserver,
|
|
QSelect: QSelect,
|
|
QSeparator: QSeparator,
|
|
QSkeleton: QSkeleton,
|
|
QSlideItem: QSlideItem,
|
|
QSlideTransition: QSlideTransition,
|
|
QSlider: QSlider,
|
|
QSpace: QSpace,
|
|
QSpinner: QSpinner,
|
|
QSpinnerAudio: QSpinnerAudio,
|
|
QSpinnerBall: QSpinnerBall,
|
|
QSpinnerBars: QSpinnerBars,
|
|
QSpinnerComment: QSpinnerComment,
|
|
QSpinnerCube: QSpinnerCube,
|
|
QSpinnerDots: QSpinnerDots,
|
|
QSpinnerFacebook: QSpinnerFacebook,
|
|
QSpinnerGears: QSpinnerGears,
|
|
QSpinnerGrid: QSpinnerGrid,
|
|
QSpinnerHearts: QSpinnerHearts,
|
|
QSpinnerHourglass: QSpinnerHourglass,
|
|
QSpinnerInfinity: QSpinnerInfinity,
|
|
QSpinnerIos: QSpinnerIos,
|
|
QSpinnerOval: QSpinnerOval,
|
|
QSpinnerPie: QSpinnerPie,
|
|
QSpinnerPuff: QSpinnerPuff,
|
|
QSpinnerRadio: QSpinnerRadio,
|
|
QSpinnerRings: QSpinnerRings,
|
|
QSpinnerTail: QSpinnerTail,
|
|
QSplitter: QSplitter,
|
|
QStep: QStep,
|
|
QStepper: QStepper,
|
|
QStepperNavigation: QStepperNavigation,
|
|
QTabPanels: QTabPanels,
|
|
QTabPanel: QTabPanel,
|
|
QTable: QTable,
|
|
QTh: QTh,
|
|
QTr: QTr,
|
|
QTd: QTd,
|
|
QTabs: QTabs,
|
|
QTab: QTab,
|
|
QRouteTab: QRouteTab,
|
|
QTime: QTime,
|
|
QTimeline: QTimeline,
|
|
QTimelineEntry: QTimelineEntry,
|
|
QToggle: QToggle,
|
|
QToolbar: QToolbar,
|
|
QToolbarTitle: QToolbarTitle,
|
|
QTooltip: QTooltip,
|
|
QTree: QTree,
|
|
QUploader: QUploader,
|
|
QUploaderBase: QUploaderBase,
|
|
QUploaderAddTrigger: QUploaderAddTrigger,
|
|
QVideo: QVideo,
|
|
QVirtualScroll: QVirtualScroll
|
|
});
|
|
|
|
/*
|
|
* depth
|
|
* < 0 --> close all chain
|
|
* 0 --> disabled
|
|
* > 0 --> close chain up to N parent
|
|
*/
|
|
|
|
function getDepth (value) {
|
|
if (value === false) {
|
|
return 0
|
|
}
|
|
if (value === true || value === void 0) {
|
|
return 1
|
|
}
|
|
|
|
var depth = parseInt(value, 10);
|
|
return isNaN(depth) ? 0 : depth
|
|
}
|
|
|
|
function destroy$4 (el) {
|
|
var ctx = el.__qclosepopup;
|
|
if (ctx !== void 0) {
|
|
el.removeEventListener('click', ctx.handler);
|
|
el.removeEventListener('keyup', ctx.handlerKey);
|
|
delete el.__qclosepopup;
|
|
}
|
|
}
|
|
|
|
var ClosePopup = {
|
|
name: 'close-popup',
|
|
|
|
bind: function bind (el, ref, vnode) {
|
|
var value = ref.value;
|
|
|
|
if (el.__qclosepopup !== void 0) {
|
|
destroy$4(el);
|
|
el.__qclosepopup_destroyed = true;
|
|
}
|
|
|
|
var ctx = {
|
|
depth: getDepth(value),
|
|
|
|
handler: function handler (evt) {
|
|
// allow @click to be emitted
|
|
ctx.depth !== 0 && setTimeout(function () {
|
|
closePortals(vnode.componentInstance || vnode.context, evt, ctx.depth);
|
|
});
|
|
},
|
|
|
|
handlerKey: function handlerKey (evt) {
|
|
isKeyCode(evt, 13) === true && ctx.handler(evt);
|
|
}
|
|
};
|
|
|
|
el.__qclosepopup = ctx;
|
|
|
|
el.addEventListener('click', ctx.handler);
|
|
el.addEventListener('keyup', ctx.handlerKey);
|
|
},
|
|
|
|
update: function update (el, ref) {
|
|
var value = ref.value;
|
|
var oldValue = ref.oldValue;
|
|
|
|
if (el.__qclosepopup !== void 0 && value !== oldValue) {
|
|
el.__qclosepopup.depth = getDepth(value);
|
|
}
|
|
},
|
|
|
|
unbind: function unbind (el) {
|
|
if (el.__qclosepopup_destroyed === void 0) {
|
|
destroy$4(el);
|
|
}
|
|
else {
|
|
delete el.__qclosepopup_destroyed;
|
|
}
|
|
}
|
|
};
|
|
|
|
function destroy$5 (el) {
|
|
var ctx = el.__qgoback;
|
|
if (ctx !== void 0) {
|
|
el.removeEventListener('click', ctx.goBack);
|
|
el.removeEventListener('keyup', ctx.goBackKey);
|
|
delete el.__qgoback;
|
|
}
|
|
}
|
|
|
|
var GoBack = {
|
|
name: 'go-back',
|
|
|
|
bind: function bind (el, ref, vnode) {
|
|
var value = ref.value;
|
|
var modifiers = ref.modifiers;
|
|
|
|
if (el.__qgoback !== void 0) {
|
|
destroy$5(el);
|
|
el.__qgoback_destroyed = true;
|
|
}
|
|
|
|
var ctx = {
|
|
value: value,
|
|
|
|
position: window.history.length - 1,
|
|
single: modifiers.single,
|
|
|
|
goBack: function goBack () {
|
|
var router = vnode.context.$router;
|
|
|
|
if (ctx.single === true) {
|
|
router.go(-1);
|
|
}
|
|
else if (client.is.nativeMobile === true) {
|
|
router.go(ctx.position - window.history.length);
|
|
}
|
|
else {
|
|
router.replace(ctx.value);
|
|
}
|
|
},
|
|
|
|
goBackKey: function goBackKey (e) {
|
|
// if ENTER key
|
|
isKeyCode(e, 13) === true && ctx.goBack();
|
|
}
|
|
};
|
|
|
|
el.__qgoback = ctx;
|
|
|
|
el.addEventListener('click', ctx.goBack);
|
|
el.addEventListener('keyup', ctx.goBackKey);
|
|
},
|
|
|
|
update: function update (el, ref) {
|
|
var value = ref.value;
|
|
var oldValue = ref.oldValue;
|
|
|
|
var ctx = el.__qgoback;
|
|
|
|
if (ctx !== void 0 && value !== oldValue) {
|
|
ctx.value = value;
|
|
}
|
|
},
|
|
|
|
unbind: function unbind (el) {
|
|
if (el.__qgoback_destroyed === void 0) {
|
|
destroy$5(el);
|
|
}
|
|
else {
|
|
delete el.__qgoback_destroyed;
|
|
}
|
|
}
|
|
};
|
|
|
|
var id = 0;
|
|
var offsetBase = void 0;
|
|
|
|
function getAbsolutePosition (el, resize) {
|
|
if (offsetBase === void 0) {
|
|
offsetBase = document.createElement('div');
|
|
offsetBase.style.cssText = 'position: absolute; left: 0; top: 0';
|
|
document.body.appendChild(offsetBase);
|
|
}
|
|
|
|
var boundingRect = el.getBoundingClientRect();
|
|
var baseRect = offsetBase.getBoundingClientRect();
|
|
var ref = window.getComputedStyle(el);
|
|
var marginLeft = ref.marginLeft;
|
|
var marginRight = ref.marginRight;
|
|
var marginTop = ref.marginTop;
|
|
var marginBottom = ref.marginBottom;
|
|
var marginH = parseInt(marginLeft, 10) + parseInt(marginRight, 10);
|
|
var marginV = parseInt(marginTop, 10) + parseInt(marginBottom, 10);
|
|
|
|
return {
|
|
left: boundingRect.left - baseRect.left,
|
|
top: boundingRect.top - baseRect.top,
|
|
width: boundingRect.right - boundingRect.left,
|
|
height: boundingRect.bottom - boundingRect.top,
|
|
widthM: boundingRect.right - boundingRect.left + (resize === true ? 0 : marginH),
|
|
heightM: boundingRect.bottom - boundingRect.top + (resize === true ? 0 : marginV),
|
|
marginH: resize === true ? marginH : 0,
|
|
marginV: resize === true ? marginV : 0
|
|
}
|
|
}
|
|
|
|
function getAbsoluteSize (el) {
|
|
return {
|
|
width: el.scrollWidth,
|
|
height: el.scrollHeight
|
|
}
|
|
}
|
|
|
|
// firefox rulez
|
|
var styleEdges = [ 'Top', 'Right', 'Bottom', 'Left' ];
|
|
var styleBorderRadiuses = [ 'borderTopLeftRadius', 'borderTopRightRadius', 'borderBottomRightRadius', 'borderBottomLeftRadius' ];
|
|
|
|
function getComputedStyle$1 (el, props) {
|
|
var style = window.getComputedStyle(el);
|
|
var fixed = {};
|
|
for (var i = 0; i < props.length; i++) {
|
|
var prop = props[i];
|
|
|
|
if (style[prop] === '') {
|
|
if (prop === 'cssText') {
|
|
var styleLen = style.length;
|
|
var val = '';
|
|
|
|
for (var i$1 = 0; i$1 < styleLen; i$1++) {
|
|
val += style[i$1] + ': ' + style[style[i$1]] + '; ';
|
|
}
|
|
|
|
fixed[prop] = val;
|
|
}
|
|
else if ([ 'borderWidth', 'borderStyle', 'borderColor' ].indexOf(prop) > -1) {
|
|
var suffix = prop.replace('border', '');
|
|
var val$1 = '';
|
|
for (var j = 0; j < styleEdges.length; j++) {
|
|
var subProp = 'border' + styleEdges[j] + suffix;
|
|
val$1 += style[subProp] + ' ';
|
|
}
|
|
fixed[prop] = val$1;
|
|
}
|
|
else if (prop === 'borderRadius') {
|
|
var val1 = '';
|
|
var val2 = '';
|
|
for (var j$1 = 0; j$1 < styleBorderRadiuses.length; j$1++) {
|
|
var val$2 = style[styleBorderRadiuses[j$1]].split(' ');
|
|
val1 += val$2[0] + ' ';
|
|
val2 += (val$2[1] === void 0 ? val$2[0] : val$2[1]) + ' ';
|
|
}
|
|
fixed[prop] = val1 + '/ ' + val2;
|
|
}
|
|
else {
|
|
fixed[prop] = style[prop];
|
|
}
|
|
}
|
|
else {
|
|
fixed[prop] = style[prop];
|
|
}
|
|
}
|
|
|
|
return fixed
|
|
}
|
|
|
|
function normalizeElements (opts) {
|
|
return {
|
|
from: opts.from,
|
|
to: opts.to !== void 0
|
|
? opts.to
|
|
: opts.from
|
|
}
|
|
}
|
|
|
|
function normalizeOptions (options) {
|
|
if (typeof options === 'number') {
|
|
options = {
|
|
duration: options
|
|
};
|
|
}
|
|
else if (typeof options === 'function') {
|
|
options = {
|
|
onEnd: options
|
|
};
|
|
}
|
|
|
|
return Object.assign({}, options,
|
|
|
|
{waitFor: options.waitFor === void 0 ? 0 : options.waitFor,
|
|
|
|
duration: isNaN(options.duration) === true ? 300 : parseInt(options.duration, 10),
|
|
easing: typeof options.easing === 'string' && options.easing.length > 0 ? options.easing : 'ease-in-out',
|
|
delay: isNaN(options.delay) === true ? 0 : parseInt(options.delay, 10),
|
|
fill: typeof options.fill === 'string' && options.fill.length > 0 ? options.fill : 'none',
|
|
|
|
resize: options.resize === true,
|
|
useCSS: options.useCSS === true,
|
|
hideFromClone: options.hideFromClone === true,
|
|
keepToClone: options.keepToClone === true,
|
|
|
|
tween: options.tween === true,
|
|
tweenFromOpacity: isNaN(options.tweenFromOpacity) === true ? 0.6 : parseFloat(options.tweenFromOpacity),
|
|
tweenToOpacity: isNaN(options.tweenToOpacity) === true ? 0.5 : parseFloat(options.tweenToOpacity)})
|
|
}
|
|
|
|
function getElement (element) {
|
|
var type = typeof element;
|
|
|
|
return type === 'function'
|
|
? element()
|
|
: (
|
|
type === 'string'
|
|
? document.querySelector(element)
|
|
: element
|
|
)
|
|
}
|
|
|
|
function isValidElement (element) {
|
|
return element &&
|
|
element.ownerDocument === document &&
|
|
element.parentNode !== null
|
|
}
|
|
|
|
function morph (_options) {
|
|
var cancel = function () { return false; };
|
|
var cancelStatus = false;
|
|
var endElementTo = true;
|
|
|
|
var elements = normalizeElements(_options);
|
|
var options = normalizeOptions(_options);
|
|
|
|
var elFrom = getElement(elements.from);
|
|
if (isValidElement(elFrom) !== true) {
|
|
// we return a cancel function that return false, meaning the cancel function failed
|
|
return cancel
|
|
}
|
|
// we clean other morphs running on this element
|
|
typeof elFrom.qMorphCancel === 'function' && elFrom.qMorphCancel();
|
|
|
|
var animationFromClone = void 0;
|
|
var animationFromTween = void 0;
|
|
var animationToClone = void 0;
|
|
var animationTo = void 0;
|
|
|
|
var elFromParent = elFrom.parentNode;
|
|
var elFromNext = elFrom.nextElementSibling;
|
|
|
|
// we get the dimensions and characteristics
|
|
// of the parent of the initial element before changes
|
|
var elFromPosition = getAbsolutePosition(elFrom, options.resize);
|
|
var ref = getAbsoluteSize(elFromParent);
|
|
var elFromParentWidthBefore = ref.width;
|
|
var elFromParentHeightBefore = ref.height;
|
|
var ref$1 = getComputedStyle$1(elFrom, [ 'borderWidth', 'borderStyle', 'borderColor', 'borderRadius', 'backgroundColor', 'transform', 'position', 'cssText' ]);
|
|
var elFromBorderWidth = ref$1.borderWidth;
|
|
var elFromBorderStyle = ref$1.borderStyle;
|
|
var elFromBorderColor = ref$1.borderColor;
|
|
var elFromBorderRadius = ref$1.borderRadius;
|
|
var elFromBackground = ref$1.backgroundColor;
|
|
var elFromTransform = ref$1.transform;
|
|
var elFromPositioningType = ref$1.position;
|
|
var elFromCssText = ref$1.cssText;
|
|
var elFromClassSaved = elFrom.classList.toString();
|
|
var elFromStyleSaved = elFrom.style.cssText;
|
|
|
|
// we make a clone of the initial element and
|
|
// use it to display until the final element is ready
|
|
// and to change the occupied space during animation
|
|
var elFromClone = elFrom.cloneNode(true);
|
|
var elFromTween = options.tween === true ? elFrom.cloneNode(true) : void 0;
|
|
|
|
if (elFromTween !== void 0) {
|
|
elFromTween.className = elFromTween.classList.toString().split(' ').filter(function (c) { return /^bg-/.test(c) === false; }).join(' ');
|
|
}
|
|
|
|
// if the initial element is not going to be removed do not show the placeholder
|
|
options.hideFromClone === true && elFromClone.classList.add('q-morph--internal');
|
|
|
|
// prevent interaction with placeholder
|
|
elFromClone.setAttribute('aria-hidden', 'true');
|
|
elFromClone.style.transition = 'none';
|
|
elFromClone.style.animation = 'none';
|
|
elFromClone.style.pointerEvents = 'none';
|
|
elFromParent.insertBefore(elFromClone, elFromNext);
|
|
|
|
// we mark the element with its cleanup function
|
|
elFrom.qMorphCancel = function () {
|
|
cancelStatus = true;
|
|
|
|
// we clean the clone of the initial element
|
|
elFromClone.remove();
|
|
elFromTween !== void 0 && elFromTween.remove();
|
|
|
|
options.hideFromClone === true && elFromClone.classList.remove('q-morph--internal');
|
|
|
|
// we remove the cleanup function from the element
|
|
elFrom.qMorphCancel = void 0;
|
|
};
|
|
|
|
// will be called after Vue catches up with the changes done by _options.onToggle() function
|
|
var calculateFinalState = function () {
|
|
var elTo = getElement(elements.to);
|
|
if (cancelStatus === true || isValidElement(elTo) !== true) {
|
|
typeof elFrom.qMorphCancel === 'function' && elFrom.qMorphCancel();
|
|
|
|
return
|
|
}
|
|
// we clean other morphs running on this element
|
|
elFrom !== elTo && typeof elTo.qMorphCancel === 'function' && elTo.qMorphCancel();
|
|
|
|
// we hide the final element and the clone of the initial element
|
|
// we don't hide the final element if we want both it and the animated one visible
|
|
options.keepToClone !== true && elTo.classList.add('q-morph--internal');
|
|
elFromClone.classList.add('q-morph--internal');
|
|
|
|
// we get the dimensions of the parent of the initial element after changes
|
|
// the difference is how much we should animate the clone
|
|
var ref = getAbsoluteSize(elFromParent);
|
|
var elFromParentWidthAfter = ref.width;
|
|
var elFromParentHeightAfter = ref.height;
|
|
|
|
// we get the dimensions of the parent of the final element before changes
|
|
var ref$1 = getAbsoluteSize(elTo.parentNode);
|
|
var elToParentWidthBefore = ref$1.width;
|
|
var elToParentHeightBefore = ref$1.height;
|
|
|
|
// then we show the clone of the initial element if we don't want it hidden
|
|
options.hideFromClone !== true && elFromClone.classList.remove('q-morph--internal');
|
|
|
|
// we mark the element with its cleanup function
|
|
elTo.qMorphCancel = function () {
|
|
cancelStatus = true;
|
|
|
|
// we clean the clone of the initial element
|
|
elFromClone.remove();
|
|
elFromTween !== void 0 && elFromTween.remove();
|
|
|
|
options.hideFromClone === true && elFromClone.classList.remove('q-morph--internal');
|
|
|
|
// we show the final element
|
|
options.keepToClone !== true && elTo.classList.remove('q-morph--internal');
|
|
|
|
// we remove the cleanup function from the elements
|
|
elFrom.qMorphCancel = void 0;
|
|
elTo.qMorphCancel = void 0;
|
|
};
|
|
|
|
// will be called after waitFor (give time to render the final element)
|
|
var animate = function () {
|
|
if (cancelStatus === true) {
|
|
typeof elTo.qMorphCancel === 'function' && elTo.qMorphCancel();
|
|
|
|
return
|
|
}
|
|
|
|
// now the animation starts, so we only need the clone
|
|
// of the initial element as a spacer
|
|
// we also hide it to calculate the dimensions of the
|
|
// parent of the final element after the changes
|
|
if (options.hideFromClone !== true) {
|
|
elFromClone.classList.add('q-morph--internal');
|
|
elFromClone.innerHTML = '';
|
|
elFromClone.style.left = 0;
|
|
elFromClone.style.right = 'unset';
|
|
elFromClone.style.top = 0;
|
|
elFromClone.style.bottom = 'unset';
|
|
elFromClone.style.transform = 'none';
|
|
}
|
|
|
|
// we show the final element
|
|
if (options.keepToClone !== true) {
|
|
elTo.classList.remove('q-morph--internal');
|
|
}
|
|
|
|
// we get the dimensions of the parent of the final element after changes
|
|
// the difference is how much we should animate the clone
|
|
var elToParent = elTo.parentNode;
|
|
var ref = getAbsoluteSize(elToParent);
|
|
var elToParentWidthAfter = ref.width;
|
|
var elToParentHeightAfter = ref.height;
|
|
|
|
var elToClone = elTo.cloneNode(options.keepToClone);
|
|
elToClone.setAttribute('aria-hidden', 'true');
|
|
if (options.keepToClone !== true) {
|
|
elToClone.style.left = 0;
|
|
elToClone.style.right = 'unset';
|
|
elToClone.style.top = 0;
|
|
elToClone.style.bottom = 'unset';
|
|
elToClone.style.transform = 'none';
|
|
elToClone.style.pointerEvents = 'none';
|
|
}
|
|
elToClone.classList.add('q-morph--internal');
|
|
|
|
// if elFrom is the same as elTo the next element is elFromClone
|
|
var elToNext = elTo === elFrom && elFromParent === elToParent ? elFromClone : elTo.nextElementSibling;
|
|
elToParent.insertBefore(elToClone, elToNext);
|
|
|
|
var ref$1 = getComputedStyle$1(elTo, [ 'borderWidth', 'borderStyle', 'borderColor', 'borderRadius', 'backgroundColor', 'transform', 'position', 'cssText' ]);
|
|
var elToBorderWidth = ref$1.borderWidth;
|
|
var elToBorderStyle = ref$1.borderStyle;
|
|
var elToBorderColor = ref$1.borderColor;
|
|
var elToBorderRadius = ref$1.borderRadius;
|
|
var elToBackground = ref$1.backgroundColor;
|
|
var elToTransform = ref$1.transform;
|
|
var elToPositioningType = ref$1.position;
|
|
var elToCssText = ref$1.cssText;
|
|
var elToClassSaved = elTo.classList.toString();
|
|
var elToStyleSaved = elTo.style.cssText;
|
|
|
|
// we set the computed styles on the element (to be able to remove classes)
|
|
elTo.style.cssText = elToCssText;
|
|
elTo.style.transform = 'none';
|
|
elTo.style.animation = 'none';
|
|
elTo.style.transition = 'none';
|
|
// we strip the background classes (background color can no longer be animated if !important is used)
|
|
elTo.className = elToClassSaved.split(' ').filter(function (c) { return /^bg-/.test(c) === false; }).join(' ');
|
|
|
|
var elToPosition = getAbsolutePosition(elTo, options.resize);
|
|
|
|
var deltaX = elFromPosition.left - elToPosition.left;
|
|
var deltaY = elFromPosition.top - elToPosition.top;
|
|
var scaleX = elFromPosition.width / (elToPosition.width > 0 ? elToPosition.width : 10);
|
|
var scaleY = elFromPosition.height / (elToPosition.height > 0 ? elToPosition.height : 100);
|
|
|
|
var elFromParentWidthDiff = elFromParentWidthBefore - elFromParentWidthAfter;
|
|
var elFromParentHeightDiff = elFromParentHeightBefore - elFromParentHeightAfter;
|
|
var elToParentWidthDiff = elToParentWidthAfter - elToParentWidthBefore;
|
|
var elToParentHeightDiff = elToParentHeightAfter - elToParentHeightBefore;
|
|
|
|
var elFromCloneWidth = Math.max(elFromPosition.widthM, elFromParentWidthDiff);
|
|
var elFromCloneHeight = Math.max(elFromPosition.heightM, elFromParentHeightDiff);
|
|
var elToCloneWidth = Math.max(elToPosition.widthM, elToParentWidthDiff);
|
|
var elToCloneHeight = Math.max(elToPosition.heightM, elToParentHeightDiff);
|
|
|
|
var elSharedSize = elFrom === elTo &&
|
|
[ 'absolute', 'fixed' ].includes(elToPositioningType) === false &&
|
|
[ 'absolute', 'fixed' ].includes(elFromPositioningType) === false;
|
|
|
|
// if the final element has fixed position or if a parent
|
|
// has fixed position we need to animate it as fixed
|
|
var elToNeedsFixedPosition = elToPositioningType === 'fixed';
|
|
var parent = elToParent;
|
|
while (elToNeedsFixedPosition !== true && parent !== document) {
|
|
elToNeedsFixedPosition = window.getComputedStyle(parent).position === 'fixed';
|
|
parent = parent.parentNode;
|
|
}
|
|
|
|
// we show the spacer for the initial element
|
|
if (options.hideFromClone !== true) {
|
|
elFromClone.style.display = 'block';
|
|
elFromClone.style.flex = '0 0 auto';
|
|
elFromClone.style.opacity = 0;
|
|
elFromClone.style.minWidth = 'unset';
|
|
elFromClone.style.maxWidth = 'unset';
|
|
elFromClone.style.minHeight = 'unset';
|
|
elFromClone.style.maxHeight = 'unset';
|
|
elFromClone.classList.remove('q-morph--internal');
|
|
}
|
|
|
|
// we show the spacer for the final element
|
|
if (options.keepToClone !== true) {
|
|
elToClone.style.display = 'block';
|
|
elToClone.style.flex = '0 0 auto';
|
|
elToClone.style.opacity = 0;
|
|
elToClone.style.minWidth = 'unset';
|
|
elToClone.style.maxWidth = 'unset';
|
|
elToClone.style.minHeight = 'unset';
|
|
elToClone.style.maxHeight = 'unset';
|
|
}
|
|
elToClone.classList.remove('q-morph--internal');
|
|
|
|
// we apply classes specified by user
|
|
if (typeof options.classes === 'string') {
|
|
elTo.className += ' ' + options.classes;
|
|
}
|
|
|
|
// we apply styles specified by user
|
|
if (typeof options.style === 'string') {
|
|
elTo.style.cssText += ' ' + options.style;
|
|
}
|
|
else if (options.style === Object(options.style)) {
|
|
for (var prop in options.style) {
|
|
elTo.style[prop] = options.style[prop];
|
|
}
|
|
}
|
|
|
|
// we position the morphing element
|
|
// if we use fixed position for the final element we need to adjust for scroll
|
|
var documentScroll = elToNeedsFixedPosition === true
|
|
? document.documentElement
|
|
: { scrollLeft: 0, scrollTop: 0 };
|
|
elTo.style.position = elToNeedsFixedPosition === true ? 'fixed' : 'absolute';
|
|
elTo.style.left = (elToPosition.left - documentScroll.scrollLeft) + "px";
|
|
elTo.style.right = 'unset';
|
|
elTo.style.top = (elToPosition.top - documentScroll.scrollTop) + "px";
|
|
elTo.style.margin = 0;
|
|
|
|
if (options.resize === true) {
|
|
elTo.style.minWidth = 'unset';
|
|
elTo.style.maxWidth = 'unset';
|
|
elTo.style.minHeight = 'unset';
|
|
elTo.style.maxHeight = 'unset';
|
|
elTo.style.overflow = 'hidden';
|
|
elTo.style.overflowX = 'hidden';
|
|
elTo.style.overflowY = 'hidden';
|
|
}
|
|
|
|
document.body.appendChild(elTo);
|
|
|
|
if (elFromTween !== void 0) {
|
|
elFromTween.style.cssText = elFromCssText;
|
|
elFromTween.style.transform = 'none';
|
|
elFromTween.style.animation = 'none';
|
|
elFromTween.style.transition = 'none';
|
|
|
|
elFromTween.style.position = elTo.style.position;
|
|
elFromTween.style.left = (elFromPosition.left - documentScroll.scrollLeft) + "px";
|
|
elFromTween.style.right = 'unset';
|
|
elFromTween.style.top = (elFromPosition.top - documentScroll.scrollTop) + "px";
|
|
elFromTween.style.margin = 0;
|
|
elFromTween.style.pointerEvents = 'none';
|
|
|
|
if (options.resize === true) {
|
|
elFromTween.style.minWidth = 'unset';
|
|
elFromTween.style.maxWidth = 'unset';
|
|
elFromTween.style.minHeight = 'unset';
|
|
elFromTween.style.maxHeight = 'unset';
|
|
elFromTween.style.overflow = 'hidden';
|
|
elFromTween.style.overflowX = 'hidden';
|
|
elFromTween.style.overflowY = 'hidden';
|
|
}
|
|
|
|
document.body.appendChild(elFromTween);
|
|
}
|
|
|
|
var commonCleanup = function (aborted) {
|
|
// we put the element back in it's place
|
|
// and restore the styles and classes
|
|
if (elFrom === elTo && endElementTo !== true) {
|
|
elTo.style.cssText = elFromStyleSaved;
|
|
elTo.className = elFromClassSaved;
|
|
}
|
|
else {
|
|
elTo.style.cssText = elToStyleSaved;
|
|
elTo.className = elToClassSaved;
|
|
}
|
|
elToClone.parentNode === elToParent && elToParent.insertBefore(elTo, elToClone);
|
|
|
|
// we clean the spacers
|
|
elFromClone.remove();
|
|
elToClone.remove();
|
|
elFromTween !== void 0 && elFromTween.remove();
|
|
|
|
// cancel will be no longer available
|
|
cancel = function () { return false; };
|
|
|
|
elFrom.qMorphCancel = void 0;
|
|
elTo.qMorphCancel = void 0;
|
|
|
|
// we are ready
|
|
if (typeof options.onEnd === 'function') {
|
|
options.onEnd(endElementTo === true ? 'to' : 'from', aborted === true);
|
|
}
|
|
};
|
|
|
|
if (options.useCSS !== true && typeof elTo.animate === 'function') {
|
|
var resizeFrom = options.resize === true
|
|
? {
|
|
transform: ("translate(" + deltaX + "px, " + deltaY + "px)"),
|
|
width: (elFromCloneWidth + "px"),
|
|
height: (elFromCloneHeight + "px")
|
|
}
|
|
: {
|
|
transform: ("translate(" + deltaX + "px, " + deltaY + "px) scale(" + scaleX + ", " + scaleY + ")")
|
|
};
|
|
var resizeTo = options.resize === true
|
|
? {
|
|
width: (elToCloneWidth + "px"),
|
|
height: (elToCloneHeight + "px")
|
|
}
|
|
: {};
|
|
var resizeFromTween = options.resize === true
|
|
? {
|
|
width: (elFromCloneWidth + "px"),
|
|
height: (elFromCloneHeight + "px")
|
|
}
|
|
: {};
|
|
var resizeToTween = options.resize === true
|
|
? {
|
|
transform: ("translate(" + (-1 * deltaX) + "px, " + (-1 * deltaY) + "px)"),
|
|
width: (elToCloneWidth + "px"),
|
|
height: (elToCloneHeight + "px")
|
|
}
|
|
: {
|
|
transform: ("translate(" + (-1 * deltaX) + "px, " + (-1 * deltaY) + "px) scale(" + (1 / scaleX) + ", " + (1 / scaleY) + ")")
|
|
};
|
|
var tweenFrom = elFromTween !== void 0
|
|
? { opacity: options.tweenToOpacity }
|
|
: { backgroundColor: elFromBackground };
|
|
var tweenTo = elFromTween !== void 0
|
|
? { opacity: 1 }
|
|
: { backgroundColor: elToBackground };
|
|
animationTo = elTo.animate([
|
|
Object.assign({}, {margin: 0,
|
|
borderWidth: elFromBorderWidth,
|
|
borderStyle: elFromBorderStyle,
|
|
borderColor: elFromBorderColor,
|
|
borderRadius: elFromBorderRadius,
|
|
transformOrigin: '0 0'},
|
|
resizeFrom,
|
|
tweenFrom),
|
|
Object.assign({}, {margin: 0,
|
|
borderWidth: elToBorderWidth,
|
|
borderStyle: elToBorderStyle,
|
|
borderColor: elToBorderColor,
|
|
borderRadius: elToBorderRadius,
|
|
transformOrigin: '0 0',
|
|
transform: elToTransform},
|
|
resizeTo,
|
|
tweenTo)
|
|
], {
|
|
duration: options.duration,
|
|
easing: options.easing,
|
|
fill: options.fill,
|
|
delay: options.delay
|
|
});
|
|
|
|
animationFromTween = elFromTween === void 0 ? void 0 : elFromTween.animate([
|
|
Object.assign({}, {opacity: options.tweenFromOpacity,
|
|
margin: 0,
|
|
borderWidth: elFromBorderWidth,
|
|
borderStyle: elFromBorderStyle,
|
|
borderColor: elFromBorderColor,
|
|
borderRadius: elFromBorderRadius,
|
|
transformOrigin: '0 0',
|
|
transform: elFromTransform},
|
|
resizeFromTween),
|
|
Object.assign({}, {opacity: 0,
|
|
margin: 0,
|
|
borderWidth: elToBorderWidth,
|
|
borderStyle: elToBorderStyle,
|
|
borderColor: elToBorderColor,
|
|
borderRadius: elToBorderRadius,
|
|
transformOrigin: '0 0'},
|
|
resizeToTween)
|
|
], {
|
|
duration: options.duration,
|
|
easing: options.easing,
|
|
fill: options.fill,
|
|
delay: options.delay
|
|
});
|
|
|
|
animationFromClone = options.hideFromClone === true || elSharedSize === true ? void 0 : elFromClone.animate([
|
|
{
|
|
margin: ((elFromParentHeightDiff < 0 ? elFromParentHeightDiff / 2 : 0) + "px " + (elFromParentWidthDiff < 0 ? elFromParentWidthDiff / 2 : 0) + "px"),
|
|
width: ((elFromCloneWidth + elFromPosition.marginH) + "px"),
|
|
height: ((elFromCloneHeight + elFromPosition.marginV) + "px")
|
|
},
|
|
{
|
|
margin: 0,
|
|
width: 0,
|
|
height: 0
|
|
}
|
|
], {
|
|
duration: options.duration,
|
|
easing: options.easing,
|
|
fill: options.fill,
|
|
delay: options.delay
|
|
});
|
|
|
|
animationToClone = options.keepToClone === true ? void 0 : elToClone.animate([
|
|
elSharedSize === true
|
|
? {
|
|
margin: ((elFromParentHeightDiff < 0 ? elFromParentHeightDiff / 2 : 0) + "px " + (elFromParentWidthDiff < 0 ? elFromParentWidthDiff / 2 : 0) + "px"),
|
|
width: ((elFromCloneWidth + elFromPosition.marginH) + "px"),
|
|
height: ((elFromCloneHeight + elFromPosition.marginV) + "px")
|
|
}
|
|
: {
|
|
margin: 0,
|
|
width: 0,
|
|
height: 0
|
|
},
|
|
{
|
|
margin: ((elToParentHeightDiff < 0 ? elToParentHeightDiff / 2 : 0) + "px " + (elToParentWidthDiff < 0 ? elToParentWidthDiff / 2 : 0) + "px"),
|
|
width: ((elToCloneWidth + elToPosition.marginH) + "px"),
|
|
height: ((elToCloneHeight + elToPosition.marginV) + "px")
|
|
}
|
|
], {
|
|
duration: options.duration,
|
|
easing: options.easing,
|
|
fill: options.fill,
|
|
delay: options.delay
|
|
});
|
|
|
|
var cleanup = function (abort) {
|
|
animationFromClone !== void 0 && animationFromClone.cancel();
|
|
animationFromTween !== void 0 && animationFromTween.cancel();
|
|
animationToClone !== void 0 && animationToClone.cancel();
|
|
animationTo.cancel();
|
|
|
|
animationTo.removeEventListener('finish', cleanup);
|
|
animationTo.removeEventListener('cancel', cleanup);
|
|
|
|
commonCleanup(abort);
|
|
|
|
// we clean the animations
|
|
animationFromClone = void 0;
|
|
animationFromTween = void 0;
|
|
animationToClone = void 0;
|
|
animationTo = void 0;
|
|
};
|
|
|
|
elFrom.qMorphCancel = function () {
|
|
elFrom.qMorphCancel = void 0;
|
|
cancelStatus = true;
|
|
cleanup();
|
|
};
|
|
elTo.qMorphCancel = function () {
|
|
elTo.qMorphCancel = void 0;
|
|
cancelStatus = true;
|
|
cleanup();
|
|
};
|
|
|
|
animationTo.addEventListener('finish', cleanup);
|
|
animationTo.addEventListener('cancel', cleanup);
|
|
|
|
cancel = function (abort) {
|
|
// we are not in a morph that we can cancel
|
|
if (cancelStatus === true || animationTo === void 0) {
|
|
return false
|
|
}
|
|
|
|
if (abort === true) {
|
|
cleanup(true);
|
|
return true
|
|
}
|
|
|
|
endElementTo = endElementTo !== true;
|
|
|
|
animationFromClone !== void 0 && animationFromClone.reverse();
|
|
animationFromTween !== void 0 && animationFromTween.reverse();
|
|
animationToClone !== void 0 && animationToClone.reverse();
|
|
animationTo.reverse();
|
|
|
|
return true
|
|
};
|
|
}
|
|
else {
|
|
var qAnimId = "q-morph-anim-" + (++id);
|
|
var style = document.createElement('style');
|
|
var resizeFrom$1 = options.resize === true
|
|
? ("\n transform: translate(" + deltaX + "px, " + deltaY + "px);\n width: " + elFromCloneWidth + "px;\n height: " + elFromCloneHeight + "px;\n ")
|
|
: ("transform: translate(" + deltaX + "px, " + deltaY + "px) scale(" + scaleX + ", " + scaleY + ");");
|
|
var resizeTo$1 = options.resize === true
|
|
? ("\n width: " + elToCloneWidth + "px;\n height: " + elToCloneHeight + "px;\n ")
|
|
: '';
|
|
var resizeFromTween$1 = options.resize === true
|
|
? ("\n width: " + elFromCloneWidth + "px;\n height: " + elFromCloneHeight + "px;\n ")
|
|
: '';
|
|
var resizeToTween$1 = options.resize === true
|
|
? ("\n transform: translate(" + (-1 * deltaX) + "px, " + (-1 * deltaY) + "px);\n width: " + elToCloneWidth + "px;\n height: " + elToCloneHeight + "px;\n ")
|
|
: ("transform: translate(" + (-1 * deltaX) + "px, " + (-1 * deltaY) + "px) scale(" + (1 / scaleX) + ", " + (1 / scaleY) + ");");
|
|
var tweenFrom$1 = elFromTween !== void 0
|
|
? ("opacity: " + (options.tweenToOpacity) + ";")
|
|
: ("background-color: " + elFromBackground + ";");
|
|
var tweenTo$1 = elFromTween !== void 0
|
|
? 'opacity: 1;'
|
|
: ("background-color: " + elToBackground + ";");
|
|
var keyframesFromTween = elFromTween === void 0
|
|
? ''
|
|
: ("\n @keyframes " + qAnimId + "-from-tween {\n 0% {\n opacity: " + (options.tweenFromOpacity) + ";\n margin: 0;\n border-width: " + elFromBorderWidth + ";\n border-style: " + elFromBorderStyle + ";\n border-color: " + elFromBorderColor + ";\n border-radius: " + elFromBorderRadius + ";\n transform-origin: 0 0;\n transform: " + elFromTransform + ";\n " + resizeFromTween$1 + "\n }\n\n 100% {\n opacity: 0;\n margin: 0;\n border-width: " + elToBorderWidth + ";\n border-style: " + elToBorderStyle + ";\n border-color: " + elToBorderColor + ";\n border-radius: " + elToBorderRadius + ";\n transform-origin: 0 0;\n " + resizeToTween$1 + "\n }\n }\n ");
|
|
var keyframesFrom = options.hideFromClone === true || elSharedSize === true
|
|
? ''
|
|
: ("\n @keyframes " + qAnimId + "-from {\n 0% {\n margin: " + (elFromParentHeightDiff < 0 ? elFromParentHeightDiff / 2 : 0) + "px " + (elFromParentWidthDiff < 0 ? elFromParentWidthDiff / 2 : 0) + "px;\n width: " + (elFromCloneWidth + elFromPosition.marginH) + "px;\n height: " + (elFromCloneHeight + elFromPosition.marginV) + "px;\n }\n\n 100% {\n margin: 0;\n width: 0;\n height: 0;\n }\n }\n ");
|
|
var keyframeToStart = elSharedSize === true
|
|
? ("\n margin: " + (elFromParentHeightDiff < 0 ? elFromParentHeightDiff / 2 : 0) + "px " + (elFromParentWidthDiff < 0 ? elFromParentWidthDiff / 2 : 0) + "px;\n width: " + (elFromCloneWidth + elFromPosition.marginH) + "px;\n height: " + (elFromCloneHeight + elFromPosition.marginV) + "px;\n ")
|
|
: "\n margin: 0;\n width: 0;\n height: 0;\n ";
|
|
var keyframesTo = options.keepToClone === true
|
|
? ''
|
|
: ("\n @keyframes " + qAnimId + "-to {\n 0% {\n " + keyframeToStart + "\n }\n\n 100% {\n margin: " + (elToParentHeightDiff < 0 ? elToParentHeightDiff / 2 : 0) + "px " + (elToParentWidthDiff < 0 ? elToParentWidthDiff / 2 : 0) + "px;\n width: " + (elToCloneWidth + elToPosition.marginH) + "px;\n height: " + (elToCloneHeight + elToPosition.marginV) + "px;\n }\n }\n ");
|
|
style.innerHTML = "\n @keyframes " + qAnimId + " {\n 0% {\n margin: 0;\n border-width: " + elFromBorderWidth + ";\n border-style: " + elFromBorderStyle + ";\n border-color: " + elFromBorderColor + ";\n border-radius: " + elFromBorderRadius + ";\n background-color: " + elFromBackground + ";\n transform-origin: 0 0;\n " + resizeFrom$1 + "\n " + tweenFrom$1 + "\n }\n\n 100% {\n margin: 0;\n border-width: " + elToBorderWidth + ";\n border-style: " + elToBorderStyle + ";\n border-color: " + elToBorderColor + ";\n border-radius: " + elToBorderRadius + ";\n background-color: " + elToBackground + ";\n transform-origin: 0 0;\n transform: " + elToTransform + ";\n " + resizeTo$1 + "\n " + tweenTo$1 + "\n }\n }\n\n " + keyframesFrom + "\n\n " + keyframesFromTween + "\n\n " + keyframesTo + "\n ";
|
|
document.head.appendChild(style);
|
|
|
|
var animationDirection = 'normal';
|
|
|
|
elFromClone.style.animation = (options.duration) + "ms " + (options.easing) + " " + (options.delay) + "ms " + animationDirection + " " + (options.fill) + " " + qAnimId + "-from";
|
|
if (elFromTween !== void 0) {
|
|
elFromTween.style.animation = (options.duration) + "ms " + (options.easing) + " " + (options.delay) + "ms " + animationDirection + " " + (options.fill) + " " + qAnimId + "-from-tween";
|
|
}
|
|
elToClone.style.animation = (options.duration) + "ms " + (options.easing) + " " + (options.delay) + "ms " + animationDirection + " " + (options.fill) + " " + qAnimId + "-to";
|
|
elTo.style.animation = (options.duration) + "ms " + (options.easing) + " " + (options.delay) + "ms " + animationDirection + " " + (options.fill) + " " + qAnimId;
|
|
|
|
var cleanup$1 = function (ev) {
|
|
if (ev === Object(ev) && ev.animationName !== qAnimId) {
|
|
return
|
|
}
|
|
|
|
elTo.removeEventListener('animationend', cleanup$1);
|
|
elTo.removeEventListener('animationcancel', cleanup$1);
|
|
|
|
commonCleanup();
|
|
|
|
// we clean the animations
|
|
style.remove();
|
|
};
|
|
|
|
elFrom.qMorphCancel = function () {
|
|
elFrom.qMorphCancel = void 0;
|
|
cancelStatus = true;
|
|
cleanup$1();
|
|
};
|
|
elTo.qMorphCancel = function () {
|
|
elTo.qMorphCancel = void 0;
|
|
cancelStatus = true;
|
|
cleanup$1();
|
|
};
|
|
|
|
elTo.addEventListener('animationend', cleanup$1);
|
|
elTo.addEventListener('animationcancel', cleanup$1);
|
|
|
|
cancel = function (abort) {
|
|
// we are not in a morph that we can cancel
|
|
if (cancelStatus === true || !elTo || !elFromClone || !elToClone) {
|
|
return false
|
|
}
|
|
|
|
if (abort === true) {
|
|
cleanup$1();
|
|
|
|
return true
|
|
}
|
|
|
|
endElementTo = endElementTo !== true;
|
|
|
|
animationDirection = animationDirection === 'normal' ? 'reverse' : 'normal';
|
|
|
|
elFromClone.style.animationDirection = animationDirection;
|
|
elFromTween.style.animationDirection = animationDirection;
|
|
elToClone.style.animationDirection = animationDirection;
|
|
elTo.style.animationDirection = animationDirection;
|
|
|
|
return true
|
|
};
|
|
}
|
|
};
|
|
|
|
if (
|
|
options.waitFor > 0 ||
|
|
options.waitFor === 'transitionend' ||
|
|
(options.waitFor === Object(options.waitFor) && typeof options.waitFor.then === 'function')
|
|
) {
|
|
var delayPromise = options.waitFor > 0
|
|
? new Promise(function (resolve) { return setTimeout(resolve, options.waitFor); })
|
|
: (
|
|
options.waitFor === 'transitionend'
|
|
? new Promise(function (resolve) {
|
|
var timer = setTimeout(function () {
|
|
endFn();
|
|
}, 400);
|
|
|
|
var endFn = function (ev) {
|
|
clearTimeout(timer);
|
|
|
|
if (elTo) {
|
|
elTo.removeEventListener('transitionend', endFn);
|
|
elTo.removeEventListener('transitioncancel', endFn);
|
|
}
|
|
|
|
resolve();
|
|
};
|
|
|
|
elTo.addEventListener('transitionend', endFn);
|
|
elTo.addEventListener('transitioncancel', endFn);
|
|
})
|
|
: options.waitFor
|
|
);
|
|
|
|
delayPromise
|
|
.then(animate)
|
|
.catch(function () {
|
|
typeof elTo.qMorphCancel === 'function' && elTo.qMorphCancel();
|
|
});
|
|
}
|
|
else {
|
|
animate();
|
|
}
|
|
};
|
|
|
|
typeof _options.onToggle === 'function' && _options.onToggle();
|
|
requestAnimationFrame(calculateFinalState);
|
|
|
|
// we return the cancel function
|
|
// returns:
|
|
// false if the cancel cannot be performed (the morph ended already or has not started)
|
|
// true else
|
|
return function (abort) { return cancel(abort); }
|
|
}
|
|
|
|
var morphGroups = {};
|
|
var props = [
|
|
'duration', 'delay', 'easing', 'fill',
|
|
'classes', 'style', 'duration', 'resize',
|
|
'useCSS', 'hideFromClone', 'keepToClone', 'tween',
|
|
'tweenFromOpacity', 'tweenToOpacity',
|
|
'waitFor', 'onEnd'
|
|
];
|
|
var mods = [
|
|
'resize', 'useCSS', 'hideFromClone', 'keepToClone', 'tween'
|
|
];
|
|
|
|
function changeClass (ctx, action) {
|
|
if (ctx.clsAction !== action) {
|
|
ctx.clsAction = action;
|
|
ctx.el.classList[action]('q-morph--invisible');
|
|
}
|
|
}
|
|
|
|
function trigger (group) {
|
|
if (group.animating === true || group.queue.length < 2) {
|
|
return
|
|
}
|
|
|
|
var ref = group.queue;
|
|
var from = ref[0];
|
|
var to = ref[1];
|
|
|
|
group.animating = true;
|
|
from.animating = true;
|
|
to.animating = true;
|
|
|
|
changeClass(from, 'remove');
|
|
changeClass(to, 'remove');
|
|
|
|
var cancelFn = morph(Object.assign({}, {from: from.el,
|
|
to: to.el,
|
|
onToggle: function onToggle () {
|
|
changeClass(from, 'add');
|
|
changeClass(to, 'remove');
|
|
}},
|
|
to.opts,
|
|
{onEnd: function onEnd (dir, aborted) {
|
|
to.opts.onEnd !== void 0 && to.opts.onEnd(dir, aborted);
|
|
|
|
if (aborted === true) {
|
|
return
|
|
}
|
|
|
|
from.animating = false;
|
|
to.animating = false;
|
|
|
|
group.animating = false;
|
|
group.cancel = void 0;
|
|
group.queue.shift();
|
|
|
|
trigger(group);
|
|
}}));
|
|
|
|
group.cancel = function () {
|
|
cancelFn(true); // abort
|
|
group.cancel = void 0;
|
|
};
|
|
}
|
|
|
|
function updateModifiers$1 (mod, ctx) {
|
|
var opts = ctx.opts;
|
|
|
|
mods.forEach(function (name) {
|
|
opts[name] = mod[name] === true;
|
|
});
|
|
}
|
|
|
|
function insertArgs (arg, ctx) {
|
|
var opts = typeof arg === 'string' && arg.length > 0
|
|
? arg.split(':') : [];
|
|
|
|
ctx.name = opts[0];
|
|
ctx.group = opts[1];
|
|
|
|
Object.assign(ctx.opts, {
|
|
duration: isNaN(opts[2]) === true
|
|
? 300
|
|
: parseFloat(opts[2]),
|
|
waitFor: opts[3]
|
|
});
|
|
}
|
|
|
|
function updateArgs (arg, ctx) {
|
|
if (arg.group !== void 0) {
|
|
ctx.group = arg.group;
|
|
}
|
|
if (arg.name !== void 0) {
|
|
ctx.name = arg.name;
|
|
}
|
|
|
|
var opts = ctx.opts;
|
|
|
|
props.forEach(function (name) {
|
|
if (arg[name] !== void 0) {
|
|
opts[name] = arg[name];
|
|
}
|
|
});
|
|
}
|
|
|
|
function updateModel (name, ctx) {
|
|
if (ctx.name === name) {
|
|
var group = morphGroups[ctx.group];
|
|
|
|
// if group is not registered
|
|
if (group === void 0) {
|
|
morphGroups[ctx.group] = {
|
|
name: ctx.group,
|
|
model: name,
|
|
queue: [ ctx ],
|
|
animating: false
|
|
};
|
|
|
|
changeClass(ctx, 'remove');
|
|
}
|
|
// if model changed
|
|
else if (group.model !== name) {
|
|
group.model = name;
|
|
group.queue.push(ctx);
|
|
|
|
if (group.animating === false && group.queue.length === 2) {
|
|
trigger(group);
|
|
}
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
if (ctx.animating === false) {
|
|
changeClass(ctx, 'add');
|
|
}
|
|
}
|
|
|
|
function updateValue (ctx, value) {
|
|
var model;
|
|
|
|
if (Object(value) === value) {
|
|
model = '' + value.model;
|
|
updateArgs(value, ctx);
|
|
updateModifiers$1(value, ctx);
|
|
}
|
|
else {
|
|
model = '' + value;
|
|
}
|
|
|
|
if (model !== ctx.model) {
|
|
ctx.model = model;
|
|
updateModel(model, ctx);
|
|
}
|
|
else if (ctx.animating === false && ctx.clsAction !== void 0) {
|
|
// ensure HMR
|
|
ctx.el.classList[ctx.clsAction]('q-morph--invisible');
|
|
}
|
|
}
|
|
|
|
function destroy$6 (el) {
|
|
var ctx = el.__qmorph;
|
|
|
|
if (ctx !== void 0) {
|
|
var group = morphGroups[ctx.group];
|
|
|
|
if (group !== void 0) {
|
|
var index = group.queue.indexOf(ctx);
|
|
|
|
if (index !== -1) {
|
|
group.queue = group.queue.filter(function (item) { return item !== ctx; });
|
|
|
|
if (group.queue.length === 0) {
|
|
group.cancel !== void 0 && group.cancel();
|
|
delete morphGroups[ctx.group];
|
|
}
|
|
}
|
|
}
|
|
|
|
if (ctx.clsAction === 'add') {
|
|
el.classList.remove('q-morph--invisible');
|
|
}
|
|
|
|
delete el.__qmorph;
|
|
}
|
|
}
|
|
|
|
var Morph = {
|
|
name: 'morph',
|
|
|
|
inserted: function inserted (el, binding) {
|
|
if (el.__qmorph !== void 0) {
|
|
destroy$6(el);
|
|
el.__qmorph_destroyed = true;
|
|
}
|
|
|
|
var ctx = {
|
|
el: el,
|
|
animating: false,
|
|
opts: {}
|
|
};
|
|
|
|
updateModifiers$1(binding.modifiers, ctx);
|
|
insertArgs(binding.arg, ctx);
|
|
updateValue(ctx, binding.value);
|
|
|
|
el.__qmorph = ctx;
|
|
},
|
|
|
|
update: function update (el, binding) {
|
|
var ctx = el.__qmorph;
|
|
ctx !== void 0 && updateValue(ctx, binding.value);
|
|
},
|
|
|
|
unbind: function unbind (el) {
|
|
if (el.__qmorph_destroyed === void 0) {
|
|
destroy$6(el);
|
|
}
|
|
else {
|
|
delete el.__qmorph_destroyed;
|
|
}
|
|
}
|
|
};
|
|
|
|
function objectWithoutProperties (obj, exclude) { var target = {}; for (var k in obj) if (Object.prototype.hasOwnProperty.call(obj, k) && exclude.indexOf(k) === -1) target[k] = obj[k]; return target; }
|
|
var defaultCfg$1 = {
|
|
childList: true,
|
|
subtree: true,
|
|
attributes: true,
|
|
characterData: true,
|
|
attributeOldValue: true,
|
|
characterDataOldValue: true
|
|
};
|
|
|
|
function update$1 (el, ctx, value) {
|
|
ctx.handler = value;
|
|
ctx.observer !== void 0 && ctx.observer.disconnect();
|
|
|
|
ctx.observer = new MutationObserver(function (list) {
|
|
if (typeof ctx.handler === 'function') {
|
|
var res = ctx.handler(list);
|
|
if (res === false || ctx.once === true) {
|
|
destroy$7(el);
|
|
}
|
|
}
|
|
});
|
|
|
|
ctx.observer.observe(el, ctx.opts);
|
|
}
|
|
|
|
function destroy$7 (el) {
|
|
var ctx = el.__qmutation;
|
|
|
|
if (ctx !== void 0) {
|
|
ctx.observer !== void 0 && ctx.observer.disconnect();
|
|
delete el.__qmutation;
|
|
}
|
|
}
|
|
|
|
var Mutation = {
|
|
name: 'mutation',
|
|
|
|
inserted: function inserted (el, ref) {
|
|
var ref_modifiers = ref.modifiers;
|
|
var once = ref_modifiers.once;
|
|
var rest = objectWithoutProperties( ref_modifiers, ["once"] );
|
|
var mod = rest;
|
|
var value = ref.value;
|
|
|
|
if (el.__qmutation !== void 0) {
|
|
destroy$7(el);
|
|
el.__qmutation_destroyed = true;
|
|
}
|
|
|
|
var ctx = {
|
|
once: once,
|
|
opts: Object.keys(mod).length === 0
|
|
? defaultCfg$1
|
|
: mod
|
|
};
|
|
|
|
update$1(el, ctx, value);
|
|
|
|
el.__qmutation = ctx;
|
|
},
|
|
|
|
update: function update$1$1 (el, ref) {
|
|
var oldValue = ref.oldValue;
|
|
var value = ref.value;
|
|
|
|
var ctx = el.__qmutation;
|
|
if (ctx !== void 0 && oldValue !== value) {
|
|
update$1(el, ctx, value);
|
|
}
|
|
},
|
|
|
|
unbind: function unbind (el) {
|
|
if (el.__qmutation_destroyed === void 0) {
|
|
destroy$7(el);
|
|
}
|
|
else {
|
|
delete el.__qmutation_destroyed;
|
|
}
|
|
}
|
|
};
|
|
|
|
function update$2 (ctx, ref) {
|
|
var value = ref.value;
|
|
var oldValue = ref.oldValue;
|
|
|
|
if (typeof value !== 'function') {
|
|
ctx.scrollTarget.removeEventListener('scroll', ctx.scroll);
|
|
return
|
|
}
|
|
|
|
ctx.handler = value;
|
|
if (typeof oldValue !== 'function') {
|
|
ctx.scrollTarget.addEventListener('scroll', ctx.scroll, listenOpts.passive);
|
|
ctx.scroll();
|
|
}
|
|
}
|
|
|
|
function destroy$8 (el) {
|
|
var ctx = el.__qscrollfire;
|
|
if (ctx !== void 0) {
|
|
ctx.scrollTarget.removeEventListener('scroll', ctx.scroll, listenOpts.passive);
|
|
delete el.__qscrollfire;
|
|
}
|
|
}
|
|
|
|
var ScrollFire = {
|
|
name: 'scroll-fire',
|
|
|
|
inserted: function inserted (el, binding) {
|
|
if (el.__qscrollfire !== void 0) {
|
|
destroy$8(el);
|
|
el.__qscrollfire_destroyed = true;
|
|
}
|
|
|
|
var ctx = {
|
|
scrollTarget: getScrollTarget(el),
|
|
scroll: debounce(function () {
|
|
var containerBottom, elBottom;
|
|
|
|
if (ctx.scrollTarget === window) {
|
|
elBottom = el.getBoundingClientRect().bottom;
|
|
containerBottom = window.innerHeight;
|
|
}
|
|
else {
|
|
elBottom = offset(el).top + height(el);
|
|
containerBottom = offset(ctx.scrollTarget).top + height(ctx.scrollTarget);
|
|
}
|
|
|
|
if (elBottom > 0 && elBottom < containerBottom) {
|
|
ctx.scrollTarget.removeEventListener('scroll', ctx.scroll, listenOpts.passive);
|
|
ctx.handler(el);
|
|
}
|
|
}, 25)
|
|
};
|
|
|
|
update$2(ctx, binding);
|
|
|
|
el.__qscrollfire = ctx;
|
|
},
|
|
|
|
update: function update$1 (el, binding) {
|
|
if (el.__qscrollfire !== void 0 && binding.value !== binding.oldValue) {
|
|
update$2(el.__qscrollfire, binding);
|
|
}
|
|
},
|
|
|
|
unbind: function unbind (el) {
|
|
if (el.__qscrollfire_destroyed === void 0) {
|
|
destroy$8(el);
|
|
}
|
|
else {
|
|
delete el.__qscrollfire_destroyed;
|
|
}
|
|
}
|
|
};
|
|
|
|
function update$3 (ctx, ref) {
|
|
var value = ref.value;
|
|
var oldValue = ref.oldValue;
|
|
|
|
if (typeof value !== 'function') {
|
|
ctx.scrollTarget.removeEventListener('scroll', ctx.scroll, listenOpts.passive);
|
|
return
|
|
}
|
|
|
|
ctx.handler = value;
|
|
if (typeof oldValue !== 'function') {
|
|
ctx.scrollTarget.addEventListener('scroll', ctx.scroll, listenOpts.passive);
|
|
}
|
|
}
|
|
|
|
function destroy$9 (el) {
|
|
var ctx = el.__qscroll;
|
|
if (ctx !== void 0) {
|
|
ctx.scrollTarget.removeEventListener('scroll', ctx.scroll, listenOpts.passive);
|
|
delete el.__qscroll;
|
|
}
|
|
}
|
|
|
|
var Scroll = {
|
|
name: 'scroll',
|
|
|
|
inserted: function inserted (el, binding) {
|
|
if (el.__qscroll !== void 0) {
|
|
destroy$9(el);
|
|
el.__qscroll_destroyed = true;
|
|
}
|
|
|
|
var ctx = {
|
|
scrollTarget: getScrollTarget(el),
|
|
scroll: function scroll () {
|
|
ctx.handler(
|
|
getScrollPosition(ctx.scrollTarget),
|
|
getHorizontalScrollPosition(ctx.scrollTarget)
|
|
);
|
|
}
|
|
};
|
|
|
|
update$3(ctx, binding);
|
|
|
|
el.__qscroll = ctx;
|
|
},
|
|
|
|
update: function update$1 (el, binding) {
|
|
if (el.__qscroll !== void 0 && binding.oldValue !== binding.value) {
|
|
update$3(el.__qscroll, binding);
|
|
}
|
|
},
|
|
|
|
unbind: function unbind (el) {
|
|
if (el.__qscroll_destroyed === void 0) {
|
|
destroy$9(el);
|
|
}
|
|
else {
|
|
delete el.__qscroll_destroyed;
|
|
}
|
|
}
|
|
};
|
|
|
|
function destroy$a (el) {
|
|
var ctx = el.__qtouchhold;
|
|
if (ctx !== void 0) {
|
|
cleanEvt(ctx, 'main');
|
|
cleanEvt(ctx, 'temp');
|
|
|
|
clearTimeout(ctx.timer);
|
|
ctx.styleCleanup !== void 0 && ctx.styleCleanup();
|
|
|
|
delete el.__qtouchhold;
|
|
}
|
|
}
|
|
|
|
var TouchHold = {
|
|
name: 'touch-hold',
|
|
|
|
bind: function bind (el, binding) {
|
|
var assign;
|
|
|
|
if (el.__qtouchhold !== void 0) {
|
|
destroy$a(el);
|
|
el.__qtouchhold_destroyed = true;
|
|
}
|
|
|
|
var modifiers = binding.modifiers;
|
|
|
|
// early return, we don't need to do anything
|
|
if (modifiers.mouse !== true && client.has.touch !== true) {
|
|
return
|
|
}
|
|
|
|
var ctx = {
|
|
handler: binding.value,
|
|
noop: noop,
|
|
|
|
mouseStart: function mouseStart (evt) {
|
|
if (typeof ctx.handler === 'function' && leftClick(evt) === true) {
|
|
addEvt(ctx, 'temp', [
|
|
[ document, 'mousemove', 'move', 'passiveCapture' ],
|
|
[ document, 'click', 'end', 'notPassiveCapture' ]
|
|
]);
|
|
ctx.start(evt, true);
|
|
}
|
|
},
|
|
|
|
touchStart: function touchStart (evt) {
|
|
if (evt.target !== void 0 && typeof ctx.handler === 'function') {
|
|
var target = getTouchTarget(evt.target);
|
|
addEvt(ctx, 'temp', [
|
|
[ target, 'touchmove', 'move', 'passiveCapture' ],
|
|
[ target, 'touchcancel', 'end', 'notPassiveCapture' ],
|
|
[ target, 'touchend', 'end', 'notPassiveCapture' ]
|
|
]);
|
|
ctx.start(evt);
|
|
}
|
|
},
|
|
|
|
start: function start (evt, mouseEvent) {
|
|
ctx.origin = position(evt);
|
|
|
|
var startTime = Date.now();
|
|
|
|
if (client.is.mobile === true) {
|
|
document.body.classList.add('non-selectable');
|
|
clearSelection();
|
|
|
|
ctx.styleCleanup = function (withDelay) {
|
|
ctx.styleCleanup = void 0;
|
|
|
|
var remove = function () {
|
|
document.body.classList.remove('non-selectable');
|
|
};
|
|
|
|
if (withDelay === true) {
|
|
clearSelection();
|
|
setTimeout(remove, 10);
|
|
}
|
|
else { remove(); }
|
|
};
|
|
}
|
|
|
|
ctx.triggered = false;
|
|
ctx.sensitivity = mouseEvent === true
|
|
? ctx.mouseSensitivity
|
|
: ctx.touchSensitivity;
|
|
|
|
ctx.timer = setTimeout(function () {
|
|
clearSelection();
|
|
ctx.triggered = true;
|
|
|
|
ctx.handler({
|
|
evt: evt,
|
|
touch: mouseEvent !== true,
|
|
mouse: mouseEvent === true,
|
|
position: ctx.origin,
|
|
duration: Date.now() - startTime
|
|
});
|
|
}, ctx.duration);
|
|
},
|
|
|
|
move: function move (evt) {
|
|
var ref = position(evt);
|
|
var top = ref.top;
|
|
var left = ref.left;
|
|
if (
|
|
Math.abs(left - ctx.origin.left) >= ctx.sensitivity ||
|
|
Math.abs(top - ctx.origin.top) >= ctx.sensitivity
|
|
) {
|
|
clearTimeout(ctx.timer);
|
|
}
|
|
},
|
|
|
|
end: function end (evt) {
|
|
cleanEvt(ctx, 'temp');
|
|
|
|
// delay needed otherwise selection still occurs
|
|
ctx.styleCleanup !== void 0 && ctx.styleCleanup(ctx.triggered);
|
|
|
|
if (ctx.triggered === true) {
|
|
evt !== void 0 && stopAndPrevent(evt);
|
|
}
|
|
else {
|
|
clearTimeout(ctx.timer);
|
|
}
|
|
}
|
|
};
|
|
|
|
// duration in ms, touch in pixels, mouse in pixels
|
|
var data = [600, 5, 7];
|
|
|
|
if (typeof binding.arg === 'string' && binding.arg.length > 0) {
|
|
binding.arg.split(':').forEach(function (val, index) {
|
|
var v = parseInt(val, 10);
|
|
v && (data[index] = v);
|
|
});
|
|
}
|
|
|
|
(assign = data, ctx.duration = assign[0], ctx.touchSensitivity = assign[1], ctx.mouseSensitivity = assign[2]);
|
|
|
|
el.__qtouchhold = ctx;
|
|
|
|
modifiers.mouse === true && addEvt(ctx, 'main', [
|
|
[ el, 'mousedown', 'mouseStart', ("passive" + (modifiers.mouseCapture === true ? 'Capture' : '')) ]
|
|
]);
|
|
|
|
client.has.touch === true && addEvt(ctx, 'main', [
|
|
[ el, 'touchstart', 'touchStart', ("passive" + (modifiers.capture === true ? 'Capture' : '')) ],
|
|
[ el, 'touchend', 'noop', 'notPassiveCapture' ]
|
|
]);
|
|
},
|
|
|
|
update: function update (el, binding) {
|
|
var ctx = el.__qtouchhold;
|
|
if (ctx !== void 0 && binding.oldValue !== binding.value) {
|
|
typeof binding.value !== 'function' && ctx.end();
|
|
ctx.handler = binding.value;
|
|
}
|
|
},
|
|
|
|
unbind: function unbind (el) {
|
|
if (el.__qtouchhold_destroyed === void 0) {
|
|
destroy$a(el);
|
|
}
|
|
else {
|
|
delete el.__qtouchhold_destroyed;
|
|
}
|
|
}
|
|
};
|
|
|
|
var
|
|
keyCodes$2 = {
|
|
esc: 27,
|
|
tab: 9,
|
|
enter: 13,
|
|
space: 32,
|
|
up: 38,
|
|
left: 37,
|
|
right: 39,
|
|
down: 40,
|
|
'delete': [8, 46]
|
|
},
|
|
keyRegex = new RegExp(("^([\\d+]+|" + (Object.keys(keyCodes$2).join('|')) + ")$"), 'i');
|
|
|
|
function shouldEnd (evt, origin) {
|
|
var ref = position(evt);
|
|
var top = ref.top;
|
|
var left = ref.left;
|
|
|
|
return Math.abs(left - origin.left) >= 7 ||
|
|
Math.abs(top - origin.top) >= 7
|
|
}
|
|
|
|
function destroy$b (el) {
|
|
var ctx = el.__qtouchrepeat;
|
|
if (ctx !== void 0) {
|
|
clearTimeout(ctx.timer);
|
|
|
|
cleanEvt(ctx, 'main');
|
|
cleanEvt(ctx, 'temp');
|
|
|
|
ctx.styleCleanup !== void 0 && ctx.styleCleanup();
|
|
|
|
delete el.__qtouchrepeat;
|
|
}
|
|
}
|
|
|
|
var TouchRepeat = {
|
|
name: 'touch-repeat',
|
|
|
|
bind: function bind (el, ref) {
|
|
var modifiers = ref.modifiers;
|
|
var value = ref.value;
|
|
var arg = ref.arg;
|
|
|
|
if (el.__qtouchrepeat !== void 0) {
|
|
destroy$b(el);
|
|
el.__qtouchrepeat_destroyed = true;
|
|
}
|
|
|
|
var keyboard = Object.keys(modifiers).reduce(function (acc, key) {
|
|
if (keyRegex.test(key) === true) {
|
|
var keyCode = isNaN(parseInt(key, 10)) ? keyCodes$2[key.toLowerCase()] : parseInt(key, 10);
|
|
keyCode >= 0 && acc.push(keyCode);
|
|
}
|
|
return acc
|
|
}, []);
|
|
|
|
// early return, we don't need to do anything
|
|
if (
|
|
modifiers.mouse !== true &&
|
|
client.has.touch !== true &&
|
|
keyboard.length === 0
|
|
) {
|
|
return
|
|
}
|
|
|
|
var durations = typeof arg === 'string' && arg.length > 0
|
|
? arg.split(':').map(function (val) { return parseInt(val, 10); })
|
|
: [0, 600, 300];
|
|
|
|
var durationsLast = durations.length - 1;
|
|
|
|
var ctx = {
|
|
keyboard: keyboard,
|
|
handler: value,
|
|
|
|
noop: noop,
|
|
|
|
mouseStart: function mouseStart (evt) {
|
|
if (ctx.event === void 0 && typeof ctx.handler === 'function' && leftClick(evt) === true) {
|
|
addEvt(ctx, 'temp', [
|
|
[ document, 'mousemove', 'move', 'passiveCapture' ],
|
|
[ document, 'click', 'end', 'notPassiveCapture' ]
|
|
]);
|
|
ctx.start(evt, true);
|
|
}
|
|
},
|
|
|
|
keyboardStart: function keyboardStart (evt) {
|
|
if (typeof ctx.handler === 'function' && isKeyCode(evt, keyboard) === true) {
|
|
if (durations[0] === 0 || ctx.event !== void 0) {
|
|
stopAndPrevent(evt);
|
|
el.focus();
|
|
if (ctx.event !== void 0) {
|
|
return
|
|
}
|
|
}
|
|
|
|
addEvt(ctx, 'temp', [
|
|
[ document, 'keyup', 'end', 'notPassiveCapture' ],
|
|
[ document, 'click', 'end', 'notPassiveCapture' ]
|
|
]);
|
|
ctx.start(evt, false, true);
|
|
}
|
|
},
|
|
|
|
touchStart: function touchStart (evt) {
|
|
if (evt.target !== void 0 && typeof ctx.handler === 'function') {
|
|
var target = getTouchTarget(evt.target);
|
|
addEvt(ctx, 'temp', [
|
|
[ target, 'touchmove', 'move', 'passiveCapture' ],
|
|
[ target, 'touchcancel', 'end', 'notPassiveCapture' ],
|
|
[ target, 'touchend', 'end', 'notPassiveCapture' ]
|
|
]);
|
|
ctx.start(evt);
|
|
}
|
|
},
|
|
|
|
start: function start (evt, mouseEvent, keyboardEvent) {
|
|
if (keyboardEvent !== true) {
|
|
ctx.origin = position(evt);
|
|
}
|
|
|
|
function styleCleanup (withDelay) {
|
|
ctx.styleCleanup = void 0;
|
|
|
|
document.documentElement.style.cursor = '';
|
|
|
|
var remove = function () {
|
|
document.body.classList.remove('non-selectable');
|
|
};
|
|
|
|
if (withDelay === true) {
|
|
clearSelection();
|
|
setTimeout(remove, 10);
|
|
}
|
|
else { remove(); }
|
|
}
|
|
|
|
if (client.is.mobile === true) {
|
|
document.body.classList.add('non-selectable');
|
|
clearSelection();
|
|
ctx.styleCleanup = styleCleanup;
|
|
}
|
|
|
|
ctx.event = {
|
|
touch: mouseEvent !== true && keyboardEvent !== true,
|
|
mouse: mouseEvent === true,
|
|
keyboard: keyboardEvent === true,
|
|
startTime: Date.now(),
|
|
repeatCount: 0
|
|
};
|
|
|
|
var fn = function () {
|
|
if (ctx.event === void 0) {
|
|
return
|
|
}
|
|
|
|
if (ctx.event.repeatCount === 0) {
|
|
ctx.event.evt = evt;
|
|
|
|
if (keyboardEvent === true) {
|
|
ctx.event.keyCode = evt.keyCode;
|
|
}
|
|
else {
|
|
ctx.event.position = position(evt);
|
|
}
|
|
|
|
if (client.is.mobile !== true) {
|
|
document.documentElement.style.cursor = 'pointer';
|
|
document.body.classList.add('non-selectable');
|
|
clearSelection();
|
|
ctx.styleCleanup = styleCleanup;
|
|
}
|
|
}
|
|
|
|
ctx.event.duration = Date.now() - ctx.event.startTime;
|
|
ctx.event.repeatCount += 1;
|
|
|
|
ctx.handler(ctx.event);
|
|
|
|
var index = durationsLast < ctx.event.repeatCount
|
|
? durationsLast
|
|
: ctx.event.repeatCount;
|
|
|
|
ctx.timer = setTimeout(fn, durations[index]);
|
|
};
|
|
|
|
if (durations[0] === 0) {
|
|
fn();
|
|
}
|
|
else {
|
|
ctx.timer = setTimeout(fn, durations[0]);
|
|
}
|
|
},
|
|
|
|
move: function move (evt) {
|
|
if (ctx.event !== void 0 && shouldEnd(evt, ctx.origin) === true) {
|
|
clearTimeout(ctx.timer);
|
|
}
|
|
},
|
|
|
|
end: function end (evt) {
|
|
if (ctx.event === void 0) {
|
|
return
|
|
}
|
|
|
|
ctx.styleCleanup !== void 0 && ctx.styleCleanup(true);
|
|
evt !== void 0 && ctx.event.repeatCount > 0 && stopAndPrevent(evt);
|
|
|
|
cleanEvt(ctx, 'temp');
|
|
clearTimeout(ctx.timer);
|
|
|
|
ctx.event = void 0;
|
|
}
|
|
};
|
|
|
|
el.__qtouchrepeat = ctx;
|
|
|
|
modifiers.mouse === true && addEvt(ctx, 'main', [
|
|
[ el, 'mousedown', 'mouseStart', ("passive" + (modifiers.mouseCapture === true ? 'Capture' : '')) ]
|
|
]);
|
|
|
|
client.has.touch === true && addEvt(ctx, 'main', [
|
|
[ el, 'touchstart', 'touchStart', ("passive" + (modifiers.capture === true ? 'Capture' : '')) ],
|
|
[ el, 'touchend', 'noop', 'notPassiveCapture' ]
|
|
]);
|
|
|
|
keyboard.length > 0 && addEvt(ctx, 'main', [
|
|
[ el, 'keydown', 'keyboardStart', ("notPassive" + (modifiers.keyCapture === true ? 'Capture' : '')) ]
|
|
]);
|
|
},
|
|
|
|
update: function update (el, ref) {
|
|
var oldValue = ref.oldValue;
|
|
var value = ref.value;
|
|
|
|
var ctx = el.__qtouchrepeat;
|
|
if (ctx !== void 0 && oldValue !== value) {
|
|
typeof value !== 'function' && ctx.end();
|
|
ctx.handler = value;
|
|
}
|
|
},
|
|
|
|
unbind: function unbind (el) {
|
|
if (el.__qtouchrepeat_destroyed === void 0) {
|
|
destroy$b(el);
|
|
}
|
|
else {
|
|
delete el.__qtouchrepeat_destroyed;
|
|
}
|
|
}
|
|
};
|
|
|
|
|
|
|
|
var directives = /*#__PURE__*/Object.freeze({
|
|
__proto__: null,
|
|
ClosePopup: ClosePopup,
|
|
GoBack: GoBack,
|
|
Intersection: Intersection,
|
|
Morph: Morph,
|
|
Mutation: Mutation,
|
|
Ripple: Ripple,
|
|
ScrollFire: ScrollFire,
|
|
Scroll: Scroll,
|
|
TouchHold: TouchHold,
|
|
TouchPan: TouchPan,
|
|
TouchRepeat: TouchRepeat,
|
|
TouchSwipe: TouchSwipe
|
|
});
|
|
|
|
var metaValue;
|
|
|
|
function getProp () {
|
|
if (Platform.is.winphone) {
|
|
return 'msapplication-navbutton-color'
|
|
}
|
|
if (Platform.is.safari) {
|
|
return 'apple-mobile-web-app-status-bar-style'
|
|
}
|
|
// Chrome, Firefox OS, Opera, Vivaldi
|
|
return 'theme-color'
|
|
}
|
|
|
|
function getMetaTag (v) {
|
|
var els = document.getElementsByTagName('META');
|
|
for (var i in els) {
|
|
if (els[i].name === v) {
|
|
return els[i]
|
|
}
|
|
}
|
|
}
|
|
|
|
function setColor (hexColor) {
|
|
if (metaValue === void 0) {
|
|
// cache it
|
|
metaValue = getProp();
|
|
}
|
|
|
|
var metaTag = getMetaTag(metaValue);
|
|
var newTag = metaTag === void 0;
|
|
|
|
if (newTag) {
|
|
metaTag = document.createElement('meta');
|
|
metaTag.setAttribute('name', metaValue);
|
|
}
|
|
|
|
metaTag.setAttribute('content', hexColor);
|
|
|
|
if (newTag) {
|
|
document.head.appendChild(metaTag);
|
|
}
|
|
}
|
|
|
|
var AddressbarColor = {
|
|
install: function install (ref) {
|
|
var $q = ref.$q;
|
|
var cfg = ref.cfg;
|
|
|
|
this.set = isSSR === false && Platform.is.mobile === true && (
|
|
Platform.is.nativeMobile === true ||
|
|
Platform.is.winphone === true || Platform.is.safari === true ||
|
|
Platform.is.webkit === true || Platform.is.vivaldi === true
|
|
)
|
|
? function (hexColor) {
|
|
var val = hexColor || getBrand('primary');
|
|
|
|
if (Platform.is.nativeMobile === true && window.StatusBar) {
|
|
window.StatusBar.backgroundColorByHexString(val);
|
|
}
|
|
else {
|
|
setColor(val);
|
|
}
|
|
}
|
|
: noop;
|
|
|
|
$q.addressbarColor = this;
|
|
|
|
cfg.addressbarColor && this.set(cfg.addressbarColor);
|
|
}
|
|
};
|
|
|
|
var prefixes = {};
|
|
|
|
// needed for consistency across browsers,
|
|
// including IE11 which does not return anything
|
|
function promisify (target, fn) {
|
|
try {
|
|
var res = target[fn]();
|
|
return res === void 0
|
|
? Promise.resolve()
|
|
: res
|
|
}
|
|
catch (err) {
|
|
return Promise.reject(err)
|
|
}
|
|
}
|
|
|
|
var AppFullscreen = {
|
|
isCapable: false,
|
|
isActive: false,
|
|
activeEl: null,
|
|
|
|
request: function request (target) {
|
|
var this$1 = this;
|
|
|
|
if (this.isCapable === true && this.isActive === false) {
|
|
var el = target || document.documentElement;
|
|
return promisify(el, prefixes.request).then(function () {
|
|
this$1.activeEl = el;
|
|
})
|
|
}
|
|
|
|
return this.__getErr()
|
|
},
|
|
|
|
exit: function exit () {
|
|
var this$1 = this;
|
|
|
|
return this.isCapable === true && this.isActive === true
|
|
? promisify(document, prefixes.exit).then(function () {
|
|
this$1.activeEl = null;
|
|
})
|
|
: this.__getErr()
|
|
},
|
|
|
|
toggle: function toggle (target) {
|
|
return this.isActive === true
|
|
? this.exit()
|
|
: this.request(target)
|
|
},
|
|
|
|
install: function install (ref) {
|
|
var this$1 = this;
|
|
var $q = ref.$q;
|
|
|
|
$q.fullscreen = this;
|
|
|
|
if (isSSR === true) { return }
|
|
|
|
prefixes.request = [
|
|
'requestFullscreen',
|
|
'msRequestFullscreen', 'mozRequestFullScreen', 'webkitRequestFullscreen'
|
|
].find(function (request) { return document.documentElement[request] !== void 0; });
|
|
|
|
this.isCapable = prefixes.request !== void 0;
|
|
|
|
if (this.isCapable === false) {
|
|
// it means the browser does NOT support it
|
|
this.__getErr = function () { return Promise.reject('Not capable'); };
|
|
return
|
|
}
|
|
|
|
this.__getErr = function () { return Promise.resolve(); };
|
|
|
|
prefixes.exit = [
|
|
'exitFullscreen',
|
|
'msExitFullscreen', 'mozCancelFullScreen', 'webkitExitFullscreen'
|
|
].find(function (exit) { return document[exit]; });
|
|
|
|
this.isActive = !!(document.fullscreenElement ||
|
|
document.mozFullScreenElement ||
|
|
document.webkitFullscreenElement ||
|
|
document.msFullscreenElement)
|
|
|
|
;[
|
|
'onfullscreenchange',
|
|
'onmsfullscreenchange', 'onwebkitfullscreenchange'
|
|
].forEach(function (evt) {
|
|
document[evt] = function () {
|
|
this$1.isActive = this$1.isActive === false;
|
|
};
|
|
});
|
|
|
|
Vue.util.defineReactive(this, 'isActive', this.isActive);
|
|
Vue.util.defineReactive(this, 'activeEl', this.activeEl);
|
|
}
|
|
};
|
|
|
|
var AppVisibility = {
|
|
appVisible: false,
|
|
|
|
install: function install (ref) {
|
|
var this$1 = this;
|
|
var $q = ref.$q;
|
|
|
|
if (isSSR === true) {
|
|
this.appVisible = $q.appVisible = true;
|
|
return
|
|
}
|
|
|
|
var prop, evt;
|
|
|
|
if (typeof document.hidden !== 'undefined') { // Opera 12.10 and Firefox 18 and later support
|
|
prop = 'hidden';
|
|
evt = 'visibilitychange';
|
|
}
|
|
else if (typeof document.msHidden !== 'undefined') {
|
|
prop = 'msHidden';
|
|
evt = 'msvisibilitychange';
|
|
}
|
|
else if (typeof document.webkitHidden !== 'undefined') {
|
|
prop = 'webkitHidden';
|
|
evt = 'webkitvisibilitychange';
|
|
}
|
|
|
|
var update = function () {
|
|
this$1.appVisible = $q.appVisible = !document[prop];
|
|
};
|
|
|
|
update();
|
|
|
|
if (evt && typeof document[prop] !== 'undefined') {
|
|
Vue.util.defineReactive($q, 'appVisible', this.appVisible);
|
|
document.addEventListener(evt, update, false);
|
|
}
|
|
}
|
|
};
|
|
|
|
var BottomSheet = Vue.extend({
|
|
name: 'BottomSheetPlugin',
|
|
|
|
mixins: [ DarkMixin, AttrsMixin ],
|
|
|
|
inheritAttrs: false,
|
|
|
|
props: {
|
|
title: String,
|
|
message: String,
|
|
actions: Array,
|
|
|
|
grid: Boolean,
|
|
|
|
cardClass: [String, Array, Object],
|
|
cardStyle: [String, Array, Object]
|
|
},
|
|
|
|
computed: {
|
|
dialogProps: function dialogProps () {
|
|
return Object.assign({}, this.qAttrs,
|
|
{position: 'bottom'})
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
show: function show () {
|
|
this.$refs.dialog.show();
|
|
},
|
|
|
|
hide: function hide () {
|
|
this.$refs.dialog.hide();
|
|
},
|
|
|
|
onOk: function onOk (action) {
|
|
this.$emit('ok', action);
|
|
this.hide();
|
|
},
|
|
|
|
__getGrid: function __getGrid (h) {
|
|
var this$1 = this;
|
|
|
|
return this.actions.map(function (action) {
|
|
var img = action.avatar || action.img;
|
|
|
|
return action.label === void 0
|
|
? h(QSeparator, {
|
|
staticClass: 'col-all',
|
|
props: { dark: this$1.isDark }
|
|
})
|
|
: h('div', {
|
|
staticClass: 'q-bottom-sheet__item q-hoverable q-focusable cursor-pointer relative-position',
|
|
class: action.classes,
|
|
attrs: { tabindex: 0 },
|
|
on: {
|
|
click: function () { return this$1.onOk(action); },
|
|
keyup: function (e) {
|
|
e.keyCode === 13 && this$1.onOk(action);
|
|
}
|
|
}
|
|
}, [
|
|
h('div', { staticClass: 'q-focus-helper' }),
|
|
|
|
action.icon
|
|
? h(QIcon, { props: { name: action.icon, color: action.color } })
|
|
: (
|
|
img
|
|
? h('img', {
|
|
attrs: { src: img },
|
|
staticClass: action.avatar ? 'q-bottom-sheet__avatar' : null
|
|
})
|
|
: h('div', { staticClass: 'q-bottom-sheet__empty-icon' })
|
|
),
|
|
|
|
h('div', [ action.label ])
|
|
])
|
|
})
|
|
},
|
|
|
|
__getList: function __getList (h) {
|
|
var this$1 = this;
|
|
|
|
return this.actions.map(function (action) {
|
|
var img = action.avatar || action.img;
|
|
|
|
return action.label === void 0
|
|
? h(QSeparator, { props: { spaced: true, dark: this$1.isDark } })
|
|
: h(QItem, {
|
|
staticClass: 'q-bottom-sheet__item',
|
|
class: action.classes,
|
|
props: {
|
|
tabindex: 0,
|
|
clickable: true,
|
|
dark: this$1.isDark
|
|
},
|
|
on: {
|
|
click: function () { return this$1.onOk(action); },
|
|
keyup: function (e) {
|
|
e.keyCode === 13 && this$1.onOk(action);
|
|
}
|
|
}
|
|
}, [
|
|
h(QItemSection, { props: { avatar: true } }, [
|
|
action.icon
|
|
? h(QIcon, { props: { name: action.icon, color: action.color } })
|
|
: (
|
|
img
|
|
? h('img', {
|
|
attrs: { src: img },
|
|
staticClass: action.avatar ? 'q-bottom-sheet__avatar' : null
|
|
})
|
|
: null
|
|
)
|
|
]),
|
|
h(QItemSection, [ action.label ])
|
|
])
|
|
})
|
|
}
|
|
},
|
|
|
|
render: function render (h) {
|
|
var this$1 = this;
|
|
|
|
var child = [];
|
|
|
|
this.title && child.push(
|
|
h(QCardSection, {
|
|
staticClass: 'q-dialog__title'
|
|
}, [ this.title ])
|
|
);
|
|
|
|
this.message && child.push(
|
|
h(QCardSection, {
|
|
staticClass: 'q-dialog__message'
|
|
}, [ this.message ])
|
|
);
|
|
|
|
child.push(
|
|
this.grid === true
|
|
? h('div', {
|
|
staticClass: 'row items-stretch justify-start'
|
|
}, this.__getGrid(h))
|
|
: h('div', this.__getList(h))
|
|
);
|
|
|
|
return h(QDialog, {
|
|
ref: 'dialog',
|
|
props: this.dialogProps,
|
|
on: cache(this, 'hide', {
|
|
hide: function () {
|
|
this$1.$emit('hide');
|
|
}
|
|
})
|
|
}, [
|
|
h(QCard, {
|
|
staticClass: "q-bottom-sheet q-bottom-sheet--" + (this.grid === true ? 'grid' : 'list') +
|
|
(this.isDark === true ? ' q-bottom-sheet--dark q-dark' : ''),
|
|
style: this.cardStyle,
|
|
class: this.cardClass
|
|
}, child)
|
|
])
|
|
}
|
|
});
|
|
|
|
function objectWithoutProperties$1 (obj, exclude) { var target = {}; for (var k in obj) if (Object.prototype.hasOwnProperty.call(obj, k) && exclude.indexOf(k) === -1) target[k] = obj[k]; return target; }
|
|
|
|
var ssrAPI = {
|
|
onOk: function () { return ssrAPI; },
|
|
okCancel: function () { return ssrAPI; },
|
|
hide: function () { return ssrAPI; }
|
|
};
|
|
|
|
function globalDialog (DefaultComponent) {
|
|
return function (ref) {
|
|
var className = ref.className;
|
|
var klass = ref.class;
|
|
var style = ref.style;
|
|
var component = ref.component;
|
|
var root = ref.root;
|
|
var parent = ref.parent;
|
|
var rest = objectWithoutProperties$1( ref, ["className", "class", "style", "component", "root", "parent"] );
|
|
var props = rest;
|
|
|
|
if (isSSR === true) { return ssrAPI }
|
|
|
|
klass !== void 0 && (props.cardClass = klass);
|
|
style !== void 0 && (props.cardStyle = style);
|
|
|
|
var
|
|
okFns = [],
|
|
cancelFns = [],
|
|
API = {
|
|
onOk: function onOk (fn) {
|
|
okFns.push(fn);
|
|
return API
|
|
},
|
|
onCancel: function onCancel (fn) {
|
|
cancelFns.push(fn);
|
|
return API
|
|
},
|
|
onDismiss: function onDismiss (fn) {
|
|
okFns.push(fn);
|
|
cancelFns.push(fn);
|
|
return API
|
|
},
|
|
hide: function hide () {
|
|
vm.$refs.dialog.hide();
|
|
return API
|
|
}
|
|
};
|
|
|
|
var node = document.createElement('div');
|
|
document.body.appendChild(node);
|
|
|
|
var emittedOK = false;
|
|
|
|
var on = {
|
|
ok: function (data) {
|
|
emittedOK = true;
|
|
okFns.forEach(function (fn) { fn(data); });
|
|
},
|
|
|
|
hide: function () {
|
|
vm.$destroy();
|
|
vm.$el.remove();
|
|
vm = null;
|
|
|
|
if (emittedOK !== true) {
|
|
cancelFns.forEach(function (fn) { fn(); });
|
|
}
|
|
}
|
|
};
|
|
|
|
Vue.observable(props);
|
|
|
|
var DialogComponent = component !== void 0
|
|
? component
|
|
: DefaultComponent;
|
|
|
|
var attrs = component === void 0
|
|
? props
|
|
: void 0;
|
|
|
|
var vm = new Vue({
|
|
name: 'QGlobalDialog',
|
|
|
|
el: node,
|
|
parent: parent === void 0 ? root : parent,
|
|
|
|
render: function render (h) {
|
|
return h(DialogComponent, {
|
|
ref: 'dialog',
|
|
props: props,
|
|
attrs: attrs,
|
|
on: on
|
|
})
|
|
},
|
|
|
|
mounted: function mounted () {
|
|
this.$refs.dialog.show();
|
|
}
|
|
});
|
|
|
|
return API
|
|
}
|
|
}
|
|
|
|
var BottomSheet$1 = {
|
|
install: function install (ref) {
|
|
var $q = ref.$q;
|
|
|
|
this.create = $q.bottomSheet = globalDialog(BottomSheet);
|
|
}
|
|
};
|
|
|
|
function encode (string) {
|
|
return encodeURIComponent(string)
|
|
}
|
|
|
|
function decode (string) {
|
|
return decodeURIComponent(string)
|
|
}
|
|
|
|
function stringifyCookieValue (value) {
|
|
return encode(value === Object(value) ? JSON.stringify(value) : '' + value)
|
|
}
|
|
|
|
function read (string) {
|
|
if (string === '') {
|
|
return string
|
|
}
|
|
|
|
if (string.indexOf('"') === 0) {
|
|
// This is a quoted cookie as according to RFC2068, unescape...
|
|
string = string.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, '\\');
|
|
}
|
|
|
|
// Replace server-side written pluses with spaces.
|
|
// If we can't decode the cookie, ignore it, it's unusable.
|
|
// If we can't parse the cookie, ignore it, it's unusable.
|
|
string = decode(string.replace(/\+/g, ' '));
|
|
|
|
try {
|
|
string = JSON.parse(string);
|
|
}
|
|
catch (e) {}
|
|
|
|
return string
|
|
}
|
|
|
|
function getString (msOffset) {
|
|
var time = new Date();
|
|
time.setMilliseconds(time.getMilliseconds() + msOffset);
|
|
return time.toUTCString()
|
|
}
|
|
|
|
function parseExpireString (str) {
|
|
var timestamp = 0;
|
|
|
|
var days = str.match(/(\d+)d/);
|
|
var hours = str.match(/(\d+)h/);
|
|
var minutes = str.match(/(\d+)m/);
|
|
var seconds = str.match(/(\d+)s/);
|
|
|
|
if (days) { timestamp += days[1] * 864e+5; }
|
|
if (hours) { timestamp += hours[1] * 36e+5; }
|
|
if (minutes) { timestamp += minutes[1] * 6e+4; }
|
|
if (seconds) { timestamp += seconds[1] * 1000; }
|
|
|
|
return timestamp === 0
|
|
? str
|
|
: getString(timestamp)
|
|
}
|
|
|
|
function set (key, val, opts, ssr) {
|
|
if ( opts === void 0 ) opts = {};
|
|
|
|
var expire, expireValue;
|
|
|
|
if (opts.expires !== void 0) {
|
|
// if it's a Date Object
|
|
if (Object.prototype.toString.call(opts.expires) === '[object Date]') {
|
|
expire = opts.expires.toUTCString();
|
|
}
|
|
// if it's a String (eg. "15m", "1h", "13d", "1d 15m", "31s")
|
|
// possible units: d (days), h (hours), m (minutes), s (seconds)
|
|
else if (typeof opts.expires === 'string') {
|
|
expire = parseExpireString(opts.expires);
|
|
}
|
|
// otherwise it must be a Number (defined in days)
|
|
else {
|
|
expireValue = parseFloat(opts.expires);
|
|
expire = isNaN(expireValue) === false
|
|
? getString(expireValue * 864e+5)
|
|
: opts.expires;
|
|
}
|
|
}
|
|
|
|
var keyValue = (encode(key)) + "=" + (stringifyCookieValue(val));
|
|
|
|
var cookie = [
|
|
keyValue,
|
|
expire !== void 0 ? '; Expires=' + expire : '', // use expires attribute, max-age is not supported by IE
|
|
opts.path ? '; Path=' + opts.path : '',
|
|
opts.domain ? '; Domain=' + opts.domain : '',
|
|
opts.sameSite ? '; SameSite=' + opts.sameSite : '',
|
|
opts.httpOnly ? '; HttpOnly' : '',
|
|
opts.secure ? '; Secure' : '',
|
|
opts.other ? '; ' + opts.other : ''
|
|
].join('');
|
|
|
|
if (ssr) {
|
|
if (ssr.req.qCookies) {
|
|
ssr.req.qCookies.push(cookie);
|
|
}
|
|
else {
|
|
ssr.req.qCookies = [ cookie ];
|
|
}
|
|
|
|
ssr.res.setHeader('Set-Cookie', ssr.req.qCookies);
|
|
|
|
// make temporary update so future get()
|
|
// within same SSR timeframe would return the set value
|
|
|
|
var all = ssr.req.headers.cookie || '';
|
|
|
|
if (expire !== void 0 && expireValue < 0) {
|
|
var val$1 = get(key, ssr);
|
|
if (val$1 !== undefined) {
|
|
all = all
|
|
.replace((key + "=" + val$1 + "; "), '')
|
|
.replace(("; " + key + "=" + val$1), '')
|
|
.replace((key + "=" + val$1), '');
|
|
}
|
|
}
|
|
else {
|
|
all = all
|
|
? (keyValue + "; " + all)
|
|
: cookie;
|
|
}
|
|
|
|
ssr.req.headers.cookie = all;
|
|
}
|
|
else {
|
|
document.cookie = cookie;
|
|
}
|
|
}
|
|
|
|
function get (key, ssr) {
|
|
var
|
|
cookieSource = ssr ? ssr.req.headers : document,
|
|
cookies = cookieSource.cookie ? cookieSource.cookie.split('; ') : [],
|
|
l = cookies.length;
|
|
var
|
|
result = key ? null : {},
|
|
i = 0,
|
|
parts,
|
|
name,
|
|
cookie;
|
|
|
|
for (; i < l; i++) {
|
|
parts = cookies[i].split('=');
|
|
name = decode(parts.shift());
|
|
cookie = parts.join('=');
|
|
|
|
if (!key) {
|
|
result[name] = cookie;
|
|
}
|
|
else if (key === name) {
|
|
result = read(cookie);
|
|
break
|
|
}
|
|
}
|
|
|
|
return result
|
|
}
|
|
|
|
function remove (key, options, ssr) {
|
|
set(
|
|
key,
|
|
'',
|
|
Object.assign({}, {expires: -1}, options),
|
|
ssr
|
|
);
|
|
}
|
|
|
|
function has (key, ssr) {
|
|
return get(key, ssr) !== null
|
|
}
|
|
|
|
function getObject (ssr) {
|
|
return {
|
|
get: function (key) { return get(key, ssr); },
|
|
set: function (key, val, opts) { return set(key, val, opts, ssr); },
|
|
has: function (key) { return has(key, ssr); },
|
|
remove: function (key, options) { return remove(key, options, ssr); },
|
|
getAll: function () { return get(null, ssr); }
|
|
}
|
|
}
|
|
|
|
var Cookies = {
|
|
parseSSR: function parseSSR (ssrContext) {
|
|
return ssrContext !== void 0
|
|
? getObject(ssrContext)
|
|
: this
|
|
},
|
|
|
|
install: function install (ref) {
|
|
var $q = ref.$q;
|
|
var queues = ref.queues;
|
|
|
|
if (isSSR === true) {
|
|
queues.server.push(function (q, ctx) {
|
|
q.cookies = getObject(ctx.ssr);
|
|
});
|
|
}
|
|
else {
|
|
Object.assign(this, getObject());
|
|
$q.cookies = this;
|
|
}
|
|
}
|
|
};
|
|
|
|
var DialogPlugin = Vue.extend({
|
|
name: 'DialogPlugin',
|
|
|
|
mixins: [ DarkMixin, AttrsMixin ],
|
|
|
|
inheritAttrs: false,
|
|
|
|
props: {
|
|
title: String,
|
|
message: String,
|
|
prompt: Object,
|
|
options: Object,
|
|
|
|
html: Boolean,
|
|
|
|
ok: {
|
|
type: [String, Object, Boolean],
|
|
default: true
|
|
},
|
|
cancel: [String, Object, Boolean],
|
|
focus: {
|
|
type: String,
|
|
default: 'ok',
|
|
validator: function (v) { return ['ok', 'cancel', 'none'].includes(v); }
|
|
},
|
|
|
|
stackButtons: Boolean,
|
|
color: String,
|
|
|
|
cardClass: [String, Array, Object],
|
|
cardStyle: [String, Array, Object]
|
|
},
|
|
|
|
computed: {
|
|
hasForm: function hasForm () {
|
|
return this.prompt !== void 0 || this.options !== void 0
|
|
},
|
|
|
|
okLabel: function okLabel () {
|
|
return Object(this.ok) === this.ok
|
|
? this.$q.lang.label.ok
|
|
: (
|
|
this.ok === true
|
|
? this.$q.lang.label.ok
|
|
: this.ok
|
|
)
|
|
},
|
|
|
|
cancelLabel: function cancelLabel () {
|
|
return Object(this.cancel) === this.cancel
|
|
? this.$q.lang.label.cancel
|
|
: (
|
|
this.cancel === true
|
|
? this.$q.lang.label.cancel
|
|
: this.cancel
|
|
)
|
|
},
|
|
|
|
vmColor: function vmColor () {
|
|
return this.color || (this.isDark === true ? 'amber' : 'primary')
|
|
},
|
|
|
|
okDisabled: function okDisabled () {
|
|
if (this.prompt !== void 0) {
|
|
return this.prompt.isValid !== void 0 &&
|
|
this.prompt.isValid(this.prompt.model) !== true
|
|
}
|
|
if (this.options !== void 0) {
|
|
return this.options.isValid !== void 0 &&
|
|
this.options.isValid(this.options.model) !== true
|
|
}
|
|
},
|
|
|
|
okProps: function okProps () {
|
|
return Object.assign({}, {color: this.vmColor,
|
|
label: this.okLabel,
|
|
ripple: false},
|
|
(Object(this.ok) === this.ok ? this.ok : { flat: true }),
|
|
{disable: this.okDisabled})
|
|
},
|
|
|
|
cancelProps: function cancelProps () {
|
|
return Object.assign({}, {color: this.vmColor,
|
|
label: this.cancelLabel,
|
|
ripple: false},
|
|
(Object(this.cancel) === this.cancel ? this.cancel : { flat: true }))
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
show: function show () {
|
|
this.$refs.dialog.show();
|
|
},
|
|
|
|
hide: function hide () {
|
|
this.$refs.dialog.hide();
|
|
},
|
|
|
|
getPrompt: function getPrompt (h) {
|
|
var this$1 = this;
|
|
|
|
return [
|
|
h(QInput, {
|
|
props: {
|
|
value: this.prompt.model,
|
|
type: this.prompt.type,
|
|
|
|
label: this.prompt.label,
|
|
stackLabel: this.prompt.stackLabel,
|
|
|
|
outlined: this.prompt.outlined,
|
|
filled: this.prompt.filled,
|
|
standout: this.prompt.standout,
|
|
rounded: this.prompt.rounded,
|
|
square: this.prompt.square,
|
|
|
|
counter: this.prompt.counter,
|
|
maxlength: this.prompt.maxlength,
|
|
prefix: this.prompt.prefix,
|
|
suffix: this.prompt.suffix,
|
|
|
|
color: this.vmColor,
|
|
dense: true,
|
|
autofocus: true,
|
|
dark: this.isDark
|
|
},
|
|
attrs: this.prompt.attrs,
|
|
on: cache(this, 'prompt', {
|
|
input: function (v) { this$1.prompt.model = v; },
|
|
keyup: function (evt) {
|
|
// if ENTER key
|
|
if (
|
|
this$1.okDisabled !== true &&
|
|
this$1.prompt.type !== 'textarea' &&
|
|
isKeyCode(evt, 13) === true
|
|
) {
|
|
this$1.onOk();
|
|
}
|
|
}
|
|
})
|
|
})
|
|
]
|
|
},
|
|
|
|
getOptions: function getOptions (h) {
|
|
var this$1 = this;
|
|
|
|
return [
|
|
h(QOptionGroup, {
|
|
props: {
|
|
value: this.options.model,
|
|
type: this.options.type,
|
|
color: this.vmColor,
|
|
inline: this.options.inline,
|
|
options: this.options.items,
|
|
dark: this.isDark
|
|
},
|
|
on: cache(this, 'opts', {
|
|
input: function (v) { this$1.options.model = v; }
|
|
})
|
|
})
|
|
]
|
|
},
|
|
|
|
getButtons: function getButtons (h) {
|
|
var child = [];
|
|
|
|
this.cancel && child.push(h(QBtn, {
|
|
props: this.cancelProps,
|
|
attrs: { 'data-autofocus': this.focus === 'cancel' && this.hasForm !== true },
|
|
on: cache(this, 'cancel', { click: this.onCancel })
|
|
}));
|
|
|
|
this.ok && child.push(h(QBtn, {
|
|
props: this.okProps,
|
|
attrs: { 'data-autofocus': this.focus === 'ok' && this.hasForm !== true },
|
|
on: cache(this, 'ok', { click: this.onOk })
|
|
}));
|
|
|
|
if (child.length > 0) {
|
|
return h(QCardActions, {
|
|
staticClass: this.stackButtons === true ? 'items-end' : null,
|
|
props: {
|
|
vertical: this.stackButtons,
|
|
align: 'right'
|
|
}
|
|
}, child)
|
|
}
|
|
},
|
|
|
|
onOk: function onOk () {
|
|
this.$emit('ok', clone$1(this.getData()));
|
|
this.hide();
|
|
},
|
|
|
|
onCancel: function onCancel () {
|
|
this.hide();
|
|
},
|
|
|
|
getData: function getData () {
|
|
return this.prompt !== void 0
|
|
? this.prompt.model
|
|
: (this.options !== void 0 ? this.options.model : void 0)
|
|
},
|
|
|
|
getSection: function getSection (h, staticClass, text) {
|
|
return this.html === true
|
|
? h(QCardSection, {
|
|
staticClass: staticClass,
|
|
domProps: { innerHTML: text }
|
|
})
|
|
: h(QCardSection, { staticClass: staticClass }, [ text ])
|
|
}
|
|
},
|
|
|
|
render: function render (h) {
|
|
var this$1 = this;
|
|
|
|
var child = [];
|
|
|
|
this.title && child.push(
|
|
this.getSection(h, 'q-dialog__title', this.title)
|
|
);
|
|
|
|
this.message && child.push(
|
|
this.getSection(h, 'q-dialog__message', this.message)
|
|
);
|
|
|
|
if (this.prompt !== void 0) {
|
|
child.push(
|
|
h(
|
|
QCardSection,
|
|
{ staticClass: 'scroll q-dialog-plugin__form' },
|
|
this.getPrompt(h)
|
|
)
|
|
);
|
|
}
|
|
else if (this.options !== void 0) {
|
|
child.push(
|
|
h(QSeparator, { props: { dark: this.isDark } }),
|
|
h(
|
|
QCardSection,
|
|
{ staticClass: 'scroll q-dialog-plugin__form' },
|
|
this.getOptions(h)
|
|
),
|
|
h(QSeparator, { props: { dark: this.isDark } })
|
|
);
|
|
}
|
|
|
|
if (this.ok || this.cancel) {
|
|
child.push(this.getButtons(h));
|
|
}
|
|
|
|
return h(QDialog, {
|
|
ref: 'dialog',
|
|
|
|
props: Object.assign({}, this.qAttrs,
|
|
{value: this.value}),
|
|
|
|
on: cache(this, 'hide', {
|
|
hide: function () {
|
|
this$1.$emit('hide');
|
|
}
|
|
})
|
|
}, [
|
|
h(QCard, {
|
|
staticClass: 'q-dialog-plugin' +
|
|
(this.isDark === true ? ' q-dialog-plugin--dark q-dark' : ''),
|
|
style: this.cardStyle,
|
|
class: this.cardClass,
|
|
props: { dark: this.isDark }
|
|
}, child)
|
|
])
|
|
}
|
|
});
|
|
|
|
var Dialog = {
|
|
install: function install (ref) {
|
|
var $q = ref.$q;
|
|
|
|
this.create = $q.dialog = globalDialog(DialogPlugin);
|
|
}
|
|
};
|
|
|
|
var LoadingBar = {
|
|
isActive: false,
|
|
start: noop,
|
|
stop: noop,
|
|
increment: noop,
|
|
setDefaults: noop,
|
|
|
|
install: function install (ref) {
|
|
var this$1 = this;
|
|
var $q = ref.$q;
|
|
var cfg = ref.cfg;
|
|
|
|
if (isSSR === true) {
|
|
$q.loadingBar = this;
|
|
return
|
|
}
|
|
|
|
var props = cfg.loadingBar !== void 0
|
|
? Object.assign({}, cfg.loadingBar)
|
|
: {};
|
|
|
|
var bar = $q.loadingBar = new Vue({
|
|
name: 'LoadingBar',
|
|
render: function (h) { return h(QAjaxBar, {
|
|
ref: 'bar',
|
|
props: props
|
|
}); }
|
|
}).$mount().$refs.bar;
|
|
|
|
Object.assign(this, {
|
|
start: function (speed) {
|
|
bar.start(speed);
|
|
this$1.isActive = bar.isActive = bar.calls > 0;
|
|
},
|
|
stop: function () {
|
|
bar.stop();
|
|
this$1.isActive = bar.isActive = bar.calls > 0;
|
|
},
|
|
increment: bar.increment,
|
|
setDefaults: function (opts) {
|
|
opts === Object(opts) && Object.assign(props, opts);
|
|
bar.$parent.$forceUpdate();
|
|
}
|
|
});
|
|
|
|
Vue.util.defineReactive(this, 'isActive', this.isActive);
|
|
Vue.util.defineReactive(bar, 'isActive', this.isActive);
|
|
bar.setDefaults = this.setDefaults;
|
|
|
|
document.body.appendChild(bar.$parent.$el);
|
|
}
|
|
};
|
|
|
|
var
|
|
vm,
|
|
uid$3 = 0,
|
|
timeout,
|
|
props$1 = {};
|
|
var
|
|
originalDefaults = {
|
|
delay: 0,
|
|
message: false,
|
|
spinnerSize: 80,
|
|
spinnerColor: 'white',
|
|
messageColor: 'white',
|
|
backgroundColor: 'black',
|
|
spinner: QSpinner,
|
|
customClass: ''
|
|
},
|
|
defaults = Object.assign({}, originalDefaults);
|
|
|
|
var Loading = {
|
|
isActive: false,
|
|
|
|
show: function show (opts) {
|
|
var this$1 = this;
|
|
|
|
if (isSSR === true) { return }
|
|
|
|
props$1 = opts === Object(opts) && opts.ignoreDefaults === true
|
|
? Object.assign({}, originalDefaults, opts)
|
|
: Object.assign({}, defaults, opts);
|
|
|
|
props$1.customClass += " text-" + (props$1.backgroundColor);
|
|
props$1.uid = "l_" + (uid$3++);
|
|
|
|
this.isActive = true;
|
|
|
|
if (vm !== void 0) {
|
|
vm.$forceUpdate();
|
|
return
|
|
}
|
|
|
|
clearTimeout(timeout);
|
|
timeout = setTimeout(function () {
|
|
timeout = void 0;
|
|
|
|
var node = document.createElement('div');
|
|
document.body.appendChild(node);
|
|
|
|
vm = new Vue({
|
|
name: 'QLoading',
|
|
|
|
el: node,
|
|
|
|
mounted: function mounted () {
|
|
preventScroll(true);
|
|
},
|
|
|
|
render: function (h) {
|
|
var obj;
|
|
|
|
return h('transition', {
|
|
props: {
|
|
name: 'q-transition--fade',
|
|
appear: true
|
|
},
|
|
on: cache(this$1, 'tr', {
|
|
'after-leave': function () {
|
|
// might be called to finalize
|
|
// previous leave, even if it was cancelled
|
|
if (this$1.isActive !== true && vm !== void 0) {
|
|
preventScroll(false);
|
|
vm.$destroy();
|
|
vm.$el.remove();
|
|
vm = void 0;
|
|
}
|
|
}
|
|
})
|
|
}, [
|
|
this$1.isActive === true ? h('div', {
|
|
staticClass: 'q-loading fullscreen column flex-center z-max',
|
|
key: props$1.uid,
|
|
class: props$1.customClass.trim()
|
|
}, [
|
|
h(props$1.spinner, {
|
|
props: {
|
|
color: props$1.spinnerColor,
|
|
size: props$1.spinnerSize
|
|
}
|
|
}),
|
|
(props$1.message && h('div', {
|
|
class: ("text-" + (props$1.messageColor)),
|
|
domProps: ( obj = {}, obj[props$1.sanitize === true ? 'textContent' : 'innerHTML'] = props$1.message, obj )
|
|
})) || void 0
|
|
]) : null
|
|
])
|
|
}
|
|
});
|
|
}, props$1.delay);
|
|
},
|
|
|
|
hide: function hide () {
|
|
if (this.isActive === true) {
|
|
if (timeout !== void 0) {
|
|
clearTimeout(timeout);
|
|
timeout = void 0;
|
|
}
|
|
|
|
this.isActive = false;
|
|
}
|
|
},
|
|
|
|
setDefaults: function setDefaults (opts) {
|
|
opts === Object(opts) && Object.assign(defaults, opts);
|
|
},
|
|
|
|
install: function install (ref) {
|
|
var $q = ref.$q;
|
|
var loading = ref.cfg.loading;
|
|
|
|
this.setDefaults(loading);
|
|
$q.loading = this;
|
|
}
|
|
};
|
|
|
|
if (isSSR === false) {
|
|
Vue.util.defineReactive(Loading, 'isActive', Loading.isActive);
|
|
}
|
|
|
|
var updateId, ssrTakeover;
|
|
|
|
function normalize (meta) {
|
|
if (meta.title) {
|
|
meta.title = meta.titleTemplate
|
|
? meta.titleTemplate(meta.title)
|
|
: meta.title;
|
|
delete meta.titleTemplate;
|
|
}
|
|
[['meta', 'content'], ['link', 'href']].forEach(function (type) {
|
|
var
|
|
metaType = meta[type[0]],
|
|
metaProp = type[1];
|
|
|
|
for (var name in metaType) {
|
|
var metaLink = metaType[name];
|
|
|
|
if (metaLink.template) {
|
|
if (Object.keys(metaLink).length === 1) {
|
|
delete metaType[name];
|
|
}
|
|
else {
|
|
metaLink[metaProp] = metaLink.template(metaLink[metaProp] || '');
|
|
delete metaLink.template;
|
|
}
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
function changed (old, def) {
|
|
if (Object.keys(old).length !== Object.keys(def).length) {
|
|
return true
|
|
}
|
|
for (var key in old) {
|
|
if (old[key] !== def[key]) {
|
|
return true
|
|
}
|
|
}
|
|
}
|
|
|
|
function bodyFilter (name) {
|
|
return ['class', 'style'].includes(name) === false
|
|
}
|
|
|
|
function htmlFilter (name) {
|
|
return ['lang', 'dir'].includes(name) === false
|
|
}
|
|
|
|
function diff (meta, other) {
|
|
var add = {}, remove = {};
|
|
|
|
if (meta === void 0) {
|
|
return { add: other, remove: remove }
|
|
}
|
|
|
|
if (meta.title !== other.title) {
|
|
add.title = other.title;
|
|
}
|
|
['meta', 'link', 'script', 'htmlAttr', 'bodyAttr'].forEach(function (type) {
|
|
var old = meta[type], cur = other[type];
|
|
remove[type] = [];
|
|
|
|
if (old === void 0 || old === null) {
|
|
add[type] = cur;
|
|
return
|
|
}
|
|
|
|
add[type] = {};
|
|
|
|
for (var key in old) {
|
|
if (cur.hasOwnProperty(key) === false) {
|
|
remove[type].push(key);
|
|
}
|
|
}
|
|
for (var key$1 in cur) {
|
|
if (old.hasOwnProperty(key$1) === false) {
|
|
add[type][key$1] = cur[key$1];
|
|
}
|
|
else if (changed(old[key$1], cur[key$1]) === true) {
|
|
remove[type].push(key$1);
|
|
add[type][key$1] = cur[key$1];
|
|
}
|
|
}
|
|
});
|
|
|
|
return { add: add, remove: remove }
|
|
}
|
|
|
|
function apply$1 (ref) {
|
|
var add = ref.add;
|
|
var remove = ref.remove;
|
|
|
|
if (add.title) {
|
|
document.title = add.title;
|
|
}
|
|
|
|
if (Object.keys(remove).length > 0) {
|
|
['meta', 'link', 'script'].forEach(function (type) {
|
|
remove[type].forEach(function (name) {
|
|
document.head.querySelector((type + "[data-qmeta=\"" + name + "\"]")).remove();
|
|
});
|
|
});
|
|
remove.htmlAttr.filter(htmlFilter).forEach(function (name) {
|
|
document.documentElement.removeAttribute(name);
|
|
});
|
|
remove.bodyAttr.filter(bodyFilter).forEach(function (name) {
|
|
document.body.removeAttribute(name);
|
|
});
|
|
}
|
|
['meta', 'link', 'script'].forEach(function (type) {
|
|
var metaType = add[type];
|
|
|
|
for (var name in metaType) {
|
|
var tag = document.createElement(type);
|
|
for (var att in metaType[name]) {
|
|
if (att !== 'innerHTML') {
|
|
tag.setAttribute(att, metaType[name][att]);
|
|
}
|
|
}
|
|
tag.setAttribute('data-qmeta', name);
|
|
if (type === 'script') {
|
|
tag.innerHTML = metaType[name].innerHTML || '';
|
|
}
|
|
document.head.appendChild(tag);
|
|
}
|
|
});
|
|
Object.keys(add.htmlAttr).filter(htmlFilter).forEach(function (name) {
|
|
document.documentElement.setAttribute(name, add.htmlAttr[name] || '');
|
|
});
|
|
Object.keys(add.bodyAttr).filter(bodyFilter).forEach(function (name) {
|
|
document.body.setAttribute(name, add.bodyAttr[name] || '');
|
|
});
|
|
}
|
|
|
|
function parseMeta (component, meta) {
|
|
if (component._inactive === true) { return }
|
|
|
|
// if it has meta
|
|
if (hasMeta(component) === true) {
|
|
extend(true, meta, component.__qMeta);
|
|
|
|
if (component.$options.meta.stopPropagation === true) {
|
|
return
|
|
}
|
|
}
|
|
|
|
component.$children.forEach(function (child) {
|
|
parseMeta(child, meta);
|
|
});
|
|
}
|
|
|
|
function updateClient () {
|
|
if (ssrTakeover === true) {
|
|
ssrTakeover = false;
|
|
this.$root.__currentMeta = window.__Q_META__;
|
|
}
|
|
|
|
var meta = {
|
|
title: '',
|
|
titleTemplate: null,
|
|
meta: {},
|
|
link: {},
|
|
script: {},
|
|
htmlAttr: {},
|
|
bodyAttr: {}
|
|
};
|
|
parseMeta(this.$root, meta);
|
|
normalize(meta);
|
|
|
|
apply$1(diff(this.$root.__currentMeta, meta));
|
|
this.$root.__currentMeta = meta;
|
|
}
|
|
|
|
function getAttr (seed) {
|
|
return function (att) {
|
|
var val = seed[att];
|
|
return att + (val !== void 0 ? ("=\"" + val + "\"") : '')
|
|
}
|
|
}
|
|
|
|
function getHead (meta) {
|
|
var output = '';
|
|
if (meta.title) {
|
|
output += "<title>" + (meta.title) + "</title>";
|
|
}
|
|
['meta', 'link', 'script'].forEach(function (type) {
|
|
var metaType = meta[type];
|
|
|
|
for (var att in metaType) {
|
|
var attrs = Object.keys(metaType[att])
|
|
.filter(function (att) { return att !== 'innerHTML'; })
|
|
.map(getAttr(metaType[att]));
|
|
|
|
output += "<" + type + " " + (attrs.join(' ')) + " data-qmeta=\"" + att + "\">";
|
|
if (type === 'script') {
|
|
output += (metaType[att].innerHTML || '') + "</script>";
|
|
}
|
|
}
|
|
});
|
|
return output
|
|
}
|
|
|
|
function getServerMeta (app, html, ctx) {
|
|
var meta = {
|
|
title: '',
|
|
titleTemplate: null,
|
|
meta: {},
|
|
link: {},
|
|
htmlAttr: {},
|
|
bodyAttr: {},
|
|
noscript: {}
|
|
};
|
|
|
|
parseMeta(app, meta);
|
|
normalize(meta);
|
|
|
|
var nonce = ctx !== void 0 && ctx.nonce !== void 0
|
|
? (" nonce=\"" + (ctx.nonce) + "\"")
|
|
: '';
|
|
|
|
var tokens = {
|
|
'%%Q_HTML_ATTRS%%': Object.keys(meta.htmlAttr)
|
|
.filter(htmlFilter)
|
|
.map(getAttr(meta.htmlAttr))
|
|
.join(' '),
|
|
'%%Q_HEAD_TAGS%%': getHead(meta),
|
|
'%%Q_BODY_ATTRS%%': Object.keys(meta.bodyAttr)
|
|
.filter(bodyFilter)
|
|
.map(getAttr(meta.bodyAttr))
|
|
.join(' '),
|
|
'%%Q_BODY_TAGS%%': Object.keys(meta.noscript)
|
|
.map(function (name) { return ("<noscript data-qmeta=\"" + name + "\">" + (meta.noscript[name]) + "</noscript>"); })
|
|
.join('') +
|
|
"<script" + nonce + ">window.__Q_META__=" + (delete meta.noscript && JSON.stringify(meta)) + "</script>"
|
|
};
|
|
|
|
Object.keys(tokens).forEach(function (key) {
|
|
html = html.replace(key, tokens[key]);
|
|
});
|
|
|
|
return html
|
|
}
|
|
|
|
function beforeCreate () {
|
|
if (typeof this.$options.meta === 'function') {
|
|
if (this.$options.computed === void 0) {
|
|
this.$options.computed = {};
|
|
}
|
|
this.$options.computed.__qMeta = this.$options.meta;
|
|
}
|
|
else if (hasMeta(this) === true) {
|
|
this.__qMeta = this.$options.meta;
|
|
}
|
|
}
|
|
|
|
// needs to be really fast
|
|
function hasMeta (vm) {
|
|
return vm.$options.meta !== void 0 &&
|
|
vm.$options.meta !== null
|
|
}
|
|
|
|
function triggerMeta () {
|
|
hasMeta(this) === true && this.__qMetaUpdate();
|
|
}
|
|
|
|
var Meta = {
|
|
install: function install (ref) {
|
|
var queues = ref.queues;
|
|
|
|
if (isSSR === true) {
|
|
Vue.prototype.$getMetaHTML = function (app) {
|
|
return function (html, ctx) { return getServerMeta(app, html, ctx); }
|
|
};
|
|
|
|
Vue.mixin({ beforeCreate: beforeCreate });
|
|
|
|
queues.server.push(function (_, ctx) {
|
|
ctx.ssr.Q_HTML_ATTRS += ' %%Q_HTML_ATTRS%%';
|
|
Object.assign(ctx.ssr, {
|
|
Q_HEAD_TAGS: '%%Q_HEAD_TAGS%%',
|
|
Q_BODY_ATTRS: '%%Q_BODY_ATTRS%%',
|
|
Q_BODY_TAGS: '%%Q_BODY_TAGS%%'
|
|
});
|
|
});
|
|
}
|
|
else {
|
|
ssrTakeover = fromSSR;
|
|
|
|
Vue.mixin({
|
|
beforeCreate: beforeCreate,
|
|
created: function created () {
|
|
if (hasMeta(this) === true) {
|
|
this.__qMetaUnwatch = this.$watch('__qMeta', this.__qMetaUpdate);
|
|
}
|
|
},
|
|
activated: triggerMeta,
|
|
deactivated: triggerMeta,
|
|
beforeMount: triggerMeta,
|
|
destroyed: function destroyed () {
|
|
if (hasMeta(this) === true) {
|
|
this.__qMetaUnwatch();
|
|
this.__qMetaUpdate();
|
|
}
|
|
},
|
|
methods: {
|
|
__qMetaUpdate: function __qMetaUpdate () {
|
|
clearTimeout(updateId);
|
|
updateId = setTimeout(updateClient.bind(this), 50);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
}
|
|
};
|
|
|
|
function objectWithoutProperties$2 (obj, exclude) { var target = {}; for (var k in obj) if (Object.prototype.hasOwnProperty.call(obj, k) && exclude.indexOf(k) === -1) target[k] = obj[k]; return target; }
|
|
|
|
var uid$4 = 0;
|
|
var defaults$1 = {};
|
|
|
|
var positionList = [
|
|
'top-left', 'top-right',
|
|
'bottom-left', 'bottom-right',
|
|
'top', 'bottom', 'left', 'right', 'center'
|
|
];
|
|
|
|
var badgePositions = [
|
|
'top-left', 'top-right',
|
|
'bottom-left', 'bottom-right'
|
|
];
|
|
|
|
var notifTypes = {
|
|
positive: {
|
|
icon: function icon () { return this.$q.iconSet.type.positive },
|
|
color: 'positive'
|
|
},
|
|
|
|
negative: {
|
|
icon: function icon () { return this.$q.iconSet.type.negative },
|
|
color: 'negative'
|
|
},
|
|
|
|
warning: {
|
|
icon: function icon () { return this.$q.iconSet.type.warning },
|
|
color: 'warning',
|
|
textColor: 'dark'
|
|
},
|
|
|
|
info: {
|
|
icon: function icon () { return this.$q.iconSet.type.info },
|
|
color: 'info'
|
|
}
|
|
};
|
|
|
|
var groups = {};
|
|
var positionClass$1 = {};
|
|
|
|
var Notifications = {
|
|
name: 'QNotifications',
|
|
|
|
created: function created () {
|
|
var this$1 = this;
|
|
|
|
this.notifs = {};
|
|
|
|
positionList.forEach(function (pos) {
|
|
this$1.notifs[pos] = [];
|
|
|
|
var
|
|
vert = ['left', 'center', 'right'].includes(pos) === true ? 'center' : (pos.indexOf('top') > -1 ? 'top' : 'bottom'),
|
|
align = pos.indexOf('left') > -1 ? 'start' : (pos.indexOf('right') > -1 ? 'end' : 'center'),
|
|
classes = ['left', 'right'].includes(pos) ? ("items-" + (pos === 'left' ? 'start' : 'end') + " justify-center") : (pos === 'center' ? 'flex-center' : ("items-" + align));
|
|
|
|
positionClass$1[pos] = "q-notifications__list q-notifications__list--" + vert + " fixed column no-wrap " + classes;
|
|
});
|
|
},
|
|
|
|
methods: {
|
|
add: function add (config) {
|
|
var this$1 = this;
|
|
|
|
if (!config) {
|
|
console.error('Notify: parameter required');
|
|
return false
|
|
}
|
|
|
|
var notif = { textColor: 'white' };
|
|
|
|
if (typeof config === 'string' || config.ignoreDefaults !== true) {
|
|
Object.assign(notif, defaults$1);
|
|
}
|
|
|
|
if (Object(config) === config) {
|
|
Object.assign(notif, notifTypes[config.type], config);
|
|
|
|
if (typeof notif.icon === 'function') {
|
|
notif.icon = notif.icon.call(this);
|
|
}
|
|
}
|
|
else {
|
|
notif.message = config;
|
|
}
|
|
|
|
notif.meta = {
|
|
hasMedia: Boolean(notif.icon || notif.avatar)
|
|
};
|
|
|
|
if (notif.position) {
|
|
if (positionList.includes(notif.position) === false) {
|
|
console.error(("Notify: wrong position: " + (notif.position)));
|
|
return false
|
|
}
|
|
}
|
|
else {
|
|
notif.position = 'bottom';
|
|
}
|
|
|
|
if (notif.timeout === void 0) {
|
|
notif.timeout = 5000;
|
|
}
|
|
else {
|
|
var t = parseInt(notif.timeout, 10);
|
|
if (isNaN(t) || t < 0) {
|
|
console.error(("Notify: wrong timeout: " + (notif.timeout)));
|
|
return false
|
|
}
|
|
notif.timeout = t;
|
|
}
|
|
|
|
if (notif.timeout === 0) {
|
|
notif.progress = false;
|
|
}
|
|
else if (notif.progress === true) {
|
|
notif.meta.progressStyle = {
|
|
animationDuration: ((notif.timeout + 1000) + "ms")
|
|
};
|
|
}
|
|
|
|
var actions = (
|
|
Array.isArray(config.actions) === true
|
|
? config.actions
|
|
: []
|
|
).concat(
|
|
config.ignoreDefaults !== true && Array.isArray(defaults$1.actions) === true
|
|
? defaults$1.actions
|
|
: []
|
|
).concat(
|
|
notifTypes[config.type] !== void 0 && Array.isArray(notifTypes[config.type].actions) === true
|
|
? notifTypes[config.type].actions
|
|
: []
|
|
);
|
|
|
|
notif.closeBtn && actions.push({
|
|
label: typeof notif.closeBtn === 'string'
|
|
? notif.closeBtn
|
|
: this.$q.lang.label.close
|
|
});
|
|
|
|
notif.actions = actions.map(function (ref) {
|
|
var handler = ref.handler;
|
|
var noDismiss = ref.noDismiss;
|
|
var attrs = ref.attrs;
|
|
var rest = objectWithoutProperties$2( ref, ["handler", "noDismiss", "attrs"] );
|
|
var item = rest;
|
|
|
|
return ({
|
|
props: Object.assign({}, {flat: true}, item),
|
|
attrs: attrs,
|
|
on: {
|
|
click: typeof handler === 'function'
|
|
? function () {
|
|
handler();
|
|
noDismiss !== true && notif.meta.close();
|
|
}
|
|
: function () {
|
|
notif.meta.close();
|
|
}
|
|
}
|
|
});
|
|
});
|
|
|
|
if (notif.multiLine === void 0) {
|
|
notif.multiLine = notif.actions.length > 1;
|
|
}
|
|
|
|
Object.assign(notif.meta, {
|
|
staticClass: "q-notification row items-stretch" +
|
|
" q-notification--" + (notif.multiLine === true ? 'multi-line' : 'standard') +
|
|
(notif.color !== void 0 ? (" bg-" + (notif.color)) : '') +
|
|
(notif.textColor !== void 0 ? (" text-" + (notif.textColor)) : '') +
|
|
(notif.classes !== void 0 ? (" " + (notif.classes)) : ''),
|
|
|
|
wrapperClass: 'q-notification__wrapper col relative-position border-radius-inherit ' +
|
|
(notif.multiLine === true ? 'column no-wrap justify-center' : 'row items-center'),
|
|
|
|
contentClass: 'q-notification__content row items-center' +
|
|
(notif.multiLine === true ? '' : ' col'),
|
|
|
|
attrs: Object.assign({}, {role: 'alert'},
|
|
notif.attrs)
|
|
});
|
|
|
|
if (notif.group === false) {
|
|
notif.group = void 0;
|
|
}
|
|
else {
|
|
if (notif.group === void 0 || notif.group === true) {
|
|
// do not replace notifications with different buttons
|
|
notif.group = [
|
|
notif.message,
|
|
notif.caption,
|
|
notif.multiline
|
|
].concat(
|
|
notif.actions.map(function (a) { return ((a.props.label) + "*" + (a.props.icon)); })
|
|
).join('|');
|
|
}
|
|
|
|
notif.group += '|' + notif.position;
|
|
}
|
|
|
|
if (notif.actions.length === 0) {
|
|
notif.actions = void 0;
|
|
}
|
|
else {
|
|
notif.meta.actionsClass = 'q-notification__actions row items-center ' +
|
|
(notif.multiLine === true ? 'justify-end' : 'col-auto') +
|
|
(notif.meta.hasMedia === true ? ' q-notification__actions--with-media' : '');
|
|
}
|
|
|
|
var groupNotif = groups[notif.group];
|
|
|
|
// wohoo, new notification
|
|
if (groupNotif === void 0) {
|
|
notif.meta.uid = uid$4++;
|
|
notif.meta.badge = 1;
|
|
|
|
if (['left', 'right', 'center'].indexOf(notif.position) !== -1) {
|
|
this.notifs[notif.position].splice(
|
|
Math.floor(this.notifs[notif.position].length / 2),
|
|
0,
|
|
notif
|
|
);
|
|
}
|
|
else {
|
|
var action = notif.position.indexOf('top') > -1 ? 'unshift' : 'push';
|
|
this.notifs[notif.position][action](notif);
|
|
}
|
|
|
|
if (notif.group !== void 0) {
|
|
groups[notif.group] = notif;
|
|
}
|
|
}
|
|
// ok, so it's NOT a new one
|
|
else {
|
|
// reset timeout if any
|
|
if (groupNotif.meta.timer !== void 0) {
|
|
clearTimeout(groupNotif.meta.timer);
|
|
}
|
|
|
|
var original = groups[notif.group];
|
|
|
|
if (notif.badgePosition !== void 0) {
|
|
if (badgePositions.includes(notif.badgePosition) === false) {
|
|
console.error(("Notify - wrong badgePosition specified: " + (notif.badgePosition)));
|
|
return false
|
|
}
|
|
}
|
|
else {
|
|
notif.badgePosition = "top-" + (notif.position.indexOf('left') > -1 ? 'right' : 'left');
|
|
}
|
|
|
|
notif.meta.uid = original.meta.uid;
|
|
notif.meta.badge = original.meta.badge + 1;
|
|
notif.meta.badgeStaticClass = "q-notification__badge q-notification__badge--" + (notif.badgePosition) +
|
|
(notif.badgeColor !== void 0 ? (" bg-" + (notif.badgeColor)) : '') +
|
|
(notif.badgeTextColor !== void 0 ? (" text-" + (notif.badgeTextColor)) : '');
|
|
|
|
var index = this.notifs[notif.position].indexOf(original);
|
|
this.notifs[notif.position][index] = groups[notif.group] = notif;
|
|
}
|
|
|
|
notif.meta.close = function () {
|
|
this$1.remove(notif);
|
|
};
|
|
|
|
this.$forceUpdate();
|
|
|
|
if (notif.timeout > 0) {
|
|
notif.meta.timer = setTimeout(function () {
|
|
notif.meta.close();
|
|
}, notif.timeout + /* show duration */ 1000);
|
|
}
|
|
|
|
return notif.meta.close
|
|
},
|
|
|
|
remove: function remove (notif) {
|
|
clearTimeout(notif.meta.timer);
|
|
|
|
var index = this.notifs[notif.position].indexOf(notif);
|
|
if (index !== -1) {
|
|
if (notif.group !== void 0) {
|
|
delete groups[notif.group];
|
|
}
|
|
|
|
var el = this.$refs[("notif_" + (notif.meta.uid))];
|
|
|
|
if (el) {
|
|
var ref = getComputedStyle(el);
|
|
var width = ref.width;
|
|
var height = ref.height;
|
|
|
|
el.style.left = (el.offsetLeft) + "px";
|
|
el.style.width = width;
|
|
el.style.height = height;
|
|
}
|
|
|
|
this.notifs[notif.position].splice(index, 1);
|
|
|
|
this.$forceUpdate();
|
|
|
|
if (typeof notif.onDismiss === 'function') {
|
|
notif.onDismiss();
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
render: function render (h) {
|
|
var this$1 = this;
|
|
|
|
return h('div', { staticClass: 'q-notifications' }, positionList.map(function (pos) {
|
|
return h('transition-group', {
|
|
key: pos,
|
|
staticClass: positionClass$1[pos],
|
|
tag: 'div',
|
|
props: {
|
|
name: ("q-notification--" + pos),
|
|
mode: 'out-in'
|
|
}
|
|
}, this$1.notifs[pos].map(function (notif) {
|
|
var msgChild;
|
|
|
|
var meta = notif.meta;
|
|
var msgData = { staticClass: 'q-notification__message col' };
|
|
|
|
if (notif.html === true) {
|
|
msgData.domProps = {
|
|
innerHTML: notif.caption
|
|
? ("<div>" + (notif.message) + "</div><div class=\"q-notification__caption\">" + (notif.caption) + "</div>")
|
|
: notif.message
|
|
};
|
|
}
|
|
else {
|
|
var msgNode = [ notif.message ];
|
|
msgChild = notif.caption
|
|
? [
|
|
h('div', msgNode),
|
|
h('div', { staticClass: 'q-notification__caption' }, [ notif.caption ])
|
|
]
|
|
: msgNode;
|
|
}
|
|
|
|
var mainChild = [];
|
|
|
|
if (meta.hasMedia === true) {
|
|
if (notif.icon) {
|
|
mainChild.push(
|
|
h(QIcon, {
|
|
staticClass: 'q-notification__icon',
|
|
attrs: { role: 'img' },
|
|
props: { name: notif.icon }
|
|
})
|
|
);
|
|
}
|
|
else if (notif.avatar) {
|
|
mainChild.push(
|
|
h(QAvatar, { staticClass: 'q-notification__avatar col-auto' }, [
|
|
h('img', { attrs: { src: notif.avatar, 'aria-hidden': 'true' } })
|
|
])
|
|
);
|
|
}
|
|
}
|
|
|
|
mainChild.push(
|
|
h('div', msgData, msgChild)
|
|
);
|
|
|
|
var child = [
|
|
h('div', { staticClass: meta.contentClass }, mainChild)
|
|
];
|
|
|
|
notif.progress === true && child.push(
|
|
h('div', {
|
|
key: ((meta.uid) + "|p|" + (meta.badge)),
|
|
staticClass: 'q-notification__progress',
|
|
style: meta.progressStyle,
|
|
class: notif.progressClass
|
|
})
|
|
);
|
|
|
|
notif.actions !== void 0 && child.push(
|
|
h('div', {
|
|
staticClass: meta.actionsClass
|
|
}, notif.actions.map(function (a) { return h(QBtn, { props: a.props, attrs: a.attrs, on: a.on }); }))
|
|
);
|
|
|
|
meta.badge > 1 && child.push(
|
|
h('div', {
|
|
key: ((meta.uid) + "|" + (meta.badge)),
|
|
staticClass: meta.badgeStaticClass,
|
|
style: notif.badgeStyle,
|
|
class: notif.badgeClass
|
|
}, [ meta.badge ])
|
|
);
|
|
|
|
return h('div', {
|
|
ref: ("notif_" + (meta.uid)),
|
|
key: meta.uid,
|
|
staticClass: meta.staticClass,
|
|
attrs: meta.attrs
|
|
}, [
|
|
h('div', { staticClass: meta.wrapperClass }, child)
|
|
])
|
|
}))
|
|
}))
|
|
},
|
|
|
|
mounted: function mounted () {
|
|
var this$1 = this;
|
|
|
|
if (this.$q.fullscreen !== void 0 && this.$q.fullscreen.isCapable === true) {
|
|
var append = function (isFullscreen) {
|
|
var newParent = getBodyFullscreenElement(
|
|
isFullscreen,
|
|
this$1.$q.fullscreen.activeEl
|
|
);
|
|
|
|
if (this$1.$el.parentElement !== newParent) {
|
|
newParent.appendChild(this$1.$el);
|
|
}
|
|
};
|
|
|
|
this.unwatchFullscreen = this.$watch('$q.fullscreen.isActive', append);
|
|
|
|
if (this.$q.fullscreen.isActive === true) {
|
|
append(true);
|
|
}
|
|
}
|
|
},
|
|
|
|
beforeDestroy: function beforeDestroy () {
|
|
this.unwatchFullscreen !== void 0 && this.unwatchFullscreen();
|
|
}
|
|
};
|
|
|
|
var Notify = {
|
|
create: function create (opts) {
|
|
if (isSSR === true) { return noop }
|
|
return this.__vm.add(opts)
|
|
},
|
|
setDefaults: function setDefaults (opts) {
|
|
opts === Object(opts) && Object.assign(defaults$1, opts);
|
|
},
|
|
registerType: function registerType (typeName, typeOpts) {
|
|
if (isSSR !== true && typeOpts === Object(typeOpts)) {
|
|
notifTypes[typeName] = typeOpts;
|
|
}
|
|
},
|
|
|
|
install: function install (ref) {
|
|
var cfg = ref.cfg;
|
|
var $q = ref.$q;
|
|
|
|
if (isSSR === true) {
|
|
$q.notify = noop;
|
|
$q.notify.setDefaults = noop;
|
|
return
|
|
}
|
|
|
|
this.setDefaults(cfg.notify);
|
|
|
|
$q.notify = this.create.bind(this);
|
|
$q.notify.setDefaults = this.setDefaults;
|
|
$q.notify.registerType = this.registerType;
|
|
|
|
var node = document.createElement('div');
|
|
document.body.appendChild(node);
|
|
|
|
this.__vm = new Vue(Notifications);
|
|
this.__vm.$mount(node);
|
|
}
|
|
};
|
|
|
|
function encode$1 (value) {
|
|
if (Object.prototype.toString.call(value) === '[object Date]') {
|
|
return '__q_date|' + value.toUTCString()
|
|
}
|
|
if (Object.prototype.toString.call(value) === '[object RegExp]') {
|
|
return '__q_expr|' + value.source
|
|
}
|
|
if (typeof value === 'number') {
|
|
return '__q_numb|' + value
|
|
}
|
|
if (typeof value === 'boolean') {
|
|
return '__q_bool|' + (value ? '1' : '0')
|
|
}
|
|
if (typeof value === 'string') {
|
|
return '__q_strn|' + value
|
|
}
|
|
if (typeof value === 'function') {
|
|
return '__q_strn|' + value.toString()
|
|
}
|
|
if (value === Object(value)) {
|
|
return '__q_objt|' + JSON.stringify(value)
|
|
}
|
|
|
|
// hmm, we don't know what to do with it,
|
|
// so just return it as is
|
|
return value
|
|
}
|
|
|
|
function decode$1 (value) {
|
|
var length = value.length;
|
|
if (length < 9) {
|
|
// then it wasn't encoded by us
|
|
return value
|
|
}
|
|
|
|
var type = value.substr(0, 8);
|
|
var source = value.substring(9);
|
|
|
|
switch (type) {
|
|
case '__q_date':
|
|
return new Date(source)
|
|
|
|
case '__q_expr':
|
|
return new RegExp(source)
|
|
|
|
case '__q_numb':
|
|
return Number(source)
|
|
|
|
case '__q_bool':
|
|
return Boolean(source === '1')
|
|
|
|
case '__q_strn':
|
|
return '' + source
|
|
|
|
case '__q_objt':
|
|
return JSON.parse(source)
|
|
|
|
default:
|
|
// hmm, we reached here, we don't know the type,
|
|
// then it means it wasn't encoded by us, so just
|
|
// return whatever value it is
|
|
return value
|
|
}
|
|
}
|
|
|
|
function getEmptyStorage () {
|
|
return {
|
|
has: noop,
|
|
getLength: noop,
|
|
getItem: noop,
|
|
getIndex: noop,
|
|
getAll: noop,
|
|
set: noop,
|
|
remove: noop,
|
|
clear: noop,
|
|
isEmpty: noop
|
|
}
|
|
}
|
|
|
|
function getStorage (type) {
|
|
var
|
|
webStorage = window[type + 'Storage'],
|
|
get = function (key) {
|
|
var item = webStorage.getItem(key);
|
|
return item
|
|
? decode$1(item)
|
|
: null
|
|
};
|
|
|
|
return {
|
|
has: function (key) { return webStorage.getItem(key) !== null; },
|
|
getLength: function () { return webStorage.length; },
|
|
getItem: get,
|
|
getIndex: function (index) {
|
|
return index < webStorage.length
|
|
? get(webStorage.key(index))
|
|
: null
|
|
},
|
|
getKey: function (index) {
|
|
return index < webStorage.length
|
|
? webStorage.key(index)
|
|
: null
|
|
},
|
|
getAll: function () {
|
|
var key;
|
|
var result = {}, len = webStorage.length;
|
|
|
|
for (var i = 0; i < len; i++) {
|
|
key = webStorage.key(i);
|
|
result[key] = get(key);
|
|
}
|
|
|
|
return result
|
|
},
|
|
getAllKeys: function () {
|
|
var result = [], len = webStorage.length;
|
|
|
|
for (var i = 0; i < len; i++) {
|
|
result.push(webStorage.key(i));
|
|
}
|
|
|
|
return result
|
|
},
|
|
set: function (key, value) { webStorage.setItem(key, encode$1(value)); },
|
|
remove: function (key) { webStorage.removeItem(key); },
|
|
clear: function () { webStorage.clear(); },
|
|
isEmpty: function () { return webStorage.length === 0; }
|
|
}
|
|
}
|
|
|
|
var LocalStorage = {
|
|
install: function install (ref) {
|
|
var $q = ref.$q;
|
|
|
|
var storage = isSSR === true || client.has.webStorage === false
|
|
? getEmptyStorage()
|
|
: getStorage('local');
|
|
|
|
$q.localStorage = storage;
|
|
Object.assign(this, storage);
|
|
}
|
|
};
|
|
|
|
var SessionStorage = {
|
|
install: function install (ref) {
|
|
var $q = ref.$q;
|
|
|
|
var storage = isSSR === true || client.has.webStorage === false
|
|
? getEmptyStorage()
|
|
: getStorage('session');
|
|
|
|
$q.sessionStorage = storage;
|
|
Object.assign(this, storage);
|
|
}
|
|
};
|
|
|
|
|
|
|
|
var plugins = /*#__PURE__*/Object.freeze({
|
|
__proto__: null,
|
|
AddressbarColor: AddressbarColor,
|
|
AppFullscreen: AppFullscreen,
|
|
AppVisibility: AppVisibility,
|
|
BottomSheet: BottomSheet$1,
|
|
Cookies: Cookies,
|
|
Dark: Dark,
|
|
Dialog: Dialog,
|
|
LoadingBar: LoadingBar,
|
|
Loading: Loading,
|
|
Meta: Meta,
|
|
Notify: Notify,
|
|
Platform: Platform,
|
|
Screen: Screen,
|
|
LocalStorage: LocalStorage,
|
|
SessionStorage: SessionStorage
|
|
});
|
|
|
|
function fallback (text) {
|
|
var area = document.createElement('textarea');
|
|
area.value = text;
|
|
area.contentEditable = true;
|
|
area.style.position = 'fixed'; // avoid scrolling to bottom
|
|
|
|
document.body.appendChild(area);
|
|
area.focus();
|
|
area.select();
|
|
|
|
var res = document.execCommand('copy');
|
|
|
|
area.remove();
|
|
return res
|
|
}
|
|
|
|
function copyToClipboard (text) {
|
|
return navigator.clipboard !== void 0
|
|
? navigator.clipboard.writeText(text)
|
|
: new Promise(function (resolve, reject) {
|
|
var res = fallback(text);
|
|
if (res) {
|
|
resolve(true);
|
|
}
|
|
else {
|
|
reject(res);
|
|
}
|
|
})
|
|
}
|
|
|
|
function clean (link) {
|
|
// allow time for iOS
|
|
setTimeout(function () {
|
|
window.URL.revokeObjectURL(link.href);
|
|
}, 10000);
|
|
link.remove();
|
|
}
|
|
|
|
function exportFile (fileName, rawData, mimeType) {
|
|
var blob = new Blob([ rawData ], { type: mimeType || 'text/plain' });
|
|
|
|
// IE11 has its own stuff...
|
|
if (window.navigator.msSaveOrOpenBlob) {
|
|
return window.navigator.msSaveOrOpenBlob(blob, fileName)
|
|
}
|
|
|
|
var link = document.createElement('a');
|
|
|
|
link.download = fileName;
|
|
link.href = window.URL.createObjectURL(blob);
|
|
|
|
link.classList.add('hidden');
|
|
link.style.position = 'fixed'; // avoid scrolling to bottom
|
|
document.body.appendChild(link);
|
|
|
|
try {
|
|
link.click();
|
|
clean(link);
|
|
return true
|
|
}
|
|
catch (err) {
|
|
clean(link);
|
|
return err
|
|
}
|
|
}
|
|
|
|
function parseFeatures (winFeatures) {
|
|
var cfg = Object.assign({ noopener: true }, winFeatures);
|
|
var feat = [];
|
|
Object.keys(cfg).forEach(function (key) {
|
|
if (cfg[key] === true) {
|
|
feat.push(key);
|
|
}
|
|
});
|
|
return feat.join(',')
|
|
}
|
|
|
|
function openWindow (url, reject, windowFeatures) {
|
|
var open = window.open;
|
|
|
|
if (Platform.is.cordova === true) {
|
|
if (cordova !== void 0 && cordova.InAppBrowser !== void 0 && cordova.InAppBrowser.open !== void 0) {
|
|
open = cordova.InAppBrowser.open;
|
|
}
|
|
else if (navigator !== void 0 && navigator.app !== void 0) {
|
|
return navigator.app.loadUrl(url, {
|
|
openExternal: true
|
|
})
|
|
}
|
|
}
|
|
else if (Vue.prototype.$q.electron !== void 0) {
|
|
return Vue.prototype.$q.electron.shell.openExternal(url)
|
|
}
|
|
|
|
var win = open(url, '_blank', parseFeatures(windowFeatures));
|
|
|
|
if (win) {
|
|
Platform.is.desktop && win.focus();
|
|
return win
|
|
}
|
|
else {
|
|
reject && reject();
|
|
}
|
|
}
|
|
|
|
function openUrl (url, reject, windowFeatures) {
|
|
if (
|
|
Platform.is.ios === true &&
|
|
window.SafariViewController !== void 0
|
|
) {
|
|
window.SafariViewController.isAvailable(function (available) {
|
|
if (available) {
|
|
window.SafariViewController.show(
|
|
{ url: url },
|
|
noop,
|
|
reject
|
|
);
|
|
}
|
|
else {
|
|
openWindow(url, reject, windowFeatures);
|
|
}
|
|
});
|
|
return
|
|
}
|
|
|
|
return openWindow(url, reject, windowFeatures)
|
|
}
|
|
|
|
|
|
|
|
var utils = /*#__PURE__*/Object.freeze({
|
|
__proto__: null,
|
|
clone: clone$1,
|
|
colors: colors,
|
|
copyToClipboard: copyToClipboard,
|
|
date: date,
|
|
debounce: debounce,
|
|
dom: dom,
|
|
event: event,
|
|
exportFile: exportFile,
|
|
extend: extend,
|
|
format: format,
|
|
frameDebounce: frameDebounce,
|
|
noop: noop,
|
|
openURL: openUrl,
|
|
morph: morph,
|
|
patterns: patterns,
|
|
scroll: scroll,
|
|
throttle: throttle,
|
|
uid: uid$2
|
|
});
|
|
|
|
Vue.use({ install: install }, {
|
|
components: components$1,
|
|
directives: directives,
|
|
plugins: plugins,
|
|
config: window.quasarConfig || {}
|
|
});
|
|
|
|
var index_umd = Object.assign({}, {version: version,
|
|
lang: lang,
|
|
iconSet: iconSet,
|
|
components: components$1,
|
|
directives: directives,
|
|
plugins: plugins,
|
|
utils: utils},
|
|
components$1,
|
|
directives,
|
|
plugins,
|
|
utils);
|
|
|
|
return index_umd;
|
|
|
|
})));
|