2012-09-21 04:46:45 +00:00
/ *
* 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 .
* /
2014-02-21 22:02:51 +00:00
( 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 ( ) {
2024-09-19 12:48:24 +00:00
$ ( ".curtain" ) . fadeOut ( 2 * duration ) ;
2014-02-21 22:02:51 +00:00
} , duration ) ;
} ;
context . JK . Layout = function ( ) {
// privates
var logger = context . JK . logger ;
2014-06-09 03:26:50 +00:00
var EVENTS = context . JK . EVENTS ;
2014-04-09 17:25:52 +00:00
var NOT _HANDLED = "not handled" ;
2024-09-19 12:48:24 +00:00
var me = null ; // Reference to this instance for context sanity.
2014-02-21 22:02:51 +00:00
var opts = {
headerHeight : 75 ,
sidebarWidth : 300 ,
notifyHeight : 150 ,
notifyGutter : 10 ,
collapsedSidebar : 30 ,
panelHeaderHeight : 36 ,
2024-09-19 12:48:24 +00:00
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.
2014-02-21 22:02:51 +00:00
animationDuration : 400 ,
2024-09-19 12:48:24 +00:00
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
2012-11-18 17:27:20 +00:00
} ;
2014-02-21 22:02:51 +00:00
var width = $ ( context ) . width ( ) ;
var height = $ ( context ) . height ( ) ;
var resizing = null ;
var sidebarVisible = true ;
var expandedPanel = null ;
var previousScreen = null ;
var currentScreen = null ;
2014-02-23 04:41:42 +00:00
var currentHash = null ;
2014-02-21 22:02:51 +00:00
var screenBindings = { } ;
var dialogBindings = { } ;
var wizardShowFunctions = { } ;
var openDialogs = [ ] ; // FIFO stack
2014-02-23 04:41:42 +00:00
var resettingHash = false ;
2014-02-21 22:02:51 +00:00
function setup ( ) {
requiredStyles ( ) ;
hideAll ( ) ;
setInitialExpandedSidebarPanel ( ) ;
sizeScreens ( width , height , '[layout="screen"]' , true ) ;
positionOffscreens ( width , height ) ;
$ ( '[layout="sidebar"]' ) . show ( ) ;
$ ( '[layout="panel"]' ) . show ( ) ;
layout ( ) ;
}
function setInitialExpandedSidebarPanel ( ) {
2016-02-06 23:32:20 +00:00
if ( gon . global . chat _opened _by _default ) {
2024-09-19 12:48:24 +00:00
expandedPanel = "panelChat" ;
} else {
expandedPanel = "panelFriends" ;
2016-02-06 23:32:20 +00:00
}
2014-02-21 22:02:51 +00:00
}
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 ) ;
2021-04-10 02:45:51 +00:00
layoutNotify1 ( width , height ) ;
layoutNotify2 ( width , height ) ;
layoutNotify3 ( width , height ) ;
2014-02-21 22:02:51 +00:00
layoutFooter ( width , height ) ;
2015-03-27 20:36:09 +00:00
2024-09-19 12:48:24 +00:00
$ ( document ) . triggerHandler ( "layout_resized" ) ;
2014-02-21 22:02:51 +00:00
}
function layoutCurtain ( screenWidth , screenHeight ) {
var curtainStyle = {
2024-09-19 12:48:24 +00:00
position : "absolute" ,
width : screenWidth + "px" ,
height : screenHeight + "px" ,
2014-02-21 22:02:51 +00:00
} ;
2024-09-19 12:48:24 +00:00
$ ( ".curtain" ) . css ( curtainStyle ) ;
2014-02-21 22:02:51 +00:00
}
function layoutDialogOverlay ( screenWidth , screenHeight ) {
var style = {
2024-09-19 12:48:24 +00:00
position : "absolute" ,
width : screenWidth + "px" ,
height : screenHeight + "px" ,
2014-02-21 22:02:51 +00:00
} ;
2024-09-19 12:48:24 +00:00
$ ( ".dialog-overlay" ) . css ( style ) ;
2014-02-21 22:02:51 +00:00
}
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 ] ;
}
}
2024-09-19 12:48:24 +00:00
$ ( previousScreenSelector ) . animate (
{ left : left } ,
{ duration : opts . animationDuration , queue : false }
) ;
2014-02-21 22:02:51 +00:00
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 ) {
2024-09-19 12:48:24 +00:00
width -= opts . sidebarWidth + 2 * opts . gridPadding ;
2014-02-21 22:02:51 +00:00
} else {
width -= opts . collapsedSidebar + 2 * opts . gridPadding ;
width += opts . gutter ; // Add back in the right gutter width.
}
2024-09-19 12:48:24 +00:00
var height =
screenHeight -
opts . headerHeight -
( 2 * opts . gutter + 2 * opts . screenMargin ) ;
2014-02-21 22:02:51 +00:00
var css = {
width : width ,
2024-09-19 12:48:24 +00:00
height : height ,
2014-02-21 22:02:51 +00:00
} ;
var $screens = $ ( selector ) ;
2024-09-19 12:48:24 +00:00
$screens . animate ( css , { duration : duration , queue : false } ) ;
2014-02-21 22:02:51 +00:00
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 ) ;
2024-09-19 12:48:24 +00:00
var $screens = $ ( '[layout="screen"]' ) . not (
'[layout-id="' + currentScreen + '"]'
) ;
2014-02-21 22:02:51 +00:00
$screens . css ( {
top : top ,
2024-09-19 12:48:24 +00:00
left : left ,
2014-02-21 22:02:51 +00:00
} ) ;
}
/ * *
* 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 + '"]' ) ;
2024-09-19 12:48:24 +00:00
$screen . animate (
{
top : top ,
left : left ,
overflow : "auto" ,
} ,
duration
) ;
2014-02-21 22:02:51 +00:00
}
function layoutHomeScreen ( homeScreenWidth , homeScreenHeight ) {
2024-09-19 12:48:24 +00:00
var $grid = $ ( "[layout-grid]" ) ;
2014-02-21 22:02:51 +00:00
var gridWidth = homeScreenWidth ;
var gridHeight = homeScreenHeight ;
2024-09-19 12:48:24 +00:00
$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 ] ;
2014-02-21 22:02:51 +00:00
2015-06-10 13:26:45 +00:00
var gutterWidth = 0 ;
var findCardLayout ;
var feedCardLayout ;
2024-09-19 12:48:24 +00:00
$grid . find ( ".homecard" ) . each ( function ( ) {
2014-02-21 22:02:51 +00:00
var childPosition = $ ( this ) . attr ( "layout-grid-position" ) ;
2024-09-19 12:48:24 +00:00
var childRow = childPosition . split ( "," ) [ 1 ] ;
var childCol = childPosition . split ( "," ) [ 0 ] ;
2014-02-21 22:02:51 +00:00
var childRowspan = $ ( this ) . attr ( "layout-grid-rows" ) ;
var childColspan = $ ( this ) . attr ( "layout-grid-columns" ) ;
2024-09-19 12:48:24 +00:00
var childLayout = me . getCardLayout (
gridWidth ,
gridHeight ,
gridRows ,
gridCols ,
childRow ,
childCol ,
childRowspan ,
childColspan
) ;
if ( $ ( this ) . is ( ".jamtrack" ) ) {
2015-06-10 13:26:45 +00:00
feedCardLayout = childLayout ;
2024-09-19 12:48:24 +00:00
} else if ( $ ( this ) . is ( ".findsession" ) ) {
2015-06-10 13:26:45 +00:00
findCardLayout = childLayout ;
}
2024-09-19 12:48:24 +00:00
$ ( this ) . animate (
{
width : childLayout . width ,
height : childLayout . height ,
top : childLayout . top ,
left : childLayout . left ,
} ,
opts . animationDuration
) ;
2014-02-21 22:02:51 +00:00
} ) ;
2015-06-10 13:26:45 +00:00
2016-05-09 21:47:55 +00:00
var broadcastWidth = findCardLayout . width + feedCardLayout . width ; //+ opts.gridPadding * 2;
2015-06-10 13:26:45 +00:00
2020-05-09 13:22:19 +00:00
//layoutBroadcast(broadcastWidth, findCardLayout.left);
2024-09-19 12:48:24 +00:00
layoutTopMessage ( broadcastWidth , findCardLayout . left ) ;
2015-06-10 13:26:45 +00:00
}
2020-05-09 13:22:19 +00:00
/ * *
2015-06-10 13:26:45 +00:00
function layoutBroadcast ( width , left ) {
var css = {
width : width + opts . gridPadding * 2 ,
left : left
}
$ ( '[data-react-class="BroadcastHolder"]' ) . animate ( css , opts . animationDuration )
2020-05-09 13:22:19 +00:00
} * /
function layoutTopMessage ( width , left ) {
var css = {
2024-09-19 12:48:24 +00:00
width : width + opts . gridPadding * 2 ,
left : left ,
} ;
$ ( '[data-react-class="TopMessageHolder"]' ) . animate (
css ,
opts . animationDuration
) ;
2014-02-21 22:02:51 +00:00
}
function layoutSidebar ( screenWidth , screenHeight ) {
var width = opts . sidebarWidth ;
2024-09-19 12:48:24 +00:00
var expanderHeight = $ ( "[layout-sidebar-expander]" ) . height ( ) ;
var height =
screenHeight - opts . headerHeight - 2 * opts . gutter + expanderHeight ;
2014-02-21 22:02:51 +00:00
var right = opts . gutter ;
if ( ! sidebarVisible ) {
// Negative right to hide most of sidebar
2024-09-19 12:48:24 +00:00
right = 0 - opts . sidebarWidth + opts . collapsedSidebar ;
2014-02-21 22:02:51 +00:00
}
var top = opts . headerHeight + opts . gutter - expanderHeight ;
var css = {
width : width ,
height : height ,
top : top ,
2024-09-19 12:48:24 +00:00
right : right ,
2014-02-21 22:02:51 +00:00
} ;
$ ( '[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 ;
}
2014-03-27 18:43:15 +00:00
var $expandedPanel = $ ( '[layout-id="' + expandedPanel + '"]' ) ;
2024-09-19 12:48:24 +00:00
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 ) ;
2014-02-21 22:02:51 +00:00
$ ( '[layout-panel="contents"]' ) . hide ( ) ;
2024-09-19 12:48:24 +00:00
$ ( '[layout-panel="contents"]' ) . css ( { height : "1px" } ) ;
2014-02-21 22:02:51 +00:00
$expandedPanelContents . show ( ) ;
2024-09-19 12:48:24 +00:00
$expandedPanel . triggerHandler ( "open" ) ;
$expandedPanelContents . animate (
{ height : expandedPanelHeight + "px" } ,
opts . animationDuration ,
function ( ) {
$expandedPanel . triggerHandler ( "fullyOpen" ) ;
}
) ;
2014-02-21 22:02:51 +00:00
}
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" ,
2024-09-19 12:48:24 +00:00
left : left + "px" ,
2014-02-21 22:02:51 +00:00
} ;
$ ( '[layout="header"]' ) . css ( css ) ;
}
2021-04-10 02:45:51 +00:00
function layoutNotify1 ( screenWidth , screenHeight ) {
var $notify1 = $ ( '[layout="notify1"]' ) ;
//var nHeight = $notify1.height();
2014-02-21 22:02:51 +00:00
var notifyStyle = {
2024-09-19 12:48:24 +00:00
bottom : "0px" ,
position : "fixed" ,
padding : "20px" ,
2014-02-21 22:02:51 +00:00
} ;
2021-04-10 02:45:51 +00:00
$notify1 . css ( notifyStyle ) ;
}
function layoutNotify2 ( screenWidth , screenHeight ) {
var $notify1 = $ ( '[layout="notify1"]' ) ;
var $notify2 = $ ( '[layout="notify2"]' ) ;
var nHeight = $notify1 . height ( ) ;
var notifyStyle = {
2024-09-19 12:48:24 +00:00
bottom : ( nHeight + 41 ) . toString ( ) + "px" ,
position : "fixed" ,
padding : "20px" ,
2021-04-10 02:45:51 +00:00
} ;
$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 = {
2024-09-19 12:48:24 +00:00
bottom : ( nHeight1 + nHeight2 + 41 + 41 ) . toString ( ) + "px" ,
position : "fixed" ,
padding : "20px" ,
2021-04-10 02:45:51 +00:00
} ;
$notify3 . css ( notifyStyle ) ;
2014-02-21 22:02:51 +00:00
}
function layoutFooter ( screenWidth , screenHeight ) {
if ( ! opts . layoutFooter ) {
return ;
}
2024-09-19 12:48:24 +00:00
var $footer = $ ( "#footer" ) ;
2014-02-21 22:02:51 +00:00
$footer . show ( ) ;
var nHeight = $footer . height ( ) ;
var footerStyle = {
2024-09-19 12:48:24 +00:00
top : screenHeight - 80 + "px" ,
2014-02-21 22:02:51 +00:00
} ;
var width = screenWidth - ( 2 * opts . gutter + 2 * opts . screenMargin ) ;
var left = - 1 * width - 100 ;
2024-09-19 12:48:24 +00:00
$footer . animate (
{ left : opts . gutter , width : width , top : screenHeight - 78 + "px" } ,
opts . animationDuration
) ;
2014-02-21 22:02:51 +00:00
}
function requiredLayoutStyles ( ) {
var layoutStyle = {
2024-09-19 12:48:24 +00:00
position : "absolute" ,
margin : "0px" ,
padding : "0px" ,
2014-02-21 22:02:51 +00:00
} ;
2024-09-19 12:48:24 +00:00
$ ( "[layout]" ) . css ( layoutStyle ) ;
2014-02-21 22:02:51 +00:00
// JW: Setting z-index of notify to 1001, so it will appear above the dialog overlay.
// This allows dialogs to use the notification.
2024-09-19 12:48:24 +00:00
$ ( '[layout="notify"]' ) . css ( { "z-index" : "1001" , padding : "20px" } ) ;
$ ( '[layout="panel"]' ) . css ( { position : "relative" } ) ;
2014-04-08 11:43:26 +00:00
var $headers = $ ( '[layout-panel="expanded"] [layout-panel="header"]' ) ;
2024-09-19 12:48:24 +00:00
context . _ . each ( $headers , function ( $header ) {
2014-04-08 11:43:26 +00:00
$header = $ ( $header ) ;
2024-09-19 12:48:24 +00:00
var isAlwaysOpenHeader = $header . is ( ".always-open" ) ;
2014-04-08 11:43:26 +00:00
$header . css ( {
margin : "0px" ,
padding : "0px" ,
2024-09-19 12:48:24 +00:00
height :
( isAlwaysOpenHeader
? opts . alwaysOpenPanelHeaderHeight
: opts . panelHeaderHeight ) + "px" ,
2014-04-08 11:43:26 +00:00
} ) ;
2014-02-21 22:02:51 +00:00
} ) ;
2024-09-19 12:48:24 +00:00
$ ( "[layout-grid]" ) . css ( {
position : "relative" ,
} ) ;
$ ( "[layout-grid]" ) . children ( ) . css ( {
position : "absolute" ,
2014-02-21 22:02:51 +00:00
} ) ;
}
function requiredStyles ( ) {
var bodyStyle = {
2024-09-19 12:48:24 +00:00
margin : "0px" ,
padding : "0px" ,
overflow : "hidden" ,
2014-02-21 22:02:51 +00:00
} ;
if ( opts . allowBodyOverflow ) {
delete bodyStyle . overflow ;
}
2024-09-19 12:48:24 +00:00
$ ( "body" ) . css ( bodyStyle ) ;
2014-02-21 22:02:51 +00:00
requiredLayoutStyles ( ) ;
var curtainStyle = {
position : "absolute" ,
2024-09-19 12:48:24 +00:00
margin : "0px" ,
padding : "0px" ,
overflow : "hidden" ,
zIndex : 100 ,
2014-02-21 22:02:51 +00:00
} ;
2024-09-19 12:48:24 +00:00
$ ( ".curtain" ) . css ( curtainStyle ) ;
2014-02-21 22:02:51 +00:00
}
function hideAll ( ) {
2024-09-19 12:48:24 +00:00
$ ( "[layout]" ) . hide ( ) ;
2014-02-21 22:02:51 +00:00
$ ( '[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 ( ) ;
2024-09-19 12:48:24 +00:00
$ ( ".dialog-overlay" ) . hide ( ) ;
2014-02-21 22:02:51 +00:00
}
function tabClicked ( evt ) {
evt . preventDefault ( ) ;
2024-09-19 12:48:24 +00:00
var destination = $ ( evt . currentTarget ) . attr ( "tab-target" ) ;
$ ( "[tab-target]" ) . removeClass ( "selected" ) ;
$ ( evt . currentTarget ) . addClass ( "selected" ) ;
$ ( ".tab" ) . hide ( ) ;
2014-02-21 22:02:51 +00:00
$ ( '[tab-id="' + destination + '"]' ) . show ( ) ;
}
function linkClicked ( evt ) {
evt . preventDefault ( ) ;
var $currentTarget = $ ( evt . currentTarget ) ;
// allow links to be disabled
if ( $currentTarget . hasClass ( "disabled" ) ) {
return ;
}
2024-09-19 12:48:24 +00:00
var destination = $ ( evt . currentTarget ) . attr ( "layout-link" ) ;
2015-03-11 21:44:22 +00:00
var $destination = $ ( '[layout-id="' + destination + '"]' ) ;
2025-01-18 01:54:13 +00:00
//force user to the new site if they click on the jamtrack tile
if ( destination === "jamtrack" ) {
2025-01-24 02:40:27 +00:00
var urlToOpen = gon . spa _origin _url + '/jamtracks' ;
2025-01-18 01:54:13 +00:00
if ( gon . isNativeClient ) {
context . JK . popExternalLink ( urlToOpen ) ;
return ;
} else {
window . open ( urlToOpen , '_blank' ) ;
return ;
}
}
2015-03-11 21:44:22 +00:00
var destinationType = $destination . attr ( "layout" ) ;
2014-02-21 22:02:51 +00:00
if ( destinationType === "screen" ) {
2024-09-19 12:48:24 +00:00
if (
! context . JK . currentUserId &&
! $destination . is ( ".no-login-required" )
) {
2015-03-11 21:44:22 +00:00
// there is no user, and this item does not support 'no-login', so warn user
2024-09-19 12:48:24 +00:00
showDialog ( "login-required-dialog" ) ;
2015-03-11 21:44:22 +00:00
return ;
}
2024-09-19 12:48:24 +00:00
context . location = "/client#/" + destination ;
2014-02-21 22:02:51 +00:00
} else if ( destinationType === "dialog" ) {
showDialog ( destination ) ;
}
}
function close ( evt ) {
2024-09-19 12:48:24 +00:00
var $target = $ ( evt . currentTarget ) . closest ( "[layout]" ) ;
var layoutId = $target . attr ( "layout-id" ) ;
var isDialog = $target . attr ( "layout" ) === "dialog" ;
2014-02-21 22:02:51 +00:00
if ( isDialog ) {
closeDialog ( layoutId ) ;
} else {
$target . hide ( ) ;
}
return false ;
}
2014-09-22 19:20:58 +00:00
function cancel ( evt ) {
2024-09-19 12:48:24 +00:00
var $target = $ ( evt . currentTarget ) . closest ( "[layout]" ) ;
var layoutId = $target . attr ( "layout-id" ) ;
var isDialog = $target . attr ( "layout" ) === "dialog" ;
2014-09-22 19:20:58 +00:00
if ( isDialog ) {
cancelDialog ( layoutId ) ;
} else {
// ?
2024-09-19 12:48:24 +00:00
logger . warn ( "unable to handle cancel layout-action for %o" , $target ) ;
2014-09-22 19:20:58 +00:00
}
return false ;
}
function cancelDialog ( dialog ) {
logger . debug ( "cancelling dialog: " + dialog ) ;
var $dialog = $ ( '[layout-id="' + dialog + '"]' ) ;
2024-09-19 12:48:24 +00:00
var result = dialogEvent ( dialog , "onCancel" ) ;
if ( result !== false ) {
2014-09-22 19:20:58 +00:00
closeDialog ( dialog , true ) ;
2024-09-19 12:48:24 +00:00
} else {
2014-09-22 19:20:58 +00:00
logger . debug ( "dialog refused cancel" ) ;
}
}
function closeDialog ( dialog , canceled ) {
2014-03-20 11:53:26 +00:00
logger . debug ( "closing dialog: " + dialog ) ;
2014-02-21 22:02:51 +00:00
var $dialog = $ ( '[layout-id="' + dialog + '"]' ) ;
2024-09-19 12:48:24 +00:00
dialogEvent ( dialog , "beforeHide" ) ;
var $overlay = $ ( ".dialog-overlay" ) ;
2014-02-21 22:02:51 +00:00
unstackDialogs ( $overlay ) ;
$dialog . hide ( ) ;
2024-09-19 12:48:24 +00:00
$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" ) ;
2014-10-25 15:04:28 +00:00
$ . btOffAll ( ) ; // add any prod bubbles if you close a dialog
2014-02-21 22:02:51 +00:00
}
2016-04-06 02:23:15 +00:00
function screenProperty ( screen , property ) {
if ( screen && screen in screenBindings ) {
2024-09-19 12:48:24 +00:00
return screenBindings [ screen ] [ property ] ;
2016-04-06 02:23:15 +00:00
}
return null ;
}
2014-02-21 22:02:51 +00:00
function screenEvent ( screen , evtName , data ) {
if ( screen && screen in screenBindings ) {
if ( evtName in screenBindings [ screen ] ) {
2014-02-23 04:41:42 +00:00
return screenBindings [ screen ] [ evtName ] . call ( me , data ) ;
2014-02-21 22:02:51 +00:00
}
}
2014-04-09 17:25:52 +00:00
return NOT _HANDLED ;
2014-02-21 22:02:51 +00:00
}
function dialogEvent ( dialog , evtName , data ) {
if ( dialog && dialog in dialogBindings ) {
if ( evtName in dialogBindings [ dialog ] ) {
2014-04-09 17:25:52 +00:00
return dialogBindings [ dialog ] [ evtName ] . call ( me , data ) ;
2014-02-21 22:02:51 +00:00
}
}
2014-04-09 17:25:52 +00:00
return NOT _HANDLED ;
}
function activeElementEvent ( evtName , data ) {
var result = { } ;
var currDialog = currentDialog ( ) ;
2024-09-19 12:48:24 +00:00
if ( currDialog ) {
result . dialog = dialogEvent (
currDialog . attr ( "layout-id" ) ,
evtName ,
data
) ;
2014-04-09 17:25:52 +00:00
}
2024-09-19 12:48:24 +00:00
if ( currentScreen ) {
2014-04-09 17:25:52 +00:00
result . screen = screenEvent ( currentScreen , evtName , data ) ;
}
return result ;
2014-02-21 22:02:51 +00:00
}
2014-02-23 04:41:42 +00:00
function onHashChange ( e , postFunction ) {
2024-09-19 12:48:24 +00:00
if ( currentHash == context . location . hash ) {
return ;
}
2014-02-23 04:41:42 +00:00
2024-09-19 12:48:24 +00:00
if ( resettingHash ) {
2014-02-23 04:41:42 +00:00
resettingHash = false ;
e . preventDefault ( ) ;
return false ;
}
try {
var location = context . RouteMap . parse ( context . location . hash ) ;
2024-09-19 12:48:24 +00:00
} catch ( e ) {
2014-02-23 04:41:42 +00:00
// this is nowhere in the rich client; just let it go through
return postFunction ( e ) ;
}
2014-02-22 18:43:11 +00:00
2014-02-23 04:41:42 +00:00
var screen = location . page . substring ( 1 ) ; // remove leading slash
2024-09-19 12:48:24 +00:00
var accepted = screenEvent ( currentScreen , "beforeLeave" , {
screen : screen ,
hash : context . location . hash ,
} ) ;
if ( accepted === false ) {
logger . debug (
"navigation to " +
context . location . hash +
" rejected by " +
currentScreen
) ;
2014-02-25 19:22:32 +00:00
//resettingHash = true;
2014-02-23 04:41:42 +00:00
// reset the hash to where it just was
context . location . hash = currentHash ;
2024-09-19 12:48:24 +00:00
} else {
screen ;
2014-02-23 04:41:42 +00:00
return postFunction ( e ) ;
}
2014-02-22 18:43:11 +00:00
}
2014-02-21 22:02:51 +00:00
function changeToScreen ( screen , data ) {
2014-02-23 04:41:42 +00:00
changeScreen ( screen , data ) ;
2014-02-22 18:43:11 +00:00
}
function changeScreen ( screen , data ) {
2014-02-21 22:02:51 +00:00
previousScreen = currentScreen ;
currentScreen = screen ;
2014-02-23 04:41:42 +00:00
currentHash = context . location . hash ;
2024-09-19 12:48:24 +00:00
var accepted = screenEvent ( previousScreen , "beforeHide" , data ) ;
if ( accepted === false ) return ;
2014-02-21 22:02:51 +00:00
2015-03-11 21:44:22 +00:00
logger . debug ( "layout: changing screen to " + currentScreen ) ;
2014-02-24 18:54:19 +00:00
2016-04-06 02:23:15 +00:00
// notify everyone
2024-09-19 12:48:24 +00:00
$ ( document ) . triggerHandler ( EVENTS . SCREEN _CHANGED , {
previousScreen : previousScreen ,
newScreen : currentScreen ,
} ) ;
window . NavActions . screenChanged (
currentScreen ,
screenProperty ( currentScreen , "navName" )
) ;
context . JamTrackPreviewActions . screenChange ( ) ;
2015-08-18 19:26:41 +00:00
2024-09-19 12:48:24 +00:00
screenEvent ( currentScreen , "beforeShow" , data ) ;
2014-02-21 22:02:51 +00:00
// 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 ( ) ;
2014-06-09 03:26:50 +00:00
// add an attribute to any dialogs, which let's it know it's current screen (useful for contextual styling)
2024-09-19 12:48:24 +00:00
context . _ . each ( openDialogs , function ( dialog ) {
2014-06-09 03:26:50 +00:00
addScreenContextToDialog ( $ ( dialog ) ) ;
2024-09-19 12:48:24 +00:00
} ) ;
2014-06-09 03:26:50 +00:00
2024-09-19 12:48:24 +00:00
screenEvent ( previousScreen , "afterHide" , data ) ;
screenEvent ( currentScreen , "afterShow" , data ) ;
2014-10-25 15:04:28 +00:00
jQuery . btOffAll ( ) ; // add any prod bubbles if you change screens
2014-02-21 22:02:51 +00:00
// Show any requested dialog
if ( "d" in data ) {
2024-09-19 12:48:24 +00:00
// 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 ;
}
}
2014-03-20 11:53:26 +00:00
showDialog ( data . d , data ) ;
2014-02-21 22:02:51 +00:00
}
}
2024-09-19 12:48:24 +00:00
function isTextMessageInUrl ( ) {
2024-10-22 16:41:39 +00:00
var hash = context . location . hash ;
var regexp = /\S+\/text-message\/d1=/
2024-09-19 12:48:24 +00:00
return regexp . test ( hash ) ;
}
2014-09-22 19:20:58 +00:00
// 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
2014-03-26 17:09:48 +00:00
function isDialogShowing ( ) {
2024-09-19 12:48:24 +00:00
if ( arguments . length == 1 ) {
2014-09-22 19:20:58 +00:00
// user passed in dialog id
var dialogId = arguments [ 0 ] ;
2024-09-19 12:48:24 +00:00
var result = false ;
context . _ . each ( openDialogs , function ( dialog ) {
if ( $ ( dialog ) . attr ( "layout-id" ) == dialogId ) {
2016-04-21 14:23:29 +00:00
result = true ;
return false ;
2014-09-22 19:20:58 +00:00
}
2024-09-19 12:48:24 +00:00
} ) ;
2016-04-21 14:23:29 +00:00
return result ;
2024-09-19 12:48:24 +00:00
} else {
2014-09-22 19:20:58 +00:00
// user passed in nothing
return openDialogs . length > 0 ;
}
2014-03-26 17:09:48 +00:00
}
2014-03-27 18:43:15 +00:00
function currentDialog ( ) {
2024-09-19 12:48:24 +00:00
if ( openDialogs . length == 0 ) return null ;
2014-03-27 18:43:15 +00:00
return openDialogs [ openDialogs . length - 1 ] ;
}
// payload is a notification event from websocket gateway
function dialogObscuredNotification ( payload ) {
2024-09-19 12:48:24 +00:00
var openDialog = currentDialog ( ) ;
if ( ! openDialog ) return false ;
2014-03-27 18:43:15 +00:00
2024-09-19 12:48:24 +00:00
if ( typeof openDialog . handledNotification === "function" ) {
return ! openDialog . handledNotification ( payload ) ;
} else {
return true ;
}
2014-03-27 18:43:15 +00:00
}
2014-04-03 14:11:23 +00:00
// payload is a notification event from websocket gateway
function isNoisyNotification ( payload ) {
var openDialog = currentDialog ( ) ;
2024-09-19 12:48:24 +00:00
if ( ! openDialog ) return false ;
2014-04-03 14:11:23 +00:00
2024-09-19 12:48:24 +00:00
if ( typeof openDialog . isNoisyNotification === "function" ) {
2014-04-03 14:11:23 +00:00
return ! openDialog . isNoisyNotification ( payload ) ;
2024-09-19 12:48:24 +00:00
} else {
2014-04-03 14:11:23 +00:00
return true ;
}
}
2014-02-21 22:02:51 +00:00
/ * *
* 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
2024-09-19 12:48:24 +00:00
var layoutId = $dialog . attr ( "layout-id" ) ;
2014-02-21 22:02:51 +00:00
for ( var i = openDialogs . length - 1 ; i >= 0 ; i -- ) {
2024-09-19 12:48:24 +00:00
if ( openDialogs [ i ] . attr ( "layout-id" ) === layoutId ) {
2014-02-21 22:02:51 +00:00
openDialogs . splice ( i , 1 ) ;
}
}
2014-02-22 07:20:53 +00:00
// pull out a topmost one, if present
var topMost = null ;
for ( var i = openDialogs . length - 1 ; i >= 0 ; i -- ) {
2024-09-19 12:48:24 +00:00
if ( openDialogs [ i ] . attr ( "topmost" ) === "true" ) {
2014-02-22 07:20:53 +00:00
topMost = openDialogs [ i ] ;
openDialogs . splice ( i , 1 ) ;
}
}
2014-02-21 22:02:51 +00:00
openDialogs . push ( $dialog ) ;
2024-09-19 12:48:24 +00:00
if ( topMost ) openDialogs . push ( topMost ) ;
2014-02-22 07:20:53 +00:00
2014-02-21 22:02:51 +00:00
var zIndex = 1000 ;
for ( var i in openDialogs ) {
var $openDialog = openDialogs [ i ] ;
2024-09-19 12:48:24 +00:00
$openDialog . css ( "zIndex" , zIndex ) ;
2014-02-21 22:02:51 +00:00
zIndex ++ ;
}
2024-09-19 12:48:24 +00:00
$overlay . css ( "zIndex" , zIndex - 1 ) ;
2014-02-21 22:02:51 +00:00
}
function unstackDialogs ( $overlay ) {
if ( openDialogs . length > 0 ) {
openDialogs . pop ( ) ;
}
var zIndex = 1000 + openDialogs . length ;
2024-09-19 12:48:24 +00:00
$overlay . css ( "zIndex" , zIndex - 1 ) ;
2014-02-21 22:02:51 +00:00
if ( openDialogs . length == 0 ) {
$overlay . hide ( ) ;
}
}
2014-06-09 03:26:50 +00:00
function addScreenContextToDialog ( $dialog ) {
2024-09-19 12:48:24 +00:00
$dialog . attr ( "current-screen" , currentScreen ) ; // useful for contextual styling of dialogs
2014-06-09 03:26:50 +00:00
}
2014-02-22 07:20:53 +00:00
function showDialog ( dialog , options ) {
2024-09-19 12:48:24 +00:00
if ( dialogEvent ( dialog , "beforeShow" , options ) === false ) {
2014-06-25 21:54:31 +00:00
return null ;
2014-02-21 22:02:51 +00:00
}
2024-09-19 12:48:24 +00:00
logger . debug ( "opening dialog: " + dialog ) ;
2015-03-11 21:44:22 +00:00
2016-04-06 02:23:15 +00:00
var $dialog = $ ( '[layout-id="' + dialog + '"]' ) ;
2024-09-19 12:48:24 +00:00
if ( $dialog . length == 0 ) {
logger . debug ( "unknown dialog encountered: " + dialog ) ;
return ;
2016-04-06 02:23:15 +00:00
}
2024-09-19 12:48:24 +00:00
var $overlay = $ ( ".dialog-overlay" ) ;
2014-02-21 22:02:51 +00:00
if ( opts . sizeOverlayToContent ) {
2024-09-19 12:48:24 +00:00
var $body = $ ( "body" ) ;
$ ( ".dialog-overlay" ) . css ( {
width : $body . width ( ) + "px" ,
height : $body . height ( ) + "px" ,
2014-02-21 22:02:51 +00:00
} ) ;
}
$overlay . show ( ) ;
centerDialog ( dialog ) ;
stackDialogs ( $dialog , $overlay ) ;
2024-09-19 12:48:24 +00:00
addScreenContextToDialog ( $dialog ) ;
2014-02-21 22:02:51 +00:00
$dialog . show ( ) ;
2016-01-19 00:41:53 +00:00
// maintain center (un-attach previous sensor if applicable, then re-add always)
2016-04-06 02:23:15 +00:00
2024-09-19 12:48:24 +00:00
window . ResizeSensor . detach ( $dialog . get ( 0 ) ) ;
new window . ResizeSensor ( $dialog , function ( ) {
2016-01-19 00:41:53 +00:00
centerDialog ( dialog ) ;
} ) ;
2024-09-19 12:48:24 +00:00
dialogEvent ( dialog , "afterShow" , options ) ;
2014-10-25 15:04:28 +00:00
$ . btOffAll ( ) ; // add any prod bubbles if you open a dailog
2014-06-09 03:26:50 +00:00
return $dialog ;
2014-02-21 22:02:51 +00:00
}
function centerDialog ( dialog ) {
var $dialog = $ ( '[layout-id="' + dialog + '"]' ) ;
$dialog . css ( {
2024-09-19 12:48:24 +00:00
left : width / 2 - $dialog . width ( ) / 2 + "px" ,
top : height / 2 - $dialog . height ( ) / 2 + "px" ,
2014-02-21 22:02:51 +00:00
} ) ;
}
function panelHeaderClicked ( evt ) {
evt . preventDefault ( ) ;
2015-03-11 21:44:22 +00:00
2024-09-19 12:48:24 +00:00
if ( ! context . JK . currentUserId ) {
showDialog ( "login-required-dialog" ) ;
2015-03-11 21:44:22 +00:00
return false ;
}
2024-09-19 12:48:24 +00:00
expandedPanel = $ ( evt . currentTarget )
. closest ( '[layout="panel"]' )
. attr ( "layout-id" ) ;
2014-02-21 22:02:51 +00:00
layout ( ) ;
return false ;
}
2024-09-19 12:48:24 +00:00
function expandNotificationPanel ( ) {
if ( ! context . JK . currentUserId ) {
showDialog ( "login-required-dialog" ) ;
2021-04-10 02:45:51 +00:00
return false ;
}
2024-09-19 12:48:24 +00:00
expandedPanel = "panelNotifications" ;
2021-04-10 02:45:51 +00:00
layout ( ) ;
return false ;
}
2014-02-21 22:02:51 +00:00
function wizardLinkClicked ( evt ) {
evt . preventDefault ( ) ;
var targetStepId = $ ( evt . currentTarget ) . attr ( "layout-wizard-link" ) ;
setWizardStep ( targetStepId ) ;
return false ;
}
function startNewFtue ( ) {
2014-05-29 19:14:46 +00:00
// var step = 0;
2014-05-27 15:23:16 +00:00
//setWizardStep(step);
//wizardShowFunctions[step]();
2024-09-19 12:48:24 +00:00
return showDialog ( "gear-wizard" ) ;
2014-02-21 22:02:51 +00:00
}
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"]' ) ;
2024-09-19 12:48:24 +00:00
var $myTitle = $ ( ".content-head h1" , $myDialog ) ;
2014-02-21 22:02:51 +00:00
$myTitle . html ( stepDialogTitle ) ;
}
// Hide all steps:
// Invoke the 'show' function, if present prior to actually showing.
2024-09-19 12:48:24 +00:00
if (
context . _ . contains ( context . _ . keys ( wizardShowFunctions ) , targetStepId )
) {
2014-02-21 22:02:51 +00:00
wizardShowFunctions [ targetStepId ] ( ) ;
}
2024-09-19 12:48:24 +00:00
$ ( "[layout-wizard-step]" ) . hide ( ) ;
2014-02-21 22:02:51 +00:00
$targetStep . show ( ) ;
var ftuePurpose = $targetStep . attr ( "dialog-purpose" ) ;
context . JK . GA . trackFTUECompletion ( ftuePurpose , context . JK . detectOS ( ) ) ;
}
function trackLocationChange ( e ) {
2024-09-19 12:48:24 +00:00
context . JK . GA . virtualPageView (
location . pathname + location . search + location . hash
) ;
2014-02-21 22:02:51 +00:00
}
2014-09-22 19:20:58 +00:00
function onHandleKey ( e ) {
2024-09-19 12:48:24 +00:00
if ( e . keyCode == 27 /** esc */ ) {
if ( isDialogShowing ( ) ) {
var $dialog = currentDialog ( ) ;
if ( ! $dialog ) {
logger . error ( "unable to find current dialog on ESC" ) ;
return ;
2014-09-22 19:20:58 +00:00
}
2024-09-19 12:48:24 +00:00
cancelDialog ( $dialog . attr ( "layout-id" ) ) ;
}
2014-09-22 19:20:58 +00:00
}
}
2014-02-21 22:02:51 +00:00
function handleDialogState ( ) {
2024-09-19 12:48:24 +00:00
var rawDialogState = $ . cookie ( "dialog_state" ) ;
2014-02-21 22:02:51 +00:00
try {
var dialogState = JSON . parse ( rawDialogState ) ;
if ( ! dialogState ) {
2024-09-19 12:48:24 +00:00
$ . removeCookie ( "dialog_state" ) ;
2014-02-21 22:02:51 +00:00
return ;
}
2024-09-19 12:48:24 +00:00
} catch ( e ) {
$ . removeCookie ( "dialog_state" ) ;
2014-02-21 22:02:51 +00:00
return ;
}
2024-09-19 12:48:24 +00:00
var dialogName = dialogState [ "name" ] ;
2014-02-21 22:02:51 +00:00
if ( dialogName ) {
setTimeout ( function ( ) {
// TODO: we need a 'everything is initialized' event
showDialog ( dialogName ) ;
} , 0 ) ;
}
2024-09-19 12:48:24 +00:00
$ . removeCookie ( "dialog_state" ) ;
2014-02-21 22:02:51 +00:00
}
// on next page load, a dialog of this name will show
function queueDialog ( name ) {
2024-09-19 12:48:24 +00:00
$ . cookie ( "dialog_state" , JSON . stringify ( { name : name } ) ) ;
2014-02-21 22:02:51 +00:00
}
function events ( ) {
$ ( context ) . resize ( function ( ) {
if ( resizing ) {
context . clearTimeout ( resizing ) ;
}
resizing = context . setTimeout ( layout , 80 ) ;
} ) ;
2024-09-19 12:48:24 +00:00
$ ( "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 ) ;
2014-09-22 19:20:58 +00:00
$ ( document ) . keyup ( onHandleKey ) ;
2014-02-21 22:02:51 +00:00
}
// public functions
this . getOpts = function ( ) {
return opts ;
} ;
2013-06-10 05:24:33 +00:00
2014-02-21 22:02:51 +00:00
// used for concurrent notifications
var notifyQueue = [ ] ;
2021-04-10 02:45:51 +00:00
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"]' ) ;
2024-09-19 12:48:24 +00:00
$notify1 . on ( "mouseenter" , mouseEnterNotification ) ;
$notify1 . on ( "mouseleave" , mouseLeaveToNotification ) ;
$notify2 . on ( "mouseenter" , mouseEnterNotification ) ;
$notify2 . on ( "mouseleave" , mouseLeaveToNotification ) ;
$notify3 . on ( "mouseenter" , mouseEnterNotification ) ;
$notify3 . on ( "mouseleave" , mouseLeaveToNotification ) ;
2021-04-10 02:45:51 +00:00
2024-09-19 12:48:24 +00:00
function mouseEnterNotification ( evt ) {
2021-04-10 02:45:51 +00:00
var $notify = $ ( evt . target ) ;
2021-04-11 18:33:59 +00:00
//console.log("mouseEnter", $notify.prop("id"));
2024-09-19 12:48:24 +00:00
switch ( $notify . prop ( "id" ) ) {
case "notification1" :
2021-04-10 02:45:51 +00:00
isMouseOverNotify1 = true ;
2024-09-19 12:48:24 +00:00
break ;
case "notification2" :
2021-04-10 02:45:51 +00:00
isMouseOverNotify2 = true ;
2024-09-19 12:48:24 +00:00
break ;
case "notification3" :
2021-04-10 02:45:51 +00:00
isMouseOverNotify3 = true ;
2024-09-19 12:48:24 +00:00
break ;
2021-04-10 02:45:51 +00:00
}
}
2024-09-19 12:48:24 +00:00
function mouseLeaveToNotification ( evt ) {
2021-04-10 02:45:51 +00:00
var $notify = $ ( evt . target ) ;
2021-04-11 18:33:59 +00:00
//console.log("mouseLeave", $notify.prop("id"));
2024-09-19 12:48:24 +00:00
switch ( $notify . prop ( "id" ) ) {
case "notification1" :
if ( notify1Elapsed ) {
2021-04-10 02:45:51 +00:00
$notify1 . hide ( 0 ) ;
notify1Showing = false ;
}
isMouseOverNotify1 = false ;
2024-09-19 12:48:24 +00:00
break ;
case "notification2" :
if ( notify2Elapsed ) {
2021-04-10 02:45:51 +00:00
$notify2 . hide ( 0 ) ;
notify2Showing = false ;
}
isMouseOverNotify2 = false ;
2024-09-19 12:48:24 +00:00
break ;
case "notification3" :
if ( notify3Elapsed ) {
2021-04-10 02:45:51 +00:00
$notify3 . hide ( 0 ) ;
notify3Showing = false ;
}
isMouseOverNotify3 = false ;
2024-09-19 12:48:24 +00:00
break ;
2021-04-10 02:45:51 +00:00
}
}
//var firstNotification = false;
//var notifyDetails;
2012-10-06 16:36:05 +00:00
2014-05-13 05:22:23 +00:00
var okButton = {
id : "btn-okay" ,
text : "OKAY" ,
"layout-action" : "close" ,
href : "#" ,
2024-09-19 12:48:24 +00:00
class : "button-orange" ,
2014-05-13 05:22:23 +00:00
} ;
var cancelButton = {
id : "btn-cancel" ,
text : "CANCEL" ,
"layout-action" : "close" ,
href : "#" ,
2024-09-19 12:48:24 +00:00
class : "button-grey" ,
2014-05-13 05:22:23 +00:00
} ;
2024-09-19 12:48:24 +00:00
var defaultButtons = [ okButton , cancelButton ] ;
2014-05-13 05:22:23 +00:00
2021-04-10 02:45:51 +00:00
// 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)
// };
2014-05-14 05:16:33 +00:00
this . notify = function ( message , buttons , noCancel ) {
2021-04-10 02:45:51 +00:00
console . log ( "call this.notify" ) ;
2014-05-13 05:22:23 +00:00
if ( ! buttons ) {
2014-05-14 05:16:33 +00:00
if ( noCancel ) {
2014-05-14 05:51:18 +00:00
buttons = [ okButton ] ;
2024-09-19 12:48:24 +00:00
} else {
2014-05-14 05:16:33 +00:00
buttons = defaultButtons ;
}
2014-05-13 05:22:23 +00:00
}
2024-09-19 12:48:24 +00:00
notifyQueue . push ( { message : message , descriptor : buttons } ) ;
2013-05-20 01:54:24 +00:00
2021-04-10 02:45:51 +00:00
showNotificationToast ( ) ;
2024-09-19 12:48:24 +00:00
} ;
2021-04-10 02:45:51 +00:00
2024-09-19 12:48:24 +00:00
function showNotificationToast ( ) {
if ( ! notify1Showing ) {
2021-04-10 02:45:51 +00:00
var notifyDetails1 = notifyQueue . shift ( ) ;
if ( notifyDetails1 !== undefined ) {
2024-09-19 12:48:24 +00:00
setNotificationInfo (
notifyDetails1 . message ,
notifyDetails1 . descriptor ,
$notify1
) ;
2021-04-10 02:45:51 +00:00
notify1Elapsed = false ;
2024-09-19 12:48:24 +00:00
$notify1 . hide ( 0 ) . show ( {
2021-04-10 02:45:51 +00:00
duration : 0 ,
//queue: true,
complete : function ( ) {
2024-09-19 12:48:24 +00:00
console . log ( "Show notification1" ) ;
2021-04-10 02:45:51 +00:00
notify1Showing = true ;
notifyDetails1 = { } ;
2024-09-19 12:48:24 +00:00
} ,
} ) ;
2021-04-10 02:45:51 +00:00
//.delay(8000);
2024-09-19 12:48:24 +00:00
setTimeout ( function ( ) {
2021-04-10 02:45:51 +00:00
notify1Elapsed = true ;
2024-09-19 12:48:24 +00:00
if ( ! isMouseOverNotify1 ) {
$notify1 . hide ( 0 , function ( ) {
2021-04-10 02:45:51 +00:00
notify1Showing = false ;
2024-09-19 12:48:24 +00:00
console . log ( "Hide notification1" ) ;
} ) ;
2021-04-10 02:45:51 +00:00
}
2024-09-19 12:48:24 +00:00
} , 8000 ) ;
2021-04-10 02:45:51 +00:00
}
2024-09-19 12:48:24 +00:00
} else if ( ! notify2Showing ) {
2021-04-10 02:45:51 +00:00
var notifyDetails2 = notifyQueue . shift ( ) ;
if ( notifyDetails2 !== undefined ) {
2024-09-19 12:48:24 +00:00
setNotificationInfo (
notifyDetails2 . message ,
notifyDetails2 . descriptor ,
$notify2
) ;
2021-04-10 02:45:51 +00:00
notify2Elapsed = false ;
2024-09-19 12:48:24 +00:00
$notify2 . hide ( 0 ) . show ( {
2021-04-10 02:45:51 +00:00
duration : 0 ,
//queue: true,
complete : function ( ) {
2024-09-19 12:48:24 +00:00
console . log ( "Show notification2" ) ;
2021-04-10 02:45:51 +00:00
notify2Showing = true ;
notifyDetails2 = { } ;
2024-09-19 12:48:24 +00:00
} ,
2021-04-10 02:45:51 +00:00
} ) ;
// .delay(8000)
// .hide(0, function(){
// notify2Showing = false;
// console.log("Hide notification2")
// })
2024-09-19 12:48:24 +00:00
setTimeout ( function ( ) {
2021-04-10 02:45:51 +00:00
notify2Elapsed = true ;
2024-09-19 12:48:24 +00:00
if ( ! isMouseOverNotify2 ) {
$notify2 . hide ( 0 , function ( ) {
2021-04-10 02:45:51 +00:00
notify2Showing = false ;
2024-09-19 12:48:24 +00:00
console . log ( "Hide notification2" ) ;
} ) ;
2013-10-21 22:13:53 +00:00
}
2021-04-10 02:45:51 +00:00
} , 8000 ) ;
}
2024-09-19 12:48:24 +00:00
} else if ( ! notify3Showing ) {
2021-04-10 02:45:51 +00:00
var notifyDetails3 = notifyQueue . shift ( ) ;
if ( notifyDetails3 !== undefined ) {
2024-09-19 12:48:24 +00:00
setNotificationInfo (
notifyDetails3 . message ,
notifyDetails3 . descriptor ,
$notify3
) ;
2021-04-10 02:45:51 +00:00
notify3Elapsed = false ;
2024-09-19 12:48:24 +00:00
$notify3 . hide ( 0 ) . show ( {
2021-04-10 02:45:51 +00:00
duration : 0 ,
//queue: true,
complete : function ( ) {
2024-09-19 12:48:24 +00:00
console . log ( "Show notification3" ) ;
2021-04-10 02:45:51 +00:00
notify3Showing = true ;
notifyDetails3 = { } ;
2024-09-19 12:48:24 +00:00
} ,
} ) ;
2021-04-10 02:45:51 +00:00
// .delay(8000)
// .hide(0, function(){
// notify3Showing = false;
// console.log("Hide notification3")
// })
2024-09-19 12:48:24 +00:00
setTimeout ( function ( ) {
2021-04-10 02:45:51 +00:00
notify3Elapsed = true ;
2024-09-19 12:48:24 +00:00
if ( ! isMouseOverNotify3 ) {
$notify3 . hide ( 0 , function ( ) {
2021-04-10 02:45:51 +00:00
notify3Showing = false ;
2024-09-19 12:48:24 +00:00
console . log ( "Hide notification3" ) ;
} ) ;
2013-10-21 22:13:53 +00:00
}
2021-04-10 02:45:51 +00:00
} , 8000 ) ;
}
2024-09-19 12:48:24 +00:00
} else if ( notify1Showing && notify2Showing && notify3Showing ) {
2021-04-10 02:45:51 +00:00
//try again after 1 second
2024-09-19 12:48:24 +00:00
setTimeout ( function ( ) {
showNotificationToast ( ) ;
} , 1000 ) ;
2021-04-10 02:45:51 +00:00
}
}
// 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;
// }
// });
// });
// }
2013-10-21 22:13:53 +00:00
2014-05-13 05:22:23 +00:00
function setNotificationInfo ( message , buttons , notificationSelector ) {
2021-04-10 02:45:51 +00:00
var $notify = notificationSelector ;
2024-09-19 12:48:24 +00:00
$ ( "h2" , $notify ) . text ( message . title ) ;
$ ( "p" , $notify ) . empty ( ) ;
2014-02-21 22:02:51 +00:00
if ( message . text instanceof jQuery ) {
2024-09-19 12:48:24 +00:00
$ ( "p" , $notify ) . append ( message . text ) ;
} else {
$ ( "p" , $notify ) . html ( message . text ) ;
2014-02-21 22:02:51 +00:00
}
if ( message . icon _url ) {
2024-09-19 12:48:24 +00:00
$ ( "#avatar" , $notify ) . attr ( "src" , message . icon _url ) ;
$ ( "#notify-avatar" , $notify ) . show ( ) ;
} else {
$ ( "#notify-avatar" , $notify ) . hide ( ) ;
2014-02-21 22:02:51 +00:00
}
if ( message . detail ) {
2024-09-19 12:48:24 +00:00
$ ( "div.detail" , $notify ) . html ( message . detail ) . show ( ) ;
} else {
$ ( "div.detail" , $notify ) . hide ( ) ;
2014-02-21 22:02:51 +00:00
}
2024-09-19 12:48:24 +00:00
var $buttonDiv = $ ( "#buttons" , $notify ) ;
2014-05-13 05:22:23 +00:00
$buttonDiv . empty ( ) ;
2014-03-08 06:37:25 +00:00
2024-09-19 12:48:24 +00:00
$ . each ( buttons , function ( index , val ) {
2014-05-18 04:09:21 +00:00
// build button HTML based on KV pairs
var keys = Object . keys ( val ) ;
2024-09-19 12:48:24 +00:00
var buttonHtml = "<a" ;
2014-05-18 04:09:21 +00:00
2024-09-19 12:48:24 +00:00
for ( var i = 0 ; i < keys . length ; i ++ ) {
2014-05-27 03:52:59 +00:00
//console.log("keys[i]=%o, val[keys[i]]=%o", keys[i], val[keys[i]]);
2014-05-18 04:09:21 +00:00
// ignore button text and callback info
2024-09-19 12:48:24 +00:00
if (
keys [ i ] !== "text" &&
keys [ i ] !== "callback" &&
keys [ i ] !== "callback_args"
) {
buttonHtml += " " + keys [ i ] + '="' + val [ keys [ i ] ] + '"' ;
2014-05-18 04:09:21 +00:00
}
}
2024-09-19 12:48:24 +00:00
buttonHtml += ">" + val [ "text" ] + "</a> " ;
2014-05-18 04:09:21 +00:00
$buttonDiv . append ( buttonHtml ) ;
2013-05-26 00:55:30 +00:00
2014-05-13 05:22:23 +00:00
// ensure it doesn't fire twice
2024-09-19 12:48:24 +00:00
$ ( "#" + val . id , $notify ) . unbind ( "click" ) ;
2014-05-13 05:22:23 +00:00
2024-09-19 12:48:24 +00:00
$ ( "#" + val . id , $notify ) . click ( function ( ) {
2014-05-13 05:22:23 +00:00
if ( val . callback !== undefined ) {
if ( val . callback _args ) {
val . callback ( val . callback _args ) ;
2024-09-19 12:48:24 +00:00
} else {
2014-05-13 05:22:23 +00:00
val . callback ( ) ;
2014-02-07 14:07:08 +00:00
}
2014-05-13 05:22:23 +00:00
return false ;
2024-09-19 12:48:24 +00:00
} else {
2021-04-10 02:45:51 +00:00
$notify . hide ( ) ;
2014-07-24 03:26:54 +00:00
return false ;
2014-03-08 06:37:25 +00:00
}
} ) ;
2014-05-13 05:22:23 +00:00
} ) ;
2014-02-21 22:02:51 +00:00
}
2014-02-07 14:07:08 +00:00
2014-02-21 22:02:51 +00:00
this . setWizardStep = setWizardStep ;
this . startNewFtue = startNewFtue ;
2012-09-21 04:46:45 +00:00
2014-02-21 22:02:51 +00:00
this . changeToScreen = function ( screen , data ) {
changeToScreen ( screen , data ) ;
} ;
2012-09-21 04:46:45 +00:00
2024-09-19 12:48:24 +00:00
this . onHashChange = function ( e , postFunction ) {
2014-02-23 04:41:42 +00:00
return onHashChange ( e , postFunction ) ;
2024-09-19 12:48:24 +00:00
} ;
2014-02-23 04:41:42 +00:00
2014-03-20 11:53:26 +00:00
this . showDialog = function ( dialog , options ) {
2014-06-09 03:26:50 +00:00
return showDialog ( dialog , options ) ;
2014-02-21 22:02:51 +00:00
} ;
2013-08-10 17:37:09 +00:00
2024-09-19 12:48:24 +00:00
this . dialogObscuredNotification = function ( payload ) {
2014-04-03 14:11:23 +00:00
return dialogObscuredNotification ( payload ) ;
2024-09-19 12:48:24 +00:00
} ;
2014-04-03 14:11:23 +00:00
2024-09-19 12:48:24 +00:00
this . isNoisyNotification = function ( payload ) {
2014-04-03 14:11:23 +00:00
return isNoisyNotification ( payload ) ;
2024-09-19 12:48:24 +00:00
} ;
2014-03-27 18:43:15 +00:00
2024-09-19 12:48:24 +00:00
this . shouldFreezeAppOnDisconnect = function ( ) {
2014-04-09 17:25:52 +00:00
return shouldFreezeAppOnDisconnect ( ) ;
2024-09-19 12:48:24 +00:00
} ;
2014-04-09 17:25:52 +00:00
2024-09-19 12:48:24 +00:00
this . isDialogShowing = function ( ) {
2016-04-21 14:23:29 +00:00
return isDialogShowing ( arguments [ 0 ] ) ;
2024-09-19 12:48:24 +00:00
} ;
2014-03-26 17:09:48 +00:00
2024-09-19 12:48:24 +00:00
this . activeElementEvent = function ( evtName , data ) {
2014-04-09 17:25:52 +00:00
return activeElementEvent ( evtName , data ) ;
2024-09-19 12:48:24 +00:00
} ;
2014-04-09 17:25:52 +00:00
2024-09-19 12:48:24 +00:00
this . getCurrentScreen = function ( ) {
2014-06-09 03:26:50 +00:00
return currentScreen ; // will be a string of the layout-id of the active screen
2024-09-19 12:48:24 +00:00
} ;
2021-04-10 02:45:51 +00:00
2014-02-21 22:02:51 +00:00
this . close = function ( evt ) {
close ( evt ) ;
} ;
2013-10-21 22:13:53 +00:00
2024-09-19 12:48:24 +00:00
this . beforeDisconnect = function ( ) {
2014-04-09 17:25:52 +00:00
fireEvents ( ) ;
2024-09-19 12:48:24 +00:00
} ;
2014-04-09 17:25:52 +00:00
2024-09-19 12:48:24 +00:00
this . afterReconnect = function ( ) {
2014-04-09 17:25:52 +00:00
fireEvents ( ) ;
2024-09-19 12:48:24 +00:00
} ;
2014-04-09 17:25:52 +00:00
2014-02-21 22:02:51 +00:00
this . closeDialog = closeDialog ;
2014-09-22 19:20:58 +00:00
this . cancelDialog = cancelDialog ;
2014-02-21 22:02:51 +00:00
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 .
* /
2024-09-19 12:48:24 +00:00
this . getCardLayout = function (
gridWidth ,
gridHeight ,
gridRows ,
gridCols ,
row ,
col ,
rowspan ,
colspan
) {
2014-02-21 22:02:51 +00:00
var _gridWidth = gridWidth + 3 * opts . gridPadding ;
var _gridHeight = gridHeight + 3 * opts . gridPadding ;
var cellWidth , cellHeight , top , left , width , height ;
2024-09-19 12:48:24 +00:00
cellWidth = Math . floor (
( _gridWidth - 2 * opts . gridOuterMargin ) / gridCols
) ;
cellHeight = Math . floor (
( _gridHeight - 2 * opts . gridOuterMargin ) / gridRows
) ;
2014-02-21 22:02:51 +00:00
width = colspan * cellWidth - 2 * opts . gridPadding ;
height = rowspan * cellHeight - 2 * opts . gridPadding ;
2024-09-19 12:48:24 +00:00
top = row * cellHeight ; // + opts.gridOuterMargin; // + opts.gridPadding;
left = col * cellWidth ; // + opts.gridOuterMargin; // + opts.gridPadding;
2014-02-21 22:02:51 +00:00
return {
top : top ,
left : left ,
width : width ,
2024-09-19 12:48:24 +00:00
height : height ,
2014-02-21 22:02:51 +00:00
} ;
} ;
2013-08-10 17:37:09 +00:00
2014-02-21 22:02:51 +00:00
this . bindScreen = function ( screen , handler ) {
screenBindings [ screen ] = handler ;
} ;
2014-02-13 22:57:48 +00:00
2014-02-21 22:02:51 +00:00
this . bindDialog = function ( dialog , handler ) {
dialogBindings [ dialog ] = handler ;
} ;
2013-03-31 13:54:00 +00:00
2014-02-21 22:02:51 +00:00
this . registerWizardStepFunction = function ( stepId , showFunction ) {
wizardShowFunctions [ stepId ] = showFunction ;
} ;
2013-03-31 13:54:00 +00:00
2014-02-21 22:02:51 +00:00
this . initialize = function ( inOpts ) {
me = this ;
opts = $ . extend ( opts , inOpts ) ;
setup ( ) ;
events ( ) ;
} ;
2012-11-03 00:29:58 +00:00
2024-09-19 12:48:24 +00:00
this . expandNotificationPanel = function ( ) {
return expandNotificationPanel ( ) ;
} ;
2021-04-10 02:45:51 +00:00
2014-02-21 22:02:51 +00:00
return this ;
} ;
2024-09-19 12:48:24 +00:00
} ) ( window , jQuery ) ;