Your IP : 18.219.40.177
/**
* Модуль отвечает за отображение хинтов
* @param {object} window global object
* @param {object|function} $ jQuery
* @param {object} EventMgr Event manager
* @param {object} App Application
*/
/*global App:true*/
App.Hint = function(window, $, EventMgr, App) {
'use strict';
var init = function() {
EventMgr.on($mainWrapper(), hintItemSelector,
'mouseover', hintShowHandler);
EventMgr.on($mainWrapper(), '.i-text-content',
'mouseover', hintInListShowHandler);
EventMgr.on($mainWrapper(), hintActiveItemSelector,
'mouseover', hintActiveShowHandler);
EventMgr.bind('hintActiveShowHandler', hintActiveShowHandler);
EventMgr.on($mainWrapper(), hintMenuItemSelector,
'mouseover', hintShowHandler);
EventMgr.on($mainWrapper(), hintItemSelector,
'mouseout', hintHideHandler);
EventMgr.on($mainWrapper(), '.i-text-content',
'mouseout', hintHideHandler);
EventMgr.on($mainWrapper(), previewItemSelector,
'mouseover', previewShowHandler);
EventMgr.on($mainWrapper(), previewItemSelector,
'mouseout', hintHideHandler);
EventMgr.on($mainWrapper(), hintActiveItemSelector,
'mouseout', hintHideHandler);
EventMgr.on($mainWrapper(), hintMenuItemSelector,
'mouseout', hintHideHandler);
EventMgr.on($mainWrapper(), hintBoxSelector, 'mouseover', hintShow);
EventMgr.on($mainWrapper(), hintBoxSelector, 'mouseout', hintHide);
EventMgr.on($body(), tipCloseSelector, 'click', closeTipByCross);
//EventMgr.on($body(), tipCloseCrossSelector, 'click', closeTipByCross);
EventMgr.bind('showHintMap', showHintMap);
EventMgr.bind('forceShowHint', forceShowHint);
EventMgr.bind('hideHint', hintHide);
EventMgr.bind('stopShowHint', stopShowHint);
EventMgr.bind('tabLoading', hintHide);
EventMgr.bind('closeTabEvent', hintHide);
EventMgr.bind('ajaxResponseHint', updateHint);
EventMgr.on('.force-hint-flag', '.force-hint', 'focus', showForceHint);
EventMgr.on('.force-hint-flag', '.force-hint', 'blur', forcehintHide);
EventMgr.bind('verticalScroll', checkPosition);
EventMgr.bind('showTips', showTips);
EventMgr.bind('loadPage', checkTipsForDesktop);
EventMgr.bind('updateTipPosition', updateTipPosition);
},
$mainWrapper = function() {
return App.u.selectorCache('#main-wrapper');
},
$body = function() {
return App.u.selectorCache('#main-wrapper');
},
hintItemSelector = '.hint',
tipCloseSelector = '.b-tip',
tipCloseCrossSelector = '.b-tip__close',
pageInfo = window.pageInfo,
previewItemSelector = '#modal1-img li',
hintActiveItemSelector = '.acthint',
$hintBoxFn = function() {
return $('#hint');
},
$hintBoxInnerFn = function() {
return $('#hint-inner');
},
hintBoxSelector = '#hint',
//$ elem inner hint
$$hintBoxInner,
$$hintBox,
hintMenuItemSelector = '.overwidth',
timer,
hideTimer,
lastSelf,
/**
* Force show hint when form elem in focus
* @param {object} e
* @this HTML Node
*/
showForceHint = function(e) {
clearTimeout(hideTimer);
var $srcElem = $(this),
hintField = $srcElem.parents('.i-form__item').find('.field-help'),
self = hintField;
if (hintField.length > 0 && hintGetContent(self, false)) {
setTimeout(function() {
setHintPosition(self, true);
hintShow(undefined, true);
}, 1);
}
lastSelf = $srcElem;
},
forcehintHide = function() {
$$hintBox = $$hintBox || $hintBoxFn();
$$hintBox.css('visibility', '').removeClass('active');
},
checkPosition = function() {
if ($$hintBox.hasClass('active')) {
if (lastSelf && lastSelf.hasClass('force-hint')) {
var hintField = lastSelf.parents('.l-form__row').find('.field-help');
if (hintField.offset().top < 142) {
forcehintHide();
} else {
setHintPosition(hintField, true);
}
}
}
},
//prevent show hint
stopShowHint = function() {
clearTimeout(timer);
},
/**
* Hint handler for DCMap
* get props of element and show it as list
* @param {object} e
*/
showHintMap = function(e) {
var data = e.originalEvent.detail.props,
self = $(e.originalEvent.detail.elem),
hint = '<ul>',
msg = data.msg,
key,
$$hintBoxInner = $$hintBoxInner || $hintBoxInnerFn();
for (key in data) {
if (msg[key]) {
hint += '<li>' +
'<label class="b-hint-line__label">' + msg[key] + ':</label>' +
' ' + data[key] + '</li>';
}
}
hint += '</ul>';
$$hintBoxInner.html(hint);
//@todo least 200ms mouseover don't show hint
timer = setTimeout(function() { hintShow(self); }, 500);
lastSelf = null;
},
/**
* Show hint like preview for development mode
* @param {object} e
* @this {object} HTML Node
*/
previewShowHandler = function(e) {
var self = $(this),
imgName = this.getAttribute('data-val'),
text, style, src;
$$hintBoxInner = $$hintBoxInner || $hintBoxInnerFn();
if (!imgName) {
return;
}
src = 'src="/manimg/common/img/' + imgName + '.png"';
style = 'style="min-height: 16px; min-width: 16px;"';
text = '<img class="preview-icon" ' + style + ' ' + src + ' ></img>';
$$hintBoxInner.html(text);
//check for shadow
setHintPosition(self, false);
//@todo least 200ms mouseover don't show hint
timer = setTimeout(function() { hintShow(); }, 500);
},
/**
* show hint for element with custom hint
* @param {object} e
* @param {object} data
*/
forceShowHint = function(e, data) {
var elem = data.elem,
hint = data.hint,
self = $(elem);
$$hintBoxInner = $$hintBoxInner || $hintBoxInnerFn();
$$hintBoxInner.html(hint);
setHintPosition(self, false);
hintShow();
lastSelf = null;
},
/**
* Get hint content for view
* find out hint content in elem attribute
* @param {object} self jQuery object of element
* @param {boolean} active Flag for active hint
* @return {boolean}
*/
hintGetContent = function(self, active) {
var state, text, shadow, row, mn,
overwidth = false;
$$hintBoxInner = $$hintBoxInner || $hintBoxInnerFn();
//get hint content
state = self[0].getAttribute('data-state');
if (state) {
text = self[0].getAttribute('data-hint-' + state);
if (!text) {
text = self[0].getAttribute('data-hint');
}
} else {
text = self[0].getAttribute('data-hint');
}
mn = self[0].getAttribute('data-hint-mn');
if (active) {
text = pageInfo.loading;
}
if (!text) {
if (self.hasClass('overwidth')) {
text = self[0].innerText || self[0].firstChild.nodeValue || self.html();
overwidth = true;
} else {
return false;
}
}
//filtred text
text = window.filterXSS(text);
shadow = self.hasClass('shadow');
if (shadow) {
row = self.parents('tr.row-shadow');
if (!row.length) {
text = text.replace(/<span class=['"]hint-.*/g , '');
}
}
$$hintBoxInner.html(text);
if (mn) {
if (!String(mn).match('hint')) {
mn = 'hint_' + mn;
}
$$hintBoxInner.attr('data-mn', mn);
} else {
$$hintBoxInner.attr('data-mn', null);
}
lastSelf = null;
return true;
},
/**
* Show hint handler
* call function for show hint
* @param {object} e
* @param {boolean} active Flag for active hint
* @this HTML Node
*/
hintShowHandler = function(e, active) {
var self = $(this);
if (hintGetContent(self, active)) {
setHintPosition(self, false);
//@todo least 200ms mouseover don't show hint
timer = setTimeout(function() { hintShow(); }, 500);
}
lastSelf = null;
//if hint on parent
if (e.stopPropagation) {
e.stopPropagation();
}
},
hintInListShowHandler = function(e) {
if (this.className.match(/overwidth/)) {
hintShowHandler.apply(this, [e]);
} else {
var width = this.offsetWidth,
scrollWidth = this.scrollWidth - 1;
if (width < scrollWidth) {
this.className += ' overwidth';
hintShowHandler.apply(this, [e]);
}
}
},
/**
* Set position for hint
* detect best position for view hint
* @param {object} self jQuery object of element
* @param {boolean} fixed flag for fixed position of hint (for form items)
*/
setHintPosition = function(self, fixed, box, boxInner, forceRight, forceBottom) {
var PADDING = 15,
heightTail = 10,
marginElem = 3,
N3 = 7,
N4 = 30,
$hintBoxInner,
$hintBox;
if (box && boxInner) {
$hintBoxInner = boxInner;
$hintBox = box;
} else {
if (!$$hintBox || !$$hintBoxInner) {
$$hintBoxInner = $hintBoxInnerFn();
$$hintBox = $hintBoxFn();
}
$hintBoxInner = $$hintBoxInner;
$hintBox = $$hintBox;
}
//calculate hint position
var heightHintBox = $hintBoxInner[0].offsetHeight,
widthElem = self.width(),
heightElem,
selfOffset = self.offset(),
//top position of element
topElem = selfOffset.top,
//left position of element
leftElem = selfOffset.left,
docWidth = $('body').width(),
left, top,
topFlag = false,
rightFlag = false,
LEFT_BORDER;
//check for svg elem
if (widthElem === 0 && self && self[0]) {
widthElem = self[0].getBoundingClientRect().width;
}
$hintBoxInner
.removeClass('b-hint__inner_right_fixed' +
' b-hint__inner_right' +
' b-hint__inner_top' +
' b-hint__inner_top_right' +
' b-hint__inner_left');
//top of element hinting
if (!fixed) {
top = topElem - heightHintBox - heightTail - marginElem - PADDING;
left = leftElem + (widthElem / 2) - N3;
LEFT_BORDER = 300;
} else {
top = topElem - PADDING;
left = leftElem + widthElem + marginElem + heightTail;
LEFT_BORDER = 250;
}
//check for left border
if ((docWidth - left) < LEFT_BORDER || forceRight) {
$hintBoxInner.addClass('b-hint__inner_right');
var right = docWidth - leftElem - N4;
rightFlag = true;
$hintBox.css('right', right + 'px');
$hintBox.css('left', '');
if (fixed) {
top = topElem - heightHintBox - heightTail - marginElem - PADDING;
}
} else {
if (fixed) {
$hintBoxInner.addClass('b-hint__inner_right_fixed');
}
$hintBoxInner.addClass('b-hint__inner_left');
$hintBox.css('left', left + 'px');
$hintBox.css('right', '');
}
//check for top border
if (heightHintBox > top || forceBottom) {
heightElem = self.outerHeight();
//check for svg elem
if (heightElem === 0 && self && self[0]) {
heightElem = self[0].getBoundingClientRect().height;
}
top = self.offset().top + heightElem + heightTail - PADDING;
if (rightFlag) {
$hintBoxInner.addClass('b-hint__inner_top_right');
} else {
$hintBoxInner.addClass('b-hint__inner_top');
}
}
$hintBox.css('top', top + 'px');
},
currentHintId,
/**
* Active hint handler
* get request for content hint
* @param {object} e
* @this {object}
*/
hintActiveShowHandler = function(e) {
var _this = this;
if (e.originalEvent.detail.elem) {
_this = e.originalEvent.detail.elem;
}
var self = $(_this),
tabId = $('.tab-content_st_active').attr('data-tabid'),
elid = self.parents('tr').attr('data-elid') ||
_this.getAttribute('data-elid'),
pName = _this.getAttribute('data-name'),
value = _this.getAttribute('data-value'),
hintfunc = _this.getAttribute('data-hintfunc');
//for acthint in col
if (!pName) {
var index = self.closest('td').index(),
th = self.closest('table').find('th')[index],
pName = th.getAttribute('data-colname');
}
if (hintfunc) {
currentHintId = tabId + value + elid + pName;
var params = {
func: hintfunc,
elid: elid,
type: pName
};
EventMgr.trigger('ajaxRequest', {
url: pageInfo.url,
param: params,
invar: {
hintTabId: tabId,
hintElid: elid,
hintPName: pName,
hintValue: value,
self: self },
type: 'get',
outtype: 'json',
trfunc: 'ajaxResponseHint',
queue: 'actHint' + tabId,
failfunc: 'failCommonAjaxResponse' });
} else {
currentHintId = tabId + value + elid + pName;
EventMgr.trigger('getActiveHint', {
tabId: tabId,
elid: elid,
pName: pName,
value: value,
self: self });
}
hintShowHandler.apply(_this, [{}, true]);
e.preventDefault();
e.stopPropagation();
},
/**
* Update hint content when got response of active hint
* @param {object} e
* @param {object} data
*/
updateHint = function(e, data) {
var elid = data.hintElid,
tabId = data.hintTabId,
pName = data.hintPName,
value = data.hintValue,
self = data.self,
id = tabId + value + elid + pName,
textValue;
if (currentHintId === id) {
if (!data.hint || data.hint === '') {
textValue = 'Oops..';
} else {
textValue = window.htmlDecode(data.hint);
}
textValue = window.filterXSS(textValue);
$$hintBoxInner.html(textValue);
setHintPosition(self, false);
}
},
/**
* Show HTML Node of hint
* @param {object} self jQuery object of element
* @param {boolean} force Force show hint flag
*/
hintShow = function(self, force) {
$$hintBoxInner = $$hintBoxInner || $hintBoxInnerFn();
$$hintBox = $$hintBox || $hintBoxFn();
//check for hint show by self
if (self !== undefined && typeof self.width === 'function') {
setHintPosition(self, false);
}
$$hintBox.addClass('active');
if (force) {
$$hintBox.css('visibility', 'visible');
} else {
$$hintBox.css('visibility', '');
}
clearTimeout(timer);
},
hintHideHandler = function(e) {
hintHide();
clearTimeout(timer);
},
/**
* Hide HTML Node of hint
*/
hintHide = function() {
$$hintBox = $$hintBox || $hintBoxFn();
$$hintBox.removeClass('active');
$$hintBox.find('.hint-cont').html();
currentHintId = '';
clearTimeout(timer);
},
renderTip = function(tipObject, inTab) {
var html = templates.tip(tipObject);
if (inTab) {
$('.tab-content_st_active').append(html);
} else {
$body().append(html);
}
return $('.b-tip_name_' + tipObject.name);
},
actTip,
/**
* show Tips
* @param {object} e
* @param {object} data
*
* find target element by classname i-tip-target_st_NAME
* */
showTips = function(e, data) {
actTip = data;
var tips = data.tips,
inTab = data.inTab,
tabId = data.tabId,
l = tips.length,
sameModule = data.sameModule,
$target, $tip,
TABMARGINTOP = 69,
TABMARGINLEFT = 205,
forceRight = false,
forceBottom = false;
//show only one tip
if ($('.b-tip').length) {
return;
}
while (l--) {
//check for exist this tip
if ($('.b-tip_name_' + tips[l].name).length) {
continue;
}
//check for sameModule load form menu
if (tips[l].name === 'title_reload' && !sameModule) {
continue;
}
if (tips[l].name === 'mbar_pin') {
inTab = false;
}
if (tips[l].name === 'tabs_close') {
if ($('.tab-group').length < 9) {
continue;
}
inTab = false;
}
//show inside tab
if (inTab) {
$target = $('#cont-' + tabId + ' .i-tip-target_st_' + tips[l].name);
} else {
$target = $('.i-tip-target_st_' + tips[l].name);
}
//show textarea only when it focused
if (tips[l].name === 'textarea_resize' && !data.textareaTip) {
$('.b-textarea').bind('focus', showTipsForTextarea);
textareaTip = [tips[l]];
continue;
} else if (data.textareaTip) {
var $textarea = $('.b-textarea');
if ($target.length) {
var $targetTextarea = $target.prev();
if ($targetTextarea.length) {
var height = $targetTextarea[0].offsetHeight,
scrollHeight = $targetTextarea[0].scrollHeight - 1;
if (height < scrollHeight) {
$textarea.off('focus', showTipsForTextarea);
forceBottom = true;
} else {
continue;
}
}
}
}
//force bottom position for new_btn tip
if (tips[l].name === 'btn_new') {
forceBottom = true;
}
if ($target.length) {
//check for visibility
if ($target[0].offsetWidth === 0 || $target[0].offsetHeight === 0) {
continue;
}
$tip = renderTip(tips[l], inTab);
setHintPosition($target, false, $tip, $tip.find('.b-tip__inner'), forceRight, forceBottom);
//correct position inside tab
if (inTab) {
$tip.css('top', parseFloat($tip.css('top')) - TABMARGINTOP);
var left;
if ($tip.length) {
left = $tip[0].style.left;
}
if (left) {
$tip.css('left', parseFloat(left) - TABMARGINLEFT);
}
}
$target.on('click', $.proxy(closeTipByCross, {
elem: $tip.find('.b-tip__close') }));
}
}
},
textareaTip = [],
showTipsForTextarea = function(e) {
var tabId = this.getAttribute('data-tabid'),
tips = textareaTip;
EventMgr.trigger('showTips', {
tips: tips,
inTab: true,
textareaTip: true,
tabId: tabId });
},
closeTipByCross = function(e) {
var self = this,
$self = $(this);
if (this.elem && this.elem[0]) {
this.elem.trigger('click');
return;
}
var id = self.getAttribute('data-name');
if (!id) {
id = $self.find('.b-tip__close').attr('data-name');
} else {
$self = $self.closest('.b-tip');
}
var param = {
func: 'tip',
elid: id
};
EventMgr.trigger('ajaxRequest', {
param: param,
type: 'get',
outtype: 'json',
trfunc: 'DoNothing',
queue: 'noqueue' });
//$('.i-tip-target_st_' + id).off('click');
actTip = null;
$self.remove();
},
closeTip = function(e) {
$(this).remove();
actTip = null;
},
checkTipsForDesktop = function(e, data) {
if (pageInfo && pageInfo.tips) {
//timeout for make all objects in theme
setTimeout(function() {
showTips.apply(window, [{}, { tips: pageInfo.tips }]);
}, 1500);
}
},
/**
* update position for Tip
* @param {object} e
* @param {object} data
*/
updateTipPosition = function(e, data) {
if (actTip) {
$('.b-tip').remove();
showTips.apply(window, [{}, actTip]);
}
};
return {
init: init
};
}(window, $, EventMgr, App);