Permalink
Browse files

Initial commit. Still some bugs, but it's mostly working.

  • Loading branch information...
0 parents commit e322be61334341543dee6d686c0c1c5014f60395 @meltingice committed Jul 29, 2011
Showing with 276 additions and 0 deletions.
  1. +3 −0 .gitmodules
  2. +2 −0 Makefile
  3. +35 −0 README.md
  4. +69 −0 data.php
  5. +1 −0 dist/chosen
  6. +39 −0 index.html
  7. +47 −0 lib/ajax-chosen.js
  8. +80 −0 src/ajax-chosen.coffee
@@ -0,0 +1,3 @@
+[submodule "dist/chosen"]
+ path = dist/chosen
+ url = https://github.com/harvesthq/chosen.git
@@ -0,0 +1,2 @@
+all:
+ coffee -o lib/ -c src/
@@ -0,0 +1,35 @@
+# Ajax-Chosen
+
+This project is an addition to the excellent [Chosen jQuery plugin](https://github.com/harvesthq/chosen) that makes HTML input forms more friendly. Chosen adds search boxes to `select` HTML elements, so I felt it could use the addition of ajax autocomplete for awesomely dynamic forms.
+
+This script bootstraps the existing Chosen plugin without making any modifications to the original code.
+
+## How to Use
+
+This plugin exposes a new jQuery function named `ajaxChosen` that we call on a `select` element. The first argument are the options passed to the jQuery $.ajax function. The `data` parameter should be omitted, and the `success` callback is optional.
+
+The second argument is a callback that tells the plugin what HTML `option` elements to make. It is passed the data returned from the ajax call, and you have to return an object where the key is the HTML `option` value attribute and the value is the text to display. In other words:
+
+ terms[3] = "Ohio";
+
+ becomes:
+
+ <option value="3">Ohio</option>
+
+## Example Code
+
+``` js
+$("#example-input").ajaxChosen({
+ method: 'GET',
+ url: '/ajax-chosen/data.php',
+ dataType: 'json'
+}, function (data) {
+ var terms = {};
+
+ $.each(data, function (i, val) {
+ terms[i] = val;
+ });
+
+ return terms;
+});
+```
@@ -0,0 +1,69 @@
+<?php
+
+if (!isset($_GET['term'])) exit;
+else $term = trim($_GET['term']);
+
+$data = array(
+ 'Alabama',
+ 'Alaska',
+ 'Arizona',
+ 'Arkansas',
+ 'California',
+ 'Colorado',
+ 'Connecticut',
+ 'Delaware',
+ 'District of Columbia',
+ 'Florida',
+ 'Georgia',
+ 'Hawaii',
+ 'Idaho',
+ 'Illinois',
+ 'Indiana',
+ 'Iowa',
+ 'Kansas',
+ 'Kentucky',
+ 'Louisiana',
+ 'Maine',
+ 'Maryland',
+ 'Massachusetts',
+ 'Michigan',
+ 'Minnesota',
+ 'Mississippi',
+ 'Missouri',
+ 'Montana',
+ 'Nebraska',
+ 'Nevada',
+ 'New Hampshire',
+ 'New Jersey',
+ 'New Mexico',
+ 'New York',
+ 'North Carolina',
+ 'North Dakota',
+ 'Ohio',
+ 'Oklahoma',
+ 'Oregon',
+ 'Pennsylvania',
+ 'Puerto Rico',
+ 'Rhode Island',
+ 'South Carolina',
+ 'South Dakota',
+ 'Tennessee',
+ 'Texas',
+ 'Utah',
+ 'Vermont',
+ 'Virginia',
+ 'Virgin Islands',
+ 'Washington',
+ 'West Virginia',
+ 'Wisconsin',
+ 'Wyoming'
+);
+
+
+$results = array();
+foreach ($data as $i => $state) {
+ $results[$state] = levenshtein($term, $state);
+}
+
+asort($results);
+echo json_encode(array_keys(array_slice($results, 0, 5)));
Submodule chosen added at f5e508
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <title>Ajax-Chosen: Bootstrapping a Popular jQuery Plugin to add Ajax Autocomplete</title>
+
+ <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
+ <script type="text/javascript" src="/ajax-chosen/dist/chosen/chosen/chosen.jquery.min.js"></script>
+ <script type="text/javascript" src="/ajax-chosen/lib/ajax-chosen.js"></script>
+
+ <link type="text/css" rel="stylesheet" href="/ajax-chosen/dist/chosen/chosen/chosen.css" />
+
+ <style type="text/css">
+ #example1 { width: 300px; }
+ </style>
+
+ <script type="text/javascript">
+ $(document).ready(function () {
+ $("#example1").ajaxChosen({
+ method: 'GET',
+ url: '/ajax-chosen/data.php',
+ dataType: 'json'
+ }, function (data) {
+ var terms = {};
+
+ $.each(data, function (i, val) {
+ terms[i] = val;
+ });
+
+ return terms;
+ });
+ });
+ </script>
+</head>
+<body>
+ <h1>Ajax-Chosen: Bootstrapping a jQuery Plugin</h1>
+
+ <select id="example1" title="Search for a state" multiple></select>
+</body>
+</html>
@@ -0,0 +1,47 @@
+(function() {
+ (function($) {
+ return $.fn.ajaxChosen = function(options, callback) {
+ var select;
+ select = this;
+ this.chosen();
+ return this.next('.chzn-container').find(".search-field > input").bind('keyup', function() {
+ var field, val;
+ val = $.trim($(this).attr('value'));
+ if (val.length < 3 || val === $(this).data('prevVal')) {
+ return false;
+ }
+ $(this).data('prevVal', val);
+ field = $(this);
+ options.data = {
+ term: val
+ };
+ if (typeof success !== "undefined" && success !== null) {
+ success;
+ } else {
+ success = options.success;
+ };
+ options.success = function(data) {
+ var items;
+ if (!(data != null)) {
+ return;
+ }
+ select.find('option').each(function() {
+ if (!$(this).is(":selected")) {
+ return $(this).remove();
+ }
+ });
+ items = callback(data);
+ $.each(items, function(value, text) {
+ return $("<option />").attr('value', value).html(text).appendTo(select);
+ });
+ select.trigger("liszt:updated");
+ field.attr('value', val);
+ if (typeof success !== "undefined" && success !== null) {
+ return success();
+ }
+ };
+ return $.ajax(options);
+ });
+ };
+ })(jQuery);
+}).call(this);
@@ -0,0 +1,80 @@
+(($) ->
+
+ $.fn.ajaxChosen = (options, callback) ->
+ # This will come in handy later.
+ select = this
+
+ # Load chosen. To make things clear, I have taken the liberty
+ # of using the .chzn-autoselect class to specify input elements
+ # we want to use with ajax autocomplete.
+ this.chosen()
+
+ # Now that chosen is loaded normally, we can bootstrap it with
+ # our ajax autocomplete code.
+ this.next('.chzn-container')
+ .find(".search-field > input")
+ .bind 'keyup', ->
+ # This code will be executed every time the user types a letter
+ # into the input form that chosen has created
+
+ # Retrieve the current value of the input form
+ val = $.trim $(this).attr('value')
+
+ # Some simple validation so we don't make excess ajax calls. I am
+ # assuming you don't want to perform a search with less than 3
+ # characters.
+ return false if val.length < 3 or val is $(this).data('prevVal')
+
+ # Set the current search term so we don't execute the ajax call if
+ # the user hits a key that isn't an input letter/number/symbol
+ $(this).data('prevVal', val)
+
+ # This is a useful reference for later
+ field = $(this)
+
+ # I'm assuming that it's ok to use the parameter name `term` to send
+ # the form value during the ajax call. Change if absolutely needed.
+ options.data = term: val
+
+ # If the user provided an ajax success callback, store it so we can
+ # call it after our bootstrapping is finished.
+ success ?= options.success
+
+ # Create our own callback that will be executed when the ajax call is
+ # finished.
+ options.success = (data) ->
+ # Exit if the data we're given is invalid
+ return if not data?
+
+ # Go through all of the <option> elements in the <select> and remove
+ # ones that have not been selected by the user.
+ select.find('option').each -> $(this).remove() if not $(this).is(":selected")
+
+ # Send the ajax results to the user callback so we can get an object of
+ # value => text pairs to inject as <option> elements.
+ items = callback data
+
+ # Iterate through the given data and inject the <option> elements into
+ # the DOM
+ $.each items, (value, text) ->
+ $("<option />")
+ .attr('value', value)
+ .html(text)
+ .appendTo(select)
+
+ # Tell chosen that the contents of the <select> input have been updated
+ # This makes chosen update its internal list of the input data.
+ select.trigger("liszt:updated")
+
+ # For some reason, the contents of the input field get removed once you
+ # call trigger above. Often, this can be very annoying (and can make some
+ # searches impossible), so we add the value the user was typing back into
+ # the input field.
+ field.attr('value', val)
+
+ # Finally, call the user supplied callback (if it exists)
+ success() if success?
+
+ # Execute the ajax call to search for autocomplete data
+ $.ajax(options)
+)(jQuery)

0 comments on commit e322be6

Please sign in to comment.