上一篇裏使用css樣式虛類nonie(實際屬性是定義給了yui3-panel-hidden而不是nonie)解決了在不一樣瀏覽器下的樣式兼容問題javascript
其實,css虛類(未在CSS文件中定義具體屬性)還有不少巧用,在大量使用JS腳本和AJAX的系統中,巧用css虛類,能夠實現不少功能css
下面以我實際的開發例子介紹java
第一:使用代理時,能夠經過css虛類做爲類選擇器node
例如,我在YUI的表格裏,每一行上都有一列操做列,裏面都是以<a>標籤形式顯示操做,此列都是經過模板動態生成的,因此這些<a>標籤沒有id,而指定這些<a>標籤的響應方法,必須經過代理方式,而對應的<a>標籤則經過一個虛類來指定。其實能夠在生成標籤時指定onclick事件,可是顯然沒有代理來的好,代理不用給每一個標籤寫click方法。ajax
下面是某table(yui3的DataTable widget)的操做列的定義:數據庫
{ key: 'id', label: '<center>操做</center>', sortable: false, width: '180px', allowHTML: true, formatter: function(o) { return '<center><a class="update" href="#"><img src="../image/modify.gif">修改信息</a><a class="delete" href="#"><img src="../image/delete.gif">刪除</a></center>'; } }
而該table能夠定義代理並可使用<a>上的虛類類型來指定響應對象瀏覽器
table.delegate('click', showUpdatePanel, '.yui3-datatable-data tr .update', table); table.delegate('click', deleteData, '.yui3-datatable-data tr .delete, table);
第二,可使用虛類定義隱藏的信息app
我在某項目裏,須要在鼠標移動到表格裏時浮動顯示tooltip並根據用戶當前選擇動態顯示不一樣的信息,這些信息包括:用戶填寫的備註,領導的批覆,歷史修改記錄,邏輯驗證錯誤提示等,有的是數據載入時一次性載入的(固然也能夠選擇根據須要經過ajax加載),有的是根據用戶填寫動態生成的。對此,個人處理辦法是,把這些信息各自塞到一個指定了hidden樣式的span標籤裏,而後把span都隱藏到相關的td裏,這樣,在鼠標移動時,就經過查找對應的span標籤裏的信息,而後將這些信息拷貝到tooltip裏,而判斷當前顯示哪樣信息,就是經過span標籤額外的虛類樣式了ide
鼠標移動的代碼是這樣的:網站
warningMouseMove: function(e) { if (e.currentTarget.hasClass('warning') || e.currentTarget.hasClass('viewnote') || e.currentTarget.hasClass('viewaudit') || e.currentTarget.hasClass('viewmodify') || e.currentTarget.hasClass('viewhelp')) { if (e.currentTarget.hasClass('warning')) { var m = ''; e.currentTarget.all('.warningmessage').each(function(k, v) { if (m != '') { m += '<br>---------<br>'; } m += k.get('text').replace(/\n/g, "<br>"); }); tooltip.setStdModContent('body', m); } else if (e.currentTarget.hasClass('viewnote')) { tooltip.setStdModContent('body', e.currentTarget.one('.notecontent').get('text').replace(/\n/g, "<br>")); } else if (e.currentTarget.hasClass('viewmodify')) { tooltip.setStdModContent('body', e.currentTarget.one('.modifycontent').get('text').replace(/\n/g, "<br>")); } else if (e.currentTarget.hasClass('viewhelp')) { tooltip.setStdModContent('body', e.currentTarget.one('.helpcontent').get('text').replace(/\n/g, "<br>")); } else if (e.currentTarget.hasClass('viewaudit')) { var c = ''; if (e.currentTarget.one('.auditcontent') != null) { c = e.currentTarget.one('.auditcontent').get('text'); } if (e.currentTarget.one('.addauditcontent') != null) { if (c != '') { c += '<br>'; } c += e.currentTarget.one('.addauditcontent').get('text').replace(/\n/g, "<br>"); } tooltip.setStdModContent('body', c); } var posx = e.pageX > screen.width * 0.8 ? e.pageX - 200 : e.pageX + 10; tooltip.move([posx, (e.pageY + 20)]); if (tooltip.get('visible') === false) { Y.one('#tooltip').setStyle('opacity', '0'); } if (waitingToShow === false) { setTimeout(function() { Y.one('#tooltip').setStyle('opacity', '1'); tooltip.show(); }, 500); waitingToShow = true; } } else if (waitingToShow == true) { tooltip.hide(); waitingToShow = false; } },
解釋下:這個方法運行的對象是一個<table>表格裏的td,若是是正常狀態,則用戶輸入後會進行校驗,有錯誤的狀況下會產生warning樣式,並動態生成錯誤信息,而錯誤信息涉及的對象並不必定只是輸入數據的td。在用戶點擊了查看備註時,則會移除其它樣式,爲相關td添加viewnotes樣式,點擊查看批示,則會添加viewaudit樣式等。而用戶鼠標移動到格子上,則會根據當前樣式斷定獲取哪一個樣式span裏的信息並顯示
第三,這是我編寫的統計網站裏的一個校驗功能,報表有不少項輸入,這裏面有不少限制,包括:
一、容許空或非空
二、只容許整數
三、必須是數字(能夠是浮點數)
四、必須大於0
五、有的項和同期相比不能超過20%(超過的必須填寫備註)
六、衆多勾稽關係比較,例如a必須大於b,c必須等於d+e等等
用戶輸入時應立即時提示,而且,用戶輸入完畢後必須進行所有校驗經過方可提交
最初的一個版本,是將邏輯校驗寫在配置文件裏,而後經過讀取配置文件的數學公式進行運算
後來推翻重寫時,放棄了此項,直接將邏輯編寫在代碼裏,緣由麼,主要是維護那個配置文件太複雜,每次報表改動要折騰死人,並且裏面的項和數據庫字段以及表格表格上的代碼不匹配
因而解決方法是:非空項上添加虛樣式,統一校驗邏輯裏經過判斷樣式來進行處理
例如:
<td id="q2014-H02" class="tdinput numeric noteable blankenabled rule compare">
tdinput爲該td的正式樣式,numeric表明此td必須輸入浮點數,blankenabled說明此td容許空着不填,rule說明此td有邏輯校驗關係(具體是哪條則由邏輯校驗代碼經過td的id來判斷了),noteable則表明此td容許用戶輸入備註信息,compare說明此td項應當和去年同期的進行比對,若是超過指定比例(20%),則須要提示用戶必須輸入緣由(備註)
當用戶結束某td內的輸入時,執行checkNode方法
function compareToLastYear(lnode) { var pspan = lnode.one('.previous'); if (pspan == null) return true; removeWarning('comparewarning', lnode); var lastvalue = parseFloat(pspan.get('text')); var thisvalue = parseFloat(lnode.one('.current').get('text')); if (isNaN(lastvalue)) return true; if (lnode.one('.notecontent') != null && lnode.one('.notecontent').get('text') != '') return true; if (thisvalue > lastvalue * 1.2) { appendWarning('此項與上一期相比增加率超過了20%,上一期數值爲' + lastvalue + ',請覈對或填寫備註!', 'comparewarning', lnode); return false; } if (thisvalue < lastvalue * 0.8) { appendWarning('此項與上一期相比降低超過了20%,上一期數值爲' + lastvalue + ',請覈對或填寫備註!', 'comparewarning', lnode); return false; } return true; }; function removeWarning(classname) { for (var i = 1; i < arguments.length; i++) { var lnode = arguments[i]; lnode.all('.' + classname).each(function(k, v) { k.remove(); }); if (lnode.one('.warningmessage') == null) { lnode.removeClass('warning'); } } }; function appendWarning(message, classname) { for (var i = 2; i < arguments.length; i++) { lnode = arguments[i]; if (reportviewitem == 'warning' && !lnode.hasClass('warning')) { lnode.addClass('warning'); } lnode.appendChild(Y.Node.create('<span class="warningmessage ' + classname + '"></span>').set('text', message)); } }; function checkZero(lnode) { var v = lnode.one('.current').get('text'); removeWarning('zerowarning', lnode); if (parseFloat(v) <= 0) { appendWarning('此項必須大於0!', 'zerowarning', lnode); return false; } return true; }; function checkInput(lnode) { var v = lnode.one('.current').get('text'); removeWarning('inputwarning', lnode); if (!lnode.hasClass('blankenabled') && v == '') { appendWarning('此項必須填寫!', 'inputwarning', lnode); return false; } return true; }; //若是有規則,優先檢測規則 function checkNode(lnode) { checkInput(lnode); if (lnode.hasClass('rule')) { checkRule(lnode); } if (lnode.hasClass('nonzero')) { checkZero(lnode); } if (lnode.hasClass('compare')) { compareToLastYear(lnode); } };
checkRule方法就不貼了,裏面涉及到報表的具體勾稽關係,numberic和number項,則是寫在用戶輸入完畢後,不在統一的校驗邏輯裏,由於這些項可能容許空
第四,經過css樣式來進行多語言切換
其實這是個偷懶方法,在頁面裏用了多種方法顯示多語言,而後呢,有一部分頁面上不太好經過多語言資源配置的,例如中文和英文順序不同(中間還有其它東西),這時能夠用<span class="en hidden">english</span><span class="zh">中文</span>這種模式,而後呢,在腳本里判斷下,若是是英文呢,就執行
Y.all('.zh').addClass('hidden'); Y.all('.en').removeClass('hidden');