在指令有限的情況下,面對未知的需求,總難免會有無能為力的時候。本章的重點便在教大家如何去運用Script 來解決這些難題~

在NT中,不管是 VBScript 或 JavaScript  都是被允許的。但這裏只介紹JavaScript,因為篇幅不夠…    

另外,我要嚴正聲明,沒有一門學問是二、三頁就可以交待清楚的。所以 接下來的教學,是非正規的、取巧的,目的只在於速成~

若你是JS行家,看到怪異的部分也別搖頭!! 因為這份教學的前題是据限於GDL 的寫作,為了要速成我只能不按牌理來設計,實在情非得已~  


JavaScript (以下簡稱為JS)的格式算是非常開放的,行間的分號是可加可不加~

但若要寫成單行來表示的話,大括號和條件判斷式不需要加分號,而一般敘述都要加。

<script type="text/javascript">
var str="聰明漂亮美"
if (str.search("美")){
alert('字串中有找到"美"字,表示小美真的既聰明又漂亮 ')
}
else {
alert('找不到"美"字,有人要跪算盤了!!')
}
</script>
 
<script type="text/javascript">
var str="聰明漂亮美";if (str.search("美")){alert('字串中有找到"美"字,表示小美真的既聰明又漂亮 ')} else {alert('找不到"美"字,有人要跪算盤了!!')};
</script>
上面兩段結果會是一樣的,而NT只支援單行的格式!! 所以我們就要寫成像第二種這樣的~
RunScriptNext:var str="聰明漂亮美";   if (str.search("美")) {alert('字串中有找到"美"字,表示小美真的既聰明又漂亮 ')} else  {alert('找不到"美"字,有人要跪算盤了!!')};

 

 

同 NT 指令中的 ***Variable?*** 。只是JS 又區分為全域變數與局部變數兩種,兩者間差在全域是寫在 function外的,而局部是寫在funciton內的~

宣告方式是以 var 來建立一個變數名,再接等號,而等號後面可放  字串型態、數值型態、變數。 要相連的話,就用符號+ 來表示 。(字串型態需用引號或雙引號包住)

<script type="text/javascript">
var k1="聰明" , k2="漂亮" , k3="<富小美>" ;
var h= k1 + k2 +'美' + k3 ;
alert(h);
</script>

如上例中,h 便會是   聰明漂亮美<富小美>

在來看下例,我建立了一個名為 str 的全域變數,其值為聰明漂亮美,因為是字串型態,所以我用引號把它包住 。

此外,我又在 searchkey 這個function裏,宣告了兩個局部變數,分別為 susses_key 、fail_key,並將其值指定為剛建立的全域變數 str 。

<script type="text/javascript">
var str='聰明漂亮美' ;
function searchkey() { if (str.search("美")){ var susses_key=str ; alert(susses_key); alert('字串中有找到"美"字,表示小美真的既聰明又漂亮 ')} else { var fail_key= str; alert(fail_key);alert('找不到"美"字,有人要跪算盤了!!')} };
alert(str);
searchkey();
alert(susses_key);
alert(fail_key);
</script>

 

接下來看這段Script 執行的結果~

alert(str) 時,看到的會是  聰明漂亮美

searchkey() 時,因為字串中含有'美'字,所以會先跑  alert(susses_key)  也就是 聰明漂亮美,接著才會跳出  字串中有找到"美"字,表示小美真的既聰明又漂亮

alert(susses_key) 時,會顯示 susses_key 無定義

alert(fail_key) 時,會顯示 fail_key  無定義

也就是說:局部變數出不了function , 而全域變數則是可以自由來去各function中~ 

我們常會碰到需要倒數讀秒才能下載的空間,其實那個秒數就是利用一個全域變數來定義的,只要把其值指定為零,自然就不會再倒數下去囉~

例:http://www.yyshare.com/file.php?file=b72b60fed123fa3ac43a2f247bc8e80d

網頁開啟後,你會看到需等待30秒的字眼。打開原始檔後,你會發現有一個叫 _timeout 的全域變數,其值就這麼巧為 30 ,那我們就試著來給它賦值為零看看~

RunScriptNext: _timeout = 0 ;

果不其然,此時頁面已不再倒數,而是直接列出連結囉~  (建議秒數值是給定1,才會適用所有空間喔)

 

 

function 就像是一個區塊,只要定義後,在頁面沒變換前都可重覆使用。

1.不帶變數的函數

function 函數名稱() { 程式碼 }
例:我們先定義了一個叫 test的函數,然後連續執行三次。結果都會一樣。但當我們變換了頁面後,再去執行這個函數時,就會說找不到物件而出錯~
RunScriptNext:function test() { alert('小美逼我說她氣質出眾、溫柔婉約、美麗大方… ┐(─__─)┌') };
RunScriptNext:test()
RunScriptNext:test()
RunScriptNext:test()
go:about:blank
RunScriptNext:test()

2.帶有變數的函數

function 函數名稱(var1,var2,...,varX) { 撰寫程式碼… ; return  xxx }

例:我們先定義一個叫total的函數(包含了兩個變數),其功用是用來計算兩個變數的積。頁面一經變動total(a,b)便會失效。

RunScriptNext:function total(a,b) {sol = a*b ; return sol}
RunScriptNext:alert(total(7,9))
RunScriptNext:alert(total(2,3))
go:about:blank
RunScriptNext:alert(total(1,5))

 

 

簡單的說,就是利用條件判斷來控制(迴路)流程。等同於NT指令中的 IF +GoLabel ,只是更加的彈性化~

這裏我只介紹兩種最基本的,因為彼此可互相混搭,所以應該是夠用了~

1.

if (條件式 ) { 若符合條件才執行此段  }   else { 不符合條件式時才執行此段  }                    註: else { } 是可加可不加,若不加的話,表示不符合條件時就不作任何動作

RunScriptNext: var str="聰明漂亮美";   if ( str.search("美") ) {  alert('字串中有找到"美"字,表示小美真的既聰明又漂亮 ') }   else  {  alert('找不到"美"字,有人要跪算盤了!!')  };

首先我們定義了一個全域變數str ,其值為 聰明漂亮美。接在建立一個判斷式,當str 中含有 '美' 這個字時,會跑  alert('字串中有找到"美"字,表示小美真的既聰明又漂亮 ')

反之則跑 alert('找不到"美"字,有人要跪算盤了!!')

 

2.

for ( var = 變數啟始值 ;    var <= 終止值 ;  var = 變數增加的次數 ) { 執行的程式碼 }                   註:break 語法為中斷迴圈

RunScriptNext: var k=0 ;  for ( i=1; i<=100 ; i++ ){ k = k + i };  alert(k);

上面這個用意是在計算 1+2+3+…  +100 的值。首先我們定義一個全域變數 k ,其值為 0 。然後開始跑迴圈, i 從1 開始,每次增值1,直到100時才結束~

( i++ 與 i = i + 1  是一樣意思 。 若每次是累加上k,那就寫成 i = i +k  或是  i+=k   )

RunScriptNext: var k=0 ;  for ( i=1; i<=100 ; i++ ) {  k = k + i  ; if ( k  > 400 ) {break;}  };  alert(k);

這個也是1加到100,但加了個限制。當總和( 即k ) 超過 400 時,就跳出 for 這個迴圈,然後把 k 列出來。最後的k值會是 406 ,而非1加到100的1050

 

下面的例子,應該大家都有印象吧! 同樣的結果,改用JS 來處理,就變成第二段的方式~

ex:罰寫十遍讚美小美的話…
SetDataValue:0,***Variable1***
Label:begin
Math:***Variable1***,***Variable1*** + 1
Output:小美逼我說她氣質出眾、溫柔婉約、美麗大方… ┐(─__─)┌
IF: ***Variable1*** >= 10
IFYes:end
GoLabel:begin
Label:end
EXIT()

 

RunScriptNext: var k = 0; for (i=1; i<=10; i++ ){ document.write('小美逼我說她氣質出眾、溫柔婉約、美麗大方… ┐(─__─)┌') ; document.write('<br/>') }

 

 

簡單的形容就是把一個變數拆成N個,當你需要定義大量變數時,陣列會是不錯的選擇喔~

宣告方式有兩種:

var   陣列名 =  new Array(N)                                                       註:N 也可以不指定,保持空白即可

var 陣列名 = new Array(值0,值1,值2,.....,值N-1)
RunScriptNext: var test = new Array('氣質出眾','溫柔婉約','美麗大方')
RunScriptNext: alert(test.length)
RunScriptNext: alert(test[0])
RunScriptNext: alert(test[1])
RunScriptNext: alert(test[2])
RunScriptNext:test[2]='裝肖維,每次都要我說噁心的話'
RunScriptNext: alert(test[2])
上面我建立一個名為 test 的陣列,它的長度(length)是3,分別為 test[0]、test[1]、test[2]。後來我又重新定義了test[2]的值~
陣列同時又具有把變數順序化的效果,對於需要比對位置的需求特別的方便
比如星期日到星期六相對於0~6 ,這種有順序關聯的應用~
當我把日期依序來定義後,我便可以粉容易的用對應的數字來叫出它。如下面 week[4] 就代表星期四、week[6] 就代表星期六
RunScriptNext: var week=new Array( '星期日' , '星期一' , '星期二 ' ,'星期三'  , '星期四' , '星期五' , '星期六' );
RunScriptNext: alert (week[4])
RunScriptNext: alert (week[6])
 
 
 
為何要編碼呢?? 說白點,英文才是通用語,其它語系對外國人來說就像鬼畫符一樣。所以為了大家都可以看的懂,才會有編碼的這個步驟~
JavaScript 對URL編碼的提供了三個方式~
1. escape()               看不順眼的都編…  (除了 @ * / + )
2. encodeURI()            一樣是看不順眼的都編… 只是會改用UTF-8的編碼格式來轉成escape格式的字符串 (除了 ! @ # $& * ( ) = : / ; ? + ' )
3‧ encodeURIComponent()   與第二個編碼方式一樣,只是它看不順眼的更多了… (除了 ! * ( ) ' )
那既然有編碼,就會有反編碼!!
escape()  <-----> unescape()
encodeURI()  <----> decodeURI()
encodeURIComponent()  <----> decodeURIComponent()
 
runscriptnext:alert (escape('我愛小美http://keyout888.org.ru/') )
runscriptnext:alert (encodeURI('我愛小美http://keyout888.org.ru/') )
runscriptnext:alert (encodeURIComponent('我愛小美http://keyout888.org.ru/') )
runscriptnext:alert (decodeURIComponent(encodeURIComponent('我愛小美http://keyout888.org.ru/')) )
 
 

length 傳回字串長度,即所有字元的總數目
indexOf(a,b) 尋找條件字串在原字串中第一次出現的位置(若不下b則由0算起),若沒找到則傳回-1
lastIndexOf(a,b)    如同indexOf 方法,只是方向改從尾搜尋到頭
search() 傳回條件字串在原字串中第一次出現位置,若沒找到則傳回 -1
substring(a,b) 傳回原字串裏,從位置a 到b 的值 (  若只給定a ,則傳回由a 開始至最後一個字元的值)
replace(a,b) 將原字串中第一個a 值,用b值來取代
charAt(n) 抽出原字串中的第 n 個字元 (n由0算起)
split("分割點") 將原字串以"分割點"為中心,拆成多個陣列值 (陣列從0開始算)
toLowerCase() 大寫字母轉小寫字母
toUpperCase() 小寫字母轉大寫字母

 

RunScriptNext:var str="聰明漂亮美,無比美麗又大方!! Good !! ";
RunScriptNext:alert (str.length);  傳回 23
RunScriptNext:alert (str.indexOf("美"));   傳回 4
RunScriptNext:alert (str.lastIndexOf("美"));  傳回 8
RunScriptNext:alert (str.search("漂亮")); 傳回 2
RunScriptNext:alert (str.search("帥氣"));  傳回 -1
RunScriptNext:alert (str.substring(2,8)); 漂亮美,無比
RunScriptNext:alert (str.substring(2));  漂亮美,無比美麗又大方!! Good !!
RunScriptNext:alert ( str.replace('聰明','阿呆') );  阿呆漂亮美,無比美麗又大方!! Good !!
RunScriptNext:alert(str.charAt(6));  無
RunScriptNext:var new_ = str.split("!!");alert(new_[0]); 聰明漂亮美,無比美麗又大方
RunScriptNext:alert(str.toLowerCase());  聰明漂亮美,無比美麗又大方!! good !!
RunScriptNext:alert(str.toUpperCase()));   聰明漂亮美,無比美麗又大方!! GOOD !!

教學至此,沒基礎的人肯定是頭昏了…  所以來個提神的好東西吧!! 接下來要示範一個運用到目前為止所學的東西來突破 sound.jp 申請限制的例子~ 

因為該空間申請時會給你一個片假名的字串,然後要你把它轉換成平假名再填上去!! 但我連日文字都看不懂了,還片轉平咧,這不擺明了玩我嗎…  

不過還好,平、片假名是有相對位置的!! 所以我們只要把空間給定的字串於平假名的相對位置取出,自然就可以自動轉換囉~  

上面的寫法,都不出目前為止教學的部份,內容我就不再贅述。沒搞懂的人記得多看幾遍,一定要融會貫通才行!!

因為在此之前的教學都是在建立基本觀念,而從下面的 HTML DOM 開始,就要正式進入Script 之於GDL的應用囉~

 

 

HTML DOM 的概念就是要讓我們在網頁中所見即所得!! 

比如原本一張寫滿文字的紙,對有視覺障礙的人來說,在形式上就代表一張白紙罷了~ !

但若我們把紙裏的這些文字轉換成印有點痕或凸出字樣時, 他便可借此來辦識文字的內容,相對的這張紙就會是一文件囉!!

相近的意思,HTML DOM  指的是將網頁裏的所有標籤都物件化,使網頁中的所有標籤都會有一個對應的標籤物件,如此一來我們便可利用JS 來任意存取。

這就是網頁中所見即所得的函意~!  

但話雖如此,不同性質的標籤間是無法關聯的,也就是說此種作法將會据限於垂直處理,要能上下左右都關聯的話,就要再加入 W3C DOM 的概念~

( 看的粉想死的人別擔心,等後面的例子接上時,慢慢就能體會出來的      一_一"     )

 

有了基本認知後,接著我們便開始來看看如何去運用已物件化的標籤!!   處理的方式粉多,我介紹兩種就好,下面的例子會穿插兩種方式來寫 ,兩者都是通用的~

document.all.tags('標籤名').item(i)

document   .         all       .          tags('標籤名')                    .     item(i)
   文件裏      .      所有的   .       標籤中名為 '標籤名'            .     的第i 個                  註: i 從0 開始算起

 

document.getElementsByTagName('標籤名')[第幾個]


document    .     getElementsByTagName('標籤名')[i]
    文件裏       .     取得標籤物件名為 '標籤名' 的第i個                                            註: i 從0 開始算起

 

再來我就以下面這個網頁為例,示範一下何謂所見即所得~

 

 

比如我要的資料是關於連結的,那就是從標籤名為A著手,接著便可以得到它的相關屬性,比如 連結、連結文字、HTML碼 等… 

RunScriptNext:alert(document.all.tags('A').length)                                <--- 網頁中的連結總數,即是 4
RunScriptNext:alert(document.all.tags('A').item(0).href)                      <---   網頁中的第一個連結,即 http://google.com.tw/
RunScriptNext:document.all.tags('A').item(1).click()                             <----  按下網頁中的第二個連結,即  頁面會轉去yahoo
RunScriptNext:alert(document.all.tags('A').item(2).innerText)            <----  網頁中的第三個連結之連結文字,即 NT教學連結
RunScriptNext:alert(document.getElementsByTagName('A')[2].innerHTML)   <----  網頁中的第三個連結之連結文字(含HTML碼),即  <B> NT教學連結</B>

RunScriptNext:alert(document.getElementsByTagName('A')[2].outerHTML)   <----- 網頁中第二個連結含標籤之所有HTML碼
即是  <A HREF="http://keyout888.org.ru/NetTools/03.htm"><B>NT教學連結</B></A>

 

上述提到 innerText 、innerHTML、outerHTML  三個方法在GDL上是非常的實用的,一定要把它搞清楚喔!!

另外,click()  就像是滑鼠點一下(click 一下) 的意思,除了連結外,按鈕、圖片等一樣都可以用也~

再來,若我想取的資料是頁面中"我叫第二組文字"這段話,那就從是標籤名為 P 著手~

//因為文字的部份沒有HTML碼,所以這裏用 innerText 與 innerHTML 是同樣的結果
RunScriptNext:alert(document.all.tags('P').item(0).innerText)                                                <---- 我叫第二組文字
RunScriptNext:alert(document.getElementsByTagName('P')[0].innerHTML)                      <---- 我叫第二組文字

那如果我要找頁面中是否有我指定文字串呢??  那我們只要指定標籤為BODY ,再用其 innerText 的方法,就是頁面中所有的文字串囉~

RunScriptNext:var all_str = document.all.tags('BODY').item(0).innerText
RunScriptNext:if (all_str.search('NT教學連結')) {alert('有找到!!')} else {alert('沒找到指定文字串')}                <----- 結果就會出現   有找到!!

 

至此,是不是已真正實現所見即所得的運用囉!! 

 

那我們再回過頭來看一下之前我提到的垂直處理,大家看一下,我們在用上面方式的第一步時,是否都是先定義該標籤??

也就是說,只有在同標籤時,我們才有辦法去同時進行關聯處理,比如同為標籤A 下的所有連結才有其同時關聯性~

好比,我叫第一組文字 是落在標籤<H1>內,而我叫第二組文字則是落在標籤<P>內,雖然它們在頁面上看來就上下行而已,但我們就是無法同時處理…

倘若我們可以換個角度來看,其實 標籤<H1> 與 標籤<P> 都有個共同上層標籤 <BODY> 。若我們改從BODY往下看的話,原來二個不同性質的標籤不就是兄弟囉~

這個概念也就是 W3C DOM !! 把原本所有物件化的標籤再轉成有序的節點樹,此後每一個標籤、文字內容都會是一個節點~

借由父子、兄弟節點間的關聯,我們便可再進一步活化整個HTML的內容存取~  帥吧! 老皮…

下面我列一個用W3C 概念下去設計的例子給大家瞄一下就好,有興趣的請自行找書學習,本篇教學只到HTML DOM 就好,再寫下去我真的會粉想死~ 

例子中是把JP-YM 申請時的資料(select、input )用一個通用的模式取得後記錄 

//-- 取得申請資料並存入自定變數九中
runscriptnext:var tips= new Array('.pc','.byear','.ind','.job','.pw_q','.pw_a'),out=""
runscriptnext:for (y=0;y<tips.length;y++) {var objParentNode=document.all(tips[y]).parentElement;for (i=0;i<objParentNode.children.length;i++){ if (objParentNode.children[i].nodeName=="SELECT") {out+=objParentNode.children[i].options[objParentNode.children[i].selectedIndex].text+"、"} else {if (objParentNode.children[i].nodeName=="INPUT") out+=objParentNode.children[i].value+"、"};};out=out.substring(0,out.length-1)+" ★ "}
runscriptnext:document.all('.em').value=out
ItemToVariable:.em,***Variable9***
SetFieldValue:.em=

 

 

 


假設你上面的部份都理解了!!  那我們就可以開始來談談在寫GDL時,什麼時候需要用到Scirpt  ?

NT 內建的百來個指令可不是擺好看的,所以答案肯定是不會超過  填、按、連結 這三類範圍的~

 

NT 內建可以填的指令有三種,SetFieldValue 、SetFileValue、IndexInput,但通通都是將值覆蓋上去,無法累存!!

有時我們需要分次把資料放入同一個格子中時,就得用替代方案先把各次的資料放入自定變數中,最後再合併來填入。

或是碰到格子是陣列的形態時,也只有  SetFileValue、IndexInput 可以用,但 一個要置頂、另一個又不保証一定可用, 所以我才特地把如何用JS 填資料拿出來講~

先來看基本型:

document.form_name.fieldname.value= "要填入的值"
        文件         表單名       欄位名       值

再來,若表單或欄位沒有name 時,也可以用其所在的順序來代替,但要記住都是從0開始算

document.    forms[i]   .     elements[j]   . value = "要填入的值"
       文件     第i個表單         第j個物件             值

接著就是省掉表單直接指定 name 或 id 來填。            註:基本上一個網頁裏, id 不會有重覆,而 name 就不同,所以取name 的話要加上第i個,i 從0開始

document.getElementsByName("欄位名")[i].value = "要填入的值"

document.getElementById("欄位id").value = "要填入的值"

最後就是懶人法~ (這個方法是  IE only ,本來是不建議使用。但因為 NT 本身內建就是IE ,所以對GDL來說是沒差的^^ )

document.all('id').value= "要填入的值"

 

那再來複習一下前面有教過的 +=

document.all('test').value += '我愛小美' ;
就等同於
document.all('test').value = document.all('test').value +'我愛小美' ;

 

在網頁中何時會用到 按 呢?  應該就是指碰到   按鈕 或是  連結(文字) 了吧!  而NT內建對應的處理指令就是  ClickButton 和 ClickLink

倘若這兩個指令失效、或是沒有預期效果時,那就該是要特別處理了~

我舉 xuite 申請個人免費帳號為例子,它的送出鈕,就非常的討人厭~  ( 如下圖所示)

<td class="linkNo8" align="center" background="http://member.hinet.net/3gimages/bu_blue_bg.gif" valign="middle" width="60">
<a name="controlSubmit" id="controlSubmit" href="javascript:login()">確定送出</a>
</td>

從上面列出的原始碼來看,它只是個連結,一個有背景圖片的連結。所以我們會採用ClickLink:login() 的方式來按!! 而非用 ClickButton 。

但當你按了這連結後,你會發現它跑的不是表單的送出,而是另一段scirpt,也就是 login() 這段~

那我們就去原始碼找看看,該段如下~

function login()
{
//先把submit關掉,當沒有通過檢查,則再把submit打開
controlSubmit.style.visibility = "hidden";
controlReset.style.visibility = "hidden";

if( chkCoreProfile()==0 )
{
theform1 = document.registerForm;
theform1.action = "commonDoRegistForm.jsp";
theform1.method = "post";
theform1.submit();
return;
}

而在login()  裏面,又另外呼了  chkCoreProfile() 這段…  (因為粉長所以我只取重點出來)

function chkCoreProfile() // 傳回0表示成功, 1表示有沒填的必填欄位
{

theform1 = document.registerForm;
var ErrString = "";

var dotCount = 0;
var dashCount = 0;
……

……
var alertString = "請您再次確認下列資料,送出後將不可再修改下列資料:" + unescape('%0D%0A')+ unescape('%0D%0A');
alertString = alertString + "HiNet會員帳號:" + theform1.emailccfc049655.value + unescape('%0D%0A');
alertString = alertString + "真實姓名:" + theform1.NAMEccfc049655.value + unescape('%0D%0A');
alertString = alertString + "生日:" + theform1.yearccfc049655.value +"/"+ theform1.monthccfc049655.value +"/"+ theform1.dateccfc049655.value + unescape('%0D%0A');
alertString = alertString + "身份證字號:" + theform1.SSNccfc049655.value + unescape('%0D%0A');

var m_Confirmed = window.confirm( alertString )
if (m_Confirmed)
return 0;
else
return 1;

}

 

粉明顯的,上面這段就是在比對你輸入的資料,最後丟一個確認框來再跟你確認~  如下面所示~

 

既然我們知道了它的流程後,那便可以開始來看看如何才能閃掉這些多餘的動作~

話說回來,設計這網頁的人還真是好心,怕人家不會閃,還特地把關鍵點都標出來了… 

先看 chkCoreProfile() ,它的意思是若你按下確認鈕後,就會傳回值為 0。再回頭來看 login() ,當 chkCoreProfile() 傳回 0 時,才會進行下面的動作~

heform1 = document.registerForm;
theform1.action = "commonDoRegistForm.jsp";
theform1.method = "post";
theform1.submit();

所以,上面這段便是我們要的!!

我們只要把原本用 ClickLink:login()  來按的方式,改用那段來輸出,即是下面這樣子。那討人厭的身份資料確認框便不會出現囉~

RunScript:theform1 = document.registerForm;theform1.action = "commonDoRegistForm.jsp";theform1.method = "post";theform1.submit();

 

 

接著,我們再來看一下 ClickButton 和 ClickLink  都失效的例子!!

如上圖所示,GooglePage 的上傳既不是鈕也不是連結,所以 ClickButton 和 ClickLink   自然是會失效的~

此時,我們可試著從原始檔中來看,就會發現它有一段  onclick="TR_toggleSmUploadDrawer(this)" 

以後只要看到是onclick 開頭的,翻成GDL 來寫就是把後面雙引號去掉就行了~

RunScriptNext:onclick=TR_toggleSmUploadDrawer(this)

或是我們也可以用click() 的方式來按,這裏因為它已有id和name ,所以我們可以直接指定id 來按~

RunScriptNext:document.all('tr_toggle-upload-form').click()   

但若無id 也無name 呢?  此時就要弄個迴圈看看它是第幾個後,再來按就行囉~   ( 為何是28,是因為要以NT內建偵測到的原始碼為準喔!! )

RunScriptNext:document.all.tags('SPAN').item(28).click()

 

 

這部份該是大家最想學的 !! 雖然NT 內建的 GetFileLink: 指令已相當強,但碰到一些連結與連結文字是分離的狀況下,也就無用武之地了~

這情形在相本空間、BLOG 空間最是常見,現在我就教大家利用學到目前為止的東西來解決~

下面我就舉天空相本圖片空間為例~

我們要的連結是在圖片裏,但真實檔名確不在圖片中,它是獨立在圖片的下方。

所以即使可用  GetFileLink:userfile,***LinkSrc***  的方式來取得所有連結,但仍是缺了真實檔名。我們只好改採用JS 來取了!!

                                           

取法粉簡單,如上圖所示,每一個圖片會對應一個檔名,雖然它們是在不同的標籤內,但確有某種程度上的順序對應關系~

再回想上面教過的部份, 就是陣列!!  我們可以分兩次取存入陣列中,最後再來組合即可~

1. 先取連結

首先我們要定義一個陣列為 link_  好放連結,再來  index 這個變數是為了讓我們能順序儲存連結,以便將來與儲放真實檔名的陣列 照順序來結合~

接著看看圖中的源碼得知連結是落在 IMG 這個標籤內,但還要再加上過濾,只有當src 裏具有userfile 這個字串時,我們才取出存入link_ 陣列中~

RunScriptNext:var k=document.all.tags('IMG')
RunScriptNext:var link_ = new Array(),index=0 ;
RunScriptNext:for (i=0;i<k.length;i++)  {  if( k.item(i).src.search('userfile')!=-1)  { link_[index]= k.item(i).src; index++}  }

( JS 中,    != -1   的意思是說 負負得正,也就是有找到。若今天是要沒找到,那就用   == -1 ,意即真的沒找到  )

2. 取真實檔名 

一樣,我們再定義一個叫title 的陣列來放,而 index2 就同上面 index 的意思 ~

接著看看圖中的源碼得知真實檔名是落在 TD 這個標籤內。再加上過濾當outerHTML包含"albumDes"字串時,才會取出其innerText 放入陣列中~

RunScriptNext:var y=document.all.tags('TD')
RunScriptNext:var title = new Array(),index2=0;
RunScriptNext:for (i=0;i<y.length;i++) if (y.item(i).outerHTML.search('albumDes')!=-1) {title[index2]=y.item(i).innerText;index2++}

3.將連結與真實檔名組合成DSL支援的格式

原理就是一個蘿蔔一個坑,我們既已照順序取得了連結與真實檔名,那就再照順序來結合即可~

首先,我們要找一個格子來放這堆組合好的連結~ 通常我會找頁面中已存在的格子 (INPUT 、TEXTAREA 都行) ~

這裏因為是範例,所以我就自已建一個名為 All_File_Link 的格子來放~

AddWebHtml:<textarea name="All_File_Link" rows="1" cols="45"></textarea>

那在JS 中,要如何將資料放入 INPUT 、TEXTAREA  中呢?? 

就是用  document.all('ID或NAME').value = '  欲放的資料  '  ;                 註: 若要放入變數則不用再加引號

RunScriptNext:for (j=0;j<link_.length;j++) { document.all('All_File_Link').value +=  link_[j].replace( "album/t_" , "album/" ) + "|" + title[j] + "<Crlf>" ; }
ItemToVariable:All_File_Link,***Variable10***
AddOut:***Variable10***

最後附上教學的測試網頁完整範例給大家~!

go:http://album.blog.yam.com/album.php?userid=h24t7f245mbj&folder=2097164
AddWebHtml:<textarea name="All_File_Link" rows="1" cols="45"></textarea>
RunScriptNext:var y=document.all.tags('TD')
RunScriptNext:var title = new Array(),index2=0;
RunScriptNext:for (i=0;i<y.length;i++) if (y.item(i).outerHTML.search('albumDes')!=-1) {title[index2]=y.item(i).innerText;index2++}
RunScriptNext:var k=document.all.tags('IMG')
RunScriptNext:var link_ = new Array(),index=0 ;
RunScriptNext:for (i=0;i<k.length;i++) {if( k.item(i).src.search('userfile')!=-1) {link_[index]= k.item(i).src;index++}}
RunScriptNext:for (j=0;j<link_.length;j++){document.all('All_File_Link').value+=link_[j].replace("album/t_","album/")+"|"+title[j]+"<Crlf>";}
ItemToVariable:All_File_Link,***Variable10***
AddOut:***Variable10***
EXIT()

 

 

接著再來看Xuite_blog 的連結取法~

因為 xuite_blog 的檔案連結是在內頁裏,所以檔案割的愈多取連結就會愈想死…

但好在它內頁裏的連結,與外頁有一定的關聯,所以我們可以不用進內頁便可取得所有的連結~

首先,我把這八個檔的真實連結都從內頁裏手動取出排在一起分析,如下(源碼只列出其中三檔)

http://grm.cdn.hinet.net/xuite/e/d/1/f/14672058/blog_648737/dv/10028094/10028094.mpg
http://grm.cdn.hinet.net/xuite/e/d/1/f/14672058/blog_648737/dv/10028091/10028091.wmv
http://grm.cdn.hinet.net/xuite/e/d/1/f/14672058/blog_648737/dv/10028090/10028090.asf
http://grm.cdn.hinet.net/xuite/e/d/1/f/14672058/blog_648737/dv/10143777/10143777.mp4
http://grm.cdn.hinet.net/xuite/e/d/1/f/14672058/blog_648737/dv/10143922/10143922.swf
http://grm.cdn.hinet.net/xuite/e/d/1/f/14672058/blog_648737/dv/10143951/10143951.m4v
http://grm.cdn.hinet.net/xuite/e/d/1/f/14672058/blog_648737/dv/10143980/10143980.mov

http://e.mms.blog.xuite.net/e/d/1/f/14672058/blog_648737/dv/10143684/10143684.mp3

這樣列出來看就粉清楚~

只要是官方允許的檔案類型(前面七種),那它的前半段都會長的一樣! 即是 " http://grm.cdn.hinet.net/xuite/ " 的部份!

若不是官方公告的類型,那前面就會有點不一樣,如mp3 檔,它的前面就會長成 "http://e.mms.blog.xuite.net"

接著,只要是在同一個blog內,那後面那一大串,與 blog_id  也都會是一樣的~!

所後,只要能在主頁裏(第一個圖),可找到  1. e/d/1/f/14672058     2. 648737      3. 每個檔的編號與真實檔名  ,那 便可以不用再進內頁來完成快速取連結了~

1. 取類似 e/d/1/f/14672058  這串的值

WebStrToVariable:avatarPhoto><IMG,>,***Variable16***
GetstrToVariable:***Variable16***,net/,",***Variable16***
Instr:***Variable16***,/,***Variable10***,AFTER
SubStr:***Variable16***,1,***Variable10***,***Variable16***

2. 取 blog_id

WebStrToVariable:&bid=,&,***Variable11***

3. 每個檔的編號與真實檔名

從源始碼來看,我們會發現,檔案編號與真實檔名,都落在含有 "titlename"  的SPAN 標籤內,所以是粉容易取出來的~

RunScriptNext:var y=document.all.tags('SPAN');
RunScriptNext:for (i=0;i<y.length;i++) if(y.item(i).outerHTML.search('titlename')!=-1) { 執行碼  }

真實檔名就用  innerText 就是了,而副檔名就從裏面取出來即可~

var g3=y.item(i).innerText,g4=g3.substring(g3.lastIndexOf('.'))

編號就比較麻煩些,我們先取出 innerHTML ,即是  <a href="/z02y0nx8g/z02y0nx8g/10028094">klmcodec_000.mpg</a>

然後再將這個字串,用    ">   為中心割成兩段,就變成    <a href="/z02y0nx8g/z02y0nx8g/10028094   與  klmcodec_000.mpg</a>

接著再從 <a href="/z02y0nx8g/z02y0nx8g/10028094 中,取出  /10028094 

var g=y.item(i).innerHTML.split('">'),g1=g[0].substring(g[0].lastIndexOf('/'))

所以, g1 指的是 /編號  ,  g3 指的是真實檔名 ,  g4 指的副檔名

 

整個再通通組合起來就變成如下的~

其中在裏面加了一個判斷式,先把 g3(真實檔名) 轉成小寫字母,然後再來判斷g3是否為mp3 ,若是的話,就用 http://e.mms.blog.xuite.net/ 反之則用 http://grm.cdn.hinet.net/xuite/

output:ref://http://www.xuite.net/
RunScriptNext:z1='***Variable16***',z2='***Variable11***',z3='http://grm.cdn.hinet.net/xuite/',z4='http://e.mms.blog.xuite.net/';
RunScriptNext:var y=document.all.tags('SPAN');
RunScriptNext:for (i=0;i<y.length;i++) if(y.item(i).outerHTML.search('titlename')!=-1) {var g=y.item(i).innerHTML.split('">'),g1=g[0].substring(g[0].lastIndexOf('/')),g3=y.item(i).innerText,g4=g3.substring(g3.lastIndexOf('.')) ; if (g3.toLowerCase().search('mp3')!=-1) {var z5=z4} else {z5=z3};document.all('All_File_Link').value+= z5+ z1+ 'blog_'+z2+'/dv'+g1+g1+g4+'|'+g3+'<Crlf>'; }
ItemToVariable:All_File_Link,***Variable10***
AddOut:***Variable10***

  

最後附上教學測試完整範例

go:http://blog.xuite.net/z02y0nx8g/z02y0nx8g
AddWebHtml:<textarea name="All_File_Link" rows="1" cols="45"></textarea>
//-- 取得類似 9/3/2/6/14666668/ 這種的
WebStrToVariable:avatarPhoto><IMG,>,***Variable16***
GetstrToVariable:***Variable16***,net/,",***Variable16***
Instr:***Variable16***,/,***Variable10***,AFTER
SubStr:***Variable16***,1,***Variable10***,***Variable16***
//-- 取blog_id
WebStrToVariable:&bid=,&,***Variable11***
output:ref://http://www.xuite.net/
RunScriptNext:z1='***Variable16***',z2='***Variable11***',z3='http://grm.cdn.hinet.net/xuite/',z4='http://e.mms.blog.xuite.net/';
RunScriptNext:var y=document.all.tags('SPAN');
RunScriptNext:for (i=0;i<y.length;i++) if(y.item(i).outerHTML.search('titlename')!=-1) {var g=y.item(i).innerHTML.split('">'),g1=g[0].substring(g[0].lastIndexOf('/')),g3=y.item(i).innerText,g4=g3.substring(g3.lastIndexOf('.')) ; if (g3.toLowerCase().search('mp3')!=-1) {var z5=z4} else {z5=z3};document.all('All_File_Link').value+= z5+ z1+ 'blog_'+z2+'/dv'+g1+g1+g4+'|'+g3+'<Crlf>'; }
ItemToVariable:All_File_Link,***Variable10***
AddOut:***Variable10***
EXIT()

 

ps.. 以上取連結法只適用該blog 只有單頁時!! 若有多頁請自行修改一個地方即可~ (修改方式一樣不超過教學提過的內容,請自行努力)

 


 

會將框架擺到最後面,是因為它對我們寫GDL 來說,只是加個定義而已,並不會影響之前所學的部份!! 

雖然框架亂麻煩的,但只要你能站在對的角度去了解它構成的方式,再加上一些特定的調用方法,那用於寫GDL來說,其實就像喝水般容易的…  

 

框架分成兩種~

1. 內框架 Iframe

說白點就是網頁中的網頁!!

此種形態的框架是以標籤名為 <iframe>的方式內置於網頁中,也就是說它與其它的標籤都同處於一個html 下!! 

此時若我們照樣使用之前 HTML DOM 的方式,那只是把標籤<iframe> 給物件化~

接著我們能做的事,就只是讀取該物件的 src 、 name 、innerText 、outerHTML 等而已!!

例: 此網頁中有內置一個名為test2 ,id 為 test 的 iframe

go:http://keyout888.org.ru/001.htm
RunScriptNext:alert(document.all.tags('IFRAME').item(0).src)                                             <---  http://keyout888.org.ru/003.htm
RunScriptNext:alert(document.getElementsByTagName('IFRAME')[0].name)                     <----  test2
RunScriptNext:alert(document.getElementsByTagName('IFRAME')[0].outerHTML)           <---   如下 
<iframe id="test" name="test2" src="http://keyout888.org.ru/003.htm" height="500" width="700"></iframe>

 

但如果今天我們要處理的是內框架裏面的網頁物件呢 ?  也就是說我們需要的是整個 iframeDOM,而不 再單單只是要調用一個iframe_object 的屬性了 ~

此時就要改採特定的方式!! 如下三種~~

window.frames["iframe id 或name "]

window.frames[i]       i從0開始,指頁面中第i個iframe

iframe_id 或name

接著在 iframeDOM 裏面的相關處理方式,就 又是一 HTML DOM  了!!  所以看你是要 按、填、或執行某段SCRIPT 、怎樣的,都一樣用HTML DOM 的寫法就行~

例: 此網頁中有內置一個名為test2 ,id 為 test 的 iframe。我用以上三種方式來穿插示範如何去活用  iframeDOM ~

go:http://keyout888.org.ru/001.htm   
runscriptnext:window.frames[0].document.all('TextTest1').value='我愛小美'                     <--- 在內框頁裏名為 TestTest1 的欄位填上  我愛小美
runscriptnext:window.frames['test2'].document.all('TextTest2').value='聰明漂亮美'           <--- 在內框頁裏名為 TestTest2 的欄位填上 聰明漂亮美
runscriptnext:alert(test.document.getElementsByTagName('BODY')[0].innerText)             <--- 把內框頁的所有文字列出來
//runscriptnext:test2.document.all.tags('A').item(0).click()                                                    <--- 點擊內框頁裏的第一個連結,結果內框頁會轉向yahoo
runscriptnext:test2.go_()                                                                                                      <---執行test2這個內框頁裏的go_() 這段script
EXIT()

註:JS 有跨網域的安全性問題,若 iframe 的來源 與html 的來源不一樣(domain 不同), 那就會有無法存取的問題!!

 

2. 框架 frame 與 框架組 frameset

框架組顧名思義就是各框架間的集合。例如下面是 home.htm  的源碼。裏面我利用框架組的方式定義兩個互斥的框架來把整個視窗割成左、右各一半~

<FRAMESET COLS="50%,*" ID="homeframe">
<FRAME name="leftframe" src="A.htm">
<FRAME name="rightframe" src="B.htm">
<FRAMESET>

藍框代表的是 home.htm  、紅框代表的是 A.htm   、綠框代表的是 B.htm

這種框架定義的方式與內框架最大的差別就在於它不再是網頁中的網頁!! 所有框架間都是互斥的,我們可以把它們全視為不同的window來看待~

在網頁設計時,各框架間的關系必需從不同角度去考量~

例如我現在是位於  A.htm 中,那包住我的就是 home.htm ,也就是父框架。若我要以目前的角度去與home.htm 關聯,那我就必需要用 windown.parent  來作~

但是粉幸運的,寫GDL 就不用這麻煩 !! 因為我們一定是處於 hmoe.htm 的角度下來寫,也就是當下的網頁一定是框架組所在頁!!

也就是我們是以老子的角度來看孩子們,這一切都變的如此容易了~ 

 

與處理內框架一樣的想法,我們的目的在於 frameDOM,所以要先把我們的目標框架給定義出來~

frames["frame_id 或 name"]

frames[i]      i從0開始,指頁面中第i個frame

frame_id  或 name

以home.htm 為例子,若我們想處理 A.htm 內的東西,就是用  frames["leftframe"]  或  frames[0]  或 leftframe   來作開頭,接著下來就又是 HTML DOM 的方式囉~

RunScriptNext:alert(leftframe.document.getElementsByTagName('BODY')[0].innerText)                      <--- 列出A.htm 頁面中的所有文字
RunScriptNext:frames[1].document.all.tags('A').item(3).click()                                                                     <---- 點擊B.htm 裏第四個連結
RunScriptNext:alert(frames['rightframe'].document.getElementsByTagName('BODY')[0].innerText)   <--- 列出B.htm頁面中的所有文字

 

好,那基礎的看懂後,接下來再加入一些變化!!

底下是 seednet 郵空的架構~

我們同樣是以紅色大框的角度來看整個HTML ,所以我們看到了

funclist 、menu 、main 三個frame,而當中  main 中又包括了兩個子 frame ,分別為 flist 與 fdetail 。

所以它們間的關系為: funclist 、menu 、main 是同一層的,而flist 與 fdetail  是在下一層的~

 

假設今天我想要從seednet 郵空裏,把所有的信件標題存下來的話,那應該如何處理呢??

首先,我們要先看看有信件標題的頁面是在整份HTML 中的哪裏!!  從上圖中粉清楚可以了解是位於 flist 這個frame 中!!

但  flist 是有爸爸的,你要動它前,不問一下是粉不尊重的~  所以我們要從 main 開始來定義起才對!!

多層式的框架定義,可以框架名或順序來混搭!!  如下面四種方式通通是一樣的意思~

main.flist
main.frames[0]
frames[2].flist
frames[2].frames[0]

定義好框架的部份後, 接下來就又是回到 frame_DOM 的處理模式了~

從上面我們可以看出,每封信的標題就落在標籤SPAN 中,我們只加個過濾條件為 outerHTML 包函COLOR這個字串,那其 innerText 就是我們要的東西囉~

 

RunScriptNext:var k=main.flist.document.getElementsByTagName('SPAN');
RunScriptNext: for (i=0;i<k.length;i++) { if (k[i].outerHTML.search('COLOR')!=-1) {funclist.document.all('KEYWORD').value+=k[i].innerText+'<Crlf>'} }
ItemToVariable:KEYWORD,***Variable51***
addout:***Variable51***
over() 

這裏會用大寫的COLOR 是因為NT 內建原始碼偵測到就是大寫,所以要以NT 為準,不能用 color 

另外會選擇用 funclist.document.all('KEYWORD').value   這個格子來放是因為 NT 的指令只適用一層式的框架而已,第二層以上的話,指令就會失效~

所以為了方便後來我會用到的 ItemToVariable 指令,我就只能選 funclist 、menu 、main  這三個frame 裏已有的格子來放,那自然是第一個frame裏的第一格囉~

 

至此,整個框架的相關寫法都已交待清楚了!! 以後看到框架不要再頭大了,管它是幾框還是內框啥的,只要站在對的角度去分析它,自然就都不是問題囉!!

 

 

Free Web Hosting