diff --git a/public/sihnon-framework.js b/public/sihnon-framework.js index 3fc85a5..d293b73 100644 --- a/public/sihnon-framework.js +++ b/public/sihnon-framework.js @@ -1,34 +1,34 @@ /** - * Sihnon Framework JS Library - * - * Written by Ben Roberts - * Homepage: https://benroberts.net/projects/sihnon-framework/ - * Code: https://github.com/optiz0r/sihnon-js-lib/ - * - * Dependencies: - * - Bootstrap-*.js - * - * Released under a Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License - * http://creativecommons.org/licenses/by-nc-sa/3.0/ - */ +* Sihnon Framework JS Library +* +* Written by Ben Roberts +* Homepage: https://benroberts.net/projects/sihnon-framework/ +* Code: https://github.com/optiz0r/sihnon-js-lib/ +* +* Dependencies: +* - Bootstrap-*.js +* +* Released under a Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License +* http://creativecommons.org/licenses/by-nc-sa/3.0/ +*/ /** - * Sihnon Framework object - * - * Entry point for all base framework code - */ +* Sihnon Framework object +* +* Entry point for all base framework code +*/ var sf = { /** - * Library version - * - */ + * Library version + * + */ version: '0.1.0', - + /** - * Initialises the library - * - */ + * Initialises the library + * + */ init: function() { // Initialise all modules @@ -47,26 +47,26 @@ var sf = { }, /** - * Utility module - * - * Contains simple and one-off functions that aren't worth grouping into full modules - */ + * Utility module + * + * Contains simple and one-off functions that aren't worth grouping into full modules + */ utility: { /** - * Initialise the module - */ + * Initialise the module + */ init: function() { }, /** - * Returns conditional if set to a value, else returns alternative - * - * @param conditional Value to test and return if set - * @param alternative Value to return if conditional is not set - * @returns - */ + * Returns conditional if set to a value, else returns alternative + * + * @param conditional Value to test and return if set + * @param alternative Value to return if conditional is not set + * @returns + */ orelse: function(conditional, alternative) { if (typeof conditional != 'undefined') { return conditional; @@ -78,29 +78,29 @@ var sf = { }, /** - * Code for making and handling AJAX requests - */ + * Code for making and handling AJAX requests + */ ajax: { /** - * Initialise the module - */ + * Initialise the module + */ init: function() { }, /** - * Launch a simple AJAX GET request - * - * Makes an AJAX request to the specified URL and calls one of the given - * functions on completion. Default callbacks are executed if not provided. - * - * See also: sf.ajax.success, sf.ajax.failure - * - * @param url URL to request - * @param success Callback to execute on success - * @param failure Callback to execute on failure - */ + * Launch a simple AJAX GET request + * + * Makes an AJAX request to the specified URL and calls one of the given + * functions on completion. Default callbacks are executed if not provided. + * + * See also: sf.ajax.success, sf.ajax.failure + * + * @param url URL to request + * @param success Callback to execute on success + * @param failure Callback to execute on failure + */ get: function(url, success, failure) { $.ajax({ url: url, @@ -112,18 +112,18 @@ var sf = { }, /** - * Launch a simple AJAX POST request - * - * Makes an AJAX request to the specified URL and calls one of the given - * functions on completion. Default callbacks are executed if not provided. - * - * See also: sf.ajax.success, sf.ajax.failure - * - * @param url URL to request - * @param data Data to send with the request - * @param success Callback to execute on success - * @param failure Callback to execute on failure - */ + * Launch a simple AJAX POST request + * + * Makes an AJAX request to the specified URL and calls one of the given + * functions on completion. Default callbacks are executed if not provided. + * + * See also: sf.ajax.success, sf.ajax.failure + * + * @param url URL to request + * @param data Data to send with the request + * @param success Callback to execute on success + * @param failure Callback to execute on failure + */ post: function(url, data, success, failure) { $.ajax({ url: url, @@ -136,15 +136,15 @@ var sf = { }, /** - * Default success handler - * - * Function that will be called for every successful AJAX request if no custom - * handler is defined. - * - * @param d Data returned from the request - * @param s Status of the request - * @param x XHttpRequest object used for the request - */ + * Default success handler + * + * Function that will be called for every successful AJAX request if no custom + * handler is defined. + * + * @param d Data returned from the request + * @param s Status of the request + * @param x XHttpRequest object used for the request + */ success: function(d, s, x) { // Replace any requested parts of the page @@ -165,59 +165,60 @@ var sf = { }, /** - * User Interface module - * - * Code for manipulating UI elements - */ + * User Interface module + * + * Code for manipulating UI elements + */ ui: { /** - * Initialise the module - */ + * Initialise the module + */ init: function() { sf.ui.dialog.init(); + sf.ui.selectall.init(); }, /** - * Submodule for customising and displaying the app dialog - */ + * Submodule for customising and displaying the app dialog + */ dialog: { /** - * Initialise the submodule - */ + * Initialise the submodule + */ init: function() { // Permanently configure the X to close the dialog $("#dialog-header-close").click(sf.ui.dialog.close); }, /** - * Prepare a dialog and optionally show it. - * - * Parameters should be an object which may contain any of the following fields: - * var parameters = { - * show: bool, // Show the dialog immediately after configuring - * title: string, // Title to display in the dialog header - * content: string, // Body of the dialog as HTML - * buttons: { // Configuration for the buttons in the dialog footer, see below - * type: ok|okcancel|yesno, // Type of buttons to display in the footer - * params: mixed, // Any data to be passed directly to the action handlers - * actions: { - * ok: string, // Action handler to be assigned to the OK button - * cancel: string, // Action handler to be assigned to the Cancel button - * yes: string, // Action handler to be assigned to the Yes button - * no: string, // Action handler to be assigned to the No button - * } - * } - * } - * - * var buttons = { - * type: ok|okcancel|yesno - * } - * - * - * @param p Parameters for configuring the dialog - */ + * Prepare a dialog and optionally show it. + * + * Parameters should be an object which may contain any of the following fields: + * var parameters = { + * show: bool, // Show the dialog immediately after configuring + * title: string, // Title to display in the dialog header + * content: string, // Body of the dialog as HTML + * buttons: { // Configuration for the buttons in the dialog footer, see below + * type: ok|okcancel|yesno, // Type of buttons to display in the footer + * params: mixed, // Any data to be passed directly to the action handlers + * actions: { + * ok: string, // Action handler to be assigned to the OK button + * cancel: string, // Action handler to be assigned to the Cancel button + * yes: string, // Action handler to be assigned to the Yes button + * no: string, // Action handler to be assigned to the No button + * } + * } + * } + * + * var buttons = { + * type: ok|okcancel|yesno + * } + * + * + * @param p Parameters for configuring the dialog + */ prepare: function(p) { if ( ! p) { return; @@ -272,9 +273,9 @@ var sf = { }, /** - * Immediately show a pre-configured dialog - * - */ + * Immediately show a pre-configured dialog + * + */ show: function() { $("#dialog").modal({ show: true, @@ -284,12 +285,12 @@ var sf = { }, /** - * Close the dialog and reset to default values - * - * The content and title will be removed, all buttons hidden - * and all action handlers removed. - * - */ + * Close the dialog and reset to default values + * + * The content and title will be removed, all buttons hidden + * and all action handlers removed. + * + */ close: function() { // Hide the dialog $("#dialog").modal({ @@ -306,16 +307,16 @@ var sf = { }, /** - * Use the built-in dialog to display an error message - * - * Prepares the dialog with a pre-defined format using the details provided. - * The dialog is immediately shown with an OK button that cancels the dialog and - * takes no further action - * - * @param title Title for the error dialog - * @param content Content for the dialog - * @param messages An optional list of messages to be reported on the dialog, e.g. reasons for the failure described by content. - */ + * Use the built-in dialog to display an error message + * + * Prepares the dialog with a pre-defined format using the details provided. + * The dialog is immediately shown with an OK button that cancels the dialog and + * takes no further action + * + * @param title Title for the error dialog + * @param content Content for the dialog + * @param messages An optional list of messages to be reported on the dialog, e.g. reasons for the failure described by content. + */ error: function(title, content, messages) { var formatted_content = $('
').append($('

').text('content')); if (messages) { @@ -341,54 +342,86 @@ var sf = { }, }, + + /** + * Submodule for handling select-all checkbox groups + */ + selectall: { + init: function() { + // Enable select all/none for checkboxes + $('input[type=checkbox].select-all').click(sf.ui.selectall.updateChildren); + + // Enable update of the select-all checkbox as the children are manually changed + $('input[type=checkbox].select-all').each(function() { + $('input[type=checkbox][data-select-all="' + $(this).attr('id') + '"]').click(sf.ui.selectall.updateParent); + }); + }, + + updateChildren: function(parent_id, children) { + $('input[type=checkbox][data-select-all="'+$(this).attr('id')+'"]') + .attr('checked', $(this).attr('checked') == 'checked') + .trigger('change'); + }, + + updateParent: function() { + var parent = $('#' + $(this).attr('data-select-all')); + var children = $('input[type=checkbox][data-select-all="' + parent.attr('id') + '"]'); + + if (children.filter(':checked').length != children.length) { + parent.attr('checked', false); + } else if (children.not(':checked').length == 0) { + parent.attr('checked', true); + } + }, + }, }, /** - * Page module - * - * Code for updating page content - */ + * Page module + * + * Code for updating page content + */ page: { /** - * List of callbacks to be executed on a new section of a page - * - * Used for setting up any behaviour on new page elements, such as when a page is - * first loaded, or replaced by an ajax call. - * - * Callbacks should have the form: - * function(d){} - * where d is the top level dom element being updated. - * - * New callbacks can be registered with addUpdateCallback() passing a unique name - * which can be used for later removing a callback if desired. - */ + * List of callbacks to be executed on a new section of a page + * + * Used for setting up any behaviour on new page elements, such as when a page is + * first loaded, or replaced by an ajax call. + * + * Callbacks should have the form: + * function(d){} + * where d is the top level dom element being updated. + * + * New callbacks can be registered with addUpdateCallback() passing a unique name + * which can be used for later removing a callback if desired. + */ update_callbacks: { }, /** - * Initialise module - */ + * Initialise module + */ init: function() { }, /** - * Updates all given subsets of the page - * - * Takes an object defining the replacements to be made and updates the page - * - * Object should use a DOM ID as the key, and replacement content should sit under a content key, e.g.: - * - * replacements = { - * page_content: { - * content: 'This will replace the entire page!', - * }, - * } - * - * @param replacements Object containing replacements to make - */ + * Updates all given subsets of the page + * + * Takes an object defining the replacements to be made and updates the page + * + * Object should use a DOM ID as the key, and replacement content should sit under a content key, e.g.: + * + * replacements = { + * page_content: { + * content: 'This will replace the entire page!', + * }, + * } + * + * @param replacements Object containing replacements to make + */ update: function(replacements) { for ( var id in replacements) { $("#" + id).html(replacements[id].content); @@ -397,13 +430,13 @@ var sf = { }, /** - * Update a subset of the page content with any global events - * - * Called when the element d has been updated and callbacks need to be applied to - * the new content. - * - * @param elements ID or DOM element of the new content on which events need to be applied - */ + * Update a subset of the page content with any global events + * + * Called when the element d has been updated and callbacks need to be applied to + * the new content. + * + * @param elements ID or DOM element of the new content on which events need to be applied + */ updateEvents: function(d) { for (var c in sf.page.update_callbacks) { sf.page.update_callbacks[c](d); @@ -411,29 +444,29 @@ var sf = { }, /** - * Add new page update callback - * - * Defines a new function to be run when part of the page is updated. - * This function will replace any previous callback registered with the same name. - * - * See also: sf.page.update_callbacks - * - * @param name Unique name of the callback for later retrieval - * @param callback Function to call - */ + * Add new page update callback + * + * Defines a new function to be run when part of the page is updated. + * This function will replace any previous callback registered with the same name. + * + * See also: sf.page.update_callbacks + * + * @param name Unique name of the callback for later retrieval + * @param callback Function to call + */ addCallback: function(name, callback) { sf.page.update_callbacks[name] = callback; }, /** - * Remove a page update callback - * - * Removes a previously defined callback from the list of page update callbacks. - * - * See also: sf.page.update_callbacks - * - * @param name Unique name of the callback to be removed - */ + * Remove a page update callback + * + * Removes a previously defined callback from the list of page update callbacks. + * + * See also: sf.page.update_callbacks + * + * @param name Unique name of the callback to be removed + */ removeCallback: function(name) { if (sf.page.update_callback[name]) { delete sf.page.update_callbacks[name]; @@ -443,27 +476,27 @@ var sf = { }, /** - * Actions module - * - * Defines a list of named callbacks which can be executed from a non-trusted source - * such as an ajax response without requiring code evaluation. - */ + * Actions module + * + * Defines a list of named callbacks which can be executed from a non-trusted source + * such as an ajax response without requiring code evaluation. + */ actions: { /** - * List of named callbacks that can be executed - * - * Callbacks should have the form: - * function(params){} - * where params is an action-specific list of parameters passed as an object. - * The callback should return a boolean to indicate success. - * - * New callbacks can be registered with addAction() passing a unique name - * which can be used for later removing an action if desired with removeAction(). - * - * Actions can be triggered manually using the trigger() method. A list of actions - * can be triggered in one go using triggerAll(). - */ + * List of named callbacks that can be executed + * + * Callbacks should have the form: + * function(params){} + * where params is an action-specific list of parameters passed as an object. + * The callback should return a boolean to indicate success. + * + * New callbacks can be registered with addAction() passing a unique name + * which can be used for later removing an action if desired with removeAction(). + * + * Actions can be triggered manually using the trigger() method. A list of actions + * can be triggered in one go using triggerAll(). + */ callbacks: { 'close-dialog': function(params) { @@ -473,21 +506,21 @@ var sf = { }, /** - * Initialise the module - */ + * Initialise the module + */ init: function() { }, /** - * Execute a named action - * - * Runs one or more named actions with the list of parameters provided - * All actions are run with the same parameters. - * - * @param names Names of the action(s) to execute - * @param params Object containing action specific parameters - */ + * Execute a named action + * + * Runs one or more named actions with the list of parameters provided + * All actions are run with the same parameters. + * + * @param names Names of the action(s) to execute + * @param params Object containing action specific parameters + */ trigger: function(names, params) { if ( ! (names instanceof Array)) { names = [names]; @@ -501,10 +534,10 @@ var sf = { }, /** - * Executes all given actions - * - * @param actions Object containing names of all actions to execute with associated parameters - */ + * Executes all given actions + * + * @param actions Object containing names of all actions to execute with associated parameters + */ triggerAll: function(actions) { for (var action in actions) { sf.actions.trigger(action, actions[action]); @@ -512,25 +545,25 @@ var sf = { }, /** - * Adds a new named action - * - * Defines a new named action to be run when manually triggered. - * This function will replace any previous action registered with the same name. - * - * See also: sf.actions.callbacks - * - * @param name Name of the new action - * @param callback Function to execute when this callback is triggered - */ + * Adds a new named action + * + * Defines a new named action to be run when manually triggered. + * This function will replace any previous action registered with the same name. + * + * See also: sf.actions.callbacks + * + * @param name Name of the new action + * @param callback Function to execute when this callback is triggered + */ addAction: function(name, callback) { sf.actions.callbacks[name] = callback; }, /** - * Removes a previously registered named action - * - * @param name Name of the action to remove - */ + * Removes a previously registered named action + * + * @param name Name of the action to remove + */ removeAction: function(name) { if (sf.actions.callbacks[name]) { delete sf.actions.callbacks[name];