顯示具有 JavaScript 標籤的文章。 顯示所有文章
顯示具有 JavaScript 標籤的文章。 顯示所有文章

JavaScript 和 jQuery 混用

JavaScript window.onload 和 jQuery $(document).ready() 的差異

在撰寫頁面的 JavaScript 或 jQuery 時,通常會利用 window.onload 事件或 $(document).ready() 事件來確保 DOM 完全載入,不過兩者仍有以下差異。


window.onload 會等網頁的全部內容,包括圖片,CSS及 <iframe> 等外部內容都載入後才會觸發,但 $(document).ready() 在 Document Object Model (DOM) 載入後就會觸發,所以順序上$(document).ready() 會比 window.onload 先執行。


window.onload 是 JavaScript 的原生事件,而 $(document).ready() 是 jQuery 的事件(其實是透過監聽 JavaScript 的 DOMContentLoaded 事件來實現)。


window.onload 的用法如下:

window.onload = function() {

  // console.log("window loaded")

};


$(document).ready() 的用法如下:

$(document).ready(function() {

  console.log("document ready");

});

// 也可簡寫成

$(function() {

  console.log("document ready");

});



jQuery 轉為 JavaScript: var jsObject=$("#id").get(0);

JavaScript 轉為 jQuery: var $object=$(document.getElementById("id"));



JavaScript 呼叫 jQuery 方法:

function getResult(){

    $().getFuc();

};

$(function(){

    $.fn.getFuc=function(){

        alert("1111111111111");

    }

});


 jQuery 呼叫 JavaScript 方法:

$("#button3").click(function () {

        getFuc();

    });

function getFuc(){

       alert("111111");

}



在 HTML 中使用 onclick 方法與 jQuery 的事件監聽有何差異 (JS 亦能實現) ?

onclick 通常是在滿足以下條件時才優先於 .click 的方法:

1. 只有一個事件要為 click 事件註冊
2. 擔心移動性能/電池壽命

jQuery 以犧牲性能為代價來綁定所有事件。

如果我們談論性能,在任何情況下直接使用總是更快。


但倡導事件監聽的理由是 JavaScript 和 佈局(HTML) 應該分開
提倡者認為任何這些事件創建 evenHandler 是更好,一個事件可以捕獲多個項目,而不是為每個事件創建單獨的腳本



防禦利用 iframe 的站點劫持攻擊

https://paper.seebug.org/papers/Archive/drops2/Clickjacking%E7%AE%80%E5%8D%95%E4%BB%8B%E7%BB%8D.html



各種防禦與破解的方法整理


推荐的防御方法:


一、X-FRAME-OPTIONS

X-FRAME-OPTIONS是微软提出的一个http头,专门用来防御利用iframe嵌套的点击劫持攻击。

并且在IE8、Firefox3.6、Chrome4以上的版本均能很好的支持。

这个头有三个值:

DENY               // 拒绝任何域加载

SAMEORIGIN         // 允许同源域下加载

ALLOW-FROM         // 可以定义允许frame加载的页面地址

php中设置示例:

header ( "X-FRAME-OPTIONS:DENY");

二、目前最好的 JavaScript 的防御方案为:

<head>
<style> body { display : none;} </style>
</head>
<body>
<script>
if (self == top) {
    var theBody = document.getElementsByTagName('body')[0];
    theBody.style.display = "block";
} else {
    top.location = self.location;
}
</script>




0x00 相关背景介绍

Clickjacking(点击劫持)是由互联网安全专家罗伯特·汉森和耶利米·格劳斯曼在2008年首创的。

是一种视觉欺骗手段,在web端就是iframe嵌套一个透明不可见的页面,让用户在不知情的情况下,点击攻击者想要欺骗用户点击的位置。

由于点击劫持的出现,便出现了反frame嵌套的方式,因为点击劫持需要iframe嵌套页面来攻击。

下面代码是最常见的防止frame嵌套的例子:

if(top.location!=location)
    top.location=self.location;

事实上,这种代码很容易被绕过,在后文中讨论。

0x01 防御的几种方式

防止frame嵌套的js使用代码由高到低比例:

if (top != self)
if (top.location != self.location)
if (top.location != location)
if (parent.frames.length > 0)
if (window != top)
if (window.top !== window.self)
if (window.self != window.top)
if (parent && parent != window)
if (parent && parent.frames && parent.frames.length>0)
if((self.parent&&!(self.parent===self))&&(self.parent.frames.length!=0))

检测到后的处理方案:

top.location = self.location
top.location.href = document.location.href
top.location.href = self.location.href
top.location.replace(self.location)
top.location.href = window.location.href
top.location.replace(document.location)
top.location.href = window.location.href
top.location.href = "URL"
document.write('')
top.location = location
top.location.replace(document.location)
top.location.replace('URL')
top.location.href = document.location
top.location.replace(window.location.href)
top.location.href = location.href
self.parent.location = document.location
parent.location.href = self.document.location
top.location.href = self.location
top.location = window.location
top.location.replace(window.location.pathname)
window.top.location = window.self.location
setTimeout(function(){document.body.innerHTML='';},1);
window.self.onload = function(evt){document.body.innerHTML='';}
var url = window.location.href; top.location.replace(url)

0x02 绕过的几种方式

对于使用parent.location来防御的可以使用多层嵌套的方式绕过。

一、例如防御代码为:

if(top.location!=self.location){
     parent.location = self.location;
}

建立两个页面:

1.html代码为:

<iframe src="2.html">

2.html代码为:

<iframe src="http://www.victim.com">

访问1.html之后可以看到页面并无跳转等动作。

http://static.wooyun.org/20141017/2014101711515250154.png

二、onBeforeUnload函数的利用:

onBeforeUnload的介绍以及各种浏览器的支持情况请见:

http://w3help.org/zh-cn/causes/BX2047

如下的防御代码:

if(top != self) top.location.replace(location);

新建立页面,代码如下:

<script>
var framekiller = true;
window.onbeforeunload = function() { if(framekiller) { return
"Write something here to keep people stay!";} };
</script>
<iframe src="http://www.victim.com/">

打开页面显示如下:

http://static.wooyun.org/20141017/2014101711515274922.png

欺骗用户点击留在此页后显示:

http://static.wooyun.org/20141017/2014101711515228109.png

三、XSS filter的利用

IE8以上以及Chrome浏览器都有XSS筛选器,这些可以用来对付防御frame嵌套的代码。

防御代码如下:

if(top!=self){
    top.location=self.location;
}

新建立页面,代码如下:

<iframe src="http://www.victim.com/?<script>">

访问后页面显示:

http://static.wooyun.org/20141017/2014101711515211018.png

IE的xss筛选器自动拦截了跳转。

斯坦福的文章里写了Chrome也会出现这种情况,并给出了攻击代码:

<iframe src=http://www.victim.com/?v=if(top+!%3D+self)+%7B+top.location%3Dself.location%3B+%7D">

但是测试发现,新版的Chrome并不会拦截了,会直接跳转过去。

如果跟的参数中有变量在页面中显示的,会把变量过滤一遍再输出,但不会阻止跳转。

四、Referer检查的问题

有一些站点允许自己的域名嵌套自己,禁止外站对自己的嵌套。

通常是用document.referer来检测来源是否为自己的域名。

if(top.location!=location){
    if(document.referrer && document.referrer.indexOf("aaa.com")==1)
    {
        top.location.replace(document.location.href);
    }
}

判断字符串中是否含有本域名是常见的错误用法,利用二级域名的方式便可绕过,如:

http://aaa.com.bbb.com

注:从https域下post数据到http域的时候,浏览器不带Referer。

IE有个属性可以设置security为restricted可以禁止iframe里执行js脚本,但是要达到点击劫持的效果,必须要能够执行js所以很鸡肋。

代码如下:

<iframe src="http://www.victim.com/iframe.html" security="restricted"></iframe>

重点是手机站点,很多主站做的很不错,但是手机站点没有做任何防护,很容易造成点击劫持。

五、location劫持

在IE浏览器中,如果能够在防御代码的前面可以插入form表单的话,可以利用form表单对location进行劫持。

<form name=self location="javascript:alert(1)"></form>
<script>
if(top!=self){
   top.location=self.location
}
</script>

用iframe嵌套此代码,可以看到没有跳转,执行了alert(1)。



Javascript: 函數如何返回多組變數 Return multiple values in JavaScript?

https://stackoverflow.com/questions/2917175/return-multiple-values-in-javascript

Q. I am trying to return two values in JavaScript. Is that possible?

A.
No, but you could return an array containing your values:
function getValues() {
    return [getFirstValue(), getSecondValue()];
}
Then you can access them like so:
var values = getValues();
var first = values[0];
var second = values[1];
With the latest ECMAScript 6 syntax*, you can also destructure the return value more intuitively:
const [first, second] = getValues();
If you want to put "labels" on each of the returned values (easier to maintain), you can return an object:
function getValues() {
    return {
        first: getFirstValue(),
        second: getSecondValue(),
    };
}
And to access them:
var values = getValues();
var first = values.first;
var second = values.second;
Or with ES6 syntax:
const {first, second} = getValues();
* See this table for browser compatibility. Basically, all modern browsers aside from IE support this syntax, but you can compile ES6 code down to IE-compatible JavaScript at build time with tools like Babel.




JavaScript: Function 前面加上小括弧

https://freedomknight.me/javascript-ni-ming-han-shu/

如果沒有那個小括號,他就像是最一開始的宣告函數的樣子,直譯器期待你宣告一個函數的名稱。
而小括號對 js 來講,算是個強迫運算,像我們平時運算 (2 + 3) * 5 會用小括號先強迫把 2 + 3 算出來。

對這個小括弧而言,則是強迫生出個匿名函數並且呼叫

具有名稱時我們是如此呼叫:
add(1, 2);

現在是匿名函數:
(匿名函數)(1, 2);

其實形式上還是一樣,單純只是變形的呼叫。這時使用匿名的最大大大優點就是「船過水無痕」。 任何你在裡頭做的事情,所佔的任何空間,到最後會馬上釋放。

在小型 js 看不出來,但是在大型一點的程式,大家一股腦的宣告了一堆全域函數跟變數,如果瀏覽器還沒離開這個頁面,這些空間就一直被佔著,無法釋放。



JavaScript: ECMAScript 相容性


腳本引擎參考應用程式相容性[11]
ES5[12]ES6[13]ES7[14]較新(2016+)[14][15]
ChakraMicrosoft Edge 18100%96%100%58%
SpiderMonkeyFirefox 63100%98%100%78%
Chrome V8Google Chrome 70、Opera 57100%98%100%100%
JavaScriptCore(Nitro)Safari 1299%99%100%90%


JavaScript: SHA256, byte array, 16進制字串 轉換等

JavaScript SHA-256 demo: https://geraintluff.github.io/sha256/


https://github.com/emn178/js-sha256

到 https://cdnjs.com/ 搜尋
=> https://cdnjs.cloudflare.com/ajax/libs/js-sha256/0.9.0/sha256.min.js

A simple SHA-256 / SHA-224 hash function for JavaScript supports UTF-8 encoding.

It also supports byte `Array`, `Uint8Array`, `ArrayBuffer` input



https://github.com/brix/crypto-js
https://code.google.com/archive/p/crypto-js/
https://blog.zhengxianjun.com/2015/05/javascript-crypto-js/

<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.9/crypto-js.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.9/hmac-sha256.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.9/enc-base64.min.js"></script>

var hash = CryptoJS.SHA256("Message").toString();

https://github.com/brix/crypto-js/issues/157

var hash = CryptoJS.HmacSHA256("Message", "key");

// Message 是按照使用者的規則拼接的字串
// key為設置密鑰




https://github.com/digitalbazaar/forge

<script src="https://cdn.jsdelivr.net/npm/node-forge@0.7.0/dist/forge.min.js"></script>
<script type="text/javascript">
"use strict";

var md = forge.md.sha256.create();
md.update('The quick brown fox jumps over the lazy dog');
console.log(md.digest().toHex());

console.log(hexToBytes(md.digest().toHex()));

console.log(bytesToHex(hexToBytes(md.digest().toHex())));

// Convert a hex string to a byte array
function hexToBytes(hex) {
    for (var bytes = [], c = 0; c < hex.length; c += 2)
    bytes.push(parseInt(hex.substr(c, 2), 16));
    return bytes;
}

// Convert a byte array to a hex string
function bytesToHex(bytes) {
    for (var hex = [], i = 0; i < bytes.length; i++) {
        var current = bytes[i] < 0 ? bytes[i] + 256 : bytes[i];
        hex.push((current >>> 4).toString(16));
        hex.push((current & 0xF).toString(16));
    }
    return hex.join("");
}

</script>




//十六进制字符串转字节数组
function StrToBytes(str) {
var pos = 0;
var len = str.length;

if(len %2 != 0) {
return null;
}
len /= 2;
var hexA = new Array();

for(var i=0; i<len; i++) {
var s = str.substr(pos, 2);
var v = parseInt(s, 16);
hexA.push(v);
pos += 2;
}
return hexA;
}

//字节数组转十六进制字符串
function BytesToStr(arr) {
var str = "";

for(var i=0; i<arr.length; i++) {
var tmp = arr[i].toString(16);

if(tmp.length == 1) {
   tmp = "0" + tmp;
}

str += tmp;
}
return str;
}



javascript 使用 toString 10進位轉2或8或16進位.

toString():預設是10進位轉其它進位,同時,配合正則,可匹配字符。

範例:

<script language="javascript">
var x = 100;
var y1 = x.toString(2);
var y2 = x.toString(8);
var y3 = x.toString(16);
var z = "2進位 = " + y1 + "<br>8進位 = " + y2 + "<br>16進位 = " + y3;
document.write(z);
</script>





html 頁面內錨點定位及跳轉方法

一種方法是錨點用<a>標籤,在href屬性中寫入DIV的id。

<a href="#div1">to div1</a>
<a href="#div2">to div2</a>
<a href="#div3">to div3</a>
<div id="div1">div1</div>
<div id="div2">div2</div>
<div id="div3">div3</div>




另一種方法是用 JavaScript 的 srollIntoView方法,

document.getElementById("divId").scrollIntoView();

這種方法的好處,是URL不會變,同時能夠響應相應的scroll事件

JavaScript 中的 && 與 || 的用法(不用在判斷布爾值上)

https://segmentfault.com/q/1010000004265392
http://www.w3school.com.cn/js/pro_js_operators_boolean.asp


var x = a || b || c 等价于:

var x;
if(a){
    x = a;
} else if(b){
    x = b;
} else {
    x = c;
}


var x = a && b && c 等价于:

var x = a;
if(a){
    x = b;
    if(b){
        x = c;
    }
}


这种特性叫短路求值,&& 会返回第一个假值(0, null, "", undefined, NaN),而 || 则会返回第一个真值。

所以 && 有时候会用来代替 if (expression) doSomething(),转成 && 方式就是 expression && doSomething()。

而 || 比较用来在函数中设置默认值,比如

function doSomething(arg1, arg2, arg3) {
    arg1 = arg1 || 'arg1Value';
    arg2 = arg2 || 'arg2Value';
}
不过还需要看具体的使用场景,就比如如果要求 doSomething() 传入的 arg1 为一个数值,则上面的写法就会出现问题(在传入 0 的时候被认为是一个假值而使用默认值)。

现在个人比较常用的方法只判断是否与 undefined 相等,比如

function doSomething(arg) {
    arg = arg !== void 0 ? arg : 0;
}



JavaScript Image Object (可以從圖址取得圖片長寬等資訊)

JavaScript Image Object
The JavaScript Image Object is a property of the document object.

Properties
border - The width of the border around the image in pixels.
complete - A boolean value which identifies whether an image is completely loaded yet.
height - The read only height of the image in pixels.
hspace - The read only amount of horizontal space to the left and right sides of the image.
lowsrc - The read or write string giving the URL of an alternate image for low resolution screen display.
name - The assigned name of the image.
prototype - Used for adding user-specified properties to the image.
src - The URL of the image to be displayed. It is a read/write string.
vspace - The read only vertical space above and below the image.
width - The read only width of the image in pixels.
Events
onAbort
onError
onLoad


比如說

function getImgSize(imgSrc)
{
var newImg = new Image();
newImg.src = imgSrc;
var height = newImg.height;
var width = newImg.width;
alert ('The image size is '+width+'*'+height);
}
</script>

onclick="getImgSize('images/testout_r1_c2.jpg')"

HTML iframe 框架語法與其使用限制與缺點


被放進框架的內容網頁不見得能夠在 手機 等行動裝置上 正常運作,相容性很混亂

https://blog.csdn.net/Abraham_bug/article/details/80053210

無法滾動、解決滾動同時要防止框架外的移動等等衝突問題


HTML iframe 框架語法 => HTML5 改為使用 CSS 設定
https://www.w3schools.com/tags/tag_iframe.asp

iframe 連結另外開啟新視窗或在原本網頁開啟
http://www.wibibi.com/info.php?tid=374

深入了解 /iframe有那些缺點/ Iframe傳值問題
https://medium.com/@small2883/iframe%E4%BB%8B%E7%B4%B9-%E6%B7%B1%E5%85%A5%E4%BA%86%E8%A7%A3-iframe%E6%9C%89%E9%82%A3%E4%BA%9B%E7%BC%BA%E9%BB%9E-iframe%E5%82%B3%E5%80%BC%E5%95%8F%E9%A1%8C-579e6c113436

iframe這個詞是inline frame的縮寫。

iframe屬性:

1.frameborder:是否顯示邊框,1(yes),0(no)
2.height:height屬性指定了iframe的像素高度,建議使用css設置。
3.width:width屬性指定了iframe的像素寬度,建議使用css設置。
4.name:iframe的名稱,window.frames[name]時專用的屬性。
5.scrolling:iframe是否滾動。yes,no,auto。
6.src:iframe的網址。
7.sandbox:控制iframe內的權限(html5新功能):http://www.html5rocks.com/en/tutorials/security/sandboxed-iframes/?redirect_from_locale=zhhttp://msdn.microsoft.com/en-us/hh563496.aspx

為什麼前端盡量少用iframe? iframe有哪些缺點:

1.iframe会阻塞主頁面的Onload事件;
2.搜索引擎的檢索程序無法解讀這種頁面,不利於SEO;
3.iframe和主頁面共享連接池,而瀏覽器對同域的連接有限制,所以会影響頁面的並行加載。
4.因为iframe等于打開一个新的網頁,所有的JS/CSS全部加載一遍,内存会*2
5.是否同域的問題

我们通常使用iframe最基本的特性,就是能自由操作iframe和父框架的内容(DOM)。
但前提條件是同域,如果跨域頂多只能實現頁面跳轉window.location.href。

同域時,父頁面可以对子頁面進行改寫,反之亦然。
不同域,父頁面没有權限改動子頁面,但可以實現頁面的跳轉。

如果需要使用 iframe,最好是通过 javascript 動態给 iframe 添加 src 屬性值,这样可以避開一些 iframe 的缺點:

https://stackoverflow.com/questions/6000987/dynamically-set-iframe-src

跨域傳值,方法之一是使用
window.frames[0].postMessage($txt_val, ‘*’); 傳值
window.addEventListener(“message”, receiveMessage);取值
可參考
https://dotblogs.com.tw/daniel/2017/11/25/225511
https://www.cnblogs.com/dolphinX/p/3464056.html
https://blog.csdn.net/kenhins/article/details/50789125

jQuery 的動畫函式

https://www.darkthread.net/jQuery/Tutorial09/default.htm

【常用特效函數】

show() 將隱藏的元素立刻顯示出來,若元素已可見則沒有變化。
show(speed[, callback]) 在speed指定的時間內(即animate的duration,可以是"slow"、"normal"、"fast"或是數字代表微秒數,以下將不再重覆說明),將width, height由0變到原有尺寸,透明度也明完全透明變成不透明。callback即前述的complete函數,在特效結束後呼叫(稍後在其他函數中用到時便不再重覆說明)。
hide() 將顯示的元素立刻隱藏,已隱藏者不受影響。
hide(speed[, callback]) 在speed指定的時間內將width, height, opacity縮為0。
toggle() 切換元素的顯示狀態,將可見者隱藏,隱藏者顯示出來。
toggle(switch) switch為一Boolean變數,true時顯示,false時隱藏。
slideDown(speed[, callback]) 在speed指定時間內將height由0遞增至原有高度,形成向下拉開的視覺效果。
slideUp(speed[, callback]) 在speed指定時間內將height由原有高度遞減至0,形成向下收合的視覺效果。
slideToggle(speed[, callback) 切換元素的顯示狀態,將可見者隱藏,隱藏者顯示出來,但過程使用slideDown, slideUp效果。
fadeIn(speed[, callback]) 在speed指定時間內將opacity由透明逐漸變成不透明,形成漸漸浮現的視覺效果。
fadeOut(speed[, callback]) 在speed指定時間內將opacity由不透明逐漸變成透明,形成慢慢消失的視覺效果。
fadeTo(speed, opacity[, callback)  在speed指定時間內將opacity逐漸變成指定的透明度。

JavaScript 爬蟲

使用正則表達式解析的過程:https://medium.com/@realdennis/1684568f6cb4

使用 JavaScript 利用客戶端爬蟲必須面臨的最大難題為『瀏覽器有跨網域禁止訪問』的限制:
http://www.dewen.net.cn/q/7128/javascript

https://ithelp.ithome.com.tw/users/20107159/ironman/1325

用純客戶端JavaScript來爬蟲 (依賴瀏覽器擴充等):https://www.itread01.com/articles/1491156016.html

Pxer需要依賴瀏覽器擴充:https://github.com/FoXZilla/Pxer


使用 javascript 動態更改 CSS 的各種方式

https://www.jianshu.com/p/0260cddff86a


在很多情况下,都需要对网页上元素的样式进行动态的修改。在JavaScript中提供几种方式动态的修改样式,下面将介绍方法的使用、效果、以及缺陷。
1、使用obj.className来修改样式表的类名。
2、使用obj.style.cssTest来修改嵌入式的css。
3、使用obj.className来修改样式表的类名。
4、使用更改外联的css文件,从而改变元素的css

下面是一段html代码和css代码用来解释上面方法的区别的。

CSS

.style1{margin:10px auto ;background-color:#9999FF; display:block;color:White; border:1px solid white; padding:10px 25px; font-size:18px; }

.style1:hover{ background-color:#66B3FF; cursor:pointer;}

.style2{margin:10px auto ;background-color:gray; display:block;color:black; border:1px solid white; padding:10px 25px; font-size:18px; }

.style2:hover{ background-color:black; color:White; cursor:pointer}

HTML

 <div>
        <input id="btnB" type="button" name="btnLogin" value="登录" class="style1" />
        <div id="tool">
            <input type="button" value="【obj.style.className】更改样式" onclick="changeBackgroundColor()"/>
            <input type="button" value="【obj.style.cssText】更改样式" onclick="changeFontSize()" />
            <input type="button" value="【obj.className】更改样式" onclick="addRadius()" />
            <input type="button" value="更改外联css样式" onclick="recover()" />
        </div>
    </div>


一、使用obj.className来修改样式表的类名

从下面的代码可以看出ob.style.cssTest是如何来btnB的样式的。

 function changeStyle1() {
            var obj = document.getElementById("btnB");
            obj.style.backgroundColor= "black";

  }

该段代码修改btB的文字的颜色,在浏览器中打开调试工具,可以发现btB标签中多了一个属性【style="background-color:black"】,从而改变btB的样式。

缺陷:
在修改btB的背景色之后用鼠标放到btB上可以发现,btB的伪类hover里面的css根本不起作用。原来是当你修改了这个这样样式之后。在btB的内联样式中多了background-color属性了,在css的应用中也是有级别的,嵌入式>内联式>外联式。而btB的hove伪类的background-color样式写在内联式中,所以嵌入式的background-color覆盖了伪类中,这就使得鼠标放入btB上感觉不到背景颜色的变化。


二、使用obj.style.cssTest来修改嵌入式的css

直接上JavaScript代码:

 function changeStyle2() {
            var obj = document.getElementById("btnB");
            obj.style.cssText = "background-color:black; display:block;color:White;

}

该段代码和【一】中的效果是一样的,缺陷也是一样。


三、使用obj.className来修改样式表的类名

使用代码来修改btB引用样式的类名,如下段代码:

  function changeStyle3() {
            var obj = document.getElementById("btnB");
            //obj.className = "style2";
            obj.setAttribute("class", "style2");
    }

通过更改btB的css的类名的方式来更改样式,更改样式类名有两种方式。1、obj.className = "style2";  2、 obj.setAttribute("class", "style2");都是一样的效果。

用这种方式来修改css比上面的效果要好很多。

四、使用更改外联的css文件,从而改变元素的css

通过更改外联的css文件引用从而来更改btB的样式,操作很简单。代码如下:

首先得引用外联的css文件,代码如下:

<link href="css1.css" rel="stylesheet" type="text/css"  id="css"/>

function changeStyle4() {
            var obj = document.getElementById("css");
            obj.setAttribute("href","css2.css");
   }

这样也能方便的更改btB的样式,个人觉得这种方式是最好用的。是实现整体页面换肤的最佳方案。

Alert、confirm 及 prompt 對話盒

http://www.takka.com.hk/jstutor/ch3/ch3.htm

在實務應用上,Javascript 原生的對話盒外貌與 OS系統的警告視窗太過相似,會帶給網站訪客/用戶 心理上不好的感受,所以僅可參考其邏輯流程,並重新設計與自身網站美術設計渾然一體的動態 Dialog 與 UX。

WebSocket

詳閱 http://muki.tw/tech/websocket-simple-introduce-and-use/


以下為頁庫存檔:

什麼是 WebSocket?

實作之前,免不俗的要跟大家分享一下 WebSocket 到底是什麼,以下取自 wiki 百科的解釋:
WebSocket 是 HTML5 開始提供的一種瀏覽器與伺服器間進行全雙工通訊的網路技術。WebSocket 通訊協定於 2011 年被 IETF 定為標準 RFC 6455,WebSocketAPI 被 W3C 定為標準。
在 WebSocket API 中,瀏覽器和伺服器只需要要做一個握手的動作,然後,瀏覽器和伺服器之間就形成了一條快速通道。兩者之間就直接可以資料互相傳送。
@ WebSocket / wikipedia
簡單來說,就是有 Client & Server 兩端透過 WebSocket 互相傳遞與接收資料,並且即時顯示在頁面上。

WebSocket 語法說明

WebSocket 的大架構其實很簡單又直覺,他也有一些既有的事件,我們只要知道確定哪些事件發生時,該做什麼事情?把這些事情塞到對應的事件即可。
在 WebSocket 官方網站也有提供測試的頁面以及語法結構,以下就使用他提供的 Example 來跟大家說明:
JavaScript
<!DOCTYPE html>
    <meta charset="utf-8" />
    <title>WebSocket Test</title>
    <script language="javascript" type="text/javascript">
        var wsUri = "ws://echo.websocket.org/";
        var output;
            function init() {
                output = document.getElementById("output");
                testWebSocket();
            }
            function testWebSocket() {
                websocket = new WebSocket(wsUri);
                websocket.onopen = function(evt) { 
                    onOpen(evt)
                    };
                websocket.onclose = function(evt) {
                    onClose(evt)
                };
                websocket.onmessage = function(evt) {
                    onMessage(evt)
                };
                websocket.onerror = function(evt) {
                    onError(evt)
                };
            }
            function onOpen(evt) {
                writeToScreen("CONNECTED"); 
                doSend("WebSocket rocks"); 
            }  
            function onClose(evt) { 
                writeToScreen("DISCONNECTED"); 
            }  
            function onMessage(evt) { 
                writeToScreen('RESPONSE: ' + evt.data+''); 
                websocket.close(); 
            }  
            function onError(evt) { 
                writeToScreen('ERROR: ' + evt.data); 
            }  
            function doSend(message) { 
                writeToScreen("SENT: " + message);
                websocket.send(message); 
            }  
            function writeToScreen(message) { 
                var pre = document.createElement("p"); pre.style.wordWrap = "break-word"; pre.innerHTML = message; output.appendChild(pre); 
            }  
            window.addEventListener("load", init, false);  
        </script>  
        <h2>WebSocket Test</h2>  
        <div id="output"></div>  
WebSocket 已經建立好許多 function ,我們可以直接用他的 function,當然也不一定要全部 function 都用到,或是可以做點小修改,像我主管給我的範本就跟官網提供的有一點點不一樣(但基本上的呼叫是大同小異的)
  • 第 5 行:老實說我覺得所有語法中最重要的就是第 5 行的 var wsUri = "ws://echo.websocket.org/";,因為如果一開始沒有把傳輸的網址寫正確,之後的效果根本也跑不出來。記得要把 http:// 改成 ws://
  • 第 13 行:websocket.onopen這個事件是用來判斷前面的 wsUri 是否有順利抓到,如果有抓到表示 onopen,可以利用console.log或是alert做個標記:console.log("連線成功");
  • 第 16 行:跟第 13 行的事件對照就很清楚的知道,websocket.onclose是用來表示當連線中斷時,會出現什麼訊息或事件。
  • 第 19 行:wescoket.onmessage是整個 WebSocket 的重頭戲,連線後,我們就可以在onmessage裏面寫上任何想要傳輸的事件內容。
  • 第 22 行:而對應 19 行的wescoket.onmessagewescoket.onerror是用來判斷連線或事件的正確與否,如果有出現了任何錯誤,就會觸發onerror事件,所以我們可以在這邊進行除錯。
WebSocket 主要就是這四個事件,所以其實不難。那要怎麼利用 jQuery 結合 WebSocket 做出想要的功能呢?我們做法通常是將 jQuery 的主要 function 跟 WebSocket 拆開來,簡單架構參考如下:
Bash
主資料夾
├ effect.js
├ websocket.client.js
├ websocket.master.js
├ websocket.client.html
├ websocket.master.html
由此可看出,將主要的功能寫在 effect.js 裏頭, client.js(html) 與 master.js(html) 分別用來表示兩個不同網頁,他們可以有不同的功能,也可以互相傳收資料 。

利用 JSON 傳遞 WebSocket

步驟一

在 effect.js 先將所有要顯示的資料存到變數中:
JavaScript
var _name = $("#name").val();
var _company = $("#company").val();

步驟二

利用 JSON 將資料送給 WebSocket:
JavaScript
websocket.send(JSON.stringify({
    'username': _name,
    'company': _company,
}));

步驟三

在 client.js 將收到的資料存到變數中並調用:(請寫在websocket.onmessage事件裡。)
JavaScript
//設置一個變數 data, 將剛剛 JSON 的資料存入
var data = $.parseJSON(e.data);

//以下可調用該 data
username = data.username
company = data.company
以上簡單幾行,就可以完成 WebSocket 的基本功能囉 🙂

在兩個不同的網頁中 (master.html, client.html) 互傳資料

假使我們希望在 master.html 做了一個動作 (比如說點選特定的分頁時),client.html 就會秀出一個 DIV。那麼要怎麼做出這功能呢?
我們在切換 TAB 的時候,通常網址列後面都會多一個「#+英數字」作為標記,而我們可以利用這個標記來識別現在是切換到第幾個分頁,然後針對指定的分頁,在 client.html 顯示一個 DIV。

步驟一

先在 master.js 設定一個事件,將 #(hash) 給擷取出來:
JavaScript
$(window).keyup('hashchange', function() {
    var tab= location.hash;
    console.log(location.hash);
    websocket.send(JSON.stringify({'tab' : tab}));
});
我有用console.log記錄每一次的 hash 變化,確定他有抓到 hash,然後用websocket.send寫到 JSON
ps. 這個 keyup 事件不一定要寫在websocket.onmessage裡。

步驟二

同樣在 client.js 將資料抓出來,然後做判斷:
JavaScript
//如果 data.tab 有資料
if (data.tab) {
    //因為 data.tab 抓到的資料是 #1, #2, #3... 這樣的值,為了只取數字,所以用 substring 去做截斷
    for(var x = 1; x &lt; data.tab.substring(1,2); x ++) {
        if(x == 1){
            $("div").css("display", "block");
          }
    };        
};

利用這樣的概念與方法,就可以簡單地在兩端互傳資料囉

有趣的 WebSocket 實例

一個由偉大的谷歌之神做的 WebSocket 互動網站,有興趣的朋友可以玩玩看,來體驗 WebSocket 是多麼的有趣
Super Sync Sports 是個利用 WebSocket 做的運動小遊戲,請先用 web 端瀏覽該網站,然後他會要你也用手機開啟這個網站,將 web 跟手機連線之後,就可以利用手機控制 web 介面來跑步、游泳,或是騎腳踏車。
而且還可以多人連線喔,超酷的 XDDD,大家有興趣不妨跟身旁的親朋好友一起玩樂比賽吧

程式語言編年史

程式語言編年史原文 下面這張圖片描繪了整個程式語言的歷史。包括各種程式語言的發明人、程式語言的特點和適用領域、被什麼網站或公司使用等 (檢視 完整高清圖 )。 之所以會有那麼多不同的程式語言是因為設計程式語言的初衷不同、對語言學習曲線的追求不同、不同程式之間的執行成本差異...