saber酱的抱枕

转卖“saber.我爱你”域名和“lovesaber.com”域名

@saber4天前

05/19
14:05
学习

抓取所有文章页并生成网站地图的JavaScript代码

我之前的sitemap文件里有很多链接是错误的,早期的时候本站页面还没有启用伪静态,那时候文章网址后面没带.html。今天我写了个代码来自动抓取本站的所有文章,并生成sitemap字符。

这个代码可能仅适用本站使用的clearision模板。用在其他模板或其他类型的网站的话可能就需要略作修改了。
Read More →

抓取所有文章页并生成网站地图的JavaScript代码

@saber4天前

05/19
13:46
学习

使用css3动画制作网页底部走动的桌宠

在pc设备上,我的博客底部会有一个saber桌宠走来走去~这个效果大概是三年前博客建立不久就做了,但是当时是用JavaScript的定时器来改变桌宠的位置的。今天我把它用css3动画重做了一遍,效果基本上维持原样。

这次我依然用到了JavaScript,不过JavaScript已经不直接移动桌宠的位置了,它的作用是动态创建animation动画规则,这样桌宠的移动就由css3动画控制了。

其实我改成css3动画本来是想降低我的博客在浏览器里的资源占用,但是改了之后发现效果不明显,看来占用资源大头的另有原因,这个以后再查吧。
Read More →

使用css3动画制作网页底部走动的桌宠

@saber3周前

05/3
08:00
学习

使用html5的document.hidden属性查询页面是否可见

document.hidden是HTML5里一个新增的属性,它会返回一个布尔值,用来指示当前页面(标签页)是否可见。

比如说你正在看这个页面,那么document.hidden就会返回true。如果你切换到别的标签页去了,或者最小化了浏览器之类的情况,document.hidden就会返回false。

手动检测document.hidden灵活性很差,我们可以为document添加visibilitychange事件来监听页面可见性的变化。

document.addEventListener("visibilitychange", function (argument) {
	if (document.hidden) {
		alert("看不见看不见");
	}else{
		alert("二狗子你又回来了");
	}
});

当然,上面的代码只是个示例,实际使用中不要照搬。因为当用户切换到其他页面时,这个页面就会弹窗“看不见看不见”。之后点掉弹窗,你就等于又切换回来了,这时候“二狗子你又回来了”百分之百触发←_←

visibilitychange的兼容性目前应该问题不大了,毕竟document.hidden都出现至少5年了,相关事件监听应该早就跟上了。
当然IE8是不要想了,它连document.msHidden都不支持。

三大浏览器的私有属性和方法示例如下(虽然对于不支持的老IE还是没办法):

var visibilityChange;
if (typeof document.hidden !== "undefined") {
	visibilityChange = "visibilitychange";
} else if (typeof document.mozHidden !== "undefined") {
	visibilityChange = "mozvisibilitychange";
} else if (typeof document.msHidden !== "undefined") {
	visibilityChange = "msvisibilitychange";
} else if (typeof document.webkitHidden !== "undefined") {
	visibilityChange = "webkitvisibilitychange";
}
document.addEventListener(visibilityChange, function() {
	// code...
}, false);

使用html5的document.hidden属性查询页面是否可见

@saber3周前

05/2
14:41
学习

使用toBlob()方法将canvas对象转换为Blob对象

前情提要:
《在JavaScript中创建Blob对象》
《使用canvas将图片转换为base64编码》

之前的这两篇文章都是为在网页上下载文件而服务的。Blob对象可以通过URL.createObjectURL(blob)方法来生成一个blob协议的url,而canvas可以通过canvas.toDataURL()来生成一个base64编码的url。这两种url都可以用a标签的download属性来下载。

注意:
将数据(包括canvas对象)转换为blob时,会受到跨域限制。
canvas酱图片转换为base64编码时也会受到跨域限制。
使用a标签下载文件时,在firefox里会受到跨域限制。

之前我没发现canvas对象是可以转换成Blob对象的,今天才知道有一个HTMLCanvasElement.toBlob()方法可以做到。

语法如下:

canvas.toBlob(callback, mimeType, qualityArgument);

说人话:

canvas.toBlob(function(blob) {
	// code...
},"image/jpeg", 0.8);

toBlob方法内有一个回调函数,其参数就是canvas对象转换后的生成的blob对象;
如果缺少mimeType参数,则默认为png格式。

相比使用base64编码的url,blob格式的url更加简洁,我喜欢后者。不过base64编码其实储存的是文件本身,它方便重复使用。而blob对象则在刷新页面后就没了,blob格式的url也就不能重用了。

如下代码,先加载一个图片,然后将其绘制在canvas里,之后将canvas元素转化为blob对象,再用一个a标签来做下载功能。

var Img = new Image();
Img.src = "58319482.jpg";
Img.onload = function() {
	var canvas = document.createElement("canvas");
	canvas.width = Img.width;
	canvas.height = Img.height;
	canvas.getContext("2d").drawImage(Img, 0, 0, Img.width, Img.height); //将图片绘制到canvas中
	canvas.toBlob(function(blob) {
		var downloadA = document.createElement("a");
		document.body.appendChild(downloadA);
		downloadA.style.display = "none";
		downloadA.setAttribute("download", "download.jpg");
		downloadA.setAttribute("href", URL.createObjectURL(blob));
		downloadA.click();
	}, "image/jpeg", 0.8);
};

使用toBlob()方法将canvas对象转换为Blob对象

@saber3周前

04/29
14:35
学习

JavaScript选中文字

说到使用JavaScript选中文字,可能用得最多的场景是全选input输入框里面的文字,这个对input元素使用select()方法即可。

但是对于其他元素里的文字,select()方法无效,那么如何选中呢?浏览器中有Selection对象,我们可以通过Selection对象获取用户选择的区域,或者自动的去选择指定内容。

下面的代码是简单的示例,实现了选择某元素内的文本的功能。

function selectText(e) {
    if (document.selection) {	//ie
        var range = document.body.createTextRange();
        range.moveToElementText(e);
        range.select();
    } else if (window.getSelection) {	//chrome firefox
        var range = document.createRange();
        range.selectNode(e);
        window.getSelection().removeAllRanges();
        window.getSelection().addRange(range);
    }
}

selectText(document.querySelector("p"));

另外可在选择后使用document.execCommand来自动复制选择的内容:

document.execCommand('copy');

但要注意的是这个命令只能被用户手动操作来触发。


可参阅MDN文档

JavaScript选中文字

@saber3周前

04/29
14:03
学习

JavaScript获取浏览器使用的语言

有时候,我们可能需要为不同国家的用户提供个性化服务,那么在浏览器里,我们可以使用JavaScript来获取UA里的语言设置,以此来判断用户的语言环境。

代码如下:

var language = navigator.language || navigator.browserLanguage;
if (language.indexOf('zh') > -1) {
	language = "chinese"; //中文
} else if (language.indexOf('en') > -1) {
	language = "english"; //英文
} else if (language.indexOf('ja') > -1) {
	language = "japanese"; //日文
} else if (language.indexOf('nl') > -1) {
	language = "dutch"; //荷兰语
} else if (language.indexOf('fr') > -1) {
	language = "french"; //法语
} else if (language.indexOf('de') > -1) {
	language = "german"; //德语
} else if (language.indexOf('it') > -1) {
	language = "italian"; //意大利
} else if (language.indexOf('pt') > -1) {
	language = "portuguese"; //葡萄牙
} else if (language.indexOf('es') > -1) {
	language = "Spanish"; //西班牙
} else if (language.indexOf('sv') > -1) {
	language = "swedish"; //瑞典
}

navigator.language是chrome和firefox所拥有的属性,navigator.browserLanguage则是IE独有。默认的话获取到的值是和操作系统的语言保持一致的,不过用户也可以在浏览器内自行更改。

JavaScript获取浏览器使用的语言

@saber4周前

04/26
17:05
学习

JavaScript中阻止事件冒泡

JavaScript中的event.stopPropagation方法用于阻止事件冒泡,这样该事件不会继续向上级元素传递。

不过今天我想讲的是event.stopImmediatePropagation,它除了具有event.stopPropagation方法的阻止事件冒泡的功能外,还有另一个功能,就是会中止执行在它后面添加/执行的同类型事件。也就是说干完我这件事件,后面的同类型的事情就都不用干了。

示例:

document.body.addEventListener("click", function () {
	console.log("1");
});
document.body.addEventListener("click", function (ev) {
	// 在它后面添加的同类型函数不会再执行了,但是早于它添加的函数还是会执行
	ev.stopImmediatePropagation();
	console.log("2");
});
document.body.addEventListener("click", function () {
	console.log("3");
});

本来,由addEventListener添加的同类型事件会按照添加的顺序依次执行。这个例子中就是点击页面会依次输出1、2、3。

在2中加了ev.stopImmediatePropagation()之后,第二个添加的事件执行完,后面添加的同类型事件就不会执行了——不会输出3了。

注意:

1.stopImmediatePropagation方法会阻止的是同类型的,比如在click事件里执行了stopImmediatePropagation方法,并不能阻止在其后添加的其他类型的事件。
2.在执行stopImmediatePropagation的事件里,在stopImmediatePropagation后面的代码依然会执行。(如上例会继续输出2)。

ps:jQuery有个event.isImmediatePropagationStopped方法来检测该事件上是否设置了stopImmediatePropagation方法。但是原生JavaScript里好像没自带这个检测的方法。

JavaScript中阻止事件冒泡

@saber1月前

04/20
08:00
学习

JavaScript中的call()和apply()

JavaScript中每个函数都有call()和apply()方法(呼叫和申请 XD),这两个方法都是为了改变函数的this值。简单地说,如果一个对象没有某个方法,但是其他人有,那么就可以用call()或apply()来借用这个方法。

call()和apply()方法的参数都分为两个部分,第一个参数是要作为this的对象,其他参数是要借用的函数的参数。

如果第一个参数为null或缺省,就会把this指向全局对象(window)。

如下代码:

var a={
	name:"saber",
	say:function () {
		console.log(this.name);
	}
},
	b={
		name:"我是2b"
	};
a.say.call(b);

a有个say()方法,可以说出自己的名字,但b没有这个方法。我们用a的say方法来call(呼叫)b,说我也不是谦虚,还是你来吧。这样a的this就变成了b,this.name也就是b的name了。

操作NodeList时常常借助数组的方法,代码如下:

var img=document.querySelectorAll("img");
[].slice.call(img,0,5);
[].forEach.call(img,function (no) {
	console.log(no.src);
});
//[]相当于Array.prototype的简写

Read More →

JavaScript中的call()和apply()

@saber1月前

04/19
11:24
学习

JavaScript的闭包

闭包是指有权访问另一个函数作用域中的变量的函数。

不用闭包的话,在函数外操作函数内的局部变量是不行的,因为局部变量的作用域只在函数内。我们可以通过闭包解决这个问题。

创建闭包的常见方式,就是在一个函数内部创建另一个函数,这样,被创建的函数就可以访问这部分作用域。

从形式上来说,给外部变量返回一个function,就形成了一个闭包。

function b() {
	var a=1;
	return function () {
		console.log(a);
	};
}
var c=b();

c(); // 1

上面代码是给外部变量c赋值了一个函数,可以输出函数b里面的变量a。

除了用return创建函数,我们也可以直接赋值。

如下代码,函数内有一个局部变量a,我们通过闭包,可以在函数外设置和读取a的值。

var set,get;

(function () {
	var a=0;
	set=function (s) {
		a=s;
		console.log(a);
	};
	get=function () {
		console.log(a);
	};
})();

set(2);
get();

使用闭包需要注意的问题有:
内存占用增加
this的指向。

JavaScript的闭包

@saber1月前

04/18
15:46
学习

使用X-Frame-Options防止网页被Frame

如果想要防止自己的网页被别人用iframe给引用过去,可以在Header里设定X-Frame-Options。

X-Frame-Options有3个值:
DENY:浏览器拒绝当前页面加载任何Frame页面
SAMEORIGIN:frame页面的地址只能为同源域名下的页面
ALLOW-FROM:origin为允许frame加载的页面地址

pixiv的网页对于iframe就做了同源设置,如果在其他网站里试图将iframe的src设定为p站的url,是无效的。控制台报错信息如下:

使用X-Frame-Options防止网页被Frame

使用X-Frame-Options防止网页被Frame