Skip to content

clonePosition() bug in prototype.js ver 1.7.3 #2643

Closed
@kiatng

Description

@kiatng

Summary (*)

Ref issue #1497. I experienced the bug reported here. I use Ajax.Autocompleter() in

Autocompleter.Base = Class.create({

and expected the div element to show up below the input element, but the div element top position was incorrectly calculated in clonePosition()

function clonePosition(element, source, options) {

Examples (*)

See example here to test. Copy paste in case the link no longer work:

HTML

<input type="text" id="autocomplete" name="autocomplete_parameter"/>
<div id="autocomplete_choices" class="autocomplete"></div>

Javascript

new Ajax.Autocompleter("autocomplete", "autocomplete_choices", "/url/on/server", {});

CSS
The styling of the div and the returned UL are important.
Applying a visual cue that an item is selected allows the user to take advantage of the keyboard navigation of the dropdown and adding background colors, borders, positioning, etc to the div (as the demo does) allows the UI element to stand out. The CSS from the demo applied to the examples would be:

div.autocomplete {
  position:absolute;
  width:250px;
  background-color:white;
  border:1px solid #888;
  margin:0;
  padding:0;
}
div.autocomplete ul {
  list-style-type:none;
  margin:0;
  padding:0;
}
div.autocomplete ul li.selected { background-color: #ffb;}
div.autocomplete ul li {
  list-style-type:none;
  display:block;
  margin:0;
  padding:2px;
  height:32px;
  cursor:pointer;
}

Proposed solution

Replace clonePosition() with this:

  function clonePosition(element, source, options) {
    options = Object.extend({
      setLeft:    true,
      setTop:     true,
      setWidth:   true,
      setHeight:  true,
      offsetTop:  0,
      offsetLeft: 0
    }, options || {});

    source  = $(source);
    element = $(element);
    var p, delta, layout, styles = {};

    if (options.setLeft || options.setTop) {
      p = Element.viewportOffset(source);
      delta = [0, 0];
      if (Element.getStyle(element, 'position') === 'absolute') {
        var parent = Element.getOffsetParent(element);
        if (parent !== document.body) delta = Element.viewportOffset(parent);
      }
    }

    var pageXY = { x: document.body.scrollLeft, y: document.body.scrollTop };

    if (options.setWidth || options.setHeight) {
      layout = Element.getLayout(source);
    }

    if (options.setLeft)
      styles.left = (p[0] + pageXY.x - delta[0] + options.offsetLeft) + 'px';
    if (options.setTop)
      styles.top  = (p[1] + pageXY.y - delta[1] + options.offsetTop)  + 'px';

    if (options.setWidth) {
      styles.width = layout.get('width')  + 'px';
    }
    if (options.setHeight) {
      styles.height = layout.get('height') + 'px';
    }

    return Element.setStyle(element, styles);
  }

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions