New module 'Autocomplete Widgets'
This commit is contained in:
parent
17a2a7a42d
commit
5af0c1f42e
10 changed files with 1125 additions and 0 deletions
55
sites/all/modules/autocomplete_widgets/CHANGELOG.txt
Normal file
55
sites/all/modules/autocomplete_widgets/CHANGELOG.txt
Normal file
|
@ -0,0 +1,55 @@
|
|||
|
||||
6.x-1.x-dev
|
||||
===========
|
||||
|
||||
Features:
|
||||
- #656554 by dagmar - Views 3 integration.
|
||||
- #730790 by jromine - Filter HTML from display of values.
|
||||
|
||||
|
||||
6.x-1.3
|
||||
=======
|
||||
|
||||
Release notes:
|
||||
- This release requires running update.php to upgrade.
|
||||
|
||||
Security issue:
|
||||
- DRUPAL-SA-CONTRIB-2009-115 [1]: Autocomplete callback does not honor permissions to access CCK fields.
|
||||
|
||||
[1] http://drupal.org/node/670942
|
||||
|
||||
Bugfixes:
|
||||
- #562432 Autocomplete text fields do not use default value setting.
|
||||
- #553336 Follow up patch to fix case sensitivity feature.
|
||||
|
||||
Features:
|
||||
- Added CHANGELOG.txt.
|
||||
- #553336 Added case sensitive option. Needs update.php.
|
||||
- Split code into separate files to minimize memory consumption during normal site operation.
|
||||
- Added translations template and fixed a couple of potx warnings related to CCK widget labels.
|
||||
|
||||
|
||||
6.x-1.2
|
||||
=======
|
||||
|
||||
Release notes:
|
||||
- Upgrading does not require running update.php.
|
||||
|
||||
Features:
|
||||
- #550588: Add support for i18n to the 'Autocomplete for existing field data' widget.
|
||||
|
||||
|
||||
6.x-1.1
|
||||
=======
|
||||
|
||||
Release notes:
|
||||
- Upgrading does not require running update.php.
|
||||
|
||||
Bugfixes:
|
||||
- #405628 by nguyenquocviet - The widget of autocomplete for allowed values list does not show any possible values from allowed values list.
|
||||
|
||||
|
||||
6.x-1.0
|
||||
=======
|
||||
|
||||
- Initial release.
|
339
sites/all/modules/autocomplete_widgets/LICENSE.txt
Normal file
339
sites/all/modules/autocomplete_widgets/LICENSE.txt
Normal file
|
@ -0,0 +1,339 @@
|
|||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License.
|
47
sites/all/modules/autocomplete_widgets/README.txt
Normal file
47
sites/all/modules/autocomplete_widgets/README.txt
Normal file
|
@ -0,0 +1,47 @@
|
|||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Autocomplete Widgets for CCK Text and Number fields
|
||||
;;
|
||||
;; Module Author: markus_petrux (http://drupal.org/user/39593)
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
OVERVIEW
|
||||
========
|
||||
|
||||
This module adds 2 autocomplete widgets for CCK fields.
|
||||
|
||||
- Autocomplete for allowed values list: This widget can be used for Text and
|
||||
Number fields and it takes candidate values from the defined list of Allowed
|
||||
values of the fields.
|
||||
|
||||
- Autocomplete for existing field data: This widget can be used for Text only
|
||||
and it takes candidate values from existing values in the database for that
|
||||
field.
|
||||
|
||||
Both widgets allow you to choose the size of the text element and the method
|
||||
used to match values between 'Starts with' and 'Contains'.
|
||||
|
||||
When the Internationalization module [1] is enabled, the 'Autocomplete for
|
||||
existing field data' widget also provides an option to filter values by the
|
||||
language assigned to their corresponding nodes. This option allows you to
|
||||
provide a different set of allowed values per language.
|
||||
|
||||
[1] http://drupal.org/project/i18n
|
||||
|
||||
|
||||
REQUIREMENTS
|
||||
============
|
||||
|
||||
- CCK (http://drupal.org/project/cck)
|
||||
- CCK Text and/or Number modules provided by CCK itself.
|
||||
|
||||
|
||||
INSTALLATION
|
||||
============
|
||||
|
||||
- Copy all contents of this package to your modules directory preserving
|
||||
subdirectory structure.
|
||||
|
||||
- Goto Administer > Site building > Modules to install this module.
|
||||
|
||||
- Create or edit content types and start using the widgets for your Text and/or
|
||||
Number fields. :)
|
|
@ -0,0 +1,123 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Administration related code for Autocomplete Widgets module.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Alter the CCK widget settings form.
|
||||
*/
|
||||
function _autocomplete_widgets_content_field_edit_form_alter(&$form, $form_state) {
|
||||
$widget_type = $form['#field']['widget']['type'];
|
||||
if (in_array($widget_type, array('autocomplete_widgets_allowvals', 'autocomplete_widgets_flddata'))) {
|
||||
// Implementation of allowed values list.
|
||||
if ($widget_type == 'autocomplete_widgets_allowvals') {
|
||||
$form['field']['allowed_values_fieldset']['#collapsed'] = FALSE;
|
||||
$form['field']['allowed_values_fieldset']['#description'] = '<p>'. t('Create a list of options as a list in <strong>Allowed values list</strong> or as an array in PHP code. These values will be the same for %field in all content types.', array('%field' => $form['#field']['widget']['label'])) .'</p>';
|
||||
|
||||
// If no 'allowed values' were set yet, add a remainder in the messages area.
|
||||
if (empty($form_state['post'])
|
||||
&& empty($form['field']['allowed_values_fieldset']['allowed_values']['#default_value'])
|
||||
&& empty($form['field']['allowed_values_fieldset']['advanced_options']['allowed_values_php']['#default_value'])) {
|
||||
drupal_set_message(t("You need to specify the 'allowed values' for this field."), 'warning');
|
||||
}
|
||||
}
|
||||
else {
|
||||
// For the autocomplete 'field data' widget we do not use the 'Allowed values' list.
|
||||
unset($form['field']['allowed_values_fieldset']);
|
||||
}
|
||||
// Disable the text processing option of text fields. These widgets can
|
||||
// only use plain text fields.
|
||||
if (isset($form['field']['text_processing'])) {
|
||||
$form['field']['text_processing']['#type'] = 'value';
|
||||
$form['field']['text_processing']['#value'] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of hook_widget_settings().
|
||||
*/
|
||||
function _autocomplete_widgets_widget_settings($op, $widget) {
|
||||
switch ($op) {
|
||||
case 'form':
|
||||
$form = array();
|
||||
$form['size'] = array(
|
||||
'#type' => 'textfield',
|
||||
'#title' => t('Size of textfield'),
|
||||
'#default_value' => (isset($widget['size']) ? $widget['size'] : 60),
|
||||
'#element_validate' => array('_element_validate_integer_positive'),
|
||||
'#required' => TRUE,
|
||||
);
|
||||
$form['autocomplete_match'] = array(
|
||||
'#type' => 'select',
|
||||
'#title' => t('Autocomplete matching'),
|
||||
'#default_value' => (isset($widget['autocomplete_match']) ? $widget['autocomplete_match'] : 'contains'),
|
||||
'#options' => array('starts_with' => t('Starts with'), 'contains' => t('Contains')),
|
||||
'#description' => t('Select the method used to collect autocomplete suggestions. Note that <em>Contains</em> can cause performance issues on sites with thousands of records.'),
|
||||
);
|
||||
$form['autocomplete_case'] = array(
|
||||
'#type' => 'radios',
|
||||
'#title' => t('Case sensitive'),
|
||||
'#default_value' => (isset($widget['autocomplete_case']) ? $widget['autocomplete_case'] : 1),
|
||||
'#options' => array(0 => t('Disabled'), 1 => t('Enabled')),
|
||||
);
|
||||
if ($widget['type'] == 'autocomplete_widgets_flddata') {
|
||||
$form['autocomplete_case']['#description'] = t('Case-insensitive queries are implemented using the <a href="!function-lower-url">LOWER()</a> function in combination with the <a href="!operator-like-url">LIKE</a> operator.', array(
|
||||
'!function-lower-url' => 'http://dev.mysql.com/doc/refman/5.1/en/string-functions.html#function_lower',
|
||||
'!operator-like-url' => 'http://dev.mysql.com/doc/refman/5.1/en/string-comparison-functions.html#operator_like',
|
||||
));
|
||||
if (in_array($GLOBALS['db_type'], array('mysql', 'mysqli'))) {
|
||||
$form['autocomplete_case']['#description'] .= ' '. t('Note that MySQL might ignore case sensitivity depending on the collation used in your database definition (see <a href="!mysql-i18n-l10n-url">Internationalization and Localization</a> chapter in the MySQL manual). If you need case insensitive checks, it is recommended (for performance reasons) to use a case insensitive collation as well (such as utf8_general_ci), rather than disabling the case sensitive option here.', array(
|
||||
'!mysql-i18n-l10n-url' => 'http://dev.mysql.com/doc/refman/5.1/en/internationalization-localization.html',
|
||||
));
|
||||
}
|
||||
elseif ($GLOBALS['db_type'] == 'pgsql') {
|
||||
$form['autocomplete_case']['#description'] .= ' '. t('You may want to create an expression index using the LOWER() function to speed up this kind of queries in PostgreSQL (See <a href="!indexes-expressional-url">Indexes on Expressions</a>).', array(
|
||||
'!indexes-expressional-url' => 'http://www.postgresql.org/docs/8.4/static/indexes-expressional.html',
|
||||
));
|
||||
}
|
||||
}
|
||||
else {
|
||||
$form['autocomplete_case']['#description'] = t('Case-insensitive queries are implemented using the function <a href="!drupal-strtolower-url">drupal_strtolower()</a>.', array(
|
||||
'!drupal-strtolower-url' => 'http://api.drupal.org/api/function/drupal_strtolower/6',
|
||||
));
|
||||
}
|
||||
$form['autocomplete_xss'] = array(
|
||||
'#type' => 'radios',
|
||||
'#title' => t('Filter HTML'),
|
||||
'#default_value' => (isset($widget['autocomplete_xss']) ? $widget['autocomplete_xss'] : 0),
|
||||
'#options' => array(0 => t('Disabled'), 1 => t('Enabled')),
|
||||
'#description' => t('Enable this option to filter out HTML in display of values.'),
|
||||
);
|
||||
if ($widget['type'] == 'autocomplete_widgets_flddata' && module_exists('i18n')) {
|
||||
$form['i18n_flddata'] = array(
|
||||
'#type' => 'radios',
|
||||
'#title' => t('Internationalization support'),
|
||||
'#default_value' => (isset($widget['i18n_flddata']) ? $widget['i18n_flddata'] : 0),
|
||||
'#options' => array(0 => t('Disabled'), 1 => t('Enabled')),
|
||||
'#description' => t('Enable this option to provide a different set of allowed values based on the language their nodes are assigned to. This option is only available when <a href="@i18n-project-page">Internationalization</a> module is enabled.', array('@i18n-project-page' => 'http://drupal.org/project/i18n')),
|
||||
);
|
||||
}
|
||||
else {
|
||||
$form['i18n_flddata'] = array(
|
||||
'#type' => 'value',
|
||||
'#value' => 0,
|
||||
);
|
||||
}
|
||||
if ($widget['type'] == 'autocomplete_widgets_flddata') {
|
||||
$form['obey_access_controls'] = array(
|
||||
'#type' => 'checkbox',
|
||||
'#title' => t('Only suggest content from nodes that the current user has permission to access.'),
|
||||
'#default_value' => (isset($widget['obey_access_controls']) ? $widget['obey_access_controls'] : 1),
|
||||
'#description' => t('Unchecking this means that users might have content suggested to them from nodes to which they do not have access. Proceed with caution.'),
|
||||
);
|
||||
}
|
||||
|
||||
return $form;
|
||||
|
||||
case 'save':
|
||||
return array('size', 'autocomplete_match', 'autocomplete_case', 'autocomplete_xss', 'i18n_flddata', 'obey_access_controls');
|
||||
}
|
||||
}
|
|
@ -0,0 +1,157 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Common functions for Autocomplete Widgets module.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Fetch an array of options for the given widget.
|
||||
*
|
||||
* @param $field
|
||||
* The field description.
|
||||
* @param $string
|
||||
* Optional string to filter values on (used by autocomplete).
|
||||
* @param $match
|
||||
* Operator to match filtered name against, can be any of:
|
||||
* 'contains', 'equals', 'starts_with'
|
||||
* @param $keys
|
||||
* Optional keys to lookup (the $string and $match arguments will be
|
||||
* ignored).
|
||||
* @param $limit
|
||||
* If non-zero, limit the size of the result set.
|
||||
*
|
||||
* @return
|
||||
* An array of valid values in the form:
|
||||
* array(
|
||||
* key => value,
|
||||
* ...
|
||||
* )
|
||||
*/
|
||||
function _autocomplete_widgets_get_options($field, $string = '', $match = 'contains', $keys = NULL, $limit = NULL) {
|
||||
static $results = array();
|
||||
|
||||
// Create unique id for static cache.
|
||||
if (!isset($keys) || !is_array($keys)) {
|
||||
$keys = array();
|
||||
}
|
||||
$cid = $field['field_name'] .':'. $match .':'. ($string !== '' ? $string : implode('-', $keys)) .':'. $limit;
|
||||
|
||||
if (!isset($results[$cid])) {
|
||||
if ($field['widget']['type'] == 'autocomplete_widgets_allowvals') {
|
||||
$results[$cid] = _autocomplete_widgets_get_options_allowvals($field, $string, $match, $keys, $limit);
|
||||
}
|
||||
else if ($field['widget']['type'] == 'autocomplete_widgets_flddata') {
|
||||
$results[$cid] = _autocomplete_widgets_get_options_flddata($field, $string, $match, $keys, $limit);
|
||||
}
|
||||
else {
|
||||
$results[$cid] = array();
|
||||
}
|
||||
}
|
||||
|
||||
return $results[$cid];
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch an array of options for the given widget (allowed values).
|
||||
*
|
||||
* Options are retrieved from the allowed values defined for the field.
|
||||
*/
|
||||
function _autocomplete_widgets_get_options_allowvals($field, $string = '', $match = 'contains', $keys = NULL, $limit = NULL) {
|
||||
$function = $field['module'] .'_allowed_values';
|
||||
$allowed_values = (array)(function_exists($function) ? $function($field) : content_allowed_values($field));
|
||||
if (!isset($limit) || !is_numeric($limit)) {
|
||||
$limit = count($allowed_values);
|
||||
}
|
||||
$case_insensitive = (!empty($field['widget']['autocomplete_case']) ? FALSE : TRUE);
|
||||
if ($case_insensitive && $match != 'equals') {
|
||||
$string = drupal_strtolower($string);
|
||||
}
|
||||
$filter_xss = !empty($field['widget']['autocomplete_xss']);
|
||||
$count = 0;
|
||||
$options = array();
|
||||
foreach ($allowed_values as $key => $value) {
|
||||
if ($filter_xss) {
|
||||
// Filter all HTML in $value, then trim white spaces.
|
||||
$value = trim(filter_xss($value, array()));
|
||||
}
|
||||
if ($string === '') {
|
||||
if (isset($keys) && is_array($keys)) {
|
||||
if (in_array($key, $keys)) {
|
||||
$options[$key] = $value;
|
||||
$count++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
$options[$key] = $value;
|
||||
$count++;
|
||||
}
|
||||
}
|
||||
else if ($match == 'equals') {
|
||||
if ($value == $string) {
|
||||
$options[$key] = $value;
|
||||
$count++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
$pos = strpos(($case_insensitive ? drupal_strtolower($value) : $value), $string);
|
||||
if (($match == 'starts_with' && $pos === 0) || ($match == 'contains' && $pos !== FALSE)) {
|
||||
$options[$key] = $value;
|
||||
$count++;
|
||||
}
|
||||
}
|
||||
if ($count >= $limit) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch an array of options for the given widget (field data).
|
||||
*
|
||||
* Options are retrieved from existing values for the field.
|
||||
*/
|
||||
function _autocomplete_widgets_get_options_flddata($field, $string = '', $match = 'contains', $keys = NULL, $limit = NULL) {
|
||||
$db_info = content_database_info($field);
|
||||
$table = $db_info['table'];
|
||||
$column = $field['field_name'] .'_'. key($db_info['columns']);
|
||||
$where = array();
|
||||
$args = array();
|
||||
|
||||
if ($string !== '') {
|
||||
$lower = (!empty($field['widget']['autocomplete_case']) || $match == 'equals' ? '' : 'LOWER');
|
||||
$match_operators = array(
|
||||
'contains' => "LIKE $lower('%%%s%%')",
|
||||
'equals' => "= '%s'",
|
||||
'starts_with' => "LIKE $lower('%s%%')",
|
||||
);
|
||||
$where[] = "$lower(f.". $column .') '. (isset($match_operators[$match]) ? $match_operators[$match] : $match_operators['contains']);
|
||||
$args[] = $string;
|
||||
}
|
||||
else if (isset($keys) && is_array($keys)) {
|
||||
$where[] = 'f.'. $column .' IN ('. db_placeholders($keys) .')';
|
||||
$args = array_merge($args, $keys);
|
||||
}
|
||||
|
||||
// When obey_access_controls is enabled, we need to add node status
|
||||
// to the where clause before the sql is combined.
|
||||
if(!empty($field['widget']['obey_access_controls'])) {
|
||||
$where[] = 'n.status = 1 ';
|
||||
}
|
||||
|
||||
$sql = 'SELECT f.'. $column .' FROM {'. $table .'} f WHERE '. implode(' AND ', $where) .' ORDER BY f.'. $column;
|
||||
if (!empty($field['widget']['obey_access_controls']) || !empty($field['widget']['i18n_flddata'])) {
|
||||
// Adding a join with the node table allows the i18n rewrite the query
|
||||
// to filter values from node for the proper language.
|
||||
$sql = db_rewrite_sql(str_replace(' WHERE ', ' INNER JOIN {node} n ON f.vid = n.vid WHERE ', $sql));
|
||||
}
|
||||
|
||||
$result = $limit ? db_query_range($sql, $args, 0, $limit) : db_query($sql, $args);
|
||||
$options = array();
|
||||
while ($row = db_fetch_object($result)) {
|
||||
$options[$row->$column] = $row->$column;
|
||||
}
|
||||
|
||||
return $options;
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
name = Autocomplete Widgets
|
||||
description = Provides autocomplete widgets for CCK Text and Number fields.
|
||||
dependencies[] = content
|
||||
package = CCK
|
||||
core = 6.x
|
||||
|
||||
; Information added by drupal.org packaging script on 2013-04-16
|
||||
version = "6.x-1.4"
|
||||
core = "6.x"
|
||||
project = "autocomplete_widgets"
|
||||
datestamp = "1366135717"
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Module installation/uninstallation hooks.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implementation of hook_install().
|
||||
*/
|
||||
function autocomplete_widgets_install() {
|
||||
// Make sure this module is loaded after CCK Text/Number fields.
|
||||
// See autocomplete_widgets_form_alter().
|
||||
db_query("UPDATE {system} SET weight = 1 WHERE name = 'autocomplete_widgets'");
|
||||
|
||||
// Notify content module when this module is installed.
|
||||
drupal_load('module', 'content');
|
||||
content_notify('install', 'autocomplete_widgets');
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of hook_uninstall().
|
||||
*/
|
||||
function autocomplete_widgets_uninstall() {
|
||||
// Notify content module when this module is uninstalled.
|
||||
drupal_load('module', 'content');
|
||||
content_notify('uninstall', 'autocomplete_widgets');
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of hook_enable().
|
||||
*/
|
||||
function autocomplete_widgets_enable() {
|
||||
// Notify content module when this module is enabled.
|
||||
drupal_load('module', 'content');
|
||||
content_notify('enable', 'autocomplete_widgets');
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of hook_disable().
|
||||
*/
|
||||
function autocomplete_widgets_disable() {
|
||||
// Notify content module when this module is disabled.
|
||||
drupal_load('module', 'content');
|
||||
content_notify('disable', 'autocomplete_widgets');
|
||||
}
|
||||
|
||||
/**
|
||||
* Update all Autocomplete Widgets for new case sensitive option.
|
||||
*/
|
||||
function autocomplete_widgets_update_6001() {
|
||||
drupal_load('module', 'content');
|
||||
|
||||
if ($abort = content_check_update('autocomplete_widgets')) {
|
||||
return $abort;
|
||||
}
|
||||
|
||||
$ret = array();
|
||||
$result = db_query("SELECT field_name, type_name, widget_settings FROM {content_node_field_instance} WHERE (widget_type = 'autocomplete_widgets_allowvals' OR widget_type = 'autocomplete_widgets_flddata')");
|
||||
while ($field = db_fetch_object($result)) {
|
||||
$widget_settings = unserialize($field->widget_settings);
|
||||
if (!isset($widget_settings['autocomplete_case'])) {
|
||||
$widget_settings['autocomplete_case'] = 1;
|
||||
$widget_settings = serialize($widget_settings);
|
||||
$success = db_query("UPDATE {content_node_field_instance} SET widget_settings = '%s' WHERE type_name = '%s' AND field_name = '%s'", $widget_settings, $field->type_name, $field->field_name);
|
||||
$ret[] = array(
|
||||
'success' => $success !== FALSE,
|
||||
'query' => strtr('Updating definition of the Autocomplete Widget for field %field-name in type %type-name.', array('%field-name' => $field->field_name, '%type-name' => $field->type_name)),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($ret)) {
|
||||
content_clear_type_cache();
|
||||
}
|
||||
return $ret;
|
||||
}
|
|
@ -0,0 +1,220 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Provides autocomplete widgets for CCK Text and Number fields.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implementation of hook_menu().
|
||||
*/
|
||||
function autocomplete_widgets_menu() {
|
||||
$items = array();
|
||||
$items['autocomplete_widgets'] = array(
|
||||
'title' => 'Autocomplete Widgets',
|
||||
'page callback' => 'autocomplete_widgets_json',
|
||||
'access callback' => 'autocomplete_widgets_access',
|
||||
'access arguments' => array(1, 2),
|
||||
'type' => MENU_CALLBACK,
|
||||
);
|
||||
return $items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of hook_theme().
|
||||
*/
|
||||
function autocomplete_widgets_theme() {
|
||||
return array(
|
||||
'autocomplete_widgets' => array('arguments' => array('element' => NULL)),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of hook_views_api().
|
||||
*/
|
||||
function autocomplete_widgets_views_api() {
|
||||
return array(
|
||||
'api' => 3.0,
|
||||
'path' => drupal_get_path('module', 'autocomplete_widgets') . '/views',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of hook_form_alter().
|
||||
*
|
||||
* Because we need to alter the field settings form, this module needs
|
||||
* to be loaded after CCK Text/Number field modules.
|
||||
* See autocomplete_widgets_install().
|
||||
*/
|
||||
function autocomplete_widgets_form_alter(&$form, $form_state, $form_id) {
|
||||
// Provide additional help for the field settings form.
|
||||
if ($form_id == 'content_field_edit_form' && isset($form['widget'])) {
|
||||
module_load_include('inc', 'autocomplete_widgets', 'autocomplete_widgets.admin');
|
||||
_autocomplete_widgets_content_field_edit_form_alter($form, $form_state);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of hook_widget_info().
|
||||
*/
|
||||
function autocomplete_widgets_widget_info() {
|
||||
return array(
|
||||
'autocomplete_widgets_allowvals' => array(
|
||||
'label' => t('Autocomplete for allowed values list'), 'field types' => array('text', 'number_integer', 'number_decimal', 'number_float'),
|
||||
),
|
||||
'autocomplete_widgets_flddata' => array(
|
||||
'label' => t('Autocomplete for existing field data'), 'field types' => array('text'),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of hook_elements().
|
||||
*
|
||||
* Autocomplete_path is not used by text_widget but other widgets can use it
|
||||
* (see nodereference and userreference).
|
||||
*/
|
||||
function autocomplete_widgets_elements() {
|
||||
return array(
|
||||
'autocomplete_widgets' => array(
|
||||
'#input' => TRUE,
|
||||
'#columns' => array('value'), '#delta' => 0,
|
||||
'#process' => array('autocomplete_widgets_process'),
|
||||
'#autocomplete_path' => FALSE,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of hook_widget_settings().
|
||||
*/
|
||||
function autocomplete_widgets_widget_settings($op, $widget) {
|
||||
module_load_include('inc', 'autocomplete_widgets', 'autocomplete_widgets.admin');
|
||||
return _autocomplete_widgets_widget_settings($op, $widget);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of hook_widget().
|
||||
*/
|
||||
function autocomplete_widgets_widget(&$form, &$form_state, $field, $items, $delta = 0) {
|
||||
return array(
|
||||
'#type' => 'autocomplete_widgets',
|
||||
'#default_value' => isset($items[$delta]) ? $items[$delta] : NULL,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Process an individual textfield autocomplete element.
|
||||
*/
|
||||
function autocomplete_widgets_process($element, $edit, $form_state, $form) {
|
||||
$field = $form['#field_info'][$element['#field_name']];
|
||||
$field_key = $element['#columns'][0];
|
||||
|
||||
$value = NULL;
|
||||
if ($field['widget']['type'] == 'autocomplete_widgets_allowvals') {
|
||||
if (isset($element['#value'][$field_key])) {
|
||||
$keys = array($element['#value'][$field_key]);
|
||||
module_load_include('inc', 'autocomplete_widgets', 'autocomplete_widgets.common');
|
||||
$options = _autocomplete_widgets_get_options($field, '', '', $keys, 1);
|
||||
if (!empty($options)) {
|
||||
$value = current($options);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ($field['widget']['type'] == 'autocomplete_widgets_flddata') {
|
||||
if (isset($element['#value'][$field_key])) {
|
||||
$value = $element['#value'][$field_key];
|
||||
}
|
||||
}
|
||||
|
||||
$element[$field_key] = array(
|
||||
'#type' => 'textfield',
|
||||
'#default_value' => $value,
|
||||
'#autocomplete_path' => 'autocomplete_widgets/'. $element['#type_name'] .'/'. $element['#field_name'],
|
||||
'#size' => !empty($field['widget']['size']) ? $field['widget']['size'] : 60,
|
||||
'#attributes' => array('class' => 'text'),
|
||||
// The following values were set by the content module and need
|
||||
// to be passed down to the nested element.
|
||||
'#title' => $element['#title'],
|
||||
'#description' => $element['#description'],
|
||||
'#required' => $element['#required'],
|
||||
'#field_name' => $element['#field_name'],
|
||||
'#type_name' => $element['#type_name'],
|
||||
'#delta' => $element['#delta'],
|
||||
'#columns' => $element['#columns'],
|
||||
);
|
||||
|
||||
$element[$field_key]['#maxlength'] = !empty($field['max_length']) ? $field['max_length'] : NULL;
|
||||
|
||||
if (empty($element[$field_key]['#element_validate'])) {
|
||||
$element[$field_key]['#element_validate'] = array();
|
||||
}
|
||||
array_unshift($element[$field_key]['#element_validate'], 'autocomplete_widgets_validate');
|
||||
|
||||
$element['_error_element'] = array(
|
||||
'#type' => 'value',
|
||||
'#value' => implode('][', array_merge($element['#parents'], array($field_key))),
|
||||
);
|
||||
|
||||
return $element;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate a textfield autocomplete element.
|
||||
*/
|
||||
function autocomplete_widgets_validate($element, &$form_state) {
|
||||
$field_name = $element['#field_name'];
|
||||
$type_name = $element['#type_name'];
|
||||
$delta = $element['#delta'];
|
||||
$field = content_fields($field_name, $type_name);
|
||||
$field_key = $element['#columns'][0];
|
||||
$value = trim($element['#value']);
|
||||
|
||||
if ($field['widget']['type'] == 'autocomplete_widgets_allowvals') {
|
||||
if ($value !== '') {
|
||||
module_load_include('inc', 'autocomplete_widgets', 'autocomplete_widgets.common');
|
||||
$options = _autocomplete_widgets_get_options($field, $value, 'equals', NULL, 1);
|
||||
if (empty($options)) {
|
||||
form_error($element, t('%name: found no valid option.', array('%name' => $field['widget']['label'])));
|
||||
}
|
||||
else {
|
||||
$value = key($options);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Remove the wrapper layer and set the right element's value.
|
||||
// This will move the nested value at 'field-name-0-value-value'
|
||||
// back to its original location, 'field-name-0-value'.
|
||||
form_set_value($element, $value, $form_state);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check access to the menu callback of the autocomplete widget.
|
||||
*/
|
||||
function autocomplete_widgets_access($type_name, $field_name) {
|
||||
return user_access('access content') && ($field = content_fields($field_name, $type_name)) && content_access('view', $field) && content_access('edit', $field);
|
||||
}
|
||||
|
||||
/**
|
||||
* Menu callback; Retrieve a pipe delimited string of autocomplete suggestions.
|
||||
*/
|
||||
function autocomplete_widgets_json($type_name, $field_name, $string = '') {
|
||||
module_load_include('inc', 'autocomplete_widgets', 'autocomplete_widgets.common');
|
||||
$field = content_fields($field_name, $type_name);
|
||||
$match = isset($field['widget']['autocomplete_match']) ? $field['widget']['autocomplete_match'] : 'contains';
|
||||
$matches = array();
|
||||
$options = _autocomplete_widgets_get_options($field, $string, $match, NULL, 10);
|
||||
foreach ($options as $key => $value) {
|
||||
// Add a class wrapper for a few required CSS overrides.
|
||||
$matches[$value] = '<div class="reference-autocomplete">'. check_plain($value) .'</div>';
|
||||
}
|
||||
drupal_json($matches);
|
||||
}
|
||||
|
||||
/**
|
||||
* Theme an individual textfield autocomplete element.
|
||||
*/
|
||||
function theme_autocomplete_widgets($element) {
|
||||
return $element['#children'];
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Autocomplete widgets integration with Views 3.x.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implementation of hook_views_plugins().
|
||||
*/
|
||||
function autocomplete_widgets_views_plugins() {
|
||||
return array(
|
||||
'exposed_form' => array(
|
||||
'autocomplete_widgets_basic' => array(
|
||||
'title' => t('Autocomplete widgets'),
|
||||
'help' => t('Allow to use autocomplete widgets for CCK Text and Number exposed filters.'),
|
||||
'handler' => 'autocomplete_widgets_basic_exposed_form_plugin',
|
||||
'uses row plugin' => FALSE,
|
||||
'uses fields' => TRUE,
|
||||
'uses options' => TRUE,
|
||||
'type' => 'normal',
|
||||
'parent' => 'basic',
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Views exposed form plugin for Autocomplete Widgets module.
|
||||
*/
|
||||
class autocomplete_widgets_basic_exposed_form_plugin extends views_plugin_exposed_form_basic {
|
||||
|
||||
/**
|
||||
* Return a string to display as the clickable title for the control.
|
||||
*/
|
||||
function summary_title() {
|
||||
return t('Autocomplete widgets');
|
||||
}
|
||||
|
||||
/**
|
||||
* Declare custom plugin options.
|
||||
*/
|
||||
function option_definition() {
|
||||
$options = parent::option_definition();
|
||||
$options['make_autocompletable'] = array('default' => array());
|
||||
return $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate form elements for custom plugin options.
|
||||
*/
|
||||
function options_form(&$form, &$form_state) {
|
||||
parent::options_form($form, $form_state);
|
||||
$relationships = $this->view->relationship;
|
||||
$options = array();
|
||||
foreach ($this->display->handler->get_handlers('filter') as $filter => $handler) {
|
||||
if ($handler->is_exposed() && $handler->content_field['widget']['module'] == 'autocomplete_widgets') {
|
||||
$options[$filter] = $handler->ui_name();
|
||||
if (!empty($handler->options['relationship'])) {
|
||||
$relationship = $handler->options['relationship'];
|
||||
if (!empty($relationships[$relationship])) {
|
||||
$options[$filter] = '('. $relationships[$relationship] .') '. $options[$filter];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($options)) {
|
||||
$form['make_autocompletable'] = array(
|
||||
'#type' => 'checkboxes',
|
||||
'#title' => t('Convert into a autocomplete widget'),
|
||||
'#options' => $options,
|
||||
'#default_value' => $this->options['make_autocompletable'],
|
||||
'#description' => t('This list contains only exposed filters for CCK Text and Number fields.'),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Alter the exposed filters based on plugin options.
|
||||
*/
|
||||
function exposed_form_alter(&$form, &$form_state) {
|
||||
parent::exposed_form_alter($form, $form_state);
|
||||
|
||||
if (!empty($this->options['make_autocompletable'])) {
|
||||
foreach ($this->options['make_autocompletable'] as $filter) {
|
||||
$field_name = $this->view->filter[$filter]->content_field['field_name'];
|
||||
$type_name = $this->view->filter[$filter]->content_field['type_name'];
|
||||
$form[$filter]['#autocomplete_path'] = 'autocomplete_widgets/'. $type_name .'/'. $field_name;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Reference in a new issue