2012年3月24日 星期六

動態產生HTML element -- document.createElement


我們可以利用document.createElement()動態的產生HTML的element,再利用Node.appendChild()插入某個Node底下,或利用Node.removeChild()自某個Node底下移除,更多資訊可以參考[1]。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <title>auto table</title>
</head>

<body>
  <table id="brook" summary=""></table>
  <script type="text/javascript">
  //<![CDATA[
    function create_new_row_button(eT, msg) {
        var eR = document.createElement("tr");
        var eC = document.createElement("td");
        var eB = document.createElement("input");
        eB.type = "button"
        eB.value= msg;
        eB.style.width = "100px";

        eT.appendChild(eR);
        eR.appendChild(eC);
        eC.appendChild(eB);
    }
    var station = [
        {name: "CHT"},
        {name: "TW"},
    ];
    for (var i = 0; i < station.length; i++) {
        create_new_row_button(document.getElementById("brook"),
                              station[i].name);
    }
  //]]>
  </script>
</body>
</html>






2012年3月3日 星期六

glibc讀書心得 -- Ch2 Error Reporting


在glibc中會去偵錯並且回傳錯誤值,通常我們都應該去檢查這些回傳值,並且作error-handling,比如開檔 open()/fopen(),並非每次都會開成功,所以,open()/fopen()通常都會去檢查return value是不是有正確。

2.1 Checking for Errors
glibc的return value通常是-1、NULL或是EOF,這只能知道錯誤發生,至於發生何種錯誤,都是存在errno這個變數中,當您要使用errno必須include <errno.h>。這個header file也定義很多error code,都是以E為開頭,這些error code在Ch 2.2中有說明,用到再查就OK啦。

2.2 Error Codes
這個章節主要說明定義的error code,值得注意的是EAGAIN和EWOULDBLOCK的值一樣,所以不能放在同一個case switch中,其實我常用的error code大概只有他列的1/5不到吧,看看就好。

2.3 Error Messages 基本上我們都是希望report的錯誤是文字型態,而不是只有error code,所以glibc有提供一些轉換的function:
char * strerror(int errnum)[Function]
char * strerror_r(int errnum, char *buf, size t n)[Function]
void perror(const char *message)[Function]
char * program_invocation_name[Variable]
char * program_invocation_short_name[Variable]
void error (int status, int errnum, const char *format, . . . )[Function]
error_at_line (int status, int errnum, const char *fname,unsigned int lineno, const char *format, . . . )[Function]

char * strerror(int errnum)
將errnum轉成相對應的字串
#include <stdio.h>
#include <errno.h>  // EINTR
#include <string.h> // strerror()

int main(int argc, char *argv[])
{
    printf("%s\n", strerror(EINTR));
    // print out "Interrupted system call"
    return 0;
}

char * strerror_r(int errnum, char *buf, size t n)
strerror的reentrant版本,mutli-thread就一定要用這個版本。
#define _GNU_SOURCE
#include <stdio.h>
#include <errno.h>  // EINTR
#include <string.h> // strerror()

int main(int argc, char *argv[])
{
    char buf[32];
    printf("%s\n", strerror_r(EINTR, buf, sizeof(buf)));
    // print out "Interrupted system call"
    return 0;
}

void perror(const char *message)
效果和printf(stderr, "%s:%s", message, strerror(errno))相似,把error message寫到stderr去,接著冒號後面再接errno的message。
#include <stdio.h>
#include <errno.h>  // EINTR
#include <string.h> // strerror()

int main(int argc, char *argv[])
{
    perror("my_perror_msg1");
    // print out "my_perror_msg1: Success"
    errno = EINTR;
    perror("my_perror_msg2");
    // print out "my_perror_msg2: Interrupted system call"
    return 0;
}

char * program_invocation_name / char * program_invocation_short_name
該程式的名稱,和argv[0]的值一樣。
#include <stdio.h>
#include <errno.h>  // EINTR
#include <string.h> // strerror()

int main(int argc, char *argv[])
{
    printf("%s\n", argv[0]);
    // print out "./a.out"
    printf("%s\n", program_invocation_name);
    // print out "./a.out"
    printf("%s\n", program_invocation_short_name);
    // print out "a.out"
    return 0;
}


void error (int status, int errnum, const char *format, . . . )
status不為0時,就等同exit(status),後面的參數errnum和format用途類似perror(),當errnum為0時,就不會印後面的message,但是perror()會印Success。
#include <stdio.h>
#include <errno.h>  // EINTR
#include <string.h> // strerror()

int main(int argc, char *argv[])
{
    error(0, 0, "%s", "msg");
    error(0, EINTR, "%s", "msg");
    // print out "./a.out: msg: Interrupted system call"
    error(1, EINTR, "%s", "msg");
    // print out "./a.out: msg: Interrupted system call" and exit(1)
    return 0;
}


error_at_line(int status, int errnum, const char *fname, unsigned int lineno, const char *format, ...)
error_at_line()和error()很像,只是多了fname和lineno印出檔案名稱和行號。
#include <stdio.h>
#include <errno.h>  // EINTR
#include <string.h> // strerror()

int main(int argc, char *argv[])
{
    error_at_line(0, 0, __FILE__, __LINE__, "%s", "msg");
    // print out "./a.out:error_at_line.c:7: msg"
    error_at_line(0, EINTR, __FILE__, __LINE__, "%s", "msg");
    // print out "./a.out:error_at_line.c:8: msg: Interrupted system call"
    error_at_line(1, EINTR, __FILE__, __LINE__, "%s", "msg");
    // print out "./a.out:error_at_line.c:11: msg: Interrupted system call"
    return 0;
}



    參考資料:
  • The GNU C Library, Chapter 2



IE8無法下載檔案


話說有一天,我用Luci寫一段download動態產生的檔案時,發生部分的IE8下載有問題,都會產生無法下載的訊息,當然就是立刻請問google大神,尋得此文章[PHP]下載檔案時無法直接開啟文件的解法方法,雖然是用PHP寫,不過小改一下就可以在Luci上面如法炮製啦。

[PHP]下載檔案時無法直接開啟文件的解法方法
header("Content-Type: application/octetstream; name=$FILEname"); //for IE & Opera
header("Content-Type: application/octet-stream; name=$FILEname"); //for the rest
header("Content-Disposition: attachment; filename=$FILEname;");
header("Content-Transfer-Encoding: binary");
header("Cache-Control: cache, must-revalidate");
header("Pragma: public");
header("Expires: 0");


Luci不過就是改呼叫luci.http.header()。
[Luci]下載檔案時無法直接開啟文件的解法方法
luci.http.header("Content-Type", "application/octetstream; name=" .. fname); //for IE & Opera
luci.http.header("Content-Type", "application/octet-stream; name=" .. fname); //for the rest
luci.http.header("Content-Disposition", "attachment; filename=" .. fname);
luci.http.header("Content-Transfer-Encoding", "binary");
luci.http.header("Cache-Control", "cache, must-revalidate");
luci.http.header("Pragma", "public");
luci.http.header("Expires", "0");