Skip to content

Instantly share code, notes, and snippets.

@romaninsh
Created September 19, 2018 09:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save romaninsh/b74e0570ab5db94d8f52c6147949be73 to your computer and use it in GitHub Desktop.
Save romaninsh/b74e0570ab5db94d8f52c6147949be73 to your computer and use it in GitHub Desktop.
fly-out.js
import $ from "jquery";
import debounce from 'debounce';
/**
* Singleton class.
* Flyout needs to be reload to display different
* content. This service will take care of this.
*
*/
class FlyoutService {
static getInstance() {
return this.instance;
}
constructor() {
if (!this.instance) {
this.instance = this;
this.service = {
flyout: null,
url: null,
args: null,
triggerElement: null,
triggeredActive: {element: null, css: null},
on: false,
}
}
return this.instance;
}
/**
* Initial flyout setup.
*
* @param params
*/
setFlyout(params)
{
const that = this;
this.service.flyout = $(params.selector);
this.service.url = params.url;
// add closing handler.
this.service.flyout.on('click', '.atk-flyingSidebarClose', function(){
that.closeFlyout();
});
}
/**
* Open the flyout.
* Params expected the following arguments:
* triggered : A string or jQuery object that will triggered flyout to open.
* activedCss: Either an object containing a jQuery selector with a css class or css class.
* As an Object: element: the jQuery selector within the triggered element;
* css: the css class to applying to the triggered element when flyout is open.
*
* As a css class: the css class to applied to the triggered element when flyout open.
*
* @param params The params objects.
* @returns {FlyoutService|*}
*/
openFlyout(params) {
let triggerElement = params.triggered;
if (typeof triggerElement === 'string') {
triggerElement = $(triggerElement);
}
if (triggerElement.length > 0) {
// no need to do anything if we are using the same element.
if (this.service.on && this.isSameElement(triggerElement)) {
return;
}
this.service.triggerElement = triggerElement;
//Do we need to setup css class on triggering element.
if (params.activedCSS) {
let element, css;
if (params.activedCSS instanceof Object) {
element = this.service.triggerElement.find(params.activedCSS.element);
css = params.activedCSS.css;
} else {
element = triggerElement;
css = params.activedCSS;
}
if (this.service.on) {
this.deActivated(this.service.triggeredActive.element, this.service.triggeredActive.css);
}
this.activated(element, css);
this.service.triggeredActive.element = element;
this.service.triggeredActive.css = css;
}
// do we need to load anything in this flyout.
if (this.service.url) {
//Convert our array of args to object.
//Args must be defined as data-attributeName in the triggered element.
const args = params.reloadArgs.reduce( (obj, item) => {
obj[item] = params.triggered.data(item);
return obj;
}, {});
//add url argument if pass to flyout
if (params.urlArgs !== 'undefined') {
$.extend(args, params.urlArgs);
}
this.reloadFlyout(args);
}
}
this.service.flyout.addClass('atk-visible');
this.service.on = true;
this.addCloseEvent();
return this.instance;
}
/**
* Add closing event handler to mainContainerWrapper and document.
*/
addCloseEvent(){
const that = this;
$('.atk-mainContainerWrapper').on('click.saastyFlyout', debounce(function(evt){
that.closeFlyout();
}, 300));
$(document).on('keyup.saastyFlyout', debounce(function(evt) {
if (evt.keyCode === 27) {
that.closeFlyout();
}
}, 300));
}
/**
* Compare a jQueryr element to the actual triggered element for this flyout.
*
* @param el the element to compare against.
* @returns {boolean} True when both jQuery element are equal.
*/
isSameElement(el) {
return (el.length == this.service.triggerElement.length && el.length == el.filter(this.service.triggerElement).length)
}
/**
* Removed a css class to a jQuery element.
* This should normally be your triggering flyout element.
*
* @param element
* @param css
*/
deActivated(element, css) {
element.removeClass(css);
}
/**
* Add a css class name to a jQuery element.
* This should normally be your triggering flyout element.
*
* @param element
* @param css
*/
activated(element, css) {
element.addClass(css);
}
/**
* Close flyout and cleanup.
*
* @returns {FlyoutService|*}
*/
closeFlyout() {
//remove document event.
$('.atk-mainContainerWrapper').off('click.saastyFlyout');
$(document).off('keyup.saastyFlyout');
//do the actual closing.
this.service.flyout.removeClass('atk-visible');
// clean up
if (this.service.on) {
if (this.service.triggeredActive.element && this.service.triggeredActive.element.length > 0) {
this.deActivated(this.service.triggeredActive.element, this.service.triggeredActive.css);
}
this.service.on = false;
this.service.triggeredActive = {element: null, css: null};
this.service.triggerElement = null;
this.clearFlyoutContent();
}
return this.instance;
}
/**
* Clear content.
*/
clearFlyoutContent() {
this.service.flyout.find('.atk-flyoutContent, .atk-flyoutTitle').html('');
}
/**
* Load flyout content.
*
* @param args
*/
reloadFlyout(args) {
this.clearFlyoutContent();
const context = this.service.flyout.find('.atk-flyoutLoader');
this.service.flyout.api({
on: 'now',
url: this.service.url,
data: args,
method: 'GET',
stateContext: context,
});
}
}
const flyoutService = new FlyoutService();
Object.freeze(flyoutService);
export default flyoutService;
.atk-flyingSidebar {
.transition(box-shadow .2s, left .2s);
background-color: @lightGrey;
bottom: 0;
box-shadow: 0 0 0 fade(@black, 0%);
height: ~'calc(100% - '@topMenuHeight~')';
left: 100%;
overflow-y: auto;
position: fixed;
width: @flyingSidebarWidth;
z-index: 100;
>header {
background-color: @white;
border-bottom: 1px solid @smoke;
.atk-panel {
margin-bottom: @absoluteMedium;
}
}
&.atk-visible {
box-shadow: -25px 0 50px fade(@black, 20%);
left: 50%;
}
}
.atk-flyingSidebar(id="{$_id}", class="{$_class} {$class}")
header.atk-padding--xl
.atk-flex-items--center.atk-items.atk-panel
h3.atk-noMargin.atk-expand.atk-flyoutTitle {title}{/}
.atk-items.atk-nowrap
| {editBtn}
a.atk-comment(href='javascript:void(0)' data-tooltip="{$editTip}" data-position="bottom right" data-inverted="").do-flybar-edit
i.pencil.alternate.icon
| {/editBtn}
| {deleteBtn}
a.atk-comment(href='javascript:void(0)' data-tooltip="{$deleteTip}" data-position="bottom right" data-inverted="").do-flybar-delete
i.trash.alternate.outline.icon
| {/deleteBtn}
a.atk-flyingSidebarClose.atk-comment(href='javascript:void(0)' data-tooltip="{$closeTip}" data-position="bottom right" data-inverted="")
i.times.icon
.atk-flyoutContent
| {$Content}
.atk-padding--xxl
.ui.transparent.basic.segment.atk-flyoutContent.atk-flyoutLoader
| {$Sections}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment