mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-12-26 08:38:54 +01:00
Convert et2_dropdown_button to TS
This commit is contained in:
parent
5d2600ddbd
commit
b0bcadf3fa
@ -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"]);
|
|
||||||
|
|
441
api/js/etemplate/et2_widget_dropdown_button.ts
Normal file
441
api/js/etemplate/et2_widget_dropdown_button.ts
Normal 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"]);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user