Files
EasySoft-ZenTaoPMS/module/index/js/index.js
T

870 lines
29 KiB
JavaScript

(function()
{
if(showFeatures)
{
/* Show features dialog. */
new $.zui.ModalTrigger({url: $.createLink('misc', 'features'), type: 'iframe', width: 900, showHeader: false, backdrop: 'static'}).show();
}
/* Init variables */
var openedApps = {}; // Key-value to save appCode-app pairs
var appsMap = {}; // Key-value to save opened appCode-app pairs
var openedAppZIndex = 10; // Last opened app z-index
var defaultApp; // Default app code
var lastOpenedApp; // Last opened app code
/**
* Init apps menu list
*/
function initAppsMenu()
{
var $helpLink = $('#helpLink');
appsMap.help =
{
code: 'help',
icon: 'icon-help',
url: manualUrl || $helpLink.attr('href'),
external: true,
text: manualText || $helpLink.text(),
appUrl: config.webRoot + '#app=help'
};
var $menuMainNav = $('#menuMainNav').empty();
window.appsMenuItems.forEach(function(item)
{
if(item === 'divider') return $menuMainNav.append('<li class="divider"></li>');
var $link= $('<a data-pos="menu"></a>')
.attr('data-app', item.code)
.attr('data-toggle', 'tooltip')
.attr('class', 'show-in-app')
.html(item.title);
item.icon = ($link.find('.icon').attr('class') || '').replace('icon ', '');
item.text = $link.text().trim();
$link.html('<i class="icon ' + item.icon + '"></i><span class="text">' + item.text + '</span>');
if(item.code === 'devops') $link.find('.text').addClass('num');
appsMap[item.code] = item;
$('<li></li>').attr('data-app', item.code)
.append($link)
.appendTo($menuMainNav);
$link.tooltip({title: item.text, container: 'body', placement: 'right', tipClass: 'menu-tip'});
if(!defaultApp) defaultApp = item.code;
});
appsMap['search'] =
{
opened: false,
code: 'search',
group: 'search',
icon: 'icon-search',
methodName: 'index',
moduleName: 'search',
text: searchCommon,
title: '<i class="icon icon-search"></i> ' + searchCommon,
url: '/index.php?m=search&f=index',
vars: ''
};
}
/**
* Get app code from url
* @param {String} urlOrModuleName Url string
* @return {String}
*/
function getAppCodeFromUrl(urlOrModuleName)
{
var code = window.navGroup[urlOrModuleName];
if(code) return code;
var link = $.parseLink(urlOrModuleName);
if(!link.moduleName || link.isOnlyBody || (link.moduleName === 'index' && link.methodName === 'index')) return '';
if(link.hash && link.hash.indexOf('app=') === 0) return link.hash.substr(4);
/* Handling special situations */
var moduleName = link.moduleName;
var methodName = link.methodName;
if (moduleName === 'index' && methodName === 'index') return 'my';
var methodLowerCase = methodName.toLowerCase();
if(moduleName === 'doc')
{
if(link.prj) return 'project';
if((link.params.from || link.params.$3) == 'product')
{
if(['objectlibs', 'showfiles', 'browse', 'view', 'edit', 'delete', 'create'].includes(methodLowerCase)) return 'product';
}
return 'doc';
}
if(['caselib', 'testreport', 'testsuite', 'testtask', 'testcase', 'bug', 'qa'].includes(moduleName))
{
return link.prj ? 'project' : 'qa';
}
if(moduleName === 'report')
{
if(['usereport', 'editreport', 'deletereport', 'custom'].includes(methodLowerCase) && link.params.from)
{
return 'system';
}
else
{
return link.prj ? 'project' : 'report';
}
}
if(moduleName === 'story' && methodLowerCase === 'zerocase')
{
return link.params.from == 'project' ? 'project' : 'qa';
}
if(moduleName === 'execution' && methodLowerCase === 'all')
{
return (link.params.from || link.params.$3) == 'project' ? 'project' : 'execution';
}
if(moduleName === 'issue' || moduleName === 'risk' || moduleName === 'opportunity' || moduleName === 'pssp' || moduleName === 'auditplan' || moduleName === 'meeting' || moduleName === 'nc')
{
if(link.params.$2 == 'my' || link.params.from == 'my') return 'my';
if(link.params.$2 == 'project' || link.params.from == 'project') return 'project';
if(link.params.$2 == 'execution' || link.params.from == 'execution') return 'execution';
}
if(moduleName === 'product')
{
if(methodLowerCase === 'create' && (link.params.programID || link.params.$1)) return 'program';
if(methodLowerCase === 'edit' && (link.params.programID || link.params.$4)) return 'program';
if(methodLowerCase === 'batchedit') return 'program';
var moduleGroup = link.params.moduleGroup ? link.params.moduleGroup : link.params.$2;
if(methodLowerCase === 'showerrornone' && (moduleGroup || moduleGroup)) return moduleGroup;
}
if(moduleName === 'stakeholder')
{
if(methodLowerCase === 'create' && (link.params.programID || link.params.$1)) return 'program';
}
if(moduleName === 'user')
{
if(['todo', 'todocalendar', 'effortcalendar', 'effort', 'task', 'todo', 'story', 'bug', 'testtask', 'testcase', 'execution', 'dynamic', 'profile', 'view', 'issue', 'risk'].includes(methodLowerCase)) return 'system';
}
if(moduleName === 'my')
{
if(['team'].includes(methodLowerCase)) return 'system';
}
if(moduleName === 'company') if(methodLowerCase == 'browse') return 'admin';
if(moduleName === 'opportunity' || moduleName === 'risk' || moduleName == 'trainplan') if(methodLowerCase == 'view') return 'project';
if(moduleName === 'tree')
{
if(methodLowerCase === 'browse')
{
var viewType = link.params.view || link.params.$2;
if(['bug', 'case', 'caselib'].includes(viewType)) return link.params.$5 === 'project' ? 'project' : 'qa';
if(viewType === 'doc' && (link.params.from === 'product' || link.params.$5 == 'product')) return 'product';
if(viewType === 'doc' && (link.params.from === 'project' || link.params.$5 == 'project')) return 'project';
if(viewType === 'doc') return 'doc';
if(viewType === 'story') return 'product';
}
else if(methodLowerCase === 'browsetask')
{
return 'project';
}
}
if(moduleName === 'search' && methodLowerCase === 'buildindex') return 'admin';
code = window.navGroup[moduleName] || moduleName || urlOrModuleName;
return appsMap[code] ? code : '';
}
/**
* Open tab of app
* @param {string} [url] Url to open
* @param {string} [appCode] The code of target app to open
* @return {void}
*/
function openTab(url, appCode)
{
/* Check params */
if(!appCode)
{
if(appsMap[url])
{
appCode = url;
url = '';
}
else
{
appCode = getAppCodeFromUrl(url);
if(!appCode) return false;
}
}
/* Create pate app object and store it */
var app = openedApps[appCode];
if(app)
{
if(app.$iframe && app.$iframe.length)
{
var iframe = app.$iframe[0];
if(iframe && iframe.contentDocument && iframe.contentWindow && iframe.contentWindow.$)
{
var result = iframe.contentWindow.$(iframe.contentDocument).triggerHandler('openapp.apps', [app, url]);
if (result === false) {
return 'cancel';
}
}
}
}
else
{
var $iframe = $(
[
'<iframe',
'id="appIframe-' + appCode + '"',
'name="app-' + appCode + '"',
'allowfullscreen="true"',
'frameborder="no"',
'allowtransparency="true"',
'scrolling="auto"',
'style="width: 100%; height: 100%; left: 0px;"',
'/>'
].join(' '));
var $app = $('<div class="app-container" id="app-' + appCode + '"></div>')
.append($iframe)
.appendTo('#apps');
app = $.extend({$iframe: $iframe, $app: $app, code: appCode, opened: true}, appsMap[appCode]);
openedApps[appCode] = app;
/* If first show without url, then use the default url */
if(!url) url = appsMap[appCode].url;
var iframe = $iframe.get(0);
iframe.onload = iframe.onreadystatechange = function(e)
{
$app.trigger('loadapp', app);
};
}
/* Set tab cookie */
$.cookie('tab', appCode, {expires: config.cookieLife, path: config.webRoot});
/* Highlight at main menu */
var $menuMainNav = $('#menuMainNav,#menuMoreNav');
var $lastActiveNav = $menuMainNav.find('li.active');
if($lastActiveNav.data('app') !== appCode)
{
$lastActiveNav.removeClass('active');
$menuMainNav.find('li[data-app="' + appCode + '"]').addClass('active');
}
/* Show page app and update iframe source */
if(url) reloadApp(appCode, url, true);
app.zIndex = openedAppZIndex++;
app.$app.show().css('z-index', app.zIndex);
/* Update task bar */
var $bars = $('#bars');
var $bar = $('#appBar-' + appCode);
if(!$bar.length)
{
var $link= $('<a data-pos="bar"></a>')
.attr('data-app', appCode)
.attr('class', 'show-in-app')
.html('<span>' + app.text + '</span>');
var barCount = $('#bars li').length;
if(barCount) $bar = $('<li class="divider"></li>').appendTo($bars);
$bar = $('<li></li>').attr('data-app', appCode)
.attr('id', 'appBar-' + appCode)
.append($link)
.appendTo($bars);
}
var $lastActiveBar = $bars.find('li.active');
if($lastActiveBar.data('app') !== appCode)
{
$lastActiveBar.removeClass('active');
$bars.find('li[data-app="' + appCode + '"]').addClass('active');
}
app.$bar = $bar;
/* Update others app state */
for(var theCode in openedApps)
{
if(theCode !== appCode) openedApps[theCode].show = false;
}
/* Update current app state */
app.show = true;
if(lastOpenedApp !== appCode)
{
lastOpenedApp = appCode;
updateAppUrl(appCode, null, null, true);
}
app.$app.trigger('showapp', app);
return true;
}
/**
* Get last opened app
* @param {boolean} [onlyShowed] If set to true then only get last app from apps are showed
* @returns {object} The opened app info object
*/
function getLastApp(onlyShowed)
{
var lastShowIndex = 0;
var lastApp = null;
for(var appCode in openedApps)
{
var app = openedApps[appCode];
if((!onlyShowed || app.show) && lastShowIndex < app.zIndex && !app.closed)
{
lastShowIndex = app.zIndex;
lastApp = app;
}
}
return lastApp;
}
/**
* Hide app
* @param {string} appCode The app code of target app to hide
* @return {void}
*/
function hideTab(appCode)
{
var app = openedApps[appCode];
if(!app || !app.show) return;
app.$app.hide();
app.show = false;
lastOpenedApp = null;
app.$app.trigger('hideapp', app);
/* Active last app */
var lastApp = getLastApp(true) || getLastApp();
showTab(lastApp ? lastApp.code : defaultApp);
}
/**
* Show tab of app
* @param {string} appCode The app code of target app to show
* @return {void}
*/
function showTab(appCode)
{
return openTab('', appCode);
}
/**
* Toggle app
* @param {string} appCode The app code of target app to toggle
* @return {void}
*/
function toggleApp(appCode)
{
var app = openedApps[appCode];
if(!app || app.code !== lastOpenedApp) showTab(appCode);
else hideTab(appCode);
}
/**
* Close app
* @param {string} appCode The app code of target app to close
*/
function closeApp(appCode)
{
appCode = appCode || lastOpenedApp;
var app = openedApps[appCode];
if(!app) return;
if(app.$iframe && app.$iframe.length)
{
var iframe = app.$iframe[0];
if(iframe && iframe.contentDocument && iframe.contentWindow && iframe.contentWindow.$)
{
var result = iframe.contentWindow.$(iframe.contentDocument).triggerHandler('closeapp.apps', [app]);
if (result === false) {
return 'cancel';
}
}
}
var appKeys = Object.keys(openedApps)
if(appKeys[0] == appCode)
{
$("#bars li.divider:first").remove();
}
else
{
$("#appBar-" + appCode).prev().remove();
}
app.closed = true;
hideTab(appCode);
app.$app.remove();
app.$bar.remove();
delete openedApps[appCode];
var firstClass = $("#bars li:first").attr('class');
if(firstClass == 'divider') $("#bars li.divider:first").remove();
app.$app.trigger('closeapp', app);
}
/**
* Reload app
* @param {string} appCode The app code of target app to reload
* @param {string|boolean} [url] The new url to load, it's optional
* @param {boolean} [notTriggerEvent] Skip trigger event
* @return {void}
*/
function reloadApp(appCode, url, notTriggerEvent)
{
var app = openedApps[appCode];
if(!app) return;
if(url === true) url = app.url;
var iframe = app.$iframe[0];
try
{
if(url) iframe.contentWindow.location.assign(url);
else iframe.contentWindow.location.reload(true);
}
catch(_)
{
iframe.src = url || app.url || iframe.src;
}
if(!notTriggerEvent) app.$app.trigger('reloadapp', app);
}
/**
* Update browser url and title for the given app
* @param {string} appCode The app code of target app to update url
* @param {string|boolean} [url] The new url of the app
* @param {string|boolean} [title] The new title of the app
* @param {boolean} [push] Use push instead of replace
* @return {void}
*/
function updateAppUrl(appCode, url, title, push)
{
// if(window.TUTORIAL) return;
var app = openedApps[appCode];
if(!app || lastOpenedApp !== appCode) return;
if(url) app.appUrl = url;
else url = app.appUrl || app.url;
if(title) app.appTitle = title;
else title = app.appTitle || app.text;
if(url && url.indexOf('#') < 0 && getAppCodeFromUrl(url) !== appCode) url = url + '#app=' + appCode;
if(location.href !== url)
{
history[push ? 'pushState' : 'replaceState']({app: appCode}, title, url);
}
document.title = title;
}
/* Bind helper methods to global object "$.apps" */
$.apps = window.apps =
{
show: showTab,
open: openTab,
hide: hideTab,
toggle: toggleApp,
close: closeApp,
reload: reloadApp,
updateUrl: updateAppUrl,
getAppCode: getAppCodeFromUrl,
getLastApp: getLastApp,
openedApps: openedApps,
appsMap: appsMap
};
/**
* Refresh more menu in #menuNav
* @return {void}
*/
function refreshMoreMenu()
{
var $mainNav = $('#menuMainNav');
var $list = $('#menuMoreList');
var $menuNav = $('#menuNav');
var $menuItems = $mainNav.children('li');
var itemHeight = $menuItems.first().outerHeight();
var maxHeight = $menuNav.height() - 10;
var showMoreMenu = false;
var currentHeight = itemHeight;
var moreMenuHeight = 12;
$menuItems.each(function()
{
var $item = $(this);
var isDivider = $item.hasClass('divider');
var height = isDivider ? 17 : itemHeight;
currentHeight += height;
if(currentHeight > maxHeight)
{
$item.addClass('hidden');
if(!showMoreMenu)
{
showMoreMenu = true;
$list.empty();
var $prevItem = $item.prev();
if($prevItem.hasClass('divider')) $prevItem.addClass('hidden');
if(isDivider) return;
}
moreMenuHeight += isDivider ? 13 : 32;
$list.append($item.clone().removeClass('hidden'));
}
else
{
$item.removeClass('hidden');
}
});
/* The magic number "111" is the space between dropdown trigger
btn and the bottom of screen */
var listStyle = {maxHeight: 'initial', top: moreMenuHeight > 111 ? 111 - moreMenuHeight : ''};
if($list[0].getBoundingClientRect)
{
var btnBounding = $list.prev('a')[0].getBoundingClientRect();
if(btnBounding.height)
{
var winHeight = $(window).height();
if(winHeight < moreMenuHeight)
{
listStyle.maxHeight = winHeight;
listStyle.overflow = 'auto';
listStyle.top = 5 - btnBounding.top;
}
else if(moreMenuHeight > (winHeight - btnBounding.top))
{
listStyle.top = winHeight - btnBounding.top - moreMenuHeight + 5;
}
}
}
$list.css(listStyle);
$menuNav.toggleClass('show-more-nav', showMoreMenu);
if(showMoreMenu && !$list.data('listened-click'))
{
$list.data('listened-click', true).on('click', function()
{
$list.addClass('hidden');
setTimeout(function(){$list.removeClass('hidden')}, 200);
});
}
}
/* Init after current page load */
$(function()
{
initAppsMenu();
/* Bind events */
$(document).on('click', '.open-in-app,.show-in-app', function(e)
{
var $link = $(this);
if($link.is('[data-modal],[data-toggle][data-toggle!="tooltip"],.iframe,.not-in-app')) return;
var url = $link.hasClass('show-in-app') ? '' : ($link.attr('href') || $link.data('url'));
if(url && url.indexOf('onlybody=yes') > 0) return;
if(openTab(url, $link.data('app')))
{
e.preventDefault();
if($link.closest('#userNav').length)
{
var $menu = $('#userNav .dropdown-menu').addClass('hidden');
setTimeout(function(){$menu.removeClass('hidden')}, 200);
}
}
}).on('contextmenu', '.open-in-app,.show-in-app', function(event)
{
var $btn = $(this);
var appCode = $btn.data('app');
if(!appCode) return;
var lang = window.appsLang;
var app = openedApps[appCode];
var items = [{label: lang.open, disabled: app && lastOpenedApp === appCode, onClick: function(){showTab(appCode)}}];
if(app)
{
items.push({label: lang.reload, onClick: function(){reloadApp(appCode)}});
if(appCode !== 'my') items.push({label: lang.close, onClick: function(){closeApp(appCode)}});
}
var options = {event: event, onClickItem: function(_item, _$item, e){e.preventDefault();}};
var pos = $btn.data('pos');
if(pos)
{
var bounding = $btn.closest('li')[0].getBoundingClientRect();
if(pos === 'bar')
{
options.x = bounding.left;
options.y = bounding.top - (appCode === 'my' ? 65 : 92);
}
else
{
options.x = bounding.right - 10;
options.y = bounding.top;
}
}
var $dropdown = $btn.closest('.dropdown');
if($dropdown.length)
{
$dropdown.addClass('open');
options.onHide = function(){$dropdown.removeClass('open');}
}
$.zui.ContextMenu.show(items, options);
event.preventDefault();
});
window.addEventListener('popstate', function(event)
{
if(event.state && lastOpenedApp !== event.state.app) openTab(event.state.app);
});
/* Redirect or open default app after document load */
var defaultOpenUrl = window.defaultOpen;
if(!defaultOpenUrl && location.hash.indexOf('#app=') === 0)
{
defaultOpenUrl = decodeURIComponent(location.hash.substr(5));
}
openTab(defaultOpenUrl ? defaultOpenUrl : defaultApp);
/* Refresh more menu on window resize */
$(window).on('resize', refreshMoreMenu);
refreshMoreMenu();
setTimeout(refreshMoreMenu, 500);
});
}());
(function()
{
$.toggleMenu = function(toggle)
{
var $body = $('body');
if (toggle === undefined) toggle = $body.hasClass('menu-hide');
$body.toggleClass('menu-hide', !toggle).toggleClass('menu-show', !!toggle);
$.cookie('hideMenu', String(!toggle), {expires: config.cookieLife, path: config.webRoot});
};
$(function()
{
/* Click to show more. */
$(document).on('click', '.menu-toggle', function()
{
$.toggleMenu();
var $menu = $('#userNav .dropdown-menu').addClass('hidden');
setTimeout(function(){$menu.removeClass('hidden')}, 200);
});
$('.menu-toggle').each(function()
{
$(this).attr('data-toggle', 'tooltip').tooltip({container: 'body', placement: 'right', tipClass: 'menu-tip', title: function()
{
return $(this).data($('body').hasClass('menu-hide') ? 'unfoldText' : 'collapseText');
}});
});
});
}());
$.extend(
{
gotoObject:function()
{
objectType = $('#searchType').attr('value');
objectValue = $('#globalSearchInput').attr('value');
if(objectType && objectValue)
{
var reg = /[^0-9]/;
if(reg.test(objectValue) || objectType == 'all')
{
var searchLink = createLink('search', 'index') + (config.requestType == 'PATH_INFO' ? '?' : '&') + 'words=' + objectValue;
$.apps.open(searchLink);
}
else
{
var types = objectType.split('-');
var searchModule = types[0];
var searchMethod = typeof(types[1]) == 'undefined' ? 'view' : types[1];
var searchLink = createLink(searchModule, searchMethod, "id=" + objectValue);
var assetType = 'story,issue,risk,opportunity,doc';
if(assetType.indexOf(searchModule) > -1)
{
var link = createLink('index', 'ajaxGetViewMethod' , 'objectID=' + objectValue + '&objectType=' + searchModule);
$.get(link, function(data)
{
if(data)
{
searchModule = 'assetlib';
searchMethod = data;
searchLink = createLink(searchModule, searchMethod, "id=" + objectValue);
}
$.apps.open(searchLink);
});
}
else
{
$.apps.open(searchLink);
}
}
$.post(createLink('index', 'ajaxClearObjectSession'), {objectType: objectType});
$('#globalSearchInput').click();
}
}
});
/* Initialize global search. */
$(function()
{
var reg = /[^0-9]/;
var $searchbox = $('#searchbox');
var $typeSelector = $searchbox.find('.input-group-btn');
var $dropmenu = $typeSelector.children('.dropdown-menu');
var $searchQuery = $('#globalSearchInput');
var toggleMenu = function(show)
{
$searchbox.toggleClass('open', show);
$dropmenu.toggleClass('show', show).toggleClass('in', show);
if(show) $dropmenu.show();
else $dropmenu.hide();
};
var hideMenu = function(){toggleMenu(false);};
var refreshMenu = function()
{
var val = $searchQuery.val();
var searchType = changeSearchObject();
if(val !== null && val !== "")
{
var isQuickGo = !reg.test(val);
$dropmenu.toggleClass('show-quick-go', isQuickGo);
var $typeAll = $dropmenu.find('li.search-type-all > a');
$typeAll.text(searchAB + ' ' + val);
if(isQuickGo)
{
$typeAll.closest('li').removeClass('active');
$dropmenu.removeClass('with-active').find('li:not(.search-type-all) > a').each(function()
{
var $this = $(this);
var isActiveType = $this.data('value') === searchType && searchType !== 'all';
$this.closest('li').toggleClass('selected active', isActiveType);
$this.text($this.data('name') + ' #' + (val.length > 7 ? (val.substr(0, 7) + '...') : val));
if(isActiveType) $dropmenu.addClass('with-active');
});
}
else
{
$dropmenu.find('li.active').removeClass('active');
$typeAll.closest('li').addClass('active');
}
toggleMenu(true);
}
else
{
hideMenu();
}
};
$dropmenu = $dropmenu.appendTo($searchbox);
$dropmenu.on('click', 'a', function(e)
{
$('#searchType').val($(this).data('value'));
$.gotoObject();
e.stopPropagation();
}).find('li > a').each(function()
{
var $this = $(this);
$this.attr('data-name', $this.text());
});
var $allItem = $dropmenu.find('li > a[data-value="all"]');
if($allItem.length)
{
$allItem.closest('li').addClass('search-type-all').prependTo($dropmenu);
}
$searchQuery.on('change keyup paste input propertychange', refreshMenu).on('focus', function()
{
setTimeout(refreshMenu, 300);
});
$(document).on('click', hideMenu);
$(document).on('click', function()
{
$("#upgradeContent").hide();
});
$("#upgradeContent").click(function(event)
{
event.stopPropagation();
});
$("#bizLink").click(function(event)
{
var $upgradeContent = $('#upgradeContent').toggle();
if(!$upgradeContent.is(':hidden'))
{
getLatestVersion();
event.stopPropagation();
}
});
$('.has-avatar').hover(function(event)
{
$('.contextmenu').attr('class', 'contextmenu');
$('.contextmenu-menu').attr('class', 'contextmenu-menu fade');
});
$('#bars').mousedown(function()
{
$('#globalSearchInput').click();
});
});
/* Change the search object according to the module and method. */
function changeSearchObject()
{
var appInfo = $.apps.getLastApp();
var appPageModuleName = appInfo.$iframe[0].contentWindow.config.currentModule;
var appPageMethodName = appInfo.$iframe[0].contentWindow.config.currentMethod;
var searchType = appPageModuleName;
if(appPageModuleName == 'product' && appPageMethodName == 'browse') var searchType = 'story';
var projectMethod = 'task|story|bug|build';
if(appPageModuleName == 'project' && projectMethod.indexOf(appPageMethodName) != -1) var searchType = appPageMethodName;
if(appPageModuleName == 'my' || appPageModuleName == 'user') var searchType = appPageMethodName;
if(searchObjectList.indexOf(',' + searchType + ',') == -1) var searchType = 'bug';
if(searchType == 'program') var searchType = 'program-product';
if(searchType == 'deploystep') var searchType = 'deploy-viewstep';
$("#searchType").val(searchType);
$('#searchTypeMenu li:first').attr('class', 'search-type-all');
return searchType;
}
function getLatestVersion()
{
$('#globalSearchInput').click();
$('#upgradeContent').toggle();
}