1/* 2 * dom.js 3 * 4 * Copyright (C) 2006 - OS3 srl - http://www.os3.it 5 * 6 * Written by: Fabio Rotondo - [email protected] 7 * 8 * This is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU General Public 10 * License as published by the Free Software Foundation; 11 * version 2 of the License ONLY. 12 * 13 * This software is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public 19 * License along with this software; if not, write to the Free Software 20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 * 22 * NOTE: this is the GPL version of the library. If you want to include this 23 * library inside a CLOSED SOURCE / PROPRIETARY software, you need 24 * to purchase a COMMERCIAL LICENSE. See http://www.os3.it/license/ 25 * for more info. 26 */ 27 28/* 29 * 2009-09-07: Added the $c() function is like a getAllElementsByClassName ( element, class_name, [ starting_container == document ] ) 30 */ 31 32/** 33DOM Functions 34============= 35 36**/ 37 38liwe.dom = {}; 39 40// {{{ liwe.dom.get_offset_top ( elem ) 41/** 42.. function:: liwe.dom.get_offset_top ( elem ) 43 44 Calculates top offset of ``elem`` in pixels starting from the beginning of the web page. 45 46 :param elem: the DOM element 47 48 :rtype: an integer containing the offset top 49 50**/ 51liwe.dom.get_offset_top = function ( elm ) 52{ 53 var o_top = elm.offsetTop; 54 var o_parent = elm.offsetParent; 55 56 while ( o_parent && o_parent.tagName != "HTML" ) 57 { 58 // if ( o_parent.style.position == 'absolute' ) return o_top; 59 o_top += o_parent.offsetTop; 60 o_parent = o_parent.offsetParent; 61 } 62 63 return o_top; 64}; 65// }}} 66// {{{ liwe.dom.get_offset_left ( elem ) 67/** 68.. function:: liwe.dom.get_offset_left ( elem ) 69 70 Calculates left offset of ``elem`` in pixels starting from the beginning of the web page. 71 72 :param elem: the DOM element 73 74 :rtype: an integer containing the offset left 75**/ 76liwe.dom.get_offset_left = function ( elm ) 77{ 78 var o_left = elm.offsetLeft; 79 var o_parent = elm.offsetParent; 80 81 while ( o_parent ) 82 { 83 // if ( o_parent.style.position == 'absolute' ) return o_left; 84 // console.debug ( "parent: %o - o_parent: %s - left: %s", o_parent, o_parent.offsetParent, o_left ); 85 // if ( ! o_parent.offsetParent.offsetParent ) break; 86 o_left += o_parent.offsetLeft; 87 o_parent = o_parent.offsetParent; 88 } 89 90 return o_left; 91}; 92// }}} 93// {{{ liwe.dom.append_css ( css_file_name, id, as_first ) 94/** 95.. function:: liwe.dom.append_css ( css_file_name, id, as_first ) 96 97 Appends a new CSS declaration in the web page. The CSS ``ccs_file_name`` will be added (and loaded by the browser) 98 to the web page. Optionally, you can specify an ``id`` and you can also force the insertion as the first CSS in the 99 page by setting ``as_first`` to true. 100 101 :param css_file_name: the CSS file name you want to append 102 :param id: the id of the new CSS declaration (optional) 103 :param as_first: if set to ``true``, CSS will be added as the first CSS declaration of the page. 104 105 :rtype: this function returns nothing 106**/ 107liwe.dom.append_css = function ( css_file, id, as_first ) 108{ 109 var head = document.getElementsByTagName ( "head" ) [ 0 ]; 110 var new_css = document.createElement ( "link" ); 111 112 new_css.href = css_file; 113 new_css.type = "text/css"; 114 new_css.rel = "stylesheet"; 115 if ( id ) new_css.id = id; 116 117 if ( as_first ) 118 head.insertBefore ( new_css, head.firstChild ); 119 else 120 head.appendChild ( new_css ); 121}; 122// }}} 123// {{{ liwe.dom.get_padding_width ( elem ) 124/** 125.. function:: liwe.dom.get_padding_width ( elem ) 126 127 This function calculates the padding width of ``elem`` 128 129 :param elem: DOM element to calculate the padding width from. 130 131 :rtype: an integer containing the padding width 132**/ 133liwe.dom.get_padding_width = function ( el ) 134{ 135 var oldw = el.clientWidth; 136 var neww; 137 138 el.style.width = "0px"; 139 neww = el.clientWidth; 140 141 el.style.width = ( oldw - neww ) + "px"; 142 143 return neww; 144}; 145// }}} 146// {{{ liwe.dom.get_padding_height ( elem ) 147/** 148.. function:: liwe.dom.get_padding_height ( elem ) 149 150 This function calculates the padding height of ``elem`` 151 152 :param elem: DOM element to calculate the padding height from. 153
154 :rtype: an integer containing the padding height 155**/ 156liwe.dom.get_padding_height = function ( el ) 157{ 158 var oldh = el.clientHeight; 159 var newh; 160 161 el.style.height = "0px"; 162 newh = el.clientHeight; 163 164 el.style.height = ( oldh - newh ) + "px"; 165 166 return newh; 167}; 168// }}} 169// {{{ liwe.dom.get_size ( elem ) 170/** 171.. function:: liwe.dom.get_size ( elem ) 172 173 This function returns the width and height of ``elem``. 174 175 :param elem: DOM element to calculate the size from. 176 177 :rtype: a list with two integers: width and height respectively. 178**/ 179liwe.dom.get_size = function ( el ) 180{ 181 el = $el ( el ); 182 if ( ! el ) return [ 0, 0 ]; 183 return [ el.clientWidth, el.clientHeight ]; 184}; 185// }}} 186// {{{ liwe.dom.get_window_size () 187/** 188.. function:: liwe.dom.get_window_size () 189 190 This function returns the width and height of the current window. 191 192 :rtype: an object with two attributes ``width`` and ``height`` of the current window. 193**/ 194liwe.dom.get_window_size = function () 195{ 196 var s = document.createElement ( "div" ); 197 s.style.position = "absolute"; 198 s.style.bottom = "0px"; 199 s.style.right = "0px"; 200 s.style.width = "1px"; 201 s.style.height = "1px"; 202 s.style.visibility = "hidden"; 203 document.body.appendChild ( s ); 204 205 var w, h; 206 w = liwe.dom.get_offset_left ( s ) + s.clientWidth; 207 h = liwe.dom.get_offset_top ( s ) + s.clientHeight; 208 209 document.body.removeChild ( s ); 210 211 return { "width": w, "height": h }; 212}; 213// }}} 214// {{{ liwe.dom.create_element ( tag, name, parent ) 215/** 216.. function:: liwe.dom.create_element ( tag, name, parent ) 217 218 This function creates a new DOM element and adds it to the document DOM. 219 220 :param tag: the element tag you are creating. 221 :param name: the name of the element you are creating. 222 :param parent: the parent container of the new element (optional, defaults to document.body) 223 224 :rtype: this function returns nothing. 225**/ 226liwe.dom.create_element = function ( tag, name, parent ) 227{ 228 if ( ! parent ) parent = document.body; 229 230 // if ( document.ActiveXObject ) tag = '<' + tag + ' name="' + name + '">'; 231 // if ( document.all ) tag = '<' + tag + ' name="' + name + '">'; 232 233 var e = document.createElement ( tag ); 234 e.style.position = 'absolute'; 235 e.style.top = "0px"; 236 e.style.right = "0px"; 237 e.id = name; 238 e.name = name; 239 parent.appendChild ( e ); 240 241 return e; 242}; 243// }}} 244// {{{ liwe.dom.remove_element ( elem, parent ) 245/** 246.. function:: liwe.dom.remove_element ( elem, parent ) 247 248 This function removes the ``elem`` from the ``parent`` container. 249 If ``parent`` has not been specified, it will be set to ``document.body``. 250 251 :param elem: the DOM element you want to remove. 252 :param parent: the element container of ``elem`` (optional, defaults to document.body). 253 254 :rtype: this function returns nothing. 255**/ 256liwe.dom.remove_element = function ( e, parent ) 257{ 258 if ( ! parent ) parent = document.body; 259 260 parent.removeChild ( e ); 261}; 262// }}} 263// {{{ liwe.dom.get_event_pos ( e ) 264/** 265.. function:: liwe.dom.get_event_pos ( e ) 266 267 This function returns the ``x`` and ``y`` location where the event ``e`` has been fired. 268 269 :param e: the event you want to get ``x`` and ``y`` 270**/ 271liwe.dom.get_event_pos = function ( e ) 272{ 273 var posx = 0, posy = 0; 274 275 if ( ! _.isValid ( e ) ) e = window.event; 276 if ( e.pageX || e.pageY ) 277 { 278 posx = e.pageX; 279 posy = e.pageY; 280 } else if ( e.clientX || e.clientY ) { 281 if ( document.documentElement.scrollTop ) 282 { 283 posx = e.clientX + document.documentElement.scrollLeft; 284 posy = e.clientY + document.documentElement.scrollTop; 285 } else { 286 posx = e.clientX + document.body.scrollLeft; 287 posy = e.clientY + document.body.scrollTop; 288 } 289 } 290 291 return [ posx, posy ]; 292}; 293// }}} 294// {{{ liwe.dom.has_class ( elem, class_name ) 295/** 296.. function:: liwe.dom.has_class ( elem, class_name ) 297 298 This function returns ``true`` if ``elem`` has ``class_name``. 299 300 :param elem: the element to check class name. 301 302 :param class_name: the name of the class. 303 304 :rtype: ``true`` if ``elem`` has ``class_name``, ``false`` otherwise. 305**/ 306liwe.dom.has_class = function ( el, class_name ) 307{ 308 el = $el ( el ); 309 if ( ! el || ! el.className ) return false; 310 311 var cls = " " + el.className + " "; 312 var src = " " + class_name + " "; 313 314 return cls.indexOf ( src ) != -1; 315}; 316// }}} 317// {{{ liwe.dom.add_class ( elem, class_name ) 318/** 319.. function:: liwe.dom.add_class ( elem, class_name ) 320 321 This function adds ``class_name`` to ``elem``. 322 323 :param elem: the target element. 324
325 :param class_name: the new class name to be added to ``elem``. 326**/ 327liwe.dom.add_class = function ( el, class_name ) 328{ 329 if ( ! el ) return; 330 331 el = $el ( el ); 332 333 if ( ! _.isElement ( el ) ) return; 334 335 if ( _.isUndefined ( el.className ) ) el.className = class_name; 336 337 else 338 { 339 var res = el.className; 340 341 _.each ( class_name.split ( " " ), function ( v ) { 342 if ( ! liwe.dom.has_class ( el, v ) ) 343 res += " " + v; 344 } ); 345 346 el.className = res.trim (); 347 } 348}; 349// }}} 350// {{{ liwe.dom.del_class ( elem, class_name ) 351/** 352.. function:: liwe.dom.del_class ( elem, class_name ) 353 354 This function removes ``class_name`` to ``elem``. 355 356 :param elem: the target element. 357 358 :param class_name: the class name to be removed from ``elem``. 359**/ 360liwe.dom.del_class = function ( el, class_name ) 361{ 362 if ( ! el ) return; 363 364 el = $el ( el ); 365 366 if ( ! _.isElement ( el ) ) return; 367 368 if ( ! el.className ) return; 369 370 var cls = " " + el.className + " "; 371 372 _.each ( class_name.split ( " " ), function ( c ) 373 { 374 cls = cls.replace ( " " + c + " ", " " ); 375 } ); 376 377 el.className = cls.trim (); 378}; 379// }}} 380 381liwe.dom.toggle_class = function ( el, class_name, class_name2 ) 382{ 383 var res = ""; 384 if ( liwe.dom.has_class ( el, class_name ) ) 385 { 386 liwe.dom.del_class ( el, class_name ); 387 if ( class_name2 ) 388 { 389 liwe.dom.add_class ( el, class_name2 ); 390 res = class_name2; 391 } 392 393 } else { 394 liwe.dom.add_class ( el, class_name ); 395 res = class_name; 396 if ( class_name2 ) 397 liwe.dom.del_class ( el, class_name2 ); 398 } 399 return res; 400}; 401 402liwe.dom.reload_css = function () 403{ 404 var i, a, s; 405 a = document.getElementsByTagName ( 'link' ); 406 for( i = 0; i < a.length; i++ ) 407 { 408 s = a [ i ]; 409 if ( s.rel.toLowerCase ().indexOf ( 'stylesheet' ) >= 0 && s.href ) 410 { 411 var h = s.href.replace ( /(&|%5C?)forceReload=\d+/, '' ); 412 s.href = h + ( h.indexOf ( '?' ) >=0 ? '&' : '?' ) + 'forceReload=' + ( new Date ().valueOf () ); 413 } 414 } 415}; 416 417liwe.dom.get_scroll = function () 418{ 419 if ( typeof pageYOffset != 'undefined' ) 420 return [ pageXOffset, pageYOffset ]; 421 else 422 { 423 var b = document.body; 424 var d = document.documentElement; 425 d = d.clientHeight ? d : b; 426 return [ d.scrollLeft, d.scrollTop ]; 427 } 428}; 429 430liwe.dom.show = function ( el ) 431{ 432 el = $el ( el ); 433 if ( ! el || ! el.style ) return; 434 435 if ( el._old_display ) 436 el.style.display = el._old_display; 437 else 438 el.style.display = 'block'; 439}; 440 441liwe.dom.hide = function ( el ) 442{ 443 el = $el ( el ); 444 if ( ! el || ! el.style || el.style.display == 'none' ) return; 445 446 el._old_display = el.style.display; 447 el.style.display = 'none'; 448}; 449 450liwe.dom.parse = function ( str ) 451{ 452 var d = document.createElement ( "div" ); 453 var res = []; 454 var el; 455 456 d.innerHTML = str; 457 458 while ( d.childNodes.length ) 459 { 460 el = d.childNodes [ 0 ]; 461 462 res.push ( el ); 463 d.removeChild ( el ); 464 } 465 466 return res; 467}; 468 469liwe.dom.append_children = function ( el, children ) 470{ 471 if ( typeof ( children ) == 'string' ) children = liwe.dom.parse ( children ); 472 473 var t, l = children.length; 474 475 el = $el ( el ); 476 477 for ( t = 0; t < l; t ++ ) 478 el.appendChild ( children [ t ] ); 479}; 480 481// {{{ liwe.dom.get_style ( elem, style ) 482liwe.dom.get_style = function ( elem, style ) 483{ 484 var computed_style = null; 485 if ( typeof ( elem.currentStyle ) != 'undefined' ) 486 computed_style = elem.currentStyle; 487 else 488 computed_style = document.defaultView.getComputedStyle ( elem, null ); 489 if ( ! style ) 490 return computed_style; 491 else 492 return computed_style [ style ]; 493}; 494// }}} 495// {{{ liwe.dom.is_child_of ( parent, child ) 496liwe.dom.is_child_of = function ( parent, child ) 497{ 498 if( _.isValid ( child ) ) 499 { 500 while( child.parentNode ) 501 { 502 if( ( child = child.parentNode ) == parent ) 503 { 504 return true; 505 } 506 } 507 } 508 return false; 509}; 510// }}} 511// {{{ liwe.dom.supports = function ( prop ) 512liwe.dom.supports = function ( prop ) 513{ 514 console.warn ( "liwe.dom.supports() is DEPRECATED. Use liwe.utils.supports() instead." ); 515 console.trace (); 516 return liwe.utils.supports ( prop ); 517}; 518// }}} 519// {{{ function $c ( element, class_name, base ) 520/* 521 * $c ( element, class_name, base ) 522 * 523 * element - Element kind (eg. "div" ) 524 * class_name - Name of class that the element should contain
525 * base - Starting point for getElementsByTagName() (default: document) 526 * 527 * returns: a list of elements of kind ``element`` with the ``class_name`` set 528 */ 529function $c ( element, class_name, base, skip_class_name ) 530{ 531 if ( ! base ) base = document; 532 if ( ! skip_class_name ) skip_class_name = "0xdeadbeef"; 533 534 base = $el ( base ); 535 var elements = base.getElementsByTagName ( element ); 536 var t, l = elements.length; 537 var cls= [], res = [], el; 538 539 for ( t = 0; t < l; t ++ ) 540 { 541 el = elements [ t ]; 542 cls = el.className.split ( ' ' ); 543 try 544 { 545 if ( cls.indexOf ( class_name ) == -1 ) continue; 546 if ( cls.indexOf ( skip_class_name ) != -1 ) continue; 547 } catch ( err ) 548 { 549 if ( el.className.indexOf ( class_name ) == -1 ) continue; 550 if ( el.className.indexOf ( skip_class_name ) != -1 ) continue; 551 } 552 553 res.push ( el ); 554 } 555 556 return res; 557} 558// }}} 559// {{{ function $d ( el, mode ) 560/* 561 * $d ( el, mode ) 562 * 563 * Sets the style.display of element ``el`` to ``mode`` 564 */ 565function $d ( el, mode ) 566{ 567 var e = $el ( el ); 568 if ( ! e ) 569 { 570 console.warn ( "Element: %s not found", el ); 571 console.trace (); 572 return; 573 } 574 575 e.style.display = mode; 576} 577// }}} 578// {{{ function get_highest_zindex ( check_on ) 579/* 580 * get_highest_zindex ( check_on ) 581 * 582 * Compare and return highest z-index among dom elements. Param 'check_on' define on which dom element compare to ( default is 'div' ) 583 */ 584liwe.dom.get_highest_zindex = function ( check_on ) 585{ 586 var el = ( ! check_on ) ? 'div' : check_on; 587 var z = 0, tmp, val; 588 var elems = document.getElementsByTagName ( el ); 589 for ( var c = 0; c < elems.length; c++ ) 590 { 591 //if ( document.defaultView ) val = document.defaultView.getComputedStyle ( elems[c], null ).getPropertyValue ( 'z-index' ); 592 val = liwe.dom.get_style ( elems [ c ], 'zIndex' ); 593 //if ( elems [ c ].currentStyle ) val = elems [ c ].currentStyle [ 'zIndex' ]; 594 //if ( window.getComputedStyle ) val = window.getComputedStyle ( elems[c], null ).getPropertyValue ( 'z-index' ); 595 596 tmp = parseInt ( val, 10 ); 597 598 if ( ( ! isNaN ( tmp ) ) && ( tmp > z ) ) z = tmp; 599 } 600 return z; 601}; 602// }}} 603// {{{ function is_visible ( elem ) 604/* 605 * function is_visible ( elem ) 606 * 607 * traverse dom up to first hidden parentNode if any. 608 */ 609liwe.dom.is_visible = function ( el, top_elem ) 610{ 611 //FIXME:error if top_elem is not defined 612 var last = document.body; 613 var dis, vis; 614 615 el = $el ( el ); 616 617 if ( ! el ) return false; 618 if ( top_elem ) last = $el ( top_elem ); 619 620 while ( 1 ) 621 { 622 vis = liwe.dom.get_style ( el , 'visibility' ); 623 dis = liwe.dom.get_style ( el , 'display' ); 624 625 if ( vis == 'hidden' || dis == 'none' ) return false; 626 if ( el == last ) return true; 627 628 el = el.parentNode; 629 if ( ! el ) return true; 630 } 631}; 632// }}} 633// {{{ function get_body_size () 634liwe.dom.get_body_size = function () 635{ 636 var w = document.documentElement ? document.documentElement.clientWidth : document.body.clientWidth; 637 var h = document.documentElement ? document.documentElement.clientHeight : document.body.clientHeight; 638 return [ w, h ]; 639}; 640// }}} 641// {{{ function in_viewport () 642liwe.dom.in_viewport = function ( el ) 643{ 644 console.warn ( "DEPRECATION WARNING: do not use lowe.dom.in_viewport, use liwe.dom.get_rect() instead" ); 645 return liwe.dom.get_rect ( el ).inside_viewport; 646 647/* 648 var rect = liwe.dom.get_rect ( el ); 649 650 return ( 651 rect.bottom >= 0 && 652 rect.right >= 0 && 653 rect.top <= ( window.innerHeight || document.documentElement.clientHeight ) && 654 rect.left <= ( window.innerWidth || document.documentElement.clientWidth ) 655 ); 656*/ 657}; 658// }}} 659 660liwe.dom.get_rect = function ( e ) 661{ 662 var $e = $( e ); 663 664 var $window = $(window), 665 scrollLeft = $window.scrollLeft(), 666 scrollTop = $window.scrollTop(), 667 offset = $e.offset(), 668 rect1 = { x1: scrollLeft, y1: scrollTop, x2: scrollLeft + $window.width(), y2: scrollTop + $window.height() }, 669 rect2 = { x1: offset.left, y1: offset.top, x2: offset.left + $e.width(), y2: offset.top + $e.height() }; 670 671 return { 672 x: offset.left - scrollLeft, 673 y: offset.top - scrollTop, 674 w: $e.width (), 675 h: $e.height (), 676 inside_viewport: rect1.x1 < rect2.x2 && rect1.x2 > rect2.x1 && rect1.y1 < rect2.y2 && rect1.y2 > rect2.y1, 677 scroll_left: scrollLeft, 678 scroll_top: scrollTop 679 }; 680}; 681 682liwe.dom.disable_input = function ( input ) 683{ 684 input.disabled = 1; 685}; 686 687function $data ( el ) 688{ 689 el = $el ( el ); 690 if ( ! el ) return {}; 691 692 var dct = {}; 693 694 _.each ( el.attributes, function ( attr ) 695 { 696 if ( attr.name.indexOf ( 'data-' ) === 0 ) 697 dct [ attr.name.substr ( 5 ) ] = attr.value; 698 } ); 699 700 return dct; 701}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.