Convert et2_dropdown_button to TS

This commit is contained in:
Hadi Nategh 2020-01-23 16:24:53 +01:00
parent 5d2600ddbd
commit b0bcadf3fa
2 changed files with 795 additions and 395 deletions

View File

@ -1,3 +1,4 @@
"use strict";
/** /**
* EGroupware eTemplate2 - JS Dropdown Button object * EGroupware eTemplate2 - JS Dropdown Button object
* *
@ -9,13 +10,28 @@
* @copyright Nathan Gray 2013 * @copyright Nathan Gray 2013
* @version $Id$ * @version $Id$
*/ */
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
/*egw:uses /*egw:uses
/vendor/bower-asset/jquery/dist/jquery.js; /vendor/bower-asset/jquery/dist/jquery.js;
/vendor/bower-asset/jquery-ui/jquery-ui.js; /vendor/bower-asset/jquery-ui/jquery-ui.js;
et2_baseWidget; et2_baseWidget;
*/ */
var et2_core_inputWidget_1 = require("./et2_core_inputWidget");
var et2_core_widget_1 = require("./et2_core_widget");
var et2_core_inheritance_1 = require("./et2_core_inheritance");
/** /**
* A split button - a button with a dropdown list * A split button - a button with a dropdown list
* *
@ -30,393 +46,336 @@
* *
* @augments et2_inputWidget * @augments et2_inputWidget
*/ */
var et2_dropdown_button = (function(){ "use strict"; return et2_inputWidget.extend( var et2_dropdown_button = /** @class */ (function (_super) {
{ __extends(et2_dropdown_button, _super);
attributes: { /**
"label": { * Constructor
"name": "caption", *
"type": "string", * @memberOf et2_dropdown_button
"description": "Label of the button", */
"translate": true, function et2_dropdown_button(_parent, _attrs, _child) {
"default": "Select..." var _this = _super.call(this, _parent, _attrs, et2_core_inheritance_1.ClassWithAttributes.extendAttributes(et2_dropdown_button._attributes, _child || {})) || this;
}, _this.internal_ids = {
"label_updates": { div: "",
"name": "Label updates", button: "",
"type": "boolean", menu: ""
"description": "Button label updates when an option is selected from the menu", };
"default": true _this.div = null;
}, _this.buttons = null;
"image": { _this.button = null;
"name": "Icon", _this.arrow = null;
"type": "string", _this.menu = null;
"description": "Add an icon" _this.image = null;
}, _this.clicked = false;
"ro_image": { _this.label_updates = true;
"name": "Read-only Icon", _this.value = null;
"type": "string", /**
"description": "Use this icon instead of hiding for read-only" * Default menu, so there is something for the widget browser / editor to show
}, */
"onclick": { _this.default_menu = '<ul> \
"description": "JS code which gets executed when the button is clicked" <li data-id="opt_1.1"><a href="#">Option-1.1</a></li>\
}, <li data-id="opt_1.2"><a href="#">Option-1.2</a></li>\
"select_options": { <li data-id="opt_1.3"><a href="#">Option-1.3</a></li>\
"type": "any", <li data-id="opt_1.4"><a href="#">Option-1.4<br>\
"name": "Select options", <small>with second line</small>\
"default": {}, </a></li>\
"description": "Select options for dropdown. Can be a simple key => value list, or value can be full HTML", <li data-id="opt_1.5"><a href="#">Option-1.5</a></li>\
// Skip normal initialization for this one </ul>';
"ignore": true _this.clicked = false;
}, var self = _this;
"accesskey": { // Create the individual UI elements
"name": "Access Key", // Menu is a UL
"type": "string", _this.menu = jQuery(_this.default_menu).attr("id", _this.internal_ids.menu)
"default": et2_no_init, .hide()
"description": "Alt + <key> activates widget" .menu({
}, select: function (event, ui) {
"tabindex": { self.onselect.call(self, event, ui.item);
"name": "Tab index", }
"type": "integer", });
"default": et2_no_init, _this.buttons = jQuery(document.createElement("div"))
"description": "Specifies the tab order of a widget when the 'tab' button is used for navigating." .addClass("et2_dropdown");
}, // Main "wrapper" div
// No such thing as a required button _this.div = jQuery(document.createElement("div"))
"required": { .attr("id", _this.internal_ids.div)
"ignore": true .append(_this.buttons)
} .append(_this.menu);
}, // Left side - activates click action
_this.button = jQuery(document.createElement("button"))
internal_ids: { .attr("id", _this.internal_ids.button)
div: "", .attr("type", "button")
button: "", .addClass("ui-widget ui-corner-left").removeClass("ui-corner-all")
menu: "" .appendTo(_this.buttons);
}, // Right side - shows dropdown
_this.arrow = jQuery(document.createElement("button"))
div: null, .addClass("ui-widget ui-corner-right").removeClass("ui-corner-all")
buttons: null, .attr("type", "button")
button: null, .click(function () {
menu: null, // ignore click on readonly button
if (self.options.readonly)
/** return false;
* Default menu, so there is something for the widget browser / editor to show // Clicking it again hides menu
*/ if (self.menu.is(":visible")) {
default_menu: '<ul> \ self.menu.hide();
<li data-id="opt_1.1"><a href="#">Option-1.1</a></li>\ return false;
<li data-id="opt_1.2"><a href="#">Option-1.2</a></li>\ }
<li data-id="opt_1.3"><a href="#">Option-1.3</a></li>\ // Show menu dropdown
<li data-id="opt_1.4"><a href="#">Option-1.4<br>\ var menu = self.menu.show().position({
<small>with second line</small>\ my: "left top",
</a></li>\ at: "left bottom",
<li data-id="opt_1.5"><a href="#">Option-1.5</a></li>\ of: self.buttons
</ul>', });
// Hide menu if clicked elsewhere
/** jQuery(document).one("click", function () {
* Constructor menu.hide();
* });
* @memberOf et2_dropdown_button return false;
*/ })
init: function() { // This is the actual down arrow icon
this._super.apply(this, arguments); .append("<div class='ui-icon ui-icon-triangle-1-s'/>")
.appendTo(_this.buttons);
this.clicked = false; // Common button UI
_this.buttons.children("button")
var self = this; .addClass("ui-state-default")
.hover(function () { jQuery(this).addClass("ui-state-hover"); }, function () { jQuery(this).removeClass("ui-state-hover"); });
// Create the individual UI elements // Icon
_this.image = jQuery(document.createElement("img"));
// Menu is a UL _this.setDOMNode(_this.div[0]);
this.menu = jQuery(this.default_menu).attr("id",this.internal_ids.menu) return _this;
.hide() }
.menu({ et2_dropdown_button.prototype.destroy = function () {
select: function(event,ui) { // Destroy widget
self.onselect.call(self,event,ui.item); if (this.menu && this.menu.data('ui-menu'))
} this.menu.menu("destroy");
}); // Null children
this.image = null;
this.buttons = jQuery(document.createElement("div")) this.button = null;
.addClass("et2_dropdown"); this.arrow = null;
this.buttons = null;
// Main "wrapper" div this.menu = null;
this.div = jQuery(document.createElement("div")) // Remove
.attr("id", this.internal_ids.div) this.div.empty().remove();
.append(this.buttons) };
.append(this.menu); et2_dropdown_button.prototype.set_id = function (_id) {
_super.prototype.set_id.call(this, _id);
// Left side - activates click action // Update internal IDs - not really needed since we refer by internal
this.button = jQuery(document.createElement("button")) // javascript reference, but good to keep up to date
.attr("id", this.internal_ids.button) this.internal_ids = {
.attr("type", "button") div: this.dom_id + "_wrapper",
.addClass("ui-widget ui-corner-left").removeClass("ui-corner-all") button: this.dom_id,
.appendTo(this.buttons); menu: this.dom_id + "_menu"
};
// Right side - shows dropdown for (var key in this.internal_ids) {
this.arrow = jQuery(document.createElement("button")) if (this[key] == null)
.addClass("ui-widget ui-corner-right").removeClass("ui-corner-all") continue;
.attr("type", "button") this[key].attr("id", this.internal_ids[key]);
.click(function() { }
// ignore click on readonly button };
if (self.options.readonly) return false; /**
// Clicking it again hides menu * Set if the button label changes to match the selected option
if(self.menu.is(":visible")) *
{ * @param updates boolean Turn updating on or off
self.menu.hide(); */
return false; et2_dropdown_button.prototype.set_label_updates = function (updates) {
} this.label_updates = updates;
// Show menu dropdown };
var menu = self.menu.show().position({ et2_dropdown_button.prototype.set_accesskey = function (key) {
my: "left top", jQuery(this.node).attr("accesskey", key);
at: "left bottom", };
of: self.buttons et2_dropdown_button.prototype.set_ro_image = function (_image) {
}); if (this.options.readonly) {
// Hide menu if clicked elsewhere this.set_image(_image);
jQuery( document ).one( "click", function() { }
menu.hide(); };
}); et2_dropdown_button.prototype.set_image = function (_image) {
return false; if (!this.isInTree() || this.image == null)
}) return;
// This is the actual down arrow icon if (!_image.trim()) {
.append("<div class='ui-icon ui-icon-triangle-1-s'/>") this.image.hide();
.appendTo(this.buttons); }
else {
// Common button UI this.image.show();
this.buttons.children("button") }
.addClass("ui-state-default") var src = this.egw().image(_image);
.hover( if (src) {
function() {jQuery(this).addClass("ui-state-hover");}, this.image.attr("src", src);
function() {jQuery(this).removeClass("ui-state-hover");} }
); // allow url's too
else if (_image[0] == '/' || _image.substr(0, 4) == 'http') {
// Icon this.image.attr('src', _image);
this.image = jQuery(document.createElement("img")); }
else {
this.setDOMNode(this.div[0]); this.image.hide();
}, }
};
destroy: function() { /**
// Destroy widget * Overwritten to maintain an internal clicked attribute
if(this.menu && this.menu.data('ui-menu')) this.menu.menu("destroy"); *
* @param _ev
// Null children * @returns {Boolean}
this.image = null; */
this.button = null; et2_dropdown_button.prototype.click = function (_ev) {
this.arrow = null; // ignore click on readonly button
this.buttons = null; if (this.options.readonly)
this.menu = null; return false;
this.clicked = true;
// Remove if (!_super.prototype.click.call(this, _ev)) {
this.div.empty().remove(); this.clicked = false;
}, return false;
}
set_id: function(_id) { this.clicked = false;
this._super.apply(this, arguments); return true;
};
// Update internal IDs - not really needed since we refer by internal et2_dropdown_button.prototype.onselect = function (event, selected_node) {
// javascript reference, but good to keep up to date this.set_value(selected_node.attr("data-id"));
this.internal_ids = { this.change(selected_node);
div: this.dom_id + "_wrapper", };
button: this.dom_id, et2_dropdown_button.prototype.attachToDOM = function () {
menu: this.dom_id + "_menu" var res = _super.prototype.attachToDOM.call(this);
}; // Move the parent's handler to the button, or we can't tell the difference between the clicks
for(var key in this.internal_ids) jQuery(this.node).unbind("click.et2_baseWidget");
{ this.button.off().bind("click.et2_baseWidget", this, function (e) {
if(this[key] == null) continue; return e.data.click.call(e.data, this);
this[key].attr("id", this.internal_ids[key]); });
} return res;
}, };
et2_dropdown_button.prototype.set_label = function (_value) {
/** if (this.button) {
* Set if the button label changes to match the selected option this.label = _value;
* this.button.text(_value)
* @param updates boolean Turn updating on or off .prepend(this.image);
*/ }
set_label_updates: function(updates) { };
this.label_updates = updates; /**
}, * Set the options for the dropdown
*
set_accesskey: function(key) { * @param options Object ID => Label pairs
jQuery(this.node).attr("accesskey", key); */
}, et2_dropdown_button.prototype.set_select_options = function (options) {
set_ro_image: function(_image) { this.menu.first().empty();
if(this.options.readonly) // Allow more complicated content, if passed
{ if (typeof options == "string") {
this.set_image(_image); this.menu.append(options);
} }
}, else {
var add_complex_1 = function (node, options) {
set_image: function(_image) { for (var key in options) {
if(!this.isInTree() || this.image == null) return; var item = void 0;
var found_image = false; if (typeof options[key] == "string") {
if(!_image.trim()) item = jQuery("<li data-id='" + key + "'><a href='#'>" + options[key] + "</a></li>");
{ }
this.image.hide(); else if (options[key]["label"]) {
} item = jQuery("<li data-id='" + key + "'><a href='#'>" + options[key]["label"] + "</a></li>");
else }
{ // Optgroup
this.image.show(); else {
} item = jQuery("<li><a href='#'>" + key + "</a></li>");
add_complex_1(node.append("<ul>"), options[key]);
var src = this.egw().image(_image); }
if(src) node.append(item);
{ if (item && options[key].icon) {
this.image.attr("src", src); // we supply a applicable class for item images
found_image = true; jQuery('a', item).prepend('<img class="et2_button_icon" src="' + (options[key].icon.match(/^(http|https|\/)/) ? options[key].icon : egw.image(options[key].icon)) + '"/>');
} }
// allow url's too }
else if (_image[0] == '/' || _image.substr(0,4) == 'http') };
{ add_complex_1(this.menu.first(), options);
this.image.attr('src', _image); }
found_image = true; this.menu.menu("refresh");
} };
else /**
{ * Set tab index
this.image.hide(); */
} et2_dropdown_button.prototype.set_tabindex = function (index) {
}, jQuery(this.button).attr("tabindex", index);
};
/** et2_dropdown_button.prototype.set_value = function (new_value) {
* Overwritten to maintain an internal clicked attribute var menu_item = jQuery("[data-id='" + new_value + "']", this.menu);
* if (menu_item.length) {
* @param _ev this.value = new_value;
* @returns {Boolean} if (this.label_updates) {
*/ this.set_label(menu_item.text());
click: function(_ev) { }
// ignore click on readonly button }
if (this.options.readonly) return false; else {
this.value = null;
this.clicked = true; if (this.label_updates) {
this.set_label(this.options.label);
if (!this._super.apply(this, arguments)) }
{ }
this.clicked = false; };
return false; et2_dropdown_button.prototype.getValue = function () {
} return this.value;
this.clicked = false; };
return true; /**
}, * Set options.readonly
*
onselect: function(event, selected_node) { * @param {boolean} _ro
this.set_value(selected_node.attr("data-id")); */
this.change(selected_node); et2_dropdown_button.prototype.set_readonly = function (_ro) {
}, if (_ro != this.options.readonly) {
this.options.readonly = _ro;
attachToDOM: function() { // don't make readonly dropdown buttons clickable
this._super.apply(this, arguments); if (this.buttons) {
this.buttons.find('button')
// Move the parent's handler to the button, or we can't tell the difference between the clicks .toggleClass('et2_clickable', !_ro)
jQuery(this.node).unbind("click.et2_baseWidget"); .toggleClass('et2_button_ro', _ro)
this.button.off().bind("click.et2_baseWidget", this, function(e) { .css('cursor', _ro ? 'default' : 'pointer');
return e.data.click.call(e.data, this); }
}); }
}, };
et2_dropdown_button.attributes = {
set_label: function(_value) { "label": {
if (this.button) "name": "caption",
{ "type": "string",
this.label = _value; "description": "Label of the button",
"translate": true,
this.button.text(_value) "default": "Select..."
.prepend(this.image); },
} "label_updates": {
}, "name": "Label updates",
"type": "boolean",
/** "description": "Button label updates when an option is selected from the menu",
* Set the options for the dropdown "default": true
* },
* @param options Object ID => Label pairs "image": {
*/ "name": "Icon",
set_select_options: function(options) { "type": "string",
this.menu.first().empty(); "description": "Add an icon"
},
// Allow more complicated content, if passed "ro_image": {
if(typeof options == "string") "name": "Read-only Icon",
{ "type": "string",
this.menu.append(options); "description": "Use this icon instead of hiding for read-only"
} },
else "onclick": {
{ "description": "JS code which gets executed when the button is clicked"
var add_complex = function(node, options) },
{ "select_options": {
for(var key in options) "type": "any",
{ "name": "Select options",
var item; "default": {},
if(typeof options[key] == "string") "description": "Select options for dropdown. Can be a simple key => value list, or value can be full HTML",
{ // Skip normal initialization for this one
item = jQuery("<li data-id='"+key+"'><a href='#'>"+options[key]+"</a></li>"); "ignore": true
} },
else if (options[key]["label"]) "accesskey": {
{ "name": "Access Key",
item =jQuery("<li data-id='"+key+"'><a href='#'>"+options[key]["label"]+"</a></li>"); "type": "string",
} "default": et2_no_init,
// Optgroup "description": "Alt + <key> activates widget"
else },
{ "tabindex": {
item = jQuery("<li><a href='#'>"+key+"</a></li>"); "name": "Tab index",
add_complex(node.append("<ul>"), options[key]); "type": "integer",
} "default": et2_no_init,
node.append(item); "description": "Specifies the tab order of a widget when the 'tab' button is used for navigating."
if(item && options[key].icon) },
{ // No such thing as a required button
// we supply a applicable class for item images "required": {
jQuery('a',item).prepend('<img class="et2_button_icon" src="' + (options[key].icon.match(/^(http|https|\/)/) ? options[key].icon : egw.image(options[key].icon)) +'"/>'); "ignore": true
} }
} };
} return et2_dropdown_button;
add_complex(this.menu.first(), options); }(et2_core_inputWidget_1.et2_inputWidget));
} et2_core_widget_1.et2_register_widget(et2_dropdown_button, ["dropdown_button"]);
this.menu.menu("refresh"); //# sourceMappingURL=et2_widget_dropdown_button.js.map
},
/**
* Set tab index
*/
set_tabindex: function(index) {
jQuery(this.button).attr("tabindex", index);
},
set_value: function(new_value) {
var menu_item = jQuery("[data-id='"+new_value+"']",this.menu);
if(menu_item.length)
{
this.value = new_value;
if(this.label_updates)
{
this.set_label(menu_item.text());
}
}
else
{
this.value = null;
if(this.label_updates)
{
this.set_label(this.options.label);
}
}
},
getValue: function() {
return this.value;
},
/**
* Set options.readonly
*
* @param {boolean} _ro
*/
set_readonly: function(_ro)
{
if (_ro != this.options.readonly)
{
this.options.readonly = _ro;
// don't make readonly dropdown buttons clickable
if (this.buttons)
{
this.buttons.find('button')
.toggleClass('et2_clickable', !_ro)
.toggleClass('et2_button_ro', _ro)
.css('cursor', _ro ? 'default' : 'pointer');
}
}
}
});}).call(this);
et2_register_widget(et2_dropdown_button, ["dropdown_button"]);

View File

@ -0,0 +1,441 @@
/**
* EGroupware eTemplate2 - JS Dropdown Button object
*
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @package etemplate
* @subpackage api
* @link http://www.egroupware.org
* @author Nathan Gray
* @copyright Nathan Gray 2013
* @version $Id$
*/
/*egw:uses
/vendor/bower-asset/jquery/dist/jquery.js;
/vendor/bower-asset/jquery-ui/jquery-ui.js;
et2_baseWidget;
*/
import {et2_inputWidget} from './et2_core_inputWidget';
import {WidgetConfig, et2_register_widget} from "./et2_core_widget";
import {ClassWithAttributes} from "./et2_core_inheritance";
/**
* A split button - a button with a dropdown list
*
* There are several parts to the button UI:
* - Container: This is what is percieved as the dropdown button, the whole package together
* - Button: The part on the left that can be clicked
* - Arrow: The button to display the choices
* - Menu: The list of choices
*
* Menu options are passed via the select_options. They are normally ID => Title pairs,
* as for a select box, but the title can also be full HTML if needed.
*
* @augments et2_inputWidget
*/
class et2_dropdown_button extends et2_inputWidget
{
static readonly attributes : any = {
"label": {
"name": "caption",
"type": "string",
"description": "Label of the button",
"translate": true,
"default": "Select..."
},
"label_updates": {
"name": "Label updates",
"type": "boolean",
"description": "Button label updates when an option is selected from the menu",
"default": true
},
"image": {
"name": "Icon",
"type": "string",
"description": "Add an icon"
},
"ro_image": {
"name": "Read-only Icon",
"type": "string",
"description": "Use this icon instead of hiding for read-only"
},
"onclick": {
"description": "JS code which gets executed when the button is clicked"
},
"select_options": {
"type": "any",
"name": "Select options",
"default": {},
"description": "Select options for dropdown. Can be a simple key => value list, or value can be full HTML",
// Skip normal initialization for this one
"ignore": true
},
"accesskey": {
"name": "Access Key",
"type": "string",
"default": et2_no_init,
"description": "Alt + <key> activates widget"
},
"tabindex": {
"name": "Tab index",
"type": "integer",
"default": et2_no_init,
"description": "Specifies the tab order of a widget when the 'tab' button is used for navigating."
},
// No such thing as a required button
"required": {
"ignore": true
}
};
internal_ids : any = {
div: "",
button: "",
menu: ""
};
div : JQuery = null;
buttons : JQuery = null;
button : JQuery = null;
arrow : JQuery = null;
menu : JQuery = null;
image : JQuery = null;
clicked : boolean = false;
label_updates : boolean = true;
value : any = null;
/**
* Default menu, so there is something for the widget browser / editor to show
*/
readonly default_menu : string = '<ul> \
<li data-id="opt_1.1"><a href="#">Option-1.1</a></li>\
<li data-id="opt_1.2"><a href="#">Option-1.2</a></li>\
<li data-id="opt_1.3"><a href="#">Option-1.3</a></li>\
<li data-id="opt_1.4"><a href="#">Option-1.4<br>\
<small>with second line</small>\
</a></li>\
<li data-id="opt_1.5"><a href="#">Option-1.5</a></li>\
</ul>';
/**
* Constructor
*
* @memberOf et2_dropdown_button
*/
constructor(_parent?, _attrs? : WidgetConfig, _child? : object) {
super(_parent, _attrs, ClassWithAttributes.extendAttributes(et2_dropdown_button._attributes, _child || {}));
this.clicked = false;
let self = this;
// Create the individual UI elements
// Menu is a UL
this.menu = jQuery(this.default_menu).attr("id",this.internal_ids.menu)
.hide()
.menu({
select: function(event,ui) {
self.onselect.call(self,event,ui.item);
}
});
this.buttons = jQuery(document.createElement("div"))
.addClass("et2_dropdown");
// Main "wrapper" div
this.div = jQuery(document.createElement("div"))
.attr("id", this.internal_ids.div)
.append(this.buttons)
.append(this.menu);
// Left side - activates click action
this.button = jQuery(document.createElement("button"))
.attr("id", this.internal_ids.button)
.attr("type", "button")
.addClass("ui-widget ui-corner-left").removeClass("ui-corner-all")
.appendTo(this.buttons);
// Right side - shows dropdown
this.arrow = jQuery(document.createElement("button"))
.addClass("ui-widget ui-corner-right").removeClass("ui-corner-all")
.attr("type", "button")
.click(function() {
// ignore click on readonly button
if (self.options.readonly) return false;
// Clicking it again hides menu
if(self.menu.is(":visible"))
{
self.menu.hide();
return false;
}
// Show menu dropdown
var menu = self.menu.show().position({
my: "left top",
at: "left bottom",
of: self.buttons
});
// Hide menu if clicked elsewhere
jQuery( document ).one( "click", function() {
menu.hide();
});
return false;
})
// This is the actual down arrow icon
.append("<div class='ui-icon ui-icon-triangle-1-s'/>")
.appendTo(this.buttons);
// Common button UI
this.buttons.children("button")
.addClass("ui-state-default")
.hover(
function() {jQuery(this).addClass("ui-state-hover");},
function() {jQuery(this).removeClass("ui-state-hover");}
);
// Icon
this.image = jQuery(document.createElement("img"));
this.setDOMNode(this.div[0]);
}
destroy() {
// Destroy widget
if(this.menu && this.menu.data('ui-menu')) this.menu.menu("destroy");
// Null children
this.image = null;
this.button = null;
this.arrow = null;
this.buttons = null;
this.menu = null;
// Remove
this.div.empty().remove();
}
set_id(_id) {
super.set_id(_id);
// Update internal IDs - not really needed since we refer by internal
// javascript reference, but good to keep up to date
this.internal_ids = {
div: this.dom_id + "_wrapper",
button: this.dom_id,
menu: this.dom_id + "_menu"
};
for(let key in this.internal_ids)
{
if(this[key] == null) continue;
this[key].attr("id", this.internal_ids[key]);
}
}
/**
* Set if the button label changes to match the selected option
*
* @param updates boolean Turn updating on or off
*/
set_label_updates(updates)
{
this.label_updates = updates;
}
set_accesskey(key)
{
jQuery(this.node).attr("accesskey", key);
}
set_ro_image(_image)
{
if(this.options.readonly)
{
this.set_image(_image);
}
}
set_image(_image)
{
if(!this.isInTree() || this.image == null) return;
if(!_image.trim())
{
this.image.hide();
}
else
{
this.image.show();
}
let src = this.egw().image(_image);
if(src)
{
this.image.attr("src", src);
}
// allow url's too
else if (_image[0] == '/' || _image.substr(0,4) == 'http')
{
this.image.attr('src', _image);
}
else
{
this.image.hide();
}
}
/**
* Overwritten to maintain an internal clicked attribute
*
* @param _ev
* @returns {Boolean}
*/
click(_ev)
{
// ignore click on readonly button
if (this.options.readonly) return false;
this.clicked = true;
if (!super.click(_ev))
{
this.clicked = false;
return false;
}
this.clicked = false;
return true;
}
onselect(event, selected_node)
{
this.set_value(selected_node.attr("data-id"));
this.change(selected_node);
}
attachToDOM()
{
let res = super.attachToDOM();
// Move the parent's handler to the button, or we can't tell the difference between the clicks
jQuery(this.node).unbind("click.et2_baseWidget");
this.button.off().bind("click.et2_baseWidget", this, function(e) {
return e.data.click.call(e.data, this);
});
return res;
}
set_label(_value)
{
if (this.button)
{
this.label = _value;
this.button.text(_value)
.prepend(this.image);
}
}
/**
* Set the options for the dropdown
*
* @param options Object ID => Label pairs
*/
set_select_options(options) {
this.menu.first().empty();
// Allow more complicated content, if passed
if(typeof options == "string")
{
this.menu.append(options);
}
else
{
let add_complex = function(node, options)
{
for(let key in options)
{
let item;
if(typeof options[key] == "string")
{
item = jQuery("<li data-id='"+key+"'><a href='#'>"+options[key]+"</a></li>");
}
else if (options[key]["label"])
{
item =jQuery("<li data-id='"+key+"'><a href='#'>"+options[key]["label"]+"</a></li>");
}
// Optgroup
else
{
item = jQuery("<li><a href='#'>"+key+"</a></li>");
add_complex(node.append("<ul>"), options[key]);
}
node.append(item);
if(item && options[key].icon)
{
// we supply a applicable class for item images
jQuery('a',item).prepend('<img class="et2_button_icon" src="' + (options[key].icon.match(/^(http|https|\/)/) ? options[key].icon : egw.image(options[key].icon)) +'"/>');
}
}
}
add_complex(this.menu.first(), options);
}
this.menu.menu("refresh");
}
/**
* Set tab index
*/
set_tabindex(index)
{
jQuery(this.button).attr("tabindex", index);
}
set_value(new_value)
{
let menu_item = jQuery("[data-id='"+new_value+"']",this.menu);
if(menu_item.length)
{
this.value = new_value;
if(this.label_updates)
{
this.set_label(menu_item.text());
}
}
else
{
this.value = null;
if(this.label_updates)
{
this.set_label(this.options.label);
}
}
}
getValue()
{
return this.value;
}
/**
* Set options.readonly
*
* @param {boolean} _ro
*/
set_readonly(_ro : boolean)
{
if (_ro != this.options.readonly)
{
this.options.readonly = _ro;
// don't make readonly dropdown buttons clickable
if (this.buttons)
{
this.buttons.find('button')
.toggleClass('et2_clickable', !_ro)
.toggleClass('et2_button_ro', _ro)
.css('cursor', _ro ? 'default' : 'pointer');
}
}
}
}
et2_register_widget(et2_dropdown_button, ["dropdown_button"]);