因為專案的關係,需要將某一隻擁有龐大的CSS庫的HTML頁面瘦身,所以撰寫這一隻程式。
CSS可以壓縮,但是當壓縮之後的檔案依然很大,而偏偏該HTML內所使用的class其實不多的時候,怎麼辦?
我想到的方法,就是將有用到的class自正在顯示HTML中的瀏覽器內取得,這樣是最精確無誤的,所以,這隻JS程式,就是在瀏覽器開啟這樣的HTML時使用的。
使用方法,就是將該JS安插進HTML內,當HTML被開啟時,即可以在console內看見所有的css了。
如果HTML內的element是會變動或是增減的,也就是說若是HTML顯示的css在不同的時機會有不同的顯示方式時,則可以在想要擷取css時,使用chrome的console內的命令列內下指令「dumpAllCss();」即可。
get_css_from_html.js
2015-12-16
2010-08-13
閱讀「雲端策略」
中華電信也提供雲端運算服務?
對於「雲端運算」一詞,可能已有「可能的權威」已經下了定義,但是從這名詞的氾濫程度來看,可以很肯定的知道,現在的每個網路相關產業都設法跟雲端沾上邊,就算是胡扯也值得。
從前的主機租賃方案現在換個名詞就變成了雲端運算服務?不過就是自己丟個主機去中華電信機房,或是機房幫你購置架設一個主機,現在則是多一個「虛擬化主機方案」,如此而已。
完整的SDK才是雲端
對的,我個人主觀的認定「雲端運算」的主要元素是SDK,能夠提供極大效能與廣度的軟體應用平台的才是真正的雲端運算;就像Google App Engine一樣,有著完整的程式語言函式庫與開發環境,讓使用者開發應用系統時,得以專注於應用層面的開發,不再需要顧慮作業系統的差異、硬體環境的影響;只要開發雲程式與端程式之間的訊息交換與介面方式,其他的問題都交給雲端服務商即可。在此一定義下,中華電信的雲端運算服務自然不是我認為的雲端,不過就是裝個作業系統可以讓你Run,系統開發與環境的問題依然存在著。
IBM才是雲端的一種
IBM推行「軟體服務」已有相當久的時間了,雖然沒有確切的資料可以知道IBM從何時開始著手「整合性的軟體服務」(我記得應是2000年前就開始了),但是IBM努力至今,總算可以將「雲端運算」與「軟體服務」劃上等號了。IBM有著相當完整的企業應用函式庫,以及管理、分析、設計等服務的支持,它不像GAE那麼開放,卻也提供了相當充足的企業雲端應用方案了。
2010-08-01
HTML 5 隨寫
雖說現在開始玩HTML5可能為時已晚,但是總比都沒有起步好!
請看這「關於HTML5的Wiki」
HTML5最具特色的是網頁上即時的畫面處理能力,以及資料暫存能力。
「畫面處理」可以讓網頁逐漸擺脫Flash的陰影,讓網頁可以直接以標籤與JavaScript繪製圖形,或是播放影片,這可是Adobe所不樂見的,也是一堆Flash工作者所抗拒的。
以我程式設計者的觀點而言,Flash實在是很不好的瀏覽應用方式,因為Flash不受規格控管,它只是一個Plugin;在Adobe獨立管理之下,很容易因為程式設計的技術、規格發散等問題,導致瀏覽端不穩定,造成系統安全問題。舉個例來說,就像是IE,一個獨自延伸規格的瀏覽器,僅僅靠著微軟以暴力手段將瀏覽器硬塞給使用者而坐大,從IE6起完全沒有進步,
IE7生命期不到一年,IE8這爛東西相繼推出且依然不知改進,只有換換介面容貌並聲稱將更為安全而了事,這就是獨立管理的問題。
「資料暫存能力」這我可就非常重視了,這功能是資訊系統的一大福音,它可以讓網頁瀏覽器暫存資料,就像是裝一個資料庫在瀏覽端;這個資料庫依然是以暫存為主,不適合用來作為主要儲存空間,它最大的功能,就是作為系統離線時的資料暫存空間,就像是Gmail,它已經支援這個暫存功能,可以在沒有網路連線的狀態下撰寫EMail並且發送,雖然沒有真的發送郵件出去,但是當下次網路連線正常時,該新增的郵件會在同步時被發送。
下面是HTML5的評分,依支援HTML5的程度評分,分數越高支援程度越好,反之則越差。
IE8依然是最低分(毫無建樹的瀏覽器),最高分的是Safari。
您也可以上到 http://www.html5test.com/ 看看自己使用的瀏覽器評分為多少。
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):
範例圖(這是我開發中的產品的一角):

(那個"系統編碼"就是Enhance Select的效果)
程式碼如下:
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);
|
2008-07-30
兩天了, 為了測一個不明原因的錯誤, 差點被搞瘋了.
最近, 為了產品 HowIM 如火如荼的研發與測試, 總是搞到早上才睡.
HowIM 是什麼? 以後再介紹了.
至於那個讓我測了兩天的問題, 就是 eAccelerator 所產生的, 且聽我概略的描述一下.
首先, 這個 HowIM 產品使用了 Apache + PHP + Sqlite3 作為網頁端的程式架構, 並且在 PHP 多加了 eAccelerator 模組, 以作為加速之用.
由於這產品的某些網頁對於資料的讀取速度有著相當高的要求, 故需要一種共用記憶體的功能, 最好是類似於 ASP 的 Application, 用以減少資料庫的存取.
大約在上個月, 我在網上檢索了所有有關的功能選項, 經大量測試後發現, 在 Windows 上 eAccelerator 提供的共用記憶體功能較為穩定, 而且程式還滿好寫的.
在相關的測試完成後, 我開始在這產品大量使用 eAccelerator 的共用記憶體功能, 主要的函數包括: eaccelerator_lock, eaccelerator_unlock, eaccelerator_get, eaccelerator_put.
在此一階段的開發告一段落時, 我用了其他手邊的電腦測一下, 發現了一個重大的問題, 那就是 eAccelerator 有將共用記憶體依照 $_SERVER['SERVER_NAME'] 分類.
怪怪, 我先前的測試自認是很充足的, 這部分也曾測試過無誤才對, 竟然到現在才發現此一問題.
這問題害我多花了四個小時找替代方案, 在所有的替代方案皆失敗時, 我才又回去找原因起頭.
偏偏網路上對於 eAccelerator 的都是"天下文章一大抄", 少有見解與詳細說明的, 而官方的網站卻又是亂七八糟(據說是停站或是eAccelerator停止開發? eAccelerator網址).
再另外花下了數小時的搜尋時間後, 總算想到了方法, 就是回去看看 eAccelerator 的 Source Code.
終於被我找到了(在 eaccelerator.c 與 cache.c), 原來 eAccelerator 在 php.ini 裡可以設置 eaccelerator.name_space, 這個 eaccelerator.name_space 是所有 eAccelerator 鍵值的 name_space.
當 eaccelerator.name_space 沒被設置時, eAccelerator 會把 $_SERVER['SERVER_NAME'] 當作 Name Space.
也就是說, 假定本機的 IP 是 192.168.11.22, 則在本機使用 http://localhost 與 另一台遠端電腦用 http://192.168.11.22 的網址, 同樣查詢本機的 Apache 時, 所使用的鍵值是被隔開的, 就算是同樣存取同一鍵值也會完全不相干.
在改了 php.ini, 加了 eaccelerator.name_space 後, OK了, 鍵值都相同了.
附加說一下, Windows 下的 PHP 還有其他的共用記憶體方案, 如: MMCache, shmop, 這些方案的問題更大, 會導致 Apache 莫名其妙的當掉, 完全不能用.
HowIM 是什麼? 以後再介紹了.
至於那個讓我測了兩天的問題, 就是 eAccelerator 所產生的, 且聽我概略的描述一下.
首先, 這個 HowIM 產品使用了 Apache + PHP + Sqlite3 作為網頁端的程式架構, 並且在 PHP 多加了 eAccelerator 模組, 以作為加速之用.
由於這產品的某些網頁對於資料的讀取速度有著相當高的要求, 故需要一種共用記憶體的功能, 最好是類似於 ASP 的 Application, 用以減少資料庫的存取.
大約在上個月, 我在網上檢索了所有有關的功能選項, 經大量測試後發現, 在 Windows 上 eAccelerator 提供的共用記憶體功能較為穩定, 而且程式還滿好寫的.
在相關的測試完成後, 我開始在這產品大量使用 eAccelerator 的共用記憶體功能, 主要的函數包括: eaccelerator_lock, eaccelerator_unlock, eaccelerator_get, eaccelerator_put.
在此一階段的開發告一段落時, 我用了其他手邊的電腦測一下, 發現了一個重大的問題, 那就是 eAccelerator 有將共用記憶體依照 $_SERVER['SERVER_NAME'] 分類.
怪怪, 我先前的測試自認是很充足的, 這部分也曾測試過無誤才對, 竟然到現在才發現此一問題.
這問題害我多花了四個小時找替代方案, 在所有的替代方案皆失敗時, 我才又回去找原因起頭.
偏偏網路上對於 eAccelerator 的都是"天下文章一大抄", 少有見解與詳細說明的, 而官方的網站卻又是亂七八糟(據說是停站或是eAccelerator停止開發? eAccelerator網址).
再另外花下了數小時的搜尋時間後, 總算想到了方法, 就是回去看看 eAccelerator 的 Source Code.
終於被我找到了(在 eaccelerator.c 與 cache.c), 原來 eAccelerator 在 php.ini 裡可以設置 eaccelerator.name_space, 這個 eaccelerator.name_space 是所有 eAccelerator 鍵值的 name_space.
當 eaccelerator.name_space 沒被設置時, eAccelerator 會把 $_SERVER['SERVER_NAME'] 當作 Name Space.
也就是說, 假定本機的 IP 是 192.168.11.22, 則在本機使用 http://localhost 與 另一台遠端電腦用 http://192.168.11.22 的網址, 同樣查詢本機的 Apache 時, 所使用的鍵值是被隔開的, 就算是同樣存取同一鍵值也會完全不相干.
在改了 php.ini, 加了 eaccelerator.name_space 後, OK了, 鍵值都相同了.
附加說一下, Windows 下的 PHP 還有其他的共用記憶體方案, 如: MMCache, shmop, 這些方案的問題更大, 會導致 Apache 莫名其妙的當掉, 完全不能用.
訂閱:
文章 (Atom)



