SCMLife.com

 找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 3549|回复: 1

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

[复制链接]
发表于 2013-2-19 09:52:41 | 显示全部楼层 |阅读模式
本帖最后由 技术狂人 于 2013-2-19 10:40 编辑 4 \" g, k$ }6 \
' }: J2 s& b+ n7 P9 ]5 A
简介
Dojo Toolkit 是一个强大的 JavaScript™ 库,支持 Web 开发人员使用面向对象的小部件,用最少的开发时间和工作量来创建富 Internet 应用程序。Dojo Toolkit 提供了 4 个包,它们分别是 Dojo(核心)、Dijit(UI 框架)、dojox(dojo 扩展)和 util。您可以原封不动地使用该工具包提供的功能,也可扩展它们并创建自己的小部件。提供的功能包括 DOM 操作、使用 AJAX 开发、事件、数据存储等。+ @  k9 ]' b2 Y" W: `8 P- \
Dijit(dojo 小部件)包是 dojo 自己的 UI 库,它包含一组 dojo 类,使开发人员能够以最少的工作创建功能丰富且强大的跨平台 Web 2.0 接口。这些 Dijit 小部件(或 dijit)支持一些易于操作的主题。这个包中的 dijit 示例包括按钮、文本字段、编辑器、进度条等。$ {$ R5 ?& V4 S4 M. M" M
举例而言,您可以使用这些 dijit 创建一个提交表单,其中包含用于名称、电子邮件地址和电话号码的文本字段,以及日期字段、复选框、按钮和验证,所有这些在几分钟即可完成,需要的 JavaScript 知识也极少。
" c9 a" b) F  e- E) I提供的一个功能最丰富的 dijit 是 Calendar dijit,它支持在一个月的上下文中显示日历。用户可轻松地逐月、逐年导航,或者跳到同一年中任一个月,以选择特定的日期。
. h6 d# O' D7 i: [在开发富 Internet 应用程序 (RIA) 时,通常可以原封不动地使用 dijit。但是,有时您可能需要使用不同的样式(比如更改颜色或主题),或者需要进行更复杂的更改,其中可能需要结合使用某些功能、模板和样式更改。要满足这些需求,则需要从头创建一个新的自定义小部件,也可以创建一个扩展现有 dijit 的自定义小部件。+ w7 D7 G9 Q: N4 S3 ?
本文提供了一个练习,在这个练习中,您需要在自己的网站上使用 Calendar 小部件的不同变体。为了满足此需求,您需要创建一个新类。此练习使用了 Dojo version 1.7,提供了探索 Calendar dijit 的机会和以极少的改动重用现有 dijit 来节省开发时间的方式。您还会看到在 Dojo 1.7 中声明的一个新类的实用示例,探索一些 Dojo 基础功能,比如数据操作、hitch、发布和订阅等。
* F  t: y. i' C( d
问题
在此练习中,您将使用 Calendar dijit 的一个具有以下需求的自定义版本:
! _* ]; `; \: B
  • 日历应仅显示当月的日期(隐藏和禁用不属于当月的日期)。
  • 日历应仅在底部显示当前年份(没有去年或明年)。
  • 日历应在日历小部件底部显示当月的名称。
  • 用户无法跳到任何其他月份(禁用顶部的月份下拉按钮)。
  • 提取日历顶部显示的用于逐月移动(向后或向前)的箭头,将日历旁边的箭头显示为 dijit 按钮。这两个新按钮是用户更改月份的惟一方式。
  • 具有最小和最大边界日期,这意味着所有在此边界外的日期都应该是禁用和不可访问的。
  • 在到达边界日期时,禁用相应的月份导航按钮。
  • 向日历中选定的日期添加特殊的样式。
  • 当用户选择某个日期时,将该日期传递给一个将处理新选择的值的函数。
    9 U- L! C. s2 j/ I& ^. a/ w
解决方法是创建一个自定义小部件,这个小部件通过使用 JavaScript 和 CSS 编辑 Calendar dijit 来开发。图 1 显示了应用上面需求之前(左侧)和之后(右侧)的 Calendar 小部件。
$ Q4 o' C, G! i; Q* ^6 A; \4 \
6 T3 |! V4 J! p* B图 1. 标准 Calendar dijit 与自定义 Calendar 小部件的对比
: Y8 l/ f/ p/ Y5 h
- g7 b, k# t; D+ V为此,您将需要创建 3 个文件:6 S$ X0 K" D" f8 V! n: ~: D
  • Dijit 模板:一个将显示自定义小部件的组件的标记文件。
  • Dijit 类:一个使用声明 (JavaScript) 创建的小部件类。
  • CSS 文件:包含所有必要的样式表类。
    2 s$ t* p) H' t+ z1 Z8 _7 `
图 2 显示了自定义小部件的文件结构和位置。您的起点是 index.html,它在本示例中充当了小部件的控制器。simple.css 文件将包含所有样式。! h' a* c. I: Z$ |1 d' E6 |3 F

2 O- {& k! o9 j+ \8 U图 2. 文件结构
7 a9 N0 ], W7 N* a( _' l
4 T0 y- q# w* G6 M
& A+ S# S7 f$ D: r* A
+ y' _% Q/ {! E/ W+ X$ Z
创建小部件
dijit 模板
创建 3 个 JavaScript div 元素:一个用于日历,两个用于向前和向后逐月导航的箭头按钮(清单 1)。这些 div 将使用附加点 (data-dojo-attach-point) 进行引用。使用附加点比使用 id 更好,因为它使您能够在同一个页面上拥有同一个小部件的多个实例,无需担忧 id 冲突。
) U) ^( ~1 h* ^; `
/ \2 v& S8 X( Z: t2 I6 a/ E清单 1. dijit 模板
) s& T, L5 Z. G/ {3 S
<div class="CalendarArrow">
/ q3 X; ?. _. t- B5 I<div data-dojo-attach-point="calendarPreviousMonthButtonAP"></div>
& \) t- R; `, j3 m$ H% |</div>% D& a3 [( T% A9 z( }- |
3 a* b5 Q2 F( p6 n
<div class="CalendarDijit">
' v6 I; D; k5 \  ?- G3 M3 ]1 d<span data-dojo-attach-point="calendarMonthOneAttachPoint"></span>
2 \- D4 }8 J- B9 H' ~</div>. T0 G6 `1 S- [/ T; o! J, a

( @( Q) K! }) h1 g<div class="CalendarArrow">+ ?$ }0 r8 n$ O" h+ [
<div data-dojo-attach-point="calendarFollowingMonthButtonAP"></div>
$ B& t2 `- k1 o! f8 s( a& j</div>
; t7 _. J6 `2 l: t
dijit 类
根据应用程序需求,您需要定义以下变量:
- M  J7 N$ ^) c0 J+ o$ S9 W+ b
  • selectedDate:日历的初始值。
  • currentFocusDate:一个值,日历会引用该值来了解要显示的月份;该值最初被设置为等于 selectedDate。
  • calendarInstance:Dijit 日历实例。
  • bookingWindowMaxDate:日历中允许的最晚的日期。
  • bookingWindowMinDate:日历中允许的最早的日期。
  • onValueSelectedPublishIDString:表示发布/订阅频道(或主题)的字符串。* F% p. b7 q+ `' g% a- f: i
JavaScript 函数
首先修改以下样式表元素:8 s2 z" T( n) N- T0 d7 Y2 I7 h
  • constructor 修改构造函数以复制从控制器传来的变量。使用 dojo/_base/lang/mixin,它将匹配变量名称,并将值复制到您的自定义小部件变量中(清单 2)。' }$ O2 M4 D* U# x* F$ K$ H
    ( ^1 P3 U5 s5 b& j0 V$ v3 |/ k

    " W1 o7 T0 y6 _/ m- H清单 2. 构造函数
  • constructor: function (args){$ G9 z$ _  g. l2 d+ L7 ~, f
            if(args){
    + J! d9 r. _. r) k4 B! a7 B9 v: K- g                lang.mixin(this,args);$ U5 o" \& U9 f. N
            }* w( D/ o8 Z- R! Z
    }

      _$ f$ }" j0 q
  • postCreate 所有日期都将以具有 en-us 短格式 mm/dd/yyyy 的字符串形式传递。使用 dojo/date/locale 函数将用于 selectedDate、bookingWindowMaxDate、bookingWindowMinDate 的所有日期字符串转换为日期对象(清单 3)。# \3 c; y  X7 V  r, D

    - f! G' O) g4 e& \8 t4 u
    8 M& d7 |& x3 R: A; @3 A清单 3. 使用 dojo/date/locale
  • this.bookingWindowMinDate = locale.parse(this.bookingWindowMinDate, {formatLength:
    $ d3 m- M# Q# Z0 M'short', selector:'date', locale:'en-us'});
    * y' n  C, y) P/ e  m
    创建日历对象的一个实例(清单 4)。创建的逻辑在 createCalendar 函数中。以编程方式创建一个 dijit 日历的实例,将它附加到您将使用 dojo/dom-construct(等效于老版 dojo 中的 dojo.create)创建的一个 div 上。一般来讲这是一种很好的做法,因为它允许您销毁日历而不丢失附加点。0 G' ^! R' G& \" G  H
    " R. e" r% [; R# |

    " E8 U6 X4 E# M, g清单 4. 返回 dijit/Calendar 的一个实例
  • return new Calendar({% Q' I7 t9 ^# \4 G& o
            value : selectedDate,
    . }8 |- m& N. h; c) q        currentFocus : selectedDate        },  domConstruct.create("div", {},
    , ]* S( y+ c, _        calendarAttachPoint));6 L( D4 r. N, R) t$ N3 k
    }

    ) o0 i  t" S. b: _
    请注意,您在Calendar dijit 中设置了 currentFocus 值。Calendar dijit 将始终使用您本地的当前日期来显示其第一个着屏 (landing screen),所以,如果希望日历显示不同的屏幕(日期),则必须设置 currentFocus。因此,对于自定义小部件,您需要将日历的初始值和 currentFocus 设置为 selectedDate(根据需要进行设置)。对于此示例,这个日期为 2012 年 8 月中的一天。- Q/ z# H9 t. Y9 M5 A
要满足其他需求,您需要修改 Calendar dijit 中的以下 3 个函数:
- t% ^2 ^3 E# B  {! S
  • isDisabledDate 当 calendar dijit 加载一个视图时,它会逐个迭代当前视图中的日期(所有 42 个日期),并为每一天调用 isDisabledDate 和 getClassForDate(接下来将介绍)函数。
      W; C" T: [5 F+ a/ N( q" IisDisabledDate 函数用于禁用日历中的某些日期(清单 5)。如果函数返回 true,那么将会禁用该日期。每次日历刷新时,都会调用此函数,并且会将日历中的每一天的日期传送给它。对于自定义小部件,您需要:
    " ~1 a  c- z8 ^9 i7 U4 I1 x
    • 禁用不属于当月的任何日期:为此,需要使用 dojo/date/difference 函数,该函数基于某个间隔来对比两个日期对象,如果两个日期相等,则返回 0。您将使用月份间隔对比 currentFocusDate 变量与当前视图中的每个日期,如果它们不相等,则返回 true,以禁用该日期。
    • 禁用边界日期外部的日期:再次使用 dojo/date/difference,但将间隔设置为 “day”。如果返回值小于 bookingWindowMinDate 或大于 bookingWindowMaxDate,则返回 true,以禁用该日期。
      9 w- W/ j! u+ v+ I# }4 I
      ; Z' f- Q% E1 T( A' Z- d清单 5. 修改 isDisabledDate
    •                                                                 9 p; `; }1 d! f6 W, o
      isDisabledDate: function(date) {
      2 h1 i5 C# l) Y& e* _ //disable any day that doesn't belong to current month+ Z0 f7 C6 \! L# \5 e) S
              if(dojoDate.difference(parent.currentFocusDate, date, "month")!==0){
      ; R- ^. e" t6 s* P/ D- p6 |                return true;
      + u$ T4 @4 i3 y, G7 G* Q        }& G. H4 y! x* }# n8 h
              if(dojoDate.difference(parent.bookingWindowMinDate, date, "day" ||
      + _' O4 i6 d$ |# h  ~$ ^dojoDate.difference(parent.bookingWindowMaxDate, date, "day")<0){/ V  t% t. Q0 s: L. P
                      return true;+ t. _) W6 }1 I' `4 ~
              }
      1 c. G0 h/ [$ P+ F  `        else {0 L6 o8 m( L% w) D7 x+ g
                      return false;5 \1 C  V- U5 A1 c% w( `
              }. D% z& c: e/ p' V6 p
      }
      1 w7 z7 I: C; I1 x' i

      ) p4 w) _( O0 A* }
  • getClassForDate 尽管您使用 isDisabledDate 禁用了不属于当月视图的日期,但还需要隐藏它们。可以使用 getClassForDate 函数返回一个 CSS 类名,在日历上以不同形式标记该日期。对于自定义小部件,需要突出显示 selectedDate,向该日期添加一个具有黑色边界的蓝色框(清单 6)。您还需要使用灰色突出显示在最小和最大日期边界之外的日期,隐藏不属于当月的日期。9 ]+ E) f4 y  W7 m/ o
    要识别需要设置不同样式的日期,可以使用 dojo/date/compare,它将接受两个日期值(日期对象)和天数(字符串),如果相等,则返回 0。这里,您将传递 currentFocusDate、迭代中的日期和表示天数的日期,因为您仅对对比日期感兴趣,所以无需关注时间戳。如果此对比返回 0,那么该函数将返回类 “Available”,这个类是在 CSS 文件中定义的(清单 7)。您将使用 CSS .class 选择权来定位我们希望更改的特定元素。
    % a0 x; d- _2 J, }" K
    & f- P' ^0 o; n9 {( R  [% D/ n; P7 f3 c+ h# \0 V
    清单 6. 修改 getClassForDate
  • getClassForDate: function(date) {        
    1 r) |9 z; @  I( @0 ]9 h9 h/ N$ ?        if ( dojoDate.compare(date,selectedDate,"date") === 0) {
    * i9 i; m) ^, B1 ~  T                return "Available";0 Z: I' Y* A2 A! r: ~7 }- ?, K
            } // apply special style3 X! `/ {8 _, B: W
    }
    8 }. U8 S; G. H! M

    " y! a- q+ x" ~& J; R清单 7. 标记可用日期的 CSS 类
  • .AvailabilityCalendars .Calendars .CalendarDijit .Available . U7 t" e! G, M* N- X: @. w( _& N/ E& b
            .dijitCalendarDateLabel* @8 E! p+ _: `5 e" O) ^
    {, b0 q% e9 G# k) M! q
            background-color: #bccedc !important;8 l7 c. n! C. M' g8 Z5 B
            border: 1px solid #000000 !important;
    - h; v) v: a; Q}

    5 \  M5 Q6 P0 B( @4 [# Q, ~4 R
    您将使用来自 isDisabledDate 的相同的 if 条件来识别超出边界的日期和不属于当月的日期,但会返回 CSS 类名(清单 8 和清单 9)。
    ( a  S7 H9 B9 \
    % O- l1 Y0 n, m1 X
    3 s1 s( ~. _9 w% w" \# y. N清单 8. 隐藏和禁用日期
  • if(dojoDate.difference(parent.currentFocusDate, date, "month")!==0){
    ' k( \( U/ h8 j# U        return "HiddenDay";! s2 ~# q: L% V+ Z
    }+ M. c3 q6 f/ `& C: y& b4 r
    if(dojoDate.difference(parent.bookingWindowMinDate, date, "day")<0 ||
    # @  O3 Z6 G  p8 }# y; C- I        dojoDate.difference(parent.bookingWindowMaxDate, date, "day")>0){
    $ G* w  _2 A6 |2 Q        return "Disabled";: z( x6 g  T, a
    }

    . H$ s  X3 h& W$ Q6 z
    ) R4 ~- p' y& Y

    $ g# P: j- R/ V清单 9. 标记隐藏和禁用的日期的 CSS 类
  • .AvailabilityCalendars .Calendars .CalendarDijit .HiddenDay 0 t" N- l. l+ }2 L7 H
            .dijitCalendarDateLabel  B. a7 ^: q6 v0 {
    {) E, Y' h6 `4 W8 R& c
        background-color: #ffffff !important;
    1 C! G8 Y! Q" K" X, J# h    border-color: #ffffff;! a% y. F) n$ v- T. u( m0 h
        color: #ffffff;
    ' O( B) g/ {# @6 S}& v  R+ S  l: p8 I2 K  i* Q

    , a8 D. @7 D3 D$ c2 x* P3 P3 x  \* p .AvailabilityCalendars .Calendars .CalendarDijit .Disabled
    . X5 W# I( ~. b+ q        .dijitCalendarDateLabel
    ! T  s. G& a% Y- ^' j! \  Z3 W{
    ( ~; p- E7 a9 _' Y  W+ W        background-color: #9c9c9c;4 ?5 {& Q' l* _
    }
    4 h- B% b- }4 n% a
  • onChange 此函数仅在为日历设置一个新值或在日历上选择一个启用值时调用(清单 10)。此函数返回所选日期的一个日期对象。您可以使用该对象将日期发布到另一个将处理该日期的方法。调用您的自定义小部件中定义的一个函数 (onValueSelected),在发布到控制器之前,您可以在其中执行任何需要的处理(清单 11)。在本示例中,您将使用 dojo/_base/connect/publish 将日期发布到控制器。频道(或主题)字符串存储在变量 onValueSelectedPublishIDString 中。
    " S% k8 \) ?- ]2 S$ ~* x6 S6 }6 M6 ]* x  b! {8 w, P
    6 v7 I8 `( y- P6 I/ d/ |( d
    清单 10. 使用 Calendar 的 onChange 和 hitch
  • onChange : lang.hitch(this, function(date){1 P! B% S6 B3 c8 t6 E: P
            this.onValueSelected(date);
    ' p& q6 @3 G9 a9 B/ b7 ^7 ~})
    ' q. ~% u" {' x. D
    ! a& E# i! M( a
    清单 11. 使用 publish
  •                                                 
    8 N% d4 c% I" e3 H  T) T2 W$ h2 g6 QonValueSelected : function (date){+ z( W# E7 r* O: c1 ?- @
            connect.publish(this.onValueSelectedPublishIDString, [date]);% `/ }9 U9 Y1 J4 q3 l8 C& y
    }

    3 w3 X2 y& r# _! ^
    请注意,您使用了 dojo/_base/lang/hitch 来提供调用函数 onValueSelected 的范围(清单 10)。您的控制器(在此场景中为 index.html)将提供一个订阅该频道的订户来处理日期(清单 12)。在此示例中,您仅记录它。可将此替换为任何其他需要的逻辑。
    4 w, x5 T, v" f& B- v" e
    * E/ G  D1 X- Q8 O& g4 J$ [/ Z% \1 a* K) \' ~3 K, e1 u
    清单 12. 我们的发布的订户
  • connect.subscribe("selectedValueID", function(date){
    # g' R. v, D7 ?$ U2 R* ^2 S% [  //Do some processing 3 s. B% I6 @* f0 e
      console.log("New Selected Date: ", date);, D+ Q5 P. H% O& c; n
    });

    1 a4 y' ]/ X2 v6 g8 t3 z

    6 ]. E! I$ {5 Z  {, ?8 E8 m2 B& n
Calendar dijit 在页眉中附带了一个 monthDropDownButton。这个按钮显示了所有月份的列表,允许用户跳到任何月份。为了满足需求,您需要将 monthWidget 设置为 “disabled” 来禁用此按钮(清单 13)。
! d; N( ]! a' m
9 ]/ z; W+ F$ ]' z清单 13. 禁用 Calendar 页眉中的下拉按钮  r( @* t. J6 m! b! I
this.calendarInstance.monthWidget.set("disabled", true);
, `# X" ^8 G8 X5 ~: N: N
从实用性角度讲,您还需要隐藏箭头,使用户不会受到吸引而去单击它。为此,请添加定位您希望操作的元素的 CSS 类(清单 14)。
, R/ q4 p1 @, E: M
- Q5 _+ M9 {. E! D清单 14. 隐藏下拉按钮箭头的 CSS 类
' l# I6 o9 d3 s* e
.AvailabilityCalendars .Calendars .CalendarDijit .dijitDropDownButton . Z; M2 p$ S- x" f- o4 V) K
        .dijitArrowButtonInner
* D# r5 w' v4 V% H" K9 c7 M6 E, G{5 }6 [7 f* }( k
    visibility: hidden;
  l1 y! A( t! n4 e' E}

0 ?9 E- f' t# q接下来,使用 CSS 类隐藏去年和明年的 digit,禁止将它显示在底部(清单 15)。
: m# F: a' P0 M7 J6 i6 m- r& I' Z% C
清单 15. 在 Calendar 底部隐藏年份 digit 的 CSS 类! A; z' B; O( G8 ]+ e+ M- w# F
.AvailabilityCalendars .Calendars .CalendarDijit .dijitCalendarPreviousYear, / j) N' i3 B! y: A
        .dijitCalendarNextYear- R9 x* G/ e" Q# D
    {0 e7 M2 q5 U3 _
padding: 1px 6px;
- u% d3 ?3 G+ C0 h  \+ dvisibility: hidden;
# u% ~$ _* l! d4 L) i- b; @5 t/ O% U7 _    }

9 Y4 l' L% i+ d  `( z. T, P您还将隐藏顶部的箭头,否则这些箭头允许用户逐月移动(清单 16)。5 ]! y, P3 P* `' ?6 x) t+ Q. F

8 [% o. v$ \1 X& }  ?清单 16. 隐藏 Calendar 顶部的月份箭头的 CSS 类9 C8 H% W, u+ |: J* M$ v+ k. n
.AvailabilityCalendars .Calendars .CalendarDijit .dijitCalendarArrow
' q' }6 g; m8 u, ^2 v{2 i/ x! e0 E' |( u
     visibility: hidden;
6 V3 K  q/ A1 ~$ q}
  N& o1 r$ |- N$ E  b
接下来,创建两个新按钮,以便允许用户导航月份。以编程方式使用 dijit/form/Button 创建这两个按钮。对于第一个按钮(后退),可以将标签设置为 “<<” 并修改 onClick 函数(清单 17)。onClick 的逻辑将包含在 goToPreviousMonth 函数中。# B9 K7 I" I$ P! H& }
( J! f* w$ M' q" ~6 s; m, E* ?
清单 17. 创建 dijit/form/bottom 的一个实例# y" j5 j" ~; W) U0 z
this.calendarPreviousMonthButton = new Button({
1 v8 ]4 L) ^8 R, G( ]8 @- p4 Y       label: "<<",        
0 L1 S6 u) T8 a* _# R. v. a       onClick: lang.hitch(this, function(){  O9 G1 _" E6 v; \( G
               this.goToPreviousMonth(this.calendarInstance);
+ \& z  \  M3 x8 X- w       })
9 u: P! P  L9 Y: k, ]/ u; C& a}, this.calendarPreviousMonthButtonAP);
3 s7 y& z3 K$ M; _
您希望在用户每次单击该按钮时,日历后退一个月。在 goToPreviousMonth 中,需要先将 currentFocusDate 更改为 currentFocusDate - 1 month,然后刷新日历的视图。最后,必须检查这是否要显示的最后一个月,如果是,则禁用该按钮。
) K( l0 `# A, n" z! t使用 dojo/date/add 函数,它接受日期对象、间隔(字符串)和数量(整数)。对于您的情形,日期应该是 currentFocusDate 对象,间隔是 “month”,数量是 -1(清单 18)。  G5 H1 L0 f/ q8 D1 R
# ^9 |9 t) p# X+ x# w' Y
清单 18. 日历视图减去一个月  j3 n1 n" _( y$ _
this.currentFocusDate = dojoDate.add(this.currentFocusDate,"month",-1);
( D. K- S& G5 j3 ncalendarInstance.set("currentFocus",this.currentFocusDate);
1 N8 u* L) g4 K" R6 c9 p
设置日历的新视图,将 currentFocus 设置为新的日期值。(这将自动刷新日历并显示新视图)。
7 r) S7 \/ C* M5 C& P最后,请检查这是否是最后一个月的视图,方法是对比 currentFocusDate 与最小值边界;如果是最后一个月,则禁用后退按钮。另外,请检查您是否应启用了前进按钮(假如您禁用了该按钮,并且现在您离开了最大值边界)(清单 19)。& z6 }* l8 D: T7 f

# R6 [$ i  D. H清单 19. 检查我们是否应该禁用新导航按钮
- T. x8 l% W0 f$ p+ F/ o
if(this.isLastCalendarMonth(this.bookingWindowMinDate, this.currentFocusDate)){
; O1 s* p1 X& O6 p, ^7 c5 v        this.calendarPreviousMonthButton.set("disabled", true);
# K8 ]# a' P0 n% Y6 U. Y}+ P0 l# w2 R9 c8 b/ n$ r7 u2 d
if(!this.isLastCalendarMonth(this.bookingWindowMaxDate, this.currentFocusDate)){1 }  q7 u# Q3 @2 Q* ]6 Y! a, c
        this.calendarFollowingMonthButton.set("disabled", false);
, D# @, c; }% K! ]0 P; p5 ~( ~9 p}
5 }) b6 {' z/ b2 j0 t
第二个按钮的工作原理相同。该标签将为 “>>”,onClick 调用 goToNextMonth,后者使用了同一个函数,但您添加了一个月(清单 20)。* h: \4 l1 K/ O" a; H
- a$ \4 I- ^. T5 C2 d8 g
清单 20. 控制移动到下一个月的按钮的函数
! d. f5 _8 y& V- ~# r
goToNextMonth : function (calendarInstance){
" A3 F- t+ g8 u+ a  R        this.currentFocusDate = dojoDate.add(this.currentFocusDate,"month",1);
* S8 t: Z; O9 B1 }' V; M        calendarInstance.set("currentFocus",this.currentFocusDate);
6 n+ `+ U/ b) m  Y# _6 X9 i( G        if(this.isLastCalendarMonth(this.bookingWindowMaxDate, this.currentFocusDate)){" ^. d  I1 U+ S0 s5 Z
                this.calendarFollowingMonthButton.set("disabled", true);
) y8 W/ Y- _2 D# _1 M1 f        }        - s( x% i$ g) Z
        if(!this.isLastCalendarMonth(this.bookingWindowMinDate, this.currentFocusDate)){6 C# s8 B  t% ^( y. f5 N+ z/ R, V+ U
                this.calendarPreviousMonthButton.set("disabled", false);) L( s! B  I# p) \
        }: x' D. c( {# ?$ w6 {5 W
}

# E3 T& T7 C. m$ R' e最后,清单 21 显示了应该在控制器类中的内容的示例,该类将进行相关调用,以便初始化您的新 customCalendar。
9 j: S* ~, }  X) [# M8 C: _+ m) Y1 s; ]4 k
清单 21. 创建新的自定义日历小部件的实例的快照
' R+ q& E5 M0 S0 s% c2 N! ]
require(["myUtil/customCalendar","dojo/_base/connect"], function(myCalendar, connect){: l  Z3 R6 m) N) u  b6 T# l, F
        var params = {2 B  y3 h/ F7 [8 b6 {$ D9 ]
                "bookingWindowMinDate":"10/9/2011",& U' h+ _$ E- t9 C3 u/ O: |" l
                "bookingWindowMaxDate":"10/9/2012",
1 h- F2 s4 x9 W  G" }) @* Y# U, r                "selectedDate":"8/15/2012",
9 K  G- L) T3 y9 P5 c                "onValueSelectedPublishIDString":"selectedValueID"
7 ^( ]9 o) Q4 y        };* ~& ?; f. w4 t
        var myTest = myCalendar(params);
6 ]! X- Q, t4 P" ]; d7 N        myTest.placeAt("nodeId", "last");
' M( }7 \+ s, m* X: p0 K7 R                / S2 I* F# L+ R* r% N
        connect.subscribe("selectedValueID", function(date){
% ]5 [5 @) H, V: F) x" {          //Do some processing - R. F" k9 _# I) r3 Z, e/ }, c
          console.log("I got: ", date);" w8 q0 g9 @; s" ^) n6 ^1 {
        });        8 Y+ m- b& x- j* _9 v. L& p" E
        
- H9 F- q5 E5 L, ~" M* d& m; s2 k});
/ X  F' O8 \1 p* T6 I2 _7 q
如您所见,您创建了一个对象 params,其中包含需要传递给自定义日历小部件的值,并订阅了该频道。# q' L5 ~6 }% Q) M( ]2 a6 ^) U! C
更多函数
您可能会发现其他一些函数和属性在此场景中也很有用:
1 c# c; m2 _  [8 @
  • 当将一个日期对象和区域传递到 dojo/date/locale/isWeekend 时,如果日期是周末(对于 en-us 区域,是星期六和星期日),则会返回 true。如果需要,可以使用该属性来禁用周末日期或为周末设置不同的样式。
  • Calendar dijit 还包含一个 dayWidth 属性,该属性接受一个字符串作为值。默认情况下,会将它设置为 “narrow”,这缩短了显示的日历日期表示,例如使用 “M” 表示星期一。其他值包括表示完整日期名称显示的 “wide” 和表示缩写词的 “abbr”(比如 “Mon”)。" ]6 y2 K  X$ y! P0 p! a
这些自定义小部件需求的一种变体可能要求小部件显示多个日历,然后,在用户通过单击来查看下一个月时,要求两个日历都前进一个月(参见图 3)。这很容易完成,只需更改小部件变量来支持一个数组,而不是单个值变量。
) r! q& r# ^; R+ t" I, I/ R) I# y7 f+ ]) V. d# L/ e$ ?( d
图 3. 每个视图多个日历
3 C9 a: x: i; G# J* J8 D1 u
3 W+ l. [& h" {

! b- {$ F; D2 Y3 d3 K5 m! [: q' d* s. H, }; @8 x4 ]- |, H
结束语
通过组合 JavaScript 和 CSS 修改,很容易创建一个自定义小部件来更好地满足项目需求。本文演示了这种做法,使用 Dojo 1.7 声明了一个类,该类扩展了 Calendar dijit 并利用了一些 dojo 功能,比如日期操作、hitch、发布和订阅,以及其他一些基础 dojo 函数。希望您将能够应用这些步骤来扩展 Dojo dijit,并创建自己的新小部件。
9 |0 R0 U; w+ ]+ {  b. i
' u& d. x5 z, u+ {6 y' P

本帖子中包含更多资源

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

x
 楼主| 发表于 2013-2-19 10:43:23 | 显示全部楼层
本帖最后由 技术狂人 于 2013-2-19 10:44 编辑 * a4 l% ^8 N* L  }4 W

$ Q0 m3 q  E2 E7 k5 b
下载
描述名字大小: Z+ d: a- v* Y0 _
样例应用程序4 KB' o( Z" I% k# S( V) i7 F! ]0 |, V5 T
9 t3 _( M4 O5 E5 s1 s9 m

: g: k) ^, H9 i原文地址:http://www.ibm.com/developerwork ... er/1209_weller.html

本帖子中包含更多资源

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

x
回复 支持 反对

使用道具 举报

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

本版积分规则

关闭

SCMLife推荐上一条 /4 下一条

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

GMT+8, 2018-6-23 18:10 , Processed in 0.079768 second(s), 6 queries , Gzip On, MemCache On.

Powered by SCMLife X3.4 Licensed

© 2001-2017 JoyShare.

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