nyx_server
Version:
Node内容发布
408 lines (345 loc) • 12.5 kB
JavaScript
(function ($) {
'use strict';
var win = window;
var doc = document;
// 创建命名空间
var namespace = function (value) {
var values = value.split('.');
var current;
var ns = win;
for (var i = 0, iLen = values.length; i < iLen; i++) {
current = values[i];
if (typeof ns[current] === 'undefined') {
ns[current] = {};
}
ns = ns[current];
}
return ns;
};
// 选定dom对象的信息内容生成
var contentInfoCreate = function (elm) {
var tagName = elm.tagName.toLocaleLowerCase();
var id = elm.id;
var className = elm.className;
id = id ? '<span class="t_mask_info_id" data-topicSystem="true">#' + id + '</span>' : '';
className = className ? '<span class="t_mask_info_class" data-topicSystem="true">.' +
className.split(' ').join('.') + '</span>' : '';
return '<span class="t_mask_info_tagName" data-topicSystem="true">' + tagName +
'</span>' + id + className;
};
// 对选定的元素的可碎片化类型进行判断
var getElmMaskFilterType = function (elm) {
// 当选择的dom节点是body的时候,不能当作可切的标签
if (elm.tagName.toLocaleLowerCase() === 'body') {
return 'isBody';
}
// 当选择的dom节点是系统生成的节点的时候,不能当作可切的标签
if (elm.getAttribute('data-topicSystem') === 'true') {
return 'isSystem';
}
// 当选择的节点内部存在碎片的标志的时候
if (elm.outerHTML.indexOf('fragment:begin') >= 0) {
return 'hasFragment';
}
var parentElm = elm;
// 向上遍历父节点,查找是否存在祖先节点已经是碎片的属性。
while (parentElm.tagName.toLocaleLowerCase() !== 'body') {
if (parentElm.getAttribute('data-fragment-id') !== null) {
return 'belongFragment';
}
parentElm = parentElm.parentNode;
}
// 当选择的dom节点上没有lark-source这个属性的时候,不能当作可切的标签
if (!elm.getAttribute('lark-source')) {
return 'notLarkSource';
}
return 'pass';
};
// 根据当前节点,获取此节点完整的dom路径,祖先,子孙,
// 子孙一直按照只取第一个原则进行选取
var getElementTree = function (elm) {
var elms = [{elm: elm, type: getElmMaskFilterType(elm)}];
var parentElm = elm.parentNode;
var childElm = elm.children[0];
// 获取祖先
while (parentElm &&
parentElm.tagName &&
parentElm.tagName.toLocaleLowerCase() !== 'body') {
elms.unshift({elm: parentElm, type: getElmMaskFilterType(parentElm)});
parentElm = parentElm.parentNode;
}
// 获取子孙
while (childElm) {
elms.push({elm: childElm, type: getElmMaskFilterType(childElm)});
childElm = childElm.children[0];
}
return elms;
};
// 对动态碎片传回的参数依照下面的map进行属性名的转换
// 解决服务器端两个不同服务参数名不一致的问题。
var dynamicParamsTransform = function (params) {
var maps = {
designViewUrl: 'designUrl',
editViewUrl: 'editUrl',
hosts: 'host',
id: 'extId',
expiredTime: 'expireTime'
};
var results = {};
for (var key in params) {
if (maps[key]) {
results[maps[key]] = params[key];
} else {
results[key] = params[key];
}
}
return results;
};
// 通过关键字,查找匹配的注释节点。
// @todo belong参数使用时,发现没有啥效果。需要以后再验证一下。
// 参考资料:http://sunyb.diandian.com/post/2012-04-12/40039121283
var getComments = function (keyword, belong) {
belong = belong || doc;
var commentGroup = [];
var comment;
var comments = doc.evaluate('//comment()', belong, null,
XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
for (var i = 0; i < comments.snapshotLength; i++) {
comment = comments.snapshotItem(i);
if (comment.data.indexOf(keyword) > -1) {
commentGroup.push(comment);
}
}
return commentGroup;
};
// 对注释字符串进行分析,主要用途就是分析那些可以作为通栏和碎片标识的注释节点的内容
// var analyze = function (commentString) {
// commentString = commentString.trim();
// var begin = commentString.indexOf('{');
// var end = commentString.indexOf('}');
// var data;
// try {
// data = JSON.parse(decodeURIComponent(commentString.slice(begin + 1, end)));
// } catch (e) {
// data = {};
// console.error('分析注释时出错:' + commentString);
// }
// var prefix = commentString.slice(0, begin).split(':');
// var model = prefix[0];
// var uid = prefix[2];
// // @notice 通栏碎片type会传0,1,2
// var type = prefix[3];
// // 用来表面当前碎片是否是异常的,值为error就是异常的。
// var status = prefix[4];
// // uid:通栏或者碎片在页面上的唯一标识
// // type:对于碎片节点有意义,可以获取到碎片的类型
// // model: 用来说明该分析结果是一个碎片(fragment)还是一个通栏(banner)
// // data:注释中{}包围的部分,可以直接转换为一个json对象
// return {
// uid: uid,
// type: type,
// model: model,
// data: data,
// status: status
// };
// };
var analyze = function (commentString) {
commentString = commentString.trim();
var model = commentString.split(';')[0].split(':')[0];
var params = commentString.split(';').slice(1);
var result = {};
params.forEach(function (item) {
var a = item.split('=');
result[a[0]] = a[1];
});
try {
result.requestInfo = JSON.parse(decodeURIComponent(result.requestInfo));
} catch (e) {
console.error('分析注释时出错:' + commentString);
}
return {
uid: result.id,
id: result.id,
nodeId: result.nodeId,
type: result.type,
model: model,
name: result.name,
editable: result.editable === 'true' ? true : false,
ssi: result.ssi === 'true' ? true : false,
bindTemplateId: result.bindTemplateId === 'true' ? true : false,
data: result.requestInfo,
projectName:result.projectName
};
};
// 获取注释节点开始和结束节点之间的所有节点。
// 返回的结果包括三部分:
// dom集合(dom里面不包括style节点和script节点)
// 注释结束节点
// 所有节点集合
var getIncludeElm = function (id, commentElm, type) {
var endTag = type + ':end;id=' + id;
var next = commentElm.nextSibling;
var nodes = [commentElm];
var insideNodes = [];
var domNodes = [];
var commentEndElm;
// nodeType = 8 是注释节点
while (next) {
nodes.push(next);
insideNodes.push(next);
if (next.nodeType === 8 && next.data.indexOf(endTag) > -1) {
commentEndElm = next;
break;
// 过滤到script节点和style节点,因为这些节点无法获取位置。
} else if (next.nodeType === 1 &&
next.tagName.toLocaleLowerCase() !== 'style' &&
next.tagName.toLocaleLowerCase() !== 'script') {
// 在节点上设置属性。
next.setAttribute('data-' + type + '-id', id);
domNodes.push(next);
}
next = next.nextSibling;
}
insideNodes.pop();
return {
commentEndElm: commentEndElm,
domNodes: domNodes,
nodes: nodes,
insideNodes: insideNodes
};
};
// 获取节点的坐标位置,计算节点覆盖的最大面积坐标,
// 方法是获取每个节点的top left right bottom的坐标,
// 然后获取top left的最小值,right bottom的最大值。
var calRange = function (nodes) {
var left = [];
var right = [];
var top = [];
var bottom = [];
var r;
for (var i = 0, iLen = nodes.length; i < iLen; i++) {
r = nodes[i].getBoundingClientRect();
if (r.right !== 0 || r.bottom !== 0 || r.left !== 0 || r.top !== 0) {
left.push(r.left);
right.push(r.right);
top.push(r.top);
bottom.push(r.bottom);
}
}
// 如果获取位置的数组中没有一个位置信息,则任务该组dom节点都不可见。
if (left.length <= 0) {
return 'invisible';
}
return {
left: Math.min.apply(null, left),
right: Math.max.apply(null, right),
top: Math.min.apply(null, top),
bottom: Math.max.apply(null, bottom)
};
};
// 对参数进行合并扩展
var extend = function () {
var o = {};
var temp;
for (var i = 0, iLen = arguments.length; i < iLen; i++) {
temp = arguments[i];
for (var key in temp) {
o[key] = temp[key];
}
}
return o;
};
// 获取一个注释节点的某个方向相邻的注释节点,
// 主要是用来获取通栏相邻的下一个或者上一个通栏,来实现上移或者下移的需求。
// @todo 现在这种做法只是找到相关的注释节点的上一个或者下一个节点是否符合要求,
// 如果以后type为非0的通栏可以在非头尾出现的话,这样的查找就会存在问题。
// 如果出现这种需求的话,需要进行更为复杂的向上和向下的查找了。
var getCommentSiblingBannerId = function (commentElm, direction, type) {
var result;
var increment = direction === 'up' ? -1 : 1;
var comments = this.getComments(type + ':begin:');
for (var i = 0, iLen = comments.length; i < iLen; i++) {
if (commentElm === comments[i]) {
result = comments[i + increment];
break;
}
}
if (typeof result === 'undefined') {
return null;
}
var params = this.analyze(result.data);
// 现在type只对通栏有效了,碎片没有这个属性。需要用其他方式进行判断
if (params.data.type !== 0) {
return null;
}
return params.uid;
};
var getBannerUidByDom = function (elm) {
elm = elm.nodeType === 1 ? elm : elm.parentNode;
while (elm.tagName.toLocaleLowerCase() !== 'body') {
if (typeof $(elm).attr('data-banner-uid') !== 'undefined') {
return $(elm).attr('data-banner-uid');
}
elm = elm.parentNode;
}
return null;
};
var getBannerPosition = function (uid) {
var comments = getComments('banner:begin');
var data;
var index = 1;
for (var i = 0, iLen = comments.length; i < iLen; i++) {
data = analyze(comments[i].data.trim());
if (data.data.type === 0) {
if (data.uid !== uid) {
index++;
} else {
return index;
}
}
}
return null;
};
var creatBodyList = function () {
var comments = getComments('banner:begin');
var data;
var list = [];
for (var i = 0, iLen = comments.length; i < iLen; i++) {
data = analyze(comments[i].data.trim());
if (data.data.type === 0) {
list.push(data.data.id);
}
}
return list.join(',');
};
var hasBanner = function () {
var comments = getComments('banner:begin');
var data;
var count = 0;
for (var i = 0, iLen = comments.length; i < iLen; i++) {
data = analyze(comments[i].data.trim());
if (data.data.type === 0) {
count ++;
}
}
return count > 0;
};
namespace('topic.utils');
topic.utils = {
ns: namespace,
contentInfoCreate: contentInfoCreate,
getElmMaskFilterType: getElmMaskFilterType,
getElementTree: getElementTree,
dynamicParamsTransform: dynamicParamsTransform,
getComments: getComments,
analyze: analyze,
getIncludeElm: getIncludeElm,
calRange: calRange,
extend: extend,
getCommentSiblingBannerId: getCommentSiblingBannerId,
creatBodyList: creatBodyList,
getBannerUidByDom: getBannerUidByDom,
hasBanner: hasBanner,
getBannerPosition: getBannerPosition
};
}(topicJquery));