笑疯洋洋 阅读(210) 评论(0)

   前两个月,公司内部需要开发关于大数据方面的辅助工具语料分词系统,在这个项目中遇到以下几个主要问题,在此分享~

一、input宽度根据内定文本宽度自适应


  背景:项目需求中,前台展示,需要从后台获取的.txt文件解析成很多字符串,然后分别放在前台input框中,贴图:

 

  其中,每一个字符串,长度不一,所以,input框要根据字符串的长度,发生变化,这里就要解决input自适应的问题了。

  方法一:网上搜索的,误差很大,仅供参考~

    

然后,我又改善了一下,减小误差。

//字符串文本
var a1 = "人民网/nz 莫斯科/nsf 31日/t 电/n (/w 记者/nnt 屈海齐/nr )/w 据/p 俄新社/nt 报道/v ,/w 《/w [今日/t 俄罗斯/nsf]/nz 》/w (/w RussiaToday/x )/w [总裁/nnt德米特里·基谢廖夫/nrf决定]/v 任命/vn 玛格丽特·西莫尼/nrf 杨/ng 为/p 《/w [今日/t 俄罗斯/nsf]/nz 》/w 通讯社/nis 主编/v ,/w 同时/c 兼任/v 《/w [今日/t俄罗斯/nsf]/nz 》/w [电视/n 频道/n]/nz 主编/v 。/w 玛格丽特·西蒙尼扬/nrf 1980年/t 生于/v [克拉斯/nrf 诺达尔/nrf]/ns 。/w 毕业/v 于/p [库班/nrf 国立/b 大学/nis 新闻系//w 频道/n 主编/v 。/w 2013年12月9日/t ,/w [俄罗斯/nsf 总统/nnt]/nz 普京/nrf 下令/v 在/p 三个月/t 内/f 将/d 《/w 俄新社/nt 》/w 和/cc 《/w [俄罗斯/nsf 之/uzhi 声/qv]/nz 》/w 电台/nis 合并/v 为/p 《/w [今日/t 俄罗斯/nsf]/nz 》/w [国际/n 通讯社/nis]/nt 。/w ";
//把字符串根据空格整理成数组
var strArr = a1.split(" ");
console.log(strArr)

for(var i= 0;i<=strArr.length;i++){
    var ssd = strArr[i]
    //数组元素存放容器
    $("body").append('<div class="q1" style="display:inline-block;font-size:12px;fontFamily:"Serif""></div> '); 
   $(
".q1").text(ssd) var wid =$(".q1").text(strArr[i]).width(); $(".q1").remove();
  //获取宽度赋值给input宽度
   $(".a1").append($('<input type="text">').val(strArr[i]).css({
    width: wid
+18 ,
   fontSize:
"12px",
    fontFamily:
"Serif",
    boxSizing:
"border-box",
   padding:
"5px"
  }))
}

想法:

  首先,在body里新创建一个div(不建议使用span等块状级元素),设置display:inline-block、字体、字体大小。然后把字符串值赋值进去,获取div宽度,再删除掉div。把获取的宽度设置成input的宽度,这里的width = wid +18,需要在页面调试合适宽度。其中,input内的字符串也要设置字体、字体大小,减少误差。最后成为这样~

  方法二:根据scrollWidth、clientWidth判断。

  scrollWidth:对象的实际内容的宽度,不包边线宽度,会随对象中内容超过可视区后而变大。

  clientWidth:对象内容的可视区的宽度。

  在input内,scrollWidth也就相对于input中value值的长度。clientWidth相当于input默认宽度(能看到的宽度)。

for (var i = 0; i < strArr.length; i++) {
    var ssd = strArr[i];
    $(".a1").append($('<input type="text">').val(strArr[i]));
}
$("input").each(function(index, item){
    if (item.scrollWidth > item.clientWidth) {
      item.style.width = item.scrollWidth + 4 + "px";
    }
})

  注意两点:

    一点是,代码中展示的scrollWidth  >  clientWidth的时候,因为value值内容含字母符号等,获取scrollWidth有几像素的误差,加上就可以了,调试过后,没问题。

    第二点,scrollWidth  <  clientWidth  时候又该怎么让input自适应呢???  做东西呢,不能过于死脑筋。把input的宽度设置5px或者10px,让scrollWidth  总是大于clientWidth不就可以了吗!老铁,没毛病吧,哈哈哈哈~

 

二、input合并


   关于合并,在开始解决这个功能之前,应该分析出该功能实现所遇到的核心问题。

  1. 点击多个input是否连续,非连续不可合并。(项目需求)
  2. 获取到的value值如何添加到合并的位置上。

  分析完问题,方向明确了,也就好做了。

  首先是连续问题,先看代码:

  var inputArr = [];
    var item = 0;
    var len;
    var inputVal="";
    $("#demo").on("click","input",function(){
        //添加选中样式
        $(this).toggleClass('bd1');
        item = $(this).index();
        inputArr.push(item);
        //再次点击,inputArr数组删除 所对应的item值
        len=inputArr.length;
        for(var i=0;i<len;i++){
                if(item == inputArr[i]){
                    inputArr.splice(i,1);
                    console.log(inputArr);
                    return;
                }
            };
            //数组排序
            inputArr.sort();
            console.log(inputArr)
    });

说明:

  这里只是做了准备工作。点击input框获取它的index值,然后把index值push到一个新数组,然后进行排序。其中for循环是input框取消选中时,删除新数组中所对应的index值。

 

接下来需要一个判断数组是否为连续的如[1,2,3,4,5]方法,网上这类的有很多,我用了其中一个:

function isContinuationInteger(arr){
    if(!arr){
        return false;
    }
    if(arr.length==0){
        return true;
    }
    var len=arr.length;
    var n0=arr[0];
    var sortDirection=1;
    if(arr[0]>arr[len-1]){
        sortDirection=-1;
    }
    if((n0*1+(len-1)*sortDirection)!==arr[len-1]){
        return false;
    }
    var isContinuation=true;
    for(var i=0;i<len;i++){
        if(arr[i]!==(i+n0*sortDirection)){
            isContinuation=false;
            break;
        }
    }
    return isContinuation;
}

然后就是点击合并按钮,所要处理的事件了。

$("#combine").on("click",function(){
    var strArr = '';
    if(!isContinuationInteger(inputArr)){
        alert('不合法');
        return ;
    }else{
        inputArr.map(function(v){
            strArr += $('input').eq(v).val();
        })
        $(".bd1").each(function(e){
            console.log(e);
            $(this).eq(e).before($('<input type="text" readonly>').val(strArr));
            $(this).remove();
            inputArr =[];
            //console.log($(this).eq(e))              
        })
    }
})

这里要注意的有:

  1. 点击事件需要用到on()方法,不可直接用click方法,主要原因是在这个点击事件内添加了新的input框,然后,新的input也可以实现合并功能,也就有了事件委托。
  2. 数组遍历map()方法,调用数组中的每一个元素,然后把相对应的value值合并成一个字符串。
  3. 新的input添加,这里用到点击input动态添加的class,然后是each()方法返回的index值,再根据input框所在位置eq(),在它之前添加input,然后删除它本身。
  4. 以上步骤完成之后,一定要清空存放input框index值的数组。这点要注意。

 

三、input拆分


   input拆分,核心问题在于,获取光标所在位置,然后根据空格键进行拆分,用js或者jq实现的话,很麻烦,为了效率在网上找一些封装方法。要是用angluar或者vue,根据ng-model或者v-model双向数据绑定,再用watch监督,根据value值中的光标位置,点击快捷键会出现空格,然后进行字符串拆分,应该就容易了!(纯想法,有兴趣的可以尝试一下)  

  这里主要是jq实现:

  首先是封装方法,还是前边讲的,有很多时候不能死脑筋,换种思路,问题就迎刃而解了。如果说,根据光标位置进行快捷键进行拆分不好获取,是不是可以找一些方法在光标位置插入某个字符串,然后再根据这个字符串进行分割,然后就找到了下面的封装方法:

/* 在textarea处插入文本--Start */
(function($) {
    $.fn.extend({
        insertContent : function(myValue, t) {
            var $t = $(this)[0];
            if (document.selection) { // ie
                this.focus();
                var sel = document.selection.createRange();
                sel.text = myValue;
                this.focus();
                sel.moveStart('character', -l);
                var wee = sel.text.length;
                if (arguments.length == 2) {
                    var l = $t.value.length;
                    sel.moveEnd("character", wee + t);
                    t <= 0 ? sel.moveStart("character", wee - 2 * t - myValue.length) : sel.moveStart( "character", wee - t - myValue.length);
                    sel.select();
                }
            } else if ($t.selectionStart
                || $t.selectionStart == '0') {
                var startPos = $t.selectionStart;
                var endPos = $t.selectionEnd;
                var scrollTop = $t.scrollTop;
                $t.value = $t.value.substring(0, startPos)
                    + myValue
                    + $t.value.substring(endPos,$t.value.length);
                this.focus();
                $t.selectionStart = startPos + myValue.length;
                $t.selectionEnd = startPos + myValue.length;
                $t.scrollTop = scrollTop;
                if (arguments.length == 2) {
                    $t.setSelectionRange(startPos - t,
                        $t.selectionEnd + t);
                    this.focus();
                }
            } else {
                this.value += myValue;
                this.focus();
            }
        }
    })
})(jQuery);
/* 在textarea处插入文本--Ending */

使用方法是:$(文本域选择器).insertContent("插入的内容");

贴码:

$("#split").on("click",function(){
    var splitArr=[];
    $(".bd1").each(function(e){
        splitArr.push(e);
    });
    if(splitArr.length>1){
        alert("只能选择一个字符串拆分!");
        $(this).removeClass("bd1");
        return;
    }else{
        $(".bd1").each(function(e){
            //inputVal是选中input框的value值
            if(inputVal.length<2){
                alert("字符数量必须大于两个!");
                $(this).removeClass("bd1");
                return;
            }else{
                if( $(this).hasClass("bd1")){
                    $(this).toggleClass("dw1");
                    $(this).removeAttr("readonly");
                    //console.log("sdasdsad");
                    $(this).keypress(function(event){
                        if ( $(this).hasClass('dw1')){
                            if (event.keyCode == 32) {
                                $(this).insertContent("#");
                                //console.log($(this).insertContent("#"))
                                var value1 =  $(this).val();
                                console.log(value1.split("#"))
                                var valueone = value1.split("#")[0];
                                var valuetwo = value1.split("#")[1];
                                $(this).eq(e).before($('<input type="text" readonly>').val(valueone));
                                $(this).eq(e).after($('<input type="text" readonly>').val(valuetwo));
                                $(this).remove();
                            }
                        }
                    })
                }
            }
        });
    }
});

  这里用到了字符串分割成数组的split()方法,js文档中有详细介绍,在这里就不说明了。

   

  后记:内容虽然很少,可我偏偏整理了将近一天的时间 ,真的是哭笑不得啊~

 

                                                          2017.12.19