nyx_server
Version:
Node内容发布
996 lines (861 loc) • 30 kB
JavaScript
(function ($, lib, conf) {
'use strict';
var win = window;
var doc = document;
// 为banner统一定义一个事件对象。
var bannerEvent = new topic.Events();
var Banner = function (commentElm) {
this.init(commentElm);
};
Banner.prototype = {
// 初始化的过程,通过注释节点,1.初始化参数 2.获取通栏节点的dom元素集合
// 3.初始化蒙层 4.初始事件
init: function (commentElm) {
this.initParams(commentElm);
this.initLayout();
this.initEvent();
},
initParams: function (commentElm) {
this.initDataParams(commentElm);
this.initElmParams(commentElm);
},
initDataParams: function (commentElm) {
var params = lib.analyze(commentElm.data);
this.uid = params.uid;
this.id = params.data.id;
this.data = params.data;
this.isHide = false;
this.editable = typeof params.data.editable === 'undefined' ? true : params.data.editable;
this.isPreview = false;
},
// 这里将节点分成4类,便于应用到不同的操作上,
// 1. commentElm 对应此通栏的注释开始节点 (主要应对各种在前面插入、更新当前通栏等dom操作)
// 2. commentEndElm 对应此通栏的注释结束节点 (主要应对各种在后面插入等dom操作)
// 3. nodes 此通栏包含的所有节点,包括commentElm和commentEndElm
// 4. domNodes 此通栏包含的所有dom节点。不包含style和script节点,
// 这个不包含的原因是因为该节点计算不到位置,
// 不过现在在计算节点位置的时候,已经考虑了计算不到位置的情况,
// 以后是否包含还是不包含,有待商榷,看具体业务在进行调整。
initElmParams: function (commentElm) {
var result = lib.getIncludeElm(this.uid, commentElm, 'banner');
this.commentElm = commentElm;
this.commentEndElm = result.commentEndElm;
this.domNodes = result.domNodes;
this.nodes = result.nodes;
},
initLayout: function () {
// 通栏的type分为0,1,2,3 其中 1 2 3都是系统定义的非内容节点的通栏,不需要要做蒙层
if (this.data.type !== 0) {
this.visible = false;
return;
}
var disableClass = this.editable ? '' : ' t-banner-layout-disable';
var hiddenClass = this.data.hidden === 0 ? '' : ' t-banner-layout-hidden';
var title = this.data.name ? this.data.name : '';
var hide = this.data.hidden === 0 ? '' : '(隐藏)';
var disable = this.editable ? '' : ' (不可编辑)';
this.layout = $('<div id="t-banner-layout-' +
this.uid + '" data-maskId="' + this.uid + '" class="t-banner-layout' +
disableClass + hiddenClass + '" data-topicSystem="true">' +
'<div class="t-banner-layout-title" data-topicSystem="true">' + title + hide + disable + '</div>' +
'</div>');
this.title = this.layout.find('.t-banner-layout-title');
$(doc.body).append(this.layout);
this.layoutReset();
this.show();
},
layoutReset: function () {
if (typeof this.layout === 'undefined') {
return;
}
// 计算通栏内dom节点面积的时候,会返回两种值,
// 如果有面积,则会返回一个对象,包含top left right bottom
// 如果计算不出面积,则会返回一个字符串invisible,认为该通栏不可见。
var position = lib.calRange(this.domNodes);
if (position === 'invisible') {
this.visible = false;
return;
} else {
this.visible = true;
}
var scrollTop = $(win).scrollTop();
var scrollLeft = $(win).scrollLeft();
this.layout.css({
left: position.left + scrollLeft + 'px',
top: position.top + scrollTop + 'px',
width: position.right - position.left + 'px',
height: position.bottom - position.top + 'px'
});
},
// 更新通栏的属性参数,不过现在的机制用不到,因为每次更新通栏,
// 做的操作就是将当前通栏删除以后,再根据传回的代码重新建立一个通栏
updateCommentData: function (dataString) {
this.commentElm.data = dataString;
this.initDataParams(this.commentElm);
this.layoutUpdate();
},
// 对通栏进行更新,现在主要是根据内容更新title
// 随着业务的发展,估计还会有其他状态进行更新。
layoutUpdate: function () {
this.title.html(this.data.title);
},
// 通过判断当前通栏是否有蒙板,模式是否为通栏模式以及通栏的可见状态来决定是否显示蒙层
show: function () {
// this.isHide = false;
if (!this.isHide && typeof this.layout !== 'undefined' &&
this.modelCheck() && this.visible) {
this.layout.show();
}
},
hide: function () {
// this.isHide = true;
if (typeof this.layout !== 'undefined') {
this.layout.hide();
}
if (typeof this.menu !== 'undefined') {
this.menu.cancel();
}
},
initEvent: function () {
var banner = this;
// 通过按钮上的data-action来调用具体的操作。
if (this.layout) {
this.layout.on('click', function (e) {
if (typeof banner.menu === 'undefined') {
banner.menu = new topic.module.BannerMenu(banner);
}
banner.menu.show(e.pageX, e.pageY);
});
}
},
edit: function () {
if (!this.checkEditAble()) {
return false;
}
var _this = this;
var data = this.data;
var params = topic_global_params.page;
var bannerId = this.id;
var messageData = {
handler: 'editCallback',
scope: 'topic.bannerGroup.banners["' + this.uid + '"]',
sender: 'window.parent',
data: {
id: this.id
}
};
this.dialog = new topic.module.Dialog({
title: '编辑' + this.data.name,
url: conf.bannerEditUrl + '?postMessage__=' + encodeURIComponent(JSON.stringify(messageData)),
width: 800,
height: 600,
beforeClose: function () {
if (_this.isPreview) {
_this.unPreview();
}
topic.ws.unregister('edit', 'banner', bannerId);
return true;
}
});
topic.ws.register('edit', 'banner', bannerId, function (data) {
var users = data.data.users;
var html = [' 当前编辑:'];
for (var i = 0, iLen = users.length; i < iLen; i++) {
html.push(users[i].userName);
}
// @todo 这个操作,应该放到dialog对象中。
var userBox = _this.dialog.header.find('h1 .userBox');
userBox.html(html.join(' '));
});
},
checkEditAble: function () {
if (typeof this.editable !== 'undefined' && this.editable === false) {
alert('您没有此通栏的编辑权限。');
return false;
} else {
return true;
}
},
editCallback: function (data, option) {
data = JSON.parse(decodeURIComponent(data));
//if (data.data.length > 1) {
if(data.data.length > 1 || this.data.position<=0){ //this.data.position<=0表示修改的是三个默认通栏,需要全页刷新,不进行局部通栏刷新。by cc at 2014/8/27
win.location.reload();
} else {
this.dialog.closeIt();
this.refresh();
}
},
del: function (elm) {
if (!this.checkEditAble()) {
return false;
}
// if (this.isLastBanner()) {
// alert('最后一个通栏不能删除。');
// return false;
// }
new topic.module.Hint({
content: '确认要删除当前通栏么?',
target: elm,
scope: this,
type: 'confirm',
callback: function () {
this.delCallback();
}
});
},
delCallback: function () {
var params = topic_global_params.page;
var uid = this.uid;
$.ajax({
url: conf.bannerReOrderUrl,
type: 'post',
dataType: 'json',
context: this,
data: {
pageId: params.id,
pageDigest: params.digest,
bodyList: this.createDelBodyList(),
},
success: function (msg) {
if (msg.code === 1) {
if (typeof this.menu !== 'undefined') {
this.menu.cancel();
}
// 因为后端对position有顺序要求,需要在做一些改变顺序的操作的时候,
// 进行刷新操作。
window.location.reload();
return;
bannerEvent.trigger('del', uid);
} else {
// @todo 统一alert的处理
alert(msg.msg);
}
}
});
},
createDelBodyList: function () {
var comments = lib.getComments('banner:begin');
var data;
var list = [];
for (var i = 0, iLen = comments.length; i < iLen; i++) {
data = lib.analyze(comments[i].data.trim());
if (data.data.type === 0) {
if (data.uid === this.uid) {
continue;
}
list.push(data.data.id);
}
}
return list.join(',');
},
innsertAfter: function (elm) {
$.ajax({
url: conf.clipboardQueryUrl,
dataType: 'json',
type: 'get',
context: this,
success: function (msg) {
if (msg.code === 1) {
if (msg.data.type !== 'banner') {
this.insert('after');
} else {
this.innsertAfterCallback(elm);
}
} else {
this.insert('after');
}
}
});
},
innsertAfterCallback: function (elm) {
new topic.module.Hint({
content: '插入通栏,请选择插入通栏的方式',
target: elm,
scope: this,
type: 'custom',
customHtml: '<div data-topicSystem="true" class="t-hint-tools-confirm">' +
'<em data-action="custom" data-callback="callback1" data-topicSystem="true" ' +
'class="t-hint-tools-affirm_btn">创建一个新通栏</em>' +
'<em data-action="custom" data-callback="callback2" data-topicSystem="true" ' +
'class="t-hint-tools-cancel_btn">使用剪贴板中的通栏</em>' +
'</div>',
callback1: function () {
this.insert('after');
},
callback2: function () {
this.insertFromClipBoard('after');
}
});
},
innsertBefore: function (elm) {
$.ajax({
url: conf.clipboardQueryUrl,
dataType: 'json',
type: 'get',
context: this,
success: function (msg) {
if (msg.code === 1) {
if (msg.data.type !== 'banner') {
this.insert('before');
} else {
this.innsertBeforeCallback(elm);
}
} else {
this.insert('before');
}
}
});
},
innsertBeforeCallback: function (elm) {
new topic.module.Hint({
content: '插入通栏,请选择插入通栏的方式',
target: elm,
scope: this,
type: 'custom',
customHtml: '<div data-topicSystem="true" class="t-hint-tools-confirm">' +
'<em data-action="custom" data-callback="callback1" data-topicSystem="true" ' +
'class="t-hint-tools-affirm_btn">创建一个新通栏</em>' +
'<em data-action="custom" data-callback="callback2" data-topicSystem="true" ' +
'class="t-hint-tools-cancel_btn">使用剪贴板中的通栏</em>' +
'</div>',
callback1: function () {
this.insert('before');
},
callback2: function () {
this.insertFromClipBoard('before');
}
});
},
insert: function (direct) {
var data = this.data;
var params = topic_global_params.page;
var messageData = {
handler: 'insertCallback',
scope: 'topic.bannerGroup.banners["' + this.uid + '"]',
sender: 'window.parent',
data: {
pageDigest: params.digest,
pageId: params.id,
direct: direct,
position: data.position,
bodyList: this.createInsertBodyList(direct, -1)
}
};
this.dialog = new topic.module.Dialog({
title: '新建通栏',
url: conf.bannerCreateUrl + '?postMessage__=' + encodeURIComponent(JSON.stringify(messageData)),
width: 800,
height: 600
});
},
// 在新建通栏的时候,建立一个通栏id队列,将新建通栏的id设置为-1,
// 放在插入的位置上,为后端创建通栏的时候标识出通栏的位置。
createInsertBodyList: function (direct, insertId) {
var comments = lib.getComments('banner:begin');
var data;
var list = [];
for (var i = 0, iLen = comments.length; i < iLen; i++) {
data = lib.analyze(comments[i].data.trim());
if (data.data.type === 0) {
if (data.uid === this.uid && direct === 'before') {
list.push(insertId);
}
list.push(data.data.id);
if (data.uid === this.uid && direct === 'after') {
list.push(insertId);
}
}
}
return list.join(',');
},
// insert的回调函数
insertCallback: function (data, option) {
// 因为后端对position有顺序要求,需要在做一些改变顺序的操作的时候,
// 进行刷新操作。
window.location.reload();
return;
data = JSON.parse(decodeURIComponent(data));
option = JSON.parse(decodeURIComponent(option));
if (data.data.ids.length > 1) {
win.location.reload();
return;
}
var param = {
'id': data.data.ids[0],
renderType: 'edit',
position: option.position,
pageId: topic_global_params.page.id
};
$.ajax({
url: conf.bannerRefreshUrl,
data: param,
dataType: 'jsonp',
context: this,
success: function (msg) {
if (msg.code === 1) {
this.insertHtml(msg.data.content, option.direct);
if (typeof this.menu !== 'undefined') {
this.menu.cancel();
}
this.dialog.closeIt();
bannerEvent.trigger('insert');
} else {
alert(msg.msg);
}
}
});
},
insertHtml: function (content, direct) {
var tempFn = document.write;
doc.write = function () {
console.error(_this.uid, "代码内部有使用document.write", arguments);
// @todo 这里的alert会阻止线程,无法点开log查看调用堆栈,回头改成自己写的提示框
alert('当前页面上脚本有使用document.write,会导致刷新出现问题,' +
'您可以在控制台查看log代码,点击确认,将对页面进行刷新');
window.location.reload();
};
if (direct === 'before') {
$(this.commentElm).before(content);
} else {
$(this.commentEndElm).after(content);
}
doc.write = tempFn;
},
// 现在的上移下移只做了对应的dom操作,未将结果反馈给服务器。
moveUp: function (elm) {
var bannerId = lib.getCommentSiblingBannerId(this.commentElm, 'up', 'banner');
if (bannerId === null) {
new topic.module.Hint({
content: '已经在最上面啦,不能移动',
target: elm,
type: 'alert'
});
return;
}
this.moveTo(bannerId, 'before');
},
moveDown: function (elm) {
var bannerId = lib.getCommentSiblingBannerId(this.commentElm, 'down', 'banner');
if (bannerId === null) {
new topic.module.Hint({
content: '已经在最下面啦,不能移动',
target: elm,
type: 'alert'
});
return;
}
this.moveTo(bannerId, 'after');
},
moveTo: function (bannerId, direct) {
var targetBanner = topic.bannerGroup.banners[bannerId];
if (topic.state.get('isSortBanner') === false) {
topic.state.set('isSortBanner', true);
}
if (direct === 'before') {
$(targetBanner.commentElm).before(this.nodes);
} else {
$(targetBanner.commentEndElm).after(this.nodes);
}
if (topic.state.get('bodyList') === lib.creatBodyList()) {
topic.state.set('isSortBanner', false);
}
if (typeof this.menu !== 'undefined') {
this.menu.cancel();
}
bannerEvent.trigger('move');
},
// 更新通栏,通常应用在通栏内碎片操作后,通栏编辑后,
// 都需要再次从服务端将通栏的内容请求下来,进行更新操作
refresh: function () {
topic.mask.changeMsg('通栏刷新中...');
topic.mask.show();
var data = this.data;
var param = {
id: this.id,
position: data.position,
renderType: 'edit',
pageId: topic_global_params.page.id
};
$.ajax({
url: conf.bannerRefreshUrl,
data: param,
dataType: 'jsonp',
context: this,
success: function (msg) {
if (msg.code === 1) {
this.refreshCallback(msg.data.content);
if (typeof this.menu !== 'undefined') {
this.menu.cancel();
}
} else {
alert(msg.msg);
}
}
});
},
// 更新通栏对应的html代码。
// 现在的操作顺序是
// 1.先建立一个空的span点,
// 2.将此节点插入到当前需要刷新的通栏的commentElm节点前面
// 3.将需要刷新的通栏移除(会同时移除通栏中的所有碎片)
// 4.重新创建所有通栏
// 5.重新创建所有碎片 4、5是有先后顺序的,不能改
// 6.解锁锁定蒙板,隐藏路径栏,隐藏操作菜单,隐藏选择蒙板
// 6 这几步是针对碎片操作后的操作。
refreshCallback: function (html) {
var tempNode = $('<span class="t-node-temp"></span>');
var _this = this;
$(this.commentElm).before(tempNode);
topic.bannerGroup.remove(this.uid);
var tempFn = document.write;
doc.write = function () {
console.error(_this.uid, "代码内部有使用document.write", arguments);
// @todo 这里的alert会阻止线程,无法点开log查看调用堆栈,回头改成自己写的提示框
alert('当前页面上脚本有使用document.write,会导致刷新出现问题,' +
'您可以在控制台查看log代码,点击确认,页面将刷新');
window.location.reload();
};
try {
tempNode.before(html);
} catch (e) {
console.error(e);
}
tempNode.remove();
doc.write = tempFn;
bannerEvent.trigger('refresh');
topic.mask.hide();
},
destory: function () {
this.removeLayout();
this.removeNodes();
},
removeLayout: function () {
if (this.layout) {
this.layout.remove();
}
},
removeNodes: function () {
$(this.nodes).remove();
},
// @todo 要根据修改过后的情况进行返回值判断
modelCheck: function () {
if (topic.state.get('pageModel') === 'bannerEdit') {
return true;
}
return false;
},
focus: function () {
var layout = this.layout;
var top;
if (typeof layout === 'undefined') {
return;
}
if (this.isHide) {
top = $(this.domNodes[0]).offset().top;
} else {
top = layout.offset().top;
}
var windowHeight = $(win).height();
// 对相应的蒙板进行定位。
$(win).scrollTop(top - windowHeight / 2);
// if (top < scrollTop || top > scrollTop + windowHeight) {
// $(win).scrollTop(top - 50);
// }
// 如果想要点击动画多次触发,需要先将动画样式去掉,然后再延迟触发一次。
layout.removeClass('t-mask-layout-click');
setTimeout(function () {
layout.addClass('t-mask-layout-click');
}, 100);
},
active: function () {
if (typeof this.layout === 'undefined') {
return;
}
this.layout.addClass('t-mask-layout-active');
},
unActive: function () {
if (typeof this.layout === 'undefined') {
return;
}
this.layout.removeClass('t-mask-layout-click');
this.layout.removeClass('t-mask-layout-active');
},
copy: function (elm) {
var id = this.id;
// type = 'fragment' + type.slice(0, 1).toUpperCase() + type.slice(1);
$.ajax({
url: conf.clipboardCopyUrl,
dataType: 'json',
type: 'post',
data: {
id: id,
type: 'banner'
},
context: this,
success: function (msg) {
if (msg.code === 1) {
new topic.module.Hint({
content: '复制成功',
target: elm,
scope: this
});
this.saveClipBoard();
} else {
console.error(msg);
alert(msg.msg);
}
}
});
},
saveClipBoard: function () {
$.ajax({
url: conf.clipboardQueryUrl,
dataType: 'json',
type: 'get',
context: this,
success: function (msg) {
if (msg.code === 1) {
localStorage['clipboard'] = JSON.stringify(msg.data);
}
}
});
},
trans: function (elm) {
this.layout.addClass('active');
new topic.module.Hint({
content: '确认要将当前碎片转换成副本碎片么?',
target: elm,
scope: this,
type: 'confirm',
callback: function () {
this.transCallBack();
this.layout.removeClass('active');
},
cancelCallback: function () {
this.layout.removeClass('active');
}
});
},
transCallBack: function () {
var params = {
bannerId: this.id,
bannerVersion: this.data.version,
pageId: topic_global_params.page.id,
position: this.data.position
};
$.ajax({
url: conf.bannerTransUrl,
dataType: 'json',
type: 'post',
data: params,
context: this,
success: function (msg) {
if (msg.code === 1) {
this.replaceIt(replaceId, 'replace');
} else {
console.error(msg);
alert(msg.msg);
}
}
});
},
replace: function () {
// var clipboard = topic.state.get('clipboard');
// if (typeof clipboard === 'undefined') {
// return;
// }
// if (clipboard.type !== 'banner') {
// alert('不能用碎片替换通栏');
// } else {
// this.replaceIt(clipboard.content.id, 'replace');
// }
$.ajax({
url: conf.clipboardQueryUrl,
dataType: 'json',
type: 'get',
context: this,
success: function (msg) {
if (msg.code === 1) {
if (msg.data.type !== 'banner') {
alert('不能用碎片替换通栏');
} else {
this.replaceIt(msg.data.content.id, 'replace');
}
} else {
console.error(msg);
alert(msg.msg);
}
}
});
},
insertFromClipBoard: function (direct) {
$.ajax({
url: conf.clipboardQueryUrl,
dataType: 'json',
type: 'get',
context: this,
success: function (msg) {
if (msg.code === 1) {
if (msg.data.type !== 'banner') {
alert('不能将碎片插入');
} else {
this.replaceIt(msg.data.content.id, direct);
}
} else {
console.error(msg);
alert(msg.msg);
}
}
});
var clipboard = topic.state.get('clipboard');
if (typeof clipboard === 'undefined') {
return;
}
if (clipboard.type !== 'banner') {
alert('不能用碎片替换通栏');
} else {
this.replaceIt(clipboard.content.id, direct);
}
},
/*
replaceIt: function (replaceId, type) {
var bodyList;
if (type === 'replace') {
bodyList = this.createPlaceBodyList(replaceId);
} else {
bodyList = this.createInsertBodyList(type, replaceId);
}
var params = topic_global_params.page;
$.ajax({
url: conf.bannerReOrderUrl,
type: 'post',
dataType: 'json',
context: this,
data: {
bodyList: bodyList,
pageId: params.id,
// pageVersion: params.version,
pageDigest: params.digest
},
success: function (msg) {
if (msg.code === 1) {
if (typeof this.menu !== 'undefined') {
this.menu.cancel();
}
topic.state.set('bodyList', bodyList);
topic.state.set('isSortBanner', false);
if (type === 'replace') {
this.replaceInsert(replaceId, type);
} else {
// 因为后端对position有顺序要求,需要在做一些改变顺序的操作的时候,
// 进行刷新操作。
window.location.reload();
}
} else {
alert(msg.msg);
}
}
});
},
*/
//修改:通栏粘贴直接私有化 by cc
replaceIt:function(replaceId,direct){
var params = topic_global_params.page;
var positon = direct=="after"?this.data.position + 1:this.data.position;
$.ajax({
url: conf.bannerPasteUrl,
type: 'post',
dataType: 'json',
context: this,
data: {
bodyList: params.bodyList,
bannerId:replaceId,
position:positon,
direct:direct,
pageId: params.id
},
success: function (msg) {
if (msg.code === 1) {
// 进行刷新操作。
window.location.reload();
} else {
alert(msg.msg);
}
}
});
},
replaceInsert: function (replaceId, type) {
var param = {
'id': replaceId,
renderType: 'edit',
position: this.data.position,
pageId: topic_global_params.page.id
};
var direct = type === 'replace' ? 'after' : type;
$.ajax({
url: conf.bannerRefreshUrl,
data: param,
dataType: 'jsonp',
context: this,
success: function (msg) {
if (msg.code === 1) {
this.insertHtml(msg.data.content, direct);
if (type === 'replace') {
bannerEvent.trigger('replace', this.uid);
} else {
bannerEvent.trigger('insert');
}
} else {
alert(msg.msg);
}
}
});
},
createPlaceBodyList: function (replaceId) {
var comments = lib.getComments('banner:begin');
var data;
var list = [];
for (var i = 0, iLen = comments.length; i < iLen; i++) {
data = lib.analyze(comments[i].data.trim());
if (data.data.type === 0) {
if (data.uid === this.uid) {
list.push(replaceId);
continue;
}
list.push(data.data.id);
}
}
return list.join(',');
},
preview: function (data) {
this.isPreview = true;
data = JSON.parse(decodeURIComponent(data));
var content = data.msg || data.data.content || '';
this.previewContent = $(content);
var tempFn = document.write;
doc.write = function () {
console.error(this.uid, "代码内部有使用document.write", arguments);
// @todo 这里的alert会阻止线程,无法点开log查看调用堆栈,回头改成自己写的提示框
alert('代码中不能出现document.write');
};
if (content !== '') {
$(this.domNodes).addClass('hideNodes');
$(this.commentElm).after(this.previewContent);
}
doc.write = tempFn;
this.hide();
this.dialog.minimize();
},
unPreview: function () {
this.isPreview = false;
$(this.domNodes).removeClass('hideNodes');
$(this.previewContent).remove();
this.show();
this.menu.show();
}
};
topic.Events.mixTo(Banner);
lib.ns('topic.module').Banner = Banner;
lib.ns('topic').bannerEvent = bannerEvent;
}(topicJquery, topic.utils, topic.conf));