Contextual Related Posts - Version 1.2

Version Description

Download this release

Release Info

Developer Ajay
Plugin Icon 128x128 Contextual Related Posts
Version 1.2
Comparing to
See all releases

Code changes from version 1.1.1 to 1.2

admin.inc.php CHANGED
@@ -2,6 +2,16 @@
2
  /**********************************************************************
3
  * Admin Page *
4
  *********************************************************************/
 
 
 
 
 
 
 
 
 
 
5
  function crp_options() {
6
 
7
  global $wpdb;
@@ -12,10 +22,23 @@ function crp_options() {
12
  if($_POST['crp_save']){
13
  $crp_settings[title] = ($_POST['title']);
14
  $crp_settings[limit] = ($_POST['limit']);
 
15
  $crp_settings[add_to_content] = (($_POST['add_to_content']) ? true : false);
 
16
  $crp_settings[add_to_feed] = (($_POST['add_to_feed']) ? true : false);
17
  $crp_settings[match_content] = (($_POST['match_content']) ? true : false);
 
 
 
18
 
 
 
 
 
 
 
 
 
19
  update_option('ald_crp_settings', $crp_settings);
20
 
21
  $str = '<div id="message" class="updated fade"><p>'. __('Options saved successfully.','ald_crp_plugin') .'</p></div>';
@@ -49,7 +72,7 @@ function crp_options() {
49
  (<a href="http://ajaydsouza.com/donate/"><?php _e('Some reasons why you should.','ald_crp_plugin'); ?></a>)</p>
50
  </fieldset>
51
  </div>
52
- <form method="post" id="crp_options" name="crp_options" style="border: #ccc 1px solid; padding: 10px">
53
  <fieldset class="options">
54
  <legend>
55
  <h3>
@@ -68,10 +91,41 @@ function crp_options() {
68
  <input type="textbox" name="title" id="title" value="<?php echo stripslashes($crp_settings[title]); ?>">
69
  </label>
70
  </p>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
71
  <p>
72
  <label>
73
  <input type="checkbox" name="add_to_content" id="add_to_content" <?php if ($crp_settings[add_to_content]) echo 'checked="checked"' ?> />
74
- <?php _e('Add related posts to the post content on single pages. <br />If you choose to disable this, please add <code>&lt;?php if(function_exists(\'ald_crp\')) echo_ald_crp(); ?&gt;</code> to your template file where you want it displayed','ald_crp_plugin'); ?>
 
 
 
 
 
 
75
  </label>
76
  </p>
77
  <p>
@@ -86,6 +140,12 @@ function crp_options() {
86
  <?php _e('Find related posts based on content as well as title. If unchecked, only posts titles are used. (I recommend using a caching plugin if you enable this)','ald_crp_plugin'); ?>
87
  </label>
88
  </p>
 
 
 
 
 
 
89
  <p>
90
  <input type="submit" name="crp_save" id="crp_save" value="Save Options" style="border:#00CC00 1px solid" />
91
  <input name="crp_default" type="submit" id="crp_default" value="Default Options" style="border:#FF0000 1px solid" onclick="if (!confirm('<?php _e('Do you want to set options to Default? If you don\'t have a copy of the username, please hit Cancel and copy it first.','ald_crp_plugin'); ?>')) return false;" />
@@ -116,8 +176,32 @@ function crp_adminmenu() {
116
  add_options_page(__("Related Posts", 'myald_crp_plugin'), __("Related Posts", 'myald_crp_plugin'), 9, 'crp_options', 'crp_options');
117
  }
118
  }
 
119
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
120
 
121
- add_action('admin_menu', 'crp_adminmenu');
122
 
123
  ?>
2
  /**********************************************************************
3
  * Admin Page *
4
  *********************************************************************/
5
+ // Pre-2.6 compatibility
6
+ if ( !defined('WP_CONTENT_URL') )
7
+ define( 'WP_CONTENT_URL', get_option('siteurl') . '/wp-content');
8
+ if ( !defined('WP_CONTENT_DIR') )
9
+ define( 'WP_CONTENT_DIR', ABSPATH . 'wp-content' );
10
+ // Guess the location
11
+ $crp_path = WP_CONTENT_DIR.'/plugins/'.plugin_basename(dirname(__FILE__));
12
+ $crp_url = WP_CONTENT_URL.'/plugins/'.plugin_basename(dirname(__FILE__));
13
+
14
+
15
  function crp_options() {
16
 
17
  global $wpdb;
22
  if($_POST['crp_save']){
23
  $crp_settings[title] = ($_POST['title']);
24
  $crp_settings[limit] = ($_POST['limit']);
25
+ $crp_settings[exclude_cat_slugs] = ($_POST['exclude_cat_slugs']);
26
  $crp_settings[add_to_content] = (($_POST['add_to_content']) ? true : false);
27
+ $crp_settings[add_to_page] = (($_POST['add_to_page']) ? true : false);
28
  $crp_settings[add_to_feed] = (($_POST['add_to_feed']) ? true : false);
29
  $crp_settings[match_content] = (($_POST['match_content']) ? true : false);
30
+ $crp_settings[exclude_pages] = (($_POST['exclude_pages']) ? true : false);
31
+ $crp_settings[blank_output] = (($_POST['blank_output'] == 'blank' ) ? true : false);
32
+
33
 
34
+ $exclude_categories_slugs = explode(", ",$crp_settings[exclude_cat_slugs]);
35
+
36
+ $exclude_categories = '';
37
+ foreach ($exclude_categories_slugs as $exclude_categories_slug) {
38
+ $exclude_categories .= get_category_by_slug($exclude_categories_slug)->term_id . ',';
39
+ }
40
+ $crp_settings[exclude_categories] = substr($exclude_categories, 0, -2);
41
+
42
  update_option('ald_crp_settings', $crp_settings);
43
 
44
  $str = '<div id="message" class="updated fade"><p>'. __('Options saved successfully.','ald_crp_plugin') .'</p></div>';
72
  (<a href="http://ajaydsouza.com/donate/"><?php _e('Some reasons why you should.','ald_crp_plugin'); ?></a>)</p>
73
  </fieldset>
74
  </div>
75
+ <form method="post" id="crp_options" name="crp_options" style="border: #ccc 1px solid; padding: 10px" onsubmit="return checkForm()">
76
  <fieldset class="options">
77
  <legend>
78
  <h3>
91
  <input type="textbox" name="title" id="title" value="<?php echo stripslashes($crp_settings[title]); ?>">
92
  </label>
93
  </p>
94
+ <p><?php _e('Exclude Categories: ','ald_crp_plugin'); ?></p>
95
+ <div style="position:relative;text-align:left">
96
+ <table id="MYCUSTOMFLOATER" class="myCustomFloater" style="position:absolute;top:50px;left:0;background-color:#cecece;display:none;visibility:hidden">
97
+ <tr><td><!--
98
+ please see: http://chrisholland.blogspot.com/2004/09/geekstuff-css-display-inline-block.html
99
+ to explain why i'm using a table here.
100
+ You could replace the table/tr/td with a DIV, but you'd have to specify it's width and height
101
+ -->
102
+ <div class="myCustomFloaterContent">
103
+ you should never be seeing this
104
+ </div>
105
+ </td></tr>
106
+ </table>
107
+ <textarea class="wickEnabled:MYCUSTOMFLOATER" cols="50" rows="3" wrap="virtual" name="exclude_cat_slugs"><?php echo stripslashes($crp_settings[exclude_cat_slugs]); ?></textarea>
108
+ </div>
109
+ <p><?php _e('When there are no posts, what should be shown?','ald_crp_plugin'); ?><br />
110
+ <label>
111
+ <input type="radio" name="blank_output" value="blank" id="blank_output_0" <?php if ($crp_settings['blank_output']) echo 'checked="checked"' ?> />
112
+ <?php _e('Blank Output','ald_crp_plugin'); ?></label>
113
+ <br />
114
+ <label>
115
+ <input type="radio" name="blank_output" value="noposts" id="blank_output_1" <?php if (!$crp_settings['blank_output']) echo 'checked="checked"' ?> />
116
+ <?php _e('Display "No Related Posts"','ald_crp_plugin'); ?></label>
117
+ <br />
118
+ </p>
119
  <p>
120
  <label>
121
  <input type="checkbox" name="add_to_content" id="add_to_content" <?php if ($crp_settings[add_to_content]) echo 'checked="checked"' ?> />
122
+ <?php _e('Add related posts to the post content on single posts. <br />If you choose to disable this, please add <code>&lt;?php if(function_exists(\'echo_ald_crp\')) echo_ald_crp(); ?&gt;</code> to your template file where you want it displayed','ald_crp_plugin'); ?>
123
+ </label>
124
+ </p>
125
+ <p>
126
+ <label>
127
+ <input type="checkbox" name="add_to_page" id="add_to_page" <?php if ($crp_settings[add_to_page]) echo 'checked="checked"' ?> />
128
+ <?php _e('Add related posts to pages. <br />If you choose to disable this, please add <code>&lt;?php if(function_exists(\'echo_ald_crp\')) echo_ald_crp(); ?&gt;</code> to your template file where you want it displayed','ald_crp_plugin'); ?>
129
  </label>
130
  </p>
131
  <p>
140
  <?php _e('Find related posts based on content as well as title. If unchecked, only posts titles are used. (I recommend using a caching plugin if you enable this)','ald_crp_plugin'); ?>
141
  </label>
142
  </p>
143
+ <p>
144
+ <label>
145
+ <input type="checkbox" name="exclude_pages" id="exclude_pages" <?php if ($crp_settings[exclude_pages]) echo 'checked="checked"' ?> />
146
+ <?php _e('Exclude Pages in Related Posts','ald_crp_plugin'); ?>
147
+ </label>
148
+ </p>
149
  <p>
150
  <input type="submit" name="crp_save" id="crp_save" value="Save Options" style="border:#00CC00 1px solid" />
151
  <input name="crp_default" type="submit" id="crp_default" value="Default Options" style="border:#FF0000 1px solid" onclick="if (!confirm('<?php _e('Do you want to set options to Default? If you don\'t have a copy of the username, please hit Cancel and copy it first.','ald_crp_plugin'); ?>')) return false;" />
176
  add_options_page(__("Related Posts", 'myald_crp_plugin'), __("Related Posts", 'myald_crp_plugin'), 9, 'crp_options', 'crp_options');
177
  }
178
  }
179
+ add_action('admin_menu', 'crp_adminmenu');
180
 
181
+ function crp_adminhead() {
182
+ global $crp_url;
183
+
184
+ ?>
185
+ <link rel="stylesheet" type="text/css" href="<?php echo $crp_url ?>/wick/wick.css" />
186
+ <script type="text/javascript" language="JavaScript">
187
+ function checkForm() {
188
+ answer = true;
189
+ if (siw && siw.selectingSomething)
190
+ answer = false;
191
+ return answer;
192
+ }//
193
+ </script>
194
+ <?php }
195
+ add_action('admin_head', 'crp_adminhead');
196
+
197
+ function crp_adminfoot() {
198
+ global $crp_url;
199
+
200
+ ?>
201
+ <script type="text/javascript" src="<?php echo $crp_url ?>/wick/sample_data.js.php"></script>
202
+ <script type="text/javascript" src="<?php echo $crp_url ?>/wick/wick.js"></script>
203
+ <?php }
204
+ add_action('admin_footer', 'crp_adminfoot');
205
 
 
206
 
207
  ?>
contextual-related-posts.php CHANGED
@@ -1,7 +1,7 @@
1
  <?php
2
  /*
3
  Plugin Name: Contextual Related Posts
4
- Version: 1.1.1
5
  Plugin URI: http://ajaydsouza.com/wordpress/plugins/contextual-related-posts/
6
  Description: Show user defined number of contextually related posts. Based on the plugin by <a href="http://weblogtoolscollection.com">Mark Ghosh</a>. <a href="options-general.php?page=crp_options">Configure...</a>
7
  Author: Ajay D'Souza
@@ -22,9 +22,10 @@ define('ALD_crp_DIR', dirname(__FILE__));
22
  ********************************************************************/
23
  function ald_crp() {
24
  global $wpdb, $post, $single;
25
- $poststable = $wpdb->posts;
26
  $crp_settings = crp_read_options();
27
  $limit = $crp_settings['limit'];
 
28
 
29
  // Make sure the post is not from the future
30
  $time_difference = get_settings('gmt_offset');
@@ -37,35 +38,48 @@ function ald_crp() {
37
  $stuff = addslashes($post->post_title);
38
  }
39
 
40
- $sql = "SELECT ID,post_title,post_content,post_excerpt,post_date,"
41
  . "MATCH(post_title,post_content) AGAINST ('$stuff') AS score "
42
- . "FROM $poststable WHERE "
43
  . "MATCH (post_title,post_content) AGAINST ('$stuff') "
44
  . "AND post_date <= '$now' "
45
  . "AND post_status = 'publish' "
46
- . "AND id != $post->ID "
47
- . "LIMIT 0,$limit";
48
-
 
49
  $search_counter = 0;
50
  $searches = $wpdb->get_results($sql);
51
 
52
- $output = '<div id="crp_related">'.$crp_settings['title'];
53
 
54
  if($searches){
 
55
  $output .= '<ul>';
56
  foreach($searches as $search) {
 
 
57
  $title = trim(stripslashes($search->post_title));
58
- if ($search_counter <= $limit) {
59
- $output .= '<li><a href="'.get_permalink($search->ID).'" rel="bookmark">'.$title.'</a></li>';
60
- } //end of search_counter loop
61
- $search_counter++;
 
 
 
 
 
 
62
  } //end of foreach loop
63
  $output .= '</ul>';
64
  }else{
65
- $output .= '<p>'.__('No related posts found').'</p>';
66
  }
67
-
68
- $output .= '</div><br/><br/>';
 
 
 
69
 
70
  return $output;
71
  }
@@ -76,11 +90,13 @@ function ald_crp_content($content) {
76
  $crp_settings = crp_read_options();
77
  $output = ald_crp();
78
 
79
- if((is_feed())&&($crp_settings['add_to_feed'])) {
 
 
80
  return $content.$output;
81
- } elseif(($single)&&($crp_settings['add_to_content'])) {
82
  return $content.$output;
83
- } else {
84
  return $content;
85
  }
86
  }
@@ -93,14 +109,19 @@ function echo_ald_crp() {
93
 
94
  // Default Options
95
  function crp_default_options() {
96
- $title = __('<h2>Related Posts:</h2>');
97
 
98
  $crp_settings = Array (
99
- title => $title, // Add before the content
100
- add_to_content => true, // Add related posts to content (only on single pages)
 
101
  add_to_feed => true, // Add related posts to feed
102
- limit => '5', // How many posts to display?
103
- match_content => '5', // Match against post content as well as title
 
 
 
 
104
  );
105
  return $crp_settings;
106
  }
1
  <?php
2
  /*
3
  Plugin Name: Contextual Related Posts
4
+ Version: 1.2
5
  Plugin URI: http://ajaydsouza.com/wordpress/plugins/contextual-related-posts/
6
  Description: Show user defined number of contextually related posts. Based on the plugin by <a href="http://weblogtoolscollection.com">Mark Ghosh</a>. <a href="options-general.php?page=crp_options">Configure...</a>
7
  Author: Ajay D'Souza
22
  ********************************************************************/
23
  function ald_crp() {
24
  global $wpdb, $post, $single;
25
+
26
  $crp_settings = crp_read_options();
27
  $limit = $crp_settings['limit'];
28
+ $exclude_categories = explode(',',$crp_settings['exclude_categories']);
29
 
30
  // Make sure the post is not from the future
31
  $time_difference = get_settings('gmt_offset');
38
  $stuff = addslashes($post->post_title);
39
  }
40
 
41
+ $sql = "SELECT DISTINCT ID,post_title,post_date,"
42
  . "MATCH(post_title,post_content) AGAINST ('$stuff') AS score "
43
+ . "FROM $wpdb->posts WHERE "
44
  . "MATCH (post_title,post_content) AGAINST ('$stuff') "
45
  . "AND post_date <= '$now' "
46
  . "AND post_status = 'publish' "
47
+ . "AND id != $post->ID ";
48
+ if ($crp_settings['exclude_pages']) $sql .= "AND post_type = 'post' ";
49
+ $sql .= "ORDER BY score DESC ";
50
+
51
  $search_counter = 0;
52
  $searches = $wpdb->get_results($sql);
53
 
54
+ $output = '<div id="crp_related">';
55
 
56
  if($searches){
57
+ $output .= $crp_settings['title'];
58
  $output .= '<ul>';
59
  foreach($searches as $search) {
60
+ $categorys = get_the_category($search->ID); //Fetch categories of the plugin
61
+ $p_in_c = false;
62
  $title = trim(stripslashes($search->post_title));
63
+ foreach ($categorys as $cat) {
64
+ if (!$p_in_c) $p_in_c = (in_array($cat->cat_ID, $exclude_categories)) ? true : false;
65
+ }
66
+
67
+ if (!$p_in_c) {
68
+ if ($search_counter <= $limit) {
69
+ $output .= '<li><a href="'.get_permalink($search->ID).'" rel="bookmark">'.$title.'</a></li>';
70
+ $search_counter++;
71
+ } //end of search_counter loop
72
+ }
73
  } //end of foreach loop
74
  $output .= '</ul>';
75
  }else{
76
+ $output .= (($_POST['blank_output']) ? '' : '<p>'.__('No related posts found','ald_crp_plugin').'</p>');
77
  }
78
+ if ((strpos($output, '<li>')) === false) {
79
+ $output = '<div id="crp_related">';
80
+ $output .= (($_POST['blank_output']) ? '' : '<p>'.__('No related posts found','ald_crp_plugin').'</p>');
81
+ }
82
+ $output .= '</div>';
83
 
84
  return $output;
85
  }
90
  $crp_settings = crp_read_options();
91
  $output = ald_crp();
92
 
93
+ if((is_single())&&($crp_settings['add_to_content'])) {
94
+ return $content.$output;
95
+ } elseif((is_page())&&($crp_settings['add_to_page'])) {
96
  return $content.$output;
97
+ } elseif((is_feed())&&($crp_settings['add_to_feed'])) {
98
  return $content.$output;
99
+ } else {
100
  return $content;
101
  }
102
  }
109
 
110
  // Default Options
111
  function crp_default_options() {
112
+ $title = __('<h3>Related Posts:</h3>');
113
 
114
  $crp_settings = Array (
115
+ title => $title, // Add before the content
116
+ add_to_content => true, // Add related posts to content (only on single posts)
117
+ add_to_page => false, // Add related posts to content (only on single pages)
118
  add_to_feed => true, // Add related posts to feed
119
+ limit => '5', // How many posts to display?
120
+ match_content => true, // Match against post content as well as title
121
+ exclude_pages => true, // Exclude Pages
122
+ blank_output => true, // Match against post tags as well as title
123
+ exclude_categories => '', // Exclude these categories
124
+ exclude_cat_slugs => '', // Exclude these categories
125
  );
126
  return $crp_settings;
127
  }
readme.txt CHANGED
@@ -3,15 +3,21 @@ Tags: related posts, similar posts
3
  Contributors: Ajay D'Souza, Mark Ghosh
4
  Donate link: http://ajaydsouza.com/donate/
5
  Stable tag: trunk
6
- Requires at least: 1.5
7
  Tested up to: 2.7
8
 
9
 
10
  Show user defined number of contextually related posts
11
 
 
12
  == Description ==
13
 
14
- Display a list of contextually related posts for the current post. You can select the number of posts to display and if you want to automatically display the related posts in your content / feed.
 
 
 
 
 
15
 
16
  == Installation ==
17
 
@@ -26,6 +32,12 @@ Display a list of contextually related posts for the current post. You can selec
26
 
27
  == Changelog ==
28
 
 
 
 
 
 
 
29
  * 1.1 - Fixed MySQL index key conflicts by using a more unique index key name.
30
  * 1.0.1 - Release
31
 
@@ -34,7 +46,7 @@ Display a list of contextually related posts for the current post. You can selec
34
 
35
  = What are the requirements for this plugin? =
36
 
37
- WordPress 2.0 or above
38
 
39
 
40
  = Can I customize what is displayed? =
3
  Contributors: Ajay D'Souza, Mark Ghosh
4
  Donate link: http://ajaydsouza.com/donate/
5
  Stable tag: trunk
6
+ Requires at least: 2.5
7
  Tested up to: 2.7
8
 
9
 
10
  Show user defined number of contextually related posts
11
 
12
+
13
  == Description ==
14
 
15
+ Display a list of contextually related posts for the current post.
16
+
17
+ You can select the number of posts to display and if you want to automatically display the related posts in your content / feed.
18
+
19
+ Now, you can choose to exclude posts from certain categories as well as exclude pages.
20
+
21
 
22
  == Installation ==
23
 
32
 
33
  == Changelog ==
34
 
35
+ * 1.2
36
+ - Option to blank output in case nothing is found
37
+ - Exclude posts from certain categories
38
+ - Exclude pages
39
+ - Option to choose if you want related posts to be displayed on pages
40
+ * 1.1.1 - Now you can optionally choose if you want to use the post content to search for related posts
41
  * 1.1 - Fixed MySQL index key conflicts by using a more unique index key name.
42
  * 1.0.1 - Release
43
 
46
 
47
  = What are the requirements for this plugin? =
48
 
49
+ WordPress 2.5 or above
50
 
51
 
52
  = Can I customize what is displayed? =
wick/sample_data.js.php ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ //"sample_data.js.php" List of categories
3
+ Header("content-type: application/x-javascript");
4
+
5
+ if (!function_exists('add_action')) {
6
+ $wp_root = '../../../..';
7
+ if (file_exists($wp_root.'/wp-load.php')) {
8
+ require_once($wp_root.'/wp-load.php');
9
+ } else {
10
+ require_once($wp_root.'/wp-config.php');
11
+ }
12
+ }
13
+
14
+ // Ajax Increment Counter
15
+ wick_data();
16
+ function wick_data() {
17
+ global $wpdb;
18
+
19
+ $categories = get_categories('hide_empty=0');
20
+ $str = 'collection = [';
21
+ foreach ($categories as $cat) {
22
+ $str .= "'".$cat->slug."',";
23
+ }
24
+ $str = substr($str, 0, -1); // Remove trailing comma
25
+ $str .= '];';
26
+
27
+ echo $str;
28
+ }
29
+
30
+
31
+ ?>
wick/wick.css ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ WICK: Web Input Completion Kit
3
+ http://wick.sourceforge.net/
4
+ Copyright (c) 2004, Christopher T. Holland,
5
+ All rights reserved.
6
+
7
+ Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
8
+
9
+ Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
10
+ Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
11
+ Neither the name of the Christopher T. Holland, nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
12
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
13
+
14
+ */
15
+
16
+ .floater {
17
+ position:absolute;
18
+ z-index:2;
19
+ bottom:0;
20
+ right:0;
21
+ display:none;
22
+ padding:0;
23
+ }
24
+
25
+ .floater td {
26
+ font-family: Gill, Helvetica, sans-serif;
27
+ background-color:white;
28
+ border:1px inset #979797;
29
+ color:black;
30
+ }
31
+
32
+ .matchedSmartInputItem {
33
+ font-size:0.8em;
34
+ padding: 5px 10px 1px 5px;
35
+ margin:0;
36
+ cursor:pointer;
37
+ }
38
+
39
+ .selectedSmartInputItem {
40
+ color:white;
41
+ background-color:#3875D7;
42
+ }
43
+
44
+ #smartInputResults {
45
+ padding:0;margin:0;
46
+ }
47
+
48
+ .siwCredit {
49
+ margin:0;padding:0;margin-top:10px;font-size:0.7em;color:black;
50
+ }
51
+
wick/wick.js ADDED
@@ -0,0 +1,492 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ WICK: Web Input Completion Kit
3
+ http://wick.sourceforge.net/
4
+ Copyright (c) 2004, Christopher T. Holland
5
+ All rights reserved.
6
+
7
+ Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
8
+
9
+ Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
10
+ Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
11
+ Neither the name of the Christopher T. Holland, nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
12
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
13
+
14
+ */
15
+ /* start dhtml building blocks */
16
+ function freezeEvent(e) {
17
+ if (e.preventDefault) e.preventDefault();
18
+ e.returnValue = false;
19
+ e.cancelBubble = true;
20
+ if (e.stopPropagation) e.stopPropagation();
21
+ return false;
22
+ }//freezeEvent
23
+
24
+ function isWithinNode(e,i,c,t,obj) {
25
+ answer = false;
26
+ te = e;
27
+ while(te && !answer) {
28
+ if ((te.id && (te.id == i)) || (te.className && (te.className == i+"Class"))
29
+ || (!t && c && te.className && (te.className == c))
30
+ || (!t && c && te.className && (te.className.indexOf(c) != -1))
31
+ || (t && te.tagName && (te.tagName.toLowerCase() == t))
32
+ || (obj && (te == obj))
33
+ ) {
34
+ answer = te;
35
+ } else {
36
+ te = te.parentNode;
37
+ }
38
+ }
39
+ return te;
40
+ }//isWithinNode
41
+
42
+ function getEvent(event) {
43
+ return (event ? event : window.event);
44
+ }//getEvent()
45
+
46
+ function getEventElement(e) {
47
+ return (e.srcElement ? e.srcElement: (e.target ? e.target : e.currentTarget));
48
+ }//getEventElement()
49
+
50
+ function findElementPosX(obj) {
51
+ curleft = 0;
52
+ if (obj.offsetParent) {
53
+ while (obj.offsetParent) {
54
+ curleft += obj.offsetLeft;
55
+ obj = obj.offsetParent;
56
+ }
57
+ }//if offsetParent exists
58
+ else if (obj.x)
59
+ curleft += obj.x
60
+ return curleft;
61
+ }//findElementPosX
62
+
63
+ function findElementPosY(obj) {
64
+ curtop = 0;
65
+ if (obj.offsetParent) {
66
+ while (obj.offsetParent) {
67
+ curtop += obj.offsetTop;
68
+ obj = obj.offsetParent;
69
+ }
70
+ }//if offsetParent exists
71
+ else if (obj.y)
72
+ curtop += obj.y
73
+ return curtop;
74
+ }//findElementPosY
75
+
76
+ /* end dhtml building blocks */
77
+
78
+ function handleKeyPress(event) {
79
+ e = getEvent(event);
80
+ eL = getEventElement(e);
81
+
82
+ upEl = isWithinNode(eL,null,"wickEnabled",null,null);
83
+
84
+ kc = e["keyCode"];
85
+
86
+ if (siw && ((kc == 13) || (kc == 9))) {
87
+ siw.selectingSomething = true;
88
+ if (siw.isSafari) siw.inputBox.blur(); //hack to "wake up" safari
89
+ siw.inputBox.focus();
90
+ siw.inputBox.value = siw.inputBox.value.replace(/[ \r\n\t\f\s]+$/gi,' ');
91
+ hideSmartInputFloater();
92
+ } else if (upEl && (kc != 38) && (kc != 40) && (kc != 37) && (kc != 39) && (kc != 13) && (kc != 27)) {
93
+ if (!siw || (siw && !siw.selectingSomething)) {
94
+ processSmartInput(upEl);
95
+ }
96
+ } else if (siw && siw.inputBox) {
97
+ siw.inputBox.focus(); //kinda part of the hack.
98
+ }
99
+
100
+ }//handleKeyPress()
101
+
102
+
103
+ function handleKeyDown(event) {
104
+ e = getEvent(event);
105
+ eL = getEventElement(e);
106
+
107
+ if (siw && (kc = e["keyCode"])) {
108
+ if (kc == 40) {
109
+ siw.selectingSomething = true;
110
+ freezeEvent(e);
111
+ if (siw.isGecko) siw.inputBox.blur(); /* Gecko hack */
112
+ selectNextSmartInputMatchItem();
113
+ } else if (kc == 38) {
114
+ siw.selectingSomething = true;
115
+ freezeEvent(e);
116
+ if (siw.isGecko) siw.inputBox.blur();
117
+ selectPreviousSmartInputMatchItem();
118
+ } else if ((kc == 13) || (kc == 9)) {
119
+ siw.selectingSomething = true;
120
+ activateCurrentSmartInputMatch();
121
+ freezeEvent(e);
122
+ } else if (kc == 27) {
123
+ hideSmartInputFloater();
124
+ freezeEvent(e);
125
+ } else {
126
+ siw.selectingSomething = false;
127
+ }
128
+ }
129
+
130
+ }//handleKeyDown()
131
+
132
+ function handleFocus(event) {
133
+ e = getEvent(event);
134
+ eL = getEventElement(e);
135
+ if (focEl = isWithinNode(eL,null,"wickEnabled",null,null)) {
136
+ if (!siw || (siw && !siw.selectingSomething)) processSmartInput(focEl);
137
+ }
138
+ }//handleFocus()
139
+
140
+ function handleBlur(event) {
141
+ e = getEvent(event);
142
+ eL = getEventElement(e);
143
+ if (blurEl = isWithinNode(eL,null,"wickEnabled",null,null)) {
144
+ if (siw && !siw.selectingSomething) hideSmartInputFloater();
145
+ }
146
+ }//handleBlur()
147
+
148
+ function handleClick(event) {
149
+ e2 = getEvent(event);
150
+ eL2 = getEventElement(e2);
151
+ if (siw && siw.selectingSomething) {
152
+ selectFromMouseClick();
153
+ }
154
+ }//handleClick()
155
+
156
+ function handleMouseOver(event) {
157
+ e = getEvent(event);
158
+ eL = getEventElement(e);
159
+ if (siw && (mEl = isWithinNode(eL,null,"matchedSmartInputItem",null,null))) {
160
+ siw.selectingSomething = true;
161
+ selectFromMouseOver(mEl);
162
+ } else if (isWithinNode(eL,null,"siwCredit",null,null)) {
163
+ siw.selectingSomething = true;
164
+ }else if (siw) {
165
+ siw.selectingSomething = false;
166
+ }
167
+ }//handleMouseOver
168
+
169
+ function showSmartInputFloater() {
170
+ if (!siw.floater.style.display || (siw.floater.style.display=="none")) {
171
+ if (!siw.customFloater) {
172
+ x = findElementPosX(siw.inputBox);
173
+ y = findElementPosY(siw.inputBox) + siw.inputBox.offsetHeight;
174
+ //hack: browser-specific adjustments.
175
+ if (!siw.isGecko && !siw.isWinIE) x += 8;
176
+ if (!siw.isGecko && !siw.isWinIE) y += 10;
177
+ siw.floater.style.left = x;
178
+ siw.floater.style.top = y;
179
+ } else {
180
+ //you may
181
+ //do additional things for your custom floater
182
+ //beyond setting display and visibility
183
+ }
184
+ siw.floater.style.display="block";
185
+ siw.floater.style.visibility="visible";
186
+ }
187
+ }//showSmartInputFloater()
188
+
189
+ function hideSmartInputFloater() {
190
+ if (siw) {
191
+ siw.floater.style.display="none";
192
+ siw.floater.style.visibility="hidden";
193
+ siw = null;
194
+ }//siw exists
195
+ }//hideSmartInputFloater
196
+
197
+ function processSmartInput(inputBox) {
198
+ if (!siw) siw = new smartInputWindow();
199
+ siw.inputBox = inputBox;
200
+
201
+ classData = inputBox.className.split(" ");
202
+ siwDirectives = null;
203
+ for (i=0;(!siwDirectives && classData[i]);i++) {
204
+ if (classData[i].indexOf("wickEnabled") != -1)
205
+ siwDirectives = classData[i];
206
+ }
207
+
208
+ if (siwDirectives && (siwDirectives.indexOf(":") != -1)) {
209
+ siw.customFloater = true;
210
+ newFloaterId = siwDirectives.split(":")[1];
211
+ siw.floater = document.getElementById(newFloaterId);
212
+ siw.floaterContent = siw.floater.getElementsByTagName("div")[0];
213
+ }
214
+
215
+
216
+ setSmartInputData();
217
+ if (siw.matchCollection && (siw.matchCollection.length > 0)) selectSmartInputMatchItem(0);
218
+ content = getSmartInputBoxContent();
219
+ if (content) {
220
+ modifySmartInputBoxContent(content);
221
+ showSmartInputFloater();
222
+ } else hideSmartInputFloater();
223
+ }//processSmartInput()
224
+
225
+ function smartInputMatch(cleanValue, value) {
226
+ this.cleanValue = cleanValue;
227
+ this.value = value;
228
+ this.isSelected = false;
229
+ }//smartInputMatch
230
+
231
+ function simplify(s) {
232
+ return s.toLowerCase().replace(/^[ \s\f\t\n\r]+/,'').replace(/[ \s\f\t\n\r]+$/,'');
233
+ //.replace(/[�,�,�,�,\u00E9,\u00E8,\u00EA,\u00EB]/gi,"e").replace(/[�,�,\u00E0,\u00E2]/gi,"a").
234
+ }//simplify
235
+
236
+ function getUserInputToMatch(s) {
237
+ a = s;
238
+ fields = s.split(",");
239
+ if (fields.length > 0) a = fields[fields.length - 1];
240
+ return a;
241
+ }//getUserInputToMatch
242
+
243
+ function getUserInputBase() {
244
+ s = siw.inputBox.value;
245
+ a = s;
246
+ if ((lastComma = s.lastIndexOf(",")) != -1) {
247
+ a = a.replace(/^(.*\,[ \r\n\t\f\s]*).*$/i,'$1');
248
+ }
249
+ else
250
+ a = "";
251
+ return a;
252
+ }//getUserInputBase()
253
+
254
+ function runMatchingLogic(userInput, standalone) {
255
+ userInput = simplify(userInput);
256
+ uifc = userInput.charAt(0).toLowerCase();
257
+ if (uifc == '"') uifc = (n = userInput.charAt(1)) ? n.toLowerCase() : "z";
258
+ if (standalone) userInput = uifc;
259
+ if (siw) siw.matchCollection = new Array();
260
+ pointerToCollectionToUse = collection;
261
+ if (siw && siw.revisedCollection && (siw.revisedCollection.length > 0) && siw.lastUserInput && (userInput.indexOf(siw.lastUserInput) == 0)) {
262
+ pointerToCollectionToUse = siw.revisedCollection;
263
+ } else if (collectionIndex[userInput] && (collectionIndex[userInput].length > 0)) {
264
+ pointerToCollectionToUse = collectionIndex[userInput];
265
+ } else if (collectionIndex[uifc] && (collectionIndex[uifc].length > 0)) {
266
+ pointerToCollectionToUse = collectionIndex[uifc];
267
+ } else if (siw && (userInput.length == 1) && (!collectionIndex[uifc])) {
268
+ siw.buildIndex = true;
269
+ } else if (siw) {
270
+ siw.buildIndex = false;
271
+ }
272
+
273
+ tempCollection = new Array();
274
+
275
+ re1m = new RegExp("^([ \"\>\<\-]*)("+userInput+")","i");
276
+ re2m = new RegExp("([ \"\>\<\-]+)("+userInput+")","i");
277
+ re1 = new RegExp("^([ \"\}\{\-]*)("+userInput+")","gi");
278
+ re2 = new RegExp("([ \"\}\{\-]+)("+userInput+")","gi");
279
+
280
+ for (i=0,j=0;(i<pointerToCollectionToUse.length);i++) {
281
+ displayMatches = ((!standalone) && (j < siw.MAX_MATCHES));
282
+ entry = pointerToCollectionToUse[i];
283
+ mEntry = simplify(entry);
284
+ if (!standalone && (mEntry.indexOf(userInput) == 0)) {
285
+ userInput = userInput.replace(/\>/gi,'\\}').replace(/\< ?/gi,'\\{');
286
+ re = new RegExp("(" + userInput + ")","i");
287
+ if (displayMatches) {
288
+ siw.matchCollection[j] = new smartInputMatch(entry, mEntry.replace(/\>/gi,'}').replace(/\< ?/gi,'{').replace(re,"<b>$1</b>"));
289
+ }
290
+ tempCollection[j] = entry;
291
+ j++;
292
+ } else if (mEntry.match(re1m) || mEntry.match(re2m)) {
293
+ if (!standalone && displayMatches) {
294
+ siw.matchCollection[j] = new smartInputMatch(entry, mEntry.replace(/\>/gi,'}').replace(/\</gi,'{').replace(re1,"$1<b>$2</b>").replace(re2,"$1<b>$2</b>"));
295
+ }
296
+ tempCollection[j] = entry;
297
+ j++;
298
+ }
299
+ }//loop thru collection
300
+ if (siw) {
301
+ siw.lastUserInput = userInput;
302
+ siw.revisedCollection = tempCollection.join(",").split(",");
303
+ collectionIndex[userInput] = tempCollection.join(",").split(",");
304
+ }
305
+ if (standalone || siw.buildIndex) {
306
+ collectionIndex[uifc] = tempCollection.join(",").split(",");
307
+ if (siw) siw.buildIndex = false;
308
+ }
309
+ }//runMatchingLogic
310
+
311
+ function setSmartInputData() {
312
+ if (siw) {
313
+ orgUserInput = siw.inputBox.value;
314
+ orgUserInput = getUserInputToMatch(orgUserInput);
315
+ userInput = orgUserInput.toLowerCase().replace(/[\r\n\t\f\s]+/gi,' ').replace(/^ +/gi,'').replace(/ +$/gi,'').replace(/ +/gi,' ').replace(/\\/gi,'').replace(/\[/gi,'').replace(/\(/gi,'').replace(/\./gi,'\.').replace(/\?/gi,'');
316
+ if (userInput && (userInput != "") && (userInput != '"')) {
317
+ runMatchingLogic(userInput);
318
+ }//if userinput not blank and is meaningful
319
+ else {
320
+ siw.matchCollection = null;
321
+ }
322
+ }//siw exists ... uhmkaaayyyyy
323
+ }//setSmartInputData
324
+
325
+ function getSmartInputBoxContent() {
326
+ a = null;
327
+ if (siw && siw.matchCollection && (siw.matchCollection.length > 0)) {
328
+ a = '';
329
+ for (i = 0;i < siw.matchCollection.length; i++) {
330
+ selectedString = siw.matchCollection[i].isSelected ? ' selectedSmartInputItem' : '';
331
+ a += '<p class="matchedSmartInputItem' + selectedString + '">' + siw.matchCollection[i].value.replace(/\{ */gi,"&lt;").replace(/\} */gi,"&gt;") + '</p>';
332
+ }//
333
+ }//siw exists
334
+ return a;
335
+ }//getSmartInputBoxContent
336
+
337
+ function modifySmartInputBoxContent(content) {
338
+ //todo: remove credits 'cuz no one gives a shit ;] - done
339
+ siw.floaterContent.innerHTML = '<div id="smartInputResults">' + content + (siw.showCredit ? ('<p class="siwCredit">Powered By: <a target="PhrawgBlog" href="http://chrisholland.blogspot.com/?from=smartinput&ref='+escape(location.href)+'">Chris Holland</a></p>') : '') +'</div>';
340
+ siw.matchListDisplay = document.getElementById("smartInputResults");
341
+ }//modifySmartInputBoxContent()
342
+
343
+ function selectFromMouseOver(o) {
344
+ currentIndex = getCurrentlySelectedSmartInputItem();
345
+ if (currentIndex != null) deSelectSmartInputMatchItem(currentIndex);
346
+ newIndex = getIndexFromElement(o);
347
+ selectSmartInputMatchItem(newIndex);
348
+ modifySmartInputBoxContent(getSmartInputBoxContent());
349
+ }//selectFromMouseOver
350
+
351
+ function selectFromMouseClick() {
352
+ activateCurrentSmartInputMatch();
353
+ siw.inputBox.focus();
354
+ hideSmartInputFloater();
355
+ }//selectFromMouseClick
356
+
357
+ function getIndexFromElement(o) {
358
+ index = 0;
359
+ while(o = o.previousSibling) {
360
+ index++;
361
+ }//
362
+ return index;
363
+ }//getIndexFromElement
364
+
365
+ function getCurrentlySelectedSmartInputItem() {
366
+ answer = null;
367
+ for (i = 0; ((i < siw.matchCollection.length) && !answer) ; i++) {
368
+ if (siw.matchCollection[i].isSelected)
369
+ answer = i;
370
+ }//
371
+ return answer;
372
+ }//getCurrentlySelectedSmartInputItem
373
+
374
+ function selectSmartInputMatchItem(index) {
375
+ siw.matchCollection[index].isSelected = true;
376
+ }//selectSmartInputMatchItem()
377
+
378
+ function deSelectSmartInputMatchItem(index) {
379
+ siw.matchCollection[index].isSelected = false;
380
+ }//deSelectSmartInputMatchItem()
381
+
382
+ function selectNextSmartInputMatchItem() {
383
+ currentIndex = getCurrentlySelectedSmartInputItem();
384
+ if (currentIndex != null) {
385
+ deSelectSmartInputMatchItem(currentIndex);
386
+ if ((currentIndex + 1) < siw.matchCollection.length)
387
+ selectSmartInputMatchItem(currentIndex + 1);
388
+ else
389
+ selectSmartInputMatchItem(0);
390
+ } else {
391
+ selectSmartInputMatchItem(0);
392
+ }
393
+ modifySmartInputBoxContent(getSmartInputBoxContent());
394
+ }//selectNextSmartInputMatchItem
395
+
396
+ function selectPreviousSmartInputMatchItem() {
397
+ currentIndex = getCurrentlySelectedSmartInputItem();
398
+ if (currentIndex != null) {
399
+ deSelectSmartInputMatchItem(currentIndex);
400
+ if ((currentIndex - 1) >= 0)
401
+ selectSmartInputMatchItem(currentIndex - 1);
402
+ else
403
+ selectSmartInputMatchItem(siw.matchCollection.length - 1);
404
+ } else {
405
+ selectSmartInputMatchItem(siw.matchCollection.length - 1);
406
+ }
407
+ modifySmartInputBoxContent(getSmartInputBoxContent());
408
+ }//selectPreviousSmartInputMatchItem
409
+
410
+ function activateCurrentSmartInputMatch() {
411
+ baseValue = getUserInputBase();
412
+ if ((selIndex = getCurrentlySelectedSmartInputItem()) != null) {
413
+ addedValue = siw.matchCollection[selIndex].cleanValue;
414
+ theString = (baseValue ? baseValue : "") + addedValue + ", ";
415
+ siw.inputBox.value = theString;
416
+ runMatchingLogic(addedValue, true);
417
+ }
418
+ }//activateCurrentSmartInputMatch
419
+
420
+ function smartInputWindow () {
421
+ this.customFloater = false;
422
+ this.floater = document.getElementById("smartInputFloater");
423
+ this.floaterContent = document.getElementById("smartInputFloaterContent");
424
+ this.selectedSmartInputItem = null;
425
+ this.MAX_MATCHES = 15;
426
+ this.isGecko = (navigator.userAgent.indexOf("Gecko/200") != -1);
427
+ this.isSafari = (navigator.userAgent.indexOf("Safari") != -1);
428
+ this.isWinIE = ((navigator.userAgent.indexOf("Win") != -1 ) && (navigator.userAgent.indexOf("MSIE") != -1 ));
429
+ this.showCredit = false;
430
+ }//smartInputWindow Object
431
+
432
+ function registerSmartInputListeners() {
433
+ inputs = document.getElementsByTagName("input");
434
+ texts = document.getElementsByTagName("textarea");
435
+ allinputs = new Array();
436
+ z = 0;
437
+ y = 0;
438
+ while(inputs[z]) {
439
+ allinputs[z] = inputs[z];
440
+ z++;
441
+ }//
442
+ while(texts[y]) {
443
+ allinputs[z] = texts[y];
444
+ z++;
445
+ y++;
446
+ }//
447
+
448
+ for (i=0; i < allinputs.length;i++) {
449
+ if ((c = allinputs[i].className) && (c == "wickEnabled")) {
450
+ allinputs[i].setAttribute("autocomplete","OFF");
451
+ allinputs[i].onfocus = handleFocus;
452
+ allinputs[i].onblur = handleBlur;
453
+ allinputs[i].onkeydown = handleKeyDown;
454
+ allinputs[i].onkeyup = handleKeyPress;
455
+ }
456
+ }//loop thru inputs
457
+ }//registerSmartInputListeners
458
+
459
+ siw = null;
460
+
461
+ if (document.addEventListener) {
462
+ document.addEventListener("keydown", handleKeyDown, false);
463
+ document.addEventListener("keyup", handleKeyPress, false);
464
+ document.addEventListener("mouseup", handleClick, false);
465
+ document.addEventListener("mouseover", handleMouseOver, false);
466
+ } else {
467
+ document.onkeydown = handleKeyDown;
468
+ document.onkeyup = handleKeyPress;
469
+ document.onmouseup = handleClick;
470
+ document.onmouseover = handleMouseOver;
471
+ }
472
+
473
+ registerSmartInputListeners();
474
+
475
+ document.write (
476
+ '<table id="smartInputFloater" class="floater" cellpadding="0" cellspacing="0"><tr><td id="smartInputFloaterContent" nowrap="nowrap">'
477
+ +'<\/td><\/tr><\/table>'
478
+ );
479
+
480
+ //note: instruct users to the fact that no commas should be present in entries.
481
+ //it would make things insanely messy.
482
+ //this is why i'm filtering commas here:
483
+ for (x=0;x<collection.length;x++) {
484
+ collection[x] = collection[x].replace(/\,/gi,'');
485
+ }//
486
+
487
+ collectionIndex = new Array();
488
+
489
+ ds = "";
490
+ function debug(s) {
491
+ ds += ( s + "\n");
492
+ }
wick/wick_sample.html ADDED
@@ -0,0 +1,85 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <html>
2
+ <head><title>WICK Testing Ground</title>
3
+
4
+ <!-- WICK STEP 1: INSERT CSS -->
5
+ <link rel="stylesheet" type="text/css" href="./wick.css" />
6
+
7
+ </head>
8
+ <body>
9
+ <script type="text/javascript" language="JavaScript">
10
+ function checkForm() {
11
+ answer = true;
12
+ if (siw && siw.selectingSomething)
13
+ answer = false;
14
+ return answer;
15
+ }//
16
+ </script>
17
+ <center>
18
+ <p>
19
+ Welcome to the very unpolished WICK testing ground.
20
+ A view source on this document should give you most information you need
21
+ to make WICK work on your site, as i'm still working on more formal documentation
22
+ that'll also include integration suggestions to make this work as fast as possible with
23
+ large amounts of data.
24
+ <br/><br/>
25
+ Be sure to enter multiple e-mail addresses in each field, type a few characters, hit the delete key,
26
+ use your keyboard's up and down arrows, hit return or tab to select an item, use your mouse to hover and click,
27
+ deleting from a current item back into the preceding item, and basically poke around mercilessly.
28
+ <br /><br />
29
+ <div id="wickStatus">
30
+ Loading ... please hold!
31
+ </div>
32
+ <br /><br />
33
+ <form onsubmit="return checkForm()"> <!-- WICK STEP 5: this prevents form from being submitted right-away if a user hits RETURN to select an address -->
34
+ My First Box:<br />
35
+ <input class="wickEnabled" type="text" size="50" /><br />
36
+ My Second Box:<br />
37
+ <textarea class="wickEnabled" cols="50" rows="3" wrap="virtual"></textarea>
38
+ <!-- WICK STEP 4: ADD "wickEnabled" attribute to input
39
+ that'll receive autocompletion using data stored in the "collection" array defined in STEP 2 -->
40
+ <br />
41
+ My Third Box:<br />
42
+ <textarea class="wickEnabled" cols="50" rows="3" wrap="virtual"></textarea>
43
+ <br />&#160;<br />
44
+ My Fourth Box with developer-built floater USING TABLE: SHRINKS TO CONTENTS:<br />
45
+ <div style="position:relative;text-align:left">
46
+ <table id="MYCUSTOMFLOATER" class="myCustomFloater" style="position:absolute;top:50px;left:0;background-color:#cecece;display:none;visibility:hidden">
47
+ <tr><td><!--
48
+ please see: http://chrisholland.blogspot.com/2004/09/geekstuff-css-display-inline-block.html
49
+ to explain why i'm using a table here.
50
+ You could replace the table/tr/td with a DIV, but you'd have to specify it's width and height
51
+ -->
52
+ <div class="myCustomFloaterContent">
53
+ you should never be seeing this
54
+ </div>
55
+ </td></tr>
56
+ </table>
57
+ <textarea class="wickEnabled:MYCUSTOMFLOATER" cols="50" rows="3" wrap="virtual"></textarea>
58
+ </div>
59
+ <br />
60
+ some content lah lah lah
61
+ <br />
62
+ <!--
63
+ My Fourth Box with developer-built floater USING DIV: FIXED WIDTH/HEIGHT:<br />
64
+ <div style="position:relative;text-align:left">
65
+ <div id="MYCUSTOMFLOATER_TWO" class="myCustomFloater" style="position:absolute;top:50px;left:0;background-color:#cecece;width:300px;height:400px;display:none;visibility:hidden">
66
+ <div class="myCustomFloaterContent">
67
+ you should never be seeing this
68
+ </div>
69
+ </div>
70
+ <textarea class="wickEnabled:MYCUSTOMFLOATER_TWO" cols="50" rows="3" wrap="virtual"></textarea>
71
+ </div>
72
+ -->
73
+ <br />
74
+ My Fifth Box:<br />
75
+ <input class="wickEnabled" type="text" size="50" /><br />
76
+ </form>
77
+ </p>
78
+ </center>
79
+ <script type="text/javascript" language="JavaScript" src="./sample_data.js.php"></script> <!-- WICK STEP 2: DEFINE COLLECTION ARRAY THAT HOLDS DATA -->
80
+ <script type="text/javascript" language="JavaScript" src="./wick.js"></script> <!-- WICK STEP 3: INSERT WICK LOGIC -->
81
+ <script>
82
+ document.getElementById("wickStatus").innerHTML = '<a target="_blank" href="./sample_data.js.php">Loaded <b>' + collection.length + '</b> Sample Addresses</a>';
83
+ </script>
84
+ </body>
85
+ </html>