Author: jablko
Date: Wed Sep 2 18:41:02 2009
New Revision: 3158
Log:
Add JavaScript behavior to progressively enhance inputs of class
.form-autocomplete with YUI AutoComplete widget. Add class .form-autocomplete
to inputs with potentially long lists of options. -- force
Added:
trunk/web/js/autocomplete.js (contents, props changed)
Modified:
trunk/apps/qubit/modules/informationobject/config/view.yml
trunk/apps/qubit/modules/informationobject/templates/editDcSuccess.php
trunk/apps/qubit/modules/informationobject/templates/editIsadSuccess.php
trunk/apps/qubit/modules/informationobject/templates/editModsSuccess.php
trunk/apps/qubit/modules/informationobject/templates/editRadSuccess.php
trunk/web/css/main.css
Modified: trunk/apps/qubit/modules/informationobject/config/view.yml
==============================================================================
--- trunk/apps/qubit/modules/informationobject/config/view.yml Wed Sep 2
18:10:16 2009 (r3157)
+++ trunk/apps/qubit/modules/informationobject/config/view.yml Wed Sep 2
18:41:02 2009 (r3158)
@@ -1,14 +1,14 @@
editDcSuccess:
- javascripts: [/sfDrupalPlugin/vendor/drupal/misc/collapse,
/sfDrupalPlugin/vendor/drupal/misc/textarea, multiDelete, multiInstanceInput,
multiInstanceSelect, select]
+ javascripts: [autocomplete, /sfDrupalPlugin/vendor/drupal/misc/collapse,
/sfDrupalPlugin/vendor/drupal/misc/textarea, multiDelete, multiInstanceInput,
multiInstanceSelect, select]
editIsadSuccess:
- javascripts: [/sfDrupalPlugin/vendor/drupal/misc/collapse,
/sfDrupalPlugin/vendor/drupal/misc/textarea, multiDelete, multiInstanceInput,
multiInstanceSelect, select]
+ javascripts: [autocomplete, /sfDrupalPlugin/vendor/drupal/misc/collapse,
/sfDrupalPlugin/vendor/drupal/misc/textarea, multiDelete, multiInstanceInput,
multiInstanceSelect, select]
editRadSuccess:
- javascripts: [/sfDrupalPlugin/vendor/drupal/misc/collapse,
/sfDrupalPlugin/vendor/drupal/misc/textarea, multiDelete, multiInstanceInput,
multiInstanceSelect, select]
+ javascripts: [autocomplete, /sfDrupalPlugin/vendor/drupal/misc/collapse,
/sfDrupalPlugin/vendor/drupal/misc/textarea, multiDelete, multiInstanceInput,
multiInstanceSelect, select]
editModsSuccess:
- javascripts: [/sfDrupalPlugin/vendor/drupal/misc/collapse,
/sfDrupalPlugin/vendor/drupal/misc/textarea, multiDelete, multiInstanceInput,
multiInstanceSelect, select]
+ javascripts: [autocomplete, /sfDrupalPlugin/vendor/drupal/misc/collapse,
/sfDrupalPlugin/vendor/drupal/misc/textarea, multiDelete, multiInstanceInput,
multiInstanceSelect, select]
listSuccess:
javascripts: [actions]
Modified: trunk/apps/qubit/modules/informationobject/templates/editDcSuccess.php
==============================================================================
--- trunk/apps/qubit/modules/informationobject/templates/editDcSuccess.php
Wed Sep 2 18:10:16 2009 (r3157)
+++ trunk/apps/qubit/modules/informationobject/templates/editDcSuccess.php
Wed Sep 2 18:41:02 2009 (r3158)
@@ -74,7 +74,7 @@
<?php echo render_field($form->relation, $relation, array('name' =>
'value')) ?>
- <?php echo $form->language->renderRow() ?>
+ <?php echo $form->language->renderRow(array('class' =>
'form-autocomplete')) ?>
<?php include_partial('addAccessPointTermDialog') ?>
<div class="form-item" id="subjectAccessPoints">
Modified:
trunk/apps/qubit/modules/informationobject/templates/editIsadSuccess.php
==============================================================================
--- trunk/apps/qubit/modules/informationobject/templates/editIsadSuccess.php
Wed Sep 2 18:10:16 2009 (r3157)
+++ trunk/apps/qubit/modules/informationobject/templates/editIsadSuccess.php
Wed Sep 2 18:41:02 2009 (r3158)
@@ -108,9 +108,9 @@
<fieldset class="collapsible collapsed" id="contextArea">
<legend><?php echo __('context area') ?></legend>
- <?php echo $form->creatorIds->label(__('Name of creator(s)'))->renderRow()
?>
+ <?php echo $form->creatorIds->label(__('Name of
creator(s)'))->renderRow(array('class' => 'form-autocomplete')) ?>
- <?php echo $form->repositoryId->label(__('Repository'))->renderRow() ?>
+ <?php echo
$form->repositoryId->label(__('Repository'))->renderRow(array('class' =>
'form-autocomplete')) ?>
<?php echo render_field($form->archivalHistory, $informationObject,
array('class' => 'resizable')) ?>
@@ -138,9 +138,9 @@
<?php echo
render_field($form->reproductionConditions->label(__('Conditions governing
reproduction')), $informationObject, array('class' => 'resizable')) ?>
- <?php echo $form->language->renderRow() ?>
+ <?php echo $form->language->renderRow(array('class' =>
'form-autocomplete')) ?>
- <?php echo $form->script->renderRow() ?>
+ <?php echo $form->script->renderRow(array('class' => 'form-autocomplete'))
?>
<?php echo render_field($form->physicalCharacteristics->label(__('Physical
characteristics and technical requirements')), $informationObject,
array('class' => 'resizable')) ?>
@@ -348,9 +348,9 @@
<?php echo render_field($form->revisionHistory->label(__('Dates of
creation, revision and deletion')), $informationObject, array('class' =>
'resizable')) ?>
- <?php echo $form->languageOfDescription->renderRow() ?>
+ <?php echo $form->languageOfDescription->renderRow(array('class' =>
'form-autocomplete')) ?>
- <?php echo $form->scriptOfDescription->renderRow() ?>
+ <?php echo $form->scriptOfDescription->renderRow(array('class' =>
'form-autocomplete')) ?>
<?php echo render_field($form->sources, $informationObject, array('class'
=> 'resizable')) ?>
Modified:
trunk/apps/qubit/modules/informationobject/templates/editModsSuccess.php
==============================================================================
--- trunk/apps/qubit/modules/informationobject/templates/editModsSuccess.php
Wed Sep 2 18:10:16 2009 (r3157)
+++ trunk/apps/qubit/modules/informationobject/templates/editModsSuccess.php
Wed Sep 2 18:41:02 2009 (r3158)
@@ -64,7 +64,7 @@
<?php echo $form->typeIds->label(__('Type of resource'))->renderRow() ?>
- <?php echo $form->language->renderRow() ?>
+ <?php echo $form->language->renderRow(array('class' =>
'form-autocomplete')) ?>
<?php include_partial('addAccessPointTermDialog') ?>
<div class="form-item" id="subjectAccessPoints">
Modified:
trunk/apps/qubit/modules/informationobject/templates/editRadSuccess.php
==============================================================================
--- trunk/apps/qubit/modules/informationobject/templates/editRadSuccess.php
Wed Sep 2 18:10:16 2009 (r3157)
+++ trunk/apps/qubit/modules/informationobject/templates/editRadSuccess.php
Wed Sep 2 18:41:02 2009 (r3158)
@@ -76,7 +76,7 @@
</tr>
</table>
- <?php echo $form->repositoryId->label(__('Repository'))->renderRow() ?>
+ <?php echo
$form->repositoryId->label(__('Repository'))->renderRow(array('class' =>
'form-autocomplete')) ?>
<?php echo $form->identifier->renderRow() ?>
@@ -235,9 +235,9 @@
<?php echo render_field($form->arrangement, $informationObject,
array('class' => 'resizable')) ?>
- <?php echo $form->language->renderRow() ?>
+ <?php echo $form->language->renderRow(array('class' =>
'form-autocomplete')) ?>
- <?php echo $form->script->renderRow() ?>
+ <?php echo $form->script->renderRow(array('class' => 'form-autocomplete'))
?>
<?php echo render_field($form->locationOfOriginals, $informationObject,
array('class' => 'resizable')) ?>
@@ -349,9 +349,9 @@
<?php echo render_field($form->revisionHistory->label(__('Dates of
creation, revision and deletion')), $informationObject, array('class' =>
'resizable')) ?>
- <?php echo $form->languageOfDescription->renderRow() ?>
+ <?php echo $form->languageOfDescription->renderRow(array('class' =>
'form-autocomplete')) ?>
- <?php echo $form->scriptOfDescription->renderRow() ?>
+ <?php echo $form->scriptOfDescription->renderRow(array('class' =>
'form-autocomplete')) ?>
<?php echo render_field($form->sources, $informationObject, array('class'
=> 'resizable')) ?>
Modified: trunk/web/css/main.css
==============================================================================
--- trunk/web/css/main.css Wed Sep 2 18:10:16 2009 (r3157)
+++ trunk/web/css/main.css Wed Sep 2 18:41:02 2009 (r3158)
@@ -163,3 +163,11 @@
{
text-transform: lowercase;
}
+
+/* Fix YUI autocomplete */
+
+.yui-skin-sam .yui-ac-input
+{
+ position: static;
+ width: 95%;
+}
Added: trunk/web/js/autocomplete.js
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ trunk/web/js/autocomplete.js Wed Sep 2 18:41:02 2009 (r3158)
@@ -0,0 +1,218 @@
+// $Id$
+
+Drupal.behaviors.autocomplete = {
+ attach: function (context)
+ {
+ $('select.form-autocomplete', context).each(function ()
+ {
+ // Share <select> with nested scopes
+ var select = this;
+
+ // Make autocomplete <input>, copy @class from <select>, copy @id
+ // from <select> so <label for="..."> is correct
+ var input = $(<input class={$(this).attr('class')}
id={$(this).attr('id')}/>.toXMLString()).insertAfter(this)[0]
+
+ if ($(this).attr('multiple'))
+ {
+ // If multiple <select>, make <ul> of selected <option>s
+ var ul = $(<ul/>.toXMLString()).insertAfter(this)[0];
+
+ $('option:selected', this).each(function ()
+ {
+ // Make <li> of hidden <input> with <option> value, and <span>
+ // with <option> HTML contents
+ $(<li><input name={$(select).attr('name')} type="hidden"
value={$(this).val()}/><span>{XML($(this).html())}</span></li>.toXMLString())
+ .click(function ()
+ {
+ // On click, remove <li>
+ $(this).hide('fast', function ()
+ {
+ $(this).remove();
+ });
+ })
+ .appendTo(ul);
+ });
+ }
+ else
+ {
+ // If single <select>, make one hidden <input> with <option> value,
+ var hidden = $(<input name={$(this).attr('name')} type="hidden"
value={$(this).val()}/>.toXMLString()).insertAfter(this)[0];
+
+ // - and copy <option> value to autocomplete <input>
+ $(input).val($('option:selected', this).text());
+ }
+
+ var dataSource = new YAHOO.util.LocalDataSource();
+
+ $('option:enabled', this).each(function ()
+ {
+ if ($(this).val())
+ {
+ // For each item, select HTML contents and value of <option>
+ //
+ // Selecting HTML contents is important for <em>Untitled</em>
+ dataSource.liveData.push([$(this).html(), $(this).val()]);
+ }
+ });
+
+ // Can't figure out how to get access to the DOM event which
+ // triggered a custom YUI event, so bind a listener to the
+ // interesting DOM event before instantiating the YUI widget, to save
+ // the DOM event before triggering custom YUI events
+ //
+ // TODO File YUI issue for this
+ var event;
+ $(input).keydown(function ()
+ {
+ event = arguments[0];
+
+ // Tab key down
+ if (9 == event.keyCode)
+ {
+ autoComplete._onTextboxKeyDown(event, autoComplete);
+
+ // Call _onTextboxBlur() to trigger item select or unmatched
+ // item select custom YUI events
+ autoComplete._onTextboxBlur(event, autoComplete);
+ }
+ });
+
+ var autoComplete = new YAHOO.widget.AutoComplete(input,
$(<div/>.toXMLString()).insertAfter(this)[0], dataSource);
+
+ // http://developer.yahoo.com/yui/autocomplete/#force
+ autoComplete.forceSelection = true;
+
+ // Show some items even if user types nothing,
+ // http://developer.yahoo.com/yui/autocomplete/#minquery
+ autoComplete.minQueryLength = 0;
+
+ // Give user chance to type something, one second may still be too
+ // little, http://developer.yahoo.com/yui/autocomplete/#delay
+ autoComplete.queryDelay = 1;
+
+ // Start throbbing when first query is sent, stop throbbing when the
+ // last query to be sent is complete
+ //
+ // TODO This binds too many listeners and doesn't actually detect the
+ // last query to be sent : (
+ var id = 0;
+ autoComplete.dataRequestEvent.subscribe(function ()
+ {
+ var thisId = ++id;
+
+ $(input).addClass('throbbing');
+
+ autoComplete.dataReturnEvent.subscribe(function ()
+ {
+ if (id == thisId)
+ {
+ $(input).removeClass('throbbing');
+ }
+ });
+ });
+
+ autoComplete.itemSelectEvent.subscribe(function (type, args)
+ {
+ if ($(select).attr('multiple'))
+ {
+ // Cancel default action of saved DOM event so as not to loose
+ // focus when selecting multiple items
+ if (event)
+ {
+ event.preventDefault();
+ }
+
+ // If this item is already selected, highlight it, otherwise
+ // add it to list of selected items
+ if (!$('li:has(input[value=' + args[2][1] + '])', ul)
+ .each(function ()
+ {
+ // Make background yellow for one second
+ //
+ // TODO Use CSS class
+ var span = $('span', this).css('background',
'yellow')[0];
+
+ setTimeout(function ()
+ {
+ $(span).css('background', 'none');
+ }, 1000);
+ })
+ .length)
+ {
+ // Make <li> of hidden <input> with item value, and <span>
+ // with item HTML
+ //
+ // Use XML() constructor to insert parsed HTML, works for
+ // strings without an <element> and strings with one root
+ // <element>, but not, I suspect, for strings with multiple
+ // root <element>s or text outside the root <element>
+ $(<li><input name={$(select).attr('name')} type="hidden"
value={args[2][1]}/><span>{XML(args[2][0])}</span></li>.toXMLString())
+ .click(function ()
+ {
+ // On click, remove <li>
+ $(this).hide('fast', function ()
+ {
+ $(this).remove();
+ });
+ })
+ .appendTo(ul);
+ }
+
+ // Select autocomplete <input> contents so typing will replace
+ // it
+ $(input).select();
+ }
+ else
+ {
+ // On single <select> item select, simply update the value of
+ // this input
+ $(hidden).val(args[2][1]);
+
+ // Update the value of the autocomplete <input> here with text
+ // of parsed HTML, instead of source
+ //
+ // Use XML() constructor as with multiple <select>, but use
+ // toString() to get text of parsed HTML
+ $(input).val(XML(args[2][0]));
+ }
+ });
+
+ if ($(select).attr('multiple'))
+ {
+ // If multiple <select>, clear autocomplete <input> on blur
+ //
+ // TODO Don't clear if event.preventDefault() was called?
+ autoComplete.textboxBlurEvent.subscribe(function ()
+ {
+ $(input).val('');
+ });
+ }
+
+ // Show autocomplete items, use named function so it can be bound to
+ // click and focus events, use private _nDelayID to cancel query on
+ // e.g. keypress before query delay
+ //
+ // TODO File YUI issue for this
+ function sendQuery()
+ {
+ if (-1 == autoComplete._nDelayID)
+ {
+ autoComplete._nDelayID = setTimeout(function ()
+ {
+ autoComplete._sendQuery(autoComplete.getInputEl().value);
+ }, autoComplete.queryDelay * 1000);
+ }
+ }
+
+ // Use custom YUI event to avoid DOM focus events triggered by
+ // YUI widget interaction
+ autoComplete.textboxFocusEvent.subscribe(sendQuery);
+
+ // Listen for click to show autocomplete items after selecting
+ // existing item, but not changing focus
+ $(input).click(sendQuery);
+
+ // Finally remove <select> element
+ $(this).remove();
+ });
+ } };
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"Qubit Toolkit Commits" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.ca/group/qubit-commits?hl=en
-~----------~----~----~----~------~----~------~--~---