点选词高亮算法

  开发项目的过程中要求做一个点击词选定一句话的功能,当时想了好多办法并且复杂化了,现在整理下思路,其实总共就几个部分:

  1、点击词的位置记录,首个词和末尾词的位置

  2、将选定词高亮

  3、有2个词后,再次选词的逻辑

 

  下面就来代码:

<!DOCTYPE html>
<html ng-app='myApp'>
    <head>
        <meta charset='utf-8'>
        <script src='angular.js'></script>
        <script src='jquery-1.11.3.js'></script>
        <style>
            .margin-r-10 {
                margin-right: 10px;
            }
            .word {
                margin-right: 5px;
                cursor: pointer;
            }
            .selected {
                background-color: #63a855;
                color: #fff;
            }
        </style>
    </head>
    <body>
        <div ng-controller='myCtrl'>
            <ul>
                <li ng-repeat="sentence in textContent">
                    <span class='margin-r-10'>{{sentence.role}}</span>
                    <span class="word cursor-pointer" ng-repeat="word in sentence.textContent" title="{{$parent.$index+'_'+$index}}"
                    ng-click="selectWord($parent.$index, $index)" ng-class="{selected:word.selected}">{{word.word}}</span>
                </li>
            </ul>
        </div>
        <script>
            angular.module("myApp",[])
            .controller("myCtrl",function($scope){
                //文本数据
                $scope.textContent = [];
                var chars = '呃苏先生您好我这边是应答人寿的客户服务人员.感谢您对我公司的信任最近在福建很会.购买了我公司的安康宝两全保险分红型.附加安康保提前给付重大疾病保险.为了保障您的权益我们购买了我公司保险产品的客户.都会进行售后回访,服务.现在这样您几分钟您看方便吗?';
                var arr = chars.split('');
                var len = arr.length;
                var wordId = 0;
                for (var i = 0; i < 30; i++) {
                    var textContent = [];
                    for (var k = 0; k < Math.floor(Math.random() * 1000) % 100; k++) {
                        var word = '';
                        for (var j = 0; j < Math.floor(Math.random() * 10) % 5; j++) {
                            word += arr[Math.floor(Math.random() * 1000) % len];
                        }
                        textContent.push({word: word, id: wordId});
                        wordId++;
                    }
                    var role = Math.round(Math.random()) == 0 ? 'A' : 'B';
                    $scope.textContent.push({role: role, textContent: textContent});
                }
                
                //记录文本中选择词的位置的数组,最多纪录两个
                $scope.selectWordsArr = [];

                /**
                 * 选择文本内容方法
                 */
                $scope.selectWord = function (parentIndex, index) {
                    var wordInfo = {s:parentIndex,w:index};
                    //如果arr为空,则直接压入
                    if($scope.selectWordsArr.length == 0) {
                        $scope.selectWordsArr.push(wordInfo);
                        //高亮该词
                        $scope.highLightFnc($scope.selectWordsArr, true);
                    } 
                    //否则判断当前点击是否存在于arr中,判断是否点击相同节点,如果是,则取消高亮
                    else if($scope.selectWordsArr.length == 1) {
                        //如果arr长度为1,说明只有一个词
                        if($scope.isInSignWordArr($scope.selectWordsArr, wordInfo)) {
                            //如果arr中存在相同词,说明再次点击,则取消该词高亮
                            $scope.highLightFnc($scope.selectWordsArr, false);
                            //并移出数组
                            $scope.selectWordsArr = $scope.removeWordFromArrFnc($scope.selectWordsArr, wordInfo);
                        }else{
                            //否则,将该词信息压入arr
                            $scope.selectWordsArr.push(wordInfo);
                            //排序,方便后面操作
                            $scope.selectWordsArr = $scope.sortArr($scope.selectWordsArr);
                            //高亮该区间
                            $scope.highLightFnc($scope.selectWordsArr, true);
                        }
                    } 
                    //如果数组中已有2个,则对第三个点击词进行判断
                    else if ($scope.selectWordsArr.length == 2) {
                        //如果点击词的位置小于arr中较小位置,则进行对较小位置替换
                        //如果点击词的位置大于arr中较大位置,则对较大值进行替换
                        //如果点击词存在于arr中,则进行区间取消高亮,后将相同词移除,单个词高亮
                        if($scope.isInSignWordArr($scope.selectWordsArr, wordInfo)) {
                            //当前词存在,取消区间高亮
                            $scope.highLightFnc($scope.selectWordsArr, false);
                            //将对应词移出数组
                            $scope.selectWordsArr = $scope.removeWordFromArrFnc($scope.selectWordsArr, wordInfo);
                            //设置剩余单词高亮
                            $scope.highLightFnc($scope.selectWordsArr, true);                            
                        } else {
                            //进行区间外的判断,如果小于小值,则替换小值,否则什么都不做
                            if(wordInfo.s < $scope.selectWordsArr[0].s){
                                //如果行小于,直接记录小值
                                $scope.selectWordsArr[0] = wordInfo;
                            }else if(wordInfo.s == $scope.selectWordsArr[0].s && wordInfo.w < $scope.selectWordsArr[0].w) {
                                //行等于且词小于才记录
                                $scope.selectWordsArr[0] = wordInfo;
                            }
                            //进行区间外判断,大于大值则替换,否则什么都不做
                            if(wordInfo.s > $scope.selectWordsArr[1].s){
                                //行大于直接记录
                                $scope.selectWordsArr[1] = wordInfo;
                            }else if (wordInfo.s == $scope.selectWordsArr[1].s && wordInfo.w > $scope.selectWordsArr[1].w){
                                //行等于且词位置大于才记录
                                $scope.selectWordsArr[1] = wordInfo;
                                
                            }
                            //处理完后,高亮该区间
                            $scope.highLightFnc($scope.selectWordsArr, true);
                        }
                    }
                    angular.forEach($scope.selectWordsArr, function (obj, i) {                    
                        console.dir(i+ ' : '+obj.s+'_'+obj.w);
                    })            
                }
                
                //判断当前点是否存在于已纪录词位置的数组中
                $scope.isInSignWordArr = function(arr, data) {
                    var isIn = false;
                    angular.forEach(arr, function (obj) {
                        if(obj.s == data.s && obj.w == data.w) {
                            isIn = true;
                            return;
                        }
                    })
                    return isIn;
                }
                
                //将对应词位置从数组中移除
                $scope.removeWordFromArrFnc = function (arr, data) {
                    var sub = 0;
                    angular.forEach(arr, function (obj, i) {
                        if(obj.s == data.s && obj.w == data.w) {
                            sub = i;
                            return;
                        }
                    })
                    arr.splice(sub, 1);
                    return arr;
                }
                
                //对位置数组进行排序操作,小在前,大在后,并返回
                $scope.sortArr = function (arr) {
                    var maxSub,minSub;
                    if(arr[0].s> arr[1].s){
                        //如果前者大
                        maxSub = 0;
                        minSub = 1;
                    }else if(arr[0].s == arr[1].s){
                        //句子行数相同,判断词位置
                        if(arr[0].w>arr[1].w){
                            //如果前者大
                            maxSub = 0;
                            minSub = 1;
                        } else {
                            //否则后者大
                            maxSub = 1;
                            minSub = 0;
                        }
                    } else {
                        //否则后者大
                        maxSub = 1;
                        minSub = 0;
                    }
                    return [arr[minSub],arr[maxSub]];
                }
                
                //高亮或取消对应文本位置
                $scope.highLightFnc = function (arr, highLight) {
                    //如果arr中词为一个,则对一个词进行是否高亮
                    if(arr.length == 1){
                        $scope.textContent[arr[0].s].textContent[arr[0].w].selected = highLight;
                    } else {
                        if(arr[0].s == arr[1].s) {
                            //同一行
                            for(var i = arr[0].w; i <= arr[1].w; i++) {
                                $scope.textContent[arr[1].s].textContent[i].selected = highLight;
                            }
                        }else {
                            //不同行操作
                            for(var i = arr[0].s; i <= arr[1].s; i ++) {
                                for(var j = 0; j < $scope.textContent[i].textContent.length; j ++) {
                                    if(i == arr[0].s) {
                                        if(j >= arr[0].w){
                                            //如果遍历的是选择前词的行,则判断从选词开始高亮或取消
                                            $scope.textContent[i].textContent[j].selected = highLight;
                                        }
                                    } else if(i == arr[1].s) {
                                        if(j <= arr[1].w){
                                            //如果遍历的是选择后词的行,则判断从0位置搭配选词结束高亮或取消
                                            $scope.textContent[i].textContent[j].selected = highLight;    
                                        }                                    
                                    } else {
                                        //否则就高亮或取消
                                        $scope.textContent[i].textContent[j].selected = highLight;    
                                    }
                                }
                            }
                        }
                    }
                }
            })
        </script>
    </body>
</html>

 

posted @ 2017-10-19 15:09  名字不好起啊  阅读(338)  评论(0编辑  收藏  举报