File modules/cms/ui/themes/default/script/Oquery.js
Last commit: Tue Mar 1 23:03:32 2022 +0100 dankert New: OQuery support for 'parent(selector)' and 'parents(selector)'
1 /*! OQuery */ 2 /** 3 * OQuery is a very light ES6-ready replacement for JQuery 4 * 5 */ 6 let query = function (selector ) { 7 8 if ( typeof selector === 'string' ) 9 return query.createQuery( document.querySelectorAll(selector) ); 10 else if ( selector instanceof HTMLElement ) 11 return query.createQuery([selector] ); 12 else if ( selector instanceof OQuery ) 13 return selector; 14 else 15 //console.warn( new Error("Illegal argument '"+selector+"' of type "+(typeof selector)) ); 16 return query.createQuery( [] ); 17 18 } 19 20 query.createQuery = function(nodeList ) { 21 return new OQuery( nodeList ); 22 } 23 24 query.create = function(tagName ) { 25 return query.createQuery( [document.createElement( tagName )] ); 26 }; 27 28 query.id = function(id ) { 29 let el = document.getElementById( id ); 30 if ( el ) 31 return query.createQuery( [el] ); 32 else 33 return query.createQuery( [] ); 34 }; 35 36 query.one = function(selector ) { 37 return query.createQuery( [document.querySelector( selector )] ); 38 }; 39 40 query.extend = function() { 41 for(let i=1; i<arguments.length; i++) 42 for(let key in arguments[i]) 43 if(arguments[i].hasOwnProperty(key)) 44 arguments[0][key] = arguments[i][key]; 45 return arguments[0]; 46 } 47 48 export default query; 49 50 51 export class OQuery { 52 53 static fn = OQuery.prototype; 54 55 createNew(nodeList) { 56 return new OQuery(nodeList) 57 }; 58 59 constructor( nodeList ) { 60 61 this.nodes = Array.isArray(nodeList) ? nodeList : Array.from(nodeList) 62 } 63 64 get( idx ) { 65 return this.nodes[idx]; 66 } 67 first() { 68 return this.createNew( this.nodes.length > 0 ? [this.nodes[0]] : [] ); 69 }; 70 71 72 /** 73 * 'length' property is the size of all nodes in this object. 74 * this property is readonly. 75 * 76 * @return size of all elements 77 */ 78 get length() { 79 return this.nodes.length; 80 } 81 82 83 /** 84 * Reads the direct parent of all nodes, optionally filtered by a selector. 85 * @param selector 86 * @return {OQuery} 87 */ 88 parent( selector = null ) { 89 return this.createNew( 90 this.nodes.map(node => node.parentElement ) 91 .filter( node => !!node ) // Filter non-existent parents 92 .filter( node => !selector || node.matches(selector) ) 93 ); 94 }; 95 96 97 /** 98 * Reads all parents of all nodes, optionally filtered by a selector. 99 * 100 * @param selector 101 * @return {OQuery} 102 */ 103 parents( selector = null ) { 104 let parents = []; 105 for( let node of this.nodes ) 106 while (node) { 107 node = node.parentElement; 108 if ( node && (!selector || node.matches(selector)) ) 109 parents.unshift(node); 110 } 111 return this.createNew( parents ); 112 }; 113 114 115 /** 116 * reads the closest anchestor that meets the selector. 117 * 118 * @param selector 119 * @return {OQuery} 120 */ 121 closest( selector ) { 122 return this.createNew( this.nodes.map(node => node.closest( selector ) ).filter( node => node !== null ) ); 123 }; 124 125 children( selector ) { 126 let result = []; 127 for( let node of this.nodes ) 128 result = result.concat( Array.from(node.children).filter( node => !selector || node.matches(selector) ) ); 129 return this.createNew( result ); 130 }; 131 132 find(selector) { 133 let result = []; 134 for( let node of this.nodes ) 135 result = result.concat( Array.from(node.querySelectorAll(selector)) ); 136 return this.createNew( result ); 137 }; 138 139 text( value ) { 140 141 if ( typeof value !== 'undefined' ) { 142 this.nodes.forEach(node => node.textContent = value ); 143 return this; 144 } 145 else { 146 return this.nodes[0].textContent; 147 } 148 }; 149 150 addClass( name ) { 151 this.nodes.forEach(node => node.classList.add( name ) ); 152 return this; 153 }; 154 155 removeClass ( name ) { 156 157 this.nodes.forEach( 158 node => node.classList.remove( name ) 159 ); 160 return this; 161 }; 162 163 hasClass( name ) { 164 for( let node of this.nodes ) 165 if ( node.classList.contains( name ) ) 166 return true; 167 168 return false; 169 }; 170 171 toggleClass( name ) { 172 if ( this.hasClass( name ) ) 173 this.removeClass( name ); 174 else 175 this.addClass( name ); 176 177 return this; 178 }; 179 180 181 remove() { 182 this.nodes.forEach(node => node.remove() ); 183 return this; 184 }; 185 186 187 188 click ( handler ) { 189 this.on( 'click',handler ); 190 return this; 191 }; 192 dblclick ( handler ) { 193 this.on( 'dblclick',handler ); 194 return this; 195 }; 196 mouseover( handler ) { 197 this.on( 'mouseover',handler ); 198 return this; 199 }; 200 keypress( handler ) { 201 this.on( 'keypress',handler ); 202 return this; 203 }; 204 keyup( handler ) { 205 this.on( 'keyup',handler ); 206 return this; 207 }; 208 submit( handler ) { 209 this.on( 'submit',handler ); 210 return this; 211 } 212 change( handler ) { 213 this.on( 'change',handler ) 214 return this; 215 } 216 input( handler ) { 217 this.on( 'input',handler ) 218 return this; 219 } 220 221 222 223 on ( event,handler ) { 224 if ( typeof handler !== 'undefined') 225 this.nodes.forEach(node => node.addEventListener( event,handler.bind(node) ) ); 226 else 227 this.nodes.forEach(node => node.dispatchEvent( new Event(event) ) ); 228 return this; 229 }; 230 231 each( handler ) { 232 let idx = -1; 233 for( let node of this.nodes ) 234 if ( handler.call(node,idx,node) === false ) 235 break; 236 237 return this; 238 } 239 240 toggle( handler ) { 241 let idx = -1; 242 for( let node of this.nodes ) 243 if ( handler.call(node,idx,node) === false ) 244 node.style.display = 'none'; 245 else 246 node.style.display = ''; 247 248 return this; 249 } 250 251 hide() { 252 this.nodes.forEach(node => node.style.display = 'none' ); 253 return this; 254 } 255 256 show() { 257 this.nodes.forEach(node => node.style.display = '' ); 258 return this; 259 } 260 261 append( el ) { 262 this.nodes.forEach(node => el.nodes.forEach(elnode => node.appendChild(elnode) ) ); 263 return this; 264 } 265 266 appendTo( el ) { 267 let to = query( el ); 268 to.append( this ) 269 return this; 270 } 271 272 attr( name,value ) { 273 if ( typeof value === 'undefined' ) 274 return this.nodes.length > 0 ? this.nodes[0].getAttribute(name) : ''; 275 276 this.nodes.forEach(node => node.setAttribute(name,value) ); 277 return this; 278 } 279 280 data( name,value) { 281 if ( typeof value === 'undefined' ) 282 if ( typeof name === 'undefined' ) 283 return this.nodes.length > 0 ? this.nodes[0].dataset : {}; 284 else 285 return this.nodes.length > 0 ? this.nodes[0].dataset[name] : null; 286 287 this.nodes.forEach(node => node.dataset[name] = value ); 288 return this; 289 290 } 291 292 html( value ) { 293 if ( typeof value === 'undefined') 294 return this.nodes.length > 0 ? this.nodes[0].innerHTML : ''; 295 296 this.nodes.forEach(node => node.innerHTML = value ); 297 return this; 298 } 299 300 val( value = null ) { 301 if ( value !== null ) { 302 this.nodes.forEach(node => node.value = value ); 303 return this; 304 } 305 else 306 return this.nodes.length > 0 ? this.nodes[0].value : ''; 307 } 308 309 empty() { 310 this.nodes.forEach(node => { 311 while (node.firstChild) { 312 node.removeChild(node.firstChild); 313 } 314 } ); 315 316 return this; 317 } 318 319 is( selector ) { 320 for( let node of this.nodes ) 321 if ( node.matches(selector) ) 322 return true; 323 324 return false; 325 } 326 327 toArray() { 328 return this.nodes; 329 } 330 331 eq( index ) { 332 return this.createNew( [ this.nodes[index] ] ); 333 } 334 335 index() { 336 if ( this.nodes.length == 0 ) 337 return -1; 338 339 let node = this.nodes[0]; 340 341 let children = node.parentNode.childNodes; 342 let num = 0; 343 for (let i=0; i<children.length; i++) { 344 if ( children[i] == node) return num; 345 if ( children[i].nodeType==1) num++; 346 } 347 return -1; 348 } 349 350 }
Downloadmodules/cms/ui/themes/default/script/Oquery.js
History Tue, 1 Mar 2022 23:03:32 +0100 dankert New: OQuery support for 'parent(selector)' and 'parents(selector)' Tue, 22 Feb 2022 21:37:08 +0100 dankert Fix: Displaying the QRCode was broken. Now the QR code is styled with CSS :) Mon, 6 Dec 2021 23:21:18 +0100 dankert Fixes: Click on search results will close the search results. Sat, 17 Apr 2021 03:02:30 +0200 Jan Dankert Fix: Table sorter (was broken since the migration to OQuery) Thu, 15 Apr 2021 21:24:23 +0200 Jan Dankert New: Using a Proxy for calling the event handler in the correct context; Added documentation Mon, 12 Apr 2021 23:46:06 +0200 Jan Dankert New: Smaller CSS-Files, because third-party-CSS (editors...) is loaded dynamically if necessary. Thu, 1 Apr 2021 22:53:24 +0200 Jan Dankert Fix: Search Thu, 1 Apr 2021 22:20:52 +0200 Jan Dankert Using subclasses for the "JQuery"-Plugins. Thu, 1 Apr 2021 01:01:54 +0200 Jan Dankert New: Some fixes for OQuery, our new selfmade light JQuery replacement. Now the UI is back again. Wed, 31 Mar 2021 01:52:57 +0200 Jan Dankert New: Replace JQuery with OQuery, a selfmade light JQuery replacement.