Require robust autocomplete field

M

Mark Smith

Hi,

I'm looking for a way to implement an autocomplete field on some of my
forms.

I need both ajax support (for larger lists) and also a way to pass in
json arrays for smaller lists.

The best I have found so far is this one:

http://www.pengoworks.com/workshop/jquery/autocomplete.htm

(I know, jQuery - yuck!)

The problem with this one (and others) is that the rendering breaks
when any of the strings contain html entity encoded characters. This
is because the dropdown list is html, but the text box value is raw
text. Fixing the code myself to reconcile the two looks like it will
become very messy.

If anyone could recommend a way to do this properly. (Either a plugin
for an existing framework or a tried and tested pattern for
implementing autocomplete in pure JS would be greatly appreciated)

Thanks
 
E

Evertjan.

Mark Smith wrote on 05 okt 2009 in comp.lang.javascript:
Hi,

I'm looking for a way to implement an autocomplete field on some of my
forms.

I need both ajax support (for larger lists) and also a way to pass in
json arrays for smaller lists.

ajax and json are not parallel technologies,
json being just a way of defining stream content coding and
ajax being just a way to import these streams from the server
to an existing client page.

Perhaps you mean you want to have the smaller amounts of data hard coded
in your page?
The best I have found so far is this one:

http://www.pengoworks.com/workshop/jquery/autocomplete.htm

(I know, jQuery - yuck!)

The problem with this one (and others) is that the rendering breaks
when any of the strings contain html entity encoded characters. This
is because the dropdown list is html, but the text box value is raw
text. Fixing the code myself to reconcile the two looks like it will
become very messy.

You must have serverside controll over the stream,
so you can prepare the streams to your liking with serverside scripting.
If anyone could recommend a way to do this properly. (Either a plugin
for an existing framework or a tried and tested pattern for
implementing autocomplete in pure JS would be greatly appreciated)

Methinks that, if you miss the skil to do it yourself, Mark,
hiring a professional would be the way to go.
 
G

Gregor Kofler

Mark Smith meinte:
Hi,

I'm looking for a way to implement an autocomplete field on some of my
forms.

I need both ajax support (for larger lists) and also a way to pass in
json arrays for smaller lists.

The best I have found so far is this one:

http://www.pengoworks.com/workshop/jquery/autocomplete.htm

Erm... The "AJAX" version doesn't do anything on my FF3.5
(I know, jQuery - yuck!)
$input.keydown(...).focus(...).blur(...);

Nice.

The problem with this one (and others) is that the rendering breaks
when any of the strings contain html entity encoded characters. This
is because the dropdown list is html, but the text box value is raw
text.

Always use "raw" text and avoid innerHTML when creating the list.

Gregor
 
E

Eric Bednarz

Gregor Kofler said:
$input.keydown(...).focus(...).blur(...);

Nice.

Chaining is not just nice, it is beautiful!

For example, I’ve seen this the other day:

<input
type="button"
value="Submit"
onclick="$('form').attr('action', $('form').attr('action')).submit();">

This clearly demonstrates how jQuery makes everyday’s tedious tasks much
simpler and quicker.
 
G

Gregor Kofler

Eric Bednarz meinte:
Chaining is not just nice, it is beautiful!

For example, I’ve seen this the other day:

<input
type="button"
value="Submit"
onclick="$('form').attr('action', $('form').attr('action')).submit();">

This clearly demonstrates how jQuery makes everyday’s tedious tasks much
simpler and quicker.

Sheer magic - conciseness and readability form a holy alliance. In
addition your computer gets its daily exercise.

Gregor
 
M

Mark Smith

Mark Smith wrote on 05 okt 2009 in comp.lang.javascript:




ajax and json are not parallel technologies,
json being just a way of defining stream content coding and
ajax being just a way to import these streams from the server
to an existing client page.

Perhaps you mean you want to have the smaller amounts of data hard coded
in your page?

I know, for larger lists I want to deliver subsets based on a query.
(Either json, xml, raw text, I don't really mind.

For smaller lists it makes more sense to dump it all directly on the
page as json on page load....
Methinks that, if you miss the skil to do it yourself, Mark,
hiring a professional would be the way to go.

I don't lack the skill. Just didn't want to reinvent the wheel, seems
like a common requirement. Like I said if anyone had any pointers it
would be appreciated...

Thanks
 
E

Evertjan.

Mark Smith wrote on 06 okt 2009 in comp.lang.javascript:
I don't lack the skill. Just didn't want to reinvent the wheel, seems
like a common requirement. Like I said if anyone had any pointers it
would be appreciated...

Reinventing the wheel in programming is often simpler
than debugging the square wheels of others.

Looking at the methods of others however can be very helpful, I agree.
 
V

VK

the rendering breaks
when any of the strings contain html entity encoded characters. This
is because the dropdown list is html, but the text box value is raw
text.

It is not completely correct. Not every HTML encoded entity "trash
out" the input but only &lt; &gt; &amp; and &nbsp; and only if one
treats the input string as HTML code (using .innerHTML) From the point
of view of a running script any string is a Unicode sequence, so this
behavior is still a mystery, especially &nbsp; It might have something
to do with the code stability on .innerHTML assignments - just a
guess.

You may use innerText / textContent instead - in this case the string
reading goes as expected. Test case follows:

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;
charset=iso-8859-1">
<title>NoScript</title>
</head>
<body>
<h1 id="Sample">&laquo; &raquo; &Theta; &hellip;
&image; &rArr; &apos; &quot; &lt; &gt; &amp; &nbsp;</h1>
<form action="" method="GET" onsubmit="return false;">
<input type="text" name="txt" size="30">
<input type="button" value="Test innerHTML"
onclick="
this.form.elements['txt'].value = document.getElementById
('Sample').innerHTML;
">
<input type="button" value="Test innerText"
onclick="
/*@cc_on
/*@if (@_jscript)
var IE = true;
@else @*/
var IE = false;
/*@end
@*/
this.form.elements['txt'].value = (IE)?
document.getElementById('Sample').innerText
:
document.getElementById('Sample').textContent;
">
</form>
</body>
</html>
 
T

Thomas 'PointedEars' Lahn

VK said:
the rendering breaks when any of the strings contain html entity encoded
characters. This is because the dropdown list is html, but the text box
value is raw text.

It is not completely correct. Not every HTML encoded entity "trash
out" the input but only &lt; &gt; &amp; and &nbsp; and only if one
treats the input string as HTML code (using .innerHTML) [...]

Rubbish.


PointedEars
 
R

RobG

<input type="button" value="Test innerText"
 onclick="
/*@cc_on
   /*@if (@_jscript)
      var IE = true;
   @else @*/
      var IE = false;
   /*@end
@*/
this.form.elements['txt'].value = (IE)?
 document.getElementById('Sample').innerText
 :
 document.getElementById('Sample').textContent;
 ">

That is a spectacularly bad piece of code - there are many browsers
that aren't IE that implement innerText and not textContent.

A feature test using typeof offers far better cross-browser support:

var getText = (function() {
var el = document.createElement('p');
if (typeof el.textContent == 'string')
return function(el){return el.textContent;};
if (typeof el.innerText == 'string')
return function(el){return el.innerText;};
el = null;
})();
 
V

VK

<input type="button" value="Test innerText"
 onclick="
/*@cc_on
   /*@if (@_jscript)
      var IE = true;
   @else @*/
      var IE = false;
   /*@end
@*/
this.form.elements['txt'].value = (IE)?
 document.getElementById('Sample').innerText
 :
 document.getElementById('Sample').textContent;
 ">

That is a spectacularly bad piece of code - there are many browsers
that aren't IE that implement innerText and not textContent.

The current set of UAs I do care as of now is (listed by compatibility
priority, the top is the highest one):
Microsoft Internet Explorer 8.0 (X-UA-Compatible =6 =7 inclusive)
Mozilla Firefox 3.5
Safari 4.0
Google Chrome 3.0
Opera 10.0

Out of this list you have no guarantee of anything, including
document.createElement method. My principles are the same over years:
"unless you SAW it working in browser X.y under OS Y.z, it does NOT
work in browser X.y under OS Y.z". No amount of theoretical
considerations can override this simple truth.
 
V

VK

It is not completely correct. Not every HTML encoded entity "trash
out" the input but only &lt; &gt; &amp; and &nbsp; and only if one
treats the input string as HTML code (using .innerHTML) [...]

Rubbish.

Do you have a counterexample?
 
T

Thomas 'PointedEars' Lahn

VK said:
It is not completely correct. Not every HTML encoded entity "trash
out" the input but only &lt; &gt; &amp; and &nbsp; and only if one
treats the input string as HTML code (using .innerHTML) [...]

Rubbish.

Do you have a counterexample?

Do you have an example that proves it?


PointedEars
 
T

Thomas 'PointedEars' Lahn

VK said:
Thomas said:
VK said:
It is not completely correct. Not every HTML encoded entity "trash
out" the input but only &lt; &gt; &amp; and &nbsp; and only if one
treats the input string as HTML code (using .innerHTML) [...]

Rubbish.
Do you have a counterexample?
Do you have an example that proves it?

?? The test is in my first post. Can you see it?

Do you mean that *invalid* *markup*?


PointedEars
 
V

VK

VK said:
Thomas said:
VK wrote:
It is not completely correct. Not every HTML encoded entity "trash
out" the input but only &lt; &gt; &amp; and &nbsp; and only if one
treats the input string as HTML code (using .innerHTML) [...]
Rubbish.
Do you have a counterexample?
Do you have an example that proves it?
?? The test is in my first post. Can you see it?

Do you mean that *invalid* *markup*?

Really? What HTML validator are you using? I am still on W3C one.

http://validator.w3.org/#validate_by_input
[past my HTML sample]
[press Check]
"This document was successfully checked as HTML5!"

It is irrelevant though to the issue. If you like HTML 4.01 or XHTML
better, simply insert the code from BODY to your own preferred test
page.
 
R

RobG

[...]
<input type="button" value="Test innerText"
 onclick="
/*@cc_on
   /*@if (@_jscript)
      var IE = true;
   @else @*/
      var IE = false;
   /*@end
@*/
this.form.elements['txt'].value = (IE)?
 document.getElementById('Sample').innerText
 :
 document.getElementById('Sample').textContent;
 ">
That is a spectacularly bad piece of code - there are many browsers
that aren't IE that implement innerText and not textContent.

The current set of UAs I do care as of now is (listed by compatibility
priority, the top is the highest one):

It is very poor design to deliberately break functionality in browsers
that *you* don't care about when a funcionally equivalent alternative
is available that will work in nearly all browsers that support a
scriptable DOM.

 Microsoft Internet Explorer 8.0 (X-UA-Compatible =6 =7 inclusive)
 Mozilla Firefox 3.5
 Safari 4.0
 Google Chrome 3.0
 Opera 10.0

Out of this list you have no guarantee of anything, including
document.createElement method.

Perhaps you should join the jQuery development team, that seems to be
their list of browsers too. The following quote is apt:

"Much of the time it feels like the decision to limit
browser support to less than half a dozen popular desktop
web browsers was no more than the consequence of the person
who did it not knowing how to do anything else, that the
costs of the alternatives are being estimated by people who
could not produce them (so don't actually know what is
involved), and that the people who will have to live with
the financial fall-out of these decisions don't even realise
what has happened, and so never could have ratified those
decisions."
Richard Cornford
clj: Re-enable disabled form elements when user goes 'Back'
<URL: http://groups.google.com/group/comp.lang.javascript/msg/b2b3849ffad66853
 
R

RobG

RobG pisze:


<input type="button" value="Test innerText"
 onclick="
/*@cc_on
   /*@if (@_jscript)
      var IE = true;
   @else @*/
      var IE = false;
   /*@end
@*/
this.form.elements['txt'].value = (IE)?
 document.getElementById('Sample').innerText
 :
 document.getElementById('Sample').textContent;
 ">
That is a spectacularly bad piece of code - there are many browsers
that aren't IE that implement innerText and not textContent.
A feature test using typeof offers far better cross-browser support:
var getText = (function() {
  var el = document.createElement('p');
  if (typeof el.textContent == 'string')
    return function(el){return el.textContent;};
  if (typeof el.innerText == 'string')
    return function(el){return el.innerText;};
  el = null;
})();

What do you think about this solution that I was created some day?

function getInnerText(el){

   var childs = el.childNodes;
   var txt = "";
   for (var i=0, len=childs.length; i<len; ++i){
     if (childs.nodeType == 3) {
     txt += childs.data;
     } else if (childs.nodeType == 1){
     txt += getInnerText(childs);
     }
   }
   return txt.replace(/\s+/g,' ');
}


Superb! I couldn't have done better myself! ;-)

"Obtaining the textNode from within multiple elements"
<URL: http://groups.google.com/group/comp.lang.javascript/msg/eb0aca4db4ec6d97
There is a discussion of innerText and Safari 2 in the thread below.
There are other issues with an innerText/textContent fork such as they
handle whitespace and returns differently. The above recursive method
can return different strings in different browsers too, it has
limitations.

"Need something like doc.getElementById().innerHTML..."
<URL: http://groups.google.com/group/comp...95c403b8809/69a8714d71a2be24#69a8714d71a2be24
 
G

Garrett Smith

RobG said:
<input type="button" value="Test innerText"
onclick="
/*@cc_on
/*@if (@_jscript)
var IE = true;
@else @*/
var IE = false;
/*@end
@*/
this.form.elements['txt'].value = (IE)?
document.getElementById('Sample').innerText
:
document.getElementById('Sample').textContent;
">

That is a spectacularly bad piece of code - there are many browsers
that aren't IE that implement innerText and not textContent.

A feature test using typeof offers far better cross-browser support:

var getText = (function() {
var el = document.createElement('p');
if (typeof el.textContent == 'string')
return function(el){return el.textContent;};
if (typeof el.innerText == 'string')
return function(el){return el.innerText;};
el = null;
})();

Can be much better with a simple property:

var TEXT_CONTENT = typeof documentElement.textContent === "string" ?
"textContent" : "innerText";

// usage:
alert(document.body.textContent);

The textContent property is DOM 3.

There are scriptable browsers that support neither textContent nor
innerText. For example, Blackberry browser.

It may be the case that the program can be designed differently so as to
avoid the problem of reading textContent/innerText, but to read the
"data" of a text node.
 
P

Peter

RobG pisze:
RobG pisze:


[...]
<input type="button" value="Test innerText"
onclick="
/*@cc_on
/*@if (@_jscript)
var IE = true;
@else @*/
var IE = false;
/*@end
@*/
this.form.elements['txt'].value = (IE)?
document.getElementById('Sample').innerText
:
document.getElementById('Sample').textContent;
">
That is a spectacularly bad piece of code - there are many browsers
that aren't IE that implement innerText and not textContent.
A feature test using typeof offers far better cross-browser support:
var getText = (function() {
var el = document.createElement('p');
if (typeof el.textContent == 'string')
return function(el){return el.textContent;};
if (typeof el.innerText == 'string')
return function(el){return el.innerText;};
el = null;
})();
What do you think about this solution that I was created some day?

function getInnerText(el){

var childs = el.childNodes;
var txt = "";
for (var i=0, len=childs.length; i<len; ++i){
if (childs.nodeType == 3) {
txt += childs.data;
} else if (childs.nodeType == 1){
txt += getInnerText(childs);
}
}
return txt.replace(/\s+/g,' ');
}


Superb! I couldn't have done better myself! ;-)


I knew that somewhere I saw that trick :p
"Obtaining the textNode from within multiple elements"
<URL: http://groups.google.com/group/comp.lang.javascript/msg/eb0aca4db4ec6d97

There is a discussion of innerText and Safari 2 in the thread below.
There are other issues with an innerText/textContent fork such as they
handle whitespace and returns differently. The above recursive method
can return different strings in different browsers too, it has
limitations.

IMHO this recursiuve function is much better, than
innerText/textContent, but I can not imagine what restrictions may have
a solution.

Secondly, I'm sure at least that I collect the content by nodeType,
which should give me 100% sure that there is text. Hm, what limitations
could be for this solution?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,020
Latest member
GenesisGai

Latest Threads

Top