'use strict';
var lalalaStorage = require('lalala/modules/storage'),
storage_key = 'collapsible_pages_tree_states';
/**
* @constructor
*/
function CPT($element) {
this.$element = $element;
this.$tree_parents = this.getTreeParents();
this.states = lalalaStorage[storage_key] || [];
this.addTriggers();
this.initStates();
this.$tree_parents.on('click.collapsible_tree', '.collapsable', $.proxy(this.toggleState, this));
// Best behaviour would be to save on window unload,
// but the current storage save on unload is wrong,
// so this will be added after the storage module saves..
//$(window).unload( $.proxy(this.saveState, this) );
}
/**
* Get tree items (
's) with children
*
* It adds the target as a data attribute to the tree parent element
*
* @return {jQuery Array}
*/
CPT.prototype.getTreeParents = function() {
return this.$element.find('td.subtree').closest('tr').map(function() {
var $subtree = $(this),
$tree_parent = $(this).closest('tr').prev();
$tree_parent.data('collapsible_target', $subtree);
return $tree_parent.get();
});
};
/**
* Add trigger column to tree parent rows
*/
CPT.prototype.addTriggers = function() {
var $trigger = $(' | ');
// Add to every |
to keep table structure in balance
this.$element.find('tr').prepend( $trigger );
// Activate triggers
this.$element.find('table.subtree').each(function() {
var $subtree = $(this),
$tree_parent = $subtree.closest('tr').prev();
$tree_parent.find('.collapse')
.addClass('collapsable')
.data('tree_parent', $tree_parent);
});
};
/**
* Initialize saved states
*/
CPT.prototype.initStates = function() {
var _this = this;
// Close all
this.$tree_parents.each(function() {
var $tree_parent = $(this),
$target = $tree_parent.data('collapsible_target'),
$trigger = $tree_parent.find('.collapse');
_this.update($target, $trigger, 'close', false);
});
// Open saved states
$.each(this.states, function(idx, value) {
var $tree_parent = $('#' + value),
$target = $tree_parent.data('collapsible_target'),
$trigger = $tree_parent.find('.collapse');
_this.update($target, $trigger, 'open', false);
});
};
/**
* Update target state
*
* @param {jQuery object} $target The element to be closed
* @param {jQuery object} $trigger The trigger element
* @param {Boolean} save_state Default TRUE
*/
CPT.prototype.update = function($target, $trigger, state, save_state) {
if ( !$target ) {
console.warn('Collapsible tree: Can not find tree target');
return;
}
save_state = (typeof save_state == 'undefined') ? true : save_state;
if ( state == 'close' ) {
$target.hide();
$trigger.addClass('closed');
} else if ( state == 'open') {
$target.show();
$trigger.removeClass('closed');
} else {
console.warn('Collapsible tree: Unknown state');
return;
}
if ( save_state ) {
this.saveState();
}
};
/**
* Toggle collapsible sate
*
* @param {jQuery event} event
*/
CPT.prototype.toggleState = function(event) {
var $trigger = $(event.currentTarget),
$target = $trigger.data('tree_parent').data('collapsible_target');
if ( $target.is(':visible') ) {
this.update($target, $trigger, 'close');
} else {
this.update($target, $trigger, 'open');
}
event.preventDefault();
event.stopPropagation();
};
/**
* Save tree states by adding the closed ones into an Array
*/
CPT.prototype.saveState = function() {
var new_states = [];
this.$tree_parents.each( function() {
var $tree_parent = $(this),
$trigger = $tree_parent.find('.collapse');
if ( !$trigger.hasClass('closed') ) {
new_states.push($tree_parent.attr('id'));
}
});
lalalaStorage[storage_key] = this.states = new_states;
};
/**
* Initialize module
*/
exports.init = function() {
var $collapsible_page_trees = $('#index_tree_table_pages');
if ( $collapsible_page_trees.length < 1 ) {
return;
}
$collapsible_page_trees.each( function() {
var $this = $(this);
if ( !$this.data('collapsible_pages_tree_instance') ) {
$this.data( 'collapsible_pages_tree_instance', new CPT($this) );
}
});
};