使用YUI 3,建立雅虎體育TOURNEY Pick'em遊戲

2010年3月19日,6:46上午由馬克川| 發展歷程 |

馬克川 作者簡介:馬克·川上( @ skippykawakami Twitter的 )是一個前端工程師雅虎 雅虎 體育

每年三月,在世界各地的用戶湧向雅虎幻想體育發揮我們的NCAA錦標賽支架遊戲,“ TOURNEY Pick'Em 。“這是我們最流行 ​​的遊戲之一。

在許多方面,它也是我們最簡單的一個。 只需填寫您的選擇您所期望的球隊將贏得支架。 聽起來很容易,對不對? 以及有一個問題-有9,223,372,036,854,780,000不同的可能的方式,你可以填寫您的支架。

這種荒謬的大量介紹,以及對我們的挑戰。 你怎麼9三次方可能的組合東西,所以易於使用,用戶可以填寫他們在短短幾分鐘的括號? 答案涉及到相當數量的JavaScript引擎蓋下方,我們稱之為我們的“發動機支架”。

支架的發動機,我們已經從2004年起使用的服務很好,但後6個NCAA比賽開始顯示出它的年齡。 YUI庫根本不存在,當它被第一次寫入(對於這個問題,也沒有JSON或Firebug)。 因此,今年的比賽,我們決定,而不是我們通常做的逐步改善,我們會從頭開始。 從地面改造,給我們的機會,完全現代化的支架發動機,所以這是理所當然的,我們去了現代,因為我們可以通過使用YUI 3。 這將是雅虎幻想體育已建立使用YUI 3的首批項目之一,但我們知道,在這一點上,庫的優勢是太偉大了,通過了。 令人高興的是,新的支架引擎橫空出世,甚至比我們所希望的。

雅虎幻想體育TOURNEY Pick'em

YUI的3橫空出世將非常適合建設的複雜的相互作用,我們想為支架引擎。 我們從一個完全基於點擊界面拖放接口,和YUI的3拖和能力是如此易於使用,它是實際上的第一件事,我們就工作。 我們交換接口完全由JavaScript建立一個支架的繪製與HTML和CSS,然後用JavaScript增強。 這意味著到DOM一些漂亮的深海潛水,​​但3 YUI的CSS選擇器的使用幾乎無處不在,這些短期的工作。

進入這個項目,我知道,拖式和3 YUI的CSS選擇器的功能將被證明是非常寶貴的,但我一直在3 YUI的許多有用的其他組件如何將驚訝。 對於這個職位,我想探討一個不得到盡可能多的關注: Y.Base 相應的是YUI的組件基礎設施的一部分,銳的工程師Satyen德賽有一個很好的介紹,銳劇院的工具集 。)

Y.Base Pumpin“

在支架上的發動機的工作,我發現, Y.Base是非常有用的。 有兩個有價值的東西,你有自由得到Y.Base :針對屬性和事件。 均顯著比我預想的更為有用。 銳3不要求你創建自己的類時使用Y.Base ,但我的任何類建立,甚至稍不平凡的,我要去使用Y.Base作為我的出發點。

屬性

屬性使您能夠輕鬆地配置對象,當你實例化它。 如果你已經使用YUI的許多部件或公用事業,這將是熟悉的:

 VAR CONFIG = {
    節點:節點,
     '時間':0.25
     “緩和”:Y.Easing.easeOut
 };
阿尼姆=新Y.Anim(CONFIG);

例如在上面的config變量是在行動中的屬性的一個例子。 但你得到的不僅僅是簡化了複雜對象的實例化過程。 您可以定義的getter,setter方法​​,默認值等,但對我來說,真正的力量來改變屬性值。 之前和之後立即改變屬性的值,事件被解僱,讓你的代碼,以響應對象的變化。

例如,在我們的支架發動機上的對決小圖標,彈出打開一個顯示有關如何兩隊互相堆疊的信息,當用戶點擊。

表示在JavaScript彈出一類我們稱之為MatchupPanelMatchupPanel已命名的屬性存儲參考所顯示的對決對象的matchup 在事件監聽到任何時候採取行動MatchupPanel波動matchup屬性更改。 因此,要改變我們在彈出的顯示什麼對決,我們只需要改變的matchup屬性。

 MatchupPanel =功能(){
     MatchupPanel.superclass.constructor.apply(這一點,參數);
 }

 MatchupPanel.NAME =“matchuppanel”;
 MatchupPanel.ATTRS = {
     “teamA”:{值:null},
     “teamB”:{值:null},
     “集裝箱”:{值:null},
     “對決”:{值:null},
     ...
 };

 y.extend(MatchupPanel,Y.Base,{
    初始化函數(){
         ...
         this.after(“matchupChange”,this.afterMatchupChange);
     },
     ...
     afterMatchupChange:功能(E){
         VAR米= this.get(“對決”);
         (M){
             game1 = m.get(“game_1”);
             game2 = m.get(“game_2”);
             VAR team_1 game1.getValue();
             VAR team_2 game2.getValue();
             (team_1的&& team_2){
                 this.setupDisplay(team_1,team_2);
                 this.show();
             }
            其他{
                 this.hide();
             }
         }
        其他{
             this.hide();
         }
     },
     ...
 }
  

活動

Y.Base還採用銳3的自定義事件和自定義事件冒泡 這意味著,不僅是它方便地創建和觸發自定義事件,它很容易為其他對象的響應,他們包括停止傳播事件冒泡您所指定的目標鏈,就像泡了DOM瀏覽器事件層次。

對於括號內,我們在一些地方使用。 例如,用戶墊款隊通過幾輪,形成新的對決組合。 在第一輪比賽的第一和第二場比賽的獲勝者,在第二輪的第一場比賽中面對對方,我們有顯示對決彈出的圖標。

Matchup對象是負責顯示或隱藏圖標,而每一個遊戲內的對決是由代表TeamGame對象。 當一支球隊成為一個先進的TeamGame對象,該對象觸發一個事件。 申報的Matchup對象為目標TeamGame的事件, Matchup知道它的遊戲變化之一,可以隱藏或顯示必要的圖標。

這裡有一個(非常)簡化這個例子在行動Matchup對象:

對決=函數(){
     Matchup.superclass.constructor.apply(這一點,參數);
 }

 Matchup.NAME =“對決”;
 Matchup.ATTRS = {
     “集裝箱”:{值:null},
     “game_1”:{值:null},
     “game_2”:{值:null},
     “身份證”:{值:null},
     “infotrigger”:{值:NULL}
     ...
 }

 y.extend(對決,Y.Base,{
    初始化函數(CFG){
         VAR李= this.get(“容器”);
         VAR遊戲= li.all(的“li.ysf TPE遊戲”);
         ...
         / /創建這個對決TeamGame對象的
         (VAR x = 0,X <games.size(); X +){
             gameNode = games.item(X);

             VAR gameobj =新TeamGame({
                 “對決”:這一點,
                 “集裝箱”:gameNode
             });
             (this.get(“game_1”)== NULL){
                 this.set(“game_1”,gameobj);
             }
            否則,如果(this.get(“game_2”)== NULL){
                 this.set(“game_2”,gameobj);
             }

             / /這個對決允許的TeamGame的事件泡沫
             gameobj.initTarget(本);

         }
         ...
     },
     initHandlers:函數(){
         this.on(“teamgame:改變”,this.onMatchupChange);
         this.onMatchupChange();
     },
     onMatchupChange:功能(E){
         / /每當這個對決的遊戲之一變化
         / /這將檢查,看看是否需要的信息圖標
         / /隱藏或顯示。
         ...
    },
    ...
 }

......為TeamGame對象:

 TeamGame =(){
     TeamGame.superclass.constructor.apply(這一點,參數);
     this.publish(“改變”,{前綴“teamgame”});
 }

 TeamGame.NANE =“teamgame”;
 TeamGame.ATTRS = {
     “集裝箱”:{值:null},
     “對決”:{值:null},
     “選擇”:{值:null},
     “gameid”:{值:null}
     ...
 }

 y.extend(TeamGame,Y.Base,{
    初始化函數(CFG){
         CONT = this.get(“容器”);
         (續)
             VAR SEL = cont.one(“選擇”);
             this.set(“選擇”,SEL);
             VAR SID = cont.getAttribute(“ID”);
             VAR gameid,= TeamGame.getGameId(SID);
             this.set(“gameid”,gameid);
         }
     },
     initTarget:功能(對決){
         / /允許對決是本場比賽的事件的目標。
         TARG =對決| | this.get(“對決”);
         this.addTarget(TARG);
     },
     setValue方法:功能(VAL){
         / /設置給定值的選擇菜單。
         / /這是什麼時幕後發生
         / /用戶,使他們的選秀權。
         VAR oldValue = this.getValue();
         VAR SEL = Y.Node.getDOMNode(this.get(“選擇”));
         VAR OPTS = sel.options;
         VAR selIdx = NULL;
         (VAR X = 0,X <opts.length; X + +){
             (OPTS [X]。價值== VAL){
                 selIdx = X;
             }
         }
         (selIdx!== NULL){
             sel.selectedIndex = selIdx;
             VAR newValue = this.getValue();
             gameid = this.get(“gameid”);
             this.fire(“teamgame:改變”,{
                 “遊戲”:gameid
                 “老字號”:oldValue
                 “新”:newValue
             });
            返回selIdx;
         }
        返回false;
     },
    的getValue:函數(){
        選擇this.get(“選擇”);
        返回parseInt(select.get(“值”));
     },
     ...
 }

通過組合成一個易於擴展的類的事件和屬性, Y.Base需要照顧了很多管道需要一個複雜的網絡應用程序。 對我來說,這最大的好處是,我可以勾畫出一個快速的圖框和箭頭,我多麼希望我的應用程序工作,並迅速把它轉換成工作的JavaScript。

如果你想看到所有(及以上)在行動,還是有時間為我們的其他NCAA比賽,“簽署了第二機會TOURNEY Pick'Em “。 而這一次是更容易一些,還有只有32,768方式填寫的支架。

共享和擴展: 書籤del.icio.us Digg它! | reddit!

還沒有評論

很抱歉,評論已被封閉,在這個時候。

主辦雅虎

©2006-2012雅虎公司所有權利保留。 隱私政策 - 服務條款

支持WordPress的關於雅虎 虛擬主機