什麼是BOM?
- BOM是Browser Object Model的縮寫,簡稱瀏覽器物件模型
- BOM提供了獨立於內容而與瀏覽器視窗進行互動的物件
- 由於BOM主要用於管理視窗與視窗之間的通訊,因此其核心物件是window
- BOM由一系列相關的物件構成,並且每個物件都提供了很多方法與屬性
- BOM缺乏標準,JavaScript語法的標準化組織是ECMA,DOM的標準化組織是W3C(WHATWG,WebHypertextApplicationTechnologyWorkingGroup——網頁超文字應用程式技術工作組目前正在努力促進BOM的標準化)
- BOM最初是Netscape瀏覽器標準的一部分
基本的BOM體系結構圖
能利用BOM做什麼?
BOM提供了一些訪問視窗物件的一些方法,我們可以用它來移動視窗位置,改變視窗大小,開啟新視窗和關閉視窗,彈出對話方塊,進行導航以及獲取客戶的一些資訊如:瀏覽器品牌版本,螢幕解析度。但BOM最強大的功能是它提供了一個訪問HTML頁面的一入口——document物件,以使得我們可以通過這個入口來使用DOM的強大功能!!!
window物件是BOM的頂層(核心)物件,所有物件都是通過它延伸出來的,也可以稱為window的子物件。由於window是頂層物件,因此呼叫它的子物件時可以不顯示的指明window物件,例如下面兩行程式碼是一樣的:
document.write("BOM");
window.document.write("BOM");
window -- window物件是BOM中所有物件的核心。window物件表示整個瀏覽器視窗,但不必表示其中包含的內容。此外,window還可用於移動或調整它表示的瀏覽器的大小,或者對它產生其他影響。
JavaScript中的任何一個全域性函式或變數都是window的屬性
window子物件
- document 物件
- frames 物件
- history 物件
- location 物件
- navigator 物件
- screen 物件
window物件關係屬性
- parent:如果當前視窗為frame,指向包含該frame的視窗的frame (frame)
- self :指向當前的window物件,與window同意。 (window物件)
- top :如果當前視窗為frame,指向包含該frame的top-level的window物件
- window :指向當前的window物件,與self同意。
- opener :當視窗是用javascript開啟時,指向開啟它的那人視窗(開啟者)
window物件定位屬性
- IE提供了window.screenLeft和window.screenTop物件來判斷視窗的位置,但未提供任何判斷視窗大小的方法。用document.body.offsetWidth和document.body. offsetHeight屬性可以獲取視口的大小(顯示HTML頁的區域),但它們不是標準屬性。
- Mozilla提供window.screenX和window.screenY屬性判斷視窗的位置。它還提供了window.innerWidth和window.innerHeight屬性來判斷視口的大小,window.outerWidth和window.outerHeight屬性判斷瀏覽器視窗自身的大小。
window物件的方法
- 窗體控制
- moveBy(x,y)——從當前位置水平移動窗體x個畫素,垂直移動窗體y個畫素,x為負數,將向左移動窗體,y為負數,將向上移動窗體
- moveTo(x,y)——移動窗體左上角到相對於螢幕左上角的(x,y)點,當使用負數做為引數時會吧窗體移出螢幕的可視區域
- resizeBy(w,h)——相對窗體當前的大小,寬度調整w個畫素,高度調整h個畫素。如果引數為負值,將縮小窗體,反之擴大窗體
- resizeTo(w,h)——把窗體寬度調整為w個畫素,高度調整為h個畫素
- 窗體滾動軸控制
- scrollTo(x,y)——在窗體中如果有滾動條,將橫向滾動條移動到相對於窗體寬度為x個畫素的位置,將縱向滾動條移動到相對於窗體高度為y個畫素的位置
- scrollBy(x,y)—— 如果有滾動條,將橫向滾動條移動到相對於當前橫向滾動條的x個畫素的位置(就是向左移動x畫素),將縱向滾動條移動到相對於當前縱向滾動條高度為y個畫素的位置(就是向下移動y畫素)
- 窗體焦點控制
- focus()—— 使窗體或控制元件獲取焦點
- blur()——與focus函式相反,使窗體或控制元件失去焦點
- 新建窗體
- open()——開啟(彈出)一個新的窗體
- close()——關閉窗體
- opener屬性——新建窗體中對父窗體的引用,中文"開啟者"的意思
window.open方法語法
window.open(url, name, features, replace);
open方法引數說明
- url -- 要載入窗體的URL
- name -- 新建窗體的名稱(目標,將在a 標籤的target屬性中用到,當與已有窗體名稱相同時將覆蓋窗體內容).open函式預設的開啟窗體的方式為target的_blank彈出方式,因此頁面都將以彈出的方式開啟
- features -- 代表窗體特性的字串,字串中每個特性使用逗號分隔
- replace -- 一個布林值,說明新載入的頁面是否替換當前載入的頁面,此引數通常不用指定
open函式features引數說明,如果不使用第三個引數,將開啟一個新的普通視窗
引數名稱 | 型別 | 說明 |
---|---|---|
height | Number | 設定窗體的高度,不能小於100 |
left | Number | 說明建立窗體的左座標,不能為負值 |
location | Boolean | 窗體是否顯示位址列,預設值為no |
resizable | Boolean | 窗體是否允許通過拖動邊線調整大小,預設值為no |
scrollbars | Boolean | 窗體中內部超出視窗可視範圍時是否允許拖動,預設值為no |
toolbar | Boolean | 窗體是否顯示工具欄,預設值為no |
top | Number | 說明建立窗體的上座標,不能為負值 |
status | Boolean | 窗體是否顯示狀態列,預設值為no |
width | Number | 建立窗體的寬度,不能小於100 |
特性字串中的每個特性使用逗號分隔,每個特性之間不允許有空格
open方法返回值為一個新窗體的window物件的引用
- 對話方塊
- alert(str)—— 彈出訊息對話方塊(對話方塊中有一個“確定”按鈕)
- confirm(str)—— 彈出訊息對話方塊(對話方塊中包含一個“確定”按鈕與“取消”按鈕)
- prompt(str,defaultValue)——彈出訊息對話方塊(對話方塊中包含一個“確定”按鈕、“取消”按鈕與一個文字輸入框),由於各個瀏覽器實現的不同,若沒有第二個引數(文字框中的預設值)時也最好提供一個空字串
- 狀態列
- window.defaultStatus 屬性——改變瀏覽器狀態列的預設顯示(當狀態列沒有其它顯示時),瀏覽器底部的區域稱為狀態列,用於向使用者顯示資訊
- window.status 屬性——臨時改變瀏覽器狀態列的顯示
- 時間等待與間隔函式
- setTimeout()—— 暫停指定的毫秒數後執行指定的程式碼
- clearTimeout()——取消指定的setTimeout函式將要執行的程式碼
- setInterval()——間隔指定的毫秒數不停地執行指定的程式碼
- clearInterval()——取消指定的setInterval函式將要執行的程式碼
setTimeout與setInterval方法有兩個引數,第一個引數可以為字串形式的程式碼,也可以是函式引用,第二個引數為間隔毫秒數,它們的返回是一個可用於對應clear方法的數字ID
var tid = setTimeout("alert('1')",1000); alert(tid); clearTimeout(tid);
History物件,在瀏覽器歷史記錄中導航
History 物件的屬性:length 返回瀏覽器歷史列表中的 URL 數量
History 物件的方法
- back() 載入 history 列表中的前一個 URL
- forward() 載入 history 列表中的下一個 URL
- go(num) 載入 history 列表中的某個具體頁面
Location 物件
Location 物件的屬性
- hash 設定或返回從井號 (#) 開始的 URL(錨)
- host 設定或返回主機名和當前 URL 的埠號
- hostname 設定或返回當前 URL 的主機名
- href 設定或返回完整的 URL
- pathname 設定或返回當前 URL 的路徑部分
- port 設定或返回當前 URL 的埠號
- protocol 設定或返回當前 URL 的協議
- search 設定或返回從問號 (?) 開始的 URL(查詢部分)
Location 物件的方法
- assign() 載入新的文件,這與直接將一個URL賦值給Location物件的href屬性效果是一樣的
- reload() 重新載入當前文件,如果該方法沒有規定引數,或者引數是 false,它就會用 HTTP 頭 If-Modified-Since 來檢測伺服器上的文件是否已改變。如果文件已改變,reload() 會再次下載該文件。如果文件未改變,則該方法將從快取中裝載文件。這與使用者單擊瀏覽器的重新整理按鈕的效果是完全一樣的。如果把該方法的引數設定為 true,那麼無論文件的最後修改日期是什麼,它都會繞過快取,從伺服器上重新下載該文件。這與使用者在單擊瀏覽器的重新整理按鈕時按住 Shift 健的效果是完全一樣。
- replace() 用新的文件替換當前文件,replace() 方法不會在 History 物件中生成一個新的紀錄。當使用該方法時,新的 URL 將覆蓋 History 物件中的當前紀錄。
Navigator物件
Navigator 物件的屬性
- appCodeName 返回瀏覽器的程式碼名
- appName 返回瀏覽器的名稱
- appVersion 返回瀏覽器的平臺和版本資訊
- browserLanguage 返回當前瀏覽器的語言
- cookieEnabled 返回指明瀏覽器中是否啟用 cookie 的布林值
- cpuClass 返回瀏覽器系統的 CPU 等級
- onLine 返回指明系統是否處於離線模式的布林值
- platform 返回執行瀏覽器的作業系統平臺
- systemLanguage 返回 OS 使用的預設語言
- userAgent 返回由客戶機傳送伺服器的 user-agent 頭部的值
- userLanguage 返回 OS 的自然語言設定
框架與多視窗通訊
子視窗與父視窗
只有自身和使用window.open方法開啟的視窗和才能被JavaScript訪問,window.open方法開啟的視窗通過window.opener屬性來訪問父視窗。 而在opener視窗中,可以通過window.open方法的返回值來訪問開啟的視窗!
框架
window.frames集合:在框架集或包含iframe標籤的頁面中,frames集合包含了對有框架中視窗的引用
alert(frames.length);//框架的數目 alert(frames[0].document.body.innerHTML);//使用下標直接獲取對框架中視窗的引用 //不但可以使用下標,還可以使用frame標籤的name屬性 alert(frames["frame1"].document.title);
在框架集中還可以使用ID來獲取子視窗的引用
var frame1 =document.getElementById("frame1");//這樣只是獲取了標籤 var frame1Win = frame1.contentWindow;//frame物件的contentWindow包含了視窗的引用 //還可以直接獲取框架中document的引用 var frameDoc = frame1.contentDocument; alert(frameDoc);//但IE不支援contentDocument屬性
子視窗訪問父視窗——window物件的parent屬性
子視窗訪問頂層——window物件的top屬性
瀏覽器檢測
市場上的瀏覽器種類多的不計其數,它們的解釋引擎各不相同,期待所有瀏覽器都一致的支援JavaScript,CSS,DOM,那要等到不知什麼時候,然而開發者不能幹等著那天。歷史上已經有不少方法來解決瀏覽器相容問題了,主要分為兩種:1.userAgent字串檢測,2.物件檢測;當然,也不能考慮所有的瀏覽器,我們需要按照客戶需求來,如果可以確信瀏覽網站的使用者都使用或大部分使用IE瀏覽器,那麼你大可放心的使用IE專有的那些豐富的擴充套件,當然,一旦使用者開始轉向另一個瀏覽,那麼痛苦的日子便開始了。下面是市場上的主流瀏覽器列表:
- Internet Explorer
- Mozilla Firefox
- Google Chrome
- Opera
- Safari
注意,瀏覽器總是不斷更新,我們不但要為多種瀏覽器作相容處理,還要對同一瀏覽器多個版本作相容處理。比如IE瀏覽器,其6.0版本和7.0版本都很流行,因為微軟IE隨著作業系統繫結安裝(之前也是同步發行,微軟平均每兩年推出一款個人桌面,同樣IE也每兩年更新一次;直到現在,由於火狐的流行,IE工作組才加快IE的更新),所以更新的較慢,6.0版和7.0版有很大差別。
市場上還存在一些其它瀏覽器,但由於它們都是使用的上面所列瀏覽器的核心,或與上面瀏覽器使用了相同的解釋引擎,所以無需多作考慮。下面是主流的瀏覽器解釋引擎列表:
- Trident
Trident (又稱為MSHTML),是微軟的視窗作業系統(Windows)搭載的網頁瀏覽器—Internet Explorer的排版引擎的名稱,它的第一個版本隨著1997年10月Internet Explorer第四版釋出,之後不斷的加入新的技術並隨著新版本的Internet Explorer釋出。在未來最新的Internet Explorer第七版中,微軟將對Trident排版引擎做了的重大的變動,除了加入新的技術之外,並增加對網頁標準的支援。儘管這些變動已經在相當大的程度上落後了其它的排版引擎。使用該引擎的主要瀏覽器:IE,TheWorld,MiniIE,Maxthon,騰訊TT瀏覽器。事實上,這些瀏覽器是直接使用了IE核心,因為其userAgent字串中返回的資訊與IE是一模一樣的!
- Gecko
壁虎,英文為"Gecko"。Gecko是由Mozilla基金會開發的佈局引擎的名字。它原本叫作NGLayout。Gecko的作用是讀取諸如HTML、CSS、XUL和JavaScript等的網頁內容,並呈現到使用者螢幕或列印出來。Gecko已經被許多應用程式所使用,包括若干瀏覽器,例如Firefox、Mozilla Suite、Camino,Seamonkey等等
- Presto
Presto是一個由Opera Software開發的瀏覽器排版引擎,供Opera 7.0及以上使用。Presto取代了舊版Opera 4至6版本使用的Elektra排版引擎,包括加入動態功能,例如網頁或其部分可隨著DOM及Script語法的事件而重新排版。Presto在推出後不斷有更新版本推出,使不少錯誤得以修正,以及閱讀Javascript效能得以最佳化,併成為速度最快的引擎。
- KHTML
是HTML網頁排版引擎之一,由KDE所開發。KDE系統自KDE2版起,在檔案及網頁瀏覽器使用了KHTML引擎。該引擎以C++程式語言所寫,並以LGPL授權,支援大多數網頁瀏覽標準。由於微軟的Internet Explorer的佔有率相當高,不少以FrontPage製作的網頁均包含只有IE才能讀取的非標準語法,為了使KHTML引擎可呈現的網頁達到最多,部分IE專屬的語法也一併支援。目前使用KHTML的瀏覽器有Safari和Google Chrome。而KHTML也產生了許多衍生品,如:WebKit,WebCore引擎
利用userAgent檢測
下面是各大瀏覽器使用彈窗顯示的userAgent字串
IE瀏覽器:Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727)
火狐瀏覽器:Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.0.4) Gecko/2008102920 Firefox/3.0.4
Opera瀏覽器:Opera/9.64 (Windows NT 5.1; U; Edition IBIS; zh-cn) Presto/2.1.1
Safari瀏覽器:Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN) AppleWebKit/528.16 (KHTML, like Gecko) Version/4.0 Safari/528.16
Google Chrome瀏覽器:Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/530.5 (KHTML, like Gecko) Chrome/2.0.172.33 Safari/530.5
可以使用下面的程式碼進行瀏覽器檢測
var Browser = { isIE:navigator.userAgent.indexOf("MSIE")!=-1, isFF:navigator.userAgent.indexOf("Firefox")!=-1, isOpera:navigator.userAgent.indexOf("Opera")!=-1, isSafari:navigator.userAgent.indexOf("Safari")!=-1 };
但這樣做並不是萬無一失的,一個特例便是Opera可以使用userAgent偽裝自己。下面是偽裝成IE的userAgent:Mozilla/5.0 (Windows NT 5.1; U; Edition IBIS; zh-cn; rv:1.8.1) Gecko/20061208 Firefox/2.0.0 Opera 9.64;在完全偽裝的情況下,最後的“Opera 9.64”這個字串也不會出現,但Opera也有特殊的識別自身的方法,它會自動宣告一個opera全域性變數!
不但如此,我們的檢測還忽略了一點,就是那些使用相同引擎而品牌不同的瀏覽器,所以,直接檢測瀏覽器是沒有必要的,檢測瀏覽器的解釋引擎才是有必要的!
var Browser = { isIE:navigator.userAgent.indexOf("MSIE")>-1 && !window.opera, isGecko:navigator.userAgent.indexOf("Gecko")>-1 && !window.opera && navigator.userAgent.indexOf("KHTML") ==-1, isKHTML:navigator.userAgent.indexOf("KHTML")>-1, isOpera:navigator.userAgent.indexOf("Opera")>-1 };