From a3b16f33c9292aa2af8693eebb0410015efa5c5f Mon Sep 17 00:00:00 2001 From: Mike Gerwitz Date: Fri, 1 Apr 2016 15:18:25 -0400 Subject: [PATCH] Liberate ui/styler/ * src/ui/styler/ErrorFieldStyler.js: Added * src/ui/styler/ErrorStyler.js: Added * src/ui/styler/FieldStyler.js: Added * src/ui/styler/SidebarErrorStyler.js: Added * src/ui/styler/StepErrorStyler.js: Added * src/ui/styler/Styler.js: Added --- src/ui/styler/ErrorFieldStyler.js | 132 ++++++++++++++++++++++++++++ src/ui/styler/ErrorStyler.js | 108 +++++++++++++++++++++++ src/ui/styler/FieldStyler.js | 91 +++++++++++++++++++ src/ui/styler/SidebarErrorStyler.js | 66 ++++++++++++++ src/ui/styler/StepErrorStyler.js | 52 +++++++++++ src/ui/styler/Styler.js | 30 +++++++ 6 files changed, 479 insertions(+) create mode 100644 src/ui/styler/ErrorFieldStyler.js create mode 100644 src/ui/styler/ErrorStyler.js create mode 100644 src/ui/styler/FieldStyler.js create mode 100644 src/ui/styler/SidebarErrorStyler.js create mode 100644 src/ui/styler/StepErrorStyler.js create mode 100644 src/ui/styler/Styler.js diff --git a/src/ui/styler/ErrorFieldStyler.js b/src/ui/styler/ErrorFieldStyler.js new file mode 100644 index 0000000..a065047 --- /dev/null +++ b/src/ui/styler/ErrorFieldStyler.js @@ -0,0 +1,132 @@ +/** + * Error condition field styler + * + * Copyright (C) 2016 LoVullo Associates, Inc. + * + * This file is part of liza. + * + * liza is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +var Class = require( 'easejs' ).Class, + FieldStyler = require( './FieldStyler' ); + + +/** + * Style field to indicate an error and displays an error message + */ +module.exports = Class( 'ErrorFieldStyler' ) + .extend( FieldStyler, +{ + 'public getId': function() + { + return 'error'; + }, + + + 'public applyStyle': function( field, element, row, msg ) + { + var _self = this; + + // style the row containing the element + for ( var i in row ) + { + this.addClass( row[ i ], 'invalid' ); + } + + // TODO: legacy; remove + this.addClass( element, 'invalid_field' ); + + // display the error message + this._createMessage( field.getName(), msg, row[ 0 ], row[ 1 ] ); + + return this; + }, + + + 'public revokeStyle': function( field, element, row ) + { + var _self = this; + + // un-style the row containing the element + // style the row containing the element + for ( var i in row ) + { + this.removeClass( row[ i ], 'invalid' ); + } + + // TODO: legacy; remove + this.removeClass( element, 'invalid_field' ); + + this._destroyMessage( row[ 0 ], row[ 1 ] ); + + return this; + }, + + + 'private _createMessage': function( name, message, dd, dt ) + { + // we can only generate the message if the parent row is available + if ( !( dd && dt ) ) + { + return; + } + + var msg = document.createElement( 'div' ); + msg.className = 'errmsg'; + msg.innerHTML = message; + + // append to dd + dd.appendChild( msg ); + + var height = ( msg.offsetTop + msg.offsetHeight ); + + // element does not have height until added to DOM + // set a default to ensure it appears to user + height = ( height === 0 ) + ? 45 + 'px' + : ( height + 10 ) + 'px'; + + dd.style.height = height; + dt.style.height = height; + }, + + + 'private _destroyMessage': function( dd, dt ) + { + if ( !dd ) + { + return; + } + + dd.style.height = ''; + + // note that dt may not actually exist (in fact, dd may not even be a + // dd; we should rename these variables) + dt && ( dt.style.height = '' ); + + var node; + + // search for the message node, starting with the last element (since + // the error message was appended, we're likely to find it on our first + // try) + for ( node = dd.lastChild; + node && node.className !== 'errmsg'; + node = node.previousSibling + ); + + // if we found it, then remove it + node && dd.removeChild( node ); + } +} ); diff --git a/src/ui/styler/ErrorStyler.js b/src/ui/styler/ErrorStyler.js new file mode 100644 index 0000000..714aaf6 --- /dev/null +++ b/src/ui/styler/ErrorStyler.js @@ -0,0 +1,108 @@ +/** + * Error condition field styler + * + * Copyright (C) 2016 LoVullo Associates, Inc. + * + * This file is part of liza. + * + * liza is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +var Class = require( 'easejs' ).Class, + Styler = require( './Styler' ); + + +/** + * Handle error generation and defer styling to supertype + */ +module.exports = Class( 'ErrorStyler' ) + .implement( Styler ) + .extend( +{ + /** + * Hash of error messages by field name + * @type {Object} + */ + 'private _msgs': {}, + + + /** + * Initialize error styler with a hash of error messages by field name + * + * @param {Object} msgs hash of error messages by field name + */ + 'virtual __construct': function( msgs ) + { + this._msgs = msgs; + }, + + + 'public getHooks': function( uistyler ) + { + var _self = this; + + return { + fieldError: function( context, failures, msgs ) + { + msgs = msgs || {}; + + for ( var name in failures ) + { + var msgset = ( msgs[ name ] || [] ); + + for ( var index in failures[ name ] ) + { + // if no error message was provided, fall back to one of + // the defaults + var msg = ( + msgset[ index ] + || _self._msgs[ name ] + || "Field is invalid" + ); + + _self.onFieldError( + context.getFieldByName( name, index ), + msg + ); + } + } + }, + + fieldFixed: function( context, fixed ) + { + for ( var name in fixed ) + { + for ( var index in fixed[ name ] ) + { + _self.onFieldFixed( + context.getFieldByName( name, index ) + ); + } + } + } + }; + }, + + + 'virtual protected onFieldError': function( field, msg ) + { + // do nothing by default + }, + + + 'virtual protected onFieldFixed': function( field ) + { + // do nothing by default + } +} ); diff --git a/src/ui/styler/FieldStyler.js b/src/ui/styler/FieldStyler.js new file mode 100644 index 0000000..f535e30 --- /dev/null +++ b/src/ui/styler/FieldStyler.js @@ -0,0 +1,91 @@ +/** + * Style fields using CSS + * + * Copyright (C) 2016 LoVullo Associates, Inc. + * + * This file is part of liza. + * + * liza is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +var AbstractClass = require( 'easejs' ).AbstractClass; + + +/** + * Style fields using CSS + */ +module.exports = AbstractClass( 'FieldStyler', +{ + 'abstract public getId': [], + + 'abstract public applyStyle': [ 'field', 'element', 'row' ], + + 'abstract public revokeStyle': [ 'field', 'element', 'row' ], + + + 'protected addClass': function( element, cls ) + { + if ( !element ) + { + return this; + } + + // if we are given an array, then recurse + if ( Array.isArray( element ) ) + { + for ( var i in element ) + { + this.addClass( element[ i ], cls ); + } + + return; + } + else if ( typeof element.className === 'string' ) + { + element.className += ' ' + cls; + } + + return this; + }, + + + 'protected removeClass': function( element, cls ) + { + if ( !element ) + { + return this; + } + + // if we are given an array, then recurse + if ( Array.isArray( element ) ) + { + for ( var i in element ) + { + this.removeClass( element[ i ], cls ); + } + + return; + } + else if ( typeof element.className === 'string' ) + { + // note that we use a space instead of a boundary for the character + // preceding the match due to the implementation of addClass() + element.className = element.className.replace( + new RegExp( ( ' ' + cls + '\\b' ), 'g' ), '' + ); + } + + return this; + } +} ); diff --git a/src/ui/styler/SidebarErrorStyler.js b/src/ui/styler/SidebarErrorStyler.js new file mode 100644 index 0000000..c301ab3 --- /dev/null +++ b/src/ui/styler/SidebarErrorStyler.js @@ -0,0 +1,66 @@ +/** + * Style errors in sidebar + * + * Copyright (C) 2016 LoVullo Associates, Inc. + * + * This file is part of liza. + * + * liza is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +var Class = require( 'easejs' ).Class, + ErrorStyler = require( './ErrorStyler' ); + + +/** + * Displays errors in the sidebar + * + * TODO: This is an adapter around the old system; it could use some + * refactoring. + */ +module.exports = Class( 'SidebarErrorStyler' ) + .extend( ErrorStyler, +{ + /** + * Error box in which to display errors + * @type {FormErrorBox} + */ + 'private _errbox': null, + + /** + * Ui instance + * @type {Ui} + */ + 'private _ui': null, + + + 'override __construct': function( msgs, error_box, ui ) + { + this._errbox = error_box; + this._ui = ui; + this.__super( msgs ); + }, + + + 'override protected onFieldError': function( field, msg ) + { + this._errbox.show( field.getName(), field.getIndex(), msg ); + }, + + + 'override protected onFieldFixed': function( field ) + { + this._errbox.removeError( field.getName(), field.getIndex() ); + } +} ); diff --git a/src/ui/styler/StepErrorStyler.js b/src/ui/styler/StepErrorStyler.js new file mode 100644 index 0000000..83b344c --- /dev/null +++ b/src/ui/styler/StepErrorStyler.js @@ -0,0 +1,52 @@ +/** + * Styles errors on steps + * + * Copyright (C) 2016 LoVullo Associates, Inc. + * + * This file is part of liza. + * + * liza is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +var Class = require( 'easejs' ).Class, + ErrorStyler = require( './ErrorStyler' ); + + +/** + * Trigger field styling for errors on the parent step itself + */ +module.exports = Class( 'StepErrorStyler' ) + .extend( ErrorStyler, +{ + 'private _style': null, + + + 'override __construct': function( msgs, field_style ) + { + this._style = field_style; + this.__super( msgs ); + }, + + + 'override protected onFieldError': function( field, msg ) + { + field.applyStyle( this._style, msg ); + }, + + + 'override protected onFieldFixed': function( field ) + { + field.revokeStyle( this._style ); + } +} ); diff --git a/src/ui/styler/Styler.js b/src/ui/styler/Styler.js new file mode 100644 index 0000000..bfb144e --- /dev/null +++ b/src/ui/styler/Styler.js @@ -0,0 +1,30 @@ +/** + * Styler interface + * + * Copyright (C) 2016 LoVullo Associates, Inc. + * + * This file is part of liza. + * + * liza is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +var Interface = require( 'easejs' ).Interface; + + +/** + * @todo Can be used for type hinting, but we need an actual API! + */ +module.exports = Interface( 'Styler', +{ +} );