2009/1/24

透過 javascript 來新增與刪除上傳檔案《by 童顏未老人》

 最近又碰到一個比較困難的東西,就是要在使用者上傳檔案時,需要可以任意的新增檔案,也要能隨意刪出任一個已選的檔案。

 如下圖是最先的狀況,


 使用者可以任意的點選「新增檔案」來增加上傳的檔案數。


 若覺得不妥想再刪除,只要點選該檔案後面的「刪除」,即可。


 新增的部份比較簡單,刪除的部份我花了不少時間才弄出來。

 在程式本體中,請如下的程式碼 :


主要是設了一個容器 fieldset 用來包含著每一個讓人去上傳檔案之用。在這裏先放上一個,方便使用者來用。當使用者想增加其它的檔案時,就點選上面的「新增檔案」按鈕,透過 onclick 去發動 addupload()。

var fieldcount = 1;

function addupload() {
fieldcount++;
var newfield = document.createElement('input');
newfield.type = 'file';
newfield.name = 'file' + fieldcount;
newfield.id = 'file' + fieldcount;
newfield.size = '60';
document.getElementById('fs').appendChild(newfield);

var newbutton = document.createElement('input');
newbutton.type = 'button';
newbutton.name = 'b' + fieldcount;
newbutton.id = 'b' + fieldcount;
newbutton.value = '刪除';
newbutton.onclick=function(){delfile(this.getAttribute('id'));};
document.getElementById('fs').appendChild(newbutton);

}

(以上 程式碼要包函在 script 和/script 中 )

因為我們在程式中已預先擺了一組可供使用者上傳用的檔案按鈕,所以作為 counter 用的 fieldcount 起始值為 1。然後每次被 call 一次 addupload 時,便立刻加一。然後利用 createElement 來創建兩個結點,一個是讓人上傳檔案用的欄位,另一個是用刪除該上傳欄位用的按鈕。各自將其 attribute 上進去後,在利用 appendChild 來將兩個節點上到 fs ( fieldset )這個父容器之下。

要想刪除認一指定的欄位時,同時也得把後面的刪除鈕一併刪除。當點選了「刪除」鈕時,會觸發 onclick 去執行 delfile(this.getAttribute('id')), 其中要把那一顆刪除鈕的 id 一併傳到delfile 這 function 去。

function delfile(idname) {
var filename = 'file' + idname.substr(1,1);

var filex = document.getElementById(filename);
var bx = document.getElementById(idname);
filex.parentNode.removeChild(filex);
bx.parentNode.removeChild(bx);
}

因為每一組的 上傳欄位的 id 都是 file1、file2、file3、....,其相對應的「刪除」鈕之 id 為 b1、b2、b3...,所以只要透過 substr(1,1) 將「刪除」鈕 id 的第二碼取出,便可組合出相對應上傳欄位的 id 名。最後透過 父容器的 removeChild 便可將兩者一一移去!

2009/1/22

ie6 下的覆蓋問題解決《by 童顏未老人》

 這幾天被一個工作上的問題給困擾住了,小弟寫的網頁需要當滑鼠停在會員名字上或是會員的照片上時,要出現該會員的簡介。這功能原本不算太難,用小弟之前的方法,光用 css 就可以辦的很好。但是當套用在用會員照片排成的九宮格狀時,在 ie6 下會員名片會被隔壁的照片壓在下面弄的支離破碎,但是在 firefox 下卻仍有很好的表現。

慘不忍睹的 ie6 表現狀況:


firefox 下的狀況正是我所要的:


 但是我不能犧牲使用比例還是最多的 ie6 使用者,所以只得另謀他法了,有朋友介紹我使用
[jQuery] bgiframe Plugin,不過我現在情況很趕,無法仔系去鑽研 jQuery,那可得等我過年有空時慢慢去研究,我現在能用的便是 javascript 和 css 了,我試了一天後終於給我弄出來了。這想穿了其實也沒什麼高明之處,就是得花時間想一下。

首先在整個 程式最末端埋入一整段會員名片的程式碼,

<div style="position: absolute; width: 220px; height: 140px; z-index: 1;
left: -1000px; top: -1000px" id="mycard">
<table border="1" cellpadding="0" style="border-collapse: collapse"
width="220" id="table3"
height="140" bordercolor="#76A9B4">
<tr>
<td id="carddata" bgcolor="#E1F7F7">
<table width="220" height="140" border="0"
cellpadding="0" cellspacing="10" bgcolor="#E1F7F7">
<tr>
<td height="66" valign="top" align="center">
<table width="100%" border="0"
cellpadding="0" cellspacing="0">
<tr>
<td width="66" valign="top" align="center">
<table width="66" height="66" border="0"
cellpadding="0" cellspacing="0" bgcolor="#418488">
<tr>
<td align="center"><img id="pic2" src=""
width="60" height="60"></td>
</tr>
</table>
</td>
<td width="8">&nbsp;</td>
<td valign="top"><table width="100%" height="22"
border="0" cellpadding="0"
cellspacing="0" bgcolor="#C0E2DF">
<tr>
<td width="5">&nbsp;</td>
<td valign="bottom"><span class="MwordCL01"
id='username'></span>&nbsp;-<span class="Sword02"
id="sexname"></span></td>
</tr>
</table>
<table width="100%" border="0" cellspacing="0"
cellpadding="0">
<tr>
<td width="5" height="24">&nbsp;</td>
<td height="24" valign="bottom">
<span class="Sword02">層級:</span>
<span class="Sword02" id="attname"></span></td>
</tr>
<tr>
<td width="5" height="19">&nbsp;</td>
<td height="19" valign="bottom">
<span class="Sword02">區域:</span>
<span class="Sword02" id="codename"></span></td>
</tr>
</table> </td>
</tr>
</table>
</td>
</tr>
<tr>
<td bgcolor="#FFFFFF" class="SwordCL01">
<table width="100%" border="0"
cellspacing="0" cellpadding="0">
<tr>
<td width="70" height="19" align="right"
class="SwordCL01">健康部落:</td>
<td height="19" class="Sword01"><nobr>
<? if ( strstr($_SERVER["HTTP_USER_AGENT"],"MSIE")) { ?>
<span style="width:130;text-overflow: ellipsis;overflow: hidden;"
id="vip_name"></span></nobr></td>
<? }else{ ?>
<div style="width:130;text-overflow: ellipsis;overflow: hidden;"
id="vip_name"></div></nobr></td>
<? } ?>
</tr>
<tr>
<td width="70" height="19" align="right"
class="SwordCL01">發表篇數:</td>
<td height="19" class="Sword01" id="doccnt">
<span class="Sword01">篇</span></td>
</tr>
</table></td>
</tr>
</table>
</td>
</tr>
</table>
</div>

因為我需要在整個網站到處都會用到這個會員名片,所以我是把它單獨寫成一斷的程式,然後在每一隻需要用的程式末端下

<?include('Common/card.phtml');?>
</div>
</body>
</html>

 然後另外再寫一支的放滿我需要的 junction 的 js ,也是方便每隻需要用到會員名片的程式來 call !

<script language="javascript" src="/Js/feijer.js"></script>

其內容如下 :

function CardShow(obj,ty,lx,pic2,username,sexname,attname,codename,vip_name,doccnt){
enoter_IsBoard = 1;

if(enoter_IsBoard){

var enoter_demo = document.getElementById("mycard").style;
var leftNum,topNum;
enoter_demo.visibility="visible";

document.getElementById("pic2").src = pic2;
document.getElementById("username").innerHTML = username;
document.getElementById("sexname").innerHTML = sexname;
document.getElementById("attname").innerHTML = attname;
document.getElementById("codename").innerHTML = codename;
document.getElementById("vip_name").innerHTML = vip_name;
document.getElementById("doccnt").innerHTML = doccnt;
var _x = getObjX(obj);
var _y = getObjY(obj);

leftNum=19;
topNum=0;

document.getElementById("mycard").style.left = Number(_x) + lx +"px";
document.getElementById("mycard").style.top = Number(_y) + ty +"px";
}
}

function getObjX(obj){
var hlcleft = 0;
if (obj.offsetParent){
while (obj.offsetParent){
hlcleft += obj.offsetLeft;
obj = obj.offsetParent;
}
}else if (obj.x) hlcleft += obj.x;
return hlcleft;
}

function getObjY(obj){
var hlctop = 0;
if (obj.offsetParent){
while (obj.offsetParent){
hlctop += obj.offsetTop;
obj = obj.offsetParent;
}
}else if (obj.y)hlctop += obj.y;
return hlctop;
}

function CardClose(){
document.getElementById("mycard").style.left=-1000+"px";
document.getElementById("mycard").style.top=-1000+"px";
}

然後程式需要的地方,除了把值傳進去 function ,並可以指定名片視窗要出現在 父容器的那邊,因為有時那個名片太靠右邊時,會被畫面切割掉,這時就可以調整 ty lx 兩個值來指定七其位置。

<a href="<?=$Blog;?>"
onmouseover="CardShow(this,30,60,'<?=$pic2;?>','<?=$username;?>','<?=$sexname;?>',
'<?=$attname;?>','<?=$codename;?>',
'<?=$vip_name;?>','<?=$doccnt;?>');"
onmouseout="CardClose();">

所以當 onmouseover 被觸發時,便去 call js 中的 CardShow function ,再一一的將資料放會員名片中,如此便可以將名片無誤的在想要的地方去呈現。

2009/1/12

php : 上傳圖片後再切出並縮小成正方形圖《by 童顏未老人》

 這次的新需求是,會員要可以上傳自己喜愛的照片,而且要大小不拘,然後需由每一張圖居中的取出最大範圍的正方形圖後,在把他縮小到 60 X 60 的大小去,再存到系統上面去,這樣一來可以減低系統的硬碟的負擔。要作到這樣的話,就必需要利用到 GD 的函數了。

 例如,一張 1600 X 1200 的照片上傳以後,需先拮取其中的 1200 X 1200 (中心點不變),再將其縮小成 60 X 60 的圖片!

 在主要的輸入畫面上:

<form name="frm" method="POST" action="loadpic.php" enctype="multipart/form-data">
<input id="filename" type="file" size="45" name="filename">( 請上傳您的個人照片!)
<input type="submit" name="doit" value="送出">
</form>

在這裏最重要的是在 <form> 中必需要加上 enctype="multipart/form-data"!

而在 loadpic.php 這隻主要程式中,應如下的寫:

先定義出一個 function 用來抓副檔名:

function getFiletype ($FileName) {
$num=strrpos($FileName,".");
return ".".substr($FileName,$num+1);
}

// 取得上傳的圖片
$src = imagecreatefromjpeg($_FILES['filename']['tmp_name']);

// 取得圖片的寬
$src_w = imagesx($src);

// 取得圖片的長
$src_h = imagesy($src);

// 取得圖片的副檔名 ( 如 jpg, gif... )
$src_type = strtolower(getFiletype($_FILES["filename"]["name"]));

// 依長與寬兩者最短的邊來算出要抓的正方形邊長
if( $src_w > $src_h){
$new_w = $src_h;
$new_h = $src_h;
}else{
$new_w = $src_w;
$new_h = $src_w;
}

// 以長方形的中心來取得正方形的左上方原點
$srt_w = ( $src_w - $new_w ) / 2;
$srt_h = ( $src_h - $new_h ) / 2;

// 定義一個圖形 ( 針對正方形圖形 )
$newpc = imagecreatetruecolor($new_w,$new_h);

// 抓取正方形的截圖
imagecopy($newpc, $src, 0, 0, $srt_w, $srt_h, $new_w, $new_h );

// 建立縮圖
$finpic = imagecreatetruecolor(60,60);

// 開始縮圖
imagecopyresampled($finpic, $newpc, 0, 0, 0, 0, 60, 60, $new_w, $new_h);

// 儲存縮圖到指定的目錄存放 , 檔名就是記錄在 SESSION 中的 login name
imagejpeg($finpic,
"../../images/Upload/Users/".$_SESSION["MemberLoginName"].$src_type);

// 將檔名存到變數 $filename 去,以備記錄到 table 去,方便日後依會員的帳號來抓取圖片
$filename = $_SESSION["MemberLoginName"].$src_type;

大功告成!

2009/1/10

利用 css 來做到 title/alt 的功能《by 童顏未老人》

 剛剛試出一個或許對眾高手來說,是很簡單而且不太入流的技術,不過這可是我弄了好久才學到的。特別記錄下來免的以後會忘了。

 是這樣的,我希望在網頁上當使用者將滑鼠移動到某個物件上面時,右下方就會跳出一個簡單的說明,如下圖:

 這原本是不難的,只要用 title 這屬性就可以作到了,但是那樣的話,字會很小,而且沒什麼變化,對年繼大的人來說頗不友善的。於是我便動到 css 的頭上,再參考到網路上一個高手的作法,我略加修改一下,就相當的適合我用了。

首先定義一下 css 的部份


<style type="text/css">
.info {position:relative;}
.info:hover {background:#eee;color:#333;}
.info span {display: none }
.info:hover span {
display:block;
position:absolute;
top:30px;
left:60px;
width:400px;
border:1px solid #ff0000;
background:#FDFFB4;
color:#000000;
padding:5px;
text-align:left;
z-index:9;
text-decoration:none;}
</style>


然後對於 目標的地方修改 如下:

<a href="../News/List.phtml?StarID=<?echo $StarID?>" class="info">
<img src="../images/bt042.gif" name="Image0_4"
id="Image0_4" width="92" height="26" border="0">
<span>隨時將五大星球最新的資訊及活動傳達給您。</span></a>


主要的用意便是,想透過 <a> </a>裏面所包的 <span> 來顯示出那段說明。但是當游標尚未進入前,這段 span 先用 display:none; 來讓它隱藏起來。

當滑鼠的游標進入標的時,再用 display:block;的方式讓它出現,並在設定一下表現方式 ( 離游標的位置、字體、顏色‧‧‧ )

當然了 <a> 元素不要忘了設定一下 class="info" !

還有 info 本身要設定為 position:relative; ,否則那個說明會固定在畫面的左上角!

這樣就可以達到我想要的目標! :)

2009/1/7

水平線標籤在 ie 和 firefox 之不同的解決《by 童顏未老人》

 微軟的 ie 有點討厭,一些 html 的語法就是要與別人的不一樣,最近為了要讓自家公司的網頁能通吃 ie、 firefox ,於是下了苦心去調整程式。

 之前公司的在繪製長條圖時,都是採用圖片,然後再利用 width 的屬性來將其拉長到想要的長度!不過後來連圖也不想用了,畢竟圖還是有一點大小,為了省下一點點的速度,所以把它換成 html 的語法。

 當時採用的是
,這個繪製水平線的標籤。因為要區分嚴重性,所以線本身需要顏色管理,因此在
裏面特用了 css 的 style 來設定它的顏色和厚度。而且
在 default 上周在上下兩邊會有一點 margin,所以當時是如此下:

 其結果在 ie 中能得到滿意的效果,如下圖:

 但是在 firefox 中,卻是慘不忍睹,如下:

 於是經過一番測試後終於了解到,firefox 當設立 height 後,水平線本身是中空的, css 中的 color 所指定的顏色通通沒用。而且 firefox 對於
的上下 default margin 也和 ie 不同,所以程式有得依 ie 和 firefox 的不同來分別設定了!

 這樣一來, ie 還是可以好好的保遲原來的效果, firefox 的效果也能令人滿意了!