以往我们插入、移动DOM元素经常是使用appendChild和insertBefore方法。
appendChild:在父级元素内追加新元素。 insertBefore:在父级元素内的某个元素之前插入新元素。
但是这两个方法的参数只能接收元素对象,不能使用字符形式的html代码,而且它们插入元素的位置也不够灵活。我们可以使用insertAdjacentHTML方法来更方便的插入元素。
insertAdjacentHTML可以将字符串形式的html代码(需要能解析为DOM元素)解析为一个节点,并将其追加到指定元素的指定位置。
insertAdjacentHTML方法的语法如下:
element.insertAdjacentHTML(position, text);
position参数有以下四个值(都是字符串形式):
beforebegin:在元素的开始位置之前插入。 beforeend:在元素的结束位置之前插入。 afterbegin:在元素的开始位置之后插入。 afterend:在元素的结束位置之后插入。
text参数则是字符串形式的html代码。
根据position参数,我们可以将新元素插入到到指定元素的四个位置:
示例:
<div id="a"> <div></div> </div> <script type="text/javascript" defer> var a=document.querySelector("#a"); a.insertAdjacentHTML("afterbegin","<a href='' >xxx</a"); </script>
结果如下:
<div id="a"> <a href="">xxx</a> <div></div> </div>
insertAdjacentHTML方法的兼容性表现良好,主流浏览器均已支持。我们也可以如下语句来检查浏览器是否支持方法:
document.documentElement.insertAdjacentHTML
此外,由于insertAdjacentHTML是根据位置插入元素的,因此它不能把新元素插入到img、input等单标签元素里(想这么做的人才是有毛病吧)。
相关文档:《https://developer.mozilla.org/zh-CN/docs/Web/API/Element/insertAdjacentHTML》
ps:与insertAdjacentHTML系列“同一系列”的还有insertAdjacentElement方法和insertAdjacentText方法。
insertAdjacentElement方法除了第二个参数是DOM节点(不能是字符串形式)外和insertAdjacentHTML方法都一样。
insertAdjacentText方法则只接收字符串格式的参数,并输出为字符串。其他地方也和insertAdjacentHTML方法一样。
使用js的insertAdjacentHTML方法插入元素
今天fgo开了圣诞活动,bilibili上的活动页面上下着雪,于是我把代码扒了下来。
这个下雪的js依赖jquery,实际使用中感觉效果一般←_←
<body style="background: #000;"> <canvas class="snow-canvas" speed="1" interaction="true" size="8" count="40" start-color="rgba(253,252,251,1)" end-color="rgba(251,252,253,0.3)" opacity="0.00001" wind-power="2" image="false"></canvas> <script src="//apps.bdimg.com/libs/jquery/1.9.0/jquery.js"></script> <script src="//static.biligame.net/fgo/event_santa/pc/js/snow.js?v=d659f803.js"></script> <script> $(".snow-canvas").snow(); </script> <style> .snow-canvas { position: fixed; display: block; width: 100%; height: 100%; top: 0; left: 0; pointer-events: none; } </style> </body>
demo如下:
效果不是很好……不过如果像活动页面那样,有背景图片什么的,瑕疵应该不会很明显。
bilibili上使用的一个下雪效果
刚才在懒人之家找了一个JavaScript做的全国省市县三级联动的下拉选择插件,记录一下。
这个js文件的日期是2014年,使用方法如下:
<select id="s_province" name="s_province"></select> <select id="s_city" name="s_city" ></select> <select id="s_county" name="s_county"></select> <script src="form/area.js" type="text/javascript"></script> <script type="text/javascript">_init_area();</script>
JavaScript实现全国三级城市联动select选择
创建表单一直是令我头疼的问题。对于复杂些的表单,使用可视化工具来制作明显更有效率。
JotForm就是一个在线创建表单的网站,使用拖拽操作,所见即所得。我们只需要免费创建一个账号,就可以使用JotForm来创建表单了。
JotForm不使用table标签做的布局,而是使用更加简洁的div、ul、li等标签,还会自动加上label。
设计界面如下:
同时每个控件都可以点击右上角的齿轮图标进入进阶设置:
进阶设置是很有用的,我们可以在进阶设置里设置输入框长度、预设文字、添加辅助说明、设置复选框列数等。
虽然在线设计的表单在布局上可能难以完美实现我们的需求,不过它帮我们完成了最繁琐的部分,我们接下来可以再按照自己的需求调整它,工作量仍然小了许多。
Read More →
使用JotForm在线创建表单
本文要做的事情是,用户通过file控件选择一个文件,之后我们使用FileReader将其转换为base64编码,并储存在LocalStorage里。
如下代码,在用户选择一张图片时,程序会将图片以base64编码保存到LocalStorage里,然后把这张图作为网页的背景图片。
<input type="file" name="img"> <br> <input type="button" name="clearMyBG" value="清除我的设置"> <script> // 尝试读取localStorage中存储的背景图片,如果有就设置 var myBGStorage = localStorage.getItem("myBG"); if (myBGStorage) { document.body.style.backgroundImage="url("+myBGStorage+")"; } // 将选择的文件储存在localStorage里 document.querySelector("input[name=img]").addEventListener("change",function(){ if (!/image\/\w/.test(this.files[0].type)) { alert("请确保文件为图像类型"); return false; } setMyBG(this.files[0]); }) //清除存储的背景图片 document.querySelector("input[name=clearMyBG]").addEventListener("click",function(){ localStorage.removeItem("myBG"); alert("设置已清除"); location.reload(); }) //转换、存储和设置背景图片 function setMyBG (imgfile){ var fileReader = new FileReader(); fileReader.readAsDataURL(imgfile); fileReader.onload=function(){ var result = this.result; document.body.style.backgroundImage="url("+result+")"; try { localStorage.setItem("myBG", result); }catch (e) { console.log("Storage failed: " + e); } } } </script>
如下图,是localStorage中存储的键值对。注意localStorage的值都会被转换成string类型的。
相关资料:
FileReader localStorage
有一个检测localStorage容量上限的工具:
Test of localStorage
它会在你的localStorage里存储数据,直到塞满为止。chrome约为5M。据说opera和firefox可以自己调整限制,厉害了。
Read More →
使用FileReader读取并将文件存储在localStorage中
我刚才发了一篇文章:《WordPress绑定多个域名的方法》,使得“saber.我爱你”和“saber.love”都能访问本站,并且域名是分开的,“saber.我爱你”进来后,网站所有链接都是“saber.我爱你”开头的,“saber.love”亦然。
但是这样可能会使搜索引擎认为这两个域名建立的是镜像站点,可能会导致权重分散等不利后果,所以还是做301重定向比较稳妥。
由于301重定向性质所致,我需要把《WordPress绑定多个域名的方法》里添加的代码去掉,不然这会导致网站有两套url,就达不到301重定向的目的。
做301重定向首先要确定我们最后想要使用的是哪个域名(我是用的是www.saber.love),到后台常规设置里把“WordPress地址(URL)”和“站点地址(URL)”都改成这个域名。
之后在根目录的wp-blog-header.php的开头,加入以下代码:
// 301重定向到www.sbaer.love if (strtolower($_SERVER['SERVER_NAME']) != 'www.saber.love') { $URIRedirect=$_SERVER['REQUEST_URI']; if(strtolower($URIRedirect)=="/index.php") { $URIRedirect="/"; } header('HTTP/1.1 301 Moved Permanently'); header('Location:http://www.saber.love'.$URIRedirect); exit(); }
这样,“saber.love”、“www.saber.我爱你”、“saber.我爱你”都会被301 永久重定向到“www.saber.love”了。
WordPress设置301重定向
之前我的博客是“saber.我爱你”域名,最近注册了“saber.love”,我想给我的博客同时启用这两个域名。
不过我遇到了一个问题:虽然saber.love可以解析到我的网站上,但是WordPress后台并没有绑定多个域名的功能。
WordPress的设置里有WP_SITEURL和WP_HOME,不管通过哪个域名进来,网站页面里所有的链接(如文章链接、后台路径等)的域名用的都是WP_SITEURL和WP_HOME里的设置。
我后台设置的WP_SITEURL和WP_HOME原本都是“http://www.saber.我爱你”,当我通过“saber.love”进入网站时,页面上所有链接依旧都是“http://www.saber.我爱你”开头的,点击任何链接就都又转到“saber.我爱你”了。
不过我们可以通过wp-config.php来动态设置WP_SITEURL和WP_HOME,可以真正的使用多域名打开网站,所有页面的链接都是对应的域名。
找到wp-config.php最后一行:
require_once(ABSPATH . 'wp-settings.php');
在它前面添加动态设置WP_SITEURL和WP_HOME的代码就可以了:
$current_sitename=$_SERVER['HTTP_HOST']; if ($current_sitename=="saber.love"||$current_sitename=="www.saber.love") { define("WP_SITEURL", "http://www.saber.love"); define("WP_HOME", "http://www.saber.love"); }else if ($current_sitename=="saber.love"||$current_sitename=="www.saber.love") { define("WP_SITEURL", "http://www.saber.love"); define("WP_HOME", "http://www.saber.love"); }
这样设置后,网站所有页面均可以用我们设置的多个域名访问,包括后台操作都是完全正常的。
ps:上面代码中设置的WP_SITEURL和WP_HOME都会访问网站的根目录,实际上也可根据需要设置成任意层级的目录。
WordPress绑定多个域名的方法
今天发现了window.URL.createObjectURL这个东西,非常的好用啊。
语法如下:
objectURL = URL.createObjectURL(blob || file);
URL.createObjectURL()方法会根据传入的参数创建一个指向该参数对象的URL. 这个URL的生命仅存在于它被创建的这个文档里. 新的对象URL指向执行的File对象或者是Blob对象。
我们可以使用URL.createObjectURL()方法给file对象或blob对象创建一个url来使用它。
blob对象产生的url格式如下:
blob:null/c694da24-ecd6-48ee-9a21-4c2979e6ef84
在处理本地数据时,它是很有用的,比如说上传前预览。
下面代码展示了一个表单,我们想用它上传图片和声音文件。
<form id="form1"> <input type="file" name="img"> <input type="file" name="audio"> </form> <img src="" id="preview" width="300"> <audio autoplay="autoplay" controls="controls" src=""></audio> <script> document.querySelector("#form1 input[name=img]").addEventListener("change",function(){ var img=this.files[0]; var imgUrl=window.URL.createObjectURL(img); document.querySelector("#preview").src=imgUrl; }) document.querySelector("#form1 input[name=audio]").addEventListener("change",function(){ var audio=this.files[0]; var audioUrl=window.URL.createObjectURL(audio); document.querySelector("audio").src=audioUrl; }) </script>
在页面上有一个空的img元素和audio元素,在用户选择了图片或音乐后,该图片或音乐会直接显示/播放。是不是很方便呢?
你可以在下面直接操作:(第一个按钮传图片,第二个按钮传音乐)
虽然blob对象是个很方便的东西,但需要注意的是,当页面被关闭时,这个页面上生成的blob对象会被浏览器自动释放(清空)(但刷新页面不会清空blob对象),给它创建的url也就失效了。
此外有个URL.revokeObjectURL方法,用于释放blob对象的url。语法如下:
window.URL.revokeObjectURL(objectURL);
更加详细的信息可以参考此处。
使用URL.createObjectURL创建url对象
昨天圣诞节,本站页面也改成了圣诞ver~我还是很喜欢圣诞ver的,截图留念一下。
Read More →
圣诞节页面效果
dedecms里默认的文章标题长度是60,如果添加文章时标题长度超出60,就会被截断,影响恶劣。
假设我要修改dedecms的文章标题长度为200,那么需要两个步骤:
1.到“系统设置”→“系统基本参数”→“其它选项”,修改“文档标题最大长度”选项为200。
2.到“系统设置”→“SQL命令行工具”中执行下面Sql语句:
alter table #@__archives change title title varchar(200)
这样就OK了。
需要注意的是,dedecms里设置的这个长度并不是按字数,而是按PHP里的字节数。在PHP中,GBK系列编码里的一个中文占据2个字节的长度;UTF-8编码里的一个中文占据3个字节的长度。英文字符则始终是一个长度。