/* --------------------------------------------------------------
collapser.js 2016-02-19
Gambio GmbH
http://www.gambio.de
Copyright (c) 2016 Gambio GmbH
Released under the GNU General Public License (Version 2)
[http://www.gnu.org/licenses/gpl-2.0.html]
--------------------------------------------------------------
*/
/**
* ## Collapser Widget
*
* This widget expands or collapses the target element. It is not visible when collapsed but visible when expanded.
*
* ### Options
*
* **Collapsed | `data-collapser-collapsed` | Boolean | Optional**
*
* Default state of the collapser. If no value is provided, it defaults to `false`.
*
* **Collapsed Icon Class | `data-collapser-collapsed_icon_class` | String | Optional**
*
* Default Font Awesome icon when the collapser is collapsed. If no value is provided, it defaults to **'fa-plus-square-o'**.
*
* **Expanded Icon Class | `data-collapser-expanded_icon_class` | String | Optional**
*
* Default Font Awesome icon when the collapser is expanded. If no value is provided, it defaults to **'fa-minus-square-o'**.
*
* **Additional Classes | `data-collapser-additional_classes` | String | Optional**
*
* Provide additional CSS-Classes which should be added. If no value is provided, it defaults to **'pull-right'**,
* which applies a CSS *'float: right'* style.
*
* **Target Selector | `data-collapser-target_selector` | String | Required**
*
* Provide the target selector, which is the element thath will be collapsed or expanded.
*
* **Parent Selector | `data-collapser-parent_selector` | String | Optional**
*
* Provide a parent selector for the collapser. It's empty by default.
*
* ### Example
*
* When the page loads, the **collapser** widget will be added to the `<div>` element.
* On click, the target selector will be shown or hidden.
*
* ```html
* <div class="headline-wrapper"
* data-gx-widget="collapser"
* data-collapser-target_selector=".content-wrapper"
* data-collapser-section="category_base_data"
* data-collapser-user_id="1"
* data-collapser-collapsed="true">
* Click This Headline
* </div>
* <div class="content-wrapper">
* Toggled content
* </div>
* ```
*
* @module Admin/Widgets/collapser
*
* @todo Make the styling for this widget (like it is on the products site) more general. Currently, the "div" element
* has to be wrapped in another "div" with specific CSS-Classes like ".gx-container" and ".frame-head".
*/
gx.widgets.module(
'collapser',
['user_configuration_service'],
function (data) {
'use strict';
// ------------------------------------------------------------------------
// VARIABLE DEFINITION
// ------------------------------------------------------------------------
var
/**
* Widget Reference
*
* @type {object}
*/
$this = $(this),
/**
* UserConfigurationService Alias
*
* @type {object}
*/
userConfigurationService = jse.libs.user_configuration_service,
/**
* Default Options for Widget
*
* @type {object}
*/
defaults = {
collapsed: false,
collapsed_icon_class: 'fa-plus-square-o',
expanded_icon_class: 'fa-minus-square-o',
additional_classes: 'pull-right',
parent_selector: '',
is_button_trigger: false
},
/**
* Final Widget Options
*
* @type {object}
*/
options = $.extend(true, {}, defaults, data),
/**
* Module Object
*
* @type {object}
*/
module = {};
// ------------------------------------------------------------------------
// PRIVATE METHODS
// ------------------------------------------------------------------------
/**
* Sets the cursor to pointer
* @private
*/
var _setMouseCursorPointer = function () {
$this.addClass('cursor-pointer').children().addClass('cursor-pointer');
};
/**
* Sets the initial visibility according to the 'collapsed' value
* @private
*/
var _setInitialVisibilityState = function () {
if (options.collapsed) {
if (options.parent_selector) {
$this.parents(options.parent_selector).next(options.target_selector).hide();
} else {
$this.next(options.target_selector).hide();
}
}
};
/**
* Creates the markup for the collapser and adds the click event handler
* @private
*/
var _createCollapser = function () {
var $button = $('<span>', {class: `collapser ${options.additional_classes}`});
var $icon = $('<i>', {class: `fa ${options.collapsed ? options.collapsed_icon_class : options.expanded_icon_class}`});
$button
.append($icon)
.appendTo($this);
if (options.is_button_trigger) {
$button.on('click', _toggleVisibilityState);
} else {
$this.on('click', _toggleVisibilityState);
}
};
/**
* Saves the current visibility state.
*
* @private
*/
var _saveVisibilityState = function () {
var collapseState = $this.find('.collapser > i.fa').hasClass(options.collapsed_icon_class);
userConfigurationService.set({
data: {
userId: options.user_id,
configurationKey: options.section + '_collapse',
configurationValue: collapseState
}
});
};
// ------------------------------------------------------------------------
// EVENT HANDLERS
// ------------------------------------------------------------------------
/**
* Toggles the visibility state and switches between plus and minus icon.
*
* @private
*/
var _toggleVisibilityState = function () {
if (options.parent_selector) {
$this.parents(options.parent_selector).next(options.target_selector).toggle();
} else {
$this.next(options.target_selector).toggle();
}
$this.find('.collapser > i.fa').toggleClass(options.collapsed_icon_class);
$this.find('.collapser > i.fa').toggleClass(options.expanded_icon_class);
_saveVisibilityState();
};
// ------------------------------------------------------------------------
// INITIALIZE
// ------------------------------------------------------------------------
/**
* Initialize method of the module, called by the engine.
*/
module.init = function (done) {
_setMouseCursorPointer();
_setInitialVisibilityState();
_createCollapser();
done();
};
// Return data to module engine
return module;
});