Ruby on Rails | Screencasts | Download | Documentation | Weblog | Community | Source

Ticket #3572 (closed defect: invalid)

Opened 3 years ago

Last modified 3 years ago

Element.show & Element.getDimensions failes on elements with display: none

Reported by: matthias <matthias@knallgrau.at> Assigned to: sam@conio.net
Priority: normal Milestone:
Component: Prototype Version: 1.0.0
Severity: normal Keywords:
Cc:

Description

If you define display: none; via a styleClass to an element, Element.show and Element.getDimensions will fail:

Testcase:

<style>
.hidden { display: none; }
</style>
<div id="hidden" class="hidden">I'm hidden</div>
<div id="visible" style="display: none;">I'm visible</div>
<script>
Element.show($("hidden"));
Element.show($("visible"));
</script>

The problem is simply that if you remove the direct style-setting for the element element.display = ''; the style will be inherited from the styleClass. element.display = 'auto'; won't work too. So we would need to do this manualy.

Here is a working approach:

Object.extend(Element, {
  BLOCK_LEVEL: ["address","blockquote","center","dl","dir","div","fieldset",
	        "form","h1-6","hr","isindex","menu","noframes","noscript",         
                "ol","p","pre","table","ul","center","dir","menu","noframes","isindex"],

  visible: function(element) {
    return $(element).style.display != 'none';
  },
  
  toggle: function() {
// ...
  },

  isBlockLevel: function(element) {
    if (Element.getStyle(element, "display") == "block" || 
        element.isBlockLevel == true || 
        Element.BLOCK_LEVEL.indexOf(element.nodeName.toLowerCase()) != -1) 
    { return element.isBlockLevel = true; } 
	 else { return element.isBlockLevel = false; }
  },

  hide: function() {
// ...
  },
  
  show: function() {
    for (var i = 0; i < arguments.length; i++) {
      var element = $(arguments[i]);
      element.style.display = Element.isBlockLevel(element) ? 'block' : '';
    }
  },

// ...

  getDimensions: function(element) {
    element = $(element);
    if (Element.getStyle(element, 'display') != 'none')
      return {width: element.offsetWidth, height: element.offsetHeight};
    
    // All *Width and *Height properties give 0 on elements with display none,
    // so enable the element temporarily
    var els = element.style;
    var originalVisibility = els.visibility;
    var originalPosition = els.position;
    els.visibility = 'hidden';
    els.position = 'absolute';
    els.display = Element.isBlockLevel(element) ? 'block' : '';
    // ...
    return {width: originalWidth, height: originalHeight};    
  },

  // ...

p.s. sorry for not providing a diff, but i have troubles with the correct linebreaks. did they change recently?

Attachments

prototype.js (46.3 kB) - added by anonymous on 03/30/06 20:28:25.

Change History

02/19/06 15:13:39 changed by Martin Bialasinski

This is not a valid solution. You cannot derive the display property to use from the element name. You would need to walk the cascade, stripping any display: none from the tail, as the stylesheet could mark any element as display: block. A common use is defining links as block to fill the whole area of LI elements in menus.

Also, table, tr, td and th are display: block only in IE (which is wrong), any sensible browser defines them as display: table, table-row etc.

03/30/06 20:28:25 changed by anonymous

  • attachment prototype.js added.

09/06/06 20:35:24 changed by brandon.aaron@gmail.com

  • status changed from new to closed.
  • resolution set to invalid.

And what if I want a block level element to display as inline. This is just a limitation of what we can do with CSS and Javascript. To properly use Element.show() and Element.hide() an inline style or set the style via Javascript. Otherwise the best option is to create some custom methods that meet your applications needs.