Description
Summary (*)
Ref issue #1497. I experienced the bug reported here. I use Ajax.Autocompleter()
in
magento-lts/js/scriptaculous/controls.js
Line 43 in ee46ff9
and expected the div
element to show up below the input
element, but the div
element top position was incorrectly calculated in clonePosition()
magento-lts/js/prototype/prototype.js
Line 4264 in ee46ff9
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);
}