123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275 |
- // @ts-nocheck
- import {isDef} from '../isDef'
- import {ComponentPublicInstance} from 'vue'
- type HasSelectorFunc = (selector : string, element : UniElement) => boolean
- const hasSelectorClassName : HasSelectorFunc = (selector : string, element : UniElement) : boolean => {
- return element.classList.includes(selector)
- }
- const hasSelectorId : HasSelectorFunc = (selector : string, element : UniElement) : boolean => {
- return element.getAttribute("id") == selector
- }
- const hasSelectorTagName : HasSelectorFunc = (selector : string, element : UniElement) : boolean => {
- return element.tagName!.toLowerCase() == selector.toLowerCase()
- }
- type ProcessSelectorResult = {
- selectorValue : string
- hasSelector : HasSelectorFunc
- }
- const processSelector = (selector : string) : ProcessSelectorResult => {
- const selectorValue = /#|\./.test(selector) ? selector.substring(1) : selector
- let hasSelector : HasSelectorFunc
- if (selector.startsWith('.')) {
- hasSelector = hasSelectorClassName
- } else if (selector.startsWith('#')) {
- hasSelector = hasSelectorId
- } else {
- hasSelector = hasSelectorTagName
- }
- return {
- selectorValue,
- hasSelector
- } as ProcessSelectorResult
- }
- function isNotEmptyString(str:string): boolean {
- return str.length > 0;
- }
- function isElement(element:UniElement|null):boolean {
- return isDef(element) && element?.tagName != 'COMMENT';
- }
- type ElementArray = Array<UniElement|null>
- class Query {
- context : ComponentPublicInstance | null = null
- selector : string = ''
- elements : ElementArray = []
- constructor(selector : string | null, context : ComponentPublicInstance | null) {
- this.context = context
- if(selector != null){
- this.selector = selector
- }
- this.find(this.selector)
- }
- in(context : ComponentPublicInstance) : Query {
- return new Query(this.selector, context)
- }
- findAll(selector : string): Query {
- if (isDef(this.context)) {
- const root = this.context?.$el //as Element | null;
- if (isDef(root)) {
- this.elements = [root!] //as ElementArray
- }
- const { selectorValue, hasSelector } = processSelector(selector)
- const foundElements : ElementArray = [];
-
- function findChildren(element : UniElement) {
- element.children.forEach((child : UniElement) => {
- if (hasSelector(selectorValue, child)) {
- foundElements.push(child)
- }
- })
- }
- this.elements.forEach(el => {
- findChildren(el!);
- });
- this.elements = foundElements
- } else if (selector.startsWith('#')) {
- const element = uni.getElementById(selector)
- if (isElement(element!)) {
- this.elements = [element]
- }
- }
- return this;
- }
- /**
- * 在当前元素集合中查找匹配的元素
- */
- find(selector : string) : Query {
- if (isDef(this.context)) {
- const root = this.context?.$el //as Element | null;
- if (isElement(root)) {
- this.elements = [root] //as ElementArray
- }
- if(isNotEmptyString(selector) && this.elements.length > 0){
- const { selectorValue, hasSelector } = processSelector(selector)
- const foundElements : ElementArray = [];
- function findChildren(element : UniElement) {
- element.children.forEach((child : UniElement) => {
- if (hasSelector(selectorValue, child) && foundElements.length < 1) {
- foundElements.push(child)
- }
- if (foundElements.length < 1) {
- findChildren(child);
- }
- })
- }
- this.elements.forEach(el => {
- findChildren(el!);
- });
- this.elements = foundElements
- }
-
- } else if (selector.startsWith('#')) {
- const element = uni.getElementById(selector)
- if (isElement(element!)) {
- this.elements = [element]
- }
- }
- return this;
- }
- /**
- * 获取当前元素集合的直接子元素
- */
- children() : Query {
- // if (this.elements.length > 0) {
- // const children = this.elements.reduce((acc, el) => [...acc, ...Array.from(el.children)], []);
- // this.elements = children;
- // }
- return this;
- }
- /**
- * 获取当前元素集合的父元素
- */
- parent() : Query {
- // if (this.elements.length > 0) {
- // const parents = this.elements.map(el => el.parentElement).filter(parent => parent !== null) as ElementArray;
- // this.elements = parents
- // // this.elements = Array.from(new Set(parents));
- // }
- return this;
- }
- /**
- * 获取当前元素集合的兄弟元素
- */
- siblings() : Query {
- // if (this.elements.length > 0) {
- // const siblings = this.elements.reduce((acc, el) => [...acc, ...Array.from(el.parentElement?.children || [])], []);
- // this.elements = siblings.filter(sibling => sibling !== null && !this.elements?.includes(sibling));
- // }
- return this;
- }
- /**
- * 获取当前元素集合的下一个兄弟元素
- */
- next() : Query {
- // if (this.elements.length > 0) {
- // const nextElements = this.elements.map(el => el.nextElementSibling).filter(next => next !== null) as ElementArray;
- // this.elements = nextElements;
- // }
- return this;
- }
- /**
- * 获取当前元素集合的上一个兄弟元素
- */
- prev() : Query {
- // if (this.elements.length > 0) {
- // const prevElements = this.elements.map(el => el.previousElementSibling).filter(prev => prev !== null) as ElementArray;
- // this.elements = prevElements;
- // }
- return this;
- }
- /**
- * 从当前元素开始向上查找匹配的元素
- */
- closest(selector : string) : Query {
- if (isDef(this.context)) {
- // && this.context.$parent != null && this.context.$parent.$el !== null
- if(this.elements.length == 0 && isDef(this.context?.$parent) && isElement(this.context!.$parent?.$el)){
- this.elements = [this.context!.$parent?.$el!]
- }
-
- const selectorsArray = selector.split(',')
- // const { selectorValue, hasSelector } = processSelector(selector)
- const processedSelectors = selectorsArray.map((selector: string):ProcessSelectorResult => processSelector(selector))
- const closestElements = this.elements.map((el) : UniElement | null => {
- let closestElement : UniElement | null = el
- while (closestElement !== null) {
- // if (hasSelector(selectorValue, closestElement)) {
- // break;
- // }
- const isMatchingSelector = processedSelectors.some(({selectorValue, hasSelector}):boolean => {
- return hasSelector(selectorValue, closestElement!)
- })
- if(isMatchingSelector){
- break;
- }
- closestElement = closestElement.parentElement;
- }
- return closestElement
- })
- this.elements = closestElements.filter((closest : UniElement | null) : boolean => isDef(closest))// as ElementArray
-
- }
- return this;
- }
- /**
- * 从当前元素集合中过滤出匹配的元素
- */
- filter() : Query {
- return this;
- }
- /**
- * 从当前元素集合中排除匹配的元素
- */
- not() { }
- /**
- * 从当前元素集合中查找包含匹配元素的元素
- */
- has() { }
- /**
- * 获取当前元素集合的第一个
- */
- first() : Query {
- if (this.elements.length > 0) {
- // this.elements = [this.elements[0]];
- }
- return this;
- }
- /**
- * 最后一个元素
- */
- last() : Query {
- if (this.elements.length > 0) {
- // this.elements = [this.elements[this.elements.length - 1]];
- }
- return this;
- }
- /**
- * 获取当前元素在其兄弟元素中的索引
- */
- index() : number | null {
- // if (this.elements.length > 0 && this.elements.length > 0 && this.elements[0].parentElement !== null) {
- // return Array.from(this.elements[0].parentElement.children).indexOf(this.elements[0]);
- // }
- return null;
- }
- get(index : number) : UniElement | null {
- if (this.elements.length > index) {
- return this.elements[index] //as Element
- }
- return null
- }
- }
- export function selectElement(selector : string | null = null) : Query {
- // if(typeof selector == 'string' || selector == null){
- // return new Query(selector as string | null, null)
- // }
- // else if(selector instanceof ComponentPublicInstance){
- // return new Query(null, selector)
- // }
- return new Query(selector, null)
- }
- // $('xxx').in(this).find('xxx')
- // $('xxx').in(this).get()
|