2012年7月31日 星期二

deAmp() 函數 和 server.HtmlEncode() 函數

公司的前人寫了支函數: deAmp()


function deAmp(tempstr)
    xs = tempstr
    if xs = "" OR isNull(xs) then
        deAmp = ""
        exit function
    end if
    deAmp = replace(xs,"&","&")
end function

我實檢的結果發現,  function deAmp()  函數其實可以直接使用 server.htmlEncode() 函數來代替, 而且 htmlEncode() 做的事情比 deAmp() 還多.
 
以 & 為例:
deAmp() 結果是 = &
htmlEncode() 結果也是 = &
 
htmlEncode() 還會多做 > < 的轉換, 也可以避免 tag 在 xml 裡被跳脫, 

結論: 直接以 server.HtmlEncode( 取代 deAmp(

2012年7月24日 星期二

anita 提供的 jQuery 版的廣告輪播加強版 (v1.1)

上次Anita 提供的輪播 jQuery, 其實有2個小地方不太美觀, 這次找到時間就把他改掉, 雖然沒有寫的很完美, 但加減可以用, 致少有改善...

1. 調整圖片輪播的方式, 當輪到最後一張時, 不是切到第1張, 而是從右向左輪播.
2. 調整圖片與圖片間的間距, 如下圖所示, 原本會多空500 px的空白.


修改後的 javascript 如下: 

$(function(){
 slider.init();
});
var slider={
 num:-1,
 cur:0,
 cr:[],
 al:null,
 at:3*1000,
 ar:true,
 imagesize:520,
 direction:1,
 init:function(){
    if(!slider.data || !slider.data.length)
        return false;
    var d=slider.data;
    slider.num=d.length;
    var pos=Math.floor(Math.random()*1);  //slider.num);
    for(var i=0;i<slider.num;i++){
        $('#'+d[i].id).css({left:((i-pos)*slider.imagesize)});
        $('#slide-nav').append('<a id="slide-link-'+i+'" href="#" onclick="slider.slide('+i+');return false;" onfocus="this.blur();">'+(i+1)+'</a>');
    }

    $('img,div#slide-controls',$('div#slide-holder')).fadeIn();
    slider.text(d[pos]);
    slider.on(pos);
    slider.cur=pos;
    window.setTimeout('slider.auto();',slider.at);
 },
 auto:function(){
    if(!slider.ar)
        return false;
    var next=slider.cur+slider.direction;
    if(next>=slider.num){
        slider.direction*=-1;
        next=slider.num-2;
    }
    if(next<=0){
        slider.direction*=-1;
        next=0;
    }
    slider.slide(next);
 },
 slide:function(pos){
    if(pos<0 || pos>=slider.num || pos==slider.cur)
        return;
    window.clearTimeout(slider.al);
    slider.al=window.setTimeout('slider.auto();',slider.at);
    var d=slider.data;
    for(var i=0;i<slider.num;i++)
        $('#'+d[i].id).stop().animate({left:((i-pos)*slider.imagesize)},1000,'swing');
    slider.on(pos);
    slider.text(d[pos]);
    slider.cur=pos;
 },
 on:function(pos){
    $('#slide-nav a').removeClass('on');
    $('#slide-nav a#slide-link-'+pos).addClass('on');
 },
 text:function(di){
    slider.cr['a']=di.client;
    slider.cr['b']=di.desc;
    slider.ticker('#slide-client span',di.client,0,'a');
    slider.ticker('#slide-desc',di.desc,0,'b');
 },
 ticker:function(el,text,pos,unique){
    if(slider.cr[unique]!=text)
        return false;
    ctext=text.substring(0,pos)+(pos%2?'-':'_');
    $(el).html(ctext);
    if(pos==text.length)
        $(el).html(text);
    else
        window.setTimeout('slider.ticker("'+el+'","'+text+'",'+(pos+1)+',"'+unique+'");',30);
 }
};


相關文章:
anita 提供的 jQuery 版的廣告輪播
http://maxtellyou.blogspot.tw/2012/06/anita-jquery.html

2012年7月20日 星期五

測試IIS 的 URL 的 GET 模式可以傳多少變數內容

之前開發了一個功能, 是彈出新視窗來選取單位, 選取的部份是透過 javascript 的 opner 來存取, 長度上面不會有問題, 但接下來的分頁, 排序或匯出功能都是透過 URL 來傳遞, 企畫問我那不修改程式的情況下, 最多可以勾選多少個單位?


我的情況是每一個單位長度9碼,還會有一個逗號做間隔, 每一筆是總共占掉10個 bytes, 假設 deptID(單位代碼) 有 510筆, id 變數內容有 5100 bytes(510筆 x 10 bytes), 整個 queryString 因為還要加上 "id=" 的這3個 bytes, 所以是 5103 bytes.



程式碼, 增加到 511筆時:


就到 Web Server 的極限值了, deptID 的長度應該要到 5110 bytes 可是只拿到 5102 bytes, queryString 應該是 5113 bytes, 可是只拿到 5105 bytes.


結論: 以一個單位占9碼來說, 大約可以傳500筆的單位資料在 URL 裡.


附註: 不一樣的 Web Server 都會有落差, 有尤其是 Windows Server 2008 的 IIS 7, 預設值很小...



相關文章:
IIS6 遇到 URL 太長造成 Bad Request (Request Header Too Long)
http://maxtellyou.blogspot.tw/2012/06/iis6-url-bad-request-request-header-too.html


Error message when you visit a Web site that is hosted on a server that is running Internet Information Services 7.0: "HTTP Error 404.10 - REQUEST_HEADER_TOO_LONG"
http://support.microsoft.com/kb/942077/

2012年7月19日 星期四

xsl 副程式分享, 產生N個tab

假設有一個系統, 允許使用者勾選要顯示的欄位如下圖所示:

產生出來的 HTML 表格如下:

html 的 table 可以使用 colspan=N 來控制合併儲存格的數量, 如果想使用 xsl 產生 .csv 的檔案出來,  要怎麼產生出對應該的儲存格間距呢?  我的解法是透過 xsl 的副程式來解決, 計算儲存格間距的問題.


步驟1: 第1層要增加的tab 數(level1tabs) 
= (第3層的數量 x 第2層的數量) - 1 
= (2 x 3) -1 
= 5

<xsl:variable name="level1tabs"><xsl:value-of select="($level3count*$fieldCount)-1"/></xsl:variable>


步驟2: 呼叫副程式, 並傳入變數5
<xsl:call-template name="outputTabs"><xsl:with-param name="maxNum"><xsl:value-of select="$level1tabs"/></xsl:with-param></xsl:call-template>


步驟3: 被呼叫的副程式如下:
<xsl:template name="outputTabs">
<xsl:param name="currentNum">1</xsl:param>
<xsl:param name="maxNum"/><![CDATA["" ]]><xsl:if test="$maxNum!=''"><xsl:if test="$currentNum &lt; $maxNum"><xsl:call-template name="outputTabs">
<xsl:with-param name="currentNum"><xsl:value-of select="$currentNum + 1" /></xsl:with-param>
<xsl:with-param name="maxNum"><xsl:value-of select="$maxNum" /></xsl:with-param>
</xsl:call-template></xsl:if></xsl:if></xsl:template>


update: 2012-08-22, 副程式升級, 可以自行定義要輸出的符號.

[Asp] Server.URLEncode 和 encodeURIComponent 的差別

一般的情況下, 透過URL 傳遞參數, 在asp 裡只需要把要傳的變數內容透過 Server.URLEncode 就解決了, 但如果是要讓 ASP 和 javascript 同時都可以存取的話, 最好的解決方法是透過 aspEncodeURIComponent() 來解決.

以 "遺產" 這個中文字來說,
1. 在 Big5 的網頁,裡, 直接按下 submit 傳到  action 的網址, 會變成 "%BF%F2%B2%A3",
2.  Big5 的程式碼透過 Server.UrlEncode() 會產生成 "%BF%F2%B2%A3"
3.  Utf-8 的程式碼透過 Server.UrlEncode() 會產生成 "%E9%81%BA%E7%94%A2"
4. 在 Big5 的程式碼透過  aspEncodeURIComponent()  會產生成 "%E9%81%BA%E7%94%A2"
5. 在網頁裡透過 javascript 的 encodeURIComponent() 會產生成 "%25E9%2581%25BA%25E7%2594%25A2"


說明: 把 %25 視為 %, 就可以看的出來encodeURIComponent() 是產生成utf-8 編碼.




為什麼需要轉換編碼? 因為客戶的網站是 Big5 編碼, 他使用了 google site search 功能, google site search 如果是直接存取 URL 裡的變數, 有可能需要把變數存成 utf-8 編碼來讓 javascript 做處理.




附上 Asp 的 aspEncodeURIComponent 副程式:

Function aspEncodeURIComponent(sStr)
    aspEncodeURIComponent = myEncodeURIComponent(sStr)
%>
<script language="javascript" type="text/javascript" runat="server">
  function myEncodeURIComponent(sStr){
      return encodeURIComponent(sStr);
  }
</script>
<%
End Function



相關文章:
JavaScript 的 encodeURIComponent() 會將字串轉換成 UTF-8 編碼
http://blog.longwin.com.tw/2010/01/javascript-encodeuri-component-utf-8-2010/


2012年7月16日 星期一

模擬手機的瀏覽器 Mobile Emulator

專案上有一個版型是給手機用的,要測試UI是不是正常,有3個方法可以測,用Opera 那個會比較準一點,因為Windows 上的 Font Size 跟手機上的不太一樣.




方案1:
最方便的解法是透過 Opera Mobile Emulator, 下載網址:
http://www.opera.com/developer/tools/mobile/





方案2:
透過 google chrome, 先把所有的 chrome 視窗關閉後, 在 "執行"的地方輸入:
chrome.exe --user-agent="Mozilla/5.0 (Linux; U; Android 2.2; en-us; Nexus One Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1"


就可以開出 andriod 2.2 的user agent 來進行模擬,其他相關的 user-agent 有:

iPhone
chrome.exe --user-agent="Mozilla/5.0 (iPad; U; CPU OS 3_2_2 like Mac OS X; en-us) AppleWebKit/531.21.10 (KHTML, like Gecko) Version/4.0.4 Mobile/7B500 Safari/531.21.10"


Android
chrome.exe --user-agent="Mozilla/5.0 (Linux; U; Android 2.2; en-us; Nexus One Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1"


Resize 視窗工具:Sizer
http://www.brianapps.net/sizer/



方案3:
下載 andriod SDK, 透過手機模擬器來測,這個也會很準,但電腦不夠好最好不要試,因為很慢.



相關文章:
google keyword: 模擬手機瀏覽器

2012年7月12日 星期四

Firefox 不支援 innerText 屬性的解決方法

今天不小心用到 Firefox 開啟一個專案的頁面, 有一個 pop-up 視窗要帶回值到 opener 視窗時傳回的是  undefined, 如下圖:


google 了一下發現, 原來是 Firefox 不支援 innerText 屬性, 所以原本的function:

function getinnerText(id){ return (getE(id)!=undefined)?getE(id).innerText:undefined; }

重新改寫為:

function getinnerText(id){
    var hasInnerText = (document.getElementById(id).innerText != undefined) ? true : false;
    return (hasInnerText?document.getElementById(id).innerText:document.getElementById(id).textContent);
}


解決完畢.

2012年7月6日 星期五

microsoft.XMLDOM 在 XSL 套用大量資料時效能變差的解法

今天解決了一個 ASP 處理字串太長(太大) 時造成的效能不好的問題, 接著遇到是 XML + XSL 在遇到資料量太大時也會出問題, 這次的資料量是只有 300筆.


1. 首先, 在 xsl 套版前, 把系統時間印出來看看.


2. 在 300筆資料的情況下, 光這一行 transformNode() 就掉了24秒, 真是太令人吃驚!!!


3. 解決後, 一樣 300筆的資料量, 只用掉1秒.


解決辦法:
原本 create object 方式
set oxsl = server.createObject("microsoft.XMLDOM")

修改為
set oxsl = server.createObject("Msxml2.DOMDocument.6.0")

效能就變好了, 只是 Msxml2.DOMDocument.6.0 有一些問題, 就是他的 xsl include 外部檔案好像預設是 disable 的, 再透過下面這幾行來設定即可:

    oXSL.resolveExternals = True
    oXSL.async = False
    oXSL.setProperty "AllowDocumentFunction", True
    oXSL.setProperty "AllowXsltScript", True


附註:
1. Msxml2.DOMDocument.6.0 和 microsoft.XMLDOM 在 xsl 裡的空格和Enter 定義不同, 套出來的結果會有些許差異.


2. 如果要使用 "Msxml2.XSLTemplate.6.0" 來套版, 那 XSL 的定義必須是使用 oxsl = server.createObject("Msxml2.FreeThreadedDOMDocument.6.0")







相關文章:
Using ASP with XSLT Processor and Template Objects
http://msdn.microsoft.com/en-us/library/windows/desktop/ms761371(v=vs.85).aspxUsing ASP with XSLT Processor and Template Objects

Windows Server 2008 NTP 網路校時的設定

1. 先透過 "系統管理員" 權限開啟命令例視窗, 執行下面指令:

w32tm /config /update /manualpeerlist:"time.stdtime.gov.tw clock.stdtime.gov.tw tick.stdtime.gov.tw tock.stdtime.gov.tw watch.stdtime.gov.tw,0x1"

指令說明: 設定 NTP Server 為 這幾台 server: time.stdtime.gov.tw clock.stdtime.gov.tw tick.stdtime.gov.tw tock.stdtime.gov.tw watch.stdtime.gov.tw

再下指令: w3wtm /resync
就可以同步了,


設定方式有2種, 一種是透過 w32tm 下指令, 或是過 RegEdit 來設定.

設定註冊檔位置:

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W32Time\Parameters]
"Type"="NTP"




當您執行w32tm /resync命令,以與外部時間來源同步化失敗時, 因為需要去設定一下
說明: 第1之執行 /resync 時, 由於與 NTP Server 時間誤差太大, 所以無法更新, 透過修改註冊檔後, 重新停用, 再啟用服務, 就自動更新時間了.


機碼位置在:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W32Time\Config

MaxNegPhaseCorrection (負差校正) - 若網路時間比本地時間慢超過這個秒數就不自動校正
MaxPosPhaseCorrection (正差校正) - 若網路時間比本地時間快超過這個秒數就不自動校正



相關文章:
如何調整 Windows 作業系統的時間正確性 ( 終極指令版 )
http://blog.miniasp.com/post/2009/06/How-to-adjust-Time-using-Windows-Time-Service.aspx

Windows Time Service Tools and Settings
http://technet.microsoft.com/en-us/library/cc773263(v=ws.10).aspx


Windows Server 2008 中的 Windows 時間服務與產生的網際網路通訊
http://technet.microsoft.com/zh-tw/library/cc731790(v=ws.10).aspx

How to configure an authoritative time server in Windows Server
http://support.microsoft.com/kb/816042#method2

將移除 ntext、text 和 image 等資料類型。改用nvarchar(max)、varchar(max) 和varbinary(max)

資料來源:
http://technet.microsoft.com/zh-tw/library/ms187993.aspx


重要事項 重要事項
在未來的 Microsoft SQL Server 版本中,將移除 ntexttext 和 image 等資料類型。 
請避免在新的開發工作中使用這些資料類型,
並規劃修改目前在使用這些資料類型的應用程式。 
ntext
最大字串長度為 2^30 - 1 (1,073,741,823) 位元組的可變長度 Unicode 資料。 儲存體大小 (以位元組為單位) 是輸入字串長度的兩倍。 ntext 的 ISO 同義字是 national text
text
在伺服器字碼頁中、最大字串長度為 2^31-1 (2,147,483,647) 的可變長度非 Unicode 資料。 當伺服器字碼頁使用雙位元組字元時,儲存體大小仍是 2,147,483,647 個位元組。 儲存體大小有可能少於 2,147,483,647 個位元組,這會隨著字元字串而不同。
image
0 到 2^31-1 (2,147,483,647) 位元組的可變長度二進位資料。



附註:
SQL Server 2000中是不支持不支持varchar(max)和nvarchar(max)類型的。varchar(max)、nvarchar(max) 和varbinary(max)是SQL Server 2005開始有的類型。

SQL Server 2005中加入了varchar(max)、nvarchar(max) 和varbinary(max) 數據類型,統稱為大值數據類型(large-value data types),都用max說明符標示。varchar(max)、nvarchar(max) 和varbinary(max) 數據類型分別對應到SQL Server 2000以及以前版本中的varchar、nvarchar和varbinary數據類型。

大值數據類型可以存儲最大為 2^31-1 個字節的數據,所以在使用varchar、nvarchar和varbinary數據類型的地方,完全可以使用與之對應的大值數據類型。以前操作數據庫經常遇到「SqlException:將截斷字串或二進制數據錯誤」(欄位長度不夠) 的錯誤,引發這個異常與數據類型的長度或精度有很大關係,現在我們使用大值數據類型的話就會在一定程度上避免出現這些問題。





相關文章:
NTEXT vs NVARCHAR(MAX) in SQL 2005
http://geekswithblogs.net/johnsPerfBlog/archive/2008/04/16/ntext-vs-nvarcharmax-in-sql-2005.aspx


傳統ASP字串效能改善(A Fast String Builder Class For Classic ASP)

我寫了一支資料匯出的程式, 資料量才 988 筆, 可是居然花了60秒才跑的完, trace 程式後發現是大量字串相加造成的問題.


程式修改之前, 資料 979到987 就需要花掉1秒中,
即1秒只能處理 9筆資料.


程式修改之前, 第1秒可以處理 93筆資料, 
由於字串變大而且重覆相加造成效能變差.


在不修改架構的情況下, 只修改字串相加的地方改用字串物件,
第1秒可以處理到 141筆資料, 而且對於後續資料處理的速度滿固定的,
 每秒都可以處理 140筆左右.


修改架構, 不透過 function 傳回字串, 而是所有的程式存取同一個字串物件,
處理速度可以到1秒 208筆資料, 原本處理60秒才能跑完的 988筆資料,
修改後5秒內可以跑完.




使用 Asp String Builder Object 來處理ASP的程式範例:

    dim oString
    Set oString = New ASPStringBuilder
    oString.Append "要相加的字串內容"
    myString = oString.ToString()
    set oString = nothing


在 asp 改用 .net 的StringBuilder 來處理, 速度上差不多,  也是5秒內跑完:
心得:
字串處理, 的問題應該解決了, 要克服其他的(程式流程或寫法), 才能讓反應速度再上去...



使用.net 的StringBuilder 來處理, ASP的程式範例:

    dim oString
    Set oString = Server.CreateObject("Max.StringBuilderObject")
    oString.Append "要相加的字串內容"
    myString = oString.ToString()
    set oString = nothing





相關文章:
A Fast String Builder Class For Classic ASP

字串物件 source code 下載:


google keyword:
classic asp stringbuilder


附註: 
應該有其他更好的解決辦法....

2012年7月4日 星期三

pop-up 的子視窗修改父視窗 select box 的方法

直接修改會出錯, 重點在要透過 window.opener.document.createElement 在父視窗做處理即可. 分享相關的 javascript 如下:


// empty Topics select list content
function clearTopicList(select) {
    while (select.length > 0) {
        select.remove(select.length-1);
    }
}

// add item to select element the less
// elegant, but compatible way.
function appendToSelect(select, value, content) {
    var opt;
    //opt = document.createElement("option");
    opt = window.opener.document.createElement("option");
    opt.value = value;
    //var theData = document.createTextNode(content);
    var theData = window.opener.document.createTextNode(content);
    opt.appendChild(theData);
    select.appendChild(opt);
}

    clearTopicList(window.opener.document.reg.your_field);
    appendToSelect(window.opener.document. your_form .your_field ,"your_value","your_text");

分享 asp 副程式 檢查 字串是否為 html tag


'// purpose: 用 "本文內容" 自動判斷文章是 html or text, text 時把 enter 換 <br/>
'// ex: ret = htmlMessage(str)
function htmlMessage(byval str)
    str = trim("" & str)
   
    dim isHtmlContentFlag
    isHtmlContentFlag = IsHtmlContent(str)
    'response.write "<h1>isHtmlContentFlag:" & isHtmlContentFlag & "</h1>" & vbcrlf
   
    if isHtmlContentFlag then
        '// do nothing
    else
        '// do convert.
        str = replace(str,vbCRLF&vbCRLF,"<P>")
        str = replace(str,vbCRLF,"<BR>")
        str = replace(str,chr(10),"<BR>")
    end if
    htmlMessage = str
end function


'// purpose: 檢查 字串是否為 html tag.
'// PS: 其實也可以用 pattern 來做 match 應該會更好.
'// ex: ret = checkIsHtmlContent(str)
'// return:
'//     True: html
'//     False: text
function IsHtmlContent(byval str)
    dim isHtmlContentFlag
    isHtmlContentFlag = not True
   
    if instr(1, str,"<P ",1)>0 or instr(1, str,"<P>",1)>0  or instr(1, str,"<P/>",1)>0 then
        isHtmlContentFlag = True
    end if
    if instr(1, str,"<BR ",1)>0 or instr(1, str,"<BR>",1)>0 or instr(1, str,"<BR/",1)>0 then
        isHtmlContentFlag = True
    end if
    if instr(1, str,"<td",1)>0 and instr(1, str,"</td",1)>0 then
        isHtmlContentFlag = True
    end if
    if instr(1, str,"<ul",1)>0 and instr(1, str,"</ul",1)>0 then
        isHtmlContentFlag = True
    end if
    if instr(1, str,"<div",1)>0 and instr(1, str,"</div",1)>0 then
        isHtmlContentFlag = True
    end if
    IsHtmlContent = isHtmlContentFlag
end function

Facebook 留言板