1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-08-17 14:37:58 +00:00
seahub/media/aloha-0.22.7/lib/aloha/sidebar.js
llj 720ac28c22 [aloha] upgraded to 0.22.7 and added textcolor plugin
* textcolor: fixed plugin bugs, added translation for zh
* image: fixed default.jpg src bug
* added 'ru' support for seaf edit
* rm aloha-0.22.3 and ununsed files in aloha-0.22.7
2013-01-15 14:48:04 +08:00

1046 lines
27 KiB
JavaScript
Executable File

/* sidebar.js is part of Aloha Editor project http://aloha-editor.org
*
* Aloha Editor is a WYSIWYG HTML5 inline editing library and editor.
* Copyright (c) 2010-2012 Gentics Software GmbH, Vienna, Austria.
* Contributors http://aloha-editor.org/contribution.php
*
* Aloha Editor 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 2
* of the License, or any later version.
*
* Aloha Editor 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* As an additional permission to the GNU GPL version 2, you may distribute
* non-source (e.g., minimized or compacted) forms of the Aloha-Editor
* source code without the copy of the GNU GPL normally required,
* provided you include this license notice and a URL through which
* recipients can access the Corresponding Source.
*/
/**
* @todo: - Make the sidebars resizable using drag handles.
* - Make overlayPage setting settable from external config.
*/
define([
'aloha/core',
'jquery',
'aloha/selection',
'PubSub'
], function (
Aloha,
$,
Selection,
PubSub
) {
'use strict';
var uid = +(new Date());
// Extend jQuery easing animations.
//debugger;
if (!$.easing.easeOutExpo) {
$.extend($.easing, {
easeOutExpo: function (x, t, b, c, d) {
return (t == d) ? b + c : c * (-Math.pow(2, -10 * t / d) + 1) + b;
},
easeOutElastic: function (x, t, b, c, d) {
var m = Math,
s = 1.70158,
p = 0,
a = c;
if (!t) {
return b;
}
if ((t /= d) == 1) {
return b + c;
}
if (!p) {
p = d * 0.3;
}
if (a < m.abs(c)) {
a = c;
s = p / 4;
} else {
s = p / (2 * m.PI) * m.asin(c / a);
}
return a * m.pow(2, -10 * t) * m.sin((t * d - s) * (2 * m.PI) / p) + c + b;
}
});
}
var Panel = function Panel(opts) {
this.id = null;
this.folds = {};
this.button = null;
this.title = $('<div class="aloha-sidebar-panel-title">' + '<span class="aloha-sidebar-panel-title-arrow"></span>' + '<span class="aloha-sidebar-panel-title-text">Untitled</span>' + '</div>');
this.content = $('<div class="aloha-sidebar-panel-content">' + '<div class="aloha-sidebar-panel-content-inner">' + '<div class="aloha-sidebar-panel-content-inner-text"></div>' + '</div>' + '</div>');
this.element = null;
this.effectiveElement = null;
this.expanded = false;
this.isActive = true;
this.init(opts);
};
var Sidebar = function Sidebar(opts) {
var sidebar = this;
this.id = 'aloha-sidebar-' + (++uid);
this.panels = {};
this.container = $('<div class="aloha-ui aloha-sidebar-bar">' + '<div class="aloha-sidebar-handle">' + '<span class="aloha-sidebar-handle-icon"></span>' + '</div>' + '<div class="aloha-sidebar-inner">' + '<ul class="aloha-sidebar-panels"></ul>' + '</div>' + '</div>');
this.width = 300;
this.opened = false;
this.isOpen = false;
this.isCompletelyOpen = false;
this.settings = {
// We automatically set this to true when we are in IE, where
// rotating elements using filters causes undesirable rendering
// ugliness. Our solution is to fallback to swapping icon images.
// We set this as a sidebar property so that it can overridden by
// whoever thinks they are smarter than we are.
rotateIcons: !$.browser.msie,
overlayPage: true
};
$(function () {
if (!((typeof Aloha.settings.sidebar !== 'undefined') && Aloha.settings.sidebar.disabled)) {
sidebar.init(opts);
}
});
};
/**
* The last calculated view port height.
* @type {number}
*/
var previousViewportHeight = null;
var previousActivePanelIds = null;
$.extend(Sidebar.prototype, {
// We build as much of the sidebar as we can before appending it to DOM
// to minimize reflow.
init: function (opts) {
var that = this;
var panels;
if (typeof opts === 'object') {
panels = opts.panels;
delete opts.panels;
}
$.extend(this, opts);
if (typeof panels === 'object') {
$.each(panels, function () {
that.addPanel(this, true);
});
}
var bar = this.container;
if (this.position === 'right') {
bar.addClass('aloha-sidebar-right');
}
bar.hide().appendTo($('body')).click(function () {
that.barClicked.apply(that, arguments);
}).find('.aloha-sidebar-panels').width(this.width);
// IE7 needs us to explicitly set the container width, since it is
// unable to determine it on its own.
bar.width(this.width);
this.width = bar.width();
this.updateHeight();
this.initToggler();
this.container.css(this.position === 'right' ? 'marginRight' : 'marginLeft', -this.width);
if (this.opened) {
this.open(0);
}
this.toggleHandleIcon(this.isOpen);
this.subscribeToEvents();
$(window).resize(function () {
that.updateHeight();
that.correctHeight();
});
this.correctHeight();
},
show: function () {
this.container.css('display', 'block');
return this;
},
hide: function () {
this.container.css('display', 'none');
return this;
},
/**
* Determines the effective elements at the current selection.
* Iterates through all panels and checks whether the panel should be
* activated for any of the effective elements in the selection.
*
* @param {Aloha.RangeObject} range The current selection range.
*/
checkActivePanels: function (range) {
var effective = [];
if (typeof range !== 'undefined' && typeof range.markupEffectiveAtStart !== 'undefined') {
var l = range.markupEffectiveAtStart.length;
var i;
for (i = 0; i < l; ++i) {
effective.push($(range.markupEffectiveAtStart[i]));
}
}
var that = this;
$.each(this.panels, function () {
that.showActivePanel(this, effective);
});
this.correctHeight();
},
subscribeToEvents: function () {
var that = this;
PubSub.sub('aloha.selection.context-change', function (message) {
if (that.isOpen) {
that.checkActivePanels(message.range);
}
that.lastRange = message.range;
});
Aloha.bind('aloha-editable-deactivated', function (event, params) {
if (that.isOpen) {
that.checkActivePanels();
}
that.lastRange = null;
});
this.container.mousedown(function (e) {
e.originalEvent.stopSelectionUpdate = true;
Aloha.eventHandled = true;
});
this.container.mouseup(function (e) {
e.originalEvent.stopSelectionUpdate = true;
Aloha.eventHandled = false;
});
},
/**
* Dynamically set appropriate heights for panels.
* The height for each panel is determined by the amount of space that
* is available in the viewport and the number of panels that need to
* share that space.
*/
correctHeight: function () {
if (!this.isOpen) {
return;
}
if (!this.isCompletelyOpen) {
this.correctHeightWhenCompletelyOpen = true;
return;
}
var viewportHeight = $(window).height();
var activePanelIds = [];
var panels = [];
var panelId;
for (panelId in this.panels) {
if (this.panels.hasOwnProperty(panelId)) {
if (this.panels[panelId].isActive) {
panels.push(this.panels[panelId]);
activePanelIds.push(panelId);
}
}
}
if (0 === panels.length) {
return;
}
activePanelIds = activePanelIds.sort().join(',');
if (previousActivePanelIds === activePanelIds && previousViewportHeight === viewportHeight) {
return;
}
previousViewportHeight = viewportHeight;
previousActivePanelIds = activePanelIds;
var height = this.container.find('.aloha-sidebar-inner').height();
var remainingHeight = height - ((panels[0].title.outerHeight() + 10) * panels.length);
var panel;
var targetHeight;
var panelInner;
var panelText;
var undone;
var toadd = 0;
var math = Math;
var j;
while (panels.length > 0 && remainingHeight > 0) {
remainingHeight += toadd;
toadd = 0;
undone = [];
for (j = panels.length - 1; j >= 0; --j) {
panel = panels[j];
panelInner = panel.content.find('.aloha-sidebar-panel-content-inner');
targetHeight = math.min(
panelInner.height('auto').height(),
math.floor(remainingHeight / (j + 1))
);
panelInner.height(targetHeight);
remainingHeight -= targetHeight;
panelText = panelInner.find('.aloha-sidebar-panel-content-inner-text');
if (panelText.height() > targetHeight) {
undone.push(panel);
toadd += targetHeight;
panelInner.css({
'overflow-x': 'hidden',
'overflow-y': 'scroll'
});
} else {
panelInner.css('overflow-y', 'hidden');
}
if (panel.expanded) {
panel.expand();
}
}
panels = undone;
}
},
/**
* Checks whether this panel should be activated (ie: made visible) for
* any of the elements specified in a given list of elements.
*
* We have to add a null object to the list of elements to allow us to
* check whether the panel should be visible when we have no effective
* elements in the current selection
*
* @param {object} panel The Panel object we will test
* @param {Array.<jQuery.<HTMLElement>>} elements The effective
* elements, any of
* which may activate
* the panel.
*/
showActivePanel: function (panel, elements) {
elements.push(null);
var li = panel.content.parent('li');
var activeOn = panel.activeOn;
var effective = $();
var count = 0;
var j = elements.length;
var i;
for (i = 0; i < j; ++i) {
if (activeOn(elements[i])) {
++count;
if (elements[i]) {
$.merge(effective, elements[i]);
}
}
}
if (count) {
panel.activate(effective);
} else {
panel.deactivate();
}
},
/**
* Sets up the functionality, event listeners, and animation of the
* sidebar handle
*/
initToggler: function () {
var that = this;
var bar = this.container;
var icon = bar.find('.aloha-sidebar-handle-icon');
var toggledClass = 'aloha-sidebar-toggled';
var bounceTimer;
var isRight = (this.position === 'right');
if (this.opened) {
this.rotateHandleArrow(isRight ? 0 : 180, 0);
}
// configure the position of the sidebar handle
$(function () {
if (typeof Aloha.settings.sidebar !== 'undefined' && Aloha.settings.sidebar.handle && Aloha.settings.sidebar.handle.top) {
$(bar.find('.aloha-sidebar-handle'))[0].style.top = Aloha.settings.sidebar.handle.top;
}
});
bar.find('.aloha-sidebar-handle').click(function () {
if (bounceTimer) {
clearInterval(bounceTimer);
}
icon.stop().css('marginLeft', 4);
if (that.isOpen) {
$(this).removeClass(toggledClass);
that.close();
that.isOpen = false;
} else {
$(this).addClass(toggledClass);
that.open();
that.isOpen = true;
}
}).hover(function () {
var flag = that.isOpen ? -1 : 1;
if (bounceTimer) {
clearInterval(bounceTimer);
}
icon.stop();
$(this).stop().animate(
isRight ? {
marginLeft: '-=' + (flag * 5)
} : {
marginRight: '-=' + (flag * 5)
},
200
);
bounceTimer = setInterval(function () {
flag *= -1;
icon.animate(
isRight ? {
left: '-=' + (flag * 4)
} : {
right: '-=' + (flag * 4)
},
300
);
}, 300);
}, function () {
if (bounceTimer) {
clearInterval(bounceTimer);
}
icon.stop().css(isRight ? 'left' : 'right', 5);
$(this).stop().animate(
isRight ? {
marginLeft: 0
} : {
marginRight: 0
},
600,
'easeOutElastic'
);
});
},
/**
* Rounds the top corners of the first visible panel, and the bottom
* corners of the last visible panel elements in the panels ul list.
* @deprecated
* @fixme: css3
*/
roundCorners: function () {
var bar = this.container;
var lis = bar.find('.aloha-sidebar-panels>li:not(.aloha-sidebar-deactivated)');
var topClass = 'aloha-sidebar-panel-top';
var bottomClass = 'aloha-sidebar-panel-bottom';
bar.find('.aloha-sidebar-panel-top, .aloha-sidebar-panel-bottom').removeClass(topClass).removeClass(bottomClass);
lis.first().find('.aloha-sidebar-panel-title').addClass(topClass);
lis.last().find('.aloha-sidebar-panel-content').addClass(bottomClass);
},
/**
* Updates the height of the inner div of the sidebar. This is done
* whenever the viewport is resized.
*/
updateHeight: function () {
var h = $(window).height();
this.container.height(h).find('.aloha-sidebar-inner').height(h);
},
/**
* Delegate all sidebar onclick events to the container.
* Then use handleBarclick method until we bubble up to the first
* significant element that we can interact with.
*/
barClicked: function (ev) {
this.handleBarclick($(ev.target));
},
/**
* We handle all click events on the sidebar from here--dispatching
* calls to which ever methods that should be invoked for the each
* interaction.
*/
handleBarclick: function (el) {
if (el.hasClass('aloha-sidebar-panel-title')) {
this.togglePanel(el);
} else if (!el.hasClass('aloha-sidebar-panel-content') && !el.hasClass('aloha-sidebar-handle') && !el.hasClass('aloha-sidebar-bar')) {
this.handleBarclick(el.parent());
}
},
getPanelById: function (id) {
return this.panels[id];
},
getPanelByElement: function (el) {
var li = (el[0].tagName === 'LI') ? el : el.parent('li');
return this.getPanelById(li[0].id);
},
togglePanel: function (el) {
this.getPanelByElement(el).toggle();
},
/**
* Animation to rotate the sidebar arrow
*
* @param {number} angle The angle two which the arrow should rotate
* (0 or 180).
* @param {number|String} duration (Optional) How long the animation
* should play for.
*/
rotateHandleIcon: function (angle, duration) {
var arr = this.container.find('.aloha-sidebar-handle-icon');
arr.animate({
angle: angle
}, {
duration: (typeof duration === 'number' || typeof duration === 'string') ? duration : 500,
easing: 'easeOutExpo',
step: function (val, fx) {
arr.css({
'-o-transform': 'rotate(' + val + 'deg)',
'-webkit-transform': 'rotate(' + val + 'deg)',
'-moz-transform': 'rotate(' + val + 'deg)',
'-ms-transform': 'rotate(' + val + 'deg)'
// We cannot use Microsoft Internet Explorer filters
// because Microsoft Internet Explore 8 does not support
// Microsoft Internet Explorer filters correctly. It
// breaks the layout
// filter : 'progid:DXImageTransform.Microsoft.BasicImage(rotation=' + (angle / 90) + ')'
});
}
});
},
/**
* Sets the handle icon to the "i am opened, click me to close the
* sidebar" state, or vice versa. The direction of the arrow depends
* on whether the sidebar is on the left or right, and whether it is
* in an opened state or not.
*
* @param {boolean} isOpen Whether or not the sidebar is in the opened
* state.
*/
toggleHandleIcon: function (isOpen) {
var isPointingLeft = (this.position === 'right') ^ isOpen;
if (this.settings.rotateIcons) {
this.rotateHandleIcon(isPointingLeft ? 180 : 0, 0);
} else {
var icon = this.container.find('.aloha-sidebar-handle-icon');
if (isPointingLeft) {
icon.addClass('aloha-sidebar-handle-icon-left');
} else {
icon.removeClass('aloha-sidebar-handle-icon-left');
}
}
},
/**
* Slides the sidebar into view
*/
open: function (duration, callback) {
if (this.isOpen) {
return this;
}
var isRight = (this.position === 'right');
var anim = isRight ? {
marginRight: 0
} : {
marginLeft: 0
};
var sidebar = this;
this.toggleHandleIcon(true);
this.container.animate(anim, (typeof duration === 'number' || typeof duration === 'string') ? duration : 500, 'easeOutExpo');
if (!this.settings.overlayPage) {
$('body').animate(
isRight ? {
marginRight: '+=' + this.width
} : {
marginLeft: '+=' + this.width
},
500,
'easeOutExpo',
function () {
sidebar.isCompletelyOpen = true;
if (sidebar.correctHeightWhenCompletelyOpen) {
sidebar.correctHeight();
}
}
);
}
this.isOpen = true;
this.correctHeight();
if (this.lastRange) {
this.checkActivePanels(this.lastRange);
}
$('body').trigger('aloha-sidebar-opened', this);
return this;
},
/**
* Slides that sidebar out of view.
*/
close: function (duration, callback) {
if (!this.isOpen) {
return this;
}
var isRight = (this.position === 'right');
var anim = isRight ? {
marginRight: -this.width
} : {
marginLeft: -this.width
};
this.toggleHandleIcon(false);
this.container.animate(anim, (typeof duration === 'number' || typeof duration === 'string') ? duration : 500, 'easeOutExpo');
if (!this.settings.overlayPage) {
$('body').animate(
isRight ? {
marginRight: '-=' + this.width
} : {
marginLeft: '-=' + this.width
},
500,
'easeOutExpo'
);
}
this.isOpen = false;
this.isCompletelyOpen = false;
return this;
},
/**
* Activates the given panel and passes to it the given element as the
* the effective that we want it to think activated it.
*
* @param {object|String} panel Panel instance or the id of a panel
* object.
* @param {jQuery} element Element to pass to the panel as effective
* element (the element that activated it).
*/
activatePanel: function (panel, element) {
if (typeof panel === 'string') {
panel = this.getPanelById(panel);
}
if (panel) {
panel.activate(element);
}
this.roundCorners();
return this;
},
/**
* Invokes the expand method for the given panel so that it expands its
* height to display its contents
*
* @param {object|String} panel Panel instance or the id of a panel
* object.
* @param {funtion} callback
*/
expandPanel: function (panel, callback) {
if (typeof panel === 'string') {
panel = this.getPanelById(panel);
}
if (panel) {
panel.expand(callback);
}
return this;
},
/**
* Collapses the panel contents by invoking the given panel's collapse
* method.
*
* @param {object|String} panel Panel instance or the id of a panel
* object.
* @param {funtion} callback
*/
collapsePanel: function (panel, callback) {
if (typeof panel === 'string') {
panel = this.getPanelById(panel);
}
if (panel) {
panel.collapse(callback);
}
return this;
},
/**
* Adds a panel to this sidebar instance.
* We try and build as much of the panel DOM as we can before inserting
* it into the DOM in order to reduce reflow.
*
* @param {object} panel - either a panel instance or an associative
* array containing settings for the construction
* of a new panel.
* @param {boolean} deferRounding - (Optional) If true, the rounding-off
* of the top most and bottom most panels
* will not be automatically done. Set
* this to true when adding a lot of panels
* at once.
* @return {object} The newly created panel.
*/
addPanel: function (panel, deferRounding) {
if (!(panel instanceof Panel)) {
if (!panel.width) {
panel.width = this.width;
}
panel.sidebar = this;
panel = new Panel(panel);
}
this.panels[panel.id] = panel;
this.container.find('.aloha-sidebar-panels').append(panel.element);
this.checkActivePanels(Selection.getRangeObject());
return panel;
}
});
// ------------------------------------------------------------------------
// Panel prototype
// ------------------------------------------------------------------------
$.extend(Panel.prototype, {
init: function (opts) {
this.setTitle(opts.title).setContent(opts.content);
delete opts.title;
delete opts.content;
$.extend(this, opts);
if (!this.id) {
this.id = 'aloha-sidebar-' + (++uid);
}
var li = this.element = $('<li id="' + this.id + '">').append(this.title, this.content);
if (this.expanded) {
this.content.height('auto');
}
this.toggleTitleIcon(this.expanded);
this.coerceActiveOn();
// Disable text selection on title element.
this.title.attr('unselectable', 'on').css('-moz-user-select', 'none').each(function () {
this.onselectstart = function () {
return false;
};
});
if (typeof this.onInit === 'function') {
this.onInit.apply(this);
}
},
/**
* @param {boolean} isExpanded Whether or not the panel is in an
* expanded state.
*/
toggleTitleIcon: function (isExpanded) {
if (this.sidebar.settings.rotateIcons) {
this.rotateTitleIcon(isExpanded ? 90 : 0);
} else {
var icon = this.title.find('.aloha-sidebar-panel-title-arrow');
if (isExpanded) {
icon.addClass('aloha-sidebar-panel-title-arrow-down');
} else {
icon.removeClass('aloha-sidebar-panel-title-arrow-down');
}
}
},
/**
* Normalizes the activeOn property into a predicate function.
*/
coerceActiveOn: function () {
if (typeof this.activeOn !== 'function') {
var activeOn = this.activeOn;
this.activeOn = (function () {
var typeofActiveOn = typeof activeOn,
fn;
if (typeofActiveOn === 'boolean') {
fn = function () {
return activeOn;
};
} else if (typeofActiveOn === 'undefined') {
fn = function () {
return true;
};
} else if (typeofActiveOn === 'string') {
fn = function (el) {
return el ? el.is(activeOn) : false;
};
} else {
fn = function () {
return false;
};
}
return fn;
}());
}
},
/**
* Activates (displays) this panel.
*/
activate: function (effective) {
this.isActive = true;
this.content.parent('li').show().removeClass('aloha-sidebar-deactivated');
this.effectiveElement = effective;
if (typeof this.onActivate === 'function') {
this.onActivate.call(this, effective);
}
},
/**
* Hides this panel.
*/
deactivate: function () {
if (!this.isActive) {
return;
}
this.isActive = false;
this.content.parent('li').hide().addClass('aloha-sidebar-deactivated');
this.effectiveElement = null;
},
toggle: function () {
if (this.expanded) {
this.collapse();
} else {
this.expand();
}
},
/**
* Displays the panel's contents.
*/
expand: function (callback) {
var that = this;
var el = this.content;
var old_h = el.height();
var new_h = el.height('auto').height();
el.height(old_h).stop().animate(
{height: new_h},
500,
'easeOutExpo',
function () {
if (typeof callback === 'function') {
callback.call(that);
}
}
);
this.element.removeClass('collapsed');
this.toggleTitleIcon(true);
this.expanded = true;
return this;
},
/**
* Hides the panel's contents--leaving only it's header.
*/
collapse: function (duration, callback) {
var that = this;
this.element.addClass('collapsed');
this.content.stop().animate(
{ height: 5 },
250,
'easeOutExpo',
function () {
if (typeof callback === 'function') {
callback.call(that);
}
}
);
this.toggleTitleIcon(false);
this.expanded = false;
return this;
},
/**
* May also be called by the Sidebar to update title of panel
*
* @param {string} html Markup string, DOM object, or jQuery object.
*/
setTitle: function (html) {
this.title.find('.aloha-sidebar-panel-title-text').html(html);
return this;
},
/**
* May also be called by the Sidebar to update content of panel
*
* @param {string|jQuery.<HTMLElement>|HTMLElement} html Markup string,
* DOM object, or
* jQuery object.
*/
setContent: function (html) {
// We do this so that empty panels don't appear collapsed
if (!html || html === '') {
html = '&nbsp;';
}
this.content.find('.aloha-sidebar-panel-content-inner-text').html(html);
return this;
},
rotateTitleIcon: function (angle, duration) {
var arr = this.title.find('.aloha-sidebar-panel-title-arrow');
arr.animate({
angle: angle
}, {
duration: (typeof duration === 'number') ? duration : 500,
easing: 'easeOutExpo',
step: function (val, fx) {
arr.css({
'-o-transform': 'rotate(' + val + 'deg)',
'-webkit-transform': 'rotate(' + val + 'deg)',
'-moz-transform': 'rotate(' + val + 'deg)',
'-ms-transform': 'rotate(' + val + 'deg)'
// filter : 'progid:DXImageTransform.Microsoft.BasicImage(rotation=' + (angle / 90) + ')'
});
}
});
},
/**
* Walks up the ancestors chain for the given effective element, and
* renders subpanels using the specified renderer function.
*
* @param {jQuery.<HTMLElement>} effective The effective element, whose
* lineage we want to render.
* @param {function} renderer (Optional) function that will render each
* element in the parental
* lineage of the effective
* element.
*/
renderEffectiveParents: function (effective, renderer) {
var el = effective.first();
var content = [];
var path = [];
var activeOn = this.activeOn;
var l;
var pathRev;
while (el.length > 0 && !el.is('.aloha-editable')) {
if (activeOn(el)) {
path.push('<span>' + el[0].tagName.toLowerCase() + '</span>');
l = path.length;
pathRev = [];
while (l--) {
pathRev.push(path[l]);
}
content.push(
'<div class="aloha-sidebar-panel-parent">'
+ '<div class="aloha-sidebar-panel-parent-path">'
+ pathRev.join('')
+ '</div>'
+ '<div class="aloha-sidebar-panel-parent-content'
+ 'aloha-sidebar-opened">'
+ ((typeof renderer === 'function') ? renderer(el) : '----') + '</div>' + '</div>'
);
}
el = el.parent();
}
this.setContent(content.join(''));
$('.aloha-sidebar-panel-parent-path').click(function () {
var $content = $(this).parent().find('.aloha-sidebar-panel-parent-content');
if ($content.hasClass('aloha-sidebar-opened')) {
$content.hide().removeClass('aloha-sidebar-opened');
} else {
$content.show().addClass('aloha-sidebar-opened');
}
});
this.content.height('auto').find('.aloha-sidebar-panel-content-inner').height('auto');
}
});
var left = new Sidebar({
position: 'left',
width: 250 // TODO define in config
});
var right = new Sidebar({
position: 'right',
width: 250 // TODO define in config
});
Aloha.Sidebar = {
left: left,
right: right
};
return Aloha.Sidebar;
});