Javascript学习笔记(详)(六)——表单

表单脚本

表单的基础知识

在javascript中,表单对应的是HTMLFormElement类型,继承自HTMLELement类型。独特的属性与方法:

  • acceptCharset:服务器能够处理的字符集;等价于HTML 中的accept-charset 特性。
  • action:接受请求的URL;等价于HTML 中的action 特性。
  • elements:表单中所有控件的集合(HTMLCollection)。
  • enctype:请求的编码类型;等价于HTML 中的enctype 特性。
  • length:表单中控件的数量。
  • method:要发送的HTTP 请求类型,通常是"get"或"post";等价于HTML 的method 特性。
  • name:表单的名称;等价于HTML 的name 特性。
  • reset():将所有表单域重置为默认值。
  • submit():提交表单。
  • target:用于发送请求和接收响应的窗口名称;等价于HTML 的target 特性。

通过documents.forms可以取得页面中所有表单,可以通过数值索引或name值来取得特定表单

提交表单

<!-- 通用提交按钮 -->
<input type="submit" value="Submit Form">
<!-- 自定义提交按钮 -->
<button type="submit">Submit Form</button>
<!-- 图像按钮 -->
<input type="image" src="graphic.gif">

阻止表单提交:

    let form = document.getElementById("myForm");
    form.addEventListener("submit", function (event) {
        event.preventDefault();
    })
	let form = document.getElementById("myForm");
    form.submit();//不会触发submit事件

重置表单

<!-- 通用重置按钮 -->
<input type="reset" value="Reset Form">
<!-- 自定义重置按钮 -->
<button type="reset">Reset Form</button>

阻止表单重置和利用javascript重置表单的操作与提交表单类似,只需将submit改为reset即可

表单字段

每个表单都有elements属性,是一个有序列表,包含表单的所有字段

let form = document.getElementById("form1");
//取得表单中的第一个字段
var field1 = form.elements[0];
//取得名为"textbox1"的字段
var field2 = form.elements["textbox1"];
//取得表单中包含的字段的数量
var fieldCount = form.elements.length;
var form = document.getElementById("myForm");
var colorFields = form.elements["color"];
alert(colorFields.length); //3
var firstColorField = colorFields[0];
var firstFormField = form.elements[0];
alert(firstColorField === firstFormField); //true
共有的表单字段属性

除了fieldset元素之外,所有表单字段都拥有相同的一组属性:

  • disabled:布尔值,表示当前字段是否被禁用。
  • form:指向当前字段所属表单的指针;只读。
  • name:当前字段的名称。
  • readOnly:布尔值,表示当前字段是否只读。
  • tabIndex:表示当前字段的切换(tab)序号。
  • type:当前字段的类型,如"checkbox"、“radio”,等等。
  • value:当前字段将被提交给服务器的值。对于文件字段,这个属性是只读的,包含文件在计算机中的路径。
    let form = document.getElementsByTagName('form')[0];
    //alert(form);
    // let colorFields = form.elements['color'];
    // let list = Array(colorFields);
    // alert(list);
    let field = form.elements[0];
    field.value = "Another value";
    field.focus();
    field.disable = true;
    field.type = "checkbox";//不推荐,但对<input>可行
	let form = document.getElementsByTagName('form')[0];
    form.addEventListener("submit", function (event) {
        let target = event.target;
        let btn = target.elements['submit-btn'];
        btn.disabled =true;
    })
共有的表单字段方法

focus()blur()。focus()方法用于激活表单字段,使其可以响应键盘事件

    window.addEventListener("load", function (event) {
        document.forms[0].elements[1].focus();
    })

倘若是对<input type="hidden">的表单字段进行上述操作将会导致错误,通过CSS的display和visibility属性隐藏该字段都会导致错误

   //自动对焦
   window.addEventListener("load", function (event) {
        let element = document.forms[0].elements[0];
        if(element.autofocus === true){
            element.focus();
            console.log("JS focus");
        }
    })

blur()方法则相反

共有的表单字段事件
  • blur:当前字段失去焦点时触发。

  • change:对于<input><textarea>元素,在它们失去焦点且value 值改变时触发;对于<select>元素,在其选项改变时触发。

    扫描二维码关注公众号,回复: 11529186 查看本文章
  • focus:当前字段获得焦点时触发。

    let textbox = document.forms[0].elements[0];
    textbox.addEventListener("focus", function (event) {
        let target = event.target;
        if(target.style.backgroundColor != 'red'){
            target.style.backgroundColor = "yellow";
        }
    });
    textbox.addEventListener("blur", function (event) {
        let target = event.target;
        if(/[^\d]/.test(target.value)){
            target.style.backgroundColor = 'red';
        }else{
            target.style.backgroundColor = '';
        }
    });
    textbox.addEventListener("change", function (event) {
        let target = event.target;
        if(/[^\d]/.test(target.value)){
            target.style.backgroundColor = "red";
        }else{
            target.style.backgroundColor = "";
        }
    });

文本框脚本

<input type="text" size="25" maxlength="50" value="initial value"><!--单行文本框-->
<textarea rows="25" cols="5">initial value</textarea><!--多行文本框-->

选择文本

select():选择文本框中的所有文本

	 textbox.addEventListener("focus", function (event) {
        let target = event.target;
        target.select();
    })
选择事件

选择文本框中的文本后就会触发select事件

textbox.addEventListener("select", function (event) {
    alert("Text selected: " + textbox.value);
})
取得选择的文本
function getSelectedText(textbox){
    if (typeof textbox.selectionStart == "number"){
    	return textbox.value.substring(textbox.selectionStart, textbox.selectionEnd);
    } else if (document.selection){//IE
        return document.selection.createRange().text;
    }
}
选择部分文本
textbox.value = "Hello world!"
//选择所有文本
textbox.setSelectionRange(0, textbox.value.length); //"Hello world!"
//选择前3个字符
textbox.setSelectionRange(0, 3); //"Hel"
//选择第4到第6个字符
textbox.setSelectionRange(4, 7); //"o w"
function selectText(textbox, startIndex, stopIndex){
    if (textbox.setSelectionRange){
    	textbox.setSelectionRange(startIndex, stopIndex);
    } else if (textbox.createTextRange){
        var range = textbox.createTextRange();
        range.collapse(true);
        range.moveStart("character", startIndex);
        range.moveEnd("character", stopIndex - startIndex);
        range.select();
    }
    textbox.focus();
}

过滤输入

屏蔽字符
    //屏蔽非数字输入
    textbox.addEventListener("keypress", function (event) {
        let target = event.target;
        let charCode = event.charCode;
        if(!/\d/.test(String.fromCharCode(charCode)) && charCode > 9 && !event.ctrlKey){
            event.preventDefault();
        }
    })
操作剪贴板

六个剪贴板事件:

  • beforecopy:在发生复制操作前触发。
  • copy:在发生复制操作时触发。
  • beforecut:在发生剪切操作前触发。
  • cut:在发生剪切操作时触发。
  • beforepaste:在发生粘贴操作前触发。
  • paste:在发生粘贴操作时触发。

要访问剪贴板中的数据,可以使用clipboardData对象。在IE中,该对象是window对象的属性,在其余浏览器中,该对象是相应event对象的属性。

clipboardData对象的三个方法:getData(), setData(),clearData()

getClipboardText: function(event){
    var clipboardData = (event.clipboardData || window.clipboardData);
    return clipboardData.getData("text");
},

setClipboardText: function(event, value){
    if (event.clipboardData){
        return event.clipboardData.setData("text/plain", value);
    } else if (window.clipboardData){
        return window.clipboardData.setData("text", value);
    }
},
    textbox.addEventListener("paste", function (event) {
        let text = event.clipboardData.getData("text");
        if(!/^\d*$/.test(text)){
            event.preventDefault();
        }
    })

自动切换焦点

在前一个文本框的字符达到最大数量后,自动将焦点切到下一个文本框

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form>
    <input type="text" name="tel1" id="txtTel1" maxlength="3">
    <input type="text" name="tel2" id="txtTel2" maxlength="3">
    <input type="text" name="tel3" id="txtTel3" maxlength="4">
</form>
</body>
</html>
<script type="text/javascript">
    (function () {
        function tabForward(event) {
            let target = event.target;
            if(target.value.length === target.maxLength){
                let form = target.form;
                for(let i = 0, len = form.elements.length; i < len; i++){
                    if(form.elements[i] === target){
                        if(form.elements[i+1]){
                            form.elements[i+1].focus();
                        }
                        return;
                    }
                }
            }
        }

        let textbox1 = document.getElementById("txtTel1");
        let textbox2 = document.getElementById("txtTel2");
        let textbox3 = document.getElementById("txtTel3");

        textbox1.addEventListener("keyup", tabForward);
        textbox2.addEventListener("keyup", tabForward);
        textbox3.addEventListener("keyup", tabForward);
    })();
</script>

HTML5约束验证API

必填字段
<input type="text" name="username" required>

检查是否为必填字段

var isUsernameRequired = document.forms[0].elements["username"].required;
其他输入类型
<input type="email" name ="email">
<input type="url" name="homepage">
数值范围
<input type="number" min="0" max="100" step="5" name="count">
输入模式
<input type="text" pattern="\d+" name="count">  <!--无法阻止无效字符的输入-->
var pattern = document.forms[0].elements["count"].pattern;
检测有效性

checkValidity()方法可以检测表单中的某个字段是否有效

document.forms[0].elements[0].checkValidity()

document.forms[0].checkValidity()//检测整个表单

validity属性包含一系列属性:

  • customError :如果设置了setCustomValidity(),则返回true。
  • patternMismatch:如果值与指定的pattern 属性不匹配,返回true。
  • rangeOverflow:如果值比max 值大,返回true。
  • rangeUnderflow:如果值比min 值小,返回true。
  • stepMisMatch:如果min 和max 之间的步长值不合理,返回true。
  • tooLong:如果值的长度超过了maxlength ,返回true。
  • typeMismatch:如果值不是"mail"或"url"要求的格式,返回true。
  • valid:如果这里的其他属性都是false,返回true。
  • valueMissing:如果标注为required 的字段中没有值,返回true。
if (input.validity && !input.validity.valid){
    if (input.validity.valueMissing){
        alert("Please specify a value.")
    } else if (input.validity.typeMismatch){
        alert("Please enter an email address.");
    } else {
        alert("Value is invalid.");
    }
}
禁用验证

设置novalidate属性

<form method="post" action="signup.php" novalidate>
document.forms[0].noValidate = true; //禁用验证

选择框脚本

选择框是通过<select><option>元素创建的。HTMLSelectElement类型还提供了下列属性和方法:

  • add(newOption, relOption):向控件中插入新<option>元素,其位置在相关项(relOption)之前。
  • multiple:布尔值,表示是否允许多项选择;等价于HTML 中的multiple 特性。
  • options:控件中所有<option>元素的HTMLCollection。
  • remove(index):移除给定位置的选项。
  • selectedIndex:基于0 的选中项的索引,如果没有选中项,则值为-1。对于支持多选的控件,只保存选中项中第一项的索引。
  • size:选择框中可见的行数;等价于HTML 中的size 特性。

选择框的type属性是select-oneselect-multiple

选择框的value属性:如果没有选中的项,则选择框的value 属性保存空字符串。如果有一个选中项,而且该项的value 特性已经在HTML 中指定,则选择框的value 属性等于选中项的value 特性。即使value 特性的值是空字符串,也同样遵循此条规则。如果有一个选中项,但该项的value 特性在HTML 中未指定,则选择框的value 属性等于该项的文本。如果有多个选中项,则选择框的value 属性将依据前两条规则取得第一个选中项的值。

在DOM 中,每个<option>元素都有一个HTMLOptionElement 对象表示,HTMLOptionElement对象的属性:

  • index:当前选项在options 集合中的索引。
  • label:当前选项的标签;等价于HTML 中的label 特性。
  • selected:布尔值,表示当前选项是否被选中。将这个属性设置为true 可以选中当前选项。
  • text:选项的文本。
  • value:选项的值(等价于HTML中的value 特性)。
    let selectbox = document.forms[0].elements["location"];
    
    //不推荐
    let text = selectbox.options[0].firstChild.nodeValue;
    let value = selectbox.options[0].getAttribute("value");
    
    //推荐
    let text2 = selectbox.options[0].text;
    let value2 = selectbox.options[0].value;

选择框的change 事件与其他表单字段的change 事件触发的条件不一样。其他表单字段的change 事件是在值被修改且焦点离开当前字段时触发,而选择框的change 事件只要选中了选项就会触发。

选择选项

只允许选则一项的选择框,访问选中项的最简单方式

var selectedOption = selectbox.options[selectbox.selectedIndex];

另外的选择选项的方式:

selectbox.options[1].selected = true;

添加选项

var newOption = document.createElement("option");
newOption.appendChild(document.createTextNode("Option text"));
newOption.setAttribute("value", "Option value");
selectbox.appendChild(newOption);
let newOption = new Option("Option text 2 ", "Option value 2")
selectbox.appendChild(newOption);
let newOption = new Option("Option text", "Option value");
selectbox.add(newOption, undefined); //最佳方案

移除选项

selectbox.removeChild(selectbox.options[0]); //移除第一个选项

selectbox.remove(0); //移除第一个选项,0是索引

selectbox.options[0] = null; //移除第一个选项
//移除所有选项
for(let i = 0, len = selectbox.options.length; i < len; i++){
        selectbox.remove(0);
}

移动和重排选项

将第一个选择框中的第一个选项移动到第二个选择框的过程:

var selectbox1 = document.getElementById("selLocations1");
var selectbox2 = document.getElementById("selLocations2");
selectbox2.appendChild(selectbox1.options[0]);

重排选项

let optionToMove = selectbox.options[0];
selectbox.insertBefore(optionToMove, selectbox.options[optionToMove.index+2]);

表单序列化

浏览器将数据发送给服务器:

  1. 对表单字段的名称和值进行URL 编码,使用和号(&)分隔。
  2. 不发送禁用的表单字段。
  3. 只发送勾选的复选框和单选按钮。
  4. 不发送type 为"reset"和"button"的按钮。
  5. 多选选择框中的每个选中的值单独一个条目。
  6. 在单击提交按钮提交表单的情况下,也会发送提交按钮;否则,不发送提交按钮。也包括type为"image"的<input>元素。
  7. <select>元素的值,就是选中的<option>元素的value 特性的值。如果<option>元素没有value 特性,则是<option>元素的文本值。

富文本编辑

嵌入一个包含空HTML页面的iframe。设置designMode时该空白HTML页面可编辑。designMode含有两个可能的值off(默认)和on, 设置为on时整个文档都会变得可编辑

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<iframe name="richedit" style="height: 100px;width: 100px;" src="9.html"></iframe>

</body>
</html>
<script type="text/javascript">
    window.addEventListener("load", function () {
        frames["richedit"].document.designMode = "on";
    })
</script>

<!--9.html-->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Blank Page for Rich Text Editing</title>
</head>
<body>

</body>
</html>

使用contenteditable属性

<div class="editable" id="richedit" contenteditable="true"></div>

contenteditable属性的可能值:true:打开,false:关闭,inherit:从父元素那里继承

操作富文本

与富文本编辑器交互的主要方式:document.execCommand()。三个参数:要执行的命令名称,表示浏览器是否应该为当前命令提供用户界面的一个布尔值和执行命令必须的一个值(如果不需要值,则传递null)。为了保证跨浏览器的兼容性,第二个参数应该设置为false。命令:

image-20200715144944952

image-20200715145003727

//转换粗体文本
frames["richedit"].document.execCommand("bold", false, null);
//转换斜体文本
frames["richedit"].document.execCommand("italic", false, null);
//创建指向www.wrox.com 的链接
frames["richedit"].document.execCommand("createlink", false,
"http://www.wrox.com");
//格式化为1 级标题
frames["richedit"].document.execCommand("formatblock", false, "<h1>");

queryCommandEnabled(),可以用它来检测是否可以针对当前选择的文本,或者当前插入字符所在位置执行某个命令。

let result = frames["richedit"].document.queryCommandEnabled("bold");

queryCommandState()方法用于确定是否将指定命令应用到了选择的文本

var isBold = frames["richedit"].document.queryCommandState("bold");

queryCommandValue(),用于取得执行命令时传入的值(即传给document.execCommand()的第三个参数)

var fontSize = frames["richedit"].document.queryCommandValue("fontsize");

富文本选区

在富文本编辑器中使用框架(iframe)的getSelection()方法可以确定实际选择的文本。这个方法是window对象和document对象的属性,返回表示当前选择文本的Selection对象。

Selection对象的属性:

  • anchorNode:选区起点所在的节点。
  • anchorOffset:到达选区起点位置前跳过的anchorNode中的字符数。
  • focusNode:选区终点所在的节点。
  • focusOffset:focusNode 中包含在选区之内的字符数。
  • isCollapsed:布尔值,表示选区的起点和终点是否重合。
  • rangeCount:选区中包含的DOM 范围的数量。

方法:

  • addRange(range):将指定的DOM 范围添加到选区中。
  • collapse(node, offset):将选区折叠到指定节点相应的文本偏移位置。
  • collapseToEnd():将选区折叠到终点位置。
  • collapseToStart():将选区折叠到起点位置。
  • containsNode(node):确定指定的节点是否包含在选区中。
  • deleteFromDocument():从文档中删除选区中的文本,与document.execCommand(“delete”,false, null)命令的结果相同。
  • extend(node, offset):通过将focusNode 和focusOffset 移动到指定的值来扩展选区。
  • getRangeAt(index):返回索引对应的选区中的DOM范围。
  • removeAllRanges():从选区中移除所有DOM 范围。实际上这样会移除选区,因为选区中至少有一个范围。
  • removeRange(range):从选区中移除指定的DOM 范围。
  • selectAllChildren(node):清除选区并选择指定节点的所有子节点。
  • toString():返回选区所包含的文本内容。
    let selection = frames["richedit"].getSelection();
    let selectedText = selection.toString();
    let range = selection.getRangeAt(0);
    let span = frames["richedit"].document.createElement("span");
    span.style.backgroundColor = "yellow";
    range.surroundContents(span);

表单与富文本

富文本编辑器并不属于表单,其中的HTML并不会自动提交给服务器

    form.addEventListener("submit", function (event) {
        let target = event.target;
        target.elements["comments"].value = frames["richedit"].document.body.innerHTML;
    })

如果您觉得我的文章对您有帮助的话,可以点个赞,点个关注,也可以扫描下方二维码关注我。我将在这个公众号上更新自己的学习笔记,以及分享一些算法知识

Study and progress together with me!

img

猜你喜欢

转载自blog.csdn.net/qq_45359344/article/details/107755045