2013-04-16 20:50:43 +02:00
/ * *
* EGroupware eTemplate2 - JS Dialog Widget class
*
* @ license http : //opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @ package etemplate
* @ link http : //www.egroupware.org
* @ author Nathan Gray
* @ copyright Nathan Gray 2013
* @ version $Id$
* /
"use strict" ;
/ * e g w : u s e s
et2 _core _widget ;
jquery . jquery - ui ;
* /
/ * *
* A common dialog widget that makes it easy to imform users or prompt for information .
*
* It is possible to have a custom dialog by using a template , but you can also use
* the static method et2 _dialog . show _dialog ( ) . At its simplest , you can just use :
* < code >
* et2 _dialog . show _dialog ( false , "Operation completed" ) ;
* < / c o d e >
* Or a more complete example :
* < code >
* var callback = function ( button _id )
* {
* if ( button _id == et2 _dialog . YES _BUTTON )
* {
* // Do stuff
* }
* else if ( button _id == et2 _dialog . NO _BUTTON )
* {
* // Other stuff
* }
* else if ( button _id == et2 _dialog . CANCEL _BUTTON )
* {
* // Abort
* }
* } .
* var dialog = et2 _dialog . show _dialog (
2013-05-21 22:23:35 +02:00
* callback , "Erase the entire database?" , "Break things" , { } // value
2013-04-16 20:50:43 +02:00
* et2 _dialog . BUTTONS _YES _NO _CANCEL , et2 _dialog . WARNING _MESSAGE
* ) ;
* < / c o d e >
*
*
* The parameters for the above are all optional , except callback and message :
* callback - function called when the dialog closes , or false / null .
* The ID of the button will be passed . Button ID will be one of the et2 _dialog . * _BUTTON constants .
* The callback is _not _ called if the user closes the dialog with the X in the corner , or presses ESC .
* message - text to display
* title - Dialog title
2013-05-21 22:23:35 +02:00
* value ( for prompt )
2013-04-16 20:50:43 +02:00
* buttons - et2 _dialog BUTTONS _ * constant , or an array of button settings
2013-05-21 22:23:35 +02:00
* dialog _type - et2 _dialog * _MESSAGE constant
2013-04-16 20:50:43 +02:00
* icon - URL of icon
*
* Note that these methods will _not _ block program flow while waiting for user input .
* The user ' s input will be provided to the callback .
*
* You can also use the standard et2 _createWidget ( ) to create a custom dialog using an etemplate , even setting all
* the buttons yourself .
* < code >
* var dialog = et2 _createWidget ( "dialog" , {
* // If you use a template, the second parameter will be the value of the template, as if it were submitted.
* callback : function ( button _id , value ) { ... } ,
* buttons : [
* // These ones will use the callback, just like normal
* { text : egw . lang ( "OK" ) , id : "OK" , class = "ui-priority-primary" , default : true } ,
* { text : egw . lang ( "Yes" ) , id : "Yes" } ,
* { text : egw . lang ( "Sure" ) , id : "Sure" } ,
* { text : egw . lang ( "Maybe" ) , click : function ( ) {
* // If you override, 'this' will be the dialog DOMNode.
* // Things get more complicated.
* // Do what you like, but don't forget this line:
* $j ( this ) . dialog ( "close" )
* } , class = "ui-state-error" } ,
*
* ] ,
* title : 'Why would you want to do <span style="color: red">this</span>?' ,
* template : "/egroupware/addressbook/templates/default/edit.xet" ,
* value : { content : { ... default values } , sel _options : { ... } ... }
* } ) ;
* < / c o d e >
* @ augments et2 _widget
* @ see http : //api.jqueryui.com/dialog/
* /
var et2 _dialog = et2 _widget . extend ( {
attributes : {
callback : {
name : "Callback" ,
type : "js" ,
description : "Callback function is called with the value when the dialog is closed" ,
"default" : function ( button _id ) { egw . debug ( "log" , "Button ID: %d" , button _id ) ; }
} ,
message : {
name : "Message" ,
type : "string" ,
description : "Dialog message" ,
"default" : "Somebody forgot to set this..." ,
} ,
dialog _type : {
name : "Dialog type" ,
type : "integer" ,
description : "To use a pre-defined dialog style, use et2_dialog.ERROR_MESSAGE, INFORMATION_MESSAGE,WARNING_MESSAGE,QUESTION_MESSAGE,PLAIN_MESSAGE constants. Default is et2_dialog.PLAIN_MESSAGE" ,
"default" : 0 , //this.PLAIN_MESSAGE
} ,
buttons : {
name : "Buttons" ,
type : "any" ,
"default" : 0 , //this.BUTTONS_OK,
description : "Buttons that appear at the bottom of the dialog. You can use the constants et2_dialog.BUTTONS_OK, BUTTONS_YES_NO, BUTTONS_YES_NO_CANCEL, BUTTONS_OK_CANCEL, or pass in an array for full control" ,
} ,
icon : {
name : "Icon" ,
type : "string" ,
description : "URL of an icon for the dialog. If omitted, an icon based on dialog_type will be used." ,
"default" : ""
} ,
title : {
name : "Title" ,
type : "string" ,
description : "Title for the dialog box" ,
"default" : ""
} ,
modal : {
name : "Modal" ,
type : "boolean" ,
description : "Prevent the user from interacting with the page" ,
"default" : true
} ,
resizable : {
name : "Resizable" ,
type : "boolean" ,
description : "Allow the user to resize the dialog" ,
"default" : true
} ,
value : {
"name" : "Value" ,
"description" : "The (default) value of the dialog. Use with template." ,
"type" : "any" ,
"default" : et2 _no _init
} ,
template : {
"name" : "Template" ,
"description" : "Instead of displaying a simple message, a full template can be loaded instead. Set defaults with value." ,
"type" : "string" ,
"default" : et2 _no _init
}
} ,
/ * *
* Details for dialog type options
* /
_dialog _types : [
//PLAIN_MESSAGE: 0
{ icon : "" } ,
//INFORMATION_MESSAGE: 1,
{ icon : egw . image ( "dialog_info" ) } ,
//QUESTION_MESSAGE: 2,
{ icon : egw . image ( "dialog_help" ) } ,
//WARNING_MESSAGE: 3,
{ icon : egw . image ( "dialog_warning" ) } ,
//ERROR_MESSAGE: 4,
{ icon : egw . image ( "dialog_error" ) } ,
] ,
_buttons : [
/ *
Pre - defined Button combos
- button ids copied from et2 _dialog static , since the constants are not defined yet
* /
//BUTTONS_OK: 0,
2013-04-23 18:51:00 +02:00
[ { "button_id" : 1 , "text" : 'ok' , "default" : true } ] ,
2013-04-16 20:50:43 +02:00
//BUTTONS_OK_CANCEL: 1,
[
2013-04-23 18:51:00 +02:00
{ "button_id" : 1 , "text" : 'ok' , "default" : true } ,
{ "button_id" : 0 , "text" : 'cancel' }
2013-04-16 20:50:43 +02:00
] ,
//BUTTONS_YES_NO: 2,
[
2013-04-23 18:51:00 +02:00
{ "button_id" : 2 , "text" : 'yes' , "default" : true } ,
{ "button_id" : 3 , "text" : 'no' }
2013-04-16 20:50:43 +02:00
] ,
//BUTTONS_YES_NO_CANCEL: 3,
[
2013-04-23 18:51:00 +02:00
{ "button_id" : 2 , "text" : 'yes' , "default" : true } ,
{ "button_id" : 3 , "text" : 'no' } ,
{ "button_id" : 0 , "text" : 'cancel' }
2013-04-16 20:50:43 +02:00
]
] ,
// Define this as null to avoid breaking any hierarchies (eg: destroy())
_parent : null ,
2013-04-20 11:51:52 +02:00
/ * *
* Constructor
*
* @ memberOf et2 _dialog
* /
2013-04-16 20:50:43 +02:00
init : function ( ) {
// Call the inherited constructor
this . _super . apply ( this , arguments ) ;
// Button callbacks need a reference to this
var self = this ;
for ( var i = 0 ; i < this . _buttons . length ; i ++ )
{
for ( var j = 0 ; j < this . _buttons [ i ] . length ; j ++ )
{
this . _buttons [ i ] [ j ] . click = ( function ( id ) {
return function ( event ) {
self . click ( event . target , id ) ;
2013-04-20 11:51:52 +02:00
} ;
2013-04-16 20:50:43 +02:00
} ) ( this . _buttons [ i ] [ j ] . button _id ) ;
2013-04-23 18:51:00 +02:00
// translate button texts, as translations are not available before
this . _buttons [ i ] [ j ] . text = egw . lang ( this . _buttons [ i ] [ j ] . text ) ;
2013-04-16 20:50:43 +02:00
}
}
this . div = $j ( document . createElement ( "div" ) ) ;
this . _createDialog ( ) ;
} ,
/ * *
* Clean up dialog
* /
destroy : function ( ) {
2013-07-20 19:20:55 +02:00
if ( this . div != null )
2013-04-16 20:50:43 +02:00
{
2013-07-20 19:20:55 +02:00
// Un-dialog the dialog
this . div . dialog ( "destroy" ) ;
2013-04-16 20:50:43 +02:00
2013-07-20 19:20:55 +02:00
if ( this . template )
{
this . template . clear ( ) ;
this . template = null ;
}
this . div = null ;
}
2013-04-16 20:50:43 +02:00
// Call the inherited constructor
2013-04-20 11:51:52 +02:00
this . _super . apply ( this , arguments ) ;
2013-04-16 20:50:43 +02:00
} ,
/ * *
* Internal callback registered on all standard buttons .
* The provided callback is called after the dialog is closed .
*
* @ param target DOMNode The clicked button
* @ param button _id integer The ID of the clicked button
* /
click : function ( target , button _id ) {
var value = this . options . value ;
if ( this . template )
{
value = this . template . getValues ( this . template . widgetContainer ) ;
}
if ( this . options . callback )
{
this . options . callback . call ( this , button _id , value ) ;
}
// Triggers destroy too
this . div . dialog ( "close" ) ;
} ,
/ * *
* Set the displayed prompt message
*
* @ param string New message for the dialog
* /
set _message : function ( message ) {
this . options . message = message ;
this . div . empty ( )
. append ( "<img class='dialog_icon' />" )
. append ( message ) ;
} ,
/ * *
* Set the dialog type to a pre - defined type
*
* @ param integer Type constant from et2 _dialog
* /
set _dialog _type : function ( type ) {
if ( this . options . dialog _type != type && typeof this . _dialog _types [ type ] == "object" )
{
this . options . dialog _type = type ;
}
var type _info = this . _dialog _types [ type ] ;
this . set _icon ( type _info . icon ) ;
} ,
/ * *
* Set the icon for the dialog
*
* @ param string icon
* /
set _icon : function ( icon _url ) {
if ( icon _url == "" )
{
$j ( "img.dialog_icon" , this . div ) . hide ( ) ;
}
else
{
$j ( "img.dialog_icon" , this . div ) . show ( ) . attr ( "src" , icon _url ) ;
}
} ,
/ * *
* Set the dialog buttons
*
* Use either the pre - defined options in et2 _dialog , or an array
* @ see http : //api.jqueryui.com/dialog/#option-buttons
* /
set _buttons : function ( buttons ) {
this . options . buttons = buttons ;
2013-07-20 15:05:03 +02:00
if ( buttons instanceof Array )
2013-04-16 20:50:43 +02:00
{
for ( var i = 0 ; i < buttons . length ; i ++ )
{
if ( ! buttons [ i ] . click )
{
2013-04-23 00:56:55 +02:00
buttons [ i ] . click = jQuery . proxy ( this . click , this , null , buttons [ i ] . id ) ;
2013-04-16 20:50:43 +02:00
}
}
this . options . buttons = buttons ;
2013-07-20 15:05:03 +02:00
}
// If dialog already created, update buttons
2013-07-20 15:54:31 +02:00
if ( this . div . data ( 'ui-dialog' ) )
2013-07-20 15:05:03 +02:00
{
2013-04-16 20:50:43 +02:00
this . div . dialog ( "option" , "buttons" , buttons ) ;
2013-07-20 15:05:03 +02:00
// Focus default button so enter works
$j ( '.ui-dialog-buttonpane button[default]' , this . div . parent ( ) ) . focus ( ) ;
2013-04-16 20:50:43 +02:00
}
} ,
/ * *
* Set the dialog title
*
* @ param string New title for the dialog
* /
set _title : function ( title ) {
this . options . title = title ;
this . div . dialog ( "option" , "title" , title ) ;
} ,
/ * *
* Block interaction with the page behind the dialog
*
* @ param boolean Block page behind dialog
* /
set _modal : function ( modal ) {
this . options . modal = modal ;
this . div . dialog ( "option" , "modal" , modal ) ;
} ,
/ * *
* Load an etemplate into the dialog
*
* @ param template String etemplate file name
* /
set _template : function ( template ) {
if ( this . template && this . options . template != template )
{
this . template . clear ( ) ;
}
this . template = new etemplate2 ( this . div [ 0 ] , false ) ;
this . template . load ( "" , template , this . options . value || { } ) ;
} ,
/ * *
* Actually create and display the dialog
* /
_createDialog : function ( ) {
if ( this . options . template )
{
this . set _template ( this . options . template ) ;
}
else
{
this . set _message ( this . options . message ) ;
this . set _dialog _type ( this . options . dialog _type ) ;
}
2013-04-23 00:56:55 +02:00
this . set _buttons ( this . options . buttons ) ;
2013-04-16 20:50:43 +02:00
this . div . dialog ( {
// Pass the internal object, not the option
buttons : typeof this . options . buttons == "number" ? this . _buttons [ this . options . buttons ] : this . options . buttons ,
modal : this . options . modal ,
resizable : this . options . resizable ,
2013-04-23 18:51:00 +02:00
width : "auto" ,
maxWidth : 640 ,
2013-04-16 20:50:43 +02:00
title : this . options . title ,
open : function ( ) {
// Focus default button so enter works
$j ( this ) . parents ( '.ui-dialog-buttonpane button[default]' ) . focus ( ) ;
} ,
2013-04-20 11:51:52 +02:00
close : jQuery . proxy ( function ( ) { this . destroy ( ) ; } , this )
2013-04-16 20:50:43 +02:00
} ) ;
}
} ) ;
et2 _register _widget ( et2 _dialog , [ "dialog" ] ) ;
// Static class stuff
jQuery . extend ( et2 _dialog ,
/** @lends et2_dialog */
{
// Some class constants //
/ * *
* Types
* @ constant
* /
PLAIN _MESSAGE : 0 ,
INFORMATION _MESSAGE : 1 ,
QUESTION _MESSAGE : 2 ,
WARNING _MESSAGE : 3 ,
ERROR _MESSAGE : 4 ,
/* Pre-defined Button combos */
BUTTONS _OK : 0 ,
BUTTONS _OK _CANCEL : 1 ,
BUTTONS _YES _NO : 2 ,
BUTTONS _YES _NO _CANCEL : 3 ,
/* Button constants */
CANCEL _BUTTON : 0 ,
OK _BUTTON : 1 ,
YES _BUTTON : 2 ,
NO _BUTTON : 3 ,
/ * *
* Show a confirmation dialog
*
2013-04-23 18:51:00 +02:00
* @ param function _callback Function called when the user clicks a button . The context will be the et2 _dialog widget , and the button constant is passed in .
* @ param String _message Message to be place in the dialog . Usually just text , but DOM nodes will work too .
* @ param String _title Text in the top bar of the dialog .
* @ param any _value passed unchanged to callback as 2. parameter
* @ param integer | Array _buttons One of the BUTTONS _ constants defining the set of buttons at the bottom of the box
* @ param integer _type One of the message constants . This defines the style of the message .
* @ param String _icon URL of an icon to display . If not provided , a type - specific icon will be used .
2013-04-16 20:50:43 +02:00
* /
2013-04-23 18:51:00 +02:00
show _dialog : function ( _callback , _message , _title , _value , _buttons , _type , _icon ) {
// Just pass them along, widget handles defaults & missing
return et2 _createWidget ( "dialog" , {
callback : _callback || function ( ) { } ,
message : _message ,
title : _title || egw . lang ( 'Confirmation required' ) ,
buttons : _buttons || et2 _dialog . BUTTONS _YES _NO ,
dialog _type : _type || et2 _dialog . QUESTION _MESSAGE ,
icon : _icon ,
value : _value
} ) ;
} ,
/ * *
* Show a prompt dialog
*
* @ param function _callback Function called when the user clicks a button . The context will be the et2 _dialog widget , and the button constant is passed in .
* @ param String _message Message to be place in the dialog . Usually just text , but DOM nodes will work too .
* @ param String _title Text in the top bar of the dialog .
* @ param String _value for prompt , passed to callback as 2. parameter
* @ param integer | Array _buttons One of the BUTTONS _ constants defining the set of buttons at the bottom of the box
* /
show _prompt : function ( _callback , _message , _title , _value , _buttons )
{
var callback = _callback ;
2013-04-16 20:50:43 +02:00
// Just pass them along, widget handles defaults & missing
return et2 _createWidget ( "dialog" , {
2013-04-23 18:51:00 +02:00
callback : function ( _button _id , _value ) {
if ( typeof callback == "function" )
{
callback . call ( this , _button _id , _value . value ) ;
}
} ,
title : _title || egw . lang ( 'Input required' ) ,
buttons : _buttons || et2 _dialog . BUTTONS _OK _CANCEL ,
value : {
content : {
value : _value ,
message : _message
}
} ,
template : egw . webserverUrl + '/etemplate/templates/default/prompt.xet' ,
class : "et2_prompt"
2013-04-16 20:50:43 +02:00
} ) ;
2013-04-23 18:51:00 +02:00
2013-04-16 20:50:43 +02:00
}
} ) ;