百度编辑器(ueditor)魔改:3、高亮提示、搜索(广告词、违禁词等)

1、增加自定义按钮

2、彻底接管文件上传

3、高亮提示

4、滚动条管理

5、自定义排版

-----------------------------------------------------------

最近广告法实施力度好大,很多词都要下线了,但是新发的时候总得给用户一个提示,所以我们来做一个高亮显示的功能吧。

之前我们追加的按钮adwordfilter就是做这个用的

第一步:定义提醒词条

UE.commands['adwordfilter'] = {
    execCommand: function (cmd, opt) {
        var fw = ['最', '最佳', '最具', '最爱', '最赚', '最优', '最优秀', '最好', '最大', '最大程度', '最高'];
        fw.push('最高档', '最高级', '最奢侈', '最低', '最低级', '最低价', '最底', '最便宜', '时尚最低价', '最流行');
        fw.push('最受欢迎', '最时尚', '最聚拢', '最符合', '最舒适', '最先', '最先进', '最先进科学', '最先进加工工艺');
        fw.push('最先享受', '最后', '最后一波', '最新', '最新科技', '最新科学', '与“一”有关', '第一', '中国第一');
        fw.push('全网第一', '销量第一', '排名第一', '唯一', '第一品牌', 'NO.1', 'TOP.1', '独一无二', '全国第一', '一流');
        fw.push('一天', '仅此', '最后一波', '大品牌之一', '国家级', '全球级', '宇宙级', '世界级', '顶级', '顶尖', '尖端');
        fw.push('顶级工艺', '顶级享受', '极品', '极佳', '绝佳', '绝对', '终极', '极致', '首个', '首选', '独家', '独家配方');
        fw.push('全国首发', '首款', '全国销量冠军', '国家级产品', '国家', '国家免检', '填补国内空白', '王牌', '领袖品牌');
        fw.push('世界领先', '领导者', '缔造者', '创领品牌', '领先上市', '至尊', '巅峰', '领袖', '之王', '王者', '冠军');
        fw.push('史无前例', '前无古人', '永久', '万能', '祖传', '特效', '无敌', '纯天然', '100%', '恭喜获奖', '全民免单');
        fw.push('倒计时', '趁现在', '仅限', '周末', '周年庆', '特惠趴', '购物大趴', '闪购', '品牌团', '精品团', '单品团');
        fw.push('随时涨价', '马上降价', '机关推荐', '机关专供', '特供', '质量免检', '免抽检', '老字号', '中国驰名商标');
        fw.push('特供', '专供', '化解小人', '增加事业运', '招财进宝', '健康富贵', '提升运气', '有助事业', '护身');
        fw.push('平衡正负能量', '消除精神压力', '调和气压', '逢凶化吉', '时来运转', '万事亨通', '旺人', '旺财', '助吉避凶');
        fw.push('转富招福', '特效', '高效', '全效', '强效', '速效', '天见效', '周期见效', '超强', '激活', '全方位');
        fw.sort();
        fw.sort(function (x, y) {
            if (x.indexOf(y) > -1) {
                return -1;
            } else {
                return 1;
            }
        });
        var filter = new RegExp('(' + fw.join('|').replace(/\./gi, '\\.') + ')', 'gi');
        var me = this;
    }
}

这个词条可以自己任意定义,用数组方式是为了方便维护,然后将词条转成正则,用正则的方式匹配正文,然后加样式进行处理

在定义词条的数组,我们还进行了两次排序,是为了避免出现短词比长词提醒优先的问题,例如“最大”,应该是两个字同时高亮,而不是只有一个最字高亮,所以进行排序

第二步:加上高亮

打开themes\default\iframe.css,这个文件是编辑器内部的样式,如果在编辑器内要显示不同样式,在这里定义即可

.highlight {background:yellow;color:red;}

定义好高亮样式后,在编辑器内的内容,就可以直接追加这个样式了

打开src\adapter\editor.js,找到editor.addListener("afterpaste", function () {这一行,我们在这个事件里追加一个动作

editor.execCommand('adwordfilter','highlight');

目的是在用户将内容粘贴到编辑器时,高亮所有的提醒词

那么,我们的adwordfilter就需要调整一下了

UE.commands['adwordfilter'] = {
    execCommand: function (cmd, opt) {
        var fw = ['最', '最佳', '最具', '最爱', '最赚', '最优', '最优秀', '最好', '最大', '最大程度', '最高'];
        fw.push('最高档', '最高级', '最奢侈', '最低', '最低级', '最低价', '最底', '最便宜', '时尚最低价', '最流行');
        fw.push('最受欢迎', '最时尚', '最聚拢', '最符合', '最舒适', '最先', '最先进', '最先进科学', '最先进加工工艺');
        fw.push('最先享受', '最后', '最后一波', '最新', '最新科技', '最新科学', '与“一”有关', '第一', '中国第一');
        fw.push('全网第一', '销量第一', '排名第一', '唯一', '第一品牌', 'NO.1', 'TOP.1', '独一无二', '全国第一', '一流');
        fw.push('一天', '仅此', '最后一波', '大品牌之一', '国家级', '全球级', '宇宙级', '世界级', '顶级', '顶尖', '尖端');
        fw.push('顶级工艺', '顶级享受', '极品', '极佳', '绝佳', '绝对', '终极', '极致', '首个', '首选', '独家', '独家配方');
        fw.push('全国首发', '首款', '全国销量冠军', '国家级产品', '国家', '国家免检', '填补国内空白', '王牌', '领袖品牌');
        fw.push('世界领先', '领导者', '缔造者', '创领品牌', '领先上市', '至尊', '巅峰', '领袖', '之王', '王者', '冠军');
        fw.push('史无前例', '前无古人', '永久', '万能', '祖传', '特效', '无敌', '纯天然', '100%', '恭喜获奖', '全民免单');
        fw.push('倒计时', '趁现在', '仅限', '周末', '周年庆', '特惠趴', '购物大趴', '闪购', '品牌团', '精品团', '单品团');
        fw.push('随时涨价', '马上降价', '机关推荐', '机关专供', '特供', '质量免检', '免抽检', '老字号', '中国驰名商标');
        fw.push('特供', '专供', '化解小人', '增加事业运', '招财进宝', '健康富贵', '提升运气', '有助事业', '护身');
        fw.push('平衡正负能量', '消除精神压力', '调和气压', '逢凶化吉', '时来运转', '万事亨通', '旺人', '旺财', '助吉避凶');
        fw.push('转富招福', '特效', '高效', '全效', '强效', '速效', '天见效', '周期见效', '超强', '激活', '全方位');
        fw.sort();
        fw.sort(function (x, y) {
            if (x.indexOf(y) > -1) {
                return -1;
            } else {
                return 1;
            }
        });
        var filter = new RegExp('(' + fw.join('|').replace(/\./gi, '\\.') + ')', 'gi');
        var me = this;
        function HighLight() {
            var html = me.getContent();
            html = html.replace(/<span class="highlight">(.*?)<\/span>/gi, '$1');
            html = html.replace(filter, '<span class="highlight">$1</span>');
            // setContent会触发contentchange事件,所以不使用
            // me.setContent(html);
            // 更新内容到编辑器
            var root = UE.htmlparser(html);
            me.filterInputRule(root);
            html = root.toHtml();
            me.body.innerHTML = html;
        }
        if (opt) {
            switch (opt.toLowerCase().trim()) {
                case 'highlight':
                    HighLight();
                    break;
            }
        }
    }
}

在我们的定义里,追加一个Highlight方法,对编辑器内容进行调整

第三步:显示提醒词的数量

在我们高亮的同时,我们应该达到这样的效果,在按钮中显示有多少个提醒词,点击按钮时,查找并选中提醒词

那么,我们再来改造一下这个定义

UE.commands['adwordfilter'] = {
    execCommand: function (cmd, opt) {
        var fw = ['最', '最佳', '最具', '最爱', '最赚', '最优', '最优秀', '最好', '最大', '最大程度', '最高'];
        fw.push('最高档', '最高级', '最奢侈', '最低', '最低级', '最低价', '最底', '最便宜', '时尚最低价', '最流行');
        fw.push('最受欢迎', '最时尚', '最聚拢', '最符合', '最舒适', '最先', '最先进', '最先进科学', '最先进加工工艺');
        fw.push('最先享受', '最后', '最后一波', '最新', '最新科技', '最新科学', '与“一”有关', '第一', '中国第一');
        fw.push('全网第一', '销量第一', '排名第一', '唯一', '第一品牌', 'NO.1', 'TOP.1', '独一无二', '全国第一', '一流');
        fw.push('一天', '仅此', '最后一波', '大品牌之一', '国家级', '全球级', '宇宙级', '世界级', '顶级', '顶尖', '尖端');
        fw.push('顶级工艺', '顶级享受', '极品', '极佳', '绝佳', '绝对', '终极', '极致', '首个', '首选', '独家', '独家配方');
        fw.push('全国首发', '首款', '全国销量冠军', '国家级产品', '国家', '国家免检', '填补国内空白', '王牌', '领袖品牌');
        fw.push('世界领先', '领导者', '缔造者', '创领品牌', '领先上市', '至尊', '巅峰', '领袖', '之王', '王者', '冠军');
        fw.push('史无前例', '前无古人', '永久', '万能', '祖传', '特效', '无敌', '纯天然', '100%', '恭喜获奖', '全民免单');
        fw.push('倒计时', '趁现在', '仅限', '周末', '周年庆', '特惠趴', '购物大趴', '闪购', '品牌团', '精品团', '单品团');
        fw.push('随时涨价', '马上降价', '机关推荐', '机关专供', '特供', '质量免检', '免抽检', '老字号', '中国驰名商标');
        fw.push('特供', '专供', '化解小人', '增加事业运', '招财进宝', '健康富贵', '提升运气', '有助事业', '护身');
        fw.push('平衡正负能量', '消除精神压力', '调和气压', '逢凶化吉', '时来运转', '万事亨通', '旺人', '旺财', '助吉避凶');
        fw.push('转富招福', '特效', '高效', '全效', '强效', '速效', '天见效', '周期见效', '超强', '激活', '全方位');
        fw.sort();
        fw.sort(function (x, y) {
            if (x.indexOf(y) > -1) {
                return -1;
            } else {
                return 1;
            }
        });
        var filter = new RegExp('(' + fw.join('|').replace(/\./gi, '\\.') + ')', 'gi');
        var me = this;
        function searchNext() {
            HighLight();
            var el = $('.edui-toolbar .edui-for-adwordfilter .edui-button-wrap .edui-button-body .edui-icon');
            var els = $(me.body).find('.highlight');
            var sn = parseInt(el.html());
            sn = isNaN(sn) ? 0 : sn;
            if (sn >= els.length) { sn = 0; }
            if (els.length > 0) {
                els[sn].click();
                var rng = me.selection.getRange();
                rng.setStart(els[sn], 0).setEnd(els[sn], 1);
                rng.select();
                sn++;
                if (sn >= els.length) { sn = 0; }
            }
            el.html(sn);
            me.focus();
        }
        function Prompt() {
            $('#adwordfilter').remove();
            var html = me.getContent();
            var match = html.match(filter);
            var cnt = match ? match.length : 0;
            $('<style id="adwordfilter">.edui-toolbar .edui-for-adwordfilter .edui-button-wrap .edui-button-body .edui-icon:before {content:"广告法违规词提醒:' + cnt + '个词";}</style>').appendTo($(document.documentElement));
        }
        function HighLight() {
            var html = me.getContent();
            html = html.replace(/<span class="highlight">(.*?)<\/span>/gi, '$1');
            html = html.replace(filter, '<span class="highlight">$1</span>');
            // setContent会触发contentchange事件,所以不使用
            // me.setContent(html);
            // 更新内容到编辑器
            var root = UE.htmlparser(html);
            me.filterInputRule(root);
            html = root.toHtml();
            me.body.innerHTML = html;
        }
        if (opt) {
            switch (opt.toLowerCase().trim()) {
                case 'highlight':
                    HighLight();
                    break;
                case 'prompt':
                    Prompt();
            }
        } else {
            searchNext();
        }
    }
}

我们通过修改.edui-toolbar .edui-for-adwordfilter .edui-button-wrap .edui-button-body .edui-icon:before这个伪类的定义,来修改提醒词数量

点击按钮则执行searchNext来定位提醒词,这里不得不吐槽百度编辑器,居然不支持正则查找

第四步:动态改变提醒词数量

除了粘贴之外,用户也会在编辑器内直接进行编辑修改内容,这个时候提醒词数量会发生变动,所以我们追加一个方法

            $(document).ready(function () {
                $('textarea[class*=ueditor]').each(function () {
                    var id = $(this).attr('id');
                    UE.getEditor(id, { initialFrameHeight: 500, initialFrameWidth: null });
                    UE.getEditor(id).addListener('contentchange', function () {
                        //console.log(this)
                        this.execCommand('adwordfilter','prompt');
                    })
                });
            });

我们对所有样式包含ueditor的textarea进行定义,调用百度编辑器,并在初始化后追加一个监听,当contentchange,即内容变动时,调用adwordfilter里的prompt方法,这样我们在编辑内容时,提醒词数量也就跟随变动了

第五步:动态高亮

这个。。。。老顾并没有实现成功,不是不能动态高亮,而是文盲做不到在用户自行编辑时,光标保留在当前编辑位置

当Hightlight运行后,光标会自动跑到文档首位,老顾折腾了半天,也没把光标弄到编辑时的位置上,这个需要大家帮忙来实现了,毕竟文盲对range和selection不熟悉

出现的问题:Range.js : The given range isn't in document.

在文盲的searchNext时,rng.select()时会出现这个错误

                var rng = me.selection.getRange();
                rng.setStart(els[sn], 0).setEnd(els[sn], 1);
                rng.select();

虽然在实际使用中没有发现问题,但是有这么个错误一直向外跳,也很不舒服,那么就在这里寻求一下,rng该怎么写才能不出现这个错误了

最后:再说一句,广告法提示的这些词,未必是一定要删除的,比如说实验条件,光和水是唯一的条件,那么这个地方的“唯一”是不需要删除的,而我们是国内唯一能做到这个深度的企业,这个时候,唯一就是属于违反广告法了,需要删除,但只删这个词,语句都不通顺了,所以,老顾只做高亮提醒,具体处理还是交给编辑和用户去操作吧

评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

文盲老顾

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值