diff --git a/etemplate/inc/class.etemplate_widget_itempicker.inc.php b/etemplate/inc/class.etemplate_widget_itempicker.inc.php new file mode 100755 index 0000000000..5173d2cab6 --- /dev/null +++ b/etemplate/inc/class.etemplate_widget_itempicker.inc.php @@ -0,0 +1,33 @@ + + * @author Christian Binder + * @copyright 2002-11 by RalfBecker@outdoor-training.de + * @copyright 2012 by Christian Binder + * @version $Id: class.etemplate_widget_itempicker.inc.php 36221 2011-08-20 10:27:38Z jaytraxx $ + */ + +/** + * eTemplate itempicker widget + */ +class etemplate_widget_itempicker extends etemplate_widget +{ + /** + * Constructor + * + * @param string|XMLReader $xml string with xml or XMLReader positioned on the element to construct + * @throws egw_exception_wrong_parameter + */ + public function __construct($xml) + { + parent::__construct($xml); + } +} + +etemplate_widget::registerWidget('etemplate_widget_itempicker', array('itempicker')); \ No newline at end of file diff --git a/etemplate/js/et2_widget_itempicker.js b/etemplate/js/et2_widget_itempicker.js new file mode 100755 index 0000000000..d2d7a22125 --- /dev/null +++ b/etemplate/js/et2_widget_itempicker.js @@ -0,0 +1,178 @@ +/** + * eGroupWare eTemplate2 - JS Itempicker object + * derived from et2_link_entry widget @copyright 2011 Nathan Gray + * + * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License + * @package etemplate + * @subpackage api + * @link http://www.egroupware.org + * @author Christian Binder + * @author Nathan Gray + * @copyright 2012 Christian Binder + * @copyright 2011 Nathan Gray + * @version $Id: et2_widget_itempicker.js 38623 2012-03-26 23:27:53Z jaytraxx $ + */ + +"use strict"; + +/*egw:uses + jquery.jquery; + et2_core_inputWidget; + et2_core_valueWidget; +*/ + +/** + * Class which implements the "itempicker" XET-Tag + */ +var et2_itempicker = et2_inputWidget.extend({ + + attributes: { + "value": { + "type": "any", + "default": {} + }, + "application": { + "name": "Application", + "type": "string", + "default": "", + "description": "Limit to the listed application or applications (comma seperated)" + }, + "blur": { + "name": "Placeholder", + "type": "string", + "default": et2_no_init, + "description": "This text get displayed if an input-field is empty and does not have the input-focus (blur). It can be used to show a default value or a kind of help-text." + }, + "query": { + "name": "Query callback", + "type": "any", + "default": false, + "description": "Callback before query to server. Must return true, or false to abort query." + }, + "select": { + "name": "Select callback", + "type": "any", + "default": false, + "description": "Callback when user selects an option. Must return true, or false to abort normal action." + }, + }, + + legacyOptions: ["application"], + search_timeout: 200, //ms after change to send query + minimum_characters: 2, // Don't send query unless there's at least this many chars + + init: function() { + this._super.apply(this, arguments); + + this.div = null; + this.left = null; + this.right = null; + this.app_select = null; + this.search = null; + this.itemlist = null; + + this.createInputWidget(); + }, + + createInputWidget: function() { + + this.div = $j(document.createElement("div")); + this.left = $j(document.createElement("div")); + this.right = $j(document.createElement("div")); + this.app_select = $j(document.createElement("ul")); + this.search = $j(document.createElement("div")); + this.itemlist = $j(document.createElement("div")); + + // Container elements + this.div.addClass("et2_itempicker"); + this.left.addClass("et2_itempicker_left"); + this.right.addClass("et2_itempicker_right"); + + // Application select + this.app_select.addClass("et2_itempicker_app_select"); + var item_count = 0; + for(var key in this.options.select_options) { + var img_icon = this.egw().image(key + "/navbar"); + if(img_icon === null) { + continue; + } + var img = $j(document.createElement("img")); + img.attr("src", img_icon); + var item = $j(document.createElement("li")) + item.attr("id", key) + .click(function() { + $j(".et2_itempicker_app_select li").removeClass("selected"); + $j(this).addClass("selected"); + }) + .append(img); + if(item_count == 0) { + item.addClass("selected"); // select first item by default + } + this.app_select.append(item); + item_count++; + } + if(item_count == 0) + { + this.app_select.hide(); + this.div.addClass("no_app"); + } + + // Search input field + this.search.addClass("et2_itempicker_search"); + //this.search.append(this.createSearchWidget()); + + // Itemlist + this.itemlist.attr("id", "itempicker_itemlist"); + this.itemlist.addClass("et2_itempicker_itemlist"); + + // Put everything together + this.left.append(this.app_select); + this.right.append(this.search); + this.right.append(this.itemlist); + this.div.append(this.right); // right before left to have a natural + this.div.append(this.left); // z-index for left div over right div + + this.setDOMNode(this.div[0]); + }, + + getValue: function() + { + if(this.options.blur && this.input.val() == this.options.blur) return ""; + return this._super.apply(this, arguments); + }, + + transformAttributes: function(_attrs) { + this._super.apply(this, arguments); + + _attrs["select_options"] = {}; + if(_attrs["application"]) + { + var apps = et2_csvSplit(_attrs["application"], null, ","); + for(var i = 0; i < apps.length; i++) + { + _attrs["select_options"][apps[i]] = this.egw().lang(apps[i]); + } + } + else + { + _attrs["select_options"] = this.egw().link_app_list('query'); + } + + // Check whether the options entry was found, if not read it from the + // content array. + if (_attrs["select_options"] == null) + { + _attrs["select_options"] = this.getArrayMgr('content') + .getEntry("options-" + this.id) + } + + // Default to an empty object + if (_attrs["select_options"] == null) + { + _attrs["select_options"] = {}; + } + }, + +}); + +et2_register_widget(et2_itempicker, ["itempicker"]); diff --git a/etemplate/js/etemplate2.js b/etemplate/js/etemplate2.js index 86f837bfc7..ec575dea96 100644 --- a/etemplate/js/etemplate2.js +++ b/etemplate/js/etemplate2.js @@ -42,6 +42,7 @@ et2_widget_selectAccount; et2_widget_ajaxSelect; et2_widget_vfs; + et2_widget_itempicker; et2_extension_nextmatch; et2_extension_customfields; diff --git a/etemplate/templates/default/etemplate2.css b/etemplate/templates/default/etemplate2.css index d0c092cf9b..16ce683974 100644 --- a/etemplate/templates/default/etemplate2.css +++ b/etemplate/templates/default/etemplate2.css @@ -792,5 +792,54 @@ div.et2_progress > div { margin-left: 7.5em; } +/** + * itempicker widget + */ +.et2_itempicker { + display: block; + position: relative; + margin: 0; + padding: 0; + width: 100%; + height: 260px; +} +.et2_itempicker_left { + display: block; + position: absolute; + top: 0; + left: 0; + bottom: 0; + width: 50px; + overflow: hidden; +} +.et2_itempicker_right { + display: block; + position: absolute; + margin: 0; + top: 0; + left: 49px; + right: 0; + bottom: 0; + border: 1px solid #b6b6b6; + background-color: #f9f9f9; +} +.et2_itempicker_app_select { + list-style-type: none; + padding: 0; +} + +.et2_itempicker_app_select li { + display: block; + margin: 0; + padding: 6px; +} + +.et2_itempicker_app_select li.selected { + border: 1px solid #b6b6b6; + border-right: 1px solid transparent; + background-color: #f9f9f9; + border-top-left-radius: 4px; + border-bottom-left-radius: 4px; +}