標籤

Web (5) 電腦 (4) 免費小工具 (2) 創意 (2) 雲端 (2) 電影 (2) PHP (1) jQuery (1) 吃的 (1) 好書 (1) 手機 (1) 網路 (1) 自我勉勵 (1)
顯示具有 jQuery 標籤的文章。 顯示所有文章
顯示具有 jQuery 標籤的文章。 顯示所有文章

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);