Last active
January 24, 2020 05:27
-
-
Save iconifyit/0b88d049bc8af5871bd25290215544c6 to your computer and use it in GitHub Desktop.
A wrapper class for dialogs created with the Script UI Dialog Builder by Joonas - https://scriptui.joonas.me/
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* @author Scott Lewis <[email protected]> | |
* @copyright 2020 Scott Lewis | |
* @version 1.0.0 | |
* @url http://github.com/iconifyit | |
* @url https://atomiclotus.net | |
* | |
* ABOUT: | |
* | |
* This JS class is a wrapper for dialogs created with the Script UI Dialog Builder by Joonas Pääkkö. | |
* The wrapper dynamically creates getters and setters as well as provides an easy interface for | |
* retrieving field values, attaching event handlers to buttons, performing form validation, etc. | |
* This allows you to simply copy & paste the original dialog into your script/extension and not have | |
* to modify it at all to work with your code. Additionally, if you need to make changes to the dialog, | |
* you do not need to change any of your code other than custom handlers and field validators. * | |
* | |
* LICENSE: | |
* | |
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated | |
* documentation files (the “Software”), to deal in the Software without restriction, including without limitation | |
* the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, | |
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions: | |
* | |
* The above copyright notice and this permission notice shall be included in all copies or substantial portions | |
* of the Software. | |
* | |
* THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED | |
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF | |
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |
* DEALINGS IN THE SOFTWARE. | |
* | |
* Usage: | |
* | |
* The basic idea is to use the DialogWrapper like a View. You do not need to interact directly with | |
* the Dialog object itself, you can use the intuitive interfaces created by the wrapper to get, set, | |
* and validate values, as well as respond to user actions. | |
* | |
* var wrapper = new DialogWrapper( | |
* this, | |
* new Dialog(), | |
* ['name', 'email', 'url'] | |
* ['cancel', 'ok'], | |
* { | |
* name : 'Scott', | |
* email : '[email protected]', | |
* url : 'https://atomiclotus.net' | |
* } | |
* ); | |
* | |
* Using getters and setters: | |
* | |
* NOTE: You do not need to include a class reference. The getters and setters are added | |
* to the calling scope, typically Window so that calling `getName()` is the same as `window.getName()` | |
* | |
* getName() // -> Scott | |
* getEmail() // -> [email protected] | |
* getUrl() // -> https://atomiclotus.net | |
* | |
* Or update dialog field values: | |
* | |
* setName('Scott Lewis'); | |
* setEmail('[email protected]'); | |
* setUrl('https://vectoricons.net'); | |
* | |
* Validating the form: | |
* | |
* wrapper.validateForm({ | |
* name : function(name) { return name.tirm() !== '' }, | |
* email : function(email) { // email validation code }, | |
* url : function(url) { // url validation code } | |
* }); | |
* | |
* Set the default and cancel buttons: | |
* | |
* wrapper.setDefaultElement('Ok'); | |
* wrapper.setCancelElement('cancel'); | |
* | |
* Set a callback handler: | |
* | |
* wrapper.setHandler('ok', 'onclick', function() { | |
* // Handle the click event. | |
* }); | |
* | |
* OR: | |
* | |
* wrapper.setHandler('name', 'onchange', function() { | |
* wrapper.updateFormState(); | |
* }); | |
* | |
* Get the form's values: | |
* | |
* var values = wrapper.getFormValues(); | |
* | |
* Show & hide the dialog: | |
* | |
* wrapper.show(); | |
* wrapper.close(); | |
* | |
* @see https://scriptui.joonas.me/ | |
*/ | |
(function(global) { | |
/** | |
* Get a value from an object or array. | |
* @param {object|array} subject The object or array to search | |
* @param {string} key The object property to find | |
* @param {*} _default The default value to return if property is not found | |
* @returns {*} The found or default value | |
*/ | |
function get( subject, key, _default ) { | |
var value = _default; | |
if (typeof(subject[key]) !== 'undefined') { | |
value = subject[key]; | |
} | |
return value; | |
} | |
/** | |
* Creates a new DialogWrapper class. | |
* @param global | |
* @param Dialog | |
* @param fields | |
* @param buttons | |
* @param data | |
* @constructor | |
*/ | |
var DialogWrapper = function(global, Dialog, fields, buttons, data) { | |
var module = this; | |
try { | |
/** | |
* @type {{}} | |
*/ | |
this.getters = {}; | |
/** | |
* @type {{}} | |
*/ | |
this.setters = []; | |
/** | |
* @type {Window | Window | IconMetaDialog} | |
*/ | |
this.dialog = Dialog; | |
/** | |
* @type {*|*[]} | |
*/ | |
this.fields = fields || []; | |
/** | |
* @type {*|*[]} | |
*/ | |
this.buttons = buttons || []; | |
/** | |
* @type {*|{}} | |
*/ | |
this.meta = data || {}; | |
/** | |
* @type {string} | |
*/ | |
this.cancelElementName = 'cancel'; | |
/** | |
* @type {string} | |
*/ | |
this.defaultElemenName = 'save'; | |
/** | |
* Initialize the wrapper class. | |
*/ | |
this._init(); | |
} | |
catch(e) { throw e; } | |
} | |
/** | |
* Initializes the class. | |
* @private | |
*/ | |
DialogWrapper.prototype._init = function() { | |
var module = this; | |
/* | |
* Test global field values. | |
*/ | |
try { | |
this.fields.forEach(function(fieldName) { | |
module.set(fieldName, get(data, fieldName, '')); | |
}); | |
} | |
catch(e) { throw e; } | |
/* | |
* Create Getters and Setters | |
*/ | |
for (var f in this.fields) { | |
var func, | |
getter = this.makeGetterName(f), | |
setter = this.makeSetterName(f); | |
/* | |
* Adds getter for each field to the calling scope (typically Window) | |
* Example : getName() // --> returns value of 'name' field of the dialog. | |
*/ | |
func = function() { | |
return module.get(f); | |
} | |
module.getters[getter] = global[getter] = func; | |
/* | |
* Adds setter for each field to the calling scope (typically Window) | |
* Example : setName(value) // --> sets the 'name' field on the dialog. | |
*/ | |
func = function(value) { | |
module.set(f, value); | |
return module.get(f); | |
} | |
module.setters[setter] = global[setter] = func; | |
} | |
} | |
/** | |
* Show the dialog. | |
*/ | |
DialogWrapper.prototype.show = function() { | |
this.dialog.show(); | |
} | |
/** | |
* Close the dialog. | |
*/ | |
DialogWrapper.prototype.close = function() { | |
this.dialog.close(); | |
} | |
/** | |
* Sets the dialog's default button. | |
* @param buttonName | |
*/ | |
DialogWrapper.prototype.setDefaultElement = function(buttonName) { | |
this.defaultElemenName = buttonName; | |
this.dialog.defaultElement = this.findElement(buttonName); | |
} | |
/** | |
* Sets the dialog's cancel button. | |
* @param buttonName | |
*/ | |
DialogWrapper.prototype.setCancelElement = function(buttonName) { | |
this.cancelElementName = buttonName; | |
this.dialog.cancelElement = this.findElement(buttonName); | |
} | |
/** | |
* Update the form state based on form validation. | |
*/ | |
DialogWrapper.prototype.updateFormState = function() { | |
this.dialog.defaultElement.enabled = this.validateForm(); | |
} | |
/** | |
* Make sure required fields have values. | |
* @returns {boolean} | |
* | |
* Usage: | |
* | |
* Validations are necessarily custom. The validations variable is an | |
* object with field names and a function that performs the validation. | |
* So, for instance, if you have a `name` field that is required, you could | |
* just pass: | |
* | |
* validations = { | |
* 'name' : function(name) { | |
* return name.trim() !== ''; | |
* } | |
* } | |
* | |
* DialogWrapper.validateForm(validations) | |
*/ | |
DialogWrapper.prototype.validateForm = function(validations) { | |
var module = this, | |
validator, | |
value; | |
for (var fieldName in validations) { | |
value = module.get(fieldName); | |
validator = function(){} | |
if (validations[fieldName] instanceof Function) { | |
validator = validations[fieldName]; | |
} | |
if (! validator.call(this, value)) { | |
return false; | |
} | |
} | |
return true; | |
} | |
/** | |
* Get the form values. | |
* @returns {{setName: string, folderPath: *, authorName: string, imagesPath: string, fileType: string}} | |
*/ | |
DialogWrapper.prototype.getFormValues = function() { | |
var formValues = {}; | |
this.fields.forEach(function(fieldName) { | |
formValues[fieldName] = this.get(fieldName, null); | |
}) | |
return formValues; | |
} | |
/** | |
* Get a field value by field name. | |
* @param key | |
* @param fallback | |
* @returns {*} | |
*/ | |
DialogWrapper.prototype.get = function(key, fallback) { | |
try { | |
var field = this.findElement(key); | |
if (! $is.undefined()) { | |
if (! $is.undefined(field.text)) { | |
return field.text; | |
} | |
else if (! $is.undefined(field.value)) { | |
return field.value; | |
} | |
} | |
return fallback; | |
} | |
catch(e) { throw e; } | |
} | |
/** | |
* Set a field value by field name. | |
* @param key | |
* @param fallback | |
* @returns {*} | |
*/ | |
DialogWrapper.prototype.set = function(key, value) { | |
try { | |
var field = this.findElement(key); | |
if (! $is.undefined(field)) { | |
if (! $is.undefined(field.text)) { | |
field.text = value; | |
} | |
else if (! $is.undefined(field.value)) { | |
field.value = value; | |
} | |
} | |
return field; | |
} | |
catch(e) { throw e; } | |
} | |
/** | |
* Create getter from field names. | |
* @param fieldName | |
* @returns {*} | |
*/ | |
DialogWrapper.prototype.makeGetterName = function(fieldName) { | |
var f = fieldName; | |
return fieldName.replace( | |
/\w\S*/g, | |
'get' + f.charAt(0).toUpperCase() + f.substr(1) | |
); | |
} | |
/** | |
* Create setter from field names. | |
* @param fieldName | |
* @returns {*} | |
*/ | |
DialogWrapper.prototype.makeSetterName = function(fieldName) { | |
var f = fieldName; | |
return fieldName.replace( | |
/\w\S*/g, | |
'set' + f.charAt(0).toUpperCase() + f.substr(1) | |
); | |
} | |
/** | |
* Wrapper for Dialog.findElement | |
* @param entityName | |
* @returns {*} | |
*/ | |
DialogWrapper.prototype.findElement = function(entityName) { | |
return this.dialog.findElement(entityName); | |
} | |
/** | |
* Sets event handler on dialog element. | |
* @param entityName | |
* @param eventName | |
* @param handler | |
*/ | |
DialogWrapper.prototype.setHandler = function(entityName, eventName, handler) { | |
var entity = this.findElement(entityName); | |
if (typeof entity !== 'undefined') { | |
entity[eventName] = handler; | |
} | |
} | |
global.DialogWrapper = DialogWrapper; | |
})(this); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment