整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

Android开发分享-设计一个简易富文本编辑器

Android开发分享-设计一个简易富文本编辑器

简易富文本编辑

让HTML标签的contenteditable属性设为true即可直接修改内部内容,但是Android和在pc网页上使用可能存在差异。这里分享一个简单的富文本编辑,需要配合Android使用。

这个富文本编辑目前通过于Android端交互可以向其中添加图片、添加超链接、普通文本。主要靠js驱动(我的基础不行,只能写成这样)。详细解释看代码即可,需要配合Android知识。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>富文本编辑</title>
    <script type="text/javascript">
		/*每一个被添加的标签(也就是图片、超链接)都会被一层div包裹,固定其具体位置,并且每次添加完一个都会在其下部添加一个div用于输入文本(可忽略)*/
        /*添加外层标签*/
        function outDiv(inLabel)
        {
            var outdiv=document.createElement("div");
            outdiv.style.textAlign="center";
            outdiv.contentEditable=true;
            outdiv.appendChild(inLabel);
            document.getElementById("main").appendChild(outdiv);
            var nextDiv=document.createElement("div");
            document.getElementById("main").appendChild(nextDiv);
            nextDiv.outerHTML="<div style='margin-left: 30px; margin-right: 30px;' contenteditable='true'><br></div>"
        }

        /*添加图片*/
        function addPhoto(path)
        {
            var addImg=document.createElement("img");
            outDiv(addImg);
            addImg.outerHTML="<img src='" + path + "' alt='图片存在问题' id='" + path + "'/>";

        }

		/*Android端存在图片传输问题,是先将图片保存到文件夹内,再在html中调用,而在html中使用退格键即可删除标签,所以Android端在适当的时候清除没有用到的图片*/
        /*确定图片是否存在于html页面中*/
        function isExistedPhoto(id)
        {
            if(document.getElementById(id))
            {
                return 1;
            }
            else
            {
                return 0;
            }
        }
		/*受Android端影响,启用预览模式时,将整体网页所有标签设为不可编辑(代码在下面),同时为了确保同步,每次预览都会在Android端存储,因为js没法直接存储文件,所以将网页代码整体返回到Android端接收并保存到文件内,注意Android端应对得到的结果转码,因为得到的是unicode码,即使js已经转过了。*/
        /*返回整体网页*/
        function wholeHtml()
        {

            return unescape(document.getElementsByTagName('html')[0].outerHTML.toString());
        }

        /*添加链接*/
        function addHref(href)
        {
            var a=document.createElement("a");
            a.href=href;
            a.innerText=href;
            a.contentEditable=true;
            outDiv(a);
        }
		
		/*开启预览模式则不可编辑,此时可以验证链接*/
        /*可编辑设置*/
        function setEditAble(type)
        {
            if(!type)
            {
                getEdit("div", type);
                getEdit("img", type);
                getEdit("a", type);
            }
            else
            {
                getEdit("div", type);
                getEdit("img", type);
                getEdit("a", type);
            }
        }
        /*获取对象*/
        function getEdit(label, type)
        {
            var aa=document.getElementsByTagName(label);
            if(!type)
            {
                for( var a1=0; a1 < aa.length; a1++)
                {
                    aa[a1].contentEditable=false;
                }
            }
            else
            {
                for( var a1=0; a1 < aa.length; a1++)
                {
                    aa[a1].contentEditable=true;
                }
            }
        }
    </script>
</head>
<body>
	<!--只要一个基础div就行,甚至可以直接用body添加id代替-->
    <div id="main" contenteditable="true" style="margin-left: 30px; margin-right: 30px;"></div>
</body>
</html>

由于本人技术能力限制,无法很好的写出代码,只能提供一个简易的编辑。

对应Android端的简易介绍

Android端根据js代码设置对应内容。

webview建立

//根据id查找
webView=rootView.findViewById(R.id.makeArticle);
		//启用js支持
        webView.getSettings().setJavaScriptEnabled(true);
//下面有一堆设置内容,我也不太明白,大致是启用js支持、支持网络传输、支持html5格式存储、支持本地存储        webView.getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
		//网页处理,内部可根据网页开始、网页完成等状态做处响应
        webClient=new WebClient();
        webView.setWebViewClient(webClient);
        //允许操作文件
        webView.getSettings().setAllowFileAccessFromFileURLs(true);
        webView.getSettings().setAllowFileAccess(true);
        webView.getSettings().setAllowUniversalAccessFromFileURLs(true);
        webView.getSettings().setBlockNetworkLoads(false);
        webView.getSettings().setBlockNetworkImage(false);
        webView.getSettings().setDomStorageEnabled(true);
        webView.getSettings().setDatabaseEnabled(true);
        //添加js可调用的函数类,函数使用javascriptinterface注释,内部函数可以被js所调用
        webView.addJavascriptInterface(new MakeArticleWeb(getContext(), username, articleId, webView), "makeArticle");

使用Android调用js代码

//webview使用要在同一进程中
//基础格式
webView.loadUrl(url);//注意此调用异步加载,可能比后续loadUrl方法加载慢
//加载js代码
webView.loadUrl("javascript:js函数(参数)");//传入一个字符串,前面javascript固定,后面为要调用的函数名,注意当参数要传入字符串时,加上单引号。
//loaddata
webView.loadData(文本,文本格式(mimetype)(例如text/html为html文本),编码格式(例如UTF-8));

WebView的loadUrl异步加载问题

因loadUrl加载顺序不一致导致错误,因为webview使用必须在统一进程中,最好避免。如果实在需要,可以通过WebViewCilent中onPageFinsihed方法,在其中运行js可避免页面未完全加载导致js无法执行的异常。

示例:

 //网页监控
    public class WebClient extends WebViewClient
    {
		//页面加载完成调用该方法
        @Override
        public void onPageFinished(WebView view, String url)
        {
            super.onPageFinished(view, url);
            onCreateViewUpdate();
            //不为空,更新数据
            if(addList.size() > 0 && number <=30)
            {
                for (Bitmap value : addList.values()) {
                    String savePath=MakeUUID.makeUUID(username + "-" + articleId) + ".png";
                    saveThePhotoWithBitmap(value, savePath);
                    //此处调用了js,而且该js必须在页面完全加载后才能有效使用
                    webView.loadUrl(addTo(savePath, 0));
                }
            }
            //保存网页数据
            saveHtml();
        }

webview调用goback方法返回乱七八糟的东西(例如返回url)

单击webview中超链接进入其它网页再调用goback返回时可能出现问题,可通过修改默认的gobakc返回流程改善。

代码:

public String startUrl=thePath;//记录一开始的url,直接通过内部类写死,或在构造方法中定义
        private int pageNumber=0;//页面计数,判断当前网页是不是主网页
        
        //重写该方法,适配Android高版本
		@Override
        public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request)
        {
            System.out.println(startUrl);
            //如果页面不是主页面且当前url不是一开始的url,跳转会主界面
            if(!request.getUrl().equals(startUrl) && pageNumber !=0)
            {
                System.out.println(pageNumber);
                pageNumber=0;
                view.loadUrl(startUrl);//返回主界面
                return true;
            }
            else
            {
                pageNumber=1;
                //使用原流程
                return super.shouldOverrideUrlLoading(view, request);
            }
        }

最好把这些代码写在内部类中方便调用。

NSI(Windows-1252)

ANSI 是 Windows 95 及其之前的 Windows 系统中默认的字符集。

ANSI 也称为 Windows-1252。


重要提示

ANSI 和 ISO-8859-1 非常相似,唯一的不同是在 32 个字符上。

在 ANSI 中,从 128 到 159 的字符用于一些有用的字符,比如欧元符号。

在 ISO-8859-1 中,这些字符映射为在 HTML 中不起作用的控制字符。

许多 Web 开发者声明 ISO-8859-1,并使用这 32 个值,就像它们使用的是 Windows-1252。

由于这种常见的误解,当 ISO-8859-1 被声明时,浏览器将更改为 Windows-1252。这对以下文档类型都适用:HTML4、HTML5 和 XHTML。


ANSI 和 ASCII

ANSI 的第一部分(实体编号 0-127)是原来的 ASCII 字符集。它包含数字、大小写英文字母和一些特殊字符。

如需深入了解 ASCII,请查看完整的 ASCII 参考手册。


ANSI 字符集

字符编号实体名称描述
32空格(space)
!33感叹号(exclamation mark)
"34&quot;引号(quotation mark)
#35数字符号(number sign)
$36美元符号(dollar sign)
%37百分比符号(percent sign)
&38&amp;& 符号(ampersand)
'39撇号(apostrophe)
(40左括号(left parenthesis)
)41右括号(right parenthesis)
*42星号(asterisk)
+43加号(plus sign)
,44逗号(comma)
-45连字符(hyphen-minus)
.46句号(full stop)
/47斜线(solidus)
048数字 0(digit zero)
149数字 1(digit one)
250数字 2(digit two)
351数字 3(digit three)
452数字 4(digit four)
553数字 5(digit five)
654数字 6(digit six)
755数字 7(digit seven)
856数字 8(digit eight)
957数字 9(digit nine)
:58冒号(colon)
;59分号(semicolon)
<60&lt;小于号(less-than sign)
=61等于号(equals sign)
>62&gt;大于号(greater-than sign)
?63问号(question mark)
@64@ 符号(commercial at)
A65拉丁文大写字母 A
B66拉丁文大写字母 B
C67拉丁文大写字母 C
D68拉丁文大写字母 D
E69拉丁文大写字母 E
F70拉丁文大写字母 F
G71拉丁文大写字母 G
H72拉丁文大写字母 H
I73拉丁文大写字母 I
J74拉丁文大写字母 J
K75拉丁文大写字母 K
L76拉丁文大写字母 L
M77拉丁文大写字母 M
N78拉丁文大写字母 N
O79拉丁文大写字母 O
P80拉丁文大写字母 P
Q81拉丁文大写字母 Q
R82拉丁文大写字母 R
S83拉丁文大写字母 S
T84拉丁文大写字母 T
U85拉丁文大写字母 U
V86拉丁文大写字母 V
W87拉丁文大写字母 W
X88拉丁文大写字母 X
Y89拉丁文大写字母 Y
Z90拉丁文大写字母 Z
[91左方括号(left square bracket)
\92反斜线(reverse solidus)
]93右方括号(right square bracket)
^94插入符号(circumflex accent)
_95下划线(low line)
`96重音符(grave accent)
a97拉丁文小写字母 a
b98拉丁文小写字母 b
c99拉丁文小写字母 c
d100拉丁文小写字母 d
e101拉丁文小写字母 e
f102拉丁文小写字母 f
g103拉丁文小写字母 g
h104拉丁文小写字母 h
i105拉丁文小写字母 i
j106拉丁文小写字母 j
k107拉丁文小写字母 k
l108拉丁文小写字母 l
m109拉丁文小写字母 m
n110拉丁文小写字母 n
o111拉丁文小写字母 o
p112拉丁文小写字母 p
q113拉丁文小写字母 q
r114拉丁文小写字母 r
s115拉丁文小写字母 s
t116拉丁文小写字母 t
u117拉丁文小写字母 u
v118拉丁文小写字母 v
w119拉丁文小写字母 w
x120拉丁文小写字母 x
y121拉丁文小写字母 y
z122拉丁文小写字母 z
{123左花括号(left curly bracket)
|124竖线(vertical line)
}125右花括号(right curly bracket)
~126波浪线(tilde)
127未使用(NOT USED)
128&euro;欧元符号(euro sign)
129未使用(NOT USED)
?130&sbquo;下单引号(single low-9 quotation mark)
?131&fnof;带钩的拉丁文小写字母 f
?132&bdquo;下双引号(double low-9 quotation mark)
133&hellip;水平省略号(horizontal ellipsis)
?134&dagger;剑号(dagger)
?135&Dagger;双剑号(double dagger)
?136&circ;修饰字母抑扬音(modifier letter circumflex accent)
137&permil;千分比符号(per mille sign)
?138&Scaron;带有 caron 的拉丁文大写字母 S
?139&lsaquo;左单角引号(single left-pointing angle quotation mark)
?140&OElig;拉丁文大写连字 OE
141未使用(NOT USED)
?142&Zcaron;带有 caron 的拉丁文大写字母 Z
143未使用(NOT USED)
144未使用(NOT USED)
'145&lsquo;左单引号(left single quotation mark)
'146&rsquo;右单引号(right single quotation mark)
"147&ldquo;左双引号(left double quotation mark)
"148&rdquo;右双引号(right double quotation mark)
?149&bull;着重号(bullet)
150&ndash;短破折号/连字符(en dash)
151&mdash;长破折号(em dash)
?152&tilde;小波浪线(small tilde)
?153&trade;贸易标记符号(trade mark sign)
?154&scaron;带有 caron 的拉丁文小写字母 s
?155&rsaquo;右单角引号(single right-pointing angle quotation mark)
?156&oelig;拉丁文小写连字 oe
157未使用(NOT USED)
?158&zcaron;带有 caron 的拉丁文小写字母 z
?159&Yuml;带有分音符(diaeresis)的拉丁文大写字母 Y
160&nbsp;不换行空格(no-break space)
?161&iexcl;倒置感叹号(inverted exclamation mark)
162&cent;美分符号(cent sign)
163&pound;英镑符号(pound sign)
¤164&curren;货币符号(currency sign)
165&yen;日元符号(yen sign)
|166&brvbar;间断的竖杠(broken bar)
§167&sect;小节号(section sign)
¨168&uml;分音符号(diaeresis)
?169&copy;版权所有(copyright sign)
a170&ordf;阴性序数记号(feminine ordinal indicator)
?171&laquo;左双角引号(left-pointing double angle quotation mark)
?172&not;否定符号(not sign)
173&shy;软连字符(soft hyphen)
?174&reg;注册商标(registered sign)
ˉ175&macr;长音符号(macron)
°176&deg;度符号(degree sign)
±177&plusmn;加减号/正负号(plus-minus sign)
2178&sup2;上标 2(superscript two)
3179&sup3;上标 3(superscript three)
180&acute;尖音符号(acute accent)
μ181&micro;微米符号(micro sign)
?182&para;段落符号(pilcrow sign)
·183&middot;中间点(middle dot)
?184&cedil;变音符号(cedilla)
1185&sup1;上标 1(superscript one)
o186&ordm;阳性序数记号(masculine ordinal indicator)
?187&raquo;右双角引号(right-pointing double angle quotation mark)
?188&frac14;1/4 分数(vulgar fraction one quarter)
?189&frac12;1/2 分数(vulgar fraction one half)
?190&frac34;3/4 分数(vulgar fraction three quarters)
?191&iquest;倒置问号(inverted question mark)
à192&Agrave;带有重音符号(grave)的拉丁文大写字母 A
á193&Aacute;带有尖音符号(acute)的拉丁文大写字母 A
?194&Acirc;带有抑扬音符号(circumflex)的拉丁文大写字母 A
?195&Atilde;带有波浪线的拉丁文大写字母 A
?196&Auml;带有分音符(diaeresis)的拉丁文大写字母 A
?197&Aring;带有上圆圈的拉丁文大写字母 A
?198&AElig;拉丁文大写字母 AE
?199&Ccedil;带有变音符号(cedilla)的拉丁文大写字母 C
è200&Egrave;带有重音符号(grave)的拉丁文大写字母 E
é201&Eacute;带有尖音符号(acute)的拉丁文大写字母 E
ê202&Ecirc;带有抑扬符号(circumflex)的拉丁文大写字母 E
?203&Euml;带有分音符(diaeresis)的拉丁文大写字母 E
ì204&Igrave;带有重音符号(grave)的拉丁文大写字母 I
í205&Iacute;带有尖音符号(acute)的拉丁文大写字母 I
?206&Icirc;带有抑扬音符号(circumflex)的拉丁文大写字母 I
?207&Iuml;带有分音符(diaeresis)的拉丁文大写字母 I
D208&ETH;拉丁文大写字母 Eth
?209&Ntilde;带有波浪线的拉丁文大写字母 N
ò210&Ograve;带有重音符号(grave)的拉丁文大写字母 O
ó211&Oacute;带有尖音符号(acute)的拉丁文大写字母 O
?212&Ocirc;带有抑扬音符号(circumflex)的拉丁文大写字母 O
?213&Otilde;带有波浪线的拉丁文大写字母 O
?214&Ouml;带有分音符(diaeresis)的拉丁文大写字母 O
×215&times;乘号(multiplication sign)
?216&Oslash;带有删除线的拉丁文大写字母 O
ù217&Ugrave;带有重音符号(grave)的拉丁文大写字母 U
ú218&Uacute;带有尖音符号(acute)的拉丁文大写字母 U
?219&Ucirc;带有抑扬音符号(circumflex)的拉丁文大写字母 U
ü220&Uuml;带有分音符(diaeresis)的拉丁文大写字母 U
Y221&Yacute;带有尖音符号(acute)的拉丁文大写字母 Y
T222&THORN;拉丁文大写字母 Thorn
?223&szlig;拉丁文小写字母 sharp s
à224&agrave;带有重音符号(grave)的拉丁文小写字母 a
á225&aacute;带有尖音符号(acute)的拉丁文小写字母 a
a226&acirc;带有抑扬音符号(circumflex)的拉丁文小写字母 a
?227&atilde;带有波浪线的拉丁文小写字母 a
?228&auml;带有分音符(diaeresis)的拉丁文小写字母 a
?229&aring;带有上圆圈的拉丁文小写字母 a
?230&aelig;拉丁文小写字母 ae
?231&ccedil;带有变音符号(cedilla)的拉丁文小写字母 c
è232&egrave;带有重音符号(grave)的拉丁文小写字母 e
é233&eacute;带有尖音符号(acute)的拉丁文小写字母 e
ê234&ecirc;带有抑扬音符号(circumflex)的拉丁文小写字母 e
?235&euml;带有分音符(diaeresis)的拉丁文小写字母 e
ì236&igrave;带有重音符号(grave)的拉丁文小写字母 i
í237&iacute;带有尖音符号(acute)的拉丁文小写字母 i
?238&icirc;带有抑扬音符号(circumflex)的拉丁文小写字母 i
?239&iuml;带有分音符(diaeresis)的拉丁文小写字母 i
e240&eth;拉丁文小写字母 eth
?241&ntilde;带有波浪线的拉丁文小写字母 n
ò242&ograve;带有重音符号(grave)的拉丁文小写字母 o
ó243&oacute;带有尖音符号(acute)的拉丁文小写字母 o
?244&ocirc;带有抑扬音符号(circumflex)的拉丁文小写字母 o
?245&otilde;带有波浪线的拉丁文小写字母 o
?246&ouml;带有分音符(diaeresis)的拉丁文小写字母 o
÷247&divide;除号(division sign)
?248&oslash;带有删除线的拉丁文小写字母 o
ù249&ugrave;带有重音符号(grave)的拉丁文小写字母 u
ú250&uacute;带有尖音符号(acute)的拉丁文小写字母 u
?251&ucirc;带有抑扬音符号(circumflex)的拉丁文小写字母 u
ü252&uuml;带有分音符(diaeresis)的拉丁文小写字母 u
y253&yacute;带有尖音符号(acute)的拉丁文小写字母 y
t254&thorn;拉丁文小写字母 thorn
?255&yuml;带有分音符(diaeresis)的拉丁文小写字母 y

ANSI 控制字符

ANSI 控制字符(00-31,加上 127)最初被设计用来控制诸如打印机和磁带驱动器之类的硬件设备。

控制字符(除了水平制表符、换行、回车之外)在 HTML 文档中不起任何作用。

字符编号描述
NUL00空字符(null character)
SOH01标题开始(start of header)
STX02正文开始(start of text)
ETX03正文结束(end of text)
EOT04传输结束(end of transmission)
ENQ05请求(enquiry)
ACK06收到通知/响应(acknowledge)
BEL07响铃(bell)
BS08退格(backspace)
HT09水平制表符(horizontal tab)
LF10换行(line feed)
VT11垂直制表符(vertical tab)
FF12换页(form feed)
CR13回车(carriage return)
SO14不用切换(shift out)
SI15启用切换(shift in)
DLE16数据链路转义(data link escape)
DC117设备控制 1(device control 1)
DC218设备控制 2(device control 2)
DC319设备控制 3(device control 3)
DC420设备控制 4(device control 4)
NAK21拒绝接收/无响应(negative acknowledge)
SYN22同步空闲(synchronize)
ETB23传输块结束(end transmission block)
CAN24取消(cancel)
EM25已到介质末端/介质存储已满(end of medium)
SUB26替补/替换(substitute)
ESC27溢出/逃离/取消(escape)
FS28文件分隔符(file separator)
GS29组分隔符(group separator)
RS30记录分隔符(record separator)
US31单元分隔符(unit separator)
DEL127删除(delete)

如您还有不明白的可以在下面与我留言或是与我探讨QQ群308855039,我们一起飞!

节课我们讲了关于事件的基本知识,主要包括事件对象和它的一些应用。从这节课开始我们学习2个更加高级的知识。

默认行为

当我们打开一个空白页面的时候,右键点击页面会弹出来一个菜单——当然,实际上我们从来没有通过JS写过这么一个菜单,而是浏览器自带的功能。这种浏览器本身自己带的功能和事件我们将它称之为默认行为。

在这之前,要为大家介绍一个新的事件——oncontextmenu,代表的就是当用户点击右键呼出菜单的事件。现在我们用oncontextmenu来做一些事情。值得一提的是,oncontextmenu是可以有返回值的,如果我们return一个false的话会发生什么呢?

<html>
 <head> 
 <meta charset="utf-8" /> 
 <title>无标题文档</title> 
 <script>document.oncontextmenu=function (){
 return false; //阻止默认事件};</script> 
 </head> 
 <body> 
 </body>
</html>

大家可以自己尝试一下,如果我们return一个false值回去的话,右键菜单将会被阻止弹出。在系统默认事件中return false的话可以有效地阻止该默认事件。

当然,阻止右键菜单并不是我们最终的目的,我们最终的目的是为了能弹出自定义右键菜单,我们现在来看一下,如何在屏蔽右键菜单的基础之上,再弹出一个自己的菜单。

<html>
 <head> 
 <meta charset="utf-8" /> 
 <title>无标题文档</title> 
 <style>
 * {margin:0; padding:0; list-style:none;}
 #div1 {position:absolute; width:80px; background:#CCC; border:1px solid black; display:none;}
 </style> 
 <script>
 document.oncontextmenu=function (ev)
 {
 var oEvent=ev||event;
 var oDiv=document.getElementById('div1');
 oDiv.style.display='block';
 oDiv.style.left=oEvent.clientX+'px';
 oDiv.style.top=oEvent.clientY+'px';
 return false;
 };
 document.onclick=function ()
 {
 var oDiv=document.getElementById('div1');
 oDiv.style.display='none';
 };
 </script> 
 </head> 
 <body> 
 <div id="div1"> 
 <ul> 
 <li>aaa</li>
 <li>bbb</li> 
 <li>ccc</li> 
 <li>ddd</li> 
 </ul> 
 </div> 
 </body>
</html>

效果如下:

这个程序里面,我们除了用return false阻止了默认的系统菜单外,还自定义了一个div,其位置为鼠标点击的位置,同时添加了一个点击页面其他位置时,div消失的效果——这样就完成了一个自定义右键菜单。

到目前为止,我们学习了一下阻止默认行为最简单的一种应用。现在我们再来看一个默认行为的另一种应用——大家平时在表单里面会经常需要用户去填一些用户名,密码,邮箱,qq号等信息。当我们输入qq号时,我们希望用户只能输入数字,而不能输入字母和符号,这应该怎么做到呢?这里我们需要使用上节课提过的onkeydown事件。

<html>
 <head> 
 <meta charset="utf-8" /> 
 <title>无标题文档</title> 
 <script>window.onload=function (){
 var oTxt=document.getElementById('txt1');
 oTxt.onkeydown=function ()
 {
 var oEvent=ev||event;
 //alert(oEvent.keyCode);
 //0- 48
 //9- 57
 //如果 用户按的 不是退格 并且 也不是数字if(oEvent.keyCode!=8 && (oEvent.keyCode<48 || oEvent.keyCode>57))
 {
 return false;
 }
 };
 };
</script> 
 </head> 
 <body> 
 <input type="text" id="txt1" /> 
 </body>
</html>

值得一提的是,如果我们将onkeydown的return值也设为false的话,我们将无法在页面用键盘进行任何输入——实际上键盘输入本身也是系统的一个默认行为,因此可以用return false将它阻止掉。所以其实这个程序的逻辑很简单——通过keyCode判断输入的字符是否为数字,如果不是数字的话,return false阻止其输入即可(注意不要把keyCode为8的退格键阻止掉)。实际上来说默认行为的各种应用是非常广的,我们这里只举了两个例子,其他的大家可以自己去发掘。

拖拽

拖拽的含义大家应该都明白,这里我们先从它的原理开始说起。首先我们先来看一个简单的布局:

<html>
 <head> 
 <meta charset="utf-8" /> 
 <title>无标题文档</title> 
 <style>#div1 {width:200px; height:200px; background:red; position:absolute;}</style> 
 <script>
 window.onload=function ()
 {
 var oDiv=document.getElementById('div1');
 var disX=0;
 var disY=0;
 oDiv.onmousedown=function (ev)
 {
 var oEvent=ev||event;
 disX=oEvent.clientX-oDiv.offsetLeft;
 disY=oEvent.clientY-oDiv.offsetTop;
 document.onmousemove=function (ev)
 {
 var oEvent=ev||event;
 oDiv.style.left=oEvent.clientX-disX+'px';
 oDiv.style.top=oEvent.clientY-disY+'px';
 };
 document.onmouseup=function ()
 {
 document.onmousemove=null;
 document.onmouseup=null;
 };
 return false; //这里是为了阻止火狐浏览器的一个小bug。
 };
 };
 </script> 
 </head> 
 <body> 
 <div id="div1"></div> 
 </body>
</html>

大家随便在电脑上拖拽一个东西就可以发现,拖拽的一个性质是:在拖拽时,鼠标和元素右上角的距离是保持不变的。距离的求法也很简单:用鼠标的位置减去元素右上角的位置即可。

然后对于拖拽来说,大家可以很容易联想到它涉及到的几个JS事件:鼠标按下,鼠标移动和鼠标抬起。通过这些东西的组合,我们就可以轻松写出一个拖拽了(注意1.onmousemove事件需要添加为在onmousedown事件触发后才会被触发的事件2.onmousemove和onmouseup是添加给document而不是div1的事件,原因在于防止鼠标移出div或屏幕)。

效果如下:

现在我们就拥有了一个没有任何bug的拖拽,但虽然没有程序上的bug,但是有一些用户体验不太好的地方,比如,当用户将拖拽框拖出屏幕后可能就找不到拖拽框了。现在我们要尝试解决这个问题:

<html>
 <head> 
 <meta charset="utf-8" /> 
 <title>无标题文档</title> 
 <style>
 #div1 {width:200px; height:200px; background:red; position:absolute;}
 </style> 
 <script>
 window.onload=function ()
 {
 var oDiv=document.getElementById('div1');
 var disX=0;
 var disY=0;
 oDiv.onmousedown=function (ev)
 {
 var oEvent=ev||event;
 disX=oEvent.clientX-oDiv.offsetLeft;
 disY=oEvent.clientY-oDiv.offsetTop;
 document.onmousemove=function (ev)
 {
 var oEvent=ev||event;
 var l=oEvent.clientX-disX;
 var t=oEvent.clientY-disY;
 if(l<0)
 {
 l=0;
 }
 else if(l>document.documentElement.clientWidth-oDiv.offsetWidth)
 {
 l=document.documentElement.clientWidth-oDiv.offsetWidth;
 }
 if(t<0)
 {
 t=0;
 }
 else if(t>document.documentElement.clientHeight-oDiv.offsetHeight)
 {
 t=document.documentElement.clientHeight-oDiv.offsetHeight;
 }
 oDiv.style.left=l+'px';
 oDiv.style.top=t+'px';
 };
 document.onmouseup=function ()
 {
 document.onmousemove=null;
 document.onmouseup=null;
 };
 return false;
 };
 };</script> 
 </head> 
 <body> 
 <div id="div1"></div> 
 </body>
</html>

我们用l和t来储存div的位置,当二者小于0的时候,将其变为0;当二者大于可视区宽高-元素本身宽高的时候,将其变为可视区宽高-元素本身宽高。这样就完成了一个完美的拖拽。

以上,我们就把拖拽常一些问题简单的讲解一下,后面我们还会针对拖拽做更多的应用。