Add ripple support
parent
17411a9659
commit
1ecdcf58b4
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<div class="p-accordion p-component">
|
||||
<slot></slot>
|
||||
<div v-for="(tab, i) of tabs" :key="tab.header || i" class="p-accordion-tab">
|
||||
<div v-for="(tab, i) of tabs" :key="tab.header || i" :class="['p-accordion-tab', {'p-accordion-tab-active': tab.d_active}]">
|
||||
<div :class="['p-accordion-header', {'p-highlight': tab.d_active, 'p-disabled': tab.disabled}]">
|
||||
<a role="tab" class="p-accordion-header-link" @click="onTabClick($event, tab)" @keydown="onTabKeydown($event, tab)" :tabindex="tab.disabled ? null : '0'"
|
||||
:aria-expanded="tab.d_active" :id="ariaId + i + '_header'" :aria-controls="ariaId + i + '_content'">
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
<transition name="p-input-overlay" @enter="onOverlayEnter" @leave="onOverlayLeave">
|
||||
<div ref="overlay" class="p-autocomplete-panel p-component" :style="{'max-height': scrollHeight}" v-if="overlayVisible">
|
||||
<ul :id="listId" class="p-autocomplete-items" role="listbox">
|
||||
<li v-for="(item, i) of suggestions" class="p-autocomplete-item" :key="i" @click="selectItem($event, item)" role="option">
|
||||
<li v-for="(item, i) of suggestions" class="p-autocomplete-item" :key="i" @click="selectItem($event, item)" role="option" v-ripple>
|
||||
<slot name="item" :item="item" :index="i">
|
||||
{{getItemContent(item)}}
|
||||
</slot>
|
||||
|
@ -32,6 +32,7 @@ import ObjectUtils from '../utils/ObjectUtils';
|
|||
import DomHandler from '../utils/DomHandler';
|
||||
import Button from '../button/Button';
|
||||
import UniqueComponentId from '../utils/UniqueComponentId';
|
||||
import Ripple from '../ripple/Ripple';
|
||||
|
||||
export default {
|
||||
inheritAttrs: false,
|
||||
|
@ -424,6 +425,9 @@ export default {
|
|||
},
|
||||
components: {
|
||||
'Button': Button
|
||||
},
|
||||
directives: {
|
||||
'ripple': Ripple
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
@ -474,6 +478,8 @@ export default {
|
|||
.p-autocomplete-item {
|
||||
cursor: pointer;
|
||||
white-space: nowrap;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.p-autocomplete-multiple-container {
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
align-items: center;
|
||||
vertical-align: bottom;
|
||||
text-align: center;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.p-button-text {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<button :class="buttonClass" v-on="$listeners" type="button">
|
||||
<button :class="buttonClass" v-on="$listeners" type="button" v-ripple>
|
||||
<span v-if="icon" :class="iconClass"></span>
|
||||
<span class="p-button-text">{{label||' '}}</span>
|
||||
<span class="p-badge" v-if="badge" :class="badgeClass">{{badge}}</span>
|
||||
|
@ -7,6 +7,8 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import Ripple from '../ripple/Ripple';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
label: {
|
||||
|
@ -48,6 +50,9 @@ export default {
|
|||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
directives: {
|
||||
'ripple': Ripple
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<div class="p-checkbox p-component" @click="onClick($event)">
|
||||
<div :class="containerClass" @click="onClick($event)">
|
||||
<div class="p-hidden-accessible">
|
||||
<input ref="input" type="checkbox" :checked="checked" :value="value" v-bind="$attrs" @focus="onFocus($event)" @blur="onBlur($event)">
|
||||
</div>
|
||||
|
@ -61,6 +61,9 @@ export default {
|
|||
computed: {
|
||||
checked() {
|
||||
return this.binary ? this.modelValue : ObjectUtils.contains(this.value, this.modelValue);
|
||||
},
|
||||
containerClass() {
|
||||
return ['p-checkbox p-component', {'p-checkbox-checked': this.checked, 'p-checkbox-disabled': this.$attrs.disabled, 'p-checkbox-focused': this.focused}];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -151,4 +151,30 @@ button {
|
|||
position: absolute;
|
||||
width: 1px;
|
||||
word-wrap: normal !important;
|
||||
}
|
||||
|
||||
.p-ink {
|
||||
display: block;
|
||||
position: absolute;
|
||||
background: rgba(255, 255, 255, 0.5);
|
||||
border-radius: 100%;
|
||||
transform: scale(0);
|
||||
}
|
||||
|
||||
.p-ink-active {
|
||||
animation: ripple 0.4s linear;
|
||||
}
|
||||
|
||||
@-webkit-keyframes ripple {
|
||||
100% {
|
||||
opacity: 0;
|
||||
-webkit-transform: scale(2.5);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes ripple {
|
||||
100% {
|
||||
opacity: 0;
|
||||
transform: scale(2.5);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
</div>
|
||||
<div ref="itemsWrapper" class="p-dropdown-items-wrapper" :style="{'max-height': scrollHeight}">
|
||||
<ul class="p-dropdown-items" role="listbox">
|
||||
<li v-for="(option, i) of visibleOptions" :class="['p-dropdown-item', {'p-highlight': isSelected(option), 'p-disabled': isOptionDisabled(option)}]"
|
||||
<li v-for="(option, i) of visibleOptions" :class="['p-dropdown-item', {'p-highlight': isSelected(option), 'p-disabled': isOptionDisabled(option)}]" v-ripple
|
||||
:aria-label="getOptionLabel(option)" :key="getOptionRenderKey(option)" @click="onOptionSelect($event, option)" role="option" :aria-selected="isSelected(option)">
|
||||
<slot name="option" :option="option" :index="i">
|
||||
{{getOptionLabel(option)}}
|
||||
|
@ -41,6 +41,7 @@
|
|||
<script>
|
||||
import ObjectUtils from '../utils/ObjectUtils';
|
||||
import DomHandler from '../utils/DomHandler';
|
||||
import Ripple from '../ripple/Ripple';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
|
@ -451,6 +452,9 @@ export default {
|
|||
equalityKey() {
|
||||
return this.optionValue ? null : this.dataKey;
|
||||
}
|
||||
},
|
||||
directives: {
|
||||
'ripple': Ripple
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
@ -510,6 +514,8 @@ input.p-dropdown-label {
|
|||
cursor: pointer;
|
||||
font-weight: normal;
|
||||
white-space: nowrap;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.p-dropdown-items {
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
</div>
|
||||
<div class="p-listbox-list-wrapper" :style="listStyle">
|
||||
<ul class="p-listbox-list" role="listbox" aria-multiselectable="multiple">
|
||||
<li v-for="(option, i) of visibleOptions" :tabindex="isOptionDisabled(option) ? null : '0'" :class="['p-listbox-item', {'p-highlight': isSelected(option), 'p-disabled': isOptionDisabled(option)}]"
|
||||
<li v-for="(option, i) of visibleOptions" :tabindex="isOptionDisabled(option) ? null : '0'" :class="['p-listbox-item', {'p-highlight': isSelected(option), 'p-disabled': isOptionDisabled(option)}]" v-ripple
|
||||
:aria-label="getOptionLabel(option)" :key="getOptionRenderKey(option)" @click="onOptionSelect($event, option)" @touchend="onOptionTouchEnd()" @keydown="onOptionKeyDown($event, option)" role="option" :aria-selected="isSelected(option)">
|
||||
<slot name="option" :option="option" :index="i">
|
||||
{{getOptionLabel(option)}}
|
||||
|
@ -22,6 +22,7 @@
|
|||
<script>
|
||||
import ObjectUtils from '../utils/ObjectUtils';
|
||||
import DomHandler from '../utils/DomHandler';
|
||||
import Ripple from '../ripple/Ripple';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
|
@ -227,6 +228,9 @@ export default {
|
|||
equalityKey() {
|
||||
return this.optionValue ? null : this.dataKey;
|
||||
}
|
||||
},
|
||||
directives: {
|
||||
'ripple': Ripple
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
@ -244,6 +248,8 @@ export default {
|
|||
|
||||
.p-listbox-item {
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.p-listbox-filter-container {
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
<div ref="itemsWrapper" class="p-multiselect-items-wrapper" :style="{'max-height': scrollHeight}">
|
||||
<ul class="p-multiselect-items p-component" role="listbox" aria-multiselectable="true">
|
||||
<li v-for="(option, i) of visibleOptions" :class="['p-multiselect-item', {'p-highlight': isSelected(option), 'p-disabled': isOptionDisabled(option)}]" role="option" :aria-selected="isSelected(option)"
|
||||
:aria-label="getOptionLabel(option)" :key="getOptionRenderKey(option)" @click="onOptionSelect($event, option)" @keydown="onOptionKeyDown($event, option)" :tabindex="tabindex||'0'">
|
||||
:aria-label="getOptionLabel(option)" :key="getOptionRenderKey(option)" @click="onOptionSelect($event, option)" @keydown="onOptionKeyDown($event, option)" :tabindex="tabindex||'0'" v-ripple>
|
||||
<div class="p-checkbox p-component">
|
||||
<div :class="['p-checkbox-box p-component', {'p-highlight': isSelected(option)}]">
|
||||
<span :class="['p-checkbox-icon', {'pi pi-check': isSelected(option)}]"></span>
|
||||
|
@ -56,6 +56,7 @@
|
|||
<script>
|
||||
import ObjectUtils from '../utils/ObjectUtils';
|
||||
import DomHandler from '../utils/DomHandler';
|
||||
import Ripple from '../ripple/Ripple';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
|
@ -406,6 +407,9 @@ export default {
|
|||
equalityKey() {
|
||||
return this.optionValue ? null : this.dataKey;
|
||||
}
|
||||
},
|
||||
directives: {
|
||||
'ripple': Ripple
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
@ -466,6 +470,8 @@ export default {
|
|||
align-items: center;
|
||||
font-weight: normal;
|
||||
white-space: nowrap;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.p-multiselect-header {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<div class="p-radiobutton p-component" @click="onClick($event)">
|
||||
<div :class="containerClass" @click="onClick($event)">
|
||||
<div class="p-hidden-accessible">
|
||||
<input ref="input" type="radio" :checked="checked" :value="value" v-bind="$attrs" @focus="onFocus($event)" @blur="onBlur($event)">
|
||||
</div>
|
||||
|
@ -51,6 +51,9 @@ export default {
|
|||
computed: {
|
||||
checked() {
|
||||
return this.modelValue != null && ObjectUtils.equals(this.modelValue, this.value);
|
||||
},
|
||||
containerClass() {
|
||||
return ['p-radiobutton p-component', {'p-radiobutton-checked': this.checked, 'p-radiobutton-disabled': this.$attrs.disabled, 'p-radiobutton-focused': this.focused}];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,87 @@
|
|||
import DomHandler from '../utils/DomHandler';
|
||||
|
||||
function bindEvents(el) {
|
||||
el.addEventListener('mousedown', onMouseDown);
|
||||
el.addEventListener('mouseleave', onMouseLeave);
|
||||
}
|
||||
|
||||
function unbindEvents(el) {
|
||||
el.removeEventListener('mousedown', onMouseDown);
|
||||
el.removeEventListener('mouseleave', onMouseLeave);
|
||||
}
|
||||
|
||||
function create(el) {
|
||||
let ink = document.createElement('span');
|
||||
ink.className = 'p-ink';
|
||||
el.appendChild(ink);
|
||||
|
||||
ink.addEventListener('animationend', onAnimationEnd);
|
||||
}
|
||||
|
||||
function remove(el) {
|
||||
let ink = getInk(el);
|
||||
if (ink) {
|
||||
ink.removeEventListener('animationend', onAnimationEnd);
|
||||
ink.remove();
|
||||
}
|
||||
}
|
||||
|
||||
function onMouseDown(event) {
|
||||
let target = event.currentTarget;
|
||||
let ink = getInk(target);
|
||||
|
||||
if (ink) {
|
||||
DomHandler.removeClass(ink, 'p-ink-active');
|
||||
if (!DomHandler.getHeight(ink) && !DomHandler.getWidth(ink)) {
|
||||
let d = Math.max(DomHandler.getOuterWidth(target), DomHandler.getOuterHeight(target));
|
||||
ink.style.height = d + 'px';
|
||||
ink.style.width = d + 'px';
|
||||
}
|
||||
|
||||
let offset = DomHandler.getOffset(target);
|
||||
let x = event.pageX - offset.left + document.body.scrollTop - DomHandler.getWidth(ink) / 2;
|
||||
let y = event.pageY - offset.top + document.body.scrollLeft - DomHandler.getHeight(ink) / 2;
|
||||
|
||||
ink.style.top = y + 'px';
|
||||
ink.style.left = x + 'px';
|
||||
DomHandler.addClass(ink, 'p-ink-active');
|
||||
}
|
||||
}
|
||||
|
||||
function onMouseLeave(event) {
|
||||
resetInk(event);
|
||||
}
|
||||
|
||||
function resetInk(event) {
|
||||
let target = event.target;
|
||||
let ink = getInk(target);
|
||||
if (ink) {
|
||||
DomHandler.removeClass(ink, 'p-ink-active');
|
||||
}
|
||||
}
|
||||
|
||||
function onAnimationEnd(event) {
|
||||
DomHandler.removeClass(event.currentTarget, 'p-ink-active');
|
||||
}
|
||||
|
||||
function getInk(el) {
|
||||
for (let i = 0; i < el.children.length; i++) {
|
||||
if (el.children[i].className.indexOf('p-ink') !== -1) {
|
||||
return el.children[i];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
const Ripple = {
|
||||
inserted(el) {
|
||||
create(el);
|
||||
bindEvents(el);
|
||||
},
|
||||
unbind(el) {
|
||||
remove(el);
|
||||
unbindEvents(el);
|
||||
}
|
||||
};
|
||||
|
||||
export default Ripple;
|
|
@ -1,23 +1,27 @@
|
|||
<template>
|
||||
<div class="p-tabmenu p-component">
|
||||
<ul class="p-tabmenu-nav p-reset" role="tablist">
|
||||
<ul ref="nav" class="p-tabmenu-nav p-reset" role="tablist">
|
||||
<template v-for="(item,i) of model">
|
||||
<li :key="item.label + '_' + i" :class="getItemClass(item)" :style="item.style" v-if="visible(item)" role="tab" :aria-selected="isActive(item)" :aria-expanded="isActive(item)">
|
||||
<router-link v-if="item.to && !item.disabled" :to="item.to" class="p-menuitem-link" @click.native="onItemClick($event, item)" role="presentation">
|
||||
<router-link v-if="item.to && !item.disabled" :to="item.to" class="p-menuitem-link" @click.native="onItemClick($event, item)" role="presentation" v-ripple>
|
||||
<span :class="getItemIcon(item)" v-if="item.icon"></span>
|
||||
<span class="p-menuitem-text">{{item.label}}</span>
|
||||
</router-link>
|
||||
<a v-else :href="item.url" class="p-menuitem-link" :target="item.target" @click="onItemClick($event, item)" role="presentation" :tabindex="item.disabled ? null : '0'">
|
||||
<a v-else :href="item.url" class="p-menuitem-link" :target="item.target" @click="onItemClick($event, item)" role="presentation" :tabindex="item.disabled ? null : '0'" v-ripple>
|
||||
<span :class="getItemIcon(item)" v-if="item.icon"></span>
|
||||
<span class="p-menuitem-text">{{item.label}}</span>
|
||||
</a>
|
||||
</li>
|
||||
</template>
|
||||
<li ref="inkbar" class="p-tabmenu-ink-bar"></li>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import DomHandler from '../utils/DomHandler';
|
||||
import Ripple from '../ripple/Ripple';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
model: {
|
||||
|
@ -25,6 +29,12 @@ export default {
|
|||
default: null
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.updateInkBar();
|
||||
},
|
||||
updated() {
|
||||
this.updateInkBar();
|
||||
},
|
||||
methods: {
|
||||
onItemClick(event, item) {
|
||||
if (item.disabled) {
|
||||
|
@ -53,12 +63,32 @@ export default {
|
|||
},
|
||||
visible(item) {
|
||||
return (typeof item.visible === 'function' ? item.visible() : item.visible !== false);
|
||||
},
|
||||
findActiveTabIndex() {
|
||||
if (this.model) {
|
||||
for (let i = 0; i < this.model.length; i++) {
|
||||
let item = this.model[i];
|
||||
if (this.isActive(this.model[i])) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
updateInkBar() {
|
||||
let tabHeader = this.$refs.nav.children[this.findActiveTabIndex()];
|
||||
this.$refs.inkbar.style.width = DomHandler.getWidth(tabHeader) + 'px';
|
||||
this.$refs.inkbar.style.left = tabHeader.offsetLeft + 'px';
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
activeRoute() {
|
||||
return this.$route.path;
|
||||
}
|
||||
},
|
||||
directives: {
|
||||
'ripple': Ripple
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
@ -79,6 +109,8 @@ export default {
|
|||
align-items: center;
|
||||
position: relative;
|
||||
text-decoration: none;
|
||||
text-decoration: none;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.p-tabmenu-nav a:focus {
|
||||
|
@ -88,4 +120,8 @@ export default {
|
|||
.p-tabmenu-nav .p-menuitem-text {
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.p-tabmenu-ink-bar {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
<template>
|
||||
<div class="p-tabview p-component">
|
||||
<ul class="p-tabview-nav" role="tablist">
|
||||
<ul ref="nav" class="p-tabview-nav" role="tablist">
|
||||
<li role="presentation" v-for="(tab, i) of tabs" :key="tab.header || i" :class="[{'p-highlight': (tab.d_active), 'p-disabled': tab.disabled}]">
|
||||
<a role="tab" class="p-tabview-nav-link" @click="onTabClick($event, tab)" @keydown="onTabKeydown($event, tab)" :tabindex="tab.disabled ? null : '0'" :aria-selected="tab.d_active">
|
||||
<a role="tab" class="p-tabview-nav-link" @click="onTabClick($event, tab)" @keydown="onTabKeydown($event, tab)" :tabindex="tab.disabled ? null : '0'" :aria-selected="tab.d_active" v-ripple>
|
||||
<span class="p-tabview-title" v-if="tab.header">{{tab.header}}</span>
|
||||
<TabPanelHeaderSlot :tab="tab" v-if="tab.$scopedSlots.header" />
|
||||
</a>
|
||||
</li>
|
||||
<li ref="inkbar" class="p-tabview-ink-bar"></li>
|
||||
</ul>
|
||||
<div class="p-tabview-panels">
|
||||
<slot></slot>
|
||||
|
@ -15,6 +16,9 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import DomHandler from '../utils/DomHandler';
|
||||
import Ripple from '../ripple/Ripple';
|
||||
|
||||
const TabPanelHeaderSlot = {
|
||||
functional: true,
|
||||
props: {
|
||||
|
@ -37,6 +41,13 @@ export default {
|
|||
mounted() {
|
||||
this.d_children = this.$children;
|
||||
},
|
||||
updated() {
|
||||
let activeTab = this.tabs[this.findActiveTabIndex()];
|
||||
if (!activeTab && this.tabs.length) {
|
||||
this.tabs[0].d_active = true;
|
||||
}
|
||||
this.updateInkBar();
|
||||
},
|
||||
methods: {
|
||||
onTabClick(event, tab) {
|
||||
if (!tab.disabled && !tab.d_active) {
|
||||
|
@ -54,29 +65,28 @@ export default {
|
|||
this.tabs[i].d_active = active;
|
||||
this.tabs[i].$emit('update:active', active);
|
||||
}
|
||||
|
||||
this.updateInkBar();
|
||||
},
|
||||
onTabKeydown(event, tab) {
|
||||
if (event.which === 13) {
|
||||
this.onTabClick(event, tab);
|
||||
}
|
||||
},
|
||||
findActiveTab() {
|
||||
let activeTab;
|
||||
findActiveTabIndex() {
|
||||
for (let i = 0; i < this.tabs.length; i++) {
|
||||
let tab = this.tabs[i];
|
||||
if (tab.d_active) {
|
||||
activeTab = tab;
|
||||
break;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return activeTab;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
updated() {
|
||||
let activeTab = this.findActiveTab();
|
||||
if (!activeTab && this.tabs.length) {
|
||||
this.tabs[0].d_active = true;
|
||||
updateInkBar() {
|
||||
let tabHeader = this.$refs.nav.children[this.findActiveTabIndex()];
|
||||
this.$refs.inkbar.style.width = DomHandler.getWidth(tabHeader) + 'px';
|
||||
this.$refs.inkbar.style.left = tabHeader.offsetLeft + 'px';
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
@ -86,6 +96,9 @@ export default {
|
|||
},
|
||||
components: {
|
||||
'TabPanelHeaderSlot': TabPanelHeaderSlot
|
||||
},
|
||||
directives: {
|
||||
'ripple': Ripple
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
@ -106,6 +119,11 @@ export default {
|
|||
align-items: center;
|
||||
position: relative;
|
||||
text-decoration: none;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.p-tabview-ink-bar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.p-tabview-nav-link:focus {
|
||||
|
|
|
@ -88,8 +88,8 @@ export default class DomHandler {
|
|||
var rect = el.getBoundingClientRect();
|
||||
|
||||
return {
|
||||
top: rect.top + document.body.scrollTop,
|
||||
left: rect.left + document.body.scrollLeft
|
||||
top: rect.top + (window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0),
|
||||
left: rect.left + (window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft || 0),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue