SCMLife.com

 找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 3911|回复: 1

[推荐] 扩展 Dojo dijits 来创建自定义小部件

[复制链接]
发表于 2013-2-19 09:52:41 | 显示全部楼层 |阅读模式
本帖最后由 技术狂人 于 2013-2-19 10:40 编辑 , l  Q1 C$ v7 ]/ ^

$ D7 P$ t, f/ ]5 |% c  n
简介
Dojo Toolkit 是一个强大的 JavaScript™ 库,支持 Web 开发人员使用面向对象的小部件,用最少的开发时间和工作量来创建富 Internet 应用程序。Dojo Toolkit 提供了 4 个包,它们分别是 Dojo(核心)、Dijit(UI 框架)、dojox(dojo 扩展)和 util。您可以原封不动地使用该工具包提供的功能,也可扩展它们并创建自己的小部件。提供的功能包括 DOM 操作、使用 AJAX 开发、事件、数据存储等。
. P! j2 _" {! ?0 }Dijit(dojo 小部件)包是 dojo 自己的 UI 库,它包含一组 dojo 类,使开发人员能够以最少的工作创建功能丰富且强大的跨平台 Web 2.0 接口。这些 Dijit 小部件(或 dijit)支持一些易于操作的主题。这个包中的 dijit 示例包括按钮、文本字段、编辑器、进度条等。! W: P8 u& a* g7 Z) z3 z
举例而言,您可以使用这些 dijit 创建一个提交表单,其中包含用于名称、电子邮件地址和电话号码的文本字段,以及日期字段、复选框、按钮和验证,所有这些在几分钟即可完成,需要的 JavaScript 知识也极少。4 r$ K9 ?2 s4 j$ E8 _4 d/ r! U
提供的一个功能最丰富的 dijit 是 Calendar dijit,它支持在一个月的上下文中显示日历。用户可轻松地逐月、逐年导航,或者跳到同一年中任一个月,以选择特定的日期。
: t! c7 I/ v* n( Y8 c6 @' B在开发富 Internet 应用程序 (RIA) 时,通常可以原封不动地使用 dijit。但是,有时您可能需要使用不同的样式(比如更改颜色或主题),或者需要进行更复杂的更改,其中可能需要结合使用某些功能、模板和样式更改。要满足这些需求,则需要从头创建一个新的自定义小部件,也可以创建一个扩展现有 dijit 的自定义小部件。
7 o+ }/ t$ |& ?& H0 }& C2 Z9 @本文提供了一个练习,在这个练习中,您需要在自己的网站上使用 Calendar 小部件的不同变体。为了满足此需求,您需要创建一个新类。此练习使用了 Dojo version 1.7,提供了探索 Calendar dijit 的机会和以极少的改动重用现有 dijit 来节省开发时间的方式。您还会看到在 Dojo 1.7 中声明的一个新类的实用示例,探索一些 Dojo 基础功能,比如数据操作、hitch、发布和订阅等。) o7 m. q' V" }3 Q; w
问题
在此练习中,您将使用 Calendar dijit 的一个具有以下需求的自定义版本:. S/ }( s  C7 s7 }8 v3 m( G
  • 日历应仅显示当月的日期(隐藏和禁用不属于当月的日期)。
  • 日历应仅在底部显示当前年份(没有去年或明年)。
  • 日历应在日历小部件底部显示当月的名称。
  • 用户无法跳到任何其他月份(禁用顶部的月份下拉按钮)。
  • 提取日历顶部显示的用于逐月移动(向后或向前)的箭头,将日历旁边的箭头显示为 dijit 按钮。这两个新按钮是用户更改月份的惟一方式。
  • 具有最小和最大边界日期,这意味着所有在此边界外的日期都应该是禁用和不可访问的。
  • 在到达边界日期时,禁用相应的月份导航按钮。
  • 向日历中选定的日期添加特殊的样式。
  • 当用户选择某个日期时,将该日期传递给一个将处理新选择的值的函数。& Y$ n( M* f, s& s( q3 _( D$ Q
解决方法是创建一个自定义小部件,这个小部件通过使用 JavaScript 和 CSS 编辑 Calendar dijit 来开发。图 1 显示了应用上面需求之前(左侧)和之后(右侧)的 Calendar 小部件。
( k" G! Q9 K: a8 \0 f* B
0 `" a6 Z8 O6 ^3 j7 N图 1. 标准 Calendar dijit 与自定义 Calendar 小部件的对比6 @9 d& P, \- Z9 ]- ?: U; M1 |! s6 u
; V: @. H" ~3 a
为此,您将需要创建 3 个文件:1 ~" a7 ]9 V& Y$ ]$ g$ n/ _
  • Dijit 模板:一个将显示自定义小部件的组件的标记文件。
  • Dijit 类:一个使用声明 (JavaScript) 创建的小部件类。
  • CSS 文件:包含所有必要的样式表类。  f6 m2 u1 Q3 a( X& _3 p
图 2 显示了自定义小部件的文件结构和位置。您的起点是 index.html,它在本示例中充当了小部件的控制器。simple.css 文件将包含所有样式。
& V) _- e; ]0 B' ]
5 i. \7 O& V7 c/ y% {7 u  x  ?图 2. 文件结构
6 ~( s+ a% r6 E1 ^+ w; u  n4 `
: ~# Q' B5 d+ G. r3 m& z
: y* p6 e, m  N& [4 ]

" n; ]% h; M( H" F2 P( C/ Z
创建小部件
dijit 模板
创建 3 个 JavaScript div 元素:一个用于日历,两个用于向前和向后逐月导航的箭头按钮(清单 1)。这些 div 将使用附加点 (data-dojo-attach-point) 进行引用。使用附加点比使用 id 更好,因为它使您能够在同一个页面上拥有同一个小部件的多个实例,无需担忧 id 冲突。; E  ~9 t8 K7 f1 N  a
( E3 v% p, p; e4 C
清单 1. dijit 模板' o/ h' |) w+ Z- G% j  Z  l
<div class="CalendarArrow">
$ q7 y/ j" O. k5 Z# Q5 A$ |<div data-dojo-attach-point="calendarPreviousMonthButtonAP"></div>
8 J% V; {3 ^6 M8 h7 G</div>
" E1 B/ B, N6 m4 G+ G/ K( w/ |6 f& H* J+ L
<div class="CalendarDijit">
7 |  f" \+ n$ h5 a6 S# H0 P) k<span data-dojo-attach-point="calendarMonthOneAttachPoint"></span>
( e. f0 Y# o4 H# r</div># X) N; {0 Y4 o, ?
8 g+ g; H0 o& [+ E0 q6 G  }: M
<div class="CalendarArrow">
8 C9 _! ^) s% f; E& O<div data-dojo-attach-point="calendarFollowingMonthButtonAP"></div>
( }2 d! T& [% N! z</div>

+ k' ~3 s- U7 A: `- P
dijit 类
根据应用程序需求,您需要定义以下变量:& d# J: s; z& {2 |( E9 N% y. Y" U
  • selectedDate:日历的初始值。
  • currentFocusDate:一个值,日历会引用该值来了解要显示的月份;该值最初被设置为等于 selectedDate。
  • calendarInstance:Dijit 日历实例。
  • bookingWindowMaxDate:日历中允许的最晚的日期。
  • bookingWindowMinDate:日历中允许的最早的日期。
  • onValueSelectedPublishIDString:表示发布/订阅频道(或主题)的字符串。# l1 U8 _" J: U( Q4 x7 A9 f9 r
JavaScript 函数
首先修改以下样式表元素:
( J  I. v1 l" y& ]5 P! M3 W
  • constructor 修改构造函数以复制从控制器传来的变量。使用 dojo/_base/lang/mixin,它将匹配变量名称,并将值复制到您的自定义小部件变量中(清单 2)。
    , y, w! p* u4 L. [6 F+ w% x# F/ r! X4 t) ~  ?8 d+ g
    ; x" J8 X1 d& ]6 l
    清单 2. 构造函数
  • constructor: function (args){
      Y# _0 A* ?! K        if(args){
    . z( ^' M- t- B0 b) L                lang.mixin(this,args);3 J2 n+ f" n- @" ?2 c! h1 p* h8 I/ r
            }
    . J) f) P7 M+ C5 m9 K}
    5 ]5 @, A: G& {+ w
  • postCreate 所有日期都将以具有 en-us 短格式 mm/dd/yyyy 的字符串形式传递。使用 dojo/date/locale 函数将用于 selectedDate、bookingWindowMaxDate、bookingWindowMinDate 的所有日期字符串转换为日期对象(清单 3)。
    7 e" Y3 g& k2 l% K, B" B1 j: h* h( ?/ M9 ~& P: {
    , l* U& O* w$ v1 q9 T$ j, Y
    清单 3. 使用 dojo/date/locale
  • this.bookingWindowMinDate = locale.parse(this.bookingWindowMinDate, {formatLength:+ e& w. n8 g2 p2 a
    'short', selector:'date', locale:'en-us'});

    $ V, H, b% p* C/ `$ P! p! c
    创建日历对象的一个实例(清单 4)。创建的逻辑在 createCalendar 函数中。以编程方式创建一个 dijit 日历的实例,将它附加到您将使用 dojo/dom-construct(等效于老版 dojo 中的 dojo.create)创建的一个 div 上。一般来讲这是一种很好的做法,因为它允许您销毁日历而不丢失附加点。3 y6 |6 L( v2 l, M' q0 e* D( l

    2 }4 U" e3 e' m% ]7 J- D
    * o$ i0 L9 A3 t' y% y0 N2 `8 L清单 4. 返回 dijit/Calendar 的一个实例
  • return new Calendar({1 U6 n5 A+ Z, [9 s6 F! s8 P+ z
            value : selectedDate,
    9 E# \2 @0 n' r0 N) [* L, }' e) n1 J) x) b        currentFocus : selectedDate        },  domConstruct.create("div", {},
    5 z) R' T7 |0 H# [( O9 A        calendarAttachPoint));
      F9 _* ^0 Q' i/ f: A: }}

    ' T5 m5 |, i! Z
    请注意,您在Calendar dijit 中设置了 currentFocus 值。Calendar dijit 将始终使用您本地的当前日期来显示其第一个着屏 (landing screen),所以,如果希望日历显示不同的屏幕(日期),则必须设置 currentFocus。因此,对于自定义小部件,您需要将日历的初始值和 currentFocus 设置为 selectedDate(根据需要进行设置)。对于此示例,这个日期为 2012 年 8 月中的一天。( j9 }% L, p0 O3 n
要满足其他需求,您需要修改 Calendar dijit 中的以下 3 个函数:& g6 k& ~0 B. M7 s+ B
  • isDisabledDate 当 calendar dijit 加载一个视图时,它会逐个迭代当前视图中的日期(所有 42 个日期),并为每一天调用 isDisabledDate 和 getClassForDate(接下来将介绍)函数。. [5 ~" z* c" l5 ?) V$ A
    isDisabledDate 函数用于禁用日历中的某些日期(清单 5)。如果函数返回 true,那么将会禁用该日期。每次日历刷新时,都会调用此函数,并且会将日历中的每一天的日期传送给它。对于自定义小部件,您需要:
    7 y7 E  [1 t  A4 ]
    • 禁用不属于当月的任何日期:为此,需要使用 dojo/date/difference 函数,该函数基于某个间隔来对比两个日期对象,如果两个日期相等,则返回 0。您将使用月份间隔对比 currentFocusDate 变量与当前视图中的每个日期,如果它们不相等,则返回 true,以禁用该日期。
    • 禁用边界日期外部的日期:再次使用 dojo/date/difference,但将间隔设置为 “day”。如果返回值小于 bookingWindowMinDate 或大于 bookingWindowMaxDate,则返回 true,以禁用该日期。 3 }3 E7 J, s! Z2 j; q

      " Q0 }; [9 g; J# l  p4 \清单 5. 修改 isDisabledDate
    •                                                                 ' {! A: i, o# G6 M0 |7 c$ v
      isDisabledDate: function(date) {5 e# z5 P5 C+ Y- j, f
      //disable any day that doesn't belong to current month  M( ~% X% I) ^: X6 c0 `
              if(dojoDate.difference(parent.currentFocusDate, date, "month")!==0){5 M# v# j8 q8 v3 `; I+ l. C5 h$ z3 \6 ^
                      return true;
      . h2 _' j2 Z- x2 W- e, Y        }5 }1 z. P8 ?$ J; N) v
              if(dojoDate.difference(parent.bookingWindowMinDate, date, "day" ||
      / n8 ^2 t  h5 b/ u- d' `. @1 o6 }dojoDate.difference(parent.bookingWindowMaxDate, date, "day")<0){' _+ E5 e% C' |6 l1 _
                      return true;
      , t* x. s5 v0 O# r$ U, Q        }
      , ]; }7 Z. [& N. m8 k7 C        else {9 Q+ l# t+ H: r  \9 T( a
                      return false;
      4 Q& h/ O4 K8 e  g+ i3 n        }' X; V# f1 `% h  R1 w1 f
      }
      ' x0 Y- j1 Z$ @  W. O1 p

      + n: n; Z# f! ]- t5 u
  • getClassForDate 尽管您使用 isDisabledDate 禁用了不属于当月视图的日期,但还需要隐藏它们。可以使用 getClassForDate 函数返回一个 CSS 类名,在日历上以不同形式标记该日期。对于自定义小部件,需要突出显示 selectedDate,向该日期添加一个具有黑色边界的蓝色框(清单 6)。您还需要使用灰色突出显示在最小和最大日期边界之外的日期,隐藏不属于当月的日期。" ^' t7 B0 R2 a& ?
    要识别需要设置不同样式的日期,可以使用 dojo/date/compare,它将接受两个日期值(日期对象)和天数(字符串),如果相等,则返回 0。这里,您将传递 currentFocusDate、迭代中的日期和表示天数的日期,因为您仅对对比日期感兴趣,所以无需关注时间戳。如果此对比返回 0,那么该函数将返回类 “Available”,这个类是在 CSS 文件中定义的(清单 7)。您将使用 CSS .class 选择权来定位我们希望更改的特定元素。# S0 c& K1 r3 Q  k5 o$ @8 g" h
    1 i! Q" A# y1 i% K& U4 H" f& j
    ' n/ I. J2 |# K3 V9 x7 w
    清单 6. 修改 getClassForDate
  • getClassForDate: function(date) {        
    # _9 q& k7 `7 }3 I7 L  s% ~        if ( dojoDate.compare(date,selectedDate,"date") === 0) {
    - k: U$ G- G+ A                return "Available";/ {* [- o  s7 D
            } // apply special style
    0 q3 k+ k6 x" ]! k- k, p3 M}
    % @% p% v8 H& Z- Q7 C$ z
    + Y9 l0 z( q/ m. C8 ]9 I
    清单 7. 标记可用日期的 CSS 类
  • .AvailabilityCalendars .Calendars .CalendarDijit .Available
    2 O) W) G; T/ k4 t2 }        .dijitCalendarDateLabel0 Y, Y' I/ T0 O0 S
    {
    ! t- d( c; Q3 b# n        background-color: #bccedc !important;8 N8 Y; G/ |: C6 d7 j
            border: 1px solid #000000 !important;9 K; W( U! N- K' ]
    }

    1 M. f4 y6 K' Q6 h$ `
    您将使用来自 isDisabledDate 的相同的 if 条件来识别超出边界的日期和不属于当月的日期,但会返回 CSS 类名(清单 8 和清单 9)。: ]  ]6 }' b$ c
    8 ?) J0 z. |, \

    & J9 s$ N9 U6 h3 e清单 8. 隐藏和禁用日期
  • if(dojoDate.difference(parent.currentFocusDate, date, "month")!==0){ ; p, r- m6 S. m* W
            return "HiddenDay";. _7 t+ @, ?$ @: I+ Q* x9 z
    }8 @. D( K8 c. M
    if(dojoDate.difference(parent.bookingWindowMinDate, date, "day")<0 || $ T8 ~4 `7 C3 H
            dojoDate.difference(parent.bookingWindowMaxDate, date, "day")>0){
    8 C2 t8 T$ a; w. [) I/ a        return "Disabled";
    5 F) w: k+ x! S}

    8 B! S( m; s3 i; f$ @! ^% x/ }: \
    # S0 b+ u+ a' C+ t
    - l# I$ ^8 }( B' j8 F
    清单 9. 标记隐藏和禁用的日期的 CSS 类
  • .AvailabilityCalendars .Calendars .CalendarDijit .HiddenDay
    - t0 G4 `3 Z- R. R  \# C7 L" \        .dijitCalendarDateLabel( w5 k- Y1 z4 l# h
    {
    0 Y* ?6 p: s& g0 }7 _" G4 I    background-color: #ffffff !important;
    / w% }6 ?/ r) H; w0 z    border-color: #ffffff;% \) o' V" b# g" X( x2 a' H
        color: #ffffff;
    5 w( U4 s- b3 K7 Y: f( U( E* ?}
    6 |/ ]' D& ~) ^- g0 }- N2 C. y$ W. H3 \0 |4 |- |" Q! K) S
    .AvailabilityCalendars .Calendars .CalendarDijit .Disabled 2 a5 C" X6 h) B  L+ k
            .dijitCalendarDateLabel+ P5 g: `; W4 G( Y6 ^7 b
    {( o) t* D5 Q5 m+ y
            background-color: #9c9c9c;; q6 a) \' y+ m3 E
    }
    ; j5 h. w8 ]4 Z" ?
  • onChange 此函数仅在为日历设置一个新值或在日历上选择一个启用值时调用(清单 10)。此函数返回所选日期的一个日期对象。您可以使用该对象将日期发布到另一个将处理该日期的方法。调用您的自定义小部件中定义的一个函数 (onValueSelected),在发布到控制器之前,您可以在其中执行任何需要的处理(清单 11)。在本示例中,您将使用 dojo/_base/connect/publish 将日期发布到控制器。频道(或主题)字符串存储在变量 onValueSelectedPublishIDString 中。
    " `, \  H: T7 r- D7 b. t% k- W( d+ n1 L2 y

      u. n& ~8 M$ y. J' ^+ a7 f2 I6 m清单 10. 使用 Calendar 的 onChange 和 hitch
  • onChange : lang.hitch(this, function(date){! ]4 P' ~$ y$ F$ B# q+ w: X3 j
            this.onValueSelected(date);0 ]9 l4 o! m- I/ ?
    })
      o  d7 q: E' \3 r" n
      a5 G. s, k4 L
    清单 11. 使用 publish
  •                                                 
    ! X8 Q! J: ]2 }; d, s  DonValueSelected : function (date){2 S+ [  s- ]6 m7 G* V
            connect.publish(this.onValueSelectedPublishIDString, [date]);
    . `( l/ T9 D- D8 W}
    9 y; z5 ^' `- q& s5 O  R* @
    请注意,您使用了 dojo/_base/lang/hitch 来提供调用函数 onValueSelected 的范围(清单 10)。您的控制器(在此场景中为 index.html)将提供一个订阅该频道的订户来处理日期(清单 12)。在此示例中,您仅记录它。可将此替换为任何其他需要的逻辑。+ T6 `- P& J/ D; }

    6 u" a" I. @1 b% h( A
    4 M  h' D5 {( j* ^) u) Z$ s, B6 s清单 12. 我们的发布的订户
  • connect.subscribe("selectedValueID", function(date){
      E& U3 N: n3 E5 H/ g' [% x  //Do some processing + a! z( L6 z) a& t, s* j
      console.log("New Selected Date: ", date);5 u9 J" k  P) j% c# P) Y8 _
    });
    . ?; j. F* L# V- j, ?4 k1 i
    " U. ?8 n+ e' y: F* |) G0 j
Calendar dijit 在页眉中附带了一个 monthDropDownButton。这个按钮显示了所有月份的列表,允许用户跳到任何月份。为了满足需求,您需要将 monthWidget 设置为 “disabled” 来禁用此按钮(清单 13)。& s4 X) ^, E7 s( ~' J; V
: P" g9 q( ^% A+ v) }" H" S
清单 13. 禁用 Calendar 页眉中的下拉按钮, J& U% f& Q1 b: o8 x$ V" I
this.calendarInstance.monthWidget.set("disabled", true);

$ |$ T# A) R0 E7 w从实用性角度讲,您还需要隐藏箭头,使用户不会受到吸引而去单击它。为此,请添加定位您希望操作的元素的 CSS 类(清单 14)。
- P% D4 |* ^8 u/ c0 x* w( }% K# Q, y
7 R. V2 g% x. G( K7 ]% P7 {清单 14. 隐藏下拉按钮箭头的 CSS 类  F, `, o' o. R+ A
.AvailabilityCalendars .Calendars .CalendarDijit .dijitDropDownButton 9 x9 W1 }' K  B1 [5 u& H, h
        .dijitArrowButtonInner
" E- ~0 I3 h, ]{+ A, Q1 N. }) a) a
    visibility: hidden;
. F+ x" @4 ~$ t. M}

' D, }! g8 y$ _7 \5 h9 G7 Z- u接下来,使用 CSS 类隐藏去年和明年的 digit,禁止将它显示在底部(清单 15)。' m, `2 B, Y8 N# Y; v( E; q
6 `% }0 ?+ f+ [
清单 15. 在 Calendar 底部隐藏年份 digit 的 CSS 类
- t5 B* E- X" R
.AvailabilityCalendars .Calendars .CalendarDijit .dijitCalendarPreviousYear,
2 E" @! P# w8 p# y        .dijitCalendarNextYear
% Z5 ^" R2 l: B  v% Q* C) e7 Z    {, V$ l3 ^3 v  I( i2 _, Y2 Z5 q
padding: 1px 6px;
3 q  ~) R0 D6 T* l" ~8 Z; N) \- pvisibility: hidden;
8 {5 P% X2 `; J  R: c5 i, U    }

# G2 I) ?1 _+ \& h, _% w$ B您还将隐藏顶部的箭头,否则这些箭头允许用户逐月移动(清单 16)。9 Y9 E, K& _. W. Y$ F2 W

. t* ?& e+ e5 B; X3 g5 R* o9 e7 T清单 16. 隐藏 Calendar 顶部的月份箭头的 CSS 类
+ H9 O% H! P8 H3 k) ~
.AvailabilityCalendars .Calendars .CalendarDijit .dijitCalendarArrow
) ?; L$ a* g  Y. {) W9 J{1 v( y* X6 A4 t' J8 l
     visibility: hidden;
( c5 N" W6 j( D/ g; Y) q% K/ O}
+ `0 v6 i6 }- H- i2 G$ a8 I
接下来,创建两个新按钮,以便允许用户导航月份。以编程方式使用 dijit/form/Button 创建这两个按钮。对于第一个按钮(后退),可以将标签设置为 “<<” 并修改 onClick 函数(清单 17)。onClick 的逻辑将包含在 goToPreviousMonth 函数中。
7 _( N! R0 j5 q7 [* u4 P* R
+ {5 A/ c5 r( D" X清单 17. 创建 dijit/form/bottom 的一个实例0 O) g4 j1 Z3 E6 K- x
this.calendarPreviousMonthButton = new Button({
* ^% v, E( H  c5 {; B       label: "<<",        
4 |) {* n1 h! r8 q+ G       onClick: lang.hitch(this, function(){8 m  o7 K6 ^% q4 w
               this.goToPreviousMonth(this.calendarInstance);0 |. Z: Q1 N  f' `& r  z& k
       })+ O9 {4 {* u3 ]( d1 u% u
}, this.calendarPreviousMonthButtonAP);
7 J& ], Q% l, A: P" P
您希望在用户每次单击该按钮时,日历后退一个月。在 goToPreviousMonth 中,需要先将 currentFocusDate 更改为 currentFocusDate - 1 month,然后刷新日历的视图。最后,必须检查这是否要显示的最后一个月,如果是,则禁用该按钮。
# a, D, k1 T) G. ?$ a使用 dojo/date/add 函数,它接受日期对象、间隔(字符串)和数量(整数)。对于您的情形,日期应该是 currentFocusDate 对象,间隔是 “month”,数量是 -1(清单 18)。
6 b0 r# X. o/ x! K4 k
0 \! p1 c( R) n: ^" Y/ z清单 18. 日历视图减去一个月) U! k' |# {( d1 @& J7 I
this.currentFocusDate = dojoDate.add(this.currentFocusDate,"month",-1);
2 A* U& I7 I6 x. A9 j. n8 @calendarInstance.set("currentFocus",this.currentFocusDate);

6 @8 B5 |, B; p7 m! M7 f+ Y* X+ I设置日历的新视图,将 currentFocus 设置为新的日期值。(这将自动刷新日历并显示新视图)。
5 d0 f; u5 y% y( C4 R* H0 W7 R最后,请检查这是否是最后一个月的视图,方法是对比 currentFocusDate 与最小值边界;如果是最后一个月,则禁用后退按钮。另外,请检查您是否应启用了前进按钮(假如您禁用了该按钮,并且现在您离开了最大值边界)(清单 19)。
$ Z  v$ ~' |& {/ ^7 N7 s( k% c
/ h$ z& O/ C" c; k- z9 K; e清单 19. 检查我们是否应该禁用新导航按钮
+ Q: }4 @: M( y0 X/ Z# t; P6 O
if(this.isLastCalendarMonth(this.bookingWindowMinDate, this.currentFocusDate)){
5 i. s1 [/ ~+ |4 N$ s6 [        this.calendarPreviousMonthButton.set("disabled", true);4 c# X) f" |( y1 T8 s
}, e; K8 d8 |1 V# U/ Q+ j7 s
if(!this.isLastCalendarMonth(this.bookingWindowMaxDate, this.currentFocusDate)){4 o' ?# R6 b7 W4 R1 _
        this.calendarFollowingMonthButton.set("disabled", false);
- r. b' p, w" ?0 U8 T}
4 {2 \3 @( T- k+ `6 M0 h+ E; e
第二个按钮的工作原理相同。该标签将为 “>>”,onClick 调用 goToNextMonth,后者使用了同一个函数,但您添加了一个月(清单 20)。  ]# p2 [" P2 ^. a6 ]; z( @! `# d
( O3 |9 D3 f$ ]# Q% s/ ~8 l
清单 20. 控制移动到下一个月的按钮的函数2 X) q+ \1 k, S6 |; I- U0 f% T5 o
goToNextMonth : function (calendarInstance){3 M4 n5 C  Y. P( {
        this.currentFocusDate = dojoDate.add(this.currentFocusDate,"month",1);
4 v, ^( H. M7 L- p- N        calendarInstance.set("currentFocus",this.currentFocusDate);
; \, `4 `& G+ j! v        if(this.isLastCalendarMonth(this.bookingWindowMaxDate, this.currentFocusDate)){
/ \( Y2 R/ O8 _7 Q- w* w                this.calendarFollowingMonthButton.set("disabled", true);
; m% Z  H, n9 O1 P        }        " E  t2 `2 y7 ?& p4 Q, x
        if(!this.isLastCalendarMonth(this.bookingWindowMinDate, this.currentFocusDate)){6 {8 b  t! j. ?3 j! A! @! f& n$ }+ W
                this.calendarPreviousMonthButton.set("disabled", false);% g4 ?: B7 E: r9 N8 R
        }, B: v: ^* G8 ^5 R
}
' @8 }; u2 W2 q: T  E! b/ H( o8 X5 Z
最后,清单 21 显示了应该在控制器类中的内容的示例,该类将进行相关调用,以便初始化您的新 customCalendar。+ Q4 D, A- V' p9 ]5 q7 v! `
7 ^2 y5 l! M* v( K8 W+ X  C
清单 21. 创建新的自定义日历小部件的实例的快照
7 T2 c' C; f3 N
require(["myUtil/customCalendar","dojo/_base/connect"], function(myCalendar, connect){, m" x8 y# M" J% Z: s) u: T
        var params = {+ D! Z' @" w2 O2 i1 n' Z+ Z, Y
                "bookingWindowMinDate":"10/9/2011",
' t8 @9 P5 M5 Z* M8 M                "bookingWindowMaxDate":"10/9/2012",
6 ~, K- a" I) x! F! ^0 s7 W7 \                "selectedDate":"8/15/2012",
" a/ ]9 @, l( R( x                "onValueSelectedPublishIDString":"selectedValueID"$ m8 Q# G, A! [* L
        };8 b2 Q2 o" _- }) \+ l9 _
        var myTest = myCalendar(params);9 z7 J' S, c8 [. S2 U* v; M
        myTest.placeAt("nodeId", "last");0 `( V5 m$ C1 t$ R) c$ T
                9 ?* j7 i  X  h1 l. W, Y) c8 |3 N
        connect.subscribe("selectedValueID", function(date){
* b9 P* {! a8 Q  s0 r          //Do some processing 0 E' |7 g1 @0 r2 w# r5 |
          console.log("I got: ", date);
8 F( l. {! k- N; N        });        
. ?8 ~" R$ L8 C0 l- [        
; k* C1 M" h+ L9 t6 E6 a3 m});

* v( k( B9 [. P: i+ Y) C如您所见,您创建了一个对象 params,其中包含需要传递给自定义日历小部件的值,并订阅了该频道。% v: J% i9 r2 m1 f* M: c* G. `  ?6 U
更多函数
您可能会发现其他一些函数和属性在此场景中也很有用:1 Z6 s1 }* z$ \7 T: F  n, G
  • 当将一个日期对象和区域传递到 dojo/date/locale/isWeekend 时,如果日期是周末(对于 en-us 区域,是星期六和星期日),则会返回 true。如果需要,可以使用该属性来禁用周末日期或为周末设置不同的样式。
  • Calendar dijit 还包含一个 dayWidth 属性,该属性接受一个字符串作为值。默认情况下,会将它设置为 “narrow”,这缩短了显示的日历日期表示,例如使用 “M” 表示星期一。其他值包括表示完整日期名称显示的 “wide” 和表示缩写词的 “abbr”(比如 “Mon”)。3 h: T0 _  h3 A+ {2 ~
这些自定义小部件需求的一种变体可能要求小部件显示多个日历,然后,在用户通过单击来查看下一个月时,要求两个日历都前进一个月(参见图 3)。这很容易完成,只需更改小部件变量来支持一个数组,而不是单个值变量。: i, W. [  T0 A; w7 r
8 I5 `& f% ?6 T& N* b! q
图 3. 每个视图多个日历9 x4 _# _" c- J
2 |' V6 P  P! i5 r1 J8 y3 h, V


; g& z- Q! O1 y
4 x5 g$ V1 u/ j% _
结束语
通过组合 JavaScript 和 CSS 修改,很容易创建一个自定义小部件来更好地满足项目需求。本文演示了这种做法,使用 Dojo 1.7 声明了一个类,该类扩展了 Calendar dijit 并利用了一些 dojo 功能,比如日期操作、hitch、发布和订阅,以及其他一些基础 dojo 函数。希望您将能够应用这些步骤来扩展 Dojo dijit,并创建自己的新小部件。
/ L; g; p/ r. X3 ^( {: k, m% e/ V" P# x

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
 楼主| 发表于 2013-2-19 10:43:23 | 显示全部楼层
本帖最后由 技术狂人 于 2013-2-19 10:44 编辑 # k+ a( w, o1 A

) L* D6 n- A4 d
下载
描述名字大小; C5 x& F3 S* ^
样例应用程序4 KB' [6 O9 _+ e! \; Y" }9 g& {

7 Z5 K- S# \- k6 M2 X5 O9 g
& q1 g& S1 i1 k  [( O5 {0 l3 c原文地址:http://www.ibm.com/developerwork ... er/1209_weller.html

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

SCMLife推荐上一条 /4 下一条

QQ|小黑屋|手机版|无图版|SCMLife.com ( 京ICP备06056490号-1 )

GMT+8, 2018-12-11 22:49 , Processed in 0.105084 second(s), 7 queries , Gzip On, MemCache On.

Powered by SCMLife X3.4 Licensed

© 2001-2017 JoyShare.

快速回复 返回顶部 返回列表