顯示具有 網站製作 標籤的文章。 顯示所有文章
顯示具有 網站製作 標籤的文章。 顯示所有文章

JavaScript 函式筆記

喔要做法令易讀器於是翻了JavaScript的文章,筆記一些如下: ......
... read more

大學指考心得

今年,我生平第一次考了大學指考。

雖然確實也會去找工作,但我仍想保有「學生」身分,以便享受各種優惠和學校資源。雖然要再考個碩班或博班也是不錯的選擇,但不想搞研究的我,還是選擇在準備論文之餘,花個三、四週準備大學聯招指考。

為了在提倡性開放和性交易之時可以自保,並且為同志平權出一份力,我選擇的目標是法律系(也因此,以往擅長的理科就直接不準備);而為了省錢並且要有夠多的學校資源,志願序仍是以國立大學優先;為了實際接觸各團體(諸如同志熱線、日日春、愛滋權促會),我選擇台北。

不過看樣子考的並不理想,以下是各科成績和心得(試題與選擇題答案請參考大考中心網站),順序請容我調動:

地理:64.00

年初的海地7.0強震考了兩題,其他部分也不會很難作答。有碩班將畢業的朋友聽我提到4-6, 13-14這幾題的可笑之後,在沒準備的狀態下拿題目來做,也有62分。

公民:59.20

我覺得全國地理最高分是93分已經是出奇的低了,結果報考公民的四萬多個考生,最高分居然只有83分多(而且這還是唯一沒有非選題的科目)!!??今年好歹也有155個科系採計啊..

公民是被我排在地理和歷史之後才準備的科目,但卻是最讓我「感動」的科目,而它讓我感動的原因就在於:它是跟現實生活最為貼近的科目。第一冊是加深國中公民課的深度,提及心理學、性別平等、婚姻、家庭、群體、文化;第二冊是法律,包含刑法、民法、行政法,還有訴訟程序(其中關於「繼承」的段落是我覺得甚至應該被列做必考的生活常識);第三冊則是政治和憲法;第四冊則是經濟。除了第一冊之外,全都是我們就算不看電視新聞也都會實際運用到的東西,但是採計的科系和認真唸它的人卻這麼少,真是讓人痛心!!

考題部分其實也出得很實際,包含了家暴法(第2題)、性別平等(第3題)、高等教育現象(第4題)、媒體現象(第5題)、同志平權(第6題)、社會運動(第7題)、墮胎民意趨勢(第8題,出題老師們大概還是不敢碰廢死議題)、名譽損害(第11題)、隱私權(第12題)、弱勢特權(第13題,我答錯了,但覺得我的選項才是對的)、國家賠償與國家補償的差異(第15題)、釋憲門檻(第16題)....,我甚至覺得這科應該叫做「公民與『道德』」,也在此懇請看文的各位研究一下這些考題跟現實中的社會議題。

英文:80.00

完全沒準備的科目,不過畢竟七年來除了課業之外,逛網路時常看原文網站也多少有幫助,所以這個分數並不意外,相比之下是最問心無愧的分數。

但也不是沒有可檢討之處。作文題目[Smell]讓我想了好久到底應該寫哪個方向。直覺上是飲食類的描述,但除了香、臭之外,酸、甜、苦、辣中後兩者的英文我卻是怎麼也想不起來。後來雖然抱著搞笑的心態寫了[精液的氣味],但似乎把「自慰」(masturbation)拼錯了。

題型是我中學時就覺得很不解的出法,21至35題共佔20%,但答題方式卻跟小學時的「連連看」沒有兩樣,也就是說確定某幾題之後,要猜對其他題就很容易了(因為可能的選項變少)。

國文:53.70

原本是最害怕的科目,結果雖然確實沒有考好(比均標差0.3分,幸好登記分發沒有指考標的限制),但沒考好的原因卻不是原本擔心的國學常識或古文釋義判斷,而是沒戴錶又忘了國文的時間根本不夠的我,作文(佔27%)只寫了一段。

跟小時候聽到的聯考方向相比,白話文文意判斷真是讓我又驚又喜,除了比例不低於古文釋義判斷之外(7, 11-15, 19這幾題都是白話文),問的方式也很像是英文的閱讀測驗;而16, 17題雖是文言文,但考的是基本邏輯和人格,要答錯也很困難。

數甲:72.00
數乙:88.00

我覺得考這分數很丟臉,請容許我逃避。

化學:42.55

不愧是背科,我幾乎跳過沒讀的有機物考很多,不過電子軌域似乎就還好,其餘則大多是實驗題。

物理:48.25

雖然沒寫完,但其實自己原本預期是有55分的呢....物理是我高中時覺得可以靠「背公式」就順利解決的科目,但這次沒能湊出時間溫習那些七年沒碰的公式,導致電磁學的部分和光學名詞定義的部分失分嚴重。

生物:59.87

居然有均標,真是莫名其妙!明明高三起就沒碰生物的我應該是這科要考最差的啊!

歷史:51.57

以目標是法律系來說,歷史不到均標是蠻詭異的事情,但我真的背不起來嘛....

本週一成績公布後,為了確實評估自己的落點,於是做了一個大考分發科系資料查詢,可以查詢各科系前三年的最低錄取分數和加權平均(另徵求96年(含)以前各科系採計權重的Excel檔或網頁)。原本看來,應該會是在東吳大學。但結果公布是在輔大,那就試試跨系修體育課去騷擾體育健將們吧

不過週三(2010-07-21)時大考中心公布了:明年指考跟學測都不倒扣(詳見新聞稿),所以我的系統如果真要改成完整的落點分析的話,難度就又變更高了呢....

......
... read more

用SQL求得資料順位

原本是想要看看PHP Plurk API,在亂點roga部落格的MySQL分類時看到了roga大在去年六月有在想SQL的問題,於是心血來潮地試了一下。

(卻花了我兩個多小時,而這篇文不知道又要打多久了XD)

在仔細寫本文之前,先把結論呈現一下:DELETE FROM tbl
USING tbl INNER JOIN (
SELECT id, count(*) AS place
FROM (
SELECT t1.id
FROM tbl AS t1, tbl AS t2
WHERE t1.url_id = t2.url_id
AND t1.id <= t2.id
) AS t3
GROUP BY id
) AS t4
WHERE tbl.id = t4.id
AND t4.place > 1500
其中tbl是roga大大的url_detail_history,單純是名字太長所以被我換掉。此法受限於資料庫系統對Multiple-table DELETE的支援度,已知MySQL支援。


以下詳述我的思考過程(有些是繞圈子,所以看起來可能跟結果沒啥關係)
roga原本的需求大致上是「資料表中url_id欄位相同的,只留下最新的1500筆」。而該資料表有一個`id`主鍵欄位是AUTO_INCREMENT。
我試著將問題從最簡單的模式開始推導:

第一步:求「指定url_id的最新資料」

這很直覺,使用Aggregate Function中的MAX()就可以了:SELECT MAX(id) FROM tbl WHERE url_id = 'XXXX'

第二步:求「各url_id最新的一筆」

也是基本題,加上GROUP BY就可以了:SELECT url_id, COUNT(*)
FROM tbl
GROUP BY url_id
雖然沒什麼困難,不過我們稍比較一下這個和前一個SQL後會發現:
  1. WHERE變成GROUP BY
  2. SELECT區塊也要多一欄url_id,也就是GROUP BY用的欄位


第三步:求「各url_id最新的n筆」

咦....慘了,沒頭緒,也許我們第二步不應該這樣走。回到第一步,把問題改成「指定url_id的最新n筆」。(注意到題目的不同嗎?我一次只變動題目的一部分,嘗試在這樣的步驟中統整出比較有系統的解法。)

新的第二步:求「指定url_id的最新n筆」

嗯....如果不用MAX()的話,確實不難做到:SELECT id
FROM tbl
WHERE url_id = 'XXXX'
ORDER BY id DESC
LIMIT n


還是第三步:求「各url_id最新的n筆」

....我還是不知道要怎麼做

我卡了一個多小時,直到想起多年前在網路上看到的某個題目:「用SQL將名次排序出來」,雖然已經忘了網址在哪,但是解法卻非常的有趣。(效率如何我就不清楚了):
假設資料表ss的資料如下:+---------+-------+
| student | score |
+---------+-------+
| 1 | 7 |
| 2 | 5 |
| 4 | 3 |
| 5 | 4 |
+---------+-------+
而我們要產出的結果為:+---------+-------+-------+
| student | score | place |
+---------+-------+-------+
| 1 | 7 | 1 |
| 2 | 5 | 2 |
| 4 | 3 | 4 |
| 5 | 4 | 3 |
+---------+-------+-------+
也就是學生1是第一名;學生5是第三名;...

試重新思考「名次」的定義。我們直覺上對於此詞彙的解釋是:「分數第n高者為第n名」,但這個作法則是將「第n名」界定為「有n個人(含自己)的分數跟自己相同或較高」。
依照這個想法,要排序名次,資料表就得跟自身比較。讓我們試寫「列出分數不比自己低的人」的指令,也就是:SELECT t1.student, t2.student
FROM ss AS t1, ss AS t2
WHERE t1.score <= t2.score
結果為:+------------+------------+
| t1.student | t2.student |
+------------+------------+
| 1 | 1 |
| 2 | 1 |
| 2 | 2 |
| 4 | 1 |
| 4 | 2 |
| 4 | 4 |
| 4 | 5 |
| 5 | 1 |
| 5 | 2 |
| 5 | 4 |
+------------+------------+

但其實我們並不需要知道「哪些人」分數不比自己低,而是要知道有「幾個人」,所以即使沒有顯示t2.student也沒有關係:SELECT t1.student
FROM ss AS t1, ss AS t2
WHERE t1.score <= t2.score
假設這張表叫做t3,那麼「列出分數不比自己低的人的總數」,SQL指令就是:SELECT student, COUNT(*)
FROM t3
GROUP BY student
(有沒有覺得最後的指令簡潔到令人吐血?)
當然啦,通常你不需要另存t3,而會把整串步驟寫成一個指令:SELECT student, COUNT(*) AS place
FROM (
SELECT t1.student
FROM ss AS t1, ss AS t2
WHERE t1.score <= t2.score
) t3
GROUP BY student
得出來的就會是名次列表

而如果資料表裡面的主鍵並不是單一欄位組成,比方說:+---------+---------+-------+
| student | subject | score |
+---------+---------+-------+
其中Primary Key為(student, subject),那麼題目就變成「各學生在各科目的排名」,SQL指令為:SELECT student, subject, COUNT(*)
FROM (
SELECT t1.student, t1.subject
FROM ss AS t1, ss AS t2
WHERE t1.score <= t2.score
AND t1.subject = t2.subject
) t3
GROUP BY student, subject


上述的作法遇到考試科目同分時會有些狀況,不過由於今天我只想針對roga大的問題,也就是對primary key做排序,所以就不管了。

根據以上的作法,我們就可以輕易得知每一筆資料的排序順位,也就可以很輕易的執行相關的操作。而像是「列出各科目中考最差的五名」這樣的問題,即使每個科目的修課人數不同,也只要將「名次」的定義改成「分數不比自己高的人數」就可以輕易做到了。
回歸正題,roga大的狀況就會變成:DELETE FROM tbl
USING tbl INNER JOIN (
SELECT id, count(*) AS place
FROM (
SELECT t1.id
FROM tbl AS t1, tbl AS t2
WHERE t1.url_id = t2.url_id
AND t1.id <= t2.id
) AS t3
GROUP BY id
) AS t4
WHERE tbl.id = t4.id
AND t4.place > 1500
至於哪邊用大於,哪邊用小於,可得想清楚了....

(編輯終了,本文花了我一個半小時)
......
... read more

PHP + MySQL簡易操作教學

前置作業:


流程:
  1. 連線到資料庫
  2. 執行SELECT SQL
  3. 取出一列列的資料
  4. 其他注意事項和小撇步

PHP的MySQL相關function操作其實不難,但是新手們一開始在使用時卻會很不習慣,以下僅以在下的認知做出簡易示範(應該不是最好的方法,事實上我自己目前已經不是這樣做,但我相信本文應該會是很好理解的流程)
連線到資料庫

連線到資料庫通常都很好解決(如果MySQL Server有設定好的話):mysql_connect('localhost', 'username', 'password');
mysql_select_db('myDB');

這段程式碼通常會寫在一個給所有頁面引入的檔,假設上面兩行被我們存檔為"database.php",那麼遇到需要對資料庫連線的時候只要PHP呼叫:require_once 'database.php';就可以了。這個方法也可以應用在其他想要在每個頁面上做的事情(像是紀錄IP、檢查是否已登入之類的)。

不過只是這樣子有時會有點風險,比方說如果資料庫不是自己設定的,但我們又必須指定編碼(目前的趨勢是使用UTF-8)的話,就得加上一句"SET NAMES 'UTF8'"的SQL,以防止一些亂碼的狀況發生,當然這個前提是你的網頁也是用UTF-8編碼。連線的設定可能就會變成: $db_server = 'db.mycom.com';
$db_user = 'kong0107';
$db_password = '********';
$db_name = 'test';

mysql_connect($db_server, $db_user, $db_password);
mysql_select_db($db_name);
mysql_query("SET NAMES 'UTF8'");
你可能會覺得先把帳號密碼寫在變數裡這件是有點多餘,不過實務面上我們很有可能還會把「帳號資料」和「連線」這兩個區塊分開--通常是做很大的站台的時候。比方說我可能某個頁面同時要跟Google、Yahoo!和FaceBook做連線,那麼我就會分開寫兩個檔:/* 這個檔叫做config.php */
$db_server = 'db.mycom.com';
$db_user = 'kong0107';
$db_password = '********';
$db_name = 'test';

$google_user = 'kong0107';
$google_password = 'hahaha';

$yahoo_user = 'kong_crazykid';
$yahoo_password = 'oh my god';

$fb_user = 'kong0107@gmail.com';
$fb_password = 'this is longer';

/* 這個檔叫做service_connection.php */
require 'config.php'; /*就會把上面那個檔案叫進來*/

mysql_connect($db_server, $db_user, $db_password);
mysql_select_db($db_name);
mysql_query("SET NAMES 'UTF8'");

require_once 'google_api.php'; /*把google的API(最重要的是連線function)叫進來*/
$google = new GoogleAPI();
$google->connect($google_user, $google_password);

require_once 'yahoo_api.php';
$yahoo = new yahooAPI();
$yahoo->connect($yahoo_user, $yahoo_password);

require_once 'facebook_api.php';
$fb = new facebookAPI();
$fb->connect($fb_user, $fb_password);
看吧,只是連線而已就已經開始讓人頭昏眼花,而且我們根本還沒有開始真正操作什麼呢!所以還是把一些設定(諸如帳號、密碼)通通寫在同一區,這樣子之後要改才比較方便。(註:那些API的實際使用方法應該不是這樣子,我只是隨便舉個例子。但總之通常只會更複雜)

執行SELECT SQL
希望你不會覺得光是連線就亂七八糟的,因為下面才要開始操作...orz
在這邊我們先考慮把資料從資料庫中取出來就好,寫入的方法之後會再介紹。
如果你還記得最簡單的SQL:SELECT id, name FROM student
這就是取出student資料表中的id和name兩個欄位。請注意資料庫的SELECT指令只會「取出資料」而不會「排序」--除非你要求他要排序:SELECT * FROM student
ORDER BY id ASC
其中"ASC"是表示遞增排序(遞減排序則是DESC)

在這邊要注意幾點事情:

  • SQL指令可以換行,所以我建議你在寫比較長的指令時,擅用換行來讓指令比較好理解
  • SQL的關鍵字不限大小寫,所以你也可以寫成"select * from student"。但是我個人覺得把關鍵字都大寫比較容易懂
  • "select *"的星號是特殊用法,意思是「取得所有欄位」。通常我會建議這麼做,因為你不一定知道待會可能會想用到哪些欄位
  • 通常資料庫名稱、資料表名稱、欄位名稱是不需要用引號框起來的,不過你可以為了區別他們和關鍵字而特別這麼做。但是要注意的是在MySQL中,把這類名稱框起來的引號並不是單引號或雙引號,而是鍵盤上左上角Esc鍵下面的那個「`」(請小心不要打成全型字),像是:SELECT `id`, `name`
    FROM `student`
    WHERE `id` < 10
    ORDER BY `id` DESC
  • 如果有字串的話,一定要用單引號(不能用雙引號)。舉例來說:SELECT * FROM student WHERE name = '高睿甫'
    如果字串之中有單引號的話,就要用跳脫字元「\」,像是如果要取出留言板中的特定留言:SELECT *
    FROM message
    WHERE content = '野村克也說\'要讓一個選手墮落很簡單啊,只要稱讚他就行了!\'他說的真是太忠肯了'
其實還有其他要注意的,不過先到此為止吧,我們還得回來看PHP呢....

PHP執行SQL的指令是mysql_query()(注意:當然要先對資料庫連線,再執行mysql_query()才有意義),有時我們會把SQL直接寫在裡面:$res = mysql_query("SELECT * FROM student");
不過如果是像上面有比較長的SQL,我倒是比較建議先另外丟進變數裡:$sql = "SELECT `id`, `name`
FROM `student`
WHERE `id` < 10
ORDER BY `id` DESC";
$res = mysql_query($sql);
也別忘了PHP的字串裡面是可以直接換行的(題外話:如果你有在寫JavaScript的話,請注意JavaScript並不能直接這樣做喔)

有注意到我都把mysql_query()回傳的東西丟給$res變數嗎?那就是我們接下來要操作的東西囉

取出一列列的資料
好,這一個區塊其實才是我寫本文的主要目的....(不過上面講SQL好像花了太多篇幅)
mysql_query()回傳的$res變數是PHP的某種資料結構,沒辦法直接取得所有資料,不過可以「一筆一筆」的取出來(在這裡我是用mysql_fetch_assoc(),你也可以用mysql_fetch_row(),後面會再介紹他們的不同): $res = mysql_query("SELECT * FROM student");
$row1 = mysql_fetch_assoc($res); /*第一列*/
$row2 = mysql_fetch_assoc($res); /*第二列*/
$row3 = mysql_fetch_assoc($res); /*第三列*/
注意我們其實是在執行同一個function,但是每次卻回傳不同的結果喔!當然你應該不會想這麼呆呆的把整張資料表取完,這種時候就得用上迴圈啦。但是面對不知道SQL回傳的結果有幾筆資料的時候,回圈應該要在什麼時候停止呢?
其實mysql_fetch_assoc()(和mysql_fetch_row())都會在「已經沒有資料」的時候回傳false,所以我們只要把取出來的東西丟給while判斷就好啦: $res = mysql_query('SELECT * FROM student');
while($row = mysql_fetch_assoc($res)) {
/* 這裡就看你想對這一筆資料幹嘛*/
echo $row['id']; /*像這樣就可以印出該學生的學號*/
}

流程大概都清楚了,我們就來試試用HTML的表格來顯示出所有學生的學號和姓名吧: $res = mysql_query('SELECT `id`, `name` FROM `student`');
echo '<table>';
while($student = mysql_fetch_assoc($res)) {
echo '<tr>';
echo '<td>';
echo $student['id'];
echo '</td>';
echo '<td>';
echo $student['name'];
echo '</td>';
echo '</tr>';
}
echo '</table>';
像是這樣,不過輸出的部份我自己比較喜歡另一個方式:<table>
<?php
while($student = mysql_fetch_assoc($res)) {
?>
<tr>
<td><?=$student['id']?></td>
<td><?=$student['name']?></td>
</tr>
<?php
}
?>
<table>
就是這樣囉,或是看你想怎麼顯示都可以。
其他注意事項和小撇步
  • 如果你只想取得一筆資料(比方說想用學號來查名字),那就不需要用while回圈了,比方說:$id = 9646515;
    $res = mysql_query("SELECT * FROM student WHERE id = $id");
    $kong = mysql_fetch_assoc($res);
    $name = $kong['name'];
    echo "學號$id 的學生,他的名字是$name";
  • mysql_fetch_assoc()指令只是我自己慣用,如果資料表是你自己設計的,也可以使用mysql_fetch_row()。差別在於回傳回來的array結構: $res = mysql_query("SELECT id FROM student");

    $row1 = mysql_fetch_assoc($res);
    echo $row1['id'];

    $row2 = mysql_fetch_row($res);
    echo $row2[0];

    $row3 = mysql_fetch_array($res);
    echo $row3['id'];
    echo $row3[0];

    mysql_fetch_assoc()的好處是你不用記得欄位順序,但缺點是你必須記得欄位名稱;mysql_fetch_row()則相反。當然你也可以用mysql_fetch_array(),這樣就兩種方式都可以取得想要的資料。
    小提醒:上面的例子中,請注意$row1、$row2、$row3是會取得「不同筆」的資料喔。
  • 實務面上我們常常需要藉由使用者表單來湊出SQL指令,比方說前面舉過的搜尋留言板:$txt = $_GET['search'];
    $sql = "SELECT * FROM message WHERE content = '$txt'";
    // 還記得字串要加上單引號吧..
    不過以這個例子來說,我們又必須小心使用者輸入的東西本身就有單引號。比方說使用者輸入了"我好傷心喔 T_T'",那麼整個SQL丟給MySQL的時候就會變成SELECT * FROM message WHERE content = '我好傷心喔 T_T''然後就發生錯誤啦(因為MySQL看不懂那些引號是怎麼回事)
    這種時候就必須另外用程式把那個單引號解決掉:$txt = str_replace("'", "\\'", $_GET['search']);
    /* 如果你看不懂那個"\\'",就先照做吧....*/
    $sql = "SELECT * FROM message WHERE content = '$txt'";

    通常我只處理單引號,不過你可能也想把其他東西代換掉,就依樣畫葫蘆囉。
  • 承上,如果是用留言的流水號(數字)來查的話,直覺上程式碼應該是:$id = $_GET['id'];
    $sql = "SELECT * FROM message WHERE id = $id";
    可是,如果使用者在表單中,根本不是打數字的話(比方說使用者什麼都沒打),SQL就會變成SELECT * FROM message WHERE id = 於是就產生錯誤了(因為等號後面不是數字)。
    要解決這個狀況有兩個方法,一個是無論該欄位是不是數字都加上引號:$id = str_replace("'", "\\'", $_GET['id']);
    $sql = "SELECT * FROM message WHERE id = '$id'";

    另一個就是使用sprintf()函數,這也是我比較偏好的方法:$sql = "SELECT * FROM message WHERE id = %d";
    $sql = sprintf($sql, $_GET['id']);
    以上兩個方法都可以應付使用者亂打的狀況
善用sprintf()
承上,我們有時會需要比較長的SQL,像是:SELECT * FROM car
WHERE brand = 'BMW'
AND oilCart > 2000
AND price < 700000
如果我們是使用sprintf()的話,就可以用比較容易懂得簡短程式碼來執行(簡潔易懂的程式碼可以幫助自己或他人後續的除錯和更新):$sql = "
SELECT * FROM car
WHERE brand = '%s'
AND oilCart > %d
AND price < %d
";
$sql = sprintf($sql, $_GET['brand'], $_GET['oilCart'], $_GET['price']);
這只是個比較簡單的例子,但如果是遇到像是需要報表、統計這一類需要跨多的資料表的SQL,使用sprintf()的替代方式可以讓你快速的編輯和除錯。

先到此為止吧,我手痠了
......
... read more

如何在ie下面debug

作者: cole945 (躂躂..) 看板: Ajax
標題: Re: [問題] 如何在ie下面debug
時間: Sun Aug 19 01:22:27 2007


在IE的 Intenet Options 的 Advanced 頁面設定裡有個
"Disable script debugging"
預設是勾起來的..
如果有勾的話, 就算有錯誤也不會顯示~ 請把他取消掉..

如果你還需要更進階的debug功能的話再往下看~
不然就這裡你就可以按 <- 離開了 囧"

IE還可以透過Microsoft Script Editor(簡稱MSE)或Visual Studio(簡稱VS)來偵錯
(包括Step by step執行 或是變數監看等等..)

如果有灌 VS 2002以上的版本會自動與 IE 整合,
遇到錯誤選 yes 進行除錯並選擇 Visual Studio就可以了~
可是VS有點肥:x 正常寫Javscript的人應該不會想用那個除錯..

MSC則是附在Office/Frontpage裡(好像XP的版本以上就會有了..)
(應該是要含Frontpage的office版本或單Frontpage也會有)
先確認你的電腦是否已安裝 MSE,
打開 IE 在功能表的 View->Script Debugger->Open
如果有 Misrosoft Script Editor 那就是有安裝了

若沒有的話拿出你的Office補安裝,
選擇 新增/移除功能 -> 選進階自訂 ->
在 Office Tools 的分類下面應該會有個 HTML Source Editing
全部都勾起來 (Frontpage其實可以不用灌, 有勾這個就夠了)
再重開IE就可以了~

--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 220.139.142.115

......
... read more

記錄使用者瀏覽時間和下一頁

在做清大科管所的clay0529學長BuzzShare(可以自己選擇廣告的插入廣告服務,Mr.6有分享過喔:P)的時候用了這樣的方法,在此分享。簡言之就是在使用者要離開的時候引入一個檔案囉,麻煩的是要怎麼得知「下一頁」是什麼:P。

步驟一:當然要先紀錄進入頁面的時間,用now = new Date();
start = now.getTime();
就可以了

步驟二:寫一個要在離開頁面的時候執行的function。因為你不一定會想改(或說不一定能改)<body />的onunload標籤,而直接把window.onunload覆寫掉也不是個好辦法(因為可能已經有設定別的東西要執行了),所以最好是用attachEvent或是addEventListener,可以參考【Javascript: 附加 onload 事件】。function whenLeaving() {
var now = new Date();
var stayTime = now.getTime() - start;
addJavaScript('abc.php?stayTime=' + stayTime);
/*addJavaScript()是我之前寫的一個可以加入JavaScript的function(原本主要是拿來做XSS用的)
要注意的是不可以用document.write來生成<script />,否則會有想是換頁的情形發生
喜歡的話,用CSS(用我的addStyleShett)甚至是圖片也可以
至於如何不使用document.write來生成物件,可以查一下document.createElement()
另外,abc.php到底要output什麼出來就隨便囉
我自己是都留白(單純只把資料寫進資料庫,不做任何輸出)....*/
}
if(window.addEventListener)
window.addEventListener('load', whenLeaving, false);
else if (window.attachEvent)
window.attachEvent('onload', whenLeaving);

/*其實可以另外寫一個function來做這件事*/
function addEvent(obj, event, func) {
if(window.addEventListener)
obj.addEventListener(event, func, false);
else if (window.attachEvent)
obj.attachEvent('on'+event, func);
}


原則上到這裡就可以記錄使用者停留時間了。

步驟三:修改<a />的onclick,取出接下來要進入的頁面的連結
我原本以為下面這樣就可以了tagA = document.getElementsByTagName('a');
for(i = 0; i < tagA.length; i++)
addEvent(tagA[i], 'click', function(){next = tagA[i].href;});
不過至少在IE下會發生i值變動的問題。幸好這個問題在我之前在無名的Homepage板問過之後,星周(starjou)學長有解答過(簡言之就是用區域變數來繞過全域變數的問題),所以迴圈的部份改成下面這樣:for(i = 0; i < tagA.length; i++) {
function a() {
var j = i;
addEvent(tagA[j], 'click', function(){next = tagA[j].href;});
}
a();
}


步驟四:再修改一下步驟二的函數
把原本要引入的檔案多加上「下一頁」的參數囉addJavaScript('abc.php?stayTime='+stayTime+'&nextPage='+next);

這個方法原則上也可以用XSS的方法來做(事實上BuzzShare的部份我就是這樣子做)。另外就是我目前沒有處理表單送出的部份(頁面停留時間仍然可以記錄,但是「下一頁」就無法判斷了),當然表單還是可以用修改onsubmit的方式來修改,但是要注意的是有些表單(其實<a />也有可能)會被其他的JavaScript更改傳送頁面,所以實做上並不一定可以得知實際被傳送的頁面。(其實我是有想到解決辦法啦,但是有點難解釋,而且也沒有把握一定可行)

另外就是attachEvent()和addEventListener()的問題,由於前者會先執行最後被指定的function,所以有時後有點麻煩,此時可以用另一個方法解決這個問題(後來仔細想想,這個方法好像比較好...orz)var oldOnload = window.onload || function () {};
window.onload = function ()
{
oldOnload();
/* Do Something... */
}


後記:我真的希望我可以多花時間在音樂上面。......
... read more

這兩天

昨天去苗130還願(當初我根本沒去,不過既然爸媽去拜過了,跟去一下也不錯),那瞭望台的風景不錯,發現自己雖然家住16樓但還是會怕高,想起高中坐大怒神時根本不敢張開眼睛的情況。
回來之後就在兩個網站之間徘徊,去Street Voice申請了帳號也把幾首歌傳了上去,整體而言比滾石可樂好多了滾可的系統也10年了吧?? @.@),不過速度好像也沒有比Blogger快多少(我想是因為我放了Prototype.js才讓Blogger變慢的)
另外就是做了一個AddrBalance(亂取的名字),主要是通訊錄和記帳功能,不確定是不是弄得夠安全(懶得做防呆),總之目前先po在無名的個板(P_LifeOMusic)和PHP板,如果沒有被Hack的話再po到PTT給大家用看看..cc......
... read more

PHP: array2url

我很喜歡用multi-dimensional array來傳送表單資料(印象中在ASP不能直接這樣用),可是這樣的東西在做分頁界面的時候很難還原成URL,所以就寫了一個array2url:
function array2url($arr,$main='') {
$tmp = array();
foreach($arr as $key=>$val) {
$prefix = $main ? sprintf('%s[%s]', $main, $key) : $key;
$tmp[] = is_array($val) ? array2url($val, $prefix) : "$prefix=$val";
}
return implode('&',$tmp);
}


範例: $abc = array(
'ohmyhoney' => array(
'recede' => 941505,
'tbex' => array(
'school' => 'nctu',
'department' => 'cs'
)
),
'bango' => 'banco'
);
echo array2url( $abc );

結果:ohmyhoney[recede]=941505&ohmyhoney[tbex][school]=nctu&ohmyhoney[tbex][department]=cs&bango=banco

所以之後就可以: $arr = $_GET['arr'];
unset( $arr['page'] );
for( $page = 1; $page <= $amount / $records_per_page; $page++ )
printf(
'<a href="http://www.blogger.com/webpage.php?%s&page=%d">第 %d 頁</a>',
htmlentities( array2url( $arr ) ),
$page,
$page
);

比較討厭的是因為寫成recursive function,所以連結的部份要符合W3C標準的話,要自己再加上一個htmlentities()
另外還有個狀況是如果是還原自$_GET的話仍可能和$_SERVER['REQUEST_URI']不一樣,如a[]=3會變成a[0]=3,不過好像就只是網址變長而已,並不影響PHP的運作(但是仍要小心網址因此而太長而超過HTTP的限制)

Update(2007-07-26 22:40):
不過之後darkhero直接踢破說PHP5之後其實有http_build_query()可以用(雖然因為RFC 1738的關係,空格的編碼方式不同)...orz......
... read more

Kong's Website Template

http://oz.nthu.edu.tw/~u921510/siteTemplate20070724.7z

弄了一下午到現在
其實沒什麼新東西,就是把以往知道的東西湊一湊
以後要架新的網站的時候就從這邊開始吧

Smarty 2.6.18Prototype.js 1.5.1.1 都包進去了
不過prototype.js目前是盜連的..cc

自己建了一個class MySQL,很陽春但夠我用
上次弄BuzzShareXSS時寫的createElement和addStyleSheet也包進去了
Element.addMethods(
{
createElement: function (tag,attr,append) {
var obj = document.createElement(tag);
if(typeof attr == 'object' &&amp;amp; attr != null)
for(var i in attr) obj[i] = attr[i];
if(typeof append == 'string') append = document.getElementById(append);
if(typeof append == 'object' &&amp;amp; append != null) append.appendChild(obj);
return obj;
},
addStyleSheet: function (css_url) {
this.createElement(
'link',
{
rel: 'stylesheet',
type: 'text/css',
href: css_url,
media: 'all'
},
document.lastChild.firstChild
);
},
addJavaScript: function (js_url) {
this.createElement(
'script',
{ type: 'text/javascript', src: js_url },
document.getElementsByTagName('head')[0]
);
}
}
);

不想設定include/config.php中資料庫連線設定的話
直接把MySQL的連線取消就可以用了

其實有點想就這麼經營起一個toolbox去弄個SourceForge或是OSSF之類的
不過寫文件實在是太麻煩了,而且我志不在此..cc......
... read more

新版 Blogger 中 Read More 作法

「新版」係指2006年九月之後的Blogger
羊男實驗の咖啡館 * [ METAMUSE ]:
Blogger Beta 中 Read More 與 Archive 只顯示標題 作法

從 referral 中發現有人在搜尋 Blogger.com Beta 改版後 Read more 與 Archive 只顯示標題的作法,我是「遵循 Blogger 古法」的邏輯再配上新系統內建的語法後,自己摸出來感覺比較簡潔的作法 ,不過原來早有在 Blogger.com 架站的網友公開了其他的作法。
首先在 EDIT HTML 頁面中點選 Expand Widget Templates 後,在</b:skin>標籤後加入下列區段:
..........略
]]></b:skin>
<b:if cond='data:blog.pageType == "item"'>
<style type='text/css'>
span.fullpost {display:inline;}
</style>
<b:else/>
<style type='text/css'>
span.fullpost {display:none;}
</style>
</b:if>
在語法中搜尋 <data:post.body/>,原本的樣子是:
<p><data:post.body/><p>
改成:
<b:if cond='data:blog.pageType == "item"'>
<data:post.body/>
<b:else/>
<data:post.body/>
<br/><a expr:href='data:post.url'> read more... </a>
</b:if>
加<br/>是為了讓 read more 接本文時可以斷行,寫文章的時候,只要把想要隱藏的文章區段用<span class="fullpost">...</span>包起來即可:
本文.....<span class="fullpost">(本文要隱藏的部分)</span>
收工。

要記得勾選[展開小裝置範本(Expand Widget Templates)],另外第一段可以改成:<b:if cond='data:blog.pageType != "item"'>
<style type='text/css'>
span.fullpost { display: none; }
</style>
</b:if>
......
... read more

把清大課程總表丟進資料庫

  一直不知道學校到底有沒有把比較好處理的課程「總」表放在網路上,但是又不能去問(去年電商專題的EZCheat讓部分教授們對課務組和計中施壓,不會把那樣的資料給我們),最後只好自己從校務資訊系統的查詢網頁著手了,先跳過表單檢查步驟強制用空字串當關鍵字以一次查到所有課程,然後用PHP去做parsing和塞進資料庫。
  雖然講起來沒什麼,但這東西花了我整個下午,(說起來還頗對不起英翔學長的....答應的BuzzShare的進度已經落後很多了)中途還冒出一些目前還不知道怎麼解決的問題,比方說因為我幾乎不會用正規表示法,只好改用投機的方式去把 <input> 改成 <input/>。(這件事告訴我們修過【正規語言】跟擅長使用正規表示法是兩回事)
  總之,程式碼如下,已經改成只要把網頁給他就可以的function了:function nthuCourseParse( $webpage ) {
$data = file_get_contents( $webpage );
$data = mb_convert_encoding( $data, 'UTF-8', 'BIG-5' );

// Preserve only <table />
$tableStart = strpos( $data, '<table' );
$tableEnd = strpos( $data, '</table>' );
$data = substr( $data, $tableStart, $tableEnd - $tableStart + 8 );

/*
Make it to match XML format
The wierd ');"></td>"' is used for handling the button.
Note that   is not allowed in XML until other DTD declaration.
*/
$replace = array(
'<BR>' => '<BR/>',
'<br>' => '<br/>',
' ' => ' ',
');"></td>' => ');" /></td>',
'&' => '&'
);
foreach( $replace as $from => $to )
$data = str_replace( $from, $to, $data );

$parser = xml_parser_create();
xml_parser_set_option( $parser, XML_OPTION_CASE_FOLDING, 0 );
xml_parser_set_option( $parser, XML_OPTION_SKIP_WHITE, 1 );
if( !xml_parse_into_struct( $parser, $data, $values, $tags ) )
printf(
'Line %d, Col %d: %s',
xml_get_current_line_number( $parser ),
xml_get_current_column_number( $parser ),
xml_error_string( xml_get_error_code( $parser ) )
);
xml_parser_free( $parser );

/*$colName = array( '科號', '科目', '學分', '時間', '教室/容量',
'教師', '人限', '備註', '人數', '對象', '擋修', '大綱' );*/
/*
Parse into another structure in which each element is a course.
Note that empty string is also parsed.
The initial value 4 of the for-loop is based on the structure of <table />,
as the increasing-step 4 is to skip the other row of <table />.
*/
$tr = $tags['tr'];
for( $c = 0, $i = 4; $i+1 < count( $tr ); $i+=4, $c++ ) {
$tdi = 0; // index of td
for( $j = $tr[$i]+1; $j < $tr[$i+1]; $j++ ) { // Trace each <td /> for data
$re = $values[ $j ];
$arr[$c][$tdi][] .= trim( $re['value'] );
if( $re['tag'] == 'td' )
if( in_array( $re['type'], array( 'close', 'complete' ) ) )
$tdi++;
}
}
return $arr;
}

這樣就會回傳一個比較容易懂的結構了,至少比較方便直接呼叫到想要的東西,可以有如是的用法:foreach( $arr as $r => $course ) {
$db[$r]['sn'] = $course[0][1];
$db[$r]['chinese'] = $course[1][0];
$db[$r]['english'] = $course[1][2];
$db[$r]['credit'] = $course[2][1];
$db[$r]['period'] = $course[3][1];
list( $db[$r]['location'] ) = explode( '/', $course[4][1] );
$db[$r]['teacher']['chinese'] = $course[5][1];
$db[$r]['teacher']['english'] = $course[5][3];
}

其實也可以用數字當index直接呼叫所需的資料啦,不過先做過這件事的話就比較可以知道自己再寫什麼:foreach( $db as $i => $course ) {
$teacher = $db->getOne( sprintf( "SELECT sn FROM teacher WHERE name = '%s'", $course['teacher']['chinese'] ) );
$db->exec( "INSERT INTO course ( sn, name, teacher ) VALUES ( '%s', '%s', %d )", $course['sn'], $course['chinese'], $teacher ) );
}
......
... read more

Embed music in blogger without owning a server.

Well, I'm in NCTU IMU and the computer I'm using doesn't have Chinese to type. (In fact, it may have, but I'm not willing to check...XD)
After Hans told me about Box.net, I wonder whether it is possible to put "files" on it and include the files somewhere else. And the following is my result for now:

....It's the song "Good guy" I cooperated with LazyBug during high school.
The embedded flash is found at http://catz.no-ip.com/blogs/eureka/?p=133, also told by Hans.



For now, the code is not neat enough for me and I'd like to write a JS function to construct the <object> element dynamically. Also, I'd like to put the JS function in a file and put the file in Box.net.......
... read more

Google 的Bug

如題..希望這篇不會再更新了

......
... read more

Google Adsense的真實成本

李怡志: Google Adsense的真實成本

話說日前拿到一張從瑞典寄來的Google Adsense支票,雖然金額十分十分微薄,不過多少能夠貼補今年繳稅的支出,所以還是趁著中午時間拿去樓下的銀行落袋為安。

不知道為啥,排外匯的櫃臺總是要等特別久,每個人處理的時間也都特別長。就這樣等啊等的,差不多快30分鐘我才有機會把那張沒有多少錢的Google Adsense支票交給行員。

原本以為排隊是整個過程中最麻煩的一段,結果才發現苦難從此開始,難怪這個櫃臺都要排這麼久。我的Google Adsense登記名字是 Richy Li,銀行行員說,這看不出來跟「李怡志」有什麼關係,擔心不是我本人,所以得拿出可以證明「Richy Li」就是「李怡志」或者「我本人」的證件。還好,公司名片、識別證上都是印Richy Li,否則還得重新跑一趟。那張Adsense支票的金額,大約還不足以吸引我多跑一趟。

說實在的,繁體中文環境下在Blog放Google Adsense實在賺不了「大錢」,而且放了之後就立刻變成以營業為目的的「商業網站」,所以小弟的Blog現在已經沒有放Adsense了。我看到許多人——不好意思說這些人利益薰心——寫一篇文章卻開了很多Blog分站,理由是因為分站雖然比較好用,但難用到必須照三餐罵的母站卻因為Adsense收入太多而不捨得關站時,就知道這些人的心已經完全被Adsense宰制了。寫Blog不就是要自由自在嗎?結果最後還要受到那一點點小錢約束,怎麼想都不值得,所以乾脆不放。

過了幾分鐘,行員拿著影印好的證明回來了,又拿一張單子給我填,哇,這可比兌現一般台幣支票要複雜太多了,不過就是幾千台幣,有必要這麼複雜嗎?申請單上有一個最神奇的欄位要註明支票屬於什麼樣的收入,我猜大概是要防堵金融犯罪順便讓稅務機關好查稅用的吧。說實在的,我真的不知道這算是什麼收入,也不知道填錯了會不會就要繳很重的稅。

台灣的稅捐機構公務員,特別是抽小老百姓稅的那一群,大概是最勤奮的公務員了。想想網路拍賣的前例吧,原本大家以為是自己的「額外收入」,但沒想到也是國稅局的「額外收入」,還訂定了《網路交易課徵營業稅及所得稅規範。關鍵字廣告呢?我猜最遲明年,國稅局就會告訴我們這筆錢應該要怎麼讓國家分一杯羹了。

老實說我真的不知道這部分的收入該怎麼樣報稅或避稅,所以在銀行櫃臺尷尬了好久,左翻右翻都不知道應該是哪一項,弄得好像那是賣淫收入一樣難以啟齒。顯然行員很忙,也沒有在寫Blog,所以對Google Adsense不熟,否則不會一直「鼓勵」我填薪資收入。哇哩咧,這不是陷我於不仁不義嗎?抵死不從是也!後來填了什麼我也忘記了。不過這讓我一直耿耿於懷,所以想說乾脆在Yahoo!奇摩知識+問看看,希望有專家可以答覆

全部都搞定之後,就拿到錢了嗎?還早。行員說要整整21個工作天之後才會入帳,差不多就是一個月或者還要更久了。

所以把自己的網站或Blog「租」給Google Adsense基本上還有一些看不到的成本:
  • 交易成本:每張若干元的手續費外加寶貴的時間。
  • 稅務成本:還不知道要不要繳、要怎麼繳。如果要併入綜合所得稅,那也是一筆錢。
  • 延遲成本:假設說你在1月把廣告版位租給Google放Adwords,差不多要4月中或者5月才能拿到錢,中間隔了3個月,感覺就跟在台灣做生意被開90天的票一樣。
最近台灣想要跟Google Adsense競爭Blog廣告版位的台灣廠商也很多,如果能夠提供跟Adsense一樣的廣告費(當然更高更好),又能夠在次月月初就直接匯款到存款,相信會比Google更受歡迎的。
......
... read more

OZ的[隔離垃圾信通知]

新的OZ系統是外包的,目前垃圾信機制是會把被當作垃圾信的清單統整在一封信裡寄給使用者,在Gmail裡看的時候會像是右邊那樣。
附帶一提,裡面有個u920?26....不知道是真的是還是被冒充的?(e-mail寄出時並不會檢查寄信者欄位的真實性,就跟現實生活的郵政系統一樣。不過還是有IP可以查啦)

總之,Gmail預設是會先擋下圖片,然後使用者在自己看要不要顯示那些圖片。但就在我按下「顯示以下圖片」的時候,就變成了左圖那個樣子了。
那封信裡唯一的圖片(大概是外包商的logo)的確顯示出來了,可是表格裡的東西卻不見了....不曉得是哪邊的問題(懶的查了,其實看一下原始碼應該不難查),不過我猜不是Outlook的收件軟體大概也可能出現類似的情況吧。


之前還看過一篇文是說最好不要用Excel做人事資料公佈的網頁。因為這類東西的作法通常是在Excel中隱藏不該公開的資料,然後就發佈成Web網頁。但是Excel的隱藏在網頁裡也真的只是「隱藏」而不是不存在,也就是說會看HTML的人還是找的到那些資料。(其實印象中那篇文章是說那樣的網頁只要不是用IE開,就可以看到隱藏資訊....)

既然提到Excel,就順便提一下上次在清大圖書館看到的書,書名相當可怕,叫做【用Word做網頁】。......
... read more

用JS讓呈現的程式碼變色

隨著越來越誇張的免費服務,真的很希望可以完全免費的在網路上呈現很多東西。目前已知檔案可以放在Box.net
在開始看PrototypePEAR之類的東西之後,深深地覺得應該要多找這些工具才能更快地開發東西。我一直很害怕會陷入如使用DreamWeaver的困境-不會改它不支援的東西(其實我不會用DreamWeaver),畢竟我(們)不會知道自己是不是真的已經了解了那些東西的「基礎」,而已知的是若是貿然硬要使用根本不懂得「工具」,那只會成為累贅而已。
就現況而言,我自認對JS和PHP的了解能夠支援我使用Prototype和PEAR,但是再接下來呢?在我對Prototype的了解只有$()的情況下,我又嘗試使用了PWC (Prototype Window Class,一個在Prototype的基礎上建構夭壽花俏窗格的JS應用),結果當然怎麼用都不順手,還為了一個它在IE上的Bug(其實也有可能是我使用的問題)煩惱了整整一天。

PS:那個bug是,呼叫Window()必須在<body>裡還沒有任何DOM物件之時。否則IE6和IE7會說無法執行(不會說是JS錯誤),然後變成「找不到網頁」的錯誤。

回到標題要講的事情..前一篇 Blogger使用心得 - 轉錄BBS色碼文、隱藏多媒體 裡面有一些程式碼的顯現,其實那個關鍵字變色並不是手動調的喔!其實我很早就想要這樣的功能了,只是一直以來都是想在Server端做這件事情,直到看到了Prototype的code解說頁面的HTML碼才確定真的已經有人用JS做關鍵字變色了。不過,目前我看到的好像僅限於Regular Expression的應用,而且幾乎侷限在Keyword和Reserved word的變色而已,如果能夠藉由Syntax來判斷的話應該會更理想。(也就是說,希望能夠看到有人用JS來實做YACC
總之,步驟如下:
  1. 引用一些JS和CSS檔(目前我是直接連..印象中這樣不好,但是還沒去查相關法條)
    <script src='http://www.prototypejs.org/assets/2007/5/1/prototype.js' type='text/javascript'></script>
    <script src='http://www.prototypejs.org/javascripts/code_highlighter.js' type='text/javascript'></script>
    <script src='http://www.prototypejs.org/javascripts/javascript.js' type='text/javascript'></script>
    <script src='http://www.prototypejs.org/javascripts/html.js' type='text/javascript'></script>

    如果是Blogger的話,可以在po文的時候加,不過我是直接修改範本HTML,放在<head>裡
    PS:附帶一提Blogger的範本也用了頗變態的技術,範本的HTML裡頭,<script>標籤會自閉(就是變成<script />,但實際上應該要是<script></script>),而且引號會被encode(變成&quot;或&#39;),但是實際顯示的時候卻又都正常了
  2. 要放一些CSS..同樣可以改<head>裡面,或是po文的時候加(建議是前者):.html .tag { color:#34A; }
    .html .attribute { color:#B71; }
    .keywords { color: #f71; }
    .comment { color: #6c9; }
    .string { color: #392; }
    .regex { background: #CEF; color: #27b; }
    .doctype { color:red; }
    .brackets { color: navy; }
    .global { color: red; }
    .selectors { color: blue; }
    .properties { color: brown; }
    .units { color: gray; }
    .urls { color: green; }

  3. 因為想要區分程式碼跟一般文字,所以我又加上了一些CSS:code {
    display: block; /*因為<code>預設是inline物件,如果不這樣設的話就只有字的後面有顏色,而不是整個區塊*/
    white-space: pre; /*如果被自動換行的話可是會破壞程式碼縮排排版的唷,所以不允許自動換行,空白也都會留著。(IE無效,但我不想管了)*/
    overflow: auto; /*承上,如果超過一行的寬度的話,會自動有捲軸(像現在這樣:P)*/
    background: #eee;
    }

  4. 接下來就可以po文了,原理是在<code>加上以想要的語法為名的class,也就像是:<code class="html"> &lt;span style="font-style: italic;"&gt;Hahaha&lt;/span&gt;
    &lt;!-- 當然可以放註解 --&gt;</code>

    不過要注意的是大多數的Blog系統會自作聰明的轉換HTML標籤,所以編輯上可能會有點痛苦..(比方說在Blogger的WYSIWYG模式裡,我如果要打<li>的話,還是得要打&amp;lt;li&amp;gt;,不然會在切換模式的時候被自動轉換成HTML的<li>,如果又遇到是要打HTML的話,可能就又要把&再escape成&amp;了)
    另外,因為我把<code>的white-space設成pre了,所以每一個enter(包括<code>後面和</code>前面的換行),都會直接反映在結果上喔。(所以上面那個例子才會看起來像是沒排版)
以上要include的檔目前都是盜連Prototype的(其實code highliter並不是prototype計畫的部份),之後還要查GooglePage或是Box.net能不能放JS和CSS檔給別的網頁連,不然我這個Blog只會越來越肥(話說現在已經比Yahoo!奇摩首頁還要誇張了)。
話說回來,十年前的網頁也常常用很多很花俏但耗資源的JS來引人注意,現在也只是比較漂亮罷了。(也許再過十年,就不會覺得現在的品味是好的了)......
... read more

轉錄BBS色碼文、隱藏多媒體

昨天亂七八糟地測試了一下Blogger,這個範本除了之前發現的IE6下的 <li> 箭頭很大(如右圖,不過IE7就OK了)之外,寬度也不太適合BBS的文章。

原本是想把BBS的文章用Mail-to-Blogger的信箱直接寄過來的,不過因為我想要保留推文,所以色碼就變的很難處理了。查了一下PttEZSoft板得知有RainbowEditor這個軟體可以處理,試用了一下,頗堪用的,不過仍有些沒處理好的部份(以Ptt的文為例,轉錄紀錄的轉錄者ID會爆掉)。

即使色碼抽掉了也仍有問題-BBS有80個字元的寬度,排版上不合於這個範本,所以我就再加上了<pre style="overflow: auto;">這樣子就不會換行,被切掉的部份也可以用捲軸拉過去了。



多媒體的部份,常常有人內嵌Flash或是播放器在頁面中,拖慢瀏覽器的速度。話說我如果看到這樣的網頁,印象分數就直接打六折了(所以我不太喜歡Pornotube的首頁)。
至於那篇主播蘇逸洪口誤大集錦裡面的影片,是用了如下的HTML配合JS去改CSS:<input type="checkbox"
onClick="
var s = document.getElementById('video20070501').style;
s.display = this.checked ? '' : 'none';
"
/>
顯示影片
<embed id="video20070501"></embed>

如果有用 prototype.js 的話,那onClick可以改成:$('video20070501').toggle();
//連checkbox是否被勾選都不用判斷了


不過這樣就不方便連後面的文字包在一起了,其實我比較希望是這樣:<span onClick="foo();">
<input type="checkbox" />
Some texts...
<!--
畢竟就一般GUI的OS而言,
後面的文字和前面的checkbox是綁在一起的嘛~~
-->
</span>
不過懶得再改了


剛才插入圖片的時候才發現上傳圖片佔用的是Picasa的空間,可是進Picasa裡卻找不到,似乎相簿的網頁介面有被快取。
在Blogger上傳的圖片會被統一放到跟Blog同名的相簿裡,該相簿會被標示與Blogger有關,預設為不開放。......
... read more