* task #41783, #task 41765, implement tutorial mode and add new tutorial task.
This commit is contained in:
@@ -105,11 +105,16 @@ class tutorial extends control
|
||||
|
||||
/* Check priv for tutorial. */
|
||||
$hasPriv = false;
|
||||
foreach($this->lang->tutorial->tasks as $taskName)
|
||||
$moduleLower = strtolower($module);
|
||||
foreach($this->lang->tutorial->tasks as $task)
|
||||
{
|
||||
$taskModule = strtolower($taskName['nav']['module']);
|
||||
if($taskModule == strtolower($module)) $hasPriv = true;
|
||||
if($hasPriv) break;
|
||||
$taskModule = strtolower($task['nav']['module']);
|
||||
$taskMenuModule = strtolower($task['nav']['menuModule']);
|
||||
if($taskModule == $moduleLower or $taskMenuModule == $moduleLower)
|
||||
{
|
||||
$hasPriv = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!$hasPriv and $module == 'my' and $method == 'index') $hasPriv = true;
|
||||
if(!$hasPriv) die(js::locate('back'));
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#start {padding: 40px; text-align: center; color: #fff;}
|
||||
.start-icon {position: relative; width: 140px; height: 140px; margin: 0 auto; line-height: 140px;}
|
||||
.start-icon > .icon-back {font-size: 140px;}
|
||||
.start-icon > .icon-back {font-size: 140px; color: rgba(0,0,0,.1); text-shadow: 0 1px 7px rgb(0,0,0,.1);}
|
||||
.start-icon > .icon-back:before {content: '\f0a3';}
|
||||
.start-icon > .icon-front {font-size: 56px; position: absolute; top: 35px; left: 35px; color: #EBF2F9; z-index: 10; width: 70px; height: 70px; text-align: center; line-height: 70px;}
|
||||
.start-icon > .icon-front {font-size: 56px; position: absolute; top: 35px; left: 42px; color: #EBF2F9; z-index: 10; width: 70px; height: 70px; text-align: center; line-height: 70px; text-shadow: 0 1px 3px rgb(0,0,0,.15);}
|
||||
.start-icon > .icon-spin {-moz-animation: spin 15s infinite linear; -o-animation: spin 15s infinite linear; -webkit-animation: spin 15s infinite linear; animation: spin 15s infinite linear;}
|
||||
#start > h1, #start > p {margin-bottom: 30px;}
|
||||
|
||||
527
module/tutorial/js/index.js
Normal file
527
module/tutorial/js/index.js
Normal file
@@ -0,0 +1,527 @@
|
||||
$(function()
|
||||
{
|
||||
var formatSetting = function(str)
|
||||
{
|
||||
var settings = {};
|
||||
if(typeof str === 'string')
|
||||
{
|
||||
$.each(str.split(','), function(idx, name)
|
||||
{
|
||||
if(name) settings[name] = true;
|
||||
});
|
||||
}
|
||||
return settings;
|
||||
};
|
||||
|
||||
var tasks = tutorialTasks;
|
||||
var current = defaultTask;
|
||||
var setting = formatSetting(settingString);
|
||||
var lang =
|
||||
{
|
||||
targetPageTip : langTargetPageTip,
|
||||
targetAppTip : langTargetAppTip,
|
||||
target : langTarget,
|
||||
requiredTip : langRequiredTip,
|
||||
};
|
||||
|
||||
var $tasks = $('#tasks'),
|
||||
$task = $('#task'),
|
||||
$openTaskPage = $('#openTaskPage'),
|
||||
$progress = $('#tasksProgress'),
|
||||
$modal = $('#taskModal'),
|
||||
$modalBack = $('#taskModalBack');
|
||||
var totalCount = $tasks.children('li').length, finishCount = 0;
|
||||
|
||||
var appsWindow = window.frames['iframePage'];
|
||||
var checkTaskId = null, modalShowTaskId;
|
||||
var showToolTipTask = null;
|
||||
|
||||
var getApp = function(code)
|
||||
{
|
||||
if(!code) return appsWindow.$.apps.getLastApp();
|
||||
return $.extend({}, appsWindow.$.apps.appsMap[code], appsWindow.$.apps.openedApps[code]);
|
||||
};
|
||||
|
||||
var getAppWindow = function()
|
||||
{
|
||||
var app = appsWindow.$.apps.getLastApp();
|
||||
return appsWindow.frames['app-' + app.code];
|
||||
};
|
||||
|
||||
var getAppIframe = function()
|
||||
{
|
||||
var app = appsWindow.$.apps.getLastApp();
|
||||
return appsWindow.$('#appIframe-' + app.code).get(0);
|
||||
};
|
||||
|
||||
var showModal = function(showAll)
|
||||
{
|
||||
clearTimeout(modalShowTaskId);
|
||||
$modal.show();
|
||||
$modalBack.show();
|
||||
$modal.toggleClass('show-all', showAll);
|
||||
modalShowTaskId = setTimeout(function()
|
||||
{
|
||||
$modal.addClass('in');
|
||||
$modalBack.addClass('in');
|
||||
}, 10);
|
||||
};
|
||||
|
||||
var hideModal = function()
|
||||
{
|
||||
clearTimeout(modalShowTaskId);
|
||||
$modal.removeClass('in');
|
||||
$modalBack.removeClass('in');
|
||||
modalShowTaskId = setTimeout(function()
|
||||
{
|
||||
$modal.hide();
|
||||
$modalBack.hide();
|
||||
}, 450);
|
||||
};
|
||||
|
||||
var clearTips = function()
|
||||
{
|
||||
var $menuMainNav = appsWindow.$('#menuMainNav');
|
||||
$menuMainNav.find('.hl-tutorial').removeClass('hl-tutorial hl-in');
|
||||
$menuMainNav.find('.tooltip-tutorial').tooltip('destroy').removeClass('tooltip-tutorial');
|
||||
var appWindow = getAppWindow();
|
||||
if(appWindow && appWindow.$)
|
||||
{
|
||||
var $appBody = appWindow.$('body');
|
||||
$appBody.find('.hl-tutorial').removeClass('hl-tutorial hl-in');
|
||||
$appBody.find('.tooltip-tutorial').tooltip('destroy').removeClass('tooltip-tutorial');
|
||||
}
|
||||
};
|
||||
|
||||
var highlight = function($e, callback)
|
||||
{
|
||||
$e = $e.first();
|
||||
$e.closest('body').find('.hl-tutorial').removeClass('hl-tutorial hl-in');
|
||||
$e.addClass('hl-tutorial').parent().css('overflow', 'visible');
|
||||
setTimeout(function() {$e.addClass('hl-in'); callback && callback()}, 50);
|
||||
};
|
||||
|
||||
var finishTask = function()
|
||||
{
|
||||
clearTips();
|
||||
|
||||
var task = tasks[current];
|
||||
if(task)
|
||||
{
|
||||
setting[current] = true;
|
||||
var postData = [];
|
||||
$.each(setting, function(name, value) {if(value) postData.push(name);});
|
||||
|
||||
$.post(ajaxSetTasksUrl, {finish: postData.join(',')}, function(e)
|
||||
{
|
||||
if(e.result === 'success')
|
||||
{
|
||||
$task.addClass('finish').find('[data-target]').removeClass('active').addClass('finish');
|
||||
updateUI();
|
||||
showModal(finishCount >= totalCount);
|
||||
}
|
||||
else
|
||||
{
|
||||
setting[current] = false;
|
||||
alert(serverErrorTip);
|
||||
}
|
||||
}, 'json').error(function() {alert(lang.timeout)});
|
||||
}
|
||||
};
|
||||
|
||||
var resetTasks = function()
|
||||
{
|
||||
clearTips();
|
||||
|
||||
$.post(ajaxSetTasksUrl, {finish: ''}, function(e)
|
||||
{
|
||||
if(e.result === 'success')
|
||||
{
|
||||
setting = {};
|
||||
updateUI();
|
||||
}
|
||||
else
|
||||
{
|
||||
alert(serverErrorTip);
|
||||
}
|
||||
}, 'json').error(function() {alert(lang.timeout)});
|
||||
};
|
||||
|
||||
var showToolTip = function($e, text, options)
|
||||
{
|
||||
if(!$e.length) return;
|
||||
$e.closest('body').find('.tooltip-tutorial').tooltip('destroy');
|
||||
var offset = $e.offset();
|
||||
var winWidth = $(window).width();
|
||||
var placement = 'top';
|
||||
if(offset.left > (winWidth*2/3))
|
||||
{
|
||||
placement = 'left';
|
||||
}
|
||||
else if(offset.left < (winWidth/3) && (offset.left + $e.outerWidth()) < (winWidth*2/3))
|
||||
{
|
||||
placement = 'right';
|
||||
}
|
||||
else if (offset.top < 50)
|
||||
{
|
||||
placement = 'bottom';
|
||||
}
|
||||
|
||||
options = $.extend(
|
||||
{
|
||||
trigger: 'manual',
|
||||
title: text,
|
||||
placement: placement,
|
||||
container: 'body',
|
||||
tipClass: 'tooltip-warning tooltip-max'
|
||||
}, options);
|
||||
$e = $e.first();
|
||||
if($e.css('display') == 'none')
|
||||
{
|
||||
$e.parent().addClass('tooltip-tutorial').after("<div id='typeLabel' class='text-danger help-text'>" + options.title + "</div>");
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!$e.data('zui.tooltip')) $e.addClass('tooltip-tutorial').attr('data-toggle', 'tooltip').tooltip(options);
|
||||
$e.tooltip('show');
|
||||
if($e[0].getBoundingClientRect().top > $(window).height() || $e[0].getBoundingClientRect().top < 0) $e[0].scrollIntoView();
|
||||
}
|
||||
};
|
||||
|
||||
var tryCheckTask = function()
|
||||
{
|
||||
if(checkTaskId) clearTimeout(checkTaskId);
|
||||
|
||||
var iWindow = getAppWindow();
|
||||
if(!(iWindow && iWindow.config && iWindow.$))
|
||||
{
|
||||
checkTaskId = setTimeout(tryCheckTask, 1000);
|
||||
}
|
||||
else
|
||||
{
|
||||
checkTaskId = setTimeout(checkTask, 200);
|
||||
}
|
||||
};
|
||||
|
||||
var checkTask = function()
|
||||
{
|
||||
var iWindow = getAppWindow();
|
||||
if(!iWindow || !iWindow.$) return tryCheckTask();
|
||||
var task = tasks[current];
|
||||
var appCode = task.nav.app || task.nav.menuModule || task.nav['module'];
|
||||
var app = getApp(appCode);
|
||||
if(!app) return;
|
||||
|
||||
var $$ = iWindow.$;
|
||||
var pageConfig = iWindow.config;
|
||||
var currentModule = (iWindow.TUTORIAL ? iWindow.TUTORIAL['module'] : pageConfig ? pageConfig.currentModule : '').toLowerCase();
|
||||
var currentMethod = (iWindow.TUTORIAL ? iWindow.TUTORIAL['method'] : pageConfig ? pageConfig.currentMethod : '').toLowerCase();
|
||||
var targetStatus = status || {},
|
||||
$navTarget = $task.find('[data-target="nav"]').removeClass('active'),
|
||||
$formTarget = $task.find('[data-target="form"]').removeClass('active'),
|
||||
$submitTarget = $task.find('[data-target="submit"]').removeClass('active');
|
||||
targetStatus.nav = task.nav['module'].toLowerCase() === currentModule && task.nav['method'].toLowerCase() === currentMethod && (!task.nav.app || task.nav.app === appCode);
|
||||
|
||||
if(targetStatus.nav)
|
||||
{
|
||||
// check form target
|
||||
var $form = $$(task.nav.form);
|
||||
var $formWrapper = $form.closest('.main-content');
|
||||
if(!$formWrapper.length) $formWrapper = $form;
|
||||
highlight($formWrapper);
|
||||
showToolTip($formWrapper, $formTarget.text());
|
||||
var fieldSelector = '';
|
||||
var requiredFields = task.nav.requiredFields || pageConfig.requiredFields;
|
||||
|
||||
if(task.nav.formType === 'table')
|
||||
{
|
||||
fieldSelector = 'input[type="checkbox"]';
|
||||
var $checkboxes = $form.find(fieldSelector);
|
||||
targetStatus.form = $checkboxes.filter(':checked').length > 0;
|
||||
if(!targetStatus.form) {
|
||||
targetStatus.waitField = $checkboxes.filter(':not(:checked):first').closest('td');
|
||||
}
|
||||
}
|
||||
else if(requiredFields)
|
||||
{
|
||||
targetStatus.form = true;
|
||||
requiredFields = requiredFields.split(',');
|
||||
$.each(requiredFields, function(idx, requiredId)
|
||||
{
|
||||
fieldSelector += ',' + '#' + requiredId;
|
||||
var $required = $$('#' + requiredId);
|
||||
if($required.length)
|
||||
{
|
||||
var val = $required.val();
|
||||
if(val === undefined || val === null || val === '' || val === '0')
|
||||
{
|
||||
targetStatus.form = false;
|
||||
if(!targetStatus.waitField) targetStatus.waitField = $required;
|
||||
}
|
||||
}
|
||||
});
|
||||
if(fieldSelector.length > 1) fieldSelector = fieldSelector.substring(1);
|
||||
}
|
||||
|
||||
if(!$form.data('bindCheckTaskEvent'))
|
||||
{
|
||||
$form.off('.tutorial').off('submit');
|
||||
$form.on('change.tutorial', fieldSelector, tryCheckTask);
|
||||
var onSubmit = function(e)
|
||||
{
|
||||
var status = checkTask();
|
||||
if(!status.submitOK)
|
||||
{
|
||||
if(status.waitField)
|
||||
{
|
||||
var fieldName = status.waitField.closest('td').prev('th').text();
|
||||
if(!fieldName) fieldName = status.waitField.closest('.input-group').find('.input-group-addon:first').text();
|
||||
if(fieldName) showToolTip(status.waitField, lang.requiredTip.replace('%s', fieldName));
|
||||
highlight(status.waitField, function()
|
||||
{
|
||||
clearTimeout(showToolTipTask);
|
||||
showToolTipTask = setTimeout(function()
|
||||
{
|
||||
status.waitField.closest('td').find('#typeLabel').remove();
|
||||
showToolTip($formWrapper, $formTarget.text());
|
||||
highlight($formWrapper);
|
||||
}, 2000);
|
||||
});
|
||||
}
|
||||
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
finishTask();
|
||||
}
|
||||
}
|
||||
if(task.nav.submit) $form.on('click.tutorial', task.nav.submit, onSubmit);
|
||||
else $form.submit(onSubmit);
|
||||
}
|
||||
|
||||
if(targetStatus.form)
|
||||
{
|
||||
$submitTarget.addClass('active');
|
||||
if(task.nav.submit) showToolTip($form.find(task.nav.submit), $submitTarget.text(), {placement: 'top'});
|
||||
}
|
||||
else
|
||||
{
|
||||
$formTarget.addClass('active');
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Active current nav target in task panel */
|
||||
$navTarget.addClass('active');
|
||||
|
||||
/* Highlight app button in left menu */
|
||||
var $appNav = appsWindow.$('#menuMainNav > li[data-app="' + appCode + '"]');
|
||||
if(!app.show)
|
||||
{
|
||||
var targetAppTip = lang.targetAppTip.replace('%s', app.text || lang.target);
|
||||
highlight($appNav);
|
||||
showToolTip($appNav, targetAppTip);
|
||||
}
|
||||
else
|
||||
{
|
||||
$appNav.removeClass('hl-tutorial hl-in').tooltip('destroy');
|
||||
|
||||
var menuModule = task.nav.menuModule || task.nav['module'];
|
||||
var $navbar = $$('#navbar');
|
||||
var $navbarItem = $navbar.find('[data-id="' + menuModule + '"]');
|
||||
var targetPageTip = lang.targetPageTip.replace('%s', task.nav.targetPageName || lang.target);
|
||||
if($navbarItem.length && !$navbarItem.hasClass('active'))
|
||||
{
|
||||
highlight($navbarItem);
|
||||
showToolTip($navbarItem, targetPageTip);
|
||||
}
|
||||
else if(task.nav.menu)
|
||||
{
|
||||
if(task.nav.menu === '#pageNav')
|
||||
{
|
||||
var $pageNav = $$('#pageNav');
|
||||
var $targetBtn = $pageNav.find(task.nav.target);
|
||||
var $targetBtnGroup = $targetBtn.closest('.btn-group');
|
||||
if($targetBtnGroup.hasClass('open'))
|
||||
{
|
||||
highlight($targetBtn);
|
||||
showToolTip($targetBtn, targetPageTip);
|
||||
}
|
||||
else
|
||||
{
|
||||
highlight($targetBtnGroup);
|
||||
showToolTip($targetBtnGroup, targetPageTip);
|
||||
}
|
||||
if(!$targetBtnGroup.data('initTutorial'))
|
||||
{
|
||||
$targetBtnGroup.data('initTutorial', 1).on('click', tryCheckTask);
|
||||
}
|
||||
}
|
||||
else if(task.nav.menu[0] === '#')
|
||||
{
|
||||
var $customMenu = $$(task.nav.menu).last();
|
||||
if($customMenu.length)
|
||||
{
|
||||
highlight($customMenu);
|
||||
showToolTip($customMenu, targetPageTip);
|
||||
}
|
||||
else if(task.nav.target)
|
||||
{
|
||||
var $targetItem = $$(task.nav.target);
|
||||
highlight($targetItem);
|
||||
showToolTip($targetItem, targetPageTip);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var $modulemenu = $$('#subNavbar');
|
||||
var $modulemenuItem = $modulemenu.find('[data-id="' + task.nav.menu + '"]');
|
||||
if($modulemenuItem.length && !$modulemenuItem.hasClass('active'))
|
||||
{
|
||||
highlight($modulemenuItem);
|
||||
showToolTip($modulemenuItem, targetPageTip);
|
||||
}
|
||||
else if(task.nav.target)
|
||||
{
|
||||
var $targetItem = $$(task.nav.target);
|
||||
highlight($targetItem);
|
||||
showToolTip($targetItem, targetPageTip);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(task.nav.target)
|
||||
{
|
||||
var $targetItem = $$(task.nav.target);
|
||||
highlight($targetItem);
|
||||
showToolTip($targetItem, targetPageTip);
|
||||
}
|
||||
}
|
||||
}
|
||||
$navTarget.toggleClass('finish', !!targetStatus.nav);
|
||||
$formTarget.toggleClass('finish', !!targetStatus.form);
|
||||
$submitTarget.toggleClass('finish', !!targetStatus.submit);
|
||||
$openTaskPage.toggleClass('open', targetStatus.nav);
|
||||
|
||||
targetStatus.submitOK = targetStatus.nav && targetStatus.form;
|
||||
|
||||
return targetStatus;
|
||||
};
|
||||
|
||||
var checkTutorialState = function()
|
||||
{
|
||||
var iWindow = getAppWindow();
|
||||
iWindow = window.frames['iframePage'];
|
||||
tryCheckTask();
|
||||
var title = (iWindow.$ ? iWindow.$('head > title').text() : '') + $('head > title').text();
|
||||
var url = createLink('tutorial', 'index', 'referer=' + Base64.encode(iWindow.location.href) + '&task=' + current);
|
||||
try{window.history.replaceState({}, title, url);}catch(e){}
|
||||
};
|
||||
|
||||
var showTask = function(taskName)
|
||||
{
|
||||
clearTips();
|
||||
hideModal();
|
||||
|
||||
taskName = taskName || current;
|
||||
current = taskName;
|
||||
|
||||
if(!taskName) return;
|
||||
var task = tasks[taskName];
|
||||
if(!task) return;
|
||||
|
||||
var $li = $tasks.children('li').removeClass('active').filter('[data-name="' + taskName + '"]').addClass('active');
|
||||
$task.toggleClass('finish', task.finish);
|
||||
$('.task-name-current').text(task.title);
|
||||
$('.task-id-current').text(task.id);
|
||||
$('.task-desc').html(task.desc).find('.task-nav').addClass('btn-open-target-page');
|
||||
$('.task-page-name').text(task.nav.targetPageName || lang.target);
|
||||
|
||||
var $prev = $li.prev('li'), $next = $li.next('li');
|
||||
$('.btn-prev-task').toggleClass('hidden', !$prev.length).data('name', $prev.data('name'));
|
||||
$('.btn-next-task').toggleClass('hidden', !$next.length).data('name', $next.data('name'));
|
||||
tryCheckTask();
|
||||
};
|
||||
|
||||
var updateUI = function()
|
||||
{
|
||||
finishCount = 0;
|
||||
totalCount = 0;
|
||||
$tasks.children('li').each(function(idx)
|
||||
{
|
||||
var $li = $(this);
|
||||
var name = $li.data('name');
|
||||
var task = tasks[name];
|
||||
var finish = !!setting[name];
|
||||
task.id = idx + 1;
|
||||
task.finish = finish;
|
||||
finishCount += finish ? 1 : 0;
|
||||
totalCount++;
|
||||
|
||||
$li.toggleClass('finish', finish);
|
||||
if(!current && !finish) current = name;
|
||||
});
|
||||
|
||||
$('.task-num-finish').text(finishCount);
|
||||
var isFinishAll = finishCount >= totalCount;
|
||||
if(isFinishAll) current = $tasks.children('li').first().data('name');
|
||||
|
||||
var progress = Math.round(100*finishCount/totalCount);
|
||||
$progress.toggleClass('finish', isFinishAll).find('.progress-bar').css('width', (100*finishCount/totalCount) + '%');
|
||||
$progress.find('.progress-text').text(progress + '%');
|
||||
if(progress == 100) $.getJSON(createLink('tutorial', 'ajaxFinish'));
|
||||
showTask(current);
|
||||
};
|
||||
|
||||
/** Init apps iframe page */
|
||||
function initAppsPage()
|
||||
{
|
||||
var appsIframe = $('#iframePage').get(0);
|
||||
appsIframe.onload = appsIframe.onreadystatechange = function()
|
||||
{
|
||||
appsWindow.$(appsWindow.document).on('show.zentaoapp close.zentaoapp hide.zentaoapp', checkTutorialState);
|
||||
|
||||
/* Open referer page in app tab */
|
||||
if(tutorialReferer) appsWindow.$.apps.open(tutorialReferer);
|
||||
|
||||
updateUI();
|
||||
};
|
||||
}
|
||||
|
||||
/** Init current tutorial page */
|
||||
function initTutorial()
|
||||
{
|
||||
/* Quit tutorial mode on unload page */
|
||||
window.onbeforeunload = function()
|
||||
{
|
||||
var url = createLink('tutorial', 'quit');
|
||||
if(typeof navigator.sendBeacon === 'function') navigator.sendBeacon(url);
|
||||
else $.ajax({url: url, dataType: 'json', async: false});
|
||||
}
|
||||
|
||||
if(finishCount >= totalCount) showModal(true);
|
||||
|
||||
$(document).on('click', '.btn-task', function()
|
||||
{
|
||||
showTask($(this).data('name'));
|
||||
}).on('click', '.btn-reset-tasks', function()
|
||||
{
|
||||
hideModal();
|
||||
resetTasks();
|
||||
});
|
||||
|
||||
$modal.on('click', '.close', hideModal);
|
||||
|
||||
$('[data-toggle="tooltip"]').tooltip();
|
||||
|
||||
window.appsWindow = appsWindow;
|
||||
window.getAppIframe = getAppIframe;
|
||||
window.getAppWindow = getAppWindow;
|
||||
window.checkTutorialState = checkTutorialState;
|
||||
}
|
||||
|
||||
initTutorial();
|
||||
initAppsPage();
|
||||
});
|
||||
@@ -25,6 +25,7 @@ $lang->tutorial->atTargetPage = '已在 <strong class="task-page-name">目
|
||||
$lang->tutorial->reloadTargetPage = '重新载入';
|
||||
$lang->tutorial->target = '目标';
|
||||
$lang->tutorial->targetPageTip = '按此指示打开【%s】页面';
|
||||
$lang->tutorial->targetAppTip = '按此指示打开【%s】应用';
|
||||
$lang->tutorial->requiredTip = '【%s】为必填项';
|
||||
$lang->tutorial->congratulateTask = '恭喜,你完成了任务 【<span class="task-name-current"></span>】!';
|
||||
$lang->tutorial->serverErrorTip = '发生了一些错误。';
|
||||
@@ -35,49 +36,57 @@ $lang->tutorial->dataNotSave = "教程任务中,数据不会保存。";
|
||||
$lang->tutorial->tasks = array();
|
||||
|
||||
$lang->tutorial->tasks['createAccount'] = array('title' => '创建帐号');
|
||||
$lang->tutorial->tasks['createAccount']['nav'] = array('module' => 'user', 'method' => 'create', 'menuModule' => 'company', 'menu' => 'browseUser', 'form' => '#createForm', 'submit' => '#submit', 'target' => '.create-user-btn', 'targetPageName' => '添加用户');
|
||||
$lang->tutorial->tasks['createAccount']['nav'] = array('app' => 'admin', 'module' => 'user', 'method' => 'create', 'menuModule' => 'company', 'menu' => 'browseUser', 'form' => '#createForm', 'submit' => '#submit', 'target' => '.create-user-btn', 'targetPageName' => '添加用户');
|
||||
$lang->tutorial->tasks['createAccount']['desc'] = "<p>在系统创建一个新的用户帐号:</p><ul><li data-target='nav'>打开 <span class='task-nav'>组织 <i class='icon icon-angle-right'></i> 用户 <i class='icon icon-angle-right'></i> 添加用户</span> 页面;</li><li data-target='form'>在添加用户表单中填写新用户信息;</li><li data-target='submit'>保存用户信息。</li></ul>";
|
||||
|
||||
$lang->tutorial->tasks['createProgram'] = array('title' => '创建项目集');
|
||||
$lang->tutorial->tasks['createProgram']['nav'] = array('app' => 'program', 'module' => 'program', 'method' => 'create', 'menuModule' => 'program', 'menu' => 'browse', 'form' => '#dataform', 'submit' => '#submit', 'target' => '.create-program-btn', 'targetPageName' => '添加项目集');
|
||||
$lang->tutorial->tasks['createProgram']['desc'] = "<p>在系统创建一个新的项目集:</p><ul><li data-target='nav'>打开 <span class='task-nav'>项目集 <i class='icon icon-angle-right'></i> 项目集列表 <i class='icon icon-angle-right'></i> 添加项目集</span> 页面;</li><li data-target='form'>在添加项目集表单中填写项目集信息;</li><li data-target='submit'>保存项目集信息。</li></ul>";
|
||||
|
||||
global $config;
|
||||
if($config->global->flow == 'full' or $config->global->flow != 'onlyTask')
|
||||
{
|
||||
$lang->tutorial->tasks['createProduct'] = array('title' => '创建' . $lang->productCommon);
|
||||
$lang->tutorial->tasks['createProduct']['nav'] = array('module' => 'product', 'method' => 'create', 'menu' => '#pageNav', 'form' => '#createForm', 'submit' => '#submit', 'target' => '.create-product-btn', 'targetPageName' => '添加' . $lang->productCommon);
|
||||
$lang->tutorial->tasks['createProduct']['nav'] = array('app' => 'product', 'module' => 'product', 'method' => 'create', 'menuModule' => 'product', 'menu' => 'all', 'form' => '#createForm', 'submit' => '#submit', 'target' => '.create-product-btn', 'targetPageName' => '添加' . $lang->productCommon);
|
||||
$lang->tutorial->tasks['createProduct']['desc'] = "<p>在系统创建一个新的{$lang->productCommon}:</p><ul><li data-target='nav'>打开 <span class='task-nav'>{$lang->productCommon} <i class='icon icon-angle-right'></i> 添加{$lang->productCommon}</span> 页面;</li><li data-target='form'>在表单中填写要创建的{$lang->productCommon}信息;</li><li data-target='submit'>保存{$lang->productCommon}信息。</li></ul>";
|
||||
}
|
||||
|
||||
if($config->global->flow == 'full' or $config->global->flow == 'onlyStory')
|
||||
{
|
||||
$lang->tutorial->tasks['createStory'] = array('title' => "创建{$lang->SRCommon}");
|
||||
$lang->tutorial->tasks['createStory']['nav'] = array('module' => 'story', 'method' => 'create', 'menuModule' => 'product', 'menu' => 'story', 'target' => '.create-story-btn', 'form' => '#dataform', 'submit' => '#submit', 'targetPageName' => "提{$lang->SRCommon}");
|
||||
$lang->tutorial->tasks['createStory']['nav'] = array('app' => 'product', 'module' => 'story', 'method' => 'create', 'menuModule' => 'story', 'menu' => '#productTableList>tr:not(.has-nest-child)>.c-name>a', 'target' => '.create-story-btn', 'form' => '#dataform', 'submit' => '#submit', 'targetPageName' => "提{$lang->SRCommon}");
|
||||
$lang->tutorial->tasks['createStory']['desc'] = "<p>在系统创建一个新的{$lang->SRCommon}:</p><ul><li data-target='nav'>打开 <span class='task-nav'>{$lang->productCommon} <i class='icon icon-angle-right'></i> {$lang->SRCommon} <i class='icon icon-angle-right'></i> 添加{$lang->SRCommon}</span> 页面;</li><li data-target='form'>在表单中填写要创建的{$lang->SRCommon}信息;</li><li data-target='submit'>保存{$lang->SRCommon}信息。</li></ul>";
|
||||
}
|
||||
|
||||
if($config->global->flow == 'full' or $config->global->flow == 'onlyTask')
|
||||
{
|
||||
$lang->tutorial->tasks['createProject'] = array('title' => '创建' . $lang->executionCommon);
|
||||
$lang->tutorial->tasks['createProject']['nav'] = array('module' => 'execution', 'method' => 'create', 'menu' => '#pageNav', 'form' => '#dataform', 'submit' => '#submit', 'target' => '.create-project-btn', 'targetPageName' => '添加' . $lang->executionCommon);
|
||||
$lang->tutorial->tasks['createProject']['desc'] = "<p>在系统创建一个新的{$lang->executionCommon}:</p><ul><li data-target='nav'>打开 <span class='task-nav'> {$lang->executionCommon} <i class='icon icon-angle-right'></i> 添加{$lang->executionCommon}</span> 页面;</li><li data-target='form'>在表单中填写要创建的{$lang->executionCommon}信息;</li><li data-target='submit'>保存{$lang->executionCommon}信息。</li></ul>";
|
||||
$lang->tutorial->tasks['createProject'] = array('title' => '创建' . $lang->projectCommon);
|
||||
$lang->tutorial->tasks['createProject']['nav'] = array('app' => 'project', 'module' => 'project', 'method' => 'create', 'menuModule' => 'browse', 'menu' => '', 'form' => '#dataform', 'submit' => '#submit', 'target' => '.create-project-btn', 'targetPageName' => '添加' . $lang->projectCommon);
|
||||
$lang->tutorial->tasks['createProject']['desc'] = "<p>在系统创建一个新的{$lang->projectCommon}:</p><ul><li data-target='nav'>打开 <span class='task-nav'> {$lang->projectCommon} <i class='icon icon-angle-right'></i> {$lang->projectCommon}列表 <i class='icon icon-angle-right'></i> 添加{$lang->projectCommon}</span> 页面;</li><li data-target='form'>在表单中填写要创建的{$lang->projectCommon}信息;</li><li data-target='submit'>保存{$lang->projectCommon}信息。</li></ul>";
|
||||
|
||||
$lang->tutorial->tasks['manageTeam'] = array('title' => '管理团队');
|
||||
$lang->tutorial->tasks['manageTeam']['nav'] = array('module' => 'execution', 'method' => 'managemembers', 'menu' => 'team', 'target' => '.manage-team-btn', 'form' => '#teamForm', 'requiredFields' => 'account1', 'submit' => '#submit', 'targetPageName' => '团队管理');
|
||||
$lang->tutorial->tasks['manageTeam']['desc'] = "<p>管理{$lang->executionCommon}团队成员:</p><ul><li data-target='nav'>打开 <span class='task-nav'> {$lang->executionCommon} <i class='icon icon-angle-right'></i> 团队 <i class='icon icon-angle-right'></i> 团队管理</span> 页面;</li><li data-target='form'>选择要加入团队的成员;</li><li data-target='submit'>保存团队成员信息。</li></ul>";
|
||||
$lang->tutorial->tasks['manageTeam']['nav'] = array('app' => 'execution', 'module' => 'execution', 'method' => 'managemembers', 'menuModule' => 'settings', 'menu' => 'team', 'target' => '.manage-team-btn', 'form' => '#teamForm', 'requiredFields' => 'account1', 'submit' => '#submit', 'targetPageName' => '团队管理');
|
||||
$lang->tutorial->tasks['manageTeam']['desc'] = "<p>管理{$lang->executionCommon}团队成员:</p><ul><li data-target='nav'>打开 <span class='task-nav'> {$lang->executionCommon} <i class='icon icon-angle-right'></i> 设置 <i class='icon icon-angle-right'></i> 团队 <i class='icon icon-angle-right'></i> 团队管理</span> 页面;</li><li data-target='form'>选择要加入团队的成员;</li><li data-target='submit'>保存团队成员信息。</li></ul>";
|
||||
|
||||
$lang->tutorial->tasks['createExecution'] = array('title' => '创建' . $lang->executionCommon);
|
||||
$lang->tutorial->tasks['createExecution']['nav'] = array('app' => 'execution', 'module' => 'project', 'method' => 'create', 'menuModule' => 'browse', 'menu' => '#heading>.header-btn,#navbar>.nav>li[data-id="all"]', 'form' => '#dataform', 'submit' => '#submit', 'target' => '.create-execution-btn', 'targetPageName' => '添加' . $lang->executionCommon);
|
||||
$lang->tutorial->tasks['createExecution']['desc'] = "<p>在系统创建一个新的{$lang->executionCommon}:</p><ul><li data-target='nav'>打开 <span class='task-nav'> {$lang->executionCommon} <i class='icon icon-angle-right'></i> {$lang->executionCommon}列表 <i class='icon icon-angle-right'></i> 添加{$lang->executionCommon}</span> 页面;</li><li data-target='form'>在表单中填写要创建的{$lang->executionCommon}信息;</li><li data-target='submit'>保存{$lang->executionCommon}信息。</li></ul>";
|
||||
|
||||
if($config->global->flow == 'full')
|
||||
{
|
||||
$lang->tutorial->tasks['linkStory'] = array('title' => "关联{$lang->SRCommon}");
|
||||
$lang->tutorial->tasks['linkStory']['nav'] = array('module' => 'execution', 'method' => 'linkStory', 'menu' => 'story', 'target' => '.link-story-btn', 'form' => '#linkStoryForm', 'formType' => 'table', 'submit' => '#submit', 'targetPageName' => "关联{$lang->SRCommon}");
|
||||
$lang->tutorial->tasks['linkStory']['nav'] = array('app' => 'execution', 'module' => 'execution', 'method' => 'linkStory', 'menuModule' => 'story', 'menu' => '', 'target' => '.link-story-btn', 'form' => '#linkStoryForm', 'formType' => 'table', 'submit' => '#submit', 'targetPageName' => "关联{$lang->SRCommon}");
|
||||
$lang->tutorial->tasks['linkStory']['desc'] = "<p>将{$lang->SRCommon}关联到{$lang->executionCommon}:</p><ul><li data-target='nav'>打开 <span class='task-nav'> {$lang->executionCommon} <i class='icon icon-angle-right'></i> {$lang->SRCommon} <i class='icon icon-angle-right'></i> 关联{$lang->SRCommon}</span> 页面;</li><li data-target='form'>在{$lang->SRCommon}列表中勾选要关联的{$lang->SRCommon};</li><li data-target='submit'>保存关联的{$lang->SRCommon}信息。</li></ul>";
|
||||
}
|
||||
|
||||
$lang->tutorial->tasks['createTask'] = array('title' => '分解任务');
|
||||
$lang->tutorial->tasks['createTask']['nav'] = array('module' => 'task', 'method' => 'create', 'menuModule' => 'execution', 'menu' => 'story', 'target' => '.btn-task-create', 'form' => '#dataform', 'submit' => '#submit', 'targetPageName' => '建任务');
|
||||
$lang->tutorial->tasks['createTask']['nav'] = array('app' => 'execution', 'module' => 'task', 'method' => 'create', 'menuModule' => 'story', 'menu' => '', 'target' => '.btn-task-create', 'form' => '#dataform', 'submit' => '#submit', 'targetPageName' => '建任务');
|
||||
$lang->tutorial->tasks['createTask']['desc'] = "<p>将{$lang->executionCommon}{$lang->SRCommon}分解为任务:</p><ul><li data-target='nav'>打开 <span class='task-nav'> {$lang->executionCommon} <i class='icon icon-angle-right'></i> {$lang->SRCommon} <i class='icon icon-angle-right'></i> 分解任务</span> 页面;</li><li data-target='form'>在表单中填写任务信息;</li><li data-target='submit'>保存任务信息。</li></ul>";
|
||||
}
|
||||
|
||||
if($config->global->flow == 'full' or $config->global->flow == 'onlyTest')
|
||||
{
|
||||
$lang->tutorial->tasks['createBug'] = array('title' => '提Bug');
|
||||
$lang->tutorial->tasks['createBug']['nav'] = array('module' => 'bug', 'method' => 'create', 'menuModule' => 'qa', 'menu' => 'bug', 'target' => '.btn-bug-create', 'form' => '#dataform', 'submit' => '#submit', 'targetPageName' => '提Bug');
|
||||
$lang->tutorial->tasks['createBug']['nav'] = array('app' => 'qa', 'module' => 'bug', 'method' => 'create', 'menuModule' => 'bug', 'menu' => 'bug', 'target' => '.create-bug-btn', 'form' => '#dataform', 'submit' => '#submit', 'targetPageName' => '提Bug');
|
||||
$lang->tutorial->tasks['createBug']['desc'] = "<p>在系统中提交一个Bug:</p><ul><li data-target='nav'>打开 <span class='task-nav'> 测试 <i class='icon icon-angle-right'></i> Bug <i class='icon icon-angle-right'></i> 提Bug</span>;</li><li data-target='form'>在表单中填写Bug信息;</li><li data-target='submit'>保存Bug信息。</li></ul>";
|
||||
}
|
||||
|
||||
@@ -12,10 +12,9 @@
|
||||
?>
|
||||
<?php include '../../common/view/header.lite.html.php';?>
|
||||
<?php js::import($jsRoot . 'misc/base64.js');?>
|
||||
<?php $referer = $referer ? $referer : helper::createLink('my', 'index', '', 'tutorial');?>
|
||||
<div id='pageContainer'>
|
||||
<div id='iframeWrapper'>
|
||||
<iframe id='iframePage' name='iframePage' src='<?php echo $referer;?>' frameborder='no' allowtransparency='true' scrolling='auto' hidefocus='' style='width: 100%; height: 100%; left: 0; top: 0'></iframe>
|
||||
<iframe id='iframePage' name='iframePage' src='<?php echo helper::createLink('index', 'index', '', 'tutorial'); ?>' frameborder='no' allowtransparency='true' scrolling='auto' hidefocus='' style='width: 100%; height: 100%; left: 0; top: 0'></iframe>
|
||||
<div id='taskModalBack'></div>
|
||||
<div id='taskModal'>
|
||||
<button class='close'><i class="icon icon-close"></i></button>
|
||||
@@ -77,7 +76,7 @@
|
||||
<?php
|
||||
$nav = $task['nav'];
|
||||
$task['name'] = $name;
|
||||
$task['id'] = $idx + 1;
|
||||
$task['id'] = $idx++;
|
||||
$task['url'] = helper::createLink($nav['module'], $nav['method'], isset($nav['vars']) ? $nav['vars'] : '', 'tutorial');
|
||||
$tasks[$name] = $task;
|
||||
?>
|
||||
@@ -87,448 +86,16 @@
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
<?php js::set('tutorialReferer', $referer);?>
|
||||
<?php js::set('ajaxSetTasksUrl', inlink('ajaxSetTasks'));?>
|
||||
<?php js::set('serverErrorTip', $lang->tutorial->serverErrorTip);?>
|
||||
<?php js::set('defaultTask', $current);?>
|
||||
<?php js::set('settingString', $setting);?>
|
||||
<?php js::set('langTargetPageTip', $lang->tutorial->targetPageTip);?>
|
||||
<?php js::set('langTarget', $lang->tutorial->target);?>
|
||||
<?php js::set('langTargetAppTip', $lang->tutorial->targetAppTip);?>
|
||||
<?php js::set('langRequiredTip', $lang->tutorial->requiredTip);?>
|
||||
<script>
|
||||
$(function()
|
||||
{
|
||||
var formatSetting = function(str)
|
||||
{
|
||||
var settings = {};
|
||||
if(typeof str === 'string')
|
||||
{
|
||||
$.each(str.split(','), function(idx, name)
|
||||
{
|
||||
if(name) settings[name] = true;
|
||||
});
|
||||
}
|
||||
return settings;
|
||||
};
|
||||
|
||||
var tasks = $.parseJSON('<?php echo helper::jsonEncode4Parse($tasks, JSON_HEX_QUOT | JSON_HEX_APOS);?>');
|
||||
var current = '<?php echo $current;?>';
|
||||
var setting = formatSetting('<?php echo $setting;?>');
|
||||
var lang =
|
||||
{
|
||||
tagetPageTip: '<?php echo $lang->tutorial->targetPageTip;?>',
|
||||
target : '<?php echo $lang->tutorial->target;?>',
|
||||
requiredTip : '<?php echo $lang->tutorial->requiredTip;?>'
|
||||
};
|
||||
|
||||
var $tasks = $('#tasks'),
|
||||
$task = $('#task'),
|
||||
$openTaskPage = $('#openTaskPage'),
|
||||
$progress = $('#tasksProgress'),
|
||||
$modal = $('#taskModal'),
|
||||
$modalBack = $('#taskModalBack');
|
||||
var totalCount = $tasks.children('li').length, finishCount = 0;
|
||||
|
||||
var iWindow = window.frames['iframePage'];
|
||||
var iframe = $('#iframePage').get(0);
|
||||
var checkTaskId = null, modalShowTaskId;
|
||||
var showToolTipTask = null;
|
||||
|
||||
var showModal = function(showAll)
|
||||
{
|
||||
clearTimeout(modalShowTaskId);
|
||||
$modal.show();
|
||||
$modalBack.show();
|
||||
$modal.toggleClass('show-all', showAll);
|
||||
modalShowTaskId = setTimeout(function()
|
||||
{
|
||||
$modal.addClass('in');
|
||||
$modalBack.addClass('in');
|
||||
}, 10);
|
||||
};
|
||||
|
||||
var hideModal = function()
|
||||
{
|
||||
clearTimeout(modalShowTaskId);
|
||||
$modal.removeClass('in');
|
||||
$modalBack.removeClass('in');
|
||||
modalShowTaskId = setTimeout(function()
|
||||
{
|
||||
$modal.hide();
|
||||
$modalBack.hide();
|
||||
}, 450);
|
||||
};
|
||||
|
||||
var highlight = function($e, callback)
|
||||
{
|
||||
$e = $e.first();
|
||||
$e.closest('body').find('.hl-tutorial').removeClass('hl-tutorial hl-in');
|
||||
$e.addClass('hl-tutorial').parent().css('overflow', 'visible');
|
||||
setTimeout(function() {$e.addClass('hl-in'); callback && callback()}, 50);
|
||||
};
|
||||
|
||||
var finishTask = function()
|
||||
{
|
||||
var task = tasks[current];
|
||||
if(task)
|
||||
{
|
||||
setting[current] = true;
|
||||
var postData = [];
|
||||
$.each(setting, function(name, value) {if(value) postData.push(name);});
|
||||
|
||||
$.post('<?php echo inlink('ajaxSetTasks');?>', {finish: postData.join(',')}, function(e)
|
||||
{
|
||||
if(e.result === 'success')
|
||||
{
|
||||
$task.addClass('finish').find('[data-target]').removeClass('active').addClass('finish');
|
||||
updateUI();
|
||||
showModal(finishCount >= totalCount);
|
||||
}
|
||||
else
|
||||
{
|
||||
setting[current] = false;
|
||||
alert('<?php echo $lang->tutorial->serverErrorTip;?>');
|
||||
}
|
||||
}, 'json').error(function() {alert(lang.timeout)});
|
||||
}
|
||||
};
|
||||
|
||||
var resetTasks = function()
|
||||
{
|
||||
$.post('<?php echo inLink('ajaxSetTasks');?>', {finish: ''}, function(e)
|
||||
{
|
||||
if(e.result === 'success')
|
||||
{
|
||||
setting = {};
|
||||
updateUI();
|
||||
}
|
||||
else
|
||||
{
|
||||
alert('<?php echo $lang->tutorial->serverErrorTip;?>');
|
||||
}
|
||||
}, 'json').error(function() {alert(lang.timeout)});
|
||||
};
|
||||
|
||||
var showToolTip = function($e, text, options)
|
||||
{
|
||||
if(!$e.length) return;
|
||||
$e.closest('body').find('[data-toggle=tooltip]').tooltip('destroy');
|
||||
var offset = $e.offset();
|
||||
var winWidth = $(window).width();
|
||||
var placement = 'top';
|
||||
if(offset.left > (winWidth*2/3))
|
||||
{
|
||||
placement = 'left';
|
||||
}
|
||||
else if(offset.left < (winWidth/3) && (offset.left + $e.outerWidth()) < (winWidth*2/3))
|
||||
{
|
||||
placement = 'right';
|
||||
}
|
||||
else if (offset.top < 50)
|
||||
{
|
||||
placement = 'bottom';
|
||||
}
|
||||
|
||||
options = $.extend(
|
||||
{
|
||||
trigger: 'manual',
|
||||
title: text,
|
||||
placement: placement,
|
||||
container: 'body',
|
||||
tipClass: 'tooltip-warning tooltip-max'
|
||||
}, options);
|
||||
$e = $e.first();
|
||||
if($e.css('display') == 'none')
|
||||
{
|
||||
$e.parent().addClass('tooltip-tutorial').after("<div id='typeLabel' class='text-danger help-text'>" + options.title + "</div>");
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!$e.data('zui.tooltip')) $e.addClass('tooltip-tutorial').attr('data-toggle', 'tooltip').tooltip(options);
|
||||
$e.tooltip('show');
|
||||
if($e[0].getBoundingClientRect().top > $(window).height() || $e[0].getBoundingClientRect().top < 0) $e[0].scrollIntoView();
|
||||
}
|
||||
};
|
||||
|
||||
var tryCheckTask = function()
|
||||
{
|
||||
if(checkTaskId) clearTimeout(checkTaskId);
|
||||
|
||||
if(!(iWindow && iWindow.config && iWindow.$))
|
||||
{
|
||||
checkTaskId = setTimeout(tryCheckTask, 1000);
|
||||
}
|
||||
else
|
||||
{
|
||||
checkTaskId = setTimeout(checkTask, 200);
|
||||
}
|
||||
};
|
||||
|
||||
var checkTask = function()
|
||||
{
|
||||
if(!iWindow || !iWindow.$) return tryCheckTask();
|
||||
var task = tasks[current];
|
||||
var $$ = iWindow.$;
|
||||
var pageConfig = iWindow.config;
|
||||
var currentModule = (iWindow.TUTORIAL ? iWindow.TUTORIAL['module'] : pageConfig ? pageConfig.currentModule : '').toLowerCase();
|
||||
var currentMethod = (iWindow.TUTORIAL ? iWindow.TUTORIAL['method'] : pageConfig ? pageConfig.currentMethod : '').toLowerCase();
|
||||
var targetStatus = status || {},
|
||||
$navTarget = $task.find('[data-target="nav"]').removeClass('active'),
|
||||
$formTarget = $task.find('[data-target="form"]').removeClass('active'),
|
||||
$submitTarget = $task.find('[data-target="submit"]').removeClass('active');
|
||||
targetStatus.nav = task.nav['module'].toLowerCase() === currentModule && task.nav['method'].toLowerCase() === currentMethod;
|
||||
|
||||
if(targetStatus.nav)
|
||||
{
|
||||
// check form target
|
||||
var $form = $$(task.nav.form);
|
||||
var $formWrapper = $form.closest('.main-content');
|
||||
if(!$formWrapper.length) $formWrapper = $form;
|
||||
highlight($formWrapper);
|
||||
showToolTip($formWrapper, $formTarget.text());
|
||||
var fieldSelector = '';
|
||||
var requiredFields = task.nav.requiredFields || pageConfig.requiredFields;
|
||||
|
||||
if(task.nav.formType === 'table')
|
||||
{
|
||||
fieldSelector = 'input[type="checkbox"]';
|
||||
var $checkboxes = $form.find(fieldSelector);
|
||||
targetStatus.form = $checkboxes.filter(':checked').length > 0;
|
||||
if(!targetStatus.form) {
|
||||
targetStatus.waitField = $checkboxes.filter(':not(:checked):first').closest('td');
|
||||
}
|
||||
}
|
||||
else if(requiredFields)
|
||||
{
|
||||
targetStatus.form = true;
|
||||
requiredFields = requiredFields.split(',');
|
||||
$.each(requiredFields, function(idx, requiredId)
|
||||
{
|
||||
fieldSelector += ',' + '#' + requiredId;
|
||||
var $required = $$('#' + requiredId);
|
||||
if($required.length)
|
||||
{
|
||||
var val = $required.val();
|
||||
if(val === undefined || val === null || val === '' || val === '0')
|
||||
{
|
||||
targetStatus.form = false;
|
||||
if(!targetStatus.waitField) targetStatus.waitField = $required;
|
||||
}
|
||||
}
|
||||
});
|
||||
if(fieldSelector.length > 1) fieldSelector = fieldSelector.substring(1);
|
||||
}
|
||||
|
||||
if(!$form.data('bindCheckTaskEvent'))
|
||||
{
|
||||
$form.off('.tutorial').off('submit');
|
||||
$form.on('change.tutorial', fieldSelector, tryCheckTask);
|
||||
var onSubmit = function(e)
|
||||
{
|
||||
var status = checkTask();
|
||||
if(!status.submitOK)
|
||||
{
|
||||
if(status.waitField)
|
||||
{
|
||||
var fieldName = status.waitField.closest('td').prev('th').text();
|
||||
if(!fieldName) fieldName = status.waitField.closest('.input-group').find('.input-group-addon:first').text();
|
||||
if(fieldName) showToolTip(status.waitField, lang.requiredTip.replace('%s', fieldName));
|
||||
highlight(status.waitField, function()
|
||||
{
|
||||
clearTimeout(showToolTipTask);
|
||||
showToolTipTask = setTimeout(function()
|
||||
{
|
||||
status.waitField.closest('td').find('#typeLabel').remove();
|
||||
showToolTip($formWrapper, $formTarget.text());
|
||||
highlight($formWrapper);
|
||||
}, 2000);
|
||||
});
|
||||
}
|
||||
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
finishTask();
|
||||
}
|
||||
}
|
||||
if(task.nav.submit) $form.on('click.tutorial', task.nav.submit, onSubmit);
|
||||
else $form.submit(onSubmit);
|
||||
}
|
||||
|
||||
if(targetStatus.form)
|
||||
{
|
||||
$submitTarget.addClass('active');
|
||||
if(task.nav.submit) showToolTip($form.find(task.nav.submit), $submitTarget.text(), {placement: 'top'});
|
||||
}
|
||||
else
|
||||
{
|
||||
$formTarget.addClass('active');
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// check nav target
|
||||
$navTarget.addClass('active');
|
||||
var menuModule = task.nav.menuModule || task.nav['module'];
|
||||
var $navbar = $$('#navbar');
|
||||
var $navbarItem = $navbar.find('[data-id="' + menuModule + '"]');
|
||||
var tagetPageTip = lang.tagetPageTip.replace('%s', task.nav.targetPageName || lang.target);
|
||||
if(!$navbarItem.hasClass('active'))
|
||||
{
|
||||
highlight($navbarItem);
|
||||
showToolTip($navbarItem, tagetPageTip);
|
||||
}
|
||||
else if(task.nav.menu)
|
||||
{
|
||||
if(task.nav.menu === '#pageNav')
|
||||
{
|
||||
var $pageNav = $$('#pageNav');
|
||||
var $targetBtn = $pageNav.find(task.nav.target);
|
||||
var $targetBtnGroup = $targetBtn.closest('.btn-group');
|
||||
if($targetBtnGroup.hasClass('open'))
|
||||
{
|
||||
highlight($targetBtn);
|
||||
showToolTip($targetBtn, tagetPageTip);
|
||||
}
|
||||
else
|
||||
{
|
||||
highlight($targetBtnGroup);
|
||||
showToolTip($targetBtnGroup, tagetPageTip);
|
||||
}
|
||||
if(!$targetBtnGroup.data('initTutorial'))
|
||||
{
|
||||
$targetBtnGroup.data('initTutorial', 1).on('click', tryCheckTask);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var $modulemenu = $$('#subNavbar');
|
||||
var $modulemenuItem = $modulemenu.find('[data-id="' + task.nav.menu + '"]');
|
||||
if(!$modulemenuItem.hasClass('active'))
|
||||
{
|
||||
highlight($modulemenuItem);
|
||||
showToolTip($modulemenuItem, tagetPageTip);
|
||||
}
|
||||
else if(task.nav.target)
|
||||
{
|
||||
var $targetItem = $$(task.nav.target);
|
||||
highlight($targetItem);
|
||||
showToolTip($targetItem, tagetPageTip);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$navTarget.toggleClass('finish', !!targetStatus.nav);
|
||||
$formTarget.toggleClass('finish', !!targetStatus.form);
|
||||
$submitTarget.toggleClass('finish', !!targetStatus.submit);
|
||||
$openTaskPage.toggleClass('open', targetStatus.nav);
|
||||
|
||||
targetStatus.submitOK = targetStatus.nav && targetStatus.form;
|
||||
|
||||
return targetStatus;
|
||||
};
|
||||
|
||||
var onIframeLoad = function()
|
||||
{
|
||||
iWindow = window.frames['iframePage'];
|
||||
tryCheckTask();
|
||||
var title = (iWindow.$ ? iWindow.$('head > title').text() : '') + $('head > title').text();
|
||||
var url = createLink('tutorial', 'index', 'referer=' + Base64.encode(iWindow.location.href) + '&task=' + current);
|
||||
try{window.history.replaceState({}, title, url);}catch(e){}
|
||||
};
|
||||
|
||||
var openIframePage = function(url)
|
||||
{
|
||||
url = url || tasks[current].url;
|
||||
try
|
||||
{
|
||||
iWindow.location.replace(url);
|
||||
}
|
||||
catch(e)
|
||||
{
|
||||
iframe.get(0).src = url;
|
||||
}
|
||||
};
|
||||
|
||||
var showTask = function(taskName)
|
||||
{
|
||||
hideModal();
|
||||
|
||||
taskName = taskName || current;
|
||||
current = taskName;
|
||||
|
||||
if(!taskName) return;
|
||||
var task = tasks[taskName];
|
||||
if(!task) return;
|
||||
|
||||
var $li = $tasks.children('li').removeClass('active').filter('[data-name="' + taskName + '"]').addClass('active');
|
||||
$task.toggleClass('finish', task.finish);
|
||||
$('.task-name-current').text(task.title);
|
||||
$('.task-id-current').text(task.id);
|
||||
$('.task-desc').html(task.desc).find('.task-nav').addClass('btn-open-target-page');
|
||||
$('.task-page-name').text(task.nav.targetPageName || lang.target);
|
||||
|
||||
var $prev = $li.prev('li'), $next = $li.next('li');
|
||||
$('.btn-prev-task').toggleClass('hidden', !$prev.length).data('name', $prev.data('name'));
|
||||
$('.btn-next-task').toggleClass('hidden', !$next.length).data('name', $next.data('name'));
|
||||
tryCheckTask();
|
||||
};
|
||||
|
||||
var updateUI = function()
|
||||
{
|
||||
var currentTask;
|
||||
|
||||
finishCount = 0;
|
||||
totalCount = 0;
|
||||
$tasks.children('li').each(function(idx)
|
||||
{
|
||||
var $li = $(this);
|
||||
var name = $li.data('name');
|
||||
var task = tasks[name];
|
||||
var finish = !!setting[name];
|
||||
task.id = idx + 1;
|
||||
task.finish = finish;
|
||||
finishCount += finish ? 1 : 0;
|
||||
totalCount++;
|
||||
|
||||
$li.toggleClass('finish', finish);
|
||||
if(!current && !finish) current = name;
|
||||
});
|
||||
|
||||
$('.task-num-finish').text(finishCount);
|
||||
var isFinishAll = finishCount >= totalCount;
|
||||
if(isFinishAll) current = $tasks.children('li').first().data('name');
|
||||
|
||||
var progress = Math.round(100*finishCount/totalCount);
|
||||
$progress.toggleClass('finish', isFinishAll).find('.progress-bar').css('width', (100*finishCount/totalCount) + '%');
|
||||
$progress.find('.progress-text').text(progress + '%');
|
||||
if(progress == 100) $.getJSON(createLink('tutorial', 'ajaxFinish'));
|
||||
showTask(current);
|
||||
};
|
||||
|
||||
updateUI();
|
||||
if(finishCount >= totalCount) showModal(true);
|
||||
|
||||
$(document).on('click', '.btn-task', function()
|
||||
{
|
||||
showTask($(this).data('name'));
|
||||
}).on('click', '.btn-reset-tasks', function()
|
||||
{
|
||||
hideModal();
|
||||
resetTasks();
|
||||
});
|
||||
|
||||
iframe.onload = iframe.onreadystatechange = function()
|
||||
{
|
||||
if (this.readyState && this.readyState != 'complete') return;
|
||||
onIframeLoad();
|
||||
};
|
||||
|
||||
iWindow.onload = onIframeLoad;
|
||||
|
||||
$modal.on('click', '.close', hideModal);
|
||||
|
||||
$('[data-toggle="tooltip"]').tooltip();
|
||||
|
||||
window.onbeforeunload = function()
|
||||
{
|
||||
$.getJSON(createLink('tutorial', 'quit'));
|
||||
}
|
||||
});
|
||||
var tutorialTasks = $.parseJSON('<?php echo helper::jsonEncode4Parse($tasks, JSON_HEX_QUOT | JSON_HEX_APOS);?>');
|
||||
</script>
|
||||
<?php include '../../common/view/footer.lite.html.php';?>
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
?>
|
||||
<?php include '../../common/view/header.lite.html.php';?>
|
||||
<div id='start' class='bg-primary'>
|
||||
<div class='start-icon'><i class='icon icon-certificate icon-spin icon-back text-primary'></i><i class='icon icon-flag icon-front text-primary'></i></div>
|
||||
<div class='start-icon'><i class='icon icon-certificate icon-spin icon-back'></i><i class='icon icon-flag icon-front text-primary'></i></div>
|
||||
<h1><?php echo $lang->tutorial->common;?></h1>
|
||||
<p><?php echo $lang->tutorial->desc;?></p>
|
||||
<?php echo html::a(inlink('index'), $lang->tutorial->start, '_top', "class='btn btn-primary btn-lg btn-wide btn-info'");;?>
|
||||
|
||||
Reference in New Issue
Block a user