SCMLife.com

 找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 3757|回复: 1

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

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

# |: E) I" ^. f% G' k

% e# i4 X/ Y! a& p9 G+ ^
创建小部件
dijit 模板
创建 3 个 JavaScript div 元素:一个用于日历,两个用于向前和向后逐月导航的箭头按钮(清单 1)。这些 div 将使用附加点 (data-dojo-attach-point) 进行引用。使用附加点比使用 id 更好,因为它使您能够在同一个页面上拥有同一个小部件的多个实例,无需担忧 id 冲突。' W! ^  r; w6 y7 a3 k9 r
& p. E& S0 b& ~) {$ X) V$ ^, j3 `; c
清单 1. dijit 模板
/ A8 _/ o) Y! b
<div class="CalendarArrow">
2 g- [3 U( t; k<div data-dojo-attach-point="calendarPreviousMonthButtonAP"></div>
2 m, U6 b7 G: n9 M5 X& v$ R8 H</div>
" m7 A- B( t0 x- h" t
+ h& a) }3 ~& x# d+ F1 _( J<div class="CalendarDijit">7 a  r( }. ]; F; B/ m
<span data-dojo-attach-point="calendarMonthOneAttachPoint"></span>" E& p4 Z& F* |+ W+ O8 p5 ?% A% N( n
</div>! s4 L5 C- F/ ?8 D) M8 u

) B& n3 R1 ]$ f. f<div class="CalendarArrow">/ @- S4 K4 u( T6 z# r9 L+ {
<div data-dojo-attach-point="calendarFollowingMonthButtonAP"></div>0 D' `' x4 M2 y7 p
</div>
1 I7 `* s& V; F+ b
dijit 类
根据应用程序需求,您需要定义以下变量:
/ c; _  q0 Q8 ~2 K5 s$ ^: Q
  • selectedDate:日历的初始值。
  • currentFocusDate:一个值,日历会引用该值来了解要显示的月份;该值最初被设置为等于 selectedDate。
  • calendarInstance:Dijit 日历实例。
  • bookingWindowMaxDate:日历中允许的最晚的日期。
  • bookingWindowMinDate:日历中允许的最早的日期。
  • onValueSelectedPublishIDString:表示发布/订阅频道(或主题)的字符串。  _- m& r- c6 H; T/ m2 b5 _) l
JavaScript 函数
首先修改以下样式表元素:
! z( `* M) c, Q  F) W. z3 T
  • constructor 修改构造函数以复制从控制器传来的变量。使用 dojo/_base/lang/mixin,它将匹配变量名称,并将值复制到您的自定义小部件变量中(清单 2)。
    2 ?+ G- J) K5 p( t) X7 X5 O5 R0 [" D6 o) p, ]

    $ E" n, \5 t) ]/ F* z  q( f清单 2. 构造函数
  • constructor: function (args){4 a3 ~: e# |9 I8 ?5 }- Z( D
            if(args){4 Y5 J; w0 ~0 M( |9 [  T8 J) l
                    lang.mixin(this,args);" X& ~2 I: k8 j
            }
    7 v# b: p  J( {}

    ' Q/ a: p0 @1 A; g" q$ l
  • postCreate 所有日期都将以具有 en-us 短格式 mm/dd/yyyy 的字符串形式传递。使用 dojo/date/locale 函数将用于 selectedDate、bookingWindowMaxDate、bookingWindowMinDate 的所有日期字符串转换为日期对象(清单 3)。5 y$ s6 p- B' O4 [/ r! u

    + A! y) _) k9 r% j! D4 ~! _9 E  E$ s
    清单 3. 使用 dojo/date/locale
  • this.bookingWindowMinDate = locale.parse(this.bookingWindowMinDate, {formatLength:
    " o0 t7 T! R: P& f) n'short', selector:'date', locale:'en-us'});
    / z+ N4 T8 t- J, H7 \1 C: @, p
    创建日历对象的一个实例(清单 4)。创建的逻辑在 createCalendar 函数中。以编程方式创建一个 dijit 日历的实例,将它附加到您将使用 dojo/dom-construct(等效于老版 dojo 中的 dojo.create)创建的一个 div 上。一般来讲这是一种很好的做法,因为它允许您销毁日历而不丢失附加点。
    $ b( g' T4 I# K. o5 ?6 k) R( ]% h

    % o4 w3 l. D2 F1 n8 l8 x, K清单 4. 返回 dijit/Calendar 的一个实例
  • return new Calendar({
    4 f& d7 g: u3 D; K0 L# H. b        value : selectedDate,
    + u: m$ H2 ?6 t        currentFocus : selectedDate        },  domConstruct.create("div", {}, , L. `4 V' v7 n4 W# o0 \
            calendarAttachPoint));
    6 `. Q: |+ |* X; W! v+ t- D# Y}

    ! H7 M/ [4 V# ~- W' Q( o5 q
    请注意,您在Calendar dijit 中设置了 currentFocus 值。Calendar dijit 将始终使用您本地的当前日期来显示其第一个着屏 (landing screen),所以,如果希望日历显示不同的屏幕(日期),则必须设置 currentFocus。因此,对于自定义小部件,您需要将日历的初始值和 currentFocus 设置为 selectedDate(根据需要进行设置)。对于此示例,这个日期为 2012 年 8 月中的一天。
    0 w* k6 f; E' v2 N% U
要满足其他需求,您需要修改 Calendar dijit 中的以下 3 个函数:* G. J$ D0 S1 A4 B5 e  S0 z
  • isDisabledDate 当 calendar dijit 加载一个视图时,它会逐个迭代当前视图中的日期(所有 42 个日期),并为每一天调用 isDisabledDate 和 getClassForDate(接下来将介绍)函数。
    * r/ c9 L5 {9 e3 \* t7 GisDisabledDate 函数用于禁用日历中的某些日期(清单 5)。如果函数返回 true,那么将会禁用该日期。每次日历刷新时,都会调用此函数,并且会将日历中的每一天的日期传送给它。对于自定义小部件,您需要:, V. R5 W: ?: C& N
    • 禁用不属于当月的任何日期:为此,需要使用 dojo/date/difference 函数,该函数基于某个间隔来对比两个日期对象,如果两个日期相等,则返回 0。您将使用月份间隔对比 currentFocusDate 变量与当前视图中的每个日期,如果它们不相等,则返回 true,以禁用该日期。
    • 禁用边界日期外部的日期:再次使用 dojo/date/difference,但将间隔设置为 “day”。如果返回值小于 bookingWindowMinDate 或大于 bookingWindowMaxDate,则返回 true,以禁用该日期。 % Q# h( r4 X. u$ F: E) Q. V
      , a7 c2 U5 G1 m$ y6 \4 D1 m, r# X
      清单 5. 修改 isDisabledDate
    •                                                                 , N" `# j5 n. J5 _% u& [& Z
      isDisabledDate: function(date) {
      ! L/ ?1 o/ Z5 v //disable any day that doesn't belong to current month
      ! r* T  J# F& R0 P        if(dojoDate.difference(parent.currentFocusDate, date, "month")!==0){
      % ^* s" o4 m9 y0 K" N                return true;( s7 c! e! z& t0 L% e
              }) L# g+ b! ]% b( {
              if(dojoDate.difference(parent.bookingWindowMinDate, date, "day" || , T% {2 s% }% l2 ]+ L
      dojoDate.difference(parent.bookingWindowMaxDate, date, "day")<0){4 Y* ], z) [" y8 S4 M
                      return true;
      , ?! Z7 L# R) e- y* c1 e9 A. z! C* R        }; L4 Q1 Z& w0 b: S$ x/ r1 A
              else {" [. L. h) s6 ]" |8 H; W9 A3 D
                      return false;7 ]6 v/ J# H8 b+ i5 |
              }
      ' {6 g( ]( \: E) }2 [( l+ v}
      ; ?9 G) X+ g! w8 Q( A% ~
      + Y" p' F5 W' w
  • getClassForDate 尽管您使用 isDisabledDate 禁用了不属于当月视图的日期,但还需要隐藏它们。可以使用 getClassForDate 函数返回一个 CSS 类名,在日历上以不同形式标记该日期。对于自定义小部件,需要突出显示 selectedDate,向该日期添加一个具有黑色边界的蓝色框(清单 6)。您还需要使用灰色突出显示在最小和最大日期边界之外的日期,隐藏不属于当月的日期。
    - p; h. u; [3 z要识别需要设置不同样式的日期,可以使用 dojo/date/compare,它将接受两个日期值(日期对象)和天数(字符串),如果相等,则返回 0。这里,您将传递 currentFocusDate、迭代中的日期和表示天数的日期,因为您仅对对比日期感兴趣,所以无需关注时间戳。如果此对比返回 0,那么该函数将返回类 “Available”,这个类是在 CSS 文件中定义的(清单 7)。您将使用 CSS .class 选择权来定位我们希望更改的特定元素。, o- E4 l  |+ s

    8 V( d: o4 x  H. o" x3 V. E* y
    清单 6. 修改 getClassForDate
  • getClassForDate: function(date) {        
    * F8 F. U* _" G+ L  r4 F, G& v        if ( dojoDate.compare(date,selectedDate,"date") === 0) {7 a7 c* |2 K6 I: m
                    return "Available";
    8 j3 b1 _1 w" J        } // apply special style
    3 |+ p9 Q7 ~+ J7 F}

    1 f( b7 y3 \8 T4 D) h# I+ h' f- Q# w

    4 t/ E+ d# i8 J2 W: K清单 7. 标记可用日期的 CSS 类
  • .AvailabilityCalendars .Calendars .CalendarDijit .Available , B) ~8 `/ T1 A; l! i
            .dijitCalendarDateLabel- b% l9 T* Z$ q( ^: _  f
    {/ f$ G% z; u" g% b
            background-color: #bccedc !important;
    / ?, U7 [3 {! V' n. L2 |3 t        border: 1px solid #000000 !important;
    0 b& N' }% F+ }# m% l7 w}

    8 N, l( w2 t0 h3 b& V7 W$ _
    您将使用来自 isDisabledDate 的相同的 if 条件来识别超出边界的日期和不属于当月的日期,但会返回 CSS 类名(清单 8 和清单 9)。
    . i, D0 K, p- ^( X9 }0 \3 @- q! S. i, e9 m3 o$ P$ v/ F
    - k3 U/ Y& g( h- G
    清单 8. 隐藏和禁用日期
  • if(dojoDate.difference(parent.currentFocusDate, date, "month")!==0){ * ^) q; `" d% Y
            return "HiddenDay";
    . {% m) i" M, O! y+ F- o, o}
    0 W; i( {: ]+ ~9 |! S! T, Wif(dojoDate.difference(parent.bookingWindowMinDate, date, "day")<0 || " @3 {; U* L4 L5 r1 o9 B
            dojoDate.difference(parent.bookingWindowMaxDate, date, "day")>0){3 f+ A( u% Z% A6 e6 i
            return "Disabled";
    8 h& a' s1 J6 A" }& G}

    2 q. v" u6 E+ u$ U% V( _% N
    , V( a8 n; I1 I  s4 S

    : U% U' Y2 ?2 m$ n" d清单 9. 标记隐藏和禁用的日期的 CSS 类
  • .AvailabilityCalendars .Calendars .CalendarDijit .HiddenDay + Y3 F) g3 x+ e, q7 D& m) _
            .dijitCalendarDateLabel
      t& N/ f* P: {: r% f{
    / k: C, L( c! r    background-color: #ffffff !important;; [/ _4 T5 @1 y$ `( t5 Z5 S
        border-color: #ffffff;
    . p7 L) K' ^: o! W* [    color: #ffffff;
    9 W8 B% ]  G% x  Z- u* w}4 a) c4 u- i. R# `

    7 o: J9 i: B3 j3 P6 f0 q5 q5 L .AvailabilityCalendars .Calendars .CalendarDijit .Disabled 4 Z* M( l: e9 z2 D
            .dijitCalendarDateLabel
    ' ^: z' ]* {: w' u4 n# ]# o7 l{/ g# S2 G6 R8 B/ |, p6 z
            background-color: #9c9c9c;
      C  s$ r9 a& |) t2 O* }1 K}

    2 I7 _+ y4 {& h7 @, C) z( |2 U+ I: _
  • onChange 此函数仅在为日历设置一个新值或在日历上选择一个启用值时调用(清单 10)。此函数返回所选日期的一个日期对象。您可以使用该对象将日期发布到另一个将处理该日期的方法。调用您的自定义小部件中定义的一个函数 (onValueSelected),在发布到控制器之前,您可以在其中执行任何需要的处理(清单 11)。在本示例中,您将使用 dojo/_base/connect/publish 将日期发布到控制器。频道(或主题)字符串存储在变量 onValueSelectedPublishIDString 中。
    . r$ b5 X: A8 Z: C; R4 E/ }# P1 H" U3 |
    # g% ^) T8 j  t4 e6 w5 p' e
    清单 10. 使用 Calendar 的 onChange 和 hitch
  • onChange : lang.hitch(this, function(date){& @; |0 z' \0 y4 g7 A# m/ M
            this.onValueSelected(date);
    6 I* i8 F% G2 s. R})
    * H& R  L  m. j, ]" T) W

    , G: n( U. q4 w, M8 U. e- P清单 11. 使用 publish
  •                                                 
    ' Q) m3 X8 V. n/ K1 e* J( |onValueSelected : function (date){- q6 b9 v8 p' X  }7 ^. R
            connect.publish(this.onValueSelectedPublishIDString, [date]);
    2 l) G0 w4 S' m7 [}

    ; M" W, O# P; Y( j# ~, F# o# b
    请注意,您使用了 dojo/_base/lang/hitch 来提供调用函数 onValueSelected 的范围(清单 10)。您的控制器(在此场景中为 index.html)将提供一个订阅该频道的订户来处理日期(清单 12)。在此示例中,您仅记录它。可将此替换为任何其他需要的逻辑。
    9 ~- `& e, l- ~8 Y, S' |' I# Q2 `% s: F6 d; y3 `+ J

    / H' {" ]5 @: S) f( C清单 12. 我们的发布的订户
  • connect.subscribe("selectedValueID", function(date){* C+ E) q4 e: S; w5 e+ u
      //Do some processing
    : i7 W0 g# u/ ]/ T+ I  console.log("New Selected Date: ", date);* [2 u, V: L6 I/ S% B
    });

    $ ?) }- G/ A* h  h: L; J- P6 q/ D

    2 M5 B5 T  y: j
Calendar dijit 在页眉中附带了一个 monthDropDownButton。这个按钮显示了所有月份的列表,允许用户跳到任何月份。为了满足需求,您需要将 monthWidget 设置为 “disabled” 来禁用此按钮(清单 13)。
9 C/ z: g* h! l/ Y6 R$ U* g6 A6 v8 M% O$ L
清单 13. 禁用 Calendar 页眉中的下拉按钮" N  e: T0 Q4 `  w% Q% ]/ q. j
this.calendarInstance.monthWidget.set("disabled", true);
* y. x# \5 [4 m) J$ A1 s9 s
从实用性角度讲,您还需要隐藏箭头,使用户不会受到吸引而去单击它。为此,请添加定位您希望操作的元素的 CSS 类(清单 14)。+ k% }* R) b5 \3 D

9 r% r! T( m' [# d: e( f9 s% f清单 14. 隐藏下拉按钮箭头的 CSS 类9 v  |. i& |" D) v# e' d5 X2 p
.AvailabilityCalendars .Calendars .CalendarDijit .dijitDropDownButton
0 w; Y& @' d5 K$ d2 Q6 k        .dijitArrowButtonInner
" ~. ?9 L8 E# ~6 Y{
+ y6 E7 \7 i' _    visibility: hidden;; ^5 y3 r9 S; \- o
}
7 B1 X: R3 T: d  T: S1 X5 B
接下来,使用 CSS 类隐藏去年和明年的 digit,禁止将它显示在底部(清单 15)。
% H0 g  j  k! F6 F6 n% ]5 b3 R
清单 15. 在 Calendar 底部隐藏年份 digit 的 CSS 类
" {" o. T5 K8 r: S( V
.AvailabilityCalendars .Calendars .CalendarDijit .dijitCalendarPreviousYear, 0 L" q7 O! P& ~/ H3 p# K
        .dijitCalendarNextYear
* x. c$ K- H  G, a& y5 X    {
7 h! U: t; g' [$ t. xpadding: 1px 6px;
  L; z/ q$ \2 `- ^& H  Mvisibility: hidden;$ q% K9 U* A- |2 n6 Y) l  v
    }
7 i) a  T! J4 }* S  T
您还将隐藏顶部的箭头,否则这些箭头允许用户逐月移动(清单 16)。, h& [9 |( ^0 |  c5 ?( {0 U

! b' O5 W2 |& E: g1 C$ x清单 16. 隐藏 Calendar 顶部的月份箭头的 CSS 类
4 p. \5 ?2 r' k7 C% \! Q: c) k& j
.AvailabilityCalendars .Calendars .CalendarDijit .dijitCalendarArrow
+ g. n& v# `" P0 {7 S7 s3 I7 Q8 ^{
8 ~; G6 i1 h0 n2 j     visibility: hidden;
* I: k0 I- h4 N8 H. o}

7 d" g+ t- P2 _接下来,创建两个新按钮,以便允许用户导航月份。以编程方式使用 dijit/form/Button 创建这两个按钮。对于第一个按钮(后退),可以将标签设置为 “<<” 并修改 onClick 函数(清单 17)。onClick 的逻辑将包含在 goToPreviousMonth 函数中。: G+ H3 `# u/ F# G! a
7 v6 i+ e& T) s3 n- m6 z- a! o: T$ s
清单 17. 创建 dijit/form/bottom 的一个实例0 ^- ~6 z$ U' p$ k2 k
this.calendarPreviousMonthButton = new Button({
% ]4 k( A+ c- I0 r1 K* ]/ N1 l4 ~       label: "<<",        
9 a0 f# ?; V2 N! G       onClick: lang.hitch(this, function(){- i4 f9 `5 V4 p& a& q+ X; j
               this.goToPreviousMonth(this.calendarInstance);
. ]0 I  @% Z% `: a' t0 x7 D       })! y" e6 H8 \, n" v/ B" O
}, this.calendarPreviousMonthButtonAP);
* I* ?. O/ P9 h7 B6 n/ @+ r4 s
您希望在用户每次单击该按钮时,日历后退一个月。在 goToPreviousMonth 中,需要先将 currentFocusDate 更改为 currentFocusDate - 1 month,然后刷新日历的视图。最后,必须检查这是否要显示的最后一个月,如果是,则禁用该按钮。
6 N  i  v+ u0 I& b- l4 N6 p7 ^" n使用 dojo/date/add 函数,它接受日期对象、间隔(字符串)和数量(整数)。对于您的情形,日期应该是 currentFocusDate 对象,间隔是 “month”,数量是 -1(清单 18)。
5 y( J/ I1 D/ h2 g
2 _8 o3 u6 q' T0 Z; ]清单 18. 日历视图减去一个月9 u9 o# {+ x  E" z8 x) w
this.currentFocusDate = dojoDate.add(this.currentFocusDate,"month",-1);7 C% C- J3 l5 Q9 W. O5 S
calendarInstance.set("currentFocus",this.currentFocusDate);
6 l2 Z6 m0 [# I8 X- F2 t3 d4 f) t& e
设置日历的新视图,将 currentFocus 设置为新的日期值。(这将自动刷新日历并显示新视图)。
& \6 C3 E$ s* i  h- V+ @( j最后,请检查这是否是最后一个月的视图,方法是对比 currentFocusDate 与最小值边界;如果是最后一个月,则禁用后退按钮。另外,请检查您是否应启用了前进按钮(假如您禁用了该按钮,并且现在您离开了最大值边界)(清单 19)。' W) O  c; ?* r; E# n, |/ }
/ x( g- O  `9 v- X1 a
清单 19. 检查我们是否应该禁用新导航按钮2 V* t2 m( @: P# ?0 P4 N) Q+ m
if(this.isLastCalendarMonth(this.bookingWindowMinDate, this.currentFocusDate)){
5 t/ {. k: z& o# {' Z        this.calendarPreviousMonthButton.set("disabled", true);$ T: I' J7 l0 g
}
- J" j- _+ c+ }0 T9 M& Aif(!this.isLastCalendarMonth(this.bookingWindowMaxDate, this.currentFocusDate)){+ G) ?" \8 [1 H) h
        this.calendarFollowingMonthButton.set("disabled", false);
% l8 S  o6 T2 `% b/ \7 E- E}

# x  n) i8 z9 }2 l0 U- C5 N8 i) T第二个按钮的工作原理相同。该标签将为 “>>”,onClick 调用 goToNextMonth,后者使用了同一个函数,但您添加了一个月(清单 20)。0 N( e+ d3 u  V; h, k

/ g1 p/ r5 S- D# d$ [& J清单 20. 控制移动到下一个月的按钮的函数
, G4 O' i; U$ |  H8 \( Z
goToNextMonth : function (calendarInstance){
8 A, B: |$ ^  f% M" }) g        this.currentFocusDate = dojoDate.add(this.currentFocusDate,"month",1);) A/ [/ E7 g- A# C
        calendarInstance.set("currentFocus",this.currentFocusDate);, f$ F& ^- q1 z$ {) A. z% B
        if(this.isLastCalendarMonth(this.bookingWindowMaxDate, this.currentFocusDate)){# I( e- W; d4 T" a- W) D
                this.calendarFollowingMonthButton.set("disabled", true);
2 W( S: `& x0 |* l) f  |        }        
; U# T5 S4 p  w% o1 [0 T        if(!this.isLastCalendarMonth(this.bookingWindowMinDate, this.currentFocusDate)){
+ ?9 h: @! A) W! B( z                this.calendarPreviousMonthButton.set("disabled", false);# a( j' ~2 k9 l9 U/ _
        }. Z% o) s. p( @( Y
}
8 n( z3 f" }) H+ a6 x9 Z$ g4 R5 L
最后,清单 21 显示了应该在控制器类中的内容的示例,该类将进行相关调用,以便初始化您的新 customCalendar。
8 W% T/ m# Q# W0 T4 H9 G4 O% u  \
2 g/ I% r8 D  }$ A清单 21. 创建新的自定义日历小部件的实例的快照
+ A) k+ T( H  ^- m! P; i* d/ K
require(["myUtil/customCalendar","dojo/_base/connect"], function(myCalendar, connect){
* W* Y3 p/ h" I2 x; e  n        var params = {
! g9 u5 }  }. p# G  A                "bookingWindowMinDate":"10/9/2011",
. y" P# b) }6 i5 g+ K; q3 d0 C                "bookingWindowMaxDate":"10/9/2012",
1 h7 T0 p$ m, P, w% F7 Y                "selectedDate":"8/15/2012",- \- n$ K! S/ c4 T! ]* x" q
                "onValueSelectedPublishIDString":"selectedValueID"
3 i# {% B, ?- s" H) ^( e- c        };
1 [8 R3 \+ Y0 G' ~2 V2 l6 H9 J2 G        var myTest = myCalendar(params);
: F, N$ i& [4 q- ?# S$ }        myTest.placeAt("nodeId", "last");
; H/ c2 P; ~) M( \- m               
( Z7 |+ P: b4 j. X& K        connect.subscribe("selectedValueID", function(date){
2 x3 c  F2 q; C2 C5 o2 `          //Do some processing
5 Q) O1 ]: k. N: x) ^8 Q4 x          console.log("I got: ", date);
# U4 v1 ?: D2 H. k4 Q        });        0 A( g$ Q5 D! V8 K, G* Z+ ^9 |5 q6 G
        : F0 S5 }7 J6 V$ R/ Z' g
});

& L) X* O! q* ?$ A1 d: D8 o如您所见,您创建了一个对象 params,其中包含需要传递给自定义日历小部件的值,并订阅了该频道。
, }5 C% O& J) C) W' S
更多函数
您可能会发现其他一些函数和属性在此场景中也很有用:; K- x( r  I: u' Z" p  K
  • 当将一个日期对象和区域传递到 dojo/date/locale/isWeekend 时,如果日期是周末(对于 en-us 区域,是星期六和星期日),则会返回 true。如果需要,可以使用该属性来禁用周末日期或为周末设置不同的样式。
  • Calendar dijit 还包含一个 dayWidth 属性,该属性接受一个字符串作为值。默认情况下,会将它设置为 “narrow”,这缩短了显示的日历日期表示,例如使用 “M” 表示星期一。其他值包括表示完整日期名称显示的 “wide” 和表示缩写词的 “abbr”(比如 “Mon”)。
    4 b- H/ B* L- n7 s) ]
这些自定义小部件需求的一种变体可能要求小部件显示多个日历,然后,在用户通过单击来查看下一个月时,要求两个日历都前进一个月(参见图 3)。这很容易完成,只需更改小部件变量来支持一个数组,而不是单个值变量。/ Q8 c6 \' Q  s; q/ W6 e3 h

/ P3 @! m$ S& n1 E图 3. 每个视图多个日历6 s) o  v/ f* J& P: w

) Z  \  ?. ~, }/ ^% j3 M

  n5 R0 a- _: o0 m: ]
7 D5 i7 f. ^9 n7 r
结束语
通过组合 JavaScript 和 CSS 修改,很容易创建一个自定义小部件来更好地满足项目需求。本文演示了这种做法,使用 Dojo 1.7 声明了一个类,该类扩展了 Calendar dijit 并利用了一些 dojo 功能,比如日期操作、hitch、发布和订阅,以及其他一些基础 dojo 函数。希望您将能够应用这些步骤来扩展 Dojo dijit,并创建自己的新小部件。) A6 q3 i- V* i7 m

& ^) D) y/ g: U

本帖子中包含更多资源

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

x
 楼主| 发表于 2013-2-19 10:43:23 | 显示全部楼层
本帖最后由 技术狂人 于 2013-2-19 10:44 编辑 " z, Z1 }4 t( q  ?, B( w

/ E- m6 k2 Q! `' E" [
下载
描述名字大小. `, }# L) B. O2 _6 v7 P
样例应用程序4 KB
6 k/ g# ~! S: H% O

% O7 V, T2 b+ y% m% ?# S# I
3 O2 U, S# A5 R% Z! Z, x& \7 t原文地址:http://www.ibm.com/developerwork ... er/1209_weller.html

本帖子中包含更多资源

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

x
回复 支持 反对

使用道具 举报

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

本版积分规则

关闭

SCMLife推荐上一条 /4 下一条

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

GMT+8, 2018-9-20 07:16 , Processed in 0.068279 second(s), 6 queries , Gzip On, MemCache On.

Powered by SCMLife X3.4 Licensed

© 2001-2017 JoyShare.

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