UNPKG

nyx_server

Version:

Node内容发布

996 lines (861 loc) 30 kB
(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));