文本框的部分内容能否只读?

5
我正在尝试在文本框中显示默认文本并使其只读。用户将能够在只读文本后添加文本。是否可以通过JS、HTML或CSS实现?READONLY文本将是只读的,用户无法更改它。但用户可以在此之后添加一些文本。这可行吗?我想发布这段文本,所以我不想使用标签。我可以将其拆分为两个部分。但我只是好奇!

你能详细说明一下你的使用情况吗?还是你只想要一个盲目的答案?此外,“READONLY WRITABLE”是什么意思? - Wesley Murch
1
一种方法是通过监控键事件来管理文本框的内容,并防止文本框中的固定/“只读”部分被删除。 - TGH
3
请注意:如果您想读取或添加 "readonly" 属性值,只需在服务器端手动添加即可。该属性仅用于用户界面,不能保证文本不可编辑,因为它非常容易被“黑客”攻击。您知道这点,对吗? - Wesley Murch
4个回答

2
任何真正的验证都应该在后端完成,但你可以为文本框的value属性分配一个值。在加载时,这将设置DOM元素的defaultValue属性。然后,在每个keyup事件中,你将比较文本的值与其原始值,并根据需要进行修改。
如果你在值的中间插入文本,请注意它会插入不匹配的部分并保留你已有的值的其余部分。如果你粘贴了一个长字符串而不想丢失文本,这可能很有用。

http://jsfiddle.net/vol7ron/HdpPp/

var $text = $('#text');

$text.on('keyup',function(){
    // Cache some lookups
    var $this    = $(this);
    var _val     = $this.val();           
    var _dv      = $this.prop('defaultValue');
    var _len     = _dv.length;
    var _tmp     = _val.substring( 0, Math.min( $this.val().length, _len ) );
    var mismatch = { found:false, position:0 };

    // Look for character position where two strings differ
    for(var i=0,n=_tmp.length;i<n;i++)
        if ( _tmp[i] != _dv[i] ) {      // compare two characters; true=difference found
            mismatch.found = true;      // set the boolean
            mismatch.position = i;      // store the position
            break;                      // stop looking
        }

    // Original string exists, but with end characters missing
    if ( !mismatch.found && _tmp.length < _len )
        mismatch.position = _len - ( _len - _tmp.length );

    // Insert original string before the mismatch position
    if (mismatch.found || mismatch.position) {
        _val = _val.split('');
        _val.splice( mismatch.position, 0, _dv.substring(mismatch.position) );
        _val = _val.join('');
        $this.val(_val);
    }
});

实现这个最简单的方法是使用CSS/标签定位,正如其他人已经建议的那样。

如果我在 READONLY 中输入一些东西(例如 s),它会显示为 READONLYsDONLY,所以你的答案不仅太长和复杂,甚至还不能正常工作。 - vladkras
@vladkras 不,那是预期的效果;但是,你的评论是错的... 应该是 READONLYsONLYs 后面没有 D)。此外,它不算长,打字速度很快,你可以轻松将其最小化到更合理/最优的形式,我的角色不是去做工作,而是提供一种解决方案/答案。再思考一下,这几乎太简单了,另一个 JS 解决方案将是处理键码。这甚至不包括鼠标事件。与治疗症状不同,最好的方法是治愈答案——为什么需要这样做? - vol7ron
这是我找到的唯一一个实际考虑到在输入值中具有只读文本的答案。非常有用,谢谢。 - nicholmikey

2
将文本移到文本框前的普通(<label for>)元素中,并添加 CSS 样式使其看起来好像在文本框内部。

嗯,那么为了发布该值,我必须使用隐藏的方式。假设默认值是当前日期。 - zod
@WesleyMurch:你不需要知道那个。 - SLaks
@SLaks 它会覆盖实际用户输入。也许你应该更详细地阐述你的答案。 - Wesley Murch
@WesleyMurch:这取决于您如何布局文本框。 - SLaks
4
@zod - 为什么你需要发布只读部分?你已经知道它是什么,肯定是从某个地方获取到的才能判断它是只读部分。将数据发送到页面再发回来(例如隐藏字段)只会给最终用户篡改的机会。 - Stephen P
显示剩余6条评论

1
var InputMask = {
init: function () {
    var divMask = document.getElementById("readonly");
    var inputField = document.getElementById("myInput");

    InputMask._input = inputField;
    InputMask._pos = 0;
    // resets the form
    inputField.value = "";

    divMask.addEventListener('click', InputMask.focusHandler, false );
    inputField.addEventListener('focus', InputMask.focusHandler, false );
    inputField.addEventListener('keydown', InputMask.keyInput, false );

},

focusHandler: function(event){
    InputMask._input.focus();

    var backup = InputMask._input.value.substr(20) || "";

    InputMask._input.value="                    " + backup;
},

keyInput: function ( event ) {
    var length_invalid = (InputMask._input.value.length == 20 ) ? true : false;
    var realString = InputMask._input.value.substr(20);
    var realLength = realString.length;

    // fix to mouse selection delete
    if ( InputMask._input.value.length < 20 ) {
        InputMask._input.value="                    ";
    }

    // backspace code = 8
    if (event.keyCode == 8 && length_invalid ) event.preventDefault();

    // left arrow key = 37
    if ( event.keyCode == 37 && (realLength + InputMask._pos) == 0 ) {
        event.preventDefault();
    } else if (event.keyCode == 37 && ( InputMask._pos >= (0 - realLength))) {
        InputMask._pos--;
    }

    // right arrow key = 39
    if ( event.keyCode == 39 && InputMask._pos < 0) InputMask._pos++;        

    // enter = 13
    if ( event.keyCode == 13) {
        alert ( "Input Value: ["+ InputMask._input.value.substr(20) +"]");

        // reset
        InputMask.reset();
    }
},
reset: function(){
    var field = InputMask._input;

    field.value = "";
    field.blur();
}
};

InputMask.init();

jsFiddle

这段代码使用了CSS样式、一些文本间距和事件处理。我没有编写完整的鼠标选择处理函数,目前允许用户选择空格并删除它(如果有字符串输入,则甚至可以按回退键),但如果按下任何键并且长度小于20,则会插入20个空格。

当您按箭头键时,它将计算光标所在位置,并根据此位置让您移动或不移动它(只是简单的preventDefault)。而在ENTER键上,将显示没有填充空格的值。

重叠的div的好处是可以使用不同的文本颜色、背景等(div样式)...所有你需要做的就是设置白色空格的数量,使其看起来像是div在输入框内部。

当然,这不是跨浏览器的,您必须自己进行所有声明检查和事件处理检查,但我认为这基本上是您想要的,对吗?


我刚意识到我没有添加一些if来处理向上箭头或Home键。在鼠标选择修复后添加if ( event.keyCode == 38 || event.keyCode == 36 ) event.preventDefault();会“有点”解决它,因为你将失去这些键的功能。你需要另外处理把光标放在空格的末尾... - Enzo Ferber
如果您想发布只读文本,只需将其保存在表单中的隐藏输入中即可。简单的 JS 就可以实现这个功能。因此,您可以使用 JS 设置 div 和隐藏输入!;) - Enzo Ferber

0

这只是我随手写的东西。希望能有所帮助。

 <div style="position:absolute; z-index:1; top:1px; width:270px; border:2px; border:1px 
 solid black;">type here:</div>

 <input style="position:absolute; z-index:2; top:1px; width:200px; left:70px; border:0px   
 solid black;"/>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接