標籤

Web (5) 電腦 (4) 免費小工具 (2) 創意 (2) 雲端 (2) 電影 (2) PHP (1) jQuery (1) 吃的 (1) 好書 (1) 手機 (1) 網路 (1) 自我勉勵 (1)

2008-08-02

Enhance Select 讓網頁更美觀

最近玩 jQuery, 這工具不錯用, 但是在入門方面, jQuery確實需要較多的時間才能熟悉.

jQuery 是由 Google 所做的, 原本的目的是為了方便進行 HTML 文件的節點查詢, 應該算是輔助工具, 是作為快速選擇出節點的一種方法, 後來為了更多的應用需求, 就有了 Plugin 的能力(其實也不是特別去加強什麼Plugin, 而是因為 JavaScript的語法本來就較為鬆散, 所以 jQuery 就把某一種方式的語法規劃為 Plugin的語法).

更多的 jQuery 請看看官方網站(http://docs.jquery.com/Main_Page)囉!

至於 Enhance Select 這東西, 則是我對 IE 的無奈下的產物, 我一向是非常不爽 M$, 他把啥都綁在一起, IE 這麼多年來不見任何長進...

任何, 對! 我說的是任何長進都沒有! 就連我新買的 NB 的 Vista 上的 IE7, 連它都說它自己"還是 IE6"(User-Agent的內容), 所以, Firefox竄起是應該的.

有在寫網頁的都知道, IE的 Select物件是不支援大多數的 Style 的, 若是想改變 IE 的 Select 的框框粗細、大小、顏色, 這些是不可能的!

絕對不是 IE 不支援邊框的 style 喔! Input、TextArea、Table的邊框在 IE 上都被支援, 為何獨獨 Select 沒有, 可以說是 IE 的 Bug!? 不, 應該說是 M$ 懶得改! (所以我痛恨托拉斯, 也痛恨美國司法部的懦弱)

那, 難道為了一個 Select 所以我整個網頁設計都要被迫跟隨嗎?

還好有 jQuery... 我利用 jQuery 自己寫了一個 Enhance Select (jQuery的Plugin), 管它是 IE 還是 FF, 這個程式都會把原有的 Select 物件隱藏起來, 換上另一個較為美觀而且更容易自定 Style 的一個 Select 組件.

(注意! 要先會用 jQuery 喔! 這是 jQuery 的 Plugin!)

使用範例(將該網頁上所有的 Select 換成 Enhance Select):
<script type='text/javascript' src='jquery.enhance_select.0.6.js'></script>
<script type='text/javascript'>
$(document).ready(function(){
$('select').enhanceSelect();
});
</script>


範例圖(這是我開發中的產品的一角):

(那個"系統編碼"就是Enhance Select的效果)

程式碼如下:
/*
* jQuery enhance_select plugin
*
* Copyright (c) 2008 Howard Chen
*
* Licensed under the GPL license:
*   http://www.gnu.org/licenses/gpl.html
*
* Revision: $Id$
* Version: 0.6
*/

;(function($) {

$.fn.extend({
enhanceSelect: function(options)
{
if (parseInt(this.attr('size')) == 0)
return this.each(function(){
new $.enhanceSelectComboBox(this, options);
});
else
return this.each(function(){
new $.enhanceSelectMultiLine(this, options);
});
}
});

$.enhanceSelectComboBox = function(selectobj, options)
{
var mSelect = $(selectobj);

var opt = $.extend({
inputClass: 'enhanceSelect',
listClass: 'enhanceSelectList',
hoverClass: 'hover',
selectedClass: 'selected',
edit: false,
width: mSelect.css('width') == 'auto' ? mSelect.width()+20 : parseInt(mSelect.css('width'))+20
}, options);

var mSelectId = selectobj.id;
var mMove = -1;
var mMouseOver = false;
var mMouseDown = false;
var mFocused = false;
var mList = null;
var mInput = null;
var mInputModified = false;
var mSelectOptions = null;
var mDropDownList = false;
var mSelectedTop = -1;

genList();
genInput();
genOptions();

mSelect.hide().before(mInput).before(mList);
mList.append(mSelectOptions).hide();

mInput
.click(function(){
if (!mDropDownList)
dropDown(true);
else
dropDown(false);
mInput.select();
})
.focus(function(){
updateFocus(true);
})
.keydown(function(event){
switch(event.keyCode)
{
// up
case 38:
var li = $($('li.'+opt.selectedClass, mList).get(0));
if (li.prev('li').size() > 0)
{
li.removeClass(opt.selectedClass);
li.prev('li').addClass(opt.selectedClass);
updateSelect();
mInput.select();
}
return false;
// down
case 40:
var li = $($('li.'+opt.selectedClass, mList).get(0));
if (li.next('li').size() > 0)
{
li.removeClass(opt.selectedClass);
li.next('li').addClass(opt.selectedClass);
updateSelect();
mInput.select();
}
return false;
case 9:
case 13:
return true;
default:
if (!opt.edit)
mInput.select();
return false;

if (event.keyCode >= 32)
{
if (mDropDownList)
dropDown(false);
mInputModified = true;
}
}
})
.blur(function(){
if (!mMouseOver)
{
dropDown(false);
if (mInputModified)
{
updateSelect(mInput.val());
mInputModified = false;
}
else
updateSelect();
updateFocus(false);
}
});

mList
.mouseover(function(event){
mMouseOver = true;
})
.mouseout(function(event){
mMouseOver = false;
})
.dblclick(function(eve){
if (window.getSelection)        window.getSelection().removeAllRanges();
else if(document.selection)     document.selection.empty();
})
.mousemove(function(){
if (window.getSelection)        window.getSelection().removeAllRanges();
else if(document.selection)     document.selection.empty();
})
.click(function(){
dropDown(false);
})
.blur(function(event){
if (!mMouseOver)
{
dropDown(false);
updateSelect();
updateFocus(false);
}
});

function genList()
{
mList = $(document.createElement('div'));
mList
.addClass(opt.listClass)
.attr('id', mSelectId+'_list');
}

function genInput()
{
mInput = $(document.createElement('input'));
mInput
.addClass(opt.inputClass)
.attr({
id: mSelectId+'_input',
type: 'text',
autocomplete: 'off',
tabIndex: mSelect.attr('tabindex')
})
.css({
width: opt.width
});

if (!opt.edit)
mInput.attr('readonly', 'readonly');
}

function genOptions()
{
mSelectOptions = document.createElement('ul');
mSelect.children('option').each(function(){
addOption({
val: $(this).val(),
html: $(this).html(),
selected: $(this).is(':selected')
});
});
}

function addOption(options)
{
var aopt = $.extend({
html: '',
val: '',
selected: false
}, options);

if (aopt.val == '' && options.html)
aopt.val = options.html;
if (aopt.html == '' && options.val)
aopt.html = options.val;

var li = document.createElement('li');
mSelectOptions.appendChild(li);

li = $(li);
li
.attr('id', aopt.val)
.html(aopt.html)
.mouseover(function(event){
$(event.target, mList).addClass(opt.hoverClass);
})
.mouseout(function(event){
$(event.target, mList).removeClass(opt.hoverClass);
})
.click(function(event){
$('li', mList).removeClass(opt.selectedClass);
$(this).addClass(opt.selectedClass);
updateSelect();
dropDown(false);
mInput.select();
});

if (aopt.selected)
{
mInput.val(aopt.html);
$('li', mList).removeClass(opt.selectedClass);
li.addClass(opt.selectedClass);
}

return this;
}

function dropDown(val)
{
if (val === null)
return mDropDownList;
if (val != mDropDownList)
{
if (val === true)
{
updateFocus(true);
var MaxHeight = parseInt(mList.css('max-height'));
MaxHeight = MaxHeight > 0 ? MaxHeight : 200;
if (mList.height() > MaxHeight)
mList.css('height', MaxHeight);
mList.css('width', opt.width+18).show();
mDropDownList = true;
mInputModified = false;
mList.attr('scrollTop', 0);
if ($('li.selected', mList).size() > 0)
mList.attr('scrollTop', $('li.selected', mList).offset().top-$('li', mList).offset().top);
}
else
{
mList.hide();
mDropDownList = false;
}
}
return this;
}

function val(newVal)
{
if (newVal === null)
return mInput.val();
$(mSelectOptions).children('li').removeClass(opt.selectedClass);
$(mSelectOptions).children('li #'.newVal).addClass(opt.selectedClass);
updateSelect();
}

function updateFocus(val)
{
if (val != mFocused)
{
mFocused = val;
if (mFocused)
mInputModified = false;
}
}

function updateSelect(val)
{
if (val != null)
{
var newOption = document.createElement('option');
mSelect.get(0).appendChild(newOption);
newOption.value = val;
newOption.selected = true;
mInput.val(val);
}
else
{
var li = $($('li.'+opt.selectedClass, mList).get(0));
mSelect.val(li.attr('id'));
mInput.val(li.html());
}
mSelect.trigger('change');
}
};

$.enhanceSelectMultiLine = function(selectobj, options)
{
var mSelect = $(selectobj);

var opt = $.extend({
listClass: 'enhanceSelectList',
hoverClass: 'hover',
selectedClass: 'selected',
width: mSelect.css('width') == 'auto' ? mSelect.width()+20 : parseInt(mSelect.css('width'))+20
}, options);

var mSelectId = selectobj.id;
var mFocused = false;
var mList = null;
var mSelectOptions = null;
var mSelectedTop = -1;

genList();
genOptions();

mSelect.hide().before(mList);
mList.append(mSelectOptions);

mList
.dblclick(function(eve){
if (window.getSelection)        window.getSelection().removeAllRanges();
else if(document.selection)     document.selection.empty();
})
.mousemove(function(){
if (window.getSelection)        window.getSelection().removeAllRanges();
else if(document.selection)     document.selection.empty();
})
.focus(function(){
updateFocus(true);
})
.blur(function(event){
updateSelect();
updateFocus(false);
});

function genList()
{
mList = $(document.createElement('div'));
mList
.addClass(opt.listClass)
.attr('id', mSelectId+'_list')
.css({
width: opt.width
});
}

function genOptions()
{
mSelectOptions = document.createElement('ul');
mSelect.children('option').each(function(){
addOption({
val: $(this).val(),
html: $(this).html(),
selected: $(this).is(':selected')
});
});
}

function addOption(options)
{
var aopt = $.extend({
html: '',
val: '',
selected: false
}, options);

if (aopt.val == '' && options.html)
aopt.val = options.html;
if (aopt.html == '' && options.val)
aopt.html = options.val;

var li = document.createElement('li');
mSelectOptions.appendChild(li);

li = $(li);
li
.attr('id', aopt.val)
.html(aopt.html)
.mouseover(function(event){
$(event.target, mList).addClass(opt.hoverClass);
})
.mouseout(function(event){
$(event.target, mList).removeClass(opt.hoverClass);
})
.click(function(event){
$('li', mList).removeClass(opt.selectedClass);
$(this).addClass(opt.selectedClass);
updateSelect();
});

if (aopt.selected)
{
$('li', mList).removeClass(opt.selectedClass);
li.addClass(opt.selectedClass);
}

return this;
}

function val(newVal)
{
if (newVal === null)
return $($('li.'+opt.selectedClass, mList).get(0)).attr('id');
$(mSelectOptions).children('li').removeClass(opt.selectedClass);
$(mSelectOptions).children('li #'.newVal).addClass(opt.selectedClass);
updateSelect();
}

function updateFocus(val)
{
if (val != mFocused)
mFocused = val;
}

function updateSelect(val)
{
if (val != null)
{
var newOption = document.createElement('option');
mSelect.get(0).appendChild(newOption);
newOption.value = val;
newOption.selected = true;
}
else
mSelect.val($($('li.'+opt.selectedClass, mList).get(0)).attr('id'));
mSelect.trigger('change');
}
};

})(jQuery);

沒有留言: