Commit 02a10b31 authored by webchick's avatar webchick

Issue #675446 by mgifford, RobLoach, amateescu, nod_, longwave, oxyc,...

Issue #675446 by mgifford, RobLoach, amateescu, nod_, longwave, oxyc, rteijeiro, tomyouds, Jelle_S, mcrittenden, Sutharsan, hansyg, Angry Dan, clemens.tolboom, droplet | Dave Reid: Change notice: Use jQuery UI Autocomplete.
parent fcea2f9e
......@@ -2158,20 +2158,8 @@ function form_process_autocomplete($element, &$form_state) {
if ($access) {
$element['#attributes']['class'][] = 'form-autocomplete';
$element['#attached']['library'][] = array('system', 'drupal.autocomplete');
// Provide a hidden element for the JavaScript behavior to bind to. Since
// this element is for client-side functionality only, do not process input.
// @todo Refactor autocomplete.js to accept drupalSettings instead of
// requiring extraneous markup.
$element['autocomplete'] = array(
'#type' => 'hidden',
'#input' => FALSE,
'#value' => $path,
'#disabled' => TRUE,
'#attributes' => array(
'class' => array('autocomplete'),
'id' => $element['#id'] . '-autocomplete',
),
);
// Provide a data attribute for the JavaScript behavior to bind to.
$element['#attributes']['data-autocomplete-path'] = $path;
}
return $element;
}
......
This diff is collapsed.
......@@ -100,7 +100,7 @@ public function getMatches($field, $instance, $entity_type, $entity_id = '', $pr
if (strpos($key, ',') !== FALSE || strpos($key, '"') !== FALSE) {
$key = '"' . str_replace('"', '""', $key) . '"';
}
$matches[$prefix . $key] = $label;
$matches[] = array('value' => $prefix . $key, 'label' => $label);
}
}
}
......
......@@ -79,21 +79,24 @@ function testEntityReferenceAutocompletion() {
// We should get both entities in a JSON encoded string.
$input = '10/';
$data = $this->getAutocompleteResult('single', $input);
$this->assertIdentical($data[$entity_1->name->value . ' (1)'], check_plain($entity_1->name->value), 'Autocomplete returned the first matching entity');
$this->assertIdentical($data[$entity_2->name->value . ' (2)'], check_plain($entity_2->name->value), 'Autocomplete returned the second matching entity');
$this->assertIdentical($data[0]['label'], check_plain($entity_1->name->value), 'Autocomplete returned the first matching entity');
$this->assertIdentical($data[1]['label'], check_plain($entity_2->name->value), 'Autocomplete returned the second matching entity');
// Try to autocomplete a entity label that matches the first entity.
// We should only get the first entity in a JSON encoded string.
$input = '10/16';
$data = $this->getAutocompleteResult('single', $input);
$target = array($entity_1->name->value . ' (1)' => check_plain($entity_1->name->value));
$this->assertIdentical($data, $target, 'Autocomplete returns only the expected matching entity.');
$target = array(
'value' => $entity_1->name->value . ' (1)',
'label' => check_plain($entity_1->name->value),
);
$this->assertIdentical(reset($data), $target, 'Autocomplete returns only the expected matching entity.');
// Try to autocomplete a entity label that matches the second entity, and
// the first entity is already typed in the autocomplete (tags) widget.
$input = $entity_1->name->value . ' (1), 10/17';
$data = $this->getAutocompleteResult('tags', $input);
$this->assertIdentical($data[$entity_1->name->value . ' (1), ' . $entity_2->name->value . ' (2)'], check_plain($entity_2->name->value), 'Autocomplete returned the second matching entity');
$this->assertIdentical($data[0]['label'], check_plain($entity_2->name->value), 'Autocomplete returned the second matching entity');
// Try to autocomplete a entity label with both a comma and a slash.
$input = '"label with, and / t';
......@@ -103,8 +106,11 @@ function testEntityReferenceAutocompletion() {
if (strpos($entity_3->name->value, ',') !== FALSE || strpos($entity_3->name->value, '"') !== FALSE) {
$n = '"' . str_replace('"', '""', $entity_3->name->value) . ' (3)"';
}
$target = array($n => check_plain($entity_3->name->value));
$this->assertIdentical($data, $target, 'Autocomplete returns an entity label containing a comma and a slash.');
$target = array(
'value' => $n,
'label' => check_plain($entity_3->name->value),
);
$this->assertIdentical(reset($data), $target, 'Autocomplete returns an entity label containing a comma and a slash.');
}
/**
......
......@@ -131,7 +131,7 @@ public function testAuthorAutocomplete() {
$this->drupalGet('node/add/page');
$result = $this->xpath('//input[@id = "edit-name-autocomplete"]');
$result = $this->xpath('//input[@id="edit-name" and contains(@data-autocomplete-path, "user/autocomplete")]');
$this->assertEqual(count($result), 0, 'No autocompletion without access user profiles.');
$admin_user = $this->drupalCreateUser(array('administer nodes', 'create page content', 'access user profiles'));
......@@ -139,8 +139,7 @@ public function testAuthorAutocomplete() {
$this->drupalGet('node/add/page');
$result = $this->xpath('//input[@id = "edit-name-autocomplete"]');
$this->assertEqual((string) $result[0]['value'], url('user/autocomplete'));
$result = $this->xpath('//input[@id="edit-name" and contains(@data-autocomplete-path, "user/autocomplete")]');
$this->assertEqual(count($result), 1, 'Ensure that the user does have access to the autocompletion');
}
......
......@@ -8,25 +8,6 @@
*
* @see autocomplete.js
*/
/* Suggestion list */
#autocomplete {
border: 1px solid;
overflow: hidden;
position: absolute;
z-index: 100;
}
#autocomplete ul {
list-style: none;
list-style-image: none;
margin: 0;
padding: 0;
}
#autocomplete li {
background: #fff;
color: #000;
cursor: default;
white-space: pre;
}
/* Animated throbber */
.js input.form-autocomplete {
......@@ -37,10 +18,10 @@
.js[dir="rtl"] input.form-autocomplete {
background-position: 0% 2px;
}
.js input.throbbing {
.js input.form-autocomplete.ui-autocomplete-loading {
background-position: 100% -18px; /* LTR */
}
.js[dir="rtl"] input.throbbing {
.js[dir="rtl"] input.form-autocomplete.ui-autocomplete-loading {
background-position: 0% -18px;
}
......
......@@ -192,9 +192,10 @@ label button.link {
* @see autocomplete.js
*/
/* Suggestion list */
#autocomplete li.selected {
.ui-autocomplete li.ui-menu-item a.ui-state-focus, .autocomplete li.ui-menu-item a.ui-state-hover {
background: #0072b9;
color: #fff;
margin: 0;
}
/**
......
......@@ -133,20 +133,18 @@ function testGroupElements() {
public function testFormAutocomplete() {
$this->drupalGet('form-test/autocomplete');
$result = $this->xpath('//input[@id = "edit-autocomplete-1-autocomplete"]');
$result = $this->xpath('//input[@id="edit-autocomplete-1" and contains(@data-autocomplete-path, "form-test/autocomplete-1")]');
$this->assertEqual(count($result), 0, 'Ensure that the user does not have access to the autocompletion');
$result = $this->xpath('//input[@id="edit-autocomplete-2" and contains(@data-autocomplete-path, "form-test/autocomplete-2/value")]');
$this->assertEqual(count($result), 0, 'Ensure that the user does not have access to the autocompletion');
$result = $this->xpath('//input[@id = "edit-autocomplete-2-autocomplete"]');
$this->assertEqual(count($result), 0, 'Ensure that the user did not had access to the autocompletion');
$user = $this->drupalCreateUser(array('access autocomplete test'));
$this->drupalLogin($user);
$this->drupalGet('form-test/autocomplete');
$result = $this->xpath('//input[@id = "edit-autocomplete-1-autocomplete"]');
$this->assertEqual((string) $result[0]['value'], url('form-test/autocomplete-1'));
$result = $this->xpath('//input[@id="edit-autocomplete-1" and contains(@data-autocomplete-path, "form-test/autocomplete-1")]');
$this->assertEqual(count($result), 1, 'Ensure that the user does have access to the autocompletion');
$result = $this->xpath('//input[@id = "edit-autocomplete-2-autocomplete"]');
$this->assertEqual((string) $result[0]['value'], url('form-test/autocomplete-2/value'));
$result = $this->xpath('//input[@id="edit-autocomplete-2" and contains(@data-autocomplete-path, "form-test/autocomplete-2/value")]');
$this->assertEqual(count($result), 1, 'Ensure that the user does have access to the autocompletion');
}
......
......@@ -1096,7 +1096,9 @@ function system_library_info() {
'dependencies' => array(
array('system', 'jquery'),
array('system', 'drupal'),
array('system', 'drupalSettings'),
array('system', 'drupal.ajax'),
array('system', 'jquery.ui.autocomplete'),
),
);
......
......@@ -200,7 +200,7 @@ protected function getMatchingTerms($tags_typed, array $vids, $tag_last) {
if (strpos($name, ',') !== FALSE || strpos($name, '"') !== FALSE) {
$name = '"' . str_replace('"', '""', $name) . '"';
}
$matches[$prefix . $name] = String::checkPlain($term->label());
$matches[] = array('value' => $prefix . $name, 'label' => String::checkPlain($term->label()));
}
return $matches;
}
......
......@@ -220,13 +220,13 @@ function testNodeTermCreationAndDeletion() {
// The term will be quoted, and the " will be encoded in unicode (\u0022).
$input = substr($term_objects['term3']->label(), 0, 3);
$json = $this->drupalGet('taxonomy/autocomplete/node/taxonomy_' . $this->vocabulary->id(), array('query' => array('q' => $input)));
$this->assertEqual($json, '{"\u0022' . $term_objects['term3']->label() . '\u0022":"' . $term_objects['term3']->label() . '"}', format_string('Autocomplete returns term %term_name after typing the first 3 letters.', array('%term_name' => $term_objects['term3']->label())));
$this->assertEqual($json, '[{"value":"\u0022' . $term_objects['term3']->label() . '\u0022","label":"' . $term_objects['term3']->label() . '"}]', format_string('Autocomplete returns term %term_name after typing the first 3 letters.', array('%term_name' => $term_objects['term3']->label())));
// Test autocomplete on term 4 - it is alphanumeric only, so no extra
// quoting.
$input = substr($term_objects['term4']->label(), 0, 3);
$this->drupalGet('taxonomy/autocomplete/node/taxonomy_' . $this->vocabulary->id(), array('query' => array('q' => $input)));
$this->assertRaw('{"' . $term_objects['term4']->label() . '":"' . $term_objects['term4']->label() . '"}', format_string('Autocomplete returns term %term_name after typing the first 3 letters.', array('%term_name' => $term_objects['term4']->label())));
$this->assertRaw('[{"value":"' . $term_objects['term4']->label() . '","label":"' . $term_objects['term4']->label() . '"}', format_string('Autocomplete returns term %term_name after typing the first 3 letters.', array('%term_name' => $term_objects['term4']->label())));
// Test taxonomy autocomplete with a nonexistent field.
$field_name = $this->randomName();
......@@ -261,15 +261,18 @@ function testTermAutocompletion() {
// The result order is not guaranteed, so check each term separately.
$result = $this->drupalGet($path, array('query' => array('q' => $input)));
$data = drupal_json_decode($result);
$this->assertEqual($data[$first_term->label()], check_plain($first_term->label()), 'Autocomplete returned the first matching term.');
$this->assertEqual($data[$second_term->label()], check_plain($second_term->label()), 'Autocomplete returned the second matching term.');
$this->assertEqual($data[0]['label'], check_plain($first_term->label()), 'Autocomplete returned the first matching term');
$this->assertEqual($data[1]['label'], check_plain($second_term->label()), 'Autocomplete returned the second matching term');
// Try to autocomplete a term name that matches first term.
// We should only get the first term in a json encoded string.
$input = '10/16';
$path = 'taxonomy/autocomplete/node/taxonomy_' . $this->vocabulary->id();
$this->drupalGet($path, array('query' => array('q' => $input)));
$target = array($first_term->label() => check_plain($first_term->label()));
$target = array(array(
'value' => check_plain($first_term->label()),
'label' => $first_term->label(),
));
$this->assertRaw(drupal_json_encode($target), 'Autocomplete returns only the expected matching term.');
// Try to autocomplete a term name with both a comma and a slash.
......@@ -281,7 +284,10 @@ function testTermAutocompletion() {
if (strpos($third_term->label(), ',') !== FALSE || strpos($third_term->label(), '"') !== FALSE) {
$n = '"' . str_replace('"', '""', $third_term->label()) . '"';
}
$target = array($n => check_plain($third_term->label()));
$target = array(array(
'value' => $n,
'label' => check_plain($third_term->label()),
));
$this->assertRaw(drupal_json_encode($target), 'Autocomplete returns a term containing a comma and a slash.');
}
......
......@@ -101,8 +101,8 @@ public function testFilterUI() {
$display['display_options']['filters']['tid']['type'] = 'textfield';
$view->save();
$this->drupalGet('admin/structure/views/nojs/config-item/test_filter_taxonomy_index_tid/default/filter/tid');
$result = $this->xpath('//input[@id = "edit-options-value-autocomplete"]');
$this->assertEqual((string) $result[0]['value'], url('taxonomy/autocomplete_vid/tags'));
$result = $this->xpath('//input[@id="edit-options-value"]/@data-autocomplete-path');
$this->assertEqual((string) $result[0], url('taxonomy/autocomplete_vid/tags'));
}
}
......@@ -53,8 +53,8 @@ function testUserAutocomplete() {
// Test that anonymous username is in the result when requested and escaped
// with check_plain().
$users = $this->drupalGetJSON('user/autocomplete/anonymous', array('query' => array('q' => drupal_substr($anonymous_name, 0, 4))));
$this->assertTrue(in_array(check_plain($anonymous_name), $users), 'The anonymous name found in autocompletion results.');
$this->assertEqual(check_plain($anonymous_name), $users[0]['label'], 'The anonymous name found in autocompletion results.');
$users = $this->drupalGetJSON('user/autocomplete', array('query' => array('q' => drupal_substr($anonymous_name, 0, 4))));
$this->assertFalse(isset($users[$anonymous_name]), 'The anonymous name not found in autocompletion results without enabling anonymous username.');
$this->assertTrue(empty($users), 'The anonymous name not found in autocompletion results without enabling anonymous username.');
}
}
......@@ -7,6 +7,7 @@
namespace Drupal\user;
use Drupal\Component\Utility\String;
use Drupal\Core\Config\ConfigFactory;
use Drupal\Core\Database\Connection;
......@@ -62,12 +63,12 @@ public function getMatches($string, $include_anonymous = FALSE) {
$anonymous_name = $this->configFactory->get('user.settings')->get('anonymous');
// Allow autocompletion for the anonymous user.
if (stripos($anonymous_name, $string) !== FALSE) {
$matches[$anonymous_name] = check_plain($anonymous_name);
$matches[] = array('value' => $anonymous_name, 'label' => String::checkPlain($anonymous_name));
}
}
$result = $this->connection->select('users')->fields('users', array('name'))->condition('name', db_like($string) . '%', 'LIKE')->range(0, 10)->execute();
foreach ($result as $account) {
$matches[$account->name] = check_plain($account->name);
$matches[] = array('value' => $account->name, 'label' => String::checkPlain($account->name));
}
}
......
......@@ -8,7 +8,6 @@
namespace Drupal\views\Tests;
use Drupal\views\Tests\ViewTestBase;
use Drupal\Component\Utility\MapArray;
use Drupal\Core\Language\Language;
/**
......@@ -81,7 +80,10 @@ public function testTaxonomyAutocomplete() {
// Test a with whole name term.
$label = $this->term1->label();
$expected = MapArray::copyValuesToKeys((array) $label);
$expected = array(array(
'value' => $label,
'label' => check_plain($label),
));
$this->assertIdentical($expected, $this->drupalGetJSON($base_autocomplete_path, array('query' => array('q' => $label))));
// Test a term by partial name.
$partial = substr($label, 0, 2);
......
......@@ -1434,10 +1434,10 @@ input.form-submit:focus {
.js[dir="rtl"] input.form-autocomplete {
background-position: 1% 4px;
}
.js input.throbbing {
.js input.form-autocomplete.ui-autocomplete-loading {
background-position: 100% -16px; /* LTR */
}
.js[dir="rtl"] input.throbbing {
.js[dir="rtl"] input.form-autocomplete.ui-autocomplete-loading {
background-position: 1% -16px;
}
......
......@@ -730,7 +730,6 @@ label {
.form-item label.option input {
vertical-align: middle;
}
.form-disabled input.form-autocomplete,
.form-disabled input.form-text,
.form-disabled input.form-tel,
.form-disabled input.form-email,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment