mirror of
https://github.com/e107inc/e107.git
synced 2025-08-06 14:46:56 +02:00
Little experiment with PM - not fully functional, but you get the idea.
This commit is contained in:
@@ -11,14 +11,24 @@
|
|||||||
| GNU General Public License (http://gnu.org).
|
| GNU General Public License (http://gnu.org).
|
||||||
|
|
|
|
||||||
| $Source: /cvs_backup/e107_0.8/e107_plugins/pm/pm.php,v $
|
| $Source: /cvs_backup/e107_0.8/e107_plugins/pm/pm.php,v $
|
||||||
| $Revision: 1.9 $
|
| $Revision: 1.10 $
|
||||||
| $Date: 2009-02-02 17:42:59 $
|
| $Date: 2009-07-21 14:44:11 $
|
||||||
| $Author: e107steved $
|
| $Author: e107coders $
|
||||||
+----------------------------------------------------------------------------+
|
+----------------------------------------------------------------------------+
|
||||||
*/
|
*/
|
||||||
|
|
||||||
$retrieve_prefs[] = 'pm_prefs';
|
$retrieve_prefs[] = 'pm_prefs';
|
||||||
require_once("../../class2.php");
|
require_once("../../class2.php");
|
||||||
|
|
||||||
|
if($_POST['keyword'])
|
||||||
|
{
|
||||||
|
pm_user_lookup();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
require_once(e_PLUGIN."pm/pm_class.php");
|
require_once(e_PLUGIN."pm/pm_class.php");
|
||||||
require_once(e_PLUGIN."pm/pm_func.php");
|
require_once(e_PLUGIN."pm/pm_func.php");
|
||||||
$lan_file = e_PLUGIN."pm/languages/".e_LANGUAGE.".php";
|
$lan_file = e_PLUGIN."pm/languages/".e_LANGUAGE.".php";
|
||||||
@@ -129,6 +139,12 @@ if("get" == $action)
|
|||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$eplug_js[] = e_FILE."jslib/prototype/prototype.js";
|
||||||
|
$eplug_js[] = e_PLUGIN."pm/textboxlist.js";
|
||||||
|
$eplug_js[] = e_PLUGIN."pm/test.js";
|
||||||
|
$eplug_css[] = e_PLUGIN."pm/test.css";
|
||||||
|
// test.
|
||||||
|
|
||||||
require_once(HEADERF);
|
require_once(HEADERF);
|
||||||
|
|
||||||
if(isset($_POST['postpm']))
|
if(isset($_POST['postpm']))
|
||||||
@@ -436,5 +452,53 @@ function post_pm()
|
|||||||
$_POST['from_id'] = USERID;
|
$_POST['from_id'] = USERID;
|
||||||
return $msg.$pm->add($_POST);
|
return $msg.$pm->add($_POST);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function pm_user_lookup()
|
||||||
|
{
|
||||||
|
global $sql;
|
||||||
|
|
||||||
|
|
||||||
|
$query = "SELECT * FROM #user WHERE user_name REGEXP '^".$_POST['keyword']."' ";
|
||||||
|
if($sql -> db_Select_gen($query))
|
||||||
|
{
|
||||||
|
echo "[";
|
||||||
|
while($row = $sql-> db_Fetch())
|
||||||
|
{
|
||||||
|
$u[] = "{\"caption\":\"".$row['user_name']."\",\"value\":".$row['user_id']."}";
|
||||||
|
}
|
||||||
|
|
||||||
|
echo implode(",",$u);
|
||||||
|
echo "]";
|
||||||
|
|
||||||
|
// echo "[{\"caption\":\"Manuel Mujica Lainez\",\"value\":4},{\"caption\":\"Gustavo Nielsen\",\"value\":3},{\"caption\":\"Silvina Ocampo\",\"value\":3},{\"caption\":\"Victoria Ocampo\", \"value\":3},{\"caption\":\"Hector German Oesterheld\", \"value\":3},{\"caption\":\"Olga Orozco\", \"value\":3},{\"caption\":\"Juan L. Ortiz\", \"value\":3},{\"caption\":\"Alicia Partnoy\", \"value\":3},{\"caption\":\"Roberto Payro\", \"value\":3},{\"caption\":\"Ricardo Piglia\", \"value\":3},{\"caption\":\"Felipe Pigna\", \"value\":3},{\"caption\":\"Alejandra Pizarnik\", \"value\":3},{\"caption\":\"Antonio Porchia\", \"value\":3},{\"caption\":\"Juan Carlos Portantiero\", \"value\":3},{\"caption\":\"Manuel Puig\", \"value\":3},{\"caption\":\"Andres Rivera\", \"value\":3},{\"caption\":\"Mario Rodriguez Cobos\", \"value\":3},{\"caption\":\"Arturo Andres Roig\", \"value\":3},{\"caption\":\"Ricardo Rojas\", \"value\":3}]";
|
||||||
|
}
|
||||||
|
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
function headerjs()
|
||||||
|
{
|
||||||
|
return " <script type='text/javascript'>
|
||||||
|
document.observe('dom:loaded', function() {
|
||||||
|
|
||||||
|
|
||||||
|
// init
|
||||||
|
tlist2 = new FacebookList('facebook-demo', 'facebook-auto',{fetchFile:'".e_SELF."'});
|
||||||
|
|
||||||
|
// fetch and feed
|
||||||
|
new Ajax.Request('".e_SELF."', {
|
||||||
|
onSuccess: function(transport) {
|
||||||
|
transport.responseText.evalJSON(true).each(function(t){tlist2.autoFeed(t)});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
?>
|
?>
|
@@ -11,9 +11,9 @@
|
|||||||
| GNU General Public License (http://gnu.org).
|
| GNU General Public License (http://gnu.org).
|
||||||
|
|
|
|
||||||
| $Source: /cvs_backup/e107_0.8/e107_plugins/pm/pm_shortcodes.php,v $
|
| $Source: /cvs_backup/e107_0.8/e107_plugins/pm/pm_shortcodes.php,v $
|
||||||
| $Revision: 1.9 $
|
| $Revision: 1.10 $
|
||||||
| $Date: 2009-02-02 17:43:00 $
|
| $Date: 2009-07-21 14:44:13 $
|
||||||
| $Author: e107steved $
|
| $Author: e107coders $
|
||||||
+----------------------------------------------------------------------------+
|
+----------------------------------------------------------------------------+
|
||||||
*/
|
*/
|
||||||
if (!defined('e107_INIT')) { exit; }
|
if (!defined('e107_INIT')) { exit; }
|
||||||
@@ -31,6 +31,27 @@ if($pm_info['from_name'])
|
|||||||
require_once(e_HANDLER."user_select_class.php");
|
require_once(e_HANDLER."user_select_class.php");
|
||||||
$us = new user_select;
|
$us = new user_select;
|
||||||
$type = ($pm_prefs['dropdown'] == TRUE ? 'list' : 'popup');
|
$type = ($pm_prefs['dropdown'] == TRUE ? 'list' : 'popup');
|
||||||
|
|
||||||
|
|
||||||
|
$ret = "<ol>
|
||||||
|
|
||||||
|
<li id=\"facebook-list\" class=\"input-text\">
|
||||||
|
<input type=\"text\" value=\"\" id=\"facebook-demo\" />
|
||||||
|
<div id=\"facebook-auto\">
|
||||||
|
|
||||||
|
<div class=\"default\">Type the name of a user</div>
|
||||||
|
<ul class=\"feed\">
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</ol>";
|
||||||
|
|
||||||
|
return $ret;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if(check_class($pm_prefs['multi_class']))
|
if(check_class($pm_prefs['multi_class']))
|
||||||
{
|
{
|
||||||
$ret = $us->select_form($type, 'textarea.pm_to');
|
$ret = $us->select_form($type, 'textarea.pm_to');
|
||||||
|
40
e107_plugins/pm/test.css
Normal file
40
e107_plugins/pm/test.css
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
/* TextboxList sample CSS */
|
||||||
|
ul.holder { margin: 0; border: 1px solid #999; overflow: hidden; height: auto !important; height: 1%; padding: 4px 5px 0; }
|
||||||
|
*:first-child+html ul.holder { padding-bottom: 2px; } * html ul.holder { padding-bottom: 2px; } /* ie7 and below */
|
||||||
|
ul.holder li { float: left; list-style-type: none; margin: 0 5px 4px 0; }
|
||||||
|
ul.holder li.bit-box, ul.holder li.bit-input input { font: 11px "Lucida Grande", "Verdana"; }
|
||||||
|
ul.holder li.bit-box { -moz-border-radius: 6px; -webkit-border-radius: 6px; border-radius: 6px; border: 1px solid #CAD8F3; background: #DEE7F8; padding: 1px 5px 2px; }
|
||||||
|
ul.holder li.bit-box-focus { border-color: #598BEC; background: #598BEC; color: #fff; }
|
||||||
|
ul.holder li.bit-input input { width: 150px; margin: 0; border: none; outline: 0; padding: 3px 0 2px; } /* no left/right padding here please */
|
||||||
|
ul.holder li.bit-input input.smallinput { width: 20px; }
|
||||||
|
|
||||||
|
/* Facebook demo CSS */
|
||||||
|
form, #add { border: 1px solid #999; width: 550px; margin: 50px; padding: 20px 30px 10px; }
|
||||||
|
form ol { font: 11px "Lucida Grande", "Verdana"; margin: 0; padding: 0; }
|
||||||
|
form ol li.input-text { margin-bottom: 10px; list-style-type: none; border-bottom: 1px dotted #999; padding-bottom: 10px; }
|
||||||
|
form ol li.input-text label { font-weight: bold; cursor: pointer; display: block; font-size: 13px; margin-bottom: 10px; }
|
||||||
|
form ol li.input-text input { width: 500px; padding: 5px 5px 6px; font: 11px "Lucida Grande", "Verdana"; border: 1px solid #999; }
|
||||||
|
form ul.holder { width: 500px; }
|
||||||
|
#facebook-list ul.holder li.bit-box, #apple-list ul.holder li.bit-box { padding-right: 15px; position: relative; }
|
||||||
|
#apple-list ul.holder li.bit-input { margin: 0; }
|
||||||
|
#apple-list ul.holder li.bit-input input.smallinput { width: 5px; }
|
||||||
|
ul.holder li.bit-hover { background: #BBCEF1; border: 1px solid #6D95E0; }
|
||||||
|
ul.holder li.bit-box-focus { border-color: #598BEC; background: #598BEC; color: #fff; }
|
||||||
|
ul.holder li.bit-box a.closebutton { position: absolute; right: 4px; top: 5px; display: block; width: 7px; height: 7px; font-size: 1px; background: url('images/close.gif'); }
|
||||||
|
ul.holder li.bit-box a.closebutton:hover { background-position: 7px; }
|
||||||
|
ul.holder li.bit-box-focus a.closebutton, ul.holder li.bit-box-focus a.closebutton:hover { background-position: bottom; }
|
||||||
|
|
||||||
|
/* Autocompleter */
|
||||||
|
|
||||||
|
#facebook-auto { display: none; position: absolute; width: 512px; background: #eee; }
|
||||||
|
#facebook-auto .default { padding: 5px 7px; border: 1px solid #ccc; border-width: 0 1px 1px; }
|
||||||
|
#facebook-auto ul { display: none; margin: 0; padding: 0; overflow: auto; }
|
||||||
|
#facebook-auto ul li { padding: 5px 12px; z-index: 1000; cursor: pointer; margin: 0; list-style-type: none; border: 1px solid #ccc; border-width: 0 1px 1px; font: 11px "Lucida Grande", "Verdana"; }
|
||||||
|
#facebook-auto ul li em { font-weight: bold; font-style: normal; background: #ccc; }
|
||||||
|
#facebook-auto ul li.auto-focus { background: #4173CC; color: #fff; }
|
||||||
|
#facebook-auto ul li.auto-focus em { background: none; }
|
||||||
|
|
||||||
|
#demo ul.holder li.bit-input input { padding: 2px 0 1px; border: 1px solid #999; }
|
||||||
|
#add a { color: #666; }
|
||||||
|
#add-test { width: 100px; padding: 2px; }
|
||||||
|
#button_container { margin-left: 70px; margin-bottom: 30px;}
|
209
e107_plugins/pm/test.js
Normal file
209
e107_plugins/pm/test.js
Normal file
@@ -0,0 +1,209 @@
|
|||||||
|
/*
|
||||||
|
Proto!MultiSelect 0.2
|
||||||
|
- Prototype version required: 6.0
|
||||||
|
|
||||||
|
Credits:
|
||||||
|
- Idea: Facebook
|
||||||
|
- Guillermo Rauch: Original MooTools script
|
||||||
|
- Ran Grushkowsky/InteRiders Inc. : Porting into Prototype and further development
|
||||||
|
|
||||||
|
Changelog:
|
||||||
|
- 0.1: translation of MooTools script
|
||||||
|
- 0.2: renamed from Proto!TextboxList to Proto!MultiSelect, added new features/bug fixes
|
||||||
|
added feature: support to fetch list on-the-fly using AJAX Credit: Cheeseroll
|
||||||
|
added feature: support for value/caption
|
||||||
|
added feature: maximum results to display, when greater displays a scrollbar Credit: Marcel
|
||||||
|
added feature: filter by the beginning of word only or everywhere in the word Credit: Kiliman
|
||||||
|
added feature: shows hand cursor when going over options
|
||||||
|
bug fix: the click event stopped working
|
||||||
|
bug fix: the cursor does not 'travel' when going up/down the list Credit: Marcel
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Copyright: InteRiders <http://interiders.com/> - Distributed under MIT - Keep this message! */
|
||||||
|
|
||||||
|
var FacebookList = Class.create(TextboxList, {
|
||||||
|
|
||||||
|
loptions: $H({
|
||||||
|
autocomplete: {
|
||||||
|
'opacity': 0.8,
|
||||||
|
'maxresults': 10,
|
||||||
|
'minchars': 1
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
|
||||||
|
initialize: function($super,element, autoholder, options, func) {
|
||||||
|
$super(element, options);
|
||||||
|
this.data = [];
|
||||||
|
this.autoholder = $(autoholder).setOpacity(this.loptions.get('autocomplete').opacity);
|
||||||
|
this.autoholder.observe('mouseover',function() {this.curOn = true;}.bind(this)).observe('mouseout',function() {this.curOn = false;}.bind(this));
|
||||||
|
this.autoresults = this.autoholder.select('ul').first();
|
||||||
|
var children = this.autoresults.select('li');
|
||||||
|
children.each(function(el) { this.add({value:el.readAttribute('value'),caption:el.innerHTML}); }, this);
|
||||||
|
},
|
||||||
|
|
||||||
|
autoShow: function(search) {
|
||||||
|
this.autoholder.setStyle({'display': 'block'});
|
||||||
|
this.autoholder.descendants().each(function(e) { e.hide() });
|
||||||
|
if(! search || ! search.strip() || (! search.length || search.length < this.loptions.get('autocomplete').minchars))
|
||||||
|
{
|
||||||
|
this.autoholder.select('.default').first().setStyle({'display': 'block'});
|
||||||
|
this.resultsshown = false;
|
||||||
|
} else {
|
||||||
|
this.resultsshown = true;
|
||||||
|
this.autoresults.setStyle({'display': 'block'}).update('');
|
||||||
|
if (this.options.get('wordMatch'))
|
||||||
|
var regexp = new RegExp("(^|\\s)"+search,'i')
|
||||||
|
else
|
||||||
|
var regexp = new RegExp(search,'i')
|
||||||
|
var count = 0;
|
||||||
|
this.data.filter(function(str) { return str ? regexp.test(str.evalJSON(true).caption) : false; }).each(function(result, ti) {
|
||||||
|
count++;
|
||||||
|
if(ti >= this.loptions.get('autocomplete').maxresults) return;
|
||||||
|
var that = this;
|
||||||
|
var el = new Element('li');
|
||||||
|
el.observe('click',function(e) {
|
||||||
|
e.stop();
|
||||||
|
that.autoAdd(this);
|
||||||
|
}).observe('mouseover',function() {
|
||||||
|
that.autoFocus(this);
|
||||||
|
}).update(this.autoHighlight(result.evalJSON(true).caption, search));
|
||||||
|
this.autoresults.insert(el);
|
||||||
|
el.cacheData('result', result.evalJSON(true));
|
||||||
|
if(ti == 0) this.autoFocus(el);
|
||||||
|
}, this);
|
||||||
|
}
|
||||||
|
if (count > this.options.get('results'))
|
||||||
|
this.autoresults.setStyle({'height': (this.options.get('results')*24)+'px'});
|
||||||
|
else
|
||||||
|
this.autoresults.setStyle({'height': (count?(count*24):0)+'px'});
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
autoHighlight: function(html, highlight) {
|
||||||
|
return html.gsub(new RegExp(highlight,'i'), function(match) {
|
||||||
|
return '<em>' + match[0] + '</em>';
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
autoHide: function() {
|
||||||
|
this.resultsshown = false;
|
||||||
|
this.autoholder.hide();
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
autoFocus: function(el) {
|
||||||
|
if(! el) return;
|
||||||
|
if(this.autocurrent) this.autocurrent.removeClassName('auto-focus');
|
||||||
|
this.autocurrent = el.addClassName('auto-focus');
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
autoMove: function(direction) {
|
||||||
|
if(!this.resultsshown) return;
|
||||||
|
this.autoFocus(this.autocurrent[(direction == 'up' ? 'previous' : 'next')]());
|
||||||
|
this.autoresults.scrollTop = this.autocurrent.positionedOffset()[1]-this.autocurrent.getHeight();
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
autoFeed: function(text) {
|
||||||
|
if (this.data.indexOf(Object.toJSON(text)) == -1)
|
||||||
|
this.data.push(Object.toJSON(text));
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
autoAdd: function(el) {
|
||||||
|
if(!el || ! el.retrieveData('result')) return;
|
||||||
|
this.add(el.retrieveData('result'));
|
||||||
|
delete this.data[this.data.indexOf(Object.toJSON(el.retrieveData('result')))];
|
||||||
|
this.autoHide();
|
||||||
|
var input = this.lastinput || this.current.retrieveData('input');
|
||||||
|
input.clear().focus();
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
createInput: function($super,options) {
|
||||||
|
var li = $super(options);
|
||||||
|
var input = li.retrieveData('input');
|
||||||
|
input.observe('keydown', function(e) {
|
||||||
|
this.dosearch = false;
|
||||||
|
switch(e.keyCode) {
|
||||||
|
case Event.KEY_UP: e.stop(); return this.autoMove('up');
|
||||||
|
case Event.KEY_DOWN: e.stop(); return this.autoMove('down');
|
||||||
|
case Event.KEY_RETURN:
|
||||||
|
e.stop();
|
||||||
|
if(! this.autocurrent) break;
|
||||||
|
this.autoAdd(this.autocurrent);
|
||||||
|
this.autocurrent = false;
|
||||||
|
this.autoenter = true;
|
||||||
|
break;
|
||||||
|
case Event.KEY_ESC:
|
||||||
|
this.autoHide();
|
||||||
|
if(this.current && this.current.retrieveData('input'))
|
||||||
|
this.current.retrieveData('input').clear();
|
||||||
|
break;
|
||||||
|
default: this.dosearch = true;
|
||||||
|
}
|
||||||
|
}.bind(this));
|
||||||
|
input.observe('keyup',function(e) {
|
||||||
|
|
||||||
|
switch(e.keyCode) {
|
||||||
|
case Event.KEY_UP:
|
||||||
|
case Event.KEY_DOWN:
|
||||||
|
case Event.KEY_RETURN:
|
||||||
|
case Event.KEY_ESC:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (!Object.isUndefined(this.options.get('fetchFile'))) {
|
||||||
|
new Ajax.Request(this.options.get('fetchFile'), {
|
||||||
|
parameters: {keyword: input.value},
|
||||||
|
onSuccess: function(transport) {
|
||||||
|
transport.responseText.evalJSON(true).each(function(t){this.autoFeed(t)}.bind(this));
|
||||||
|
this.autoShow(input.value);
|
||||||
|
}.bind(this)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if(this.dosearch) this.autoShow(input.value);
|
||||||
|
}
|
||||||
|
}.bind(this));
|
||||||
|
input.observe(Prototype.Browser.IE ? 'keydown' : 'keypress', function(e) {
|
||||||
|
if(this.autoenter) e.stop();
|
||||||
|
this.autoenter = false;
|
||||||
|
}.bind(this));
|
||||||
|
return li;
|
||||||
|
},
|
||||||
|
|
||||||
|
createBox: function($super,text, options) {
|
||||||
|
var li = $super(text, options);
|
||||||
|
li.observe('mouseover',function() {
|
||||||
|
this.addClassName('bit-hover');
|
||||||
|
}).observe('mouseout',function() {
|
||||||
|
this.removeClassName('bit-hover')
|
||||||
|
});
|
||||||
|
var a = new Element('a', {
|
||||||
|
'href': '#',
|
||||||
|
'class': 'closebutton'
|
||||||
|
}
|
||||||
|
);
|
||||||
|
a.observe('click',function(e) {
|
||||||
|
e.stop();
|
||||||
|
if(! this.current) this.focus(this.maininput);
|
||||||
|
this.dispose(li);
|
||||||
|
}.bind(this));
|
||||||
|
li.insert(a).cacheData('text', Object.toJSON(text));
|
||||||
|
return li;
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
Element.addMethods({
|
||||||
|
onBoxDispose: function(item,obj) { obj.autoFeed(item.retrieveData('text').evalJSON(true)); },
|
||||||
|
onInputFocus: function(el,obj) { obj.autoShow(); },
|
||||||
|
onInputBlur: function(el,obj) {
|
||||||
|
obj.lastinput = el;
|
||||||
|
if(!obj.curOn) {
|
||||||
|
obj.blurhide = obj.autoHide.bind(obj).delay(0.1);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
filter:function(D,E){var C=[];for(var B=0,A=this.length;B<A;B++){if(D.call(E,this[B],B,this)){C.push(this[B]);}}return C;}
|
||||||
|
});
|
244
e107_plugins/pm/textboxlist.js
Normal file
244
e107_plugins/pm/textboxlist.js
Normal file
@@ -0,0 +1,244 @@
|
|||||||
|
/*
|
||||||
|
Proto!MultiSelect 0.2
|
||||||
|
- Prototype version required: 6.0
|
||||||
|
|
||||||
|
Credits:
|
||||||
|
- Idea: Facebook + Apple Mail
|
||||||
|
- Caret position method: Diego Perini <http://javascript.nwbox.com/cursor_position/cursor.js>
|
||||||
|
- Guillermo Rauch: Original MooTools script
|
||||||
|
- Ran Grushkowsky/InteRiders Inc. : Porting into Prototype and further development
|
||||||
|
|
||||||
|
Changelog:
|
||||||
|
- 0.1: translation of MooTools script
|
||||||
|
- 0.2: renamed from Proto!TextboxList to Proto!MultiSelect, added new features/bug fixes
|
||||||
|
added feature: support to fetch list on-the-fly using AJAX Credit: Cheeseroll
|
||||||
|
added feature: support for value/caption
|
||||||
|
added feature: maximum results to display, when greater displays a scrollbar Credit: Marcel
|
||||||
|
added feature: filter by the beginning of word only or everywhere in the word Credit: Kiliman
|
||||||
|
added feature: shows hand cursor when going over options
|
||||||
|
bug fix: the click event stopped working
|
||||||
|
bug fix: the cursor does not 'travel' when going up/down the list Credit: Marcel
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Copyright: InteRiders <http://interiders.com/> - Distributed under MIT - Keep this message! */
|
||||||
|
|
||||||
|
var ResizableTextbox = Class.create({
|
||||||
|
|
||||||
|
options: $H({
|
||||||
|
min: 5,
|
||||||
|
max: 500,
|
||||||
|
step: 7
|
||||||
|
}),
|
||||||
|
|
||||||
|
initialize: function(element, options) {
|
||||||
|
var that = this;
|
||||||
|
this.options.update(options);
|
||||||
|
this.el = $(element);
|
||||||
|
this.width = this.el.offsetWidth;
|
||||||
|
this.el.observe(
|
||||||
|
'keyup', function() {
|
||||||
|
var newsize = that.options.get('step') * $F(this).length;
|
||||||
|
if(newsize <= that.options.get('min')) newsize = that.width;
|
||||||
|
if(! ($F(this).length == this.retrieveData('rt-value') || newsize <= that.options.min || newsize >= that.options.max))
|
||||||
|
this.setStyle({'width': newsize});
|
||||||
|
}).observe('keydown', function() {
|
||||||
|
this.cacheData('rt-value', $F(this).length);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var TextboxList = Class.create({
|
||||||
|
|
||||||
|
options: $H({/*
|
||||||
|
onFocus: $empty,
|
||||||
|
onBlur: $empty,
|
||||||
|
onInputFocus: $empty,
|
||||||
|
onInputBlur: $empty,
|
||||||
|
onBoxFocus: $empty,
|
||||||
|
onBoxBlur: $empty,
|
||||||
|
onBoxDispose: $empty,*/
|
||||||
|
resizable: {},
|
||||||
|
className: 'bit',
|
||||||
|
separator: '###',
|
||||||
|
extrainputs: true,
|
||||||
|
startinput: true,
|
||||||
|
hideempty: true,
|
||||||
|
fetchFile: undefined,
|
||||||
|
results: 10,
|
||||||
|
wordMatch: false
|
||||||
|
}),
|
||||||
|
|
||||||
|
initialize: function(element, options) {
|
||||||
|
this.options.update(options);
|
||||||
|
this.element = $(element).hide();
|
||||||
|
this.bits = new Hash();
|
||||||
|
this.events = new Hash();
|
||||||
|
this.count = 0;
|
||||||
|
this.current = false;
|
||||||
|
this.maininput = this.createInput({'class': 'maininput'});
|
||||||
|
this.holder = new Element('ul', {
|
||||||
|
'class': 'holder'
|
||||||
|
}).insert(this.maininput);
|
||||||
|
this.element.insert({'before':this.holder});
|
||||||
|
this.holder.observe('click', function(event){
|
||||||
|
event.stop();
|
||||||
|
if(this.maininput != this.current) this.focus(this.maininput);
|
||||||
|
}.bind(this));
|
||||||
|
this.makeResizable(this.maininput);
|
||||||
|
this.setEvents();
|
||||||
|
},
|
||||||
|
|
||||||
|
setEvents: function() {
|
||||||
|
document.observe(Prototype.Browser.IE ? 'keydown' : 'keypress', function(e) {
|
||||||
|
if(! this.current) return;
|
||||||
|
if(this.current.retrieveData('type') == 'box' && e.keyCode == Event.KEY_BACKSPACE) e.stop();
|
||||||
|
}.bind(this));
|
||||||
|
|
||||||
|
document.observe(
|
||||||
|
'keyup', function(e) {
|
||||||
|
e.stop();
|
||||||
|
if(! this.current) return;
|
||||||
|
switch(e.keyCode){
|
||||||
|
case Event.KEY_LEFT: return this.move('left');
|
||||||
|
case Event.KEY_RIGHT: return this.move('right');
|
||||||
|
case Event.KEY_DELETE:
|
||||||
|
case Event.KEY_BACKSPACE: return this.moveDispose();
|
||||||
|
}
|
||||||
|
}.bind(this)).observe(
|
||||||
|
'click', function() { document.fire('blur'); }.bindAsEventListener(this)
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
update: function() {
|
||||||
|
this.element.value = this.bits.values().join(this.options.get('separator'));
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
add: function(text, html) {
|
||||||
|
var id = this.options.get('className') + '-' + this.count++;
|
||||||
|
var el = this.createBox($pick(html, text), {'id': id});
|
||||||
|
(this.current || this.maininput).insert({'before':el});
|
||||||
|
el.observe('click', function(e) {
|
||||||
|
e.stop();
|
||||||
|
this.focus(el);
|
||||||
|
}.bind(this));
|
||||||
|
this.bits.set(id, text.value);
|
||||||
|
if(this.options.get('extrainputs') && (this.options.get('startinput') || el.previous())) this.addSmallInput(el,'before');
|
||||||
|
return el;
|
||||||
|
},
|
||||||
|
|
||||||
|
addSmallInput: function(el, where) {
|
||||||
|
var input = this.createInput({'class': 'smallinput'});
|
||||||
|
el.insert({}[where] = input);
|
||||||
|
input.cacheData('small', true);
|
||||||
|
this.makeResizable(input);
|
||||||
|
if(this.options.get('hideempty')) input.hide();
|
||||||
|
return input;
|
||||||
|
},
|
||||||
|
|
||||||
|
dispose: function(el) {
|
||||||
|
this.bits.unset(el.id);
|
||||||
|
if(el.previous() && el.previous().retrieveData('small')) el.previous().remove();
|
||||||
|
if(this.current == el) this.focus(el.next());
|
||||||
|
if(el.retrieveData('type') == 'box') el.onBoxDispose(this);
|
||||||
|
el.remove();
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
focus: function(el, nofocus) {
|
||||||
|
if(! this.current) el.fire('focus');
|
||||||
|
else if(this.current == el) return this;
|
||||||
|
this.blur();
|
||||||
|
el.addClassName(this.options.get('className') + '-' + el.retrieveData('type') + '-focus');
|
||||||
|
if(el.retrieveData('small')) el.setStyle({'display': 'block'});
|
||||||
|
if(el.retrieveData('type') == 'input') {
|
||||||
|
el.onInputFocus(this);
|
||||||
|
if(! nofocus) this.callEvent(el.retrieveData('input'), 'focus');
|
||||||
|
}
|
||||||
|
else el.fire('onBoxFocus');
|
||||||
|
this.current = el;
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
blur: function(noblur) {
|
||||||
|
if(! this.current) return this;
|
||||||
|
if(this.current.retrieveData('type') == 'input') {
|
||||||
|
var input = this.current.retrieveData('input');
|
||||||
|
if(! noblur) this.callEvent(input, 'blur');
|
||||||
|
input.onInputBlur(this);
|
||||||
|
}
|
||||||
|
else this.current.fire('onBoxBlur');
|
||||||
|
if(this.current.retrieveData('small') && ! input.get('value') && this.options.get('hideempty'))
|
||||||
|
this.current.hide();
|
||||||
|
this.current.removeClassName(this.options.get('className') + '-' + this.current.retrieveData('type') + '-focus');
|
||||||
|
this.current = false;
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
createBox: function(text, options) {
|
||||||
|
return new Element('li', options).addClassName(this.options.get('className') + '-box').update(text.caption).cacheData('type', 'box');
|
||||||
|
},
|
||||||
|
|
||||||
|
createInput: function(options) {
|
||||||
|
var li = new Element('li', {'class': this.options.get('className') + '-input'});
|
||||||
|
var el = new Element('input', Object.extend(options,{'type': 'text'}));
|
||||||
|
el.observe('click', function(e) { e.stop(); }).observe('focus', function(e) { if(! this.isSelfEvent('focus')) this.focus(li, true); }.bind(this)).observe('blur', function() { if(! this.isSelfEvent('blur')) this.blur(true); }.bind(this)).observe('keydown', function(e) { this.cacheData('lastvalue', this.value).cacheData('lastcaret', this.getCaretPosition()); });
|
||||||
|
var tmp = li.cacheData('type', 'input').cacheData('input', el).insert(el);
|
||||||
|
return tmp;
|
||||||
|
},
|
||||||
|
|
||||||
|
callEvent: function(el, type) {
|
||||||
|
this.events.set(type, el);
|
||||||
|
el[type]();
|
||||||
|
},
|
||||||
|
|
||||||
|
isSelfEvent: function(type) {
|
||||||
|
return (this.events.get(type)) ? !! this.events.unset(type) : false;
|
||||||
|
},
|
||||||
|
|
||||||
|
makeResizable: function(li) {
|
||||||
|
var el = li.retrieveData('input');
|
||||||
|
el.cacheData('resizable', new ResizableTextbox(el, Object.extend(this.options.get('resizable'),{min: el.offsetWidth, max: (this.element.getWidth()?this.element.getWidth():0)})));
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
checkInput: function() {
|
||||||
|
var input = this.current.retrieveData('input');
|
||||||
|
return (! input.retrieveData('lastvalue') || (input.getCaretPosition() === 0 && input.retrieveData('lastcaret') === 0));
|
||||||
|
},
|
||||||
|
|
||||||
|
move: function(direction) {
|
||||||
|
var el = this.current[(direction == 'left' ? 'previous' : 'next')]();
|
||||||
|
if(el && (! this.current.retrieveData('input') || ((this.checkInput() || direction == 'right')))) this.focus(el);
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
moveDispose: function() {
|
||||||
|
if(this.current.retrieveData('type') == 'box') return this.dispose(this.current);
|
||||||
|
if(this.checkInput() && this.bits.keys().length && this.current.previous()) return this.focus(this.current.previous());
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
//helper functions
|
||||||
|
Element.addMethods({
|
||||||
|
getCaretPosition: function() {
|
||||||
|
if (this.createTextRange) {
|
||||||
|
var r = document.selection.createRange().duplicate();
|
||||||
|
r.moveEnd('character', this.value.length);
|
||||||
|
if (r.text === '') return this.value.length;
|
||||||
|
return this.value.lastIndexOf(r.text);
|
||||||
|
} else return this.selectionStart;
|
||||||
|
},
|
||||||
|
cacheData: function(element, key, value) {
|
||||||
|
if (Object.isUndefined(this[$(element).identify()]) || !Object.isHash(this[$(element).identify()]))
|
||||||
|
this[$(element).identify()] = $H();
|
||||||
|
this[$(element).identify()].set(key,value);
|
||||||
|
return element;
|
||||||
|
},
|
||||||
|
retrieveData: function(element,key) {
|
||||||
|
return this[$(element).identify()].get(key);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function $pick(){for(var B=0,A=arguments.length;B<A;B++){if(!Object.isUndefined(arguments[B])){return arguments[B];}}return null;}
|
Reference in New Issue
Block a user