From 642345fd53faabd9183bef1a7667bdb7956d27f7 Mon Sep 17 00:00:00 2001 From: Petr Vobornik Date: Mon, 25 Nov 2013 13:56:27 +0100 Subject: webui: standalone facet `facet.Facet` is a new base class for facets. It doesn't have any dependencies on entities so it's usable for general purpose facets, e.g., future API browser, load facet or login facet. https://fedorahosted.org/freeipa/ticket/3903 Reviewed-By: Adam Misnyovszki --- install/ui/src/freeipa/facets/Facet.js | 329 +++++++++++++++++++++++++++++++++ 1 file changed, 329 insertions(+) create mode 100644 install/ui/src/freeipa/facets/Facet.js (limited to 'install/ui/src/freeipa/facets/Facet.js') diff --git a/install/ui/src/freeipa/facets/Facet.js b/install/ui/src/freeipa/facets/Facet.js new file mode 100644 index 000000000..8b55cec12 --- /dev/null +++ b/install/ui/src/freeipa/facets/Facet.js @@ -0,0 +1,329 @@ +/* Authors: + * Petr Vobornik + * + * Copyright (C) 2013 Red Hat + * see file 'COPYING' for use and warranty information + * + * This program 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 . +*/ + +define(['dojo/_base/declare', + 'dojo/_base/lang', + 'dojo/Evented', + 'dojo/dom-construct', + 'dojo/dom-class', + 'dojo/on', + '../builder', + '../facet', + '../ipa', // for util functions + '../jquery', + '../text', + '../widgets/ContainerMixin' + ], + function(declare, lang, Evented, construct, dom_class, + on, builder, mod_facet, IPA, $, text, ContainerMixin) { + + /** + * Base class of Facet + * + * A future replacement/base class for `facet.facet` + * + * @class facets.Facet + * @mixins widgets.ContainerMixin + */ + var Facet = declare([Evented, ContainerMixin], { + + /** + * Name of preferred facet container + * + * Leave unset to use default container. + * @property {string} + */ + preferred_container: null, + + /** + * Facet name + * @property {string} + */ + name: null, + + /** + * Facet label + * @property {string} + */ + label: null, + + /** + * Facet title + * @property {string} + */ + title: null, + + /** + * Facet element's CSS class + * @property {string} + */ + 'class': null, + + /** + * Class which tells that the facet should be visible + * @property {string} + */ + active_class: 'active', + + /** + * dom_node of container + * Suppose to contain dom_node of this and other facets. + * @property {jQuery} + */ + container_node: null, + + /** + * dom_node which contains all content of this Facet. + * @property {HTMLElement} + * @readonly + */ + dom_node: null, + + /** + * DOM node which serves as container for child widgets + * @property {HTMLElement} + */ + children_node: null, + + /** + * Redirection target information. + * + * Can be facet and/or entity name. + * @property {Object} + * @param {string} entity entity name + * @param {string} facet facet name + */ + redirect_info: null, + + /** + * Public state + * @property {facet.FacetState} + * @protected + */ + state: null, + + /** + * Checks if two objects has the same properties with equal values. + * + * @param {Object} a + * @param {Object} b + * @return {boolean} `a` and `b` are value-equal + * @protected + */ + state_diff: function(a, b) { + var diff = false; + var checked = {}; + + var check_diff = function(a, b, skip) { + + var same = true; + skip = skip || {}; + + for (var key in a) { + if (a.hasOwnProperty(key) && !(key in skip)) { + var va = a[key]; + var vb = b[key]; + if (lang.isArray(va)) { + if (IPA.array_diff(va,vb)) { + same = false; + skip[a] = true; + break; + } + } else { + if (va != vb) { + same = false; + skip[a] = true; + break; + } + } + } + } + return !same; + }; + + diff = check_diff(a,b, checked); + diff = diff || check_diff(b,a, checked); + return diff; + }, + + /** + * Reset facet state to supplied + * + * @param {Object} state state to set + */ + reset_state: function(state) { + this.state.reset(state); + }, + + /** + * Get copy of current state + * + * @return {Object} state + */ + get_state: function() { + return this.state.clone(); + }, + + /** + * Merges state into current and notifies it. + * + * @param {Object} state object to merge into current state + */ + set_state: function(state) { + this.state.set(state); + }, + + /** + * Handle state set + * @param {Object} old_state + * @param {Object} state + * @protected + */ + on_state_set: function(old_state, state) { + this.on_state_change(state); + }, + + /** + * Handle state change + * @param {Object} state + * @protected + */ + on_state_change: function(state) { + + this._notify_state_change(state); + }, + + /** + * Fires `facet-state-change` event with given state as event parameter. + * + * @fires facet-state-change + * @protected + * @param {Object} state + */ + _notify_state_change: function(state) { + this.emit('facet-state-change', { + facet: this, + state: state + }); + }, + + /** + * Create facet's HTML representation + * NOTE: may be renamed to render + */ + create: function() { + + if (this.dom_node) { + construct.empty(this.dom_node); + } else { + this.dom_node = construct.create('div', { + 'class': 'facet', + name: this.name, + 'data-name': this.name + }); + } + if (this.container_node) { + construct.place(this.dom_node, this.container_node); + } + this.children_node = this.dom_node; + return this.dom_node; + }, + + /** + * Render child widgets + */ + render_children: function() { + var widgets = this.get_widgets(); + + for (var i=0;i').appendTo(this.children_node); + widget.create(container); + } + } + }, + + /** + * Show facet + * + * - mark itself as active facet + */ + show: function() { + + if (!this.dom_node) { + this.create(); + this.render_children(); + } + + dom_class.add(this.dom_node, 'active-facet'); + this.emit('show', { source: this }); + }, + + /** + * Un-mark itself as active facet + */ + hide: function() { + dom_class.remove(this.dom_node, 'active-facet'); + this.emit('hide', { source: this }); + }, + + /** + * Initializes facet + * + * Facet builder should run this method after instantiation. + * @param {Object} spec + */ + init: function(spec) { + + this.add_widgets(spec.widgets || []); + }, + + can_leave: function() { + return true; + }, + + show_leave_dialog: function(callback) { + window.console.warning('Unimplemented'); + }, + + /** Constructor */ + constructor: function(spec) { + + this.preferred_container = spec.preferred_container; + this.name = spec.name; + this.label = text.get(spec.label); + this.title = text.get(spec.title || spec.label); + this['class'] = spec['class']; + this.container_node = spec.container_node; + this.dom_node = spec.dom_node; + this.redirect_info = spec.redirect_info; + this.state = new mod_facet.FacetState(); + on(this.state, 'set', lang.hitch(this, this.on_state_set)); + } + }); + + return Facet; +}); \ No newline at end of file -- cgit