zentaopms/www/js/my.full.js
2023-05-16 10:47:08 +08:00

1586 lines
49 KiB
JavaScript
Executable File

(function($)
{
/**
* Save form Arr to $.zui.store.
*
* @access public
* @param {string} formID
* @param {array} formData
* @return void
*/
function storeFormData(formID, formData)
{
$.zui.store.set(formID, formData);
}
/**
* Handle the logic save form draft.
*
* @access public
* @return void
*/
function handleSaveFormDraft()
{
if(config.currentModule.indexOf('workflow') !== -1) return;
var skipModules = ['repo', 'mr', 'job', 'dev', 'custom', 'editor'];
if(skipModules.indexOf(config.currentModule) !== -1) return;
var skipMethods = ['edit', 'import', 'login', 'export', 'finish', 'confirm', 'resolve', 'start', 'pause', 'cancel', 'report', 'close', 'activate', 'restart', 'suspend', 'putoff', 'browse', 'hangup', 'track', 'index', 'reply', 'manage', 'run', 'show'];
for(var i = 0; i < skipMethods.length; i++)
{
if(config.currentMethod.indexOf(skipMethods[i]) === 0) return;
};
var $messager = '';
setTimeout(function()
{
var form = $('form[method=post].main-form');
if(form.length)
{
if($(form).hasClass('no-stash') || $(form).data('ride') == 'table') return;
var target = $(form).attr('target');
if($(form).attr('target') == 'hiddenwin')
{
var needSkip = true;
var keepModules = ['program', 'product', 'project', 'testcase', 'execution', 'caselib'];
for(var i = 0; i < keepModules.length; i++)
{
if(needSkip && config.currentModule.indexOf(keepModules[i]) === 0) needSkip = false;
};
if(needSkip) return;
}
var formID = config.currentMethod + '-' + config.currentModule + '-' + $(form).attr("id");
var formDataStored = $.zui.store.get(formID);
/* Clear form data for store. */
setTimeout(function() {
$.zui.store.remove(formID);
}, 100);
if(formDataStored && formDataStored.length)
{
message = lang.confirmDraft.replace('%name%', lang[config.currentModule] ? lang[config.currentModule] : '');
$messager = new $.zui.Messager(message, {
close: true,
type: 'info',
placement: 'top',
cssClass: 'mt-md messagger-zt ',
time: 0,
actions: [
{
name: 'undo',
icon: 'undo',
text: lang.resume,
action: function()
{
var valueMultiple = {};
for(var i = 0; i < formDataStored.length; i++)
{
var item = formDataStored[i];
/* formItem === checkbox or formItem === multipleSelect */
if(item.name.indexOf('[]') != -1)
{
if((item.name.indexOf(']') != -1) && (item.name.indexOf('[') != -1))
{
var formItem = $('#' + item.name.replace('[]', '').replace('[', '').replace(']', ''));
}
else
{
var formItem = $('#' + item.name.replace('[]', ''));
}
}
else if((item.name.indexOf(']') != -1) && (item.name.indexOf('[') != -1))
{
var formItem = $('#' + item.name.replace('[', '').replace(']', ''));
}
else
{
var formItem = $('[name^=' + item.name + ']');
if (!(formItem.length && (formItem.attr('type') === 'radio' || formItem.attr('type') === 'checkbox')))
formItem = $('#' + item.name);
}
var tagName = formItem.prop('tagName');
if(tagName === 'SELECT')
{
if($(formItem).attr('multiple'))
{
if(!valueMultiple[item.name]) valueMultiple[item.name] = [];
valueMultiple[item.name].push(item.value);
if($(formItem).hasClass('picker-select'))
{
$(formItem).trigger('change');
$(formItem).data('zui.picker').setValue(valueMultiple[item.name]);
}
else if($(formItem).hasClass('chosen'))
{
formItem.val(valueMultiple[item.name]);
$(formItem).trigger('change');
$(formItem).trigger('chosen:updated');
}
}
else if($(formItem).hasClass('chosen'))
{
formItem.val(item.value);
$(formItem).trigger('chosen:updated');
}
else if($(formItem).hasClass('picker-select'))
{
$(formItem).data('zui.picker').setValue(item.value);
}
}
else if(tagName === 'TEXTAREA' && $(formItem).hasClass('kindeditor'))
{
KindEditor.remove('#' + item.name);
formItem.val(item.value);
$(formItem).kindeditor(
{
afterChange: function()
{
$(formItem).closest('.main-form').trigger('change');
}
});
}
else
{
if($(formItem).attr('type') === 'checkbox')
{
$(formItem).prop('checked', true).trigger('change');
}
else if($(formItem).attr('type') === 'radio')
{
$('#' + item.name + item.value).prop('checked', true).trigger('change');
}
else
{
formItem.val(item.value);
}
}
}
}
}
],
onAction: function(name, action, messager)
{
setTimeout(function () {
$.zui.store.remove(formID);
}, 100)
}
}).show();
}
form.on('input', function()
{
storeFormData(formID, $(form).serializeArray())
}).on('change', function()
{
storeFormData(formID, $(form).serializeArray())
}).on('success.form.zui', function(event, res)
{
if(res.result === 'success' || res.status === 'success') $.zui.store.remove(formID);
})
}
$('body').one('click', function(e)
{
if($messager && $('.messager').length && !$.contains(e.target, $('.messager')))
$messager.destroy();
}).on('click', '#submit.form-stash-clear', function()
{
$.zui.store.remove(formID);
});
}, 500);
}
/* Tab session */
if(!config.tabSession) return;
/** Store current tab id */
var _tid = '';
/**
* Get current tab id
* @returns {string} Tab id
*/
function getTid(){return _tid;}
/**
* Convert url with tab id
* @param {string} url
* @param {string} [tid]
* @param {boolean} [force]
* @returns {string} Tab id
*/
function convertUrlWithTid(url, tid, force)
{
var link = $.parseLink(url);
if(!link.moduleName) return url;
tid = tid || _tid;
if(!force && link.tid === tid) return url;
link.tid = tid;
return $.createLink(link);
}
/** Init */
function init()
{
/* Check tid */
if(window.parent !== window)
{
if(window.parent.$.tabSession) _tid = window.parent.$.tabSession.getTid();
}
else
{
var isIndexOrLoginPage = (config.currentModule === 'index' && config.currentMethod === 'index') || (config.currentModule === 'user' && config.currentMethod === 'login');
var link = $.parseLink(window.location.href);
_tid = sessionStorage.getItem('TID');
if(!_tid)
{
if(link.tid && isIndexOrLoginPage)
{
_tid = link.tid
}
if(!_tid)
{
_tid = $.zui.uuid();
_tid = _tid.substr(_tid.length - 8);
}
}
sessionStorage.setItem('TID', _tid);
if(isIndexOrLoginPage && !link.tid)
{
window.location.href = convertUrlWithTid(window.location.href, _tid);
}
}
$.tabSession =
{
getTid: getTid,
convertUrlWithTid: convertUrlWithTid,
};
/* Handle all links in page */
$('a').each(function()
{
var $a = $(this);
var url = $a.attr('href');
var urlWithTid = convertUrlWithTid(url);
if(urlWithTid !== url) $a.attr('href', urlWithTid);
});
$('[data-url]').each(function()
{
var $e = $(this);
var url = $e.attr('data-url');
var urlWithTid = convertUrlWithTid(url);
if(urlWithTid !== url) $e.attr('data-url', urlWithTid);
});
if(config.debug > 2)
{
$(function()
{
$('#tid').prepend('<code class="bg-blue">localtid=' + _tid + '</code>');
});
}
}
init();
/* Hide context menu when window is scroll. */
$(window).on('scroll', function()
{
$.zui.ContextMenu.hide();
});
}(jQuery));
/**
* Set the ping url.
*
* @access public
* @return void
*/
function setPing()
{
$('#hiddenwin').attr('src', createLink('misc', 'ping'));
}
/**
* Disable the submit button when submit form.
*
* @access public
* @return void
*/
function setForm()
{
var formClicked = false;
$('form').submit(function()
{
submitObj = $(this).find(':submit');
if($(submitObj).size() >= 1)
{
var isBtn = submitObj.prop('tagName') == "BUTTON";
submitLabel = isBtn ? $(submitObj).html() : $(submitObj).attr('value');
$(submitObj).attr('disabled', 'disabled');
var submitting = submitObj.attr('data-submitting') || lang.submitting;
if(isBtn) submitObj.text(submitting);
else $(submitObj).attr('value', submitting);
formClicked = true;
}
});
$("body").click(function()
{
if(formClicked)
{
$(submitObj).removeAttr('disabled');
if(submitObj.prop('tagName') == "BUTTON")
{
submitObj.text(submitLabel);
}
else
{
$(submitObj).attr('value', submitLabel);
}
$(submitObj).removeClass('button-d');
}
formClicked = false;
});
}
/**
* Set form action and submit.
*
* @param url $actionLink
* @param string $hiddenwin 'hiddenwin'
* @access public
* @return void
*/
function setFormAction(actionLink, hiddenwin, obj)
{
$form = typeof(obj) == 'undefined' ? $('form') : $(obj).closest('form');
if(hiddenwin) $form.attr('target', hiddenwin);
else $form.removeAttr('target');
$form.attr('action', actionLink);
// Check safari for bug #1000, see http://pms.zentao.net/bug-view-1000.html
var userAgent = navigator.userAgent;
var isSafari = userAgent.indexOf('AppleWebKit') > -1 && userAgent.indexOf('Safari') > -1 && userAgent.indexOf('Chrome') < 0;
if(isSafari)
{
var idPreffix = 'checkbox-fix-' + $.zui.uuid();
$form.find('[data-fix-checkbox]').remove();
$form.find('input[type="checkbox"]:not(.rows-selector)').each(function()
{
var $checkbox = $(this);
var checkboxId = idPreffix + $checkbox.val();
$checkbox.clone().attr('data-fix-checkbox', checkboxId).css('display', 'none').after('<div id="' + checkboxId + '"/>').appendTo($form);
});
}
$form.submit();
}
/**
* Set the max with of image.
*
* @access public
* @return void
*/
function setImageSize(image, maxWidth, maxHeight)
{
var $image = $(image);
if($image.parent().prop('tagName').toLowerCase() == 'a') return;
/* If not set maxWidth, set it auto. */
if(!maxWidth)
{
bodyWidth = $('body').width();
maxWidth = bodyWidth - 470; // The side bar's width is 336, and add some margins.
}
if(!maxHeight) maxHeight = $(top.window).height();
setTimeout(function()
{
maxHeightStyle = $image.height() > 0 ? 'max-height:' + maxHeight + 'px' : '';
if(!document.getElementsByClassName('xxc-embed').length && $image.width() > 0 && $image.width() > maxWidth) $image.attr('width', maxWidth);
$image.wrap('<a href="' + $image.attr('src') + '" style="display:inline-block;position:relative;overflow:hidden;' + maxHeightStyle + '" target="_blank"></a>');
if($image.height() > 0 && $image.height() > maxHeight) $image.closest('a').append("<a href='###' class='showMoreImage' onclick='showMoreImage(this)'>" + lang.expand + " <i class='icon-angle-down'></i></a>");
}, 50);
}
/**
* Show more image when image is too height.
*
* @param obj $obj
* @access public
* @return void
*/
function showMoreImage(obj)
{
$(obj).parents('a').css('max-height', 'none');
$(obj).remove();
}
/**
* Set mailto list from a contact list..
*
* @param string $mailto
* @param int $contactListID
* @access public
* @return void
*/
function setMailto(mailto, contactListID)
{
var oldUsers = $('#' + mailto).val() ? $('#' + mailto).val() : '';
link = createLink('user', 'ajaxGetContactUsers', 'listID=' + contactListID + '&dropdownName=' + mailto + '&oldUsers=' + oldUsers);
$.get(link, function(users)
{
var picker = $('#' + mailto).data('zui.picker');
if(picker) picker.destroy();
$('#' + mailto).replaceWith(users);
$('#' + mailto + '_chosen').remove();
$('#' + mailto).siblings('.picker').remove();
if($("[data-pickertype='remote']").length == 0 && $('.picker-select').length == 0)
{
$('#' + mailto).chosen();
}
else
{
$('#' + mailto + "[data-pickertype!='remote']").picker({chosenMode: true});
$("[data-pickertype='remote']").each(function()
{
var pickerremote = $(this).attr('data-pickerremote');
$(this).picker({chosenMode: true, remote: pickerremote});
});
}
});
}
/**
* Ajax get contacts.
*
* @param object $obj
* @param string $dropdownName mailto|whitelist
* @access public
* @return void
*/
function ajaxGetContacts(obj, dropdownName)
{
if(typeof(dropdownName) == 'undefined') dropdownName = 'mailto';
link = createLink('user', 'ajaxGetContactList', 'dropdownName=' + dropdownName);
$.get(link, function(contacts)
{
if(!contacts) return false;
$inputgroup = $(obj).closest('.input-group');
$inputgroup.find('.input-group-btn').remove();
$inputgroup.append(contacts);
$inputgroup.find('select:last').chosen().fixInputGroup();
});
}
/**
* add one option of a select to another select.
*
* @param string $SelectID
* @param string $TargetID
* @access public
* @return void
*/
function addItem(SelectID,TargetID)
{
ItemList = document.getElementById(SelectID);
Target = document.getElementById(TargetID);
for(var x = 0; x < ItemList.length; x++)
{
var opt = ItemList.options[x];
if (opt.selected)
{
flag = true;
for (var y=0;y<Target.length;y++)
{
var myopt = Target.options[y];
if (myopt.value == opt.value)
{
flag = false;
}
}
if(flag)
{
Target.options[Target.options.length] = new Option(opt.text, opt.value, 0, 0);
}
}
}
}
/**
* Remove one selected option from a select.
*
* @param string $SelectID
* @access public
* @return void
*/
function delItem(SelectID)
{
ItemList = document.getElementById(SelectID);
for(var x=ItemList.length-1;x>=0;x--)
{
var opt = ItemList.options[x];
if (opt.selected)
{
ItemList.options[x] = null;
}
}
}
/**
* move one selected option up from a select.
*
* @param string $SelectID
* @access public
* @return void
*/
function upItem(SelectID)
{
ItemList = document.getElementById(SelectID);
for(var x=1;x<ItemList.length;x++)
{
var opt = ItemList.options[x];
if(opt.selected)
{
tmpUpValue = ItemList.options[x-1].value;
tmpUpText = ItemList.options[x-1].text;
ItemList.options[x-1].value = opt.value;
ItemList.options[x-1].text = opt.text;
ItemList.options[x].value = tmpUpValue;
ItemList.options[x].text = tmpUpText;
ItemList.options[x-1].selected = true;
ItemList.options[x].selected = false;
break;
}
}
}
/**
* move one selected option down from a select.
*
* @param string $SelectID
* @access public
* @return void
*/
function downItem(SelectID)
{
ItemList = document.getElementById(SelectID);
for(var x=0;x<ItemList.length;x++)
{
var opt = ItemList.options[x];
if(opt.selected)
{
tmpUpValue = ItemList.options[x+1].value;
tmpUpText = ItemList.options[x+1].text;
ItemList.options[x+1].value = opt.value;
ItemList.options[x+1].text = opt.text;
ItemList.options[x].value = tmpUpValue;
ItemList.options[x].text = tmpUpText;
ItemList.options[x+1].selected = true;
ItemList.options[x].selected = false;
break;
}
}
}
/**
* select all items of a select.
*
* @param string $SelectID
* @access public
* @return void
*/
function selectItem(SelectID)
{
ItemList = document.getElementById(SelectID);
for(var x=ItemList.length-1;x>=0;x--)
{
var opt = ItemList.options[x];
opt.selected = true;
}
}
/**
* Delete item use ajax.
*
* @param string url
* @param string replaceID
* @param string notice
* @access public
* @return void
*/
function ajaxDelete(url, replaceID, notice)
{
if(confirm(notice))
{
$.ajax(
{
type: 'GET',
url: url,
dataType: 'json',
success: function(data)
{
if(data.result == 'success')
{
var $table = $('#' + replaceID).closest('[data-ride="table"]');
if($table.length)
{
var table = $table.data('zui.table');
if(table)
{
table.options.replaceId = replaceID;
return table.reload();
}
}
$.get(document.location.href, function(data)
{
if(!($(data).find('#' + replaceID).length)) location.reload();
$('#' + replaceID).html($(data).find('#' + replaceID).html());
if(typeof sortTable == 'function') sortTable();
$('#' + replaceID).find('[data-toggle=modal], a.iframe').modalTrigger();
if($('#' + replaceID).find('table.datatable').length) $('#' + replaceID).find('table.datatable').datatable();
$('.table-footer [data-ride=pager]').pager();
});
}
else if(data.result == 'fail' && typeof(data.message) == 'string')
{
bootbox.alert(data.message);
}
}
});
}
}
/**
* Judge the string is a integer number
*
* @access public
* @return bool
*/
function isNum(s)
{
if(s!=null)
{
var r, re;
re = /\d*/i;
r = s.match(re);
return (r == s) ? true : false;
}
return false;
}
/**
* Start cron.
*
* @access public
* @return void
*/
function startCron(restart)
{
if(typeof(restart) == 'undefined') restart = 0;
$.ajax({type:"GET", timeout:100, url:createLink('cron', 'ajaxExec', 'restart=' + restart)});
}
function computePasswordStrength(password)
{
if(password.length == 0) return 0;
var strength = 0;
var length = password.length;
var complexity = new Array();
for(i = 0; i < length; i++)
{
letter = password.charAt(i);
var asc = letter.charCodeAt();
if(asc >= 48 && asc <= 57)
{
complexity[0] = 1;
}
else if((asc >= 65 && asc <= 90))
{
complexity[1] = 2;
}
else if(asc >= 97 && asc <= 122)
{
complexity[2] = 4;
}
else
{
complexity[3] = 8;
}
}
var sumComplexity = 0;
for(i in complexity) sumComplexity += complexity[i];
if((sumComplexity == 7 || sumComplexity == 15) && password.length >= 6) strength = 1;
if(sumComplexity == 15 && password.length >= 10) strength = 2;
return strength;
}
/**
* Check onlybody page when it is not open in modal then location to on onlybody page.
*
* @access public
* @return void
*/
function checkOnlybodyPage()
{
if(self == parent)
{
href = location.href.replace('?onlybody=yes', '');
location.href = href.replace('&onlybody=yes', '');
}
}
/**
* Fixed table head in list when scrolling.
*
* @param string $tableID
* @access public
* @return void
*/
function fixedTheadOfList(tableID)
{
if($(tableID).size() == 0) return false;
if($(tableID).css('display') == 'none') return false;
if($(tableID).find('thead').size() == 0) return false;
fixTheadInit();
$(window).scroll(fixThead);//Fix table head when scrolling.
$('.side-handle').click(function(){setTimeout(fixTheadInit, 300);});//Fix table head if module tree is hidden or displayed.
var tableWidth, theadOffset, fixedThead, $fixedThead;
function fixThead()
{
theadOffset = $(tableID).find('thead').offset().top;
$fixedThead = $(tableID).parent().find('.fixedTheadOfList');
if($fixedThead.size() <= 0 &&theadOffset < $(window).scrollTop())
{
tableWidth = $(tableID).width();
fixedThead = "<table class='fixedTheadOfList'><thead>" + $(tableID).find('thead').html() + '</thead></table>';
$(tableID).before(fixedThead);
$('.fixedTheadOfList').addClass($(tableID).attr('class')).width(tableWidth);
}
if($fixedThead.size() > 0 && theadOffset >= $(window).scrollTop()) $fixedThead.remove();
}
function fixTheadInit()
{
$fixedThead = $(tableID).parent().find('.fixedTheadOfList');
if($fixedThead.size() > 0) $fixedThead.remove();
fixThead();
}
}
/**
* Apply cs style to page
* @return void
*/
function applyCssStyle(css, tag)
{
tag = tag || 'default';
var name = 'applyStyle-' + tag;
var $style = $('style#' + name);
if(!$style.length)
{
$style = $('<style id="' + name + '">').appendTo('body');
}
var styleTag = $style.get(0);
if (styleTag.styleSheet) styleTag.styleSheet.cssText = css;
else styleTag.innerHTML = css;
}
/**
* Remove cookie by key
*
* @param cookieKey $cookieKey
* @access public
* @return void
*/
function removeCookieByKey(cookieKey)
{
$.cookie(cookieKey, '', {expires:config.cookieLife, path:config.webRoot});
location.href = location.href;
}
/**
* Set homepage.
*
* @param string $module
* @param string $page
* @access public
* @return void
*/
function setHomepage(module, page)
{
$.get(createLink('custom', 'ajaxSetHomepage', 'module=' + module + '&page=' + page), function(){location.reload(true)});
}
/**
* Reload page when tutorial mode setted in this session but not load in iframe
*
* @access public
* @return void
*/
function checkTutorial()
{
if(config.currentModule != 'tutorial' && window.TUTORIAL && (!frameElement || frameElement.tagName != 'IFRAME'))
{
if(confirm(window.TUTORIAL.tip))
{
$.getJSON(createLink('tutorial', 'ajaxQuit'), function()
{
window.location.reload();
}).error(function(){alert(lang.timeout)});
}
else
{
window.location.href = createLink('tutorial', 'index');
}
}
}
/* Remove 'ditto' in first row when batch create or edit. */
function removeDitto()
{
$firstTr = $('.table-form').find('tbody tr:first');
$firstTr.find('td select').each(function()
{
$(this).find("option[value='ditto']").remove();
$(this).trigger("chosen:updated");
});
}
/**
* Revert module cookie.
*
* @access public
* @return void
*/
function revertModuleCookie()
{
if($('#mainmenu .nav li[data-id="project"]').hasClass('active'))
{
$('#modulemenu .nav li[data-id="task"] a').click(function()
{
$.cookie('moduleBrowseParam', 0, {expires:config.cookieLife, path:config.webRoot});
});
}
if($('#mainmenu .nav li[data-id="product"]').hasClass('active'))
{
$('#modulemenu .nav li[data-id="story"] a').click(function()
{
$.cookie('storyModule', 0, {expires:config.cookieLife, path:config.webRoot});
});
}
if($('#mainmenu .nav li[data-id="qa"]').hasClass('active'))
{
$('#modulemenu .nav li[data-id="bug"] a').click(function()
{
$.cookie('bugModule', 0, {expires:config.cookieLife, path:config.webRoot});
});
$('#modulemenu .nav li[data-id="testcase"] a').click(function()
{
$.cookie('caseModule', 0, {expires:config.cookieLife, path:config.webRoot});
});
}
}
/**
* Focus move up or down for input.
*
* @param direction up|down
*/
function inputFocusJump(direction, type){
var $input = $('#mainContent table').find(type || 'input').filter(':focus').first();
if(!$input.length) return;
var $row = $input.closest('tr');
var $nextRow = $row[direction === 'up' ? 'prev' : 'next']('tr');
if(!$nextRow.length) $nextRow = $row.parent().children('tr')[direction === 'up' ? 'last' : 'first']();
if(!$nextRow.length) return;
var datetimepicker = $input.data('datetimepicker');
if(datetimepicker) datetimepicker.hide();
return $nextRow.find(':input[name^=' + ($input.attr('name').split('[')[0]) + ']:text:not(:disabled):not([name*="%"])').focus();
}
/**
* Focus move up or down for select.
*
* @param direction
*/
function selectFocusJump(direction)
{
return inputFocusJump(direction, 'select');
}
function adjustNoticePosition()
{
var bottom = 25;
$('#noticeBox').find('.alert').each(function()
{
$(this).css('bottom', bottom + 'px');
bottom += $(this).outerHeight(true) - 10;
});
}
function notifyMessage(data)
{
if(window.Notification)
{
var notify = null;
message = data;
if(typeof data.message == 'string') message = data.message;
if(Notification.permission == "granted")
{
notify = new Notification("", {body:message, tag:'zentao', data:data});
}
else if(Notification.permission != "denied")
{
Notification.requestPermission().then(function(permission)
{
notify = new Notification("", {body:message, tag:'zentao', data:data});
});
}
if(notify)
{
notify.onclick = function()
{
window.focus();
if(typeof notify.data.url == 'string' && notify.data.url) window.location.href = notify.data.url;
notify.close();
}
setTimeout(function()
{
notify.close();
}, 3000);
}
}
}
/**
* Get fingerprint.
*
* @access public
* @return void
*/
function getFingerprint()
{
if(typeof(Fingerprint) == 'function') return new Fingerprint().get();
fingerprint = '';
$.each(navigator, function(key, value)
{
if(typeof(value) == 'string') fingerprint += value.length;
})
return fingerprint;
}
/**
* Alert message with bootbox.
*
* @param message $message
* @access public
* @return bool
*/
function bootAlert(message)
{
bootbox.alert(message);
return false;
}
/**
* Toggle fold or unfold for parent.
*
* @param string $form
* @param array $unfoldIdList
* @param int $objectID
* @param string $objectType
* @access public
* @return void
*/
function toggleFold(form, unfoldIdList, objectID, objectType)
{
$form = $(form);
$parentTd = $form.find('td.has-child');
if($parentTd.length == 0) return false;
var toggleClass = ['product', 'requirement', 'story'].indexOf(objectType) !== -1 ? 'story-toggle' : 'task-toggle';
var nameClass = ['product', 'productplan'].indexOf(objectType) !== -1 ? 'c-title' : 'c-name';
$form.find('th.' + nameClass).addClass('clearfix').append("<span id='toggleFold' class='collapsed'><i class='icon icon-angle-double-right'></i></span>");
var allUnfold = true;
$parentTd.each(function()
{
var dataID = $(this).closest('tr').attr('data-id');
if(typeof(unfoldIdList[dataID]) != 'undefined') return true;
allUnfold = false;
$form.find('tr.parent-' + dataID).hide();
$(this).find('a.' + toggleClass).addClass('collapsed')
})
$form.find('th.' + nameClass + ' #toggleFold').toggleClass('collapsed', !allUnfold);
$(document).on('click', '#toggleFold', function()
{
var newUnfoldID = [];
var url = '';
var collapsed = $(this).hasClass('collapsed');
$parentTd.each(function()
{
var dataID = $(this).closest('tr').attr('data-id');
$form.find('tr.parent-' + dataID).toggle(collapsed);
$(this).find('a.' + toggleClass).toggleClass('collapsed', !collapsed)
newUnfoldID.push(dataID);
})
$(this).toggleClass('collapsed', !collapsed);
url = createLink('misc', 'ajaxSetUnfoldID', 'objectID=' + objectID + '&objectType=' + objectType + '&action=' + (collapsed ? 'add' : 'delete'));
$.post(url, {'newUnfoldID': JSON.stringify(newUnfoldID)});
});
$parentTd.find('a.' + toggleClass).click(function()
{
var newUnfoldID = [];
var url = '';
var collapsed = $(this).hasClass('collapsed');
var dataID = $(this).closest('tr').attr('data-id');
$form.find('tr.parent-' + dataID).toggle(!collapsed);
newUnfoldID.push(dataID);
url = createLink('misc', 'ajaxSetUnfoldID', 'objectID=' + objectID + '&objectType=' + objectType + '&action=' + (collapsed ? 'add' : 'delete'));
$table = $(this).closest('table');
setTimeout(function()
{
hasCollapsed = $table.find('td.has-child a.' + toggleClass + '.collapsed').length != 0;
$('#toggleFold').toggleClass('collapsed', hasCollapsed);
}, 100);
$.post(url, {'newUnfoldID': JSON.stringify(newUnfoldID)});
});
}
/**
* Adjust menu width.
*
* @access public
* @return void
*/
function adjustMenuWidth()
{
if(window.navigator.userAgent.indexOf('xuanxuan') > 0) return;
var $mainHeader = $('#mainHeader .container');
if($mainHeader.length == 0) return false;
var $navbar = $mainHeader.find('#navbar .nav');
var mainHeaderWidth = $mainHeader.width() - 10;
var headingWidth = $mainHeader.find('#heading').width() + 30;
var navbarWidth = $navbar.width();
var toolbarWidth = $mainHeader.find('#toolbar').width() + 20;
if(mainHeaderWidth < headingWidth + navbarWidth + toolbarWidth)
{
var delta = (headingWidth + navbarWidth + toolbarWidth) - mainHeaderWidth;
delta = Math.ceil(delta / $navbar.children('li').length / 2);
var aTagPadding = $navbar.find('a:first').css('padding-left').replace('px', '');
var dividerMargin = $navbar.find('.divider').css('margin-left').replace('px', '');
var newPadding = aTagPadding - delta;
var newMargin = dividerMargin - delta - 1;
if(newPadding < 0) newPadding = 0;
if(newMargin < 0) newMargin = 0;
$navbar.children('li').find('a').css('padding-left', newPadding).css('padding-right', newPadding);
$navbar.find('.divider').css('margin-left', newMargin).css('margin-right', newMargin);
}
}
/**
* Scroll to selected item in drop menu.
*
* @param string $id
* @access public
* @return void
*/
function scrollToSelected()
{
setTimeout(function()
{
$selected = $('#dropMenu .selected');
if($selected.length == 0) return;
$id = $selected.closest('.list-group');
$id.mouseout(function(){$(this).find('a.active:not(.not-list-item)').removeClass('active')});
var fixOffset = 160;
offsetTop = $selected.offset().top;
if(offsetTop < fixOffset) return;
$id.scrollTop(offsetTop - fixOffset);
}, 100);
}
/**
* Limit iframe levels up to 3.
*
* @access public
* @return void
*/
function limitIframeLevel()
{
/* Fix bug #15325. */
if(window.parent != window.top)
{
$('body').find('a.iframe').each(function()
{
$(this).replaceWith($(this).clone().removeClass('iframe'));
});
}
}
/**
* Remove html tag.
*
* @param str $str
* @access public
* @return void
*/
function removeHtmlTag(str)
{
return str.replace(/<[^>]+>/g,"");
}
/* Ping the server every some minutes to keep the session. */
needPing = true;
/* When body's ready, execute these. */
$(document).ready(function()
{
if(needPing) setTimeout('setPing()', 1000 * 60 * 10); // After 10 minutes, begin ping.
checkTutorial();
revertModuleCookie();
$(document).on('click', '#helpMenuItem .close-help-tab', function(){$('#helpMenuItem').prev().remove();$('#helpMenuItem').remove();});
/* Open link in new tab when pressed ctrl key in windows */
if(window.navigator.userAgent.match(/Windows/i))
{
$(document).on('mousedown', 'a', function(e)
{
var $a = $(this);
if(!e.ctrlKey || $a.attr('target')) return;
$a.attr('target', '_blank');
clearTimeout($a.data('ctrlTimer'));
$a.data('ctrlTimer', setTimeout(function(){$a.attr('target', null).data('ctrlTimer', 0)}, 100));
e.preventDefault();
});
}
/* Hide the global create drop-down when hovering over the avatar. */
$('.has-avatar').hover(function()
{
$(this).next().removeClass('open');
$(this).prev().removeClass('open');
});
/* Hide the avatar drop-down when hovering over the global create button. */
$('#globalCreate').hover(function()
{
$(this).next().removeClass('open');
$(this).addClass('dropdown-hover');
});
/* Hide create button when global create menu is clicked. */
$('#globalCreate').click(function()
{
$(this).removeClass('dropdown-hover');
});
});
/**
* Make the selected product non clickable.
*
* @return void
*/
function disableSelectedProduct()
{
$("select[id^='products'] option[disabled='disabled']").removeAttr('disabled');
var selectedVal = [];
$("select[id^='products']").each(function()
{
var selectedProduct = $(this).val();
if(selectedProduct != 0 && $.inArray(selectedProduct, selectedVal) < 0) selectedVal.push(selectedProduct);
})
$("select[id^='products']").each(function()
{
var selectedProduct = $(this).val();
$(this).find('option').each(function()
{
var optionVal = $(this).attr('value');
if(optionVal != selectedProduct && $.inArray(optionVal, selectedVal) >= 0) $(this).attr('disabled', 'disabled');
})
})
$("select[id^=products]").trigger('chosen:updated');
}
/**
* Make the selected branch non clickable.
*
* @return void
*/
function disableSelectedBranch()
{
var relatedProduct = $(this).siblings("select[id^='products']").val();
/* Get the products control of the same value and their branch control. */
var sameProductControl = [];
var sameProductBranchControl = [];
$("select[id^='products']").each(function()
{
if($(this).val() == relatedProduct)
{
$(this).siblings("select[id^='branch']").find("option[disabled='disabled']").removeAttr('disabled');
sameProductControl.push(this);
sameProductBranchControl.push($(this).siblings("select[id^='branch']"));
}
});
/* Get the selected branch of the related product. */
var preSelectedVal = [];
$.each(sameProductControl, function()
{
var selectedBranch = $(this).siblings("select[id^='branch']").val();
if($.inArray(selectedBranch, preSelectedVal) < 0) preSelectedVal.push(selectedBranch);
});
var selectedVal = [];
$.each(sameProductControl, function()
{
var selectedBranch = $(this).siblings("select[id^='branch']").val();
if($.inArray(selectedBranch, selectedVal) >= 0)
{
$(this).siblings("select[id^='branch']").find('option').removeAttr('selected');
for(i in preSelectedVal) $(this).siblings("select[id^='branch']").find('option[value=' + preSelectedVal[i] + ']').attr('disabled', 'disabled');
$(this).siblings("select[id^='branch']").find('option').not('[disabled=disabled]').eq(0).attr('selected', 'selected');
var selectedBranch = $(this).siblings("select[id^='branch']").val();
}
if($.inArray(selectedBranch, selectedVal) < 0) selectedVal.push(selectedBranch);
});
/* Make the selected value disabled. */
$.each(sameProductBranchControl, function()
{
var selectedBranch = $(this).val();
$(this).find('option').each(function()
{
var optionVal = $(this).attr('value');
if(optionVal != selectedBranch && $.inArray(optionVal, selectedVal) >= 0) $(this).attr('disabled', 'disabled');
})
})
$("select[id^=branch]").trigger('chosen:updated');
}
/**
* Determine whether multi-branch products should be disabled.
*
* @param object product
* @return bool
*/
function checkMultiProducts(product)
{
var disabledBranchList = [];
var optionLength = $(product).siblings("select[id^='branch']").find('option').length;
$(product).siblings("select[id^='branch']").find("option[disabled='disabled']").each(function()
{
disabledBranchList.push($(this).attr('value'));
});
if(optionLength - disabledBranchList.length == 1) return true;
return false;
}
/**
* Add row.
*
* @param object $obj
* @access public
* @return void
*/
function addRow(obj)
{
var row = $('#addRow').html().replace(/%i%/g, rowIndex + 1);
$('<tr class="addedRow">' + row + '</tr>').insertAfter($(obj).closest('tr'));
var $row = $(obj).closest('tr').next();
$row.find(".form-date").datepicker();
$row.find("input[name^=color]").colorPicker();
$row.find('div[id$=_chosen]').remove();
$row.find('.picker').remove();
$row.find('.chosen').chosen();
$row.find('.picker-select').picker();
rowIndex ++;
}
/**
* Delete row.
*
* @param object $obj
* @access public
* @return void
*/
function deleteRow(obj)
{
$(obj).closest('tr').remove();
}
/**
* Show checked fields.
*
* @param string fields
* @access public
* @return void
*/
function showCheckedFields(fields)
{
var fieldList = ',' + fields + ',';
$('#formSettingForm > .checkboxes > .checkbox-primary > input').each(function()
{
var field = ',' + $(this).val() + ',';
var $field = config.currentMethod == 'create' ? $('#' + $(this).val()) : $('[name^=' + $(this).val() + ']');
var $fieldBox = $('.' + $(this).val() + 'Box' );
var required = '';
if(typeof requiredFields != 'undefined') var required = ',' + requiredFields + ',';
if(fieldList.indexOf(field) >= 0 || (required && required.indexOf(field) >= 0))
{
$fieldBox.removeClass('hidden');
$field.removeAttr('disabled');
}
else if(!$fieldBox.hasClass('hidden'))
{
$fieldBox.addClass('hidden');
if($(this).val() != 'branch') $field.attr('disabled', true);
}
if(config.currentModule == 'story' && $(this).val() == 'source')
{
var $sourceNote = config.currentMethod == 'create' ? $('#sourceNote') : $('[name^=sourceNote]');
$sourceNote.attr('disabled', $fieldBox.hasClass('hidden'));
}
});
if(config.currentModule == 'task' && config.currentMethod == 'create');
{
if(fieldList.indexOf(',estStarted,') >= 0 && fieldList.indexOf(',deadline,') >= 0)
{
$('.borderBox').removeClass('hidden');
}
else if(fieldList.indexOf(',estStarted,') >= 0 || fieldList.indexOf(',deadline,') >= 0)
{
$('.datePlanBox').removeClass('hidden');
if(!$('.borderBox').hasClass('hidden')) $('.borderBox').addClass('hidden');
}
else
{
if(!$('.borderBox').hasClass('hidden')) $('.borderBox').addClass('hidden');
if(!$('.datePlanBox').hasClass('hidden')) $('.datePlanBox').addClass('hidden');
}
if(typeof lifetime != 'undefined' && lifetime == 'ops') $('.storyBox').addClass('hidden');
}
}
/**
* Hidden require field.
*
* @access public
* @return void
*/
function hiddenRequireFields()
{
$('#formSettingForm > .checkboxes > .checkbox-primary > input').each(function()
{
var field = ',' + $(this).val() + ',';
var required = ',' + requiredFields + ',';
if(required.indexOf(field) >= 0) $(this).closest('div').addClass('hidden');
});
}
/**
* Save custom fields.
*
* @param stirng $key
* @param int $maxFieldCount
* @param object $name
* @param int $nameMinWidth
* @access public
* @return void
*/
function saveCustomFields(key, maxFieldCount, $name, nameMinWidth)
{
var fields = '';
$('#formSettingForm > .checkboxes > .checkbox-primary > input:checked').each(function()
{
fields += ',' + $(this).val();
});
var module = config.currentModule;
var link = createLink('custom', 'ajaxSaveCustomFields', 'module=' + module + '&section=custom&key=' + key);
$.post(link, {'fields' : fields}, function()
{
showFields = fields;
showCheckedFields(fields);
$('#formSetting').parent().removeClass('open');
if(key == 'batchCreateFields') setCustomFieldsStyle(maxFieldCount, $name, nameMinWidth);
});
}
/**
* Set custom fields style.
*
* @param int $maxFieldCount
* @param object $name
* @param int $nameMinWidth
* @access public
* @return void
*/
function setCustomFieldsStyle(maxFieldCount, $name, nameMinWidth)
{
var fieldCount = $('#batchCreateForm .table thead>tr>th:visible').length;
$('.form-actions').attr('colspan', fieldCount);
var $table = $('#batchCreateForm > .table-responsive');
if(fieldCount > maxFieldCount)
{
$table.removeClass('scroll-none');
$table.css('overflow', 'auto');
}
else
{
$table.addClass('scroll-none');
$table.css('overflow', 'visible');
}
if($name.width() < nameMinWidth) $name.width(200);
}
/**
* Refresh budget units of the project.
*
* @param object $data
* @access public
* @return void
*/
function refreshBudgetUnit(data)
{
$('#budgetUnit').val(data.budgetUnit).trigger('chosen:updated');
if(typeof(data.availableBudget) == 'undefined')
{
$('#budget').removeAttr('placeholder').attr('disabled', true);
$('#future').prop('checked', true);
}
else
{
$('#budget').removeAttr('disabled');
$('#future').prop('checked', false);
}
}
/**
* Handle radio logic of Kanban column width setting.
*
* @access public
* @return void
*/
function handleKanbanWidthAttr ()
{
$('#colWidth, #minColWidth, #maxColWidth').attr('onkeyup', 'value=value.match(/^\\d+$/) ? value : ""');
$('#colWidth, #minColWidth, #maxColWidth').attr('maxlength', '3');
var fluidBoard = $("#mainContent input[name='fluidBoard'][checked='checked']").val() || 0;
var addAttrEle = fluidBoard == 0 ? '#colWidth' : '#minColWidth, #maxColWidth';
var $fixedTip = $('#colWidth + .fixedTip');
var $autoTip = $('#maxColWidth + .autoTip');
$(addAttrEle).closest('.width-radio-row').addClass('required');
$('#colWidth').attr('disabled',fluidBoard == 1);
$('#minColWidth, #maxColWidth').attr('disabled',fluidBoard == 0);
$("#minColWidth, #maxColWidth").on('input', function()
{
$('#minColWidthLabel, #maxColWidthLabel').remove();
$('#minColWidth, #maxColWidth').removeClass('has-error');
});
if(fluidBoard == 1)
{
$fixedTip.addClass('hidden');
$autoTip.removeClass('hidden');
}
else
{
$fixedTip.removeClass('hidden');
$autoTip.addClass('hidden');
}
$(document).on('change', "#mainContent input[name='fluidBoard']", function(e)
{
$('#colWidth').attr('disabled', e.target.value == 1);
$('#minColWidth, #maxColWidth').attr('disabled', e.target.value == 0);
if(e.target.value == 0 && $('#minColWidthLabel, #maxColWidthLabel'))
{
$('#colWidth').closest('.width-radio-row').addClass('required');
$('#minColWidth, #maxColWidth').closest('.width-radio-row').removeClass('required');
$('#minColWidthLabel, #maxColWidthLabel').remove();
$('#minColWidth, #maxColWidth').removeClass('has-error');
$fixedTip.removeClass('hidden');
$autoTip.addClass('hidden');
}
else if(e.target.value == 1 && $('#colWidthLabel'))
{
$('#minColWidth, #maxColWidth').closest('.width-radio-row').addClass('required');
$('#colWidth').closest('.width-radio-row').removeClass('required');
$('#colWidthLabel').remove();
$('#colWidth').removeClass('has-error');
$fixedTip.addClass('hidden');
$autoTip.removeClass('hidden');
}
});
}