This patch is an emanation from this cck/nodereference issue (see more specifically comment #10)

the issue

In short, an autocomplete field is used to select a node by entering (a part of) its title.
Really handy, and practically the only way to select between 100+ nodes...

Now, node titles are not unique in drupal - nothing enforces that, and that's really handy too.
The completion list provides the ability to display additional information about a node (ype, fields...), so that the user can choose correctly beetween nodes with the same title.
But once the user has clicked the node he wants, all you get is the title of the node, so at submission time you can't tell which one of the nodes with this title he actually selected. CCK currently picks the 1st one SQL returns. Veeeery error-prone.

Problem is, the autocomplete widget outputs in the same place it take its input, so the two have to be homogenous (a node title).
We need an additional (hidden) field that receives the nid.

the (proposed) solution

This patch extends the autocomplete widget by adding the ability to define additional "target fields" (possibly hidden), that get updated whith additional content (the nid, in my example) when an item in the completion list is selected.

It's used this way :

$form['target1'] = array(
  '#type' => 'hidden',
);
$form['main_field'] = array(
  '#type' => 'textfield',
  '#title' => ...
  '#autocomplete_path' => ...
);
$form['target2'] = array(
  '#type' => 'hidden',
);
$form['node_name']['#autocomplete_targets'] => array(&$form['target1'], &$form['target1']);

with the autocomplete callback returning an array in the form :

[text for the main field] => array('display' => text for the completion list , 
                                   'targets' => array(texts for the additional targets))

Side note :
this format is not really coherent but ensures compatibility with the 'simple' autocompletes that are already in use. Maybe we can drop compatibility, update core, and have a more coherent :

[text for the completion list] => array(text for the main field, texts for the targets...)
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

yched’s picture

FileSize
3.5 KB

re-rolled against current HEAD

yched’s picture

FileSize
2.67 KB

And here is a concrete example (on author field in node submission form)

It is just for the sake of demonstration, completely useless, and of course not meant to get committed :-)

yched’s picture

FileSize
3.24 KB

re-rolled against current HEAD

Steven’s picture

It's kind of bad though as you really don't get the equivalent functionality without JS.

You can get around this problem with a trick: title (#node id). When reading in the value, you look for the node id, and use it if present. If only title is there, you take the first matching node by title. When filling in from the autocomplete, you fill in with title (#node id), so there is no confusion about which was selected.

You can even make it better by allowing users to paste in the URL to a node as well. Non-JS users will need to visit the page of the node they're looking for anyway, so then they can just copy/paste that as a friendlier fallback.

It's still human readable, very user-friendly with JS turned on, while still degrading to a reasonable substitute otherwise (select nodes by title, by title+nid and by url).

yched’s picture

It's kind of bad though as you really don't get the equivalent functionality without JS.
I don't quite agree with that.

The autocomplete feature itself provides a functionality you don't get without js : pick an item amongst items matching your input.
This patch is intended to tackle an issue within this js functionnality (namely : you don't really know what the user has picked)
It leaves the 'non-js' functionnality exactly where it currently is :
deal with the user "keyboard" input, which might be invalid or ambiguous (and this you have to deal with anyway, since even a js-enabled user might have typed is input straight ahead, without selecting an item in the completion list)


You can get around this problem with a trick: title (#node id).
I considered this workaround too. In fact this is precisely what I'm trying to avoid, for it breaks the unwritten (?) "keep nids out of users sight" rule.

Currently nids are absent from about the whole drupal UI. Except from (non aliased) node-urls, I can't think of any place in drupal interface where you can see one. This is an internal, code-related concept, that doesn't mean anything to the users.

I don't think we have a case here to break that rule : bringing out nids doesn't bring anything to the user, it's "just" for our own internal, technical reasons, so they should stay out of the UI.


This being said, I have tried in my above patch to abstract from the basic need (one hidden "id" field), and leave this open to various uses (several custom defined targets, with the idea in mind that these targets might be not just textfieds, but also any markup element in your form - current patch doesn't allow this ATM, but it painlessly could).

This does in fact extend the "js / non-js" gap. Maybe this is not what we want.
What about a narrowed, "black-boxed" version of the functionnality :

$form['my_field'] = array(
  '#type' => 'textfield',
  '#title' => ...
  '#autocomplete_path' => ...
  '#autocomplete_id_field' => true
);

This makes theme_textfield add an additional hidden field that receives the 'id'.
On form submission, you get $edit['my_field'] and $edit['my_field_id'] and deal with them.

WDYT ?

yched’s picture

FileSize
3.24 KB

re-rolled against current HEAD, BTW

webchick’s picture

yched: No, I think what Steven means is change the hidden value so that instead of only storing the node ID it stores "Node title (nid)", and pass that into the receiving funciton.

The JS autocomplete widget would still show "(review) It stinks!" and the nid would be suppressed. But "behind the scenes" it would pass in "It stinks! (23)" .. that way if I have JavaScript disabled, I can manually type in "It stinks! (23)" and the field works fine for me (most users wouldn't be in this position, but you can get around it if you have to).

Existing user autocomplete and taxonomy autocomplete work fine without JS, because the things they're referring to are unique. There will never be two users called "bob", nor will there ever be two free-tagging terms called "food" in the same vocabulary.

Steven’s picture

Status: Needs review » Closed (won't fix)

Nope, I was indeed talking about an approach without any hidden fields. The NID thing would just be for unambiguously identifying the node for Drupal. But if you want to expel NIDs from the UI you could just as well autocomplete to the URL of the node, and let non-JS users paste in the URL of the node as a fallback. The completed value does not have to match what you type.

What I meant with 'JS behaviour does not match non-JS functionality' is that yched's approach does not offer a solution for ambiguous cases, when JS is disabled.

However, I think any of these approaches (including mine) is an abuse of the autocompleter widget. Without a hidden field, it is not very elegant. With a hidden field, it is error prone because you can't see what's in it. What happens if I later come back to a form that uses this widget? It will just say "Some title" and I won't be able to see whether it is node 3 or node 4.

The real solution is a separate widget with its own behaviour IMO. One which is not just 'write only'.

RobRoy’s picture

I feel this is badly needed as part of the autocomplete widget itself as another widget would be duplicating almost all of the same code. But, either way is fine with me I suppose. I'm not sure what the best solution is as there is a need for something to degrade gracefully for non-JS situations as Steven said.

RobRoy’s picture

Version: x.y.z » 6.x-dev
Status: Closed (won't fix) » Active

Marking this active again. I think we need a solution for this in core, so I'd like to get some discussion going again. But, I've been wrong before.

beginner’s picture

subscribing

smk-ka’s picture

Similar issue. Having an extendible mechanism for 3rd party modules would be so neat, as from searching D.org it seems everyone is currently dealing with that in his/her own way. And worse, the stuff from the 4.7 days doesn't work anymore...

mdupont’s picture

Status: Active » Closed (duplicate)

Marking as duplicate of #125231: Enhance autocomplete feature, which have been created later but have seen more activity.