1559 lines
45 KiB
JavaScript
1559 lines
45 KiB
JavaScript
/*
|
|
* View framework for JamKazam.
|
|
*
|
|
* Processes proprietary attributes in markup to convert a set of HTML elements
|
|
* into the JamKazam screen layout. This module is only responsible for size
|
|
* and position. All other visual aspects should be elsewhere.
|
|
*
|
|
* See the layout-example.html file for a simple working example.
|
|
*/
|
|
(function (context, $) {
|
|
"use strict";
|
|
|
|
context.JK = context.JK || {};
|
|
|
|
// Static function to hide the 'curtain' which hides the underlying
|
|
// stuff until we can get it laid out. Called from both the main
|
|
// client as well as the landing page.
|
|
context.JK.hideCurtain = function (duration) {
|
|
context.setTimeout(function () {
|
|
$(".curtain").fadeOut(2 * duration);
|
|
}, duration);
|
|
};
|
|
|
|
context.JK.Layout = function () {
|
|
// privates
|
|
var logger = context.JK.logger;
|
|
|
|
var EVENTS = context.JK.EVENTS;
|
|
var NOT_HANDLED = "not handled";
|
|
|
|
var me = null; // Reference to this instance for context sanity.
|
|
|
|
var opts = {
|
|
headerHeight: 75,
|
|
sidebarWidth: 300,
|
|
notifyHeight: 150,
|
|
notifyGutter: 10,
|
|
collapsedSidebar: 30,
|
|
panelHeaderHeight: 36,
|
|
alwaysOpenPanelHeaderHeight: 78, // for the search bar
|
|
gutter: 60, // Margin around the whole UI
|
|
screenMargin: 0, // Margin around screens (not headers/sidebar)
|
|
gridOuterMargin: 6, // Outer margin on Grids (added to screenMargin if screen)
|
|
gridPadding: 8, // Padding around grid cells. Added to outer margin.
|
|
animationDuration: 400,
|
|
allowBodyOverflow: false, // Allow tests to disable the body-no-scroll policy
|
|
sizeOverlayToContent: false, // if true, use the size of <body> tag to decide overlay size everytime overlay is shown. should be used in non-client settings
|
|
};
|
|
|
|
var width = $(context).width();
|
|
var height = $(context).height();
|
|
var resizing = null;
|
|
var sidebarVisible = true;
|
|
var expandedPanel = null;
|
|
var previousScreen = null;
|
|
var currentScreen = null;
|
|
var currentHash = null;
|
|
|
|
var screenBindings = {};
|
|
var dialogBindings = {};
|
|
var wizardShowFunctions = {};
|
|
|
|
var openDialogs = []; // FIFO stack
|
|
|
|
var resettingHash = false;
|
|
|
|
function setup() {
|
|
requiredStyles();
|
|
hideAll();
|
|
setInitialExpandedSidebarPanel();
|
|
sizeScreens(width, height, '[layout="screen"]', true);
|
|
positionOffscreens(width, height);
|
|
$('[layout="sidebar"]').show();
|
|
$('[layout="panel"]').show();
|
|
layout();
|
|
}
|
|
|
|
function setInitialExpandedSidebarPanel() {
|
|
if (gon.global.chat_opened_by_default) {
|
|
expandedPanel = "panelChat";
|
|
} else {
|
|
expandedPanel = "panelFriends";
|
|
}
|
|
}
|
|
|
|
function layout() {
|
|
width = $(context).width();
|
|
height = $(context).height();
|
|
// TODO
|
|
// Work on naming. File is layout, class is Layout, this method
|
|
// is layout and every other method starts with 'layoutX'. Perhaps
|
|
// a little redundant?
|
|
layoutCurtain(width, height);
|
|
layoutDialogOverlay(width, height);
|
|
layoutScreens(width, height);
|
|
layoutSidebar(width, height);
|
|
layoutHeader(width, height);
|
|
layoutNotify1(width, height);
|
|
layoutNotify2(width, height);
|
|
layoutNotify3(width, height);
|
|
layoutFooter(width, height);
|
|
|
|
$(document).triggerHandler("layout_resized");
|
|
}
|
|
|
|
function layoutCurtain(screenWidth, screenHeight) {
|
|
var curtainStyle = {
|
|
position: "absolute",
|
|
width: screenWidth + "px",
|
|
height: screenHeight + "px",
|
|
};
|
|
$(".curtain").css(curtainStyle);
|
|
}
|
|
|
|
function layoutDialogOverlay(screenWidth, screenHeight) {
|
|
var style = {
|
|
position: "absolute",
|
|
width: screenWidth + "px",
|
|
height: screenHeight + "px",
|
|
};
|
|
$(".dialog-overlay").css(style);
|
|
}
|
|
|
|
function layoutScreens(screenWidth, screenHeight) {
|
|
var previousScreenSelector = '[layout-id="' + previousScreen + '"]';
|
|
var currentScreenSelector = '[layout-id="' + currentScreen + '"]';
|
|
$(currentScreenSelector).show();
|
|
|
|
var width = screenWidth - (2 * opts.gutter + 2 * opts.screenMargin);
|
|
var left = -1 * width - 100;
|
|
|
|
if (currentScreenSelector === previousScreenSelector) {
|
|
left = $(currentScreenSelector).css("left");
|
|
if (left) {
|
|
left = left.split("px")[0];
|
|
}
|
|
}
|
|
$(previousScreenSelector).animate(
|
|
{ left: left },
|
|
{ duration: opts.animationDuration, queue: false }
|
|
);
|
|
sizeScreens(screenWidth, screenHeight, '[layout="screen"]');
|
|
positionOffscreens(screenWidth, screenHeight);
|
|
positionOnscreen(screenWidth, screenHeight);
|
|
}
|
|
|
|
function sizeScreens(screenWidth, screenHeight, selector, immediate) {
|
|
var duration = opts.animationDuration;
|
|
if (immediate) {
|
|
duration = 0;
|
|
}
|
|
|
|
var width = screenWidth - (2 * opts.gutter + 2 * opts.screenMargin);
|
|
if (sidebarVisible) {
|
|
width -= opts.sidebarWidth + 2 * opts.gridPadding;
|
|
} else {
|
|
width -= opts.collapsedSidebar + 2 * opts.gridPadding;
|
|
width += opts.gutter; // Add back in the right gutter width.
|
|
}
|
|
var height =
|
|
screenHeight -
|
|
opts.headerHeight -
|
|
(2 * opts.gutter + 2 * opts.screenMargin);
|
|
var css = {
|
|
width: width,
|
|
height: height,
|
|
};
|
|
var $screens = $(selector);
|
|
$screens.animate(css, { duration: duration, queue: false });
|
|
layoutHomeScreen(width, height);
|
|
}
|
|
|
|
/**
|
|
* Postition all screens that are not the current screen.
|
|
*/
|
|
function positionOffscreens(screenWidth, screenHeight) {
|
|
var top = opts.headerHeight + opts.gutter + opts.screenMargin;
|
|
var left = -1 * (screenWidth + 2 * opts.gutter);
|
|
var $screens = $('[layout="screen"]').not(
|
|
'[layout-id="' + currentScreen + '"]'
|
|
);
|
|
$screens.css({
|
|
top: top,
|
|
left: left,
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Position the current screen
|
|
*/
|
|
function positionOnscreen(screenWidth, screenHeight, immediate) {
|
|
var duration = opts.animationDuration;
|
|
if (immediate) {
|
|
duration = 0;
|
|
}
|
|
var top = opts.headerHeight + opts.gutter + opts.screenMargin;
|
|
var left = opts.gutter + opts.screenMargin;
|
|
var $screen = $('[layout-id="' + currentScreen + '"]');
|
|
$screen.animate(
|
|
{
|
|
top: top,
|
|
left: left,
|
|
overflow: "auto",
|
|
},
|
|
duration
|
|
);
|
|
}
|
|
|
|
function layoutHomeScreen(homeScreenWidth, homeScreenHeight) {
|
|
var $grid = $("[layout-grid]");
|
|
var gridWidth = homeScreenWidth;
|
|
var gridHeight = homeScreenHeight;
|
|
$grid.css({ width: gridWidth, height: gridHeight });
|
|
var layout = $grid.attr("layout-grid");
|
|
if (!layout) return;
|
|
var gridRows = layout.split("x")[0];
|
|
var gridCols = layout.split("x")[1];
|
|
|
|
var gutterWidth = 0;
|
|
|
|
var findCardLayout;
|
|
var feedCardLayout;
|
|
|
|
$grid.find(".homecard").each(function () {
|
|
var childPosition = $(this).attr("layout-grid-position");
|
|
var childRow = childPosition.split(",")[1];
|
|
var childCol = childPosition.split(",")[0];
|
|
var childRowspan = $(this).attr("layout-grid-rows");
|
|
var childColspan = $(this).attr("layout-grid-columns");
|
|
var childLayout = me.getCardLayout(
|
|
gridWidth,
|
|
gridHeight,
|
|
gridRows,
|
|
gridCols,
|
|
childRow,
|
|
childCol,
|
|
childRowspan,
|
|
childColspan
|
|
);
|
|
|
|
if ($(this).is(".jamtrack")) {
|
|
feedCardLayout = childLayout;
|
|
} else if ($(this).is(".findsession")) {
|
|
findCardLayout = childLayout;
|
|
}
|
|
|
|
$(this).animate(
|
|
{
|
|
width: childLayout.width,
|
|
height: childLayout.height,
|
|
top: childLayout.top,
|
|
left: childLayout.left,
|
|
},
|
|
opts.animationDuration
|
|
);
|
|
});
|
|
|
|
var broadcastWidth = findCardLayout.width + feedCardLayout.width; //+ opts.gridPadding * 2;
|
|
|
|
//layoutBroadcast(broadcastWidth, findCardLayout.left);
|
|
layoutTopMessage(broadcastWidth, findCardLayout.left);
|
|
}
|
|
|
|
/**
|
|
function layoutBroadcast(width, left) {
|
|
var css = {
|
|
width:width + opts.gridPadding * 2,
|
|
left:left
|
|
}
|
|
$('[data-react-class="BroadcastHolder"]').animate(css, opts.animationDuration)
|
|
}*/
|
|
|
|
function layoutTopMessage(width, left) {
|
|
var css = {
|
|
width: width + opts.gridPadding * 2,
|
|
left: left,
|
|
};
|
|
$('[data-react-class="TopMessageHolder"]').animate(
|
|
css,
|
|
opts.animationDuration
|
|
);
|
|
}
|
|
|
|
function layoutSidebar(screenWidth, screenHeight) {
|
|
var width = opts.sidebarWidth;
|
|
var expanderHeight = $("[layout-sidebar-expander]").height();
|
|
var height =
|
|
screenHeight - opts.headerHeight - 2 * opts.gutter + expanderHeight;
|
|
var right = opts.gutter;
|
|
if (!sidebarVisible) {
|
|
// Negative right to hide most of sidebar
|
|
right = 0 - opts.sidebarWidth + opts.collapsedSidebar;
|
|
}
|
|
var top = opts.headerHeight + opts.gutter - expanderHeight;
|
|
var css = {
|
|
width: width,
|
|
height: height,
|
|
top: top,
|
|
right: right,
|
|
};
|
|
$('[layout="sidebar"]').animate(css, opts.animationDuration);
|
|
layoutPanels(width, height);
|
|
if (sidebarVisible) {
|
|
$('[layout-panel="collapsed"]').hide();
|
|
$('[layout-panel="expanded"]').show();
|
|
$('[layout-sidebar-expander="hidden"]').hide();
|
|
$('[layout-sidebar-expander="visible"]').show();
|
|
} else {
|
|
$('[layout-panel="collapsed"]').show();
|
|
$('[layout-panel="expanded"]').hide();
|
|
$('[layout-sidebar-expander="hidden"]').show();
|
|
$('[layout-sidebar-expander="visible"]').hide();
|
|
}
|
|
}
|
|
|
|
function layoutPanels(sidebarWidth, sidebarHeight) {
|
|
// TODO - don't like the accordian - poor usability. Requires longest mouse
|
|
// reach when switching panels. Probably better to do tabs.
|
|
if (!sidebarVisible) {
|
|
return;
|
|
}
|
|
var $expandedPanel = $('[layout-id="' + expandedPanel + '"]');
|
|
var $expandedPanelContents = $expandedPanel.find(
|
|
'[layout-panel="contents"]'
|
|
);
|
|
var combinedHeaderHeight =
|
|
($('[layout-panel="contents"]').length - 1) * opts.panelHeaderHeight +
|
|
opts.alwaysOpenPanelHeaderHeight;
|
|
var expanderHeight = $("[layout-sidebar-expander]").height();
|
|
var expandedPanelHeight =
|
|
sidebarHeight - (combinedHeaderHeight + expanderHeight);
|
|
$('[layout-panel="contents"]').hide();
|
|
$('[layout-panel="contents"]').css({ height: "1px" });
|
|
$expandedPanelContents.show();
|
|
$expandedPanel.triggerHandler("open");
|
|
$expandedPanelContents.animate(
|
|
{ height: expandedPanelHeight + "px" },
|
|
opts.animationDuration,
|
|
function () {
|
|
$expandedPanel.triggerHandler("fullyOpen");
|
|
}
|
|
);
|
|
}
|
|
|
|
function layoutHeader(screenWidth, screenHeight) {
|
|
var width = screenWidth - 2 * opts.gutter;
|
|
var height = opts.headerHeight - opts.gutter;
|
|
var top = opts.gutter;
|
|
var left = opts.gutter;
|
|
var css = {
|
|
width: width + "px",
|
|
height: height + "px",
|
|
top: top + "px",
|
|
left: left + "px",
|
|
};
|
|
$('[layout="header"]').css(css);
|
|
}
|
|
|
|
function layoutNotify1(screenWidth, screenHeight) {
|
|
var $notify1 = $('[layout="notify1"]');
|
|
//var nHeight = $notify1.height();
|
|
var notifyStyle = {
|
|
bottom: "0px",
|
|
position: "fixed",
|
|
padding: "20px",
|
|
};
|
|
$notify1.css(notifyStyle);
|
|
}
|
|
|
|
function layoutNotify2(screenWidth, screenHeight) {
|
|
var $notify1 = $('[layout="notify1"]');
|
|
var $notify2 = $('[layout="notify2"]');
|
|
var nHeight = $notify1.height();
|
|
var notifyStyle = {
|
|
bottom: (nHeight + 41).toString() + "px",
|
|
position: "fixed",
|
|
padding: "20px",
|
|
};
|
|
$notify2.css(notifyStyle);
|
|
}
|
|
|
|
function layoutNotify3(screenWidth, screenHeight) {
|
|
var $notify1 = $('[layout="notify1"]');
|
|
var $notify2 = $('[layout="notify2"]');
|
|
var $notify3 = $('[layout="notify3"]');
|
|
var nHeight1 = $notify1.height();
|
|
var nHeight2 = $notify2.height();
|
|
var notifyStyle = {
|
|
bottom: (nHeight1 + nHeight2 + 41 + 41).toString() + "px",
|
|
position: "fixed",
|
|
padding: "20px",
|
|
};
|
|
$notify3.css(notifyStyle);
|
|
}
|
|
|
|
function layoutFooter(screenWidth, screenHeight) {
|
|
if (!opts.layoutFooter) {
|
|
return;
|
|
}
|
|
var $footer = $("#footer");
|
|
$footer.show();
|
|
var nHeight = $footer.height();
|
|
var footerStyle = {
|
|
top: screenHeight - 80 + "px",
|
|
};
|
|
var width = screenWidth - (2 * opts.gutter + 2 * opts.screenMargin);
|
|
var left = -1 * width - 100;
|
|
$footer.animate(
|
|
{ left: opts.gutter, width: width, top: screenHeight - 78 + "px" },
|
|
opts.animationDuration
|
|
);
|
|
}
|
|
|
|
function requiredLayoutStyles() {
|
|
var layoutStyle = {
|
|
position: "absolute",
|
|
margin: "0px",
|
|
padding: "0px",
|
|
};
|
|
$("[layout]").css(layoutStyle);
|
|
// JW: Setting z-index of notify to 1001, so it will appear above the dialog overlay.
|
|
// This allows dialogs to use the notification.
|
|
$('[layout="notify"]').css({ "z-index": "1001", padding: "20px" });
|
|
$('[layout="panel"]').css({ position: "relative" });
|
|
var $headers = $('[layout-panel="expanded"] [layout-panel="header"]');
|
|
context._.each($headers, function ($header) {
|
|
$header = $($header);
|
|
var isAlwaysOpenHeader = $header.is(".always-open");
|
|
$header.css({
|
|
margin: "0px",
|
|
padding: "0px",
|
|
height:
|
|
(isAlwaysOpenHeader
|
|
? opts.alwaysOpenPanelHeaderHeight
|
|
: opts.panelHeaderHeight) + "px",
|
|
});
|
|
});
|
|
$("[layout-grid]").css({
|
|
position: "relative",
|
|
});
|
|
$("[layout-grid]").children().css({
|
|
position: "absolute",
|
|
});
|
|
}
|
|
|
|
function requiredStyles() {
|
|
var bodyStyle = {
|
|
margin: "0px",
|
|
padding: "0px",
|
|
overflow: "hidden",
|
|
};
|
|
if (opts.allowBodyOverflow) {
|
|
delete bodyStyle.overflow;
|
|
}
|
|
$("body").css(bodyStyle);
|
|
|
|
requiredLayoutStyles();
|
|
|
|
var curtainStyle = {
|
|
position: "absolute",
|
|
margin: "0px",
|
|
padding: "0px",
|
|
overflow: "hidden",
|
|
zIndex: 100,
|
|
};
|
|
$(".curtain").css(curtainStyle);
|
|
}
|
|
|
|
function hideAll() {
|
|
$("[layout]").hide();
|
|
$('[layout="header"]').show();
|
|
}
|
|
|
|
function showSidebar() {
|
|
sidebarVisible = true;
|
|
layout();
|
|
}
|
|
|
|
function hideSidebar() {
|
|
sidebarVisible = false;
|
|
layout();
|
|
}
|
|
|
|
function toggleSidebar() {
|
|
if (sidebarVisible) {
|
|
hideSidebar();
|
|
} else {
|
|
showSidebar();
|
|
}
|
|
}
|
|
|
|
function hideDialogs() {
|
|
// TODO - may need dialogEvents here for specific dialogs.
|
|
$('[layout="dialog"]').hide();
|
|
$(".dialog-overlay").hide();
|
|
}
|
|
|
|
function tabClicked(evt) {
|
|
evt.preventDefault();
|
|
var destination = $(evt.currentTarget).attr("tab-target");
|
|
$("[tab-target]").removeClass("selected");
|
|
$(evt.currentTarget).addClass("selected");
|
|
$(".tab").hide();
|
|
$('[tab-id="' + destination + '"]').show();
|
|
}
|
|
|
|
function linkClicked(evt) {
|
|
evt.preventDefault();
|
|
var $currentTarget = $(evt.currentTarget);
|
|
|
|
// allow links to be disabled
|
|
if ($currentTarget.hasClass("disabled")) {
|
|
return;
|
|
}
|
|
|
|
var destination = $(evt.currentTarget).attr("layout-link");
|
|
var $destination = $('[layout-id="' + destination + '"]');
|
|
|
|
//force user to the new site if they click on the jamtrack tile
|
|
if(destination === "jamtrack") {
|
|
var urlToOpen = gon.spa_origin_url + '/jamtracks';
|
|
if(gon.isNativeClient) {
|
|
context.JK.popExternalLink(urlToOpen);
|
|
return;
|
|
}else{
|
|
window.open(urlToOpen, '_blank');
|
|
return;
|
|
}
|
|
}
|
|
|
|
var destinationType = $destination.attr("layout");
|
|
if (destinationType === "screen") {
|
|
if (
|
|
!context.JK.currentUserId &&
|
|
!$destination.is(".no-login-required")
|
|
) {
|
|
// there is no user, and this item does not support 'no-login', so warn user
|
|
showDialog("login-required-dialog");
|
|
return;
|
|
}
|
|
context.location = "/client#/" + destination;
|
|
} else if (destinationType === "dialog") {
|
|
showDialog(destination);
|
|
}
|
|
}
|
|
|
|
function close(evt) {
|
|
var $target = $(evt.currentTarget).closest("[layout]");
|
|
var layoutId = $target.attr("layout-id");
|
|
var isDialog = $target.attr("layout") === "dialog";
|
|
if (isDialog) {
|
|
closeDialog(layoutId);
|
|
} else {
|
|
$target.hide();
|
|
}
|
|
return false;
|
|
}
|
|
|
|
function cancel(evt) {
|
|
var $target = $(evt.currentTarget).closest("[layout]");
|
|
var layoutId = $target.attr("layout-id");
|
|
var isDialog = $target.attr("layout") === "dialog";
|
|
if (isDialog) {
|
|
cancelDialog(layoutId);
|
|
} else {
|
|
// ?
|
|
logger.warn("unable to handle cancel layout-action for %o", $target);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
function cancelDialog(dialog) {
|
|
logger.debug("cancelling dialog: " + dialog);
|
|
var $dialog = $('[layout-id="' + dialog + '"]');
|
|
var result = dialogEvent(dialog, "onCancel");
|
|
if (result !== false) {
|
|
closeDialog(dialog, true);
|
|
} else {
|
|
logger.debug("dialog refused cancel");
|
|
}
|
|
}
|
|
|
|
function closeDialog(dialog, canceled) {
|
|
logger.debug("closing dialog: " + dialog);
|
|
var $dialog = $('[layout-id="' + dialog + '"]');
|
|
dialogEvent(dialog, "beforeHide");
|
|
var $overlay = $(".dialog-overlay");
|
|
unstackDialogs($overlay);
|
|
$dialog.hide();
|
|
$dialog.triggerHandler(EVENTS.DIALOG_CLOSED, {
|
|
name: dialog,
|
|
dialogCount: openDialogs.length,
|
|
result: $dialog.data("result"),
|
|
canceled: canceled,
|
|
});
|
|
$(context).triggerHandler(EVENTS.DIALOG_CLOSED, {
|
|
name: dialog,
|
|
dialogCount: openDialogs.length,
|
|
result: $dialog.data("result"),
|
|
canceled: canceled,
|
|
});
|
|
dialogEvent(dialog, "afterHide");
|
|
$.btOffAll(); // add any prod bubbles if you close a dialog
|
|
}
|
|
|
|
function screenProperty(screen, property) {
|
|
if (screen && screen in screenBindings) {
|
|
return screenBindings[screen][property];
|
|
}
|
|
return null;
|
|
}
|
|
function screenEvent(screen, evtName, data) {
|
|
if (screen && screen in screenBindings) {
|
|
if (evtName in screenBindings[screen]) {
|
|
return screenBindings[screen][evtName].call(me, data);
|
|
}
|
|
}
|
|
return NOT_HANDLED;
|
|
}
|
|
|
|
function dialogEvent(dialog, evtName, data) {
|
|
if (dialog && dialog in dialogBindings) {
|
|
if (evtName in dialogBindings[dialog]) {
|
|
return dialogBindings[dialog][evtName].call(me, data);
|
|
}
|
|
}
|
|
return NOT_HANDLED;
|
|
}
|
|
|
|
function activeElementEvent(evtName, data) {
|
|
var result = {};
|
|
var currDialog = currentDialog();
|
|
if (currDialog) {
|
|
result.dialog = dialogEvent(
|
|
currDialog.attr("layout-id"),
|
|
evtName,
|
|
data
|
|
);
|
|
}
|
|
|
|
if (currentScreen) {
|
|
result.screen = screenEvent(currentScreen, evtName, data);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
function onHashChange(e, postFunction) {
|
|
if (currentHash == context.location.hash) {
|
|
return;
|
|
}
|
|
|
|
if (resettingHash) {
|
|
resettingHash = false;
|
|
e.preventDefault();
|
|
return false;
|
|
}
|
|
|
|
try {
|
|
var location = context.RouteMap.parse(context.location.hash);
|
|
} catch (e) {
|
|
// this is nowhere in the rich client; just let it go through
|
|
return postFunction(e);
|
|
}
|
|
|
|
var screen = location.page.substring(1); // remove leading slash
|
|
var accepted = screenEvent(currentScreen, "beforeLeave", {
|
|
screen: screen,
|
|
hash: context.location.hash,
|
|
});
|
|
if (accepted === false) {
|
|
logger.debug(
|
|
"navigation to " +
|
|
context.location.hash +
|
|
" rejected by " +
|
|
currentScreen
|
|
);
|
|
//resettingHash = true;
|
|
// reset the hash to where it just was
|
|
context.location.hash = currentHash;
|
|
} else {
|
|
screen;
|
|
return postFunction(e);
|
|
}
|
|
}
|
|
|
|
function changeToScreen(screen, data) {
|
|
changeScreen(screen, data);
|
|
}
|
|
|
|
function changeScreen(screen, data) {
|
|
previousScreen = currentScreen;
|
|
currentScreen = screen;
|
|
currentHash = context.location.hash;
|
|
|
|
var accepted = screenEvent(previousScreen, "beforeHide", data);
|
|
if (accepted === false) return;
|
|
|
|
logger.debug("layout: changing screen to " + currentScreen);
|
|
|
|
// notify everyone
|
|
$(document).triggerHandler(EVENTS.SCREEN_CHANGED, {
|
|
previousScreen: previousScreen,
|
|
newScreen: currentScreen,
|
|
});
|
|
window.NavActions.screenChanged(
|
|
currentScreen,
|
|
screenProperty(currentScreen, "navName")
|
|
);
|
|
context.JamTrackPreviewActions.screenChange();
|
|
|
|
screenEvent(currentScreen, "beforeShow", data);
|
|
|
|
// For now -- it seems we want it open always.
|
|
// TODO - support user preference here? Remember how they left it?
|
|
sidebarVisible = true;
|
|
/*
|
|
var openSidebarScreens = [
|
|
'home', 'session', 'createSession',
|
|
'findSession', 'searchResults'
|
|
];
|
|
$.each(openSidebarScreens, function() {
|
|
logger.debug("comparing " + this + " to " + currentScreen);
|
|
if (this === currentScreen) {
|
|
sidebarVisible = true;
|
|
return false;
|
|
}
|
|
});
|
|
*/
|
|
layout();
|
|
|
|
// add an attribute to any dialogs, which let's it know it's current screen (useful for contextual styling)
|
|
context._.each(openDialogs, function (dialog) {
|
|
addScreenContextToDialog($(dialog));
|
|
});
|
|
|
|
screenEvent(previousScreen, "afterHide", data);
|
|
screenEvent(currentScreen, "afterShow", data);
|
|
jQuery.btOffAll(); // add any prod bubbles if you change screens
|
|
|
|
// Show any requested dialog
|
|
if ("d" in data) {
|
|
// if the dialog is a text message dialog, and the user is not logged in, show the login dialog instead
|
|
if (!context.JK.currentUserId) {
|
|
if (isTextMessageInUrl()) {
|
|
showDialog("login-required-dialog");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
showDialog(data.d, data);
|
|
}
|
|
}
|
|
|
|
function isTextMessageInUrl() {
|
|
var hash = context.location.hash;
|
|
var regexp = /\S+\/text-message\/d1=/
|
|
return regexp.test(hash);
|
|
}
|
|
|
|
// if no arguments passed, then see if any dialog is showing
|
|
// if string passed, see if dialog is showing (even if buried) of a given name
|
|
function isDialogShowing() {
|
|
if (arguments.length == 1) {
|
|
// user passed in dialog id
|
|
var dialogId = arguments[0];
|
|
var result = false;
|
|
context._.each(openDialogs, function (dialog) {
|
|
if ($(dialog).attr("layout-id") == dialogId) {
|
|
result = true;
|
|
return false;
|
|
}
|
|
});
|
|
return result;
|
|
} else {
|
|
// user passed in nothing
|
|
return openDialogs.length > 0;
|
|
}
|
|
}
|
|
|
|
function currentDialog() {
|
|
if (openDialogs.length == 0) return null;
|
|
|
|
return openDialogs[openDialogs.length - 1];
|
|
}
|
|
|
|
// payload is a notification event from websocket gateway
|
|
function dialogObscuredNotification(payload) {
|
|
var openDialog = currentDialog();
|
|
if (!openDialog) return false;
|
|
|
|
if (typeof openDialog.handledNotification === "function") {
|
|
return !openDialog.handledNotification(payload);
|
|
} else {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
// payload is a notification event from websocket gateway
|
|
function isNoisyNotification(payload) {
|
|
var openDialog = currentDialog();
|
|
if (!openDialog) return false;
|
|
|
|
if (typeof openDialog.isNoisyNotification === "function") {
|
|
return !openDialog.isNoisyNotification(payload);
|
|
} else {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Responsible for keeping N dialogs in correct stacked order,
|
|
* also moves the .dialog-overlay such that it hides/obscures all dialogs except the highest one
|
|
*/
|
|
function stackDialogs($dialog, $overlay) {
|
|
// don't push a dialog on the stack that is already on there; remove it from where ever it is currently
|
|
// and the rest of the code will make it end up at the top
|
|
var layoutId = $dialog.attr("layout-id");
|
|
for (var i = openDialogs.length - 1; i >= 0; i--) {
|
|
if (openDialogs[i].attr("layout-id") === layoutId) {
|
|
openDialogs.splice(i, 1);
|
|
}
|
|
}
|
|
|
|
// pull out a topmost one, if present
|
|
var topMost = null;
|
|
for (var i = openDialogs.length - 1; i >= 0; i--) {
|
|
if (openDialogs[i].attr("topmost") === "true") {
|
|
topMost = openDialogs[i];
|
|
openDialogs.splice(i, 1);
|
|
}
|
|
}
|
|
|
|
openDialogs.push($dialog);
|
|
if (topMost) openDialogs.push(topMost);
|
|
|
|
var zIndex = 1000;
|
|
for (var i in openDialogs) {
|
|
var $openDialog = openDialogs[i];
|
|
$openDialog.css("zIndex", zIndex);
|
|
zIndex++;
|
|
}
|
|
$overlay.css("zIndex", zIndex - 1);
|
|
}
|
|
|
|
function unstackDialogs($overlay) {
|
|
if (openDialogs.length > 0) {
|
|
openDialogs.pop();
|
|
}
|
|
|
|
var zIndex = 1000 + openDialogs.length;
|
|
$overlay.css("zIndex", zIndex - 1);
|
|
|
|
if (openDialogs.length == 0) {
|
|
$overlay.hide();
|
|
}
|
|
}
|
|
|
|
function addScreenContextToDialog($dialog) {
|
|
$dialog.attr("current-screen", currentScreen); // useful for contextual styling of dialogs
|
|
}
|
|
|
|
function showDialog(dialog, options) {
|
|
if (dialogEvent(dialog, "beforeShow", options) === false) {
|
|
return null;
|
|
}
|
|
logger.debug("opening dialog: " + dialog);
|
|
|
|
var $dialog = $('[layout-id="' + dialog + '"]');
|
|
if ($dialog.length == 0) {
|
|
logger.debug("unknown dialog encountered: " + dialog);
|
|
return;
|
|
}
|
|
|
|
var $overlay = $(".dialog-overlay");
|
|
|
|
if (opts.sizeOverlayToContent) {
|
|
var $body = $("body");
|
|
$(".dialog-overlay").css({
|
|
width: $body.width() + "px",
|
|
height: $body.height() + "px",
|
|
});
|
|
}
|
|
|
|
$overlay.show();
|
|
centerDialog(dialog);
|
|
stackDialogs($dialog, $overlay);
|
|
addScreenContextToDialog($dialog);
|
|
$dialog.show();
|
|
|
|
// maintain center (un-attach previous sensor if applicable, then re-add always)
|
|
|
|
window.ResizeSensor.detach($dialog.get(0));
|
|
new window.ResizeSensor($dialog, function () {
|
|
centerDialog(dialog);
|
|
});
|
|
|
|
dialogEvent(dialog, "afterShow", options);
|
|
$.btOffAll(); // add any prod bubbles if you open a dailog
|
|
return $dialog;
|
|
}
|
|
|
|
function centerDialog(dialog) {
|
|
var $dialog = $('[layout-id="' + dialog + '"]');
|
|
$dialog.css({
|
|
left: width / 2 - $dialog.width() / 2 + "px",
|
|
top: height / 2 - $dialog.height() / 2 + "px",
|
|
});
|
|
}
|
|
|
|
function panelHeaderClicked(evt) {
|
|
evt.preventDefault();
|
|
|
|
if (!context.JK.currentUserId) {
|
|
showDialog("login-required-dialog");
|
|
return false;
|
|
}
|
|
|
|
expandedPanel = $(evt.currentTarget)
|
|
.closest('[layout="panel"]')
|
|
.attr("layout-id");
|
|
layout();
|
|
return false;
|
|
}
|
|
|
|
function expandNotificationPanel() {
|
|
if (!context.JK.currentUserId) {
|
|
showDialog("login-required-dialog");
|
|
return false;
|
|
}
|
|
expandedPanel = "panelNotifications";
|
|
layout();
|
|
return false;
|
|
}
|
|
|
|
function wizardLinkClicked(evt) {
|
|
evt.preventDefault();
|
|
var targetStepId = $(evt.currentTarget).attr("layout-wizard-link");
|
|
setWizardStep(targetStepId);
|
|
return false;
|
|
}
|
|
|
|
function startNewFtue() {
|
|
// var step = 0;
|
|
//setWizardStep(step);
|
|
//wizardShowFunctions[step]();
|
|
return showDialog("gear-wizard");
|
|
}
|
|
|
|
function setWizardStep(targetStepId) {
|
|
var selector = '[layout-wizard-step="' + targetStepId + '"]';
|
|
var $targetStep = $(selector);
|
|
var stepDialogTitle = $targetStep.attr("dialog-title");
|
|
if (stepDialogTitle) {
|
|
var $myDialog = $targetStep.closest('[layout="dialog"]');
|
|
var $myTitle = $(".content-head h1", $myDialog);
|
|
$myTitle.html(stepDialogTitle);
|
|
}
|
|
// Hide all steps:
|
|
// Invoke the 'show' function, if present prior to actually showing.
|
|
if (
|
|
context._.contains(context._.keys(wizardShowFunctions), targetStepId)
|
|
) {
|
|
wizardShowFunctions[targetStepId]();
|
|
}
|
|
$("[layout-wizard-step]").hide();
|
|
$targetStep.show();
|
|
|
|
var ftuePurpose = $targetStep.attr("dialog-purpose");
|
|
context.JK.GA.trackFTUECompletion(ftuePurpose, context.JK.detectOS());
|
|
}
|
|
|
|
function trackLocationChange(e) {
|
|
context.JK.GA.virtualPageView(
|
|
location.pathname + location.search + location.hash
|
|
);
|
|
}
|
|
|
|
function onHandleKey(e) {
|
|
if (e.keyCode == 27 /** esc */) {
|
|
if (isDialogShowing()) {
|
|
var $dialog = currentDialog();
|
|
if (!$dialog) {
|
|
logger.error("unable to find current dialog on ESC");
|
|
return;
|
|
}
|
|
|
|
cancelDialog($dialog.attr("layout-id"));
|
|
}
|
|
}
|
|
}
|
|
|
|
function handleDialogState() {
|
|
var rawDialogState = $.cookie("dialog_state");
|
|
try {
|
|
var dialogState = JSON.parse(rawDialogState);
|
|
if (!dialogState) {
|
|
$.removeCookie("dialog_state");
|
|
return;
|
|
}
|
|
} catch (e) {
|
|
$.removeCookie("dialog_state");
|
|
return;
|
|
}
|
|
|
|
var dialogName = dialogState["name"];
|
|
if (dialogName) {
|
|
setTimeout(function () {
|
|
// TODO: we need a 'everything is initialized' event
|
|
showDialog(dialogName);
|
|
}, 0);
|
|
}
|
|
$.removeCookie("dialog_state");
|
|
}
|
|
|
|
// on next page load, a dialog of this name will show
|
|
function queueDialog(name) {
|
|
$.cookie("dialog_state", JSON.stringify({ name: name }));
|
|
}
|
|
|
|
function events() {
|
|
$(context).resize(function () {
|
|
if (resizing) {
|
|
context.clearTimeout(resizing);
|
|
}
|
|
resizing = context.setTimeout(layout, 80);
|
|
});
|
|
$("body").on("click", "[layout-link]", linkClicked);
|
|
$('[layout-action="close"]').on("click", close);
|
|
$('[layout-action="cancel"]').on("click", cancel);
|
|
$("[layout-sidebar-expander]").on("click", toggleSidebar);
|
|
$('[layout-panel="expanded"] [layout-panel="header"]').on(
|
|
"click",
|
|
panelHeaderClicked
|
|
);
|
|
$("[layout-wizard-link]").on("click", wizardLinkClicked);
|
|
$("[tab-target]").on("click", tabClicked);
|
|
$(context).on("hashchange", trackLocationChange);
|
|
$(document).keyup(onHandleKey);
|
|
}
|
|
|
|
// public functions
|
|
this.getOpts = function () {
|
|
return opts;
|
|
};
|
|
|
|
// used for concurrent notifications
|
|
var notifyQueue = [];
|
|
var notify1Showing = false;
|
|
var notify2Showing = false;
|
|
var notify3Showing = false;
|
|
var isMouseOverNotify1 = false;
|
|
var isMouseOverNotify2 = false;
|
|
var isMouseOverNotify3 = false;
|
|
var notify1Elapsed = false;
|
|
var notify2Elapsed = false;
|
|
var notify3Elapsed = false;
|
|
|
|
var $notify1 = $('[layout="notify1"]');
|
|
var $notify2 = $('[layout="notify2"]');
|
|
var $notify3 = $('[layout="notify3"]');
|
|
|
|
$notify1.on("mouseenter", mouseEnterNotification);
|
|
$notify1.on("mouseleave", mouseLeaveToNotification);
|
|
$notify2.on("mouseenter", mouseEnterNotification);
|
|
$notify2.on("mouseleave", mouseLeaveToNotification);
|
|
$notify3.on("mouseenter", mouseEnterNotification);
|
|
$notify3.on("mouseleave", mouseLeaveToNotification);
|
|
|
|
function mouseEnterNotification(evt) {
|
|
var $notify = $(evt.target);
|
|
//console.log("mouseEnter", $notify.prop("id"));
|
|
switch ($notify.prop("id")) {
|
|
case "notification1":
|
|
isMouseOverNotify1 = true;
|
|
break;
|
|
case "notification2":
|
|
isMouseOverNotify2 = true;
|
|
break;
|
|
case "notification3":
|
|
isMouseOverNotify3 = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
function mouseLeaveToNotification(evt) {
|
|
var $notify = $(evt.target);
|
|
//console.log("mouseLeave", $notify.prop("id"));
|
|
switch ($notify.prop("id")) {
|
|
case "notification1":
|
|
if (notify1Elapsed) {
|
|
$notify1.hide(0);
|
|
notify1Showing = false;
|
|
}
|
|
isMouseOverNotify1 = false;
|
|
break;
|
|
case "notification2":
|
|
if (notify2Elapsed) {
|
|
$notify2.hide(0);
|
|
notify2Showing = false;
|
|
}
|
|
isMouseOverNotify2 = false;
|
|
break;
|
|
case "notification3":
|
|
if (notify3Elapsed) {
|
|
$notify3.hide(0);
|
|
notify3Showing = false;
|
|
}
|
|
isMouseOverNotify3 = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//var firstNotification = false;
|
|
//var notifyDetails;
|
|
|
|
var okButton = {
|
|
id: "btn-okay",
|
|
text: "OKAY",
|
|
"layout-action": "close",
|
|
href: "#",
|
|
class: "button-orange",
|
|
};
|
|
|
|
var cancelButton = {
|
|
id: "btn-cancel",
|
|
text: "CANCEL",
|
|
"layout-action": "close",
|
|
href: "#",
|
|
class: "button-grey",
|
|
};
|
|
|
|
var defaultButtons = [okButton, cancelButton];
|
|
|
|
// this.notify = function (message, buttons, noCancel) {
|
|
// if (!buttons) {
|
|
// if (noCancel) {
|
|
// buttons = [okButton];
|
|
// }
|
|
// else {
|
|
// buttons = defaultButtons;
|
|
// }
|
|
// }
|
|
|
|
// // this allows clients to just specify the important action button without having to repeat the cancel descripton everywhere
|
|
// if (buttons.length === 1) {
|
|
// // jkolyer: changed default to remove cancel as this is used as an alert, not a confirmation (see ConfirmDialog)
|
|
// // buttons.push(cancelButton);
|
|
// }
|
|
|
|
// var $notify = $('[layout="notify"]');
|
|
|
|
// if (notifyQueue.length === 0) {
|
|
// firstNotification = true;
|
|
// setNotificationInfo(message, buttons, $notify);
|
|
// }
|
|
|
|
// notifyQueue.push({message: message, descriptor: buttons});
|
|
// // JW - speeding up the in/out parts of notify. Extending non-moving time.
|
|
// $notify.hide(0)
|
|
// .show({
|
|
// duration: 0,
|
|
// queue: true,
|
|
// complete: function () {
|
|
// notifyDetails = notifyQueue.shift();
|
|
|
|
// // shift 1 more time if this is first notification being displayed
|
|
// if (firstNotification) {
|
|
// notifyDetails = notifyQueue.shift();
|
|
// firstNotification = false;
|
|
// }
|
|
|
|
// if (notifyDetails !== undefined) {
|
|
// setNotificationInfo(notifyDetails.message, notifyDetails.descriptor, $notify);
|
|
// }
|
|
|
|
// notifyDetails = {};
|
|
// }
|
|
// })
|
|
// .delay(8000)
|
|
// .hide(0)
|
|
// };
|
|
|
|
this.notify = function (message, buttons, noCancel) {
|
|
console.log("call this.notify");
|
|
|
|
if (!buttons) {
|
|
if (noCancel) {
|
|
buttons = [okButton];
|
|
} else {
|
|
buttons = defaultButtons;
|
|
}
|
|
}
|
|
|
|
notifyQueue.push({ message: message, descriptor: buttons });
|
|
|
|
showNotificationToast();
|
|
};
|
|
|
|
function showNotificationToast() {
|
|
if (!notify1Showing) {
|
|
var notifyDetails1 = notifyQueue.shift();
|
|
if (notifyDetails1 !== undefined) {
|
|
setNotificationInfo(
|
|
notifyDetails1.message,
|
|
notifyDetails1.descriptor,
|
|
$notify1
|
|
);
|
|
notify1Elapsed = false;
|
|
$notify1.hide(0).show({
|
|
duration: 0,
|
|
//queue: true,
|
|
complete: function () {
|
|
console.log("Show notification1");
|
|
notify1Showing = true;
|
|
notifyDetails1 = {};
|
|
},
|
|
});
|
|
//.delay(8000);
|
|
|
|
setTimeout(function () {
|
|
notify1Elapsed = true;
|
|
if (!isMouseOverNotify1) {
|
|
$notify1.hide(0, function () {
|
|
notify1Showing = false;
|
|
console.log("Hide notification1");
|
|
});
|
|
}
|
|
}, 8000);
|
|
}
|
|
} else if (!notify2Showing) {
|
|
var notifyDetails2 = notifyQueue.shift();
|
|
if (notifyDetails2 !== undefined) {
|
|
setNotificationInfo(
|
|
notifyDetails2.message,
|
|
notifyDetails2.descriptor,
|
|
$notify2
|
|
);
|
|
notify2Elapsed = false;
|
|
$notify2.hide(0).show({
|
|
duration: 0,
|
|
//queue: true,
|
|
complete: function () {
|
|
console.log("Show notification2");
|
|
notify2Showing = true;
|
|
notifyDetails2 = {};
|
|
},
|
|
});
|
|
// .delay(8000)
|
|
// .hide(0, function(){
|
|
// notify2Showing = false;
|
|
// console.log("Hide notification2")
|
|
// })
|
|
setTimeout(function () {
|
|
notify2Elapsed = true;
|
|
if (!isMouseOverNotify2) {
|
|
$notify2.hide(0, function () {
|
|
notify2Showing = false;
|
|
console.log("Hide notification2");
|
|
});
|
|
}
|
|
}, 8000);
|
|
}
|
|
} else if (!notify3Showing) {
|
|
var notifyDetails3 = notifyQueue.shift();
|
|
if (notifyDetails3 !== undefined) {
|
|
setNotificationInfo(
|
|
notifyDetails3.message,
|
|
notifyDetails3.descriptor,
|
|
$notify3
|
|
);
|
|
notify3Elapsed = false;
|
|
$notify3.hide(0).show({
|
|
duration: 0,
|
|
//queue: true,
|
|
complete: function () {
|
|
console.log("Show notification3");
|
|
notify3Showing = true;
|
|
notifyDetails3 = {};
|
|
},
|
|
});
|
|
// .delay(8000)
|
|
// .hide(0, function(){
|
|
// notify3Showing = false;
|
|
// console.log("Hide notification3")
|
|
// })
|
|
setTimeout(function () {
|
|
notify3Elapsed = true;
|
|
if (!isMouseOverNotify3) {
|
|
$notify3.hide(0, function () {
|
|
notify3Showing = false;
|
|
console.log("Hide notification3");
|
|
});
|
|
}
|
|
}, 8000);
|
|
}
|
|
} else if (notify1Showing && notify2Showing && notify3Showing) {
|
|
//try again after 1 second
|
|
setTimeout(function () {
|
|
showNotificationToast();
|
|
}, 1000);
|
|
}
|
|
}
|
|
|
|
// function setNotificationInfo(message, buttons, notificationSelector) {
|
|
// var $notify = $('[layout="notify"]');
|
|
// $('h2', $notify).text(message.title);
|
|
// $('p', $notify).empty();
|
|
// if (message.text instanceof jQuery) {
|
|
// $('p', $notify).append(message.text)
|
|
// }
|
|
// else {
|
|
// $('p', $notify).html(message.text);
|
|
// }
|
|
|
|
// if (message.icon_url) {
|
|
// $('#avatar', $notify).attr('src', message.icon_url);
|
|
// $('#notify-avatar', $notify).show();
|
|
// }
|
|
// else {
|
|
// $('#notify-avatar', $notify).hide();
|
|
// }
|
|
|
|
// if (message.detail) {
|
|
// $('div.detail', $notify).html(message.detail).show();
|
|
// }
|
|
// else {
|
|
// $('div.detail', $notify).hide();
|
|
// }
|
|
|
|
// var $buttonDiv = $('#buttons', $notify);
|
|
// $buttonDiv.empty();
|
|
|
|
// $.each(buttons, function(index, val) {
|
|
|
|
// // build button HTML based on KV pairs
|
|
// var keys = Object.keys(val);
|
|
// var buttonHtml = '<a';
|
|
|
|
// for (var i=0; i < keys.length; i++) {
|
|
// //console.log("keys[i]=%o, val[keys[i]]=%o", keys[i], val[keys[i]]);
|
|
|
|
// // ignore button text and callback info
|
|
// if (keys[i] !== 'text' && keys[i] !== 'callback' && keys[i] !== 'callback_args') {
|
|
// buttonHtml += ' ' + keys[i] + '="' + val[keys[i]] + '"';
|
|
// }
|
|
// }
|
|
|
|
// buttonHtml += '>' + val['text'] + '</a> ';
|
|
// $buttonDiv.append(buttonHtml);
|
|
|
|
// // ensure it doesn't fire twice
|
|
// $('#' + val.id, $notify).unbind('click');
|
|
|
|
// $('#' + val.id, $notify).click(function() {
|
|
// if (val.callback !== undefined) {
|
|
// if (val.callback_args) {
|
|
// val.callback(val.callback_args);
|
|
// }
|
|
// else {
|
|
// val.callback();
|
|
// }
|
|
// return false;
|
|
// }
|
|
// else {
|
|
// notificationSelector.hide();
|
|
// return false;
|
|
// }
|
|
// });
|
|
// });
|
|
// }
|
|
|
|
function setNotificationInfo(message, buttons, notificationSelector) {
|
|
var $notify = notificationSelector;
|
|
$("h2", $notify).text(message.title);
|
|
$("p", $notify).empty();
|
|
if (message.text instanceof jQuery) {
|
|
$("p", $notify).append(message.text);
|
|
} else {
|
|
$("p", $notify).html(message.text);
|
|
}
|
|
|
|
if (message.icon_url) {
|
|
$("#avatar", $notify).attr("src", message.icon_url);
|
|
$("#notify-avatar", $notify).show();
|
|
} else {
|
|
$("#notify-avatar", $notify).hide();
|
|
}
|
|
|
|
if (message.detail) {
|
|
$("div.detail", $notify).html(message.detail).show();
|
|
} else {
|
|
$("div.detail", $notify).hide();
|
|
}
|
|
|
|
var $buttonDiv = $("#buttons", $notify);
|
|
$buttonDiv.empty();
|
|
|
|
$.each(buttons, function (index, val) {
|
|
// build button HTML based on KV pairs
|
|
var keys = Object.keys(val);
|
|
var buttonHtml = "<a";
|
|
|
|
for (var i = 0; i < keys.length; i++) {
|
|
//console.log("keys[i]=%o, val[keys[i]]=%o", keys[i], val[keys[i]]);
|
|
|
|
// ignore button text and callback info
|
|
if (
|
|
keys[i] !== "text" &&
|
|
keys[i] !== "callback" &&
|
|
keys[i] !== "callback_args"
|
|
) {
|
|
buttonHtml += " " + keys[i] + '="' + val[keys[i]] + '"';
|
|
}
|
|
}
|
|
|
|
buttonHtml += ">" + val["text"] + "</a> ";
|
|
$buttonDiv.append(buttonHtml);
|
|
|
|
// ensure it doesn't fire twice
|
|
$("#" + val.id, $notify).unbind("click");
|
|
|
|
$("#" + val.id, $notify).click(function () {
|
|
if (val.callback !== undefined) {
|
|
if (val.callback_args) {
|
|
val.callback(val.callback_args);
|
|
} else {
|
|
val.callback();
|
|
}
|
|
return false;
|
|
} else {
|
|
$notify.hide();
|
|
return false;
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
this.setWizardStep = setWizardStep;
|
|
this.startNewFtue = startNewFtue;
|
|
|
|
this.changeToScreen = function (screen, data) {
|
|
changeToScreen(screen, data);
|
|
};
|
|
|
|
this.onHashChange = function (e, postFunction) {
|
|
return onHashChange(e, postFunction);
|
|
};
|
|
|
|
this.showDialog = function (dialog, options) {
|
|
return showDialog(dialog, options);
|
|
};
|
|
|
|
this.dialogObscuredNotification = function (payload) {
|
|
return dialogObscuredNotification(payload);
|
|
};
|
|
|
|
this.isNoisyNotification = function (payload) {
|
|
return isNoisyNotification(payload);
|
|
};
|
|
|
|
this.shouldFreezeAppOnDisconnect = function () {
|
|
return shouldFreezeAppOnDisconnect();
|
|
};
|
|
|
|
this.isDialogShowing = function () {
|
|
return isDialogShowing(arguments[0]);
|
|
};
|
|
|
|
this.activeElementEvent = function (evtName, data) {
|
|
return activeElementEvent(evtName, data);
|
|
};
|
|
|
|
this.getCurrentScreen = function () {
|
|
return currentScreen; // will be a string of the layout-id of the active screen
|
|
};
|
|
|
|
this.close = function (evt) {
|
|
close(evt);
|
|
};
|
|
|
|
this.beforeDisconnect = function () {
|
|
fireEvents();
|
|
};
|
|
|
|
this.afterReconnect = function () {
|
|
fireEvents();
|
|
};
|
|
|
|
this.closeDialog = closeDialog;
|
|
this.cancelDialog = cancelDialog;
|
|
|
|
this.handleDialogState = handleDialogState;
|
|
this.queueDialog = queueDialog;
|
|
|
|
/**
|
|
* Given information on a grid, and a given card's grid settings, use the
|
|
* margin options and return a list of [top, left, width, height]
|
|
* for the cell.
|
|
*/
|
|
this.getCardLayout = function (
|
|
gridWidth,
|
|
gridHeight,
|
|
gridRows,
|
|
gridCols,
|
|
row,
|
|
col,
|
|
rowspan,
|
|
colspan
|
|
) {
|
|
var _gridWidth = gridWidth + 3 * opts.gridPadding;
|
|
var _gridHeight = gridHeight + 3 * opts.gridPadding;
|
|
var cellWidth, cellHeight, top, left, width, height;
|
|
|
|
cellWidth = Math.floor(
|
|
(_gridWidth - 2 * opts.gridOuterMargin) / gridCols
|
|
);
|
|
cellHeight = Math.floor(
|
|
(_gridHeight - 2 * opts.gridOuterMargin) / gridRows
|
|
);
|
|
width = colspan * cellWidth - 2 * opts.gridPadding;
|
|
height = rowspan * cellHeight - 2 * opts.gridPadding;
|
|
top = row * cellHeight; // + opts.gridOuterMargin; // + opts.gridPadding;
|
|
left = col * cellWidth; // + opts.gridOuterMargin; // + opts.gridPadding;
|
|
|
|
return {
|
|
top: top,
|
|
left: left,
|
|
width: width,
|
|
height: height,
|
|
};
|
|
};
|
|
|
|
this.bindScreen = function (screen, handler) {
|
|
screenBindings[screen] = handler;
|
|
};
|
|
|
|
this.bindDialog = function (dialog, handler) {
|
|
dialogBindings[dialog] = handler;
|
|
};
|
|
|
|
this.registerWizardStepFunction = function (stepId, showFunction) {
|
|
wizardShowFunctions[stepId] = showFunction;
|
|
};
|
|
|
|
this.initialize = function (inOpts) {
|
|
me = this;
|
|
opts = $.extend(opts, inOpts);
|
|
setup();
|
|
events();
|
|
};
|
|
|
|
this.expandNotificationPanel = function () {
|
|
return expandNotificationPanel();
|
|
};
|
|
|
|
return this;
|
|
};
|
|
})(window, jQuery);
|