Add calendar code from binoc-central

TRUNK
Matt A. Tobin 2 years ago
parent 14b241a2e0
commit 91bb501538
  1. 474
      .eslintrc.js
  2. 1130
      base/content/agenda-listbox.js
  3. 289
      base/content/agenda-listbox.xml
  4. 924
      base/content/calendar-base-view.xml
  5. 46
      base/content/calendar-bindings.css
  6. 76
      base/content/calendar-calendars-list.xul
  7. 165
      base/content/calendar-chrome-startup.js
  8. 201
      base/content/calendar-clipboard.js
  9. 950
      base/content/calendar-common-sets.js
  10. 582
      base/content/calendar-common-sets.xul
  11. 265
      base/content/calendar-daypicker.xml
  12. 600
      base/content/calendar-dnd-listener.js
  13. 274
      base/content/calendar-extract.js
  14. 422
      base/content/calendar-invitations-manager.js
  15. 97
      base/content/calendar-item-bindings.xml
  16. 744
      base/content/calendar-item-editing.js
  17. 444
      base/content/calendar-management.js
  18. 149
      base/content/calendar-menus.xml
  19. 1137
      base/content/calendar-month-view.xml
  20. 3886
      base/content/calendar-multiday-view.xml
  21. 111
      base/content/calendar-statusbar.js
  22. 250
      base/content/calendar-task-editing.js
  23. 312
      base/content/calendar-task-tree.js
  24. 1195
      base/content/calendar-task-tree.xml
  25. 300
      base/content/calendar-task-view.js
  26. 244
      base/content/calendar-task-view.xul
  27. 654
      base/content/calendar-ui-utils.js
  28. 60
      base/content/calendar-unifinder-todo.js
  29. 43
      base/content/calendar-unifinder-todo.xul
  30. 959
      base/content/calendar-unifinder.js
  31. 140
      base/content/calendar-unifinder.xul
  32. 72
      base/content/calendar-view-bindings.css
  33. 389
      base/content/calendar-view-core.xml
  34. 723
      base/content/calendar-views.js
  35. 289
      base/content/calendar-views.xml
  36. 115
      base/content/calendar-views.xul
  37. 359
      base/content/dialogs/calendar-alarm-dialog.js
  38. 49
      base/content/dialogs/calendar-alarm-dialog.xul
  39. 59
      base/content/dialogs/calendar-conflicts-dialog.xul
  40. 49
      base/content/dialogs/calendar-creation.js
  41. 693
      base/content/dialogs/calendar-dialog-utils.js
  42. 67
      base/content/dialogs/calendar-error-prompt.xul
  43. 1004
      base/content/dialogs/calendar-event-dialog-attendees.js
  44. 1604
      base/content/dialogs/calendar-event-dialog-attendees.xml
  45. 198
      base/content/dialogs/calendar-event-dialog-attendees.xul
  46. 1599
      base/content/dialogs/calendar-event-dialog-freebusy.xml
  47. 245
      base/content/dialogs/calendar-event-dialog-recurrence-preview.xml
  48. 804
      base/content/dialogs/calendar-event-dialog-recurrence.js
  49. 514
      base/content/dialogs/calendar-event-dialog-recurrence.xul
  50. 446
      base/content/dialogs/calendar-event-dialog-reminder.js
  51. 121
      base/content/dialogs/calendar-event-dialog-reminder.xul
  52. 138
      base/content/dialogs/calendar-event-dialog-timezone.js
  53. 46
      base/content/dialogs/calendar-event-dialog-timezone.xul
  54. 64
      base/content/dialogs/calendar-event-dialog.css
  55. 648
      base/content/dialogs/calendar-event-dialog.xul
  56. 15
      base/content/dialogs/calendar-invitations-dialog.css
  57. 119
      base/content/dialogs/calendar-invitations-dialog.js
  58. 49
      base/content/dialogs/calendar-invitations-dialog.xul
  59. 240
      base/content/dialogs/calendar-invitations-list.xml
  60. 662
      base/content/dialogs/calendar-migration-dialog.js
  61. 48
      base/content/dialogs/calendar-migration-dialog.xul
  62. 85
      base/content/dialogs/calendar-occurrence-prompt.xul
  63. 320
      base/content/dialogs/calendar-print-dialog.js
  64. 131
      base/content/dialogs/calendar-print-dialog.xul
  65. 178
      base/content/dialogs/calendar-properties-dialog.js
  66. 115
      base/content/dialogs/calendar-properties-dialog.xul
  67. 38
      base/content/dialogs/calendar-providerUninstall-dialog.js
  68. 37
      base/content/dialogs/calendar-providerUninstall-dialog.xul
  69. 13
      base/content/dialogs/calendar-subscriptions-dialog.css
  70. 154
      base/content/dialogs/calendar-subscriptions-dialog.js
  71. 85
      base/content/dialogs/calendar-subscriptions-dialog.xul
  72. 401
      base/content/dialogs/calendar-summary-dialog.js
  73. 300
      base/content/dialogs/calendar-summary-dialog.xul
  74. 91
      base/content/dialogs/chooseCalendarDialog.xul
  75. 358
      base/content/import-export.js
  76. 137
      base/content/preferences/alarms.js
  77. 239
      base/content/preferences/alarms.xul
  78. 339
      base/content/preferences/categories.js
  79. 60
      base/content/preferences/categories.xul
  80. 111
      base/content/preferences/editCategory.js
  81. 41
      base/content/preferences/editCategory.xul
  82. 122
      base/content/preferences/general.js
  83. 311
      base/content/preferences/general.xul
  84. 99
      base/content/preferences/views.js
  85. 306
      base/content/preferences/views.xul
  86. 482
      base/content/today-pane.js
  87. 293
      base/content/today-pane.xul
  88. 351
      base/content/widgets/calendar-alarm-widget.xml
  89. 1110
      base/content/widgets/calendar-list-tree.xml
  90. 129
      base/content/widgets/calendar-subscriptions-list.xml
  91. 70
      base/content/widgets/calendar-widget-bindings.css
  92. 731
      base/content/widgets/calendar-widgets.xml
  93. 1221
      base/content/widgets/minimonth.xml
  94. 225
      base/jar.mn
  95. 170
      base/modules/calAlarmUtils.jsm
  96. 128
      base/modules/calAsyncUtils.jsm
  97. 385
      base/modules/calAuthUtils.jsm
  98. 1296
      base/modules/calExtract.jsm
  99. 261
      base/modules/calHashedArray.jsm
  100. 179
      base/modules/calItemUtils.jsm
  101. Some files were not shown because too many files have changed in this diff Show More

@ -0,0 +1,474 @@
"use strict";
module.exports = {
"extends": [
"../platform/toolkit/.eslintrc.js"
],
"rules": {
// Enforce one true brace style (opening brace on the same line)
// Allow single line (for now) because of the vast number of changes needed
"brace-style": [2, "1tbs", { allowSingleLine: true }],
// Enforce newline at the end of file, with no multiple empty lines.
"eol-last": 2,
// Disallow using variables outside the blocks they are defined
"block-scoped-var": 2,
// Allow trailing commas for easy list extension. Having them does not
// impair readability, but also not required either.
"comma-dangle": 0,
// Enforce spacing before and after comma
"comma-spacing": [2, { before: false, after: true }],
// Enforce one true comma style.
"comma-style": [2, "last"],
// Enforce curly brace conventions for all control statements.
"curly": 2,
// Enforce the spacing around the * in generator functions.
"generator-star-spacing": [2, "after"],
// Require space before/after arrow function's arrow
"arrow-spacing": [2, { before: true, after: true }],
// Enforces spacing between keys and values in object literal properties.
"key-spacing": [2, { beforeColon: false, afterColon: true, mode: "minimum" }],
// Disallow the omission of parentheses when invoking a constructor with no
// arguments.
"new-parens": 2,
// Disallow use of the Array constructor.
"no-array-constructor": 2,
// disallow use of the Object constructor
"no-new-object": 2,
// Disallow Primitive Wrapper Instances
"no-new-wrappers": 2,
// Disallow the catch clause parameter name being the same as a variable in
// the outer scope, to avoid confusion.
"no-catch-shadow": 2,
// Disallow assignment in conditional expressions.
"no-cond-assign": 2,
// Disallow use of debugger.
"no-debugger": 2,
// Disallow deletion of variables (deleting properties is fine).
"no-delete-var": 2,
// Disallow duplicate arguments in functions.
"no-dupe-args": 2,
// Disallow duplicate keys when creating object literals.
"no-dupe-keys": 2,
// Disallow a duplicate case label.
"no-duplicate-case": 2,
// Disallow the use of empty character classes in regular expressions.
"no-empty-character-class": 2,
// Disallow assigning to the exception in a catch block.
"no-ex-assign": 2,
// Disallow adding to native types
"no-extend-native": 2,
// Disallow double-negation boolean casts in a boolean context.
"no-extra-boolean-cast": 2,
// Disallow unnecessary semicolons.
"no-extra-semi": 2,
// Disallow mixed spaces and tabs for indentation.
"no-mixed-spaces-and-tabs": 2,
// Disallow reassignments of native objects.
"no-native-reassign": 2,
// Disallow nested ternary expressions, they make the code hard to read.
"no-nested-ternary": 2,
// Disallow use of octal literals.
"no-octal": 2,
// Disallow comparisons where both sides are exactly the same.
"no-self-compare": 2,
// Disallow sparse arrays, eg. let arr = [,,2].
// Array destructuring is fine though:
// for (let [, breakpointPromise] of aPromises)
"no-sparse-arrays": 2,
// Disallow trailing whitespace at the end of lines.
"no-trailing-spaces": 2,
// Disallow use of the with statement.
"no-with": 2,
// Disallow comparisons with the value NaN.
"use-isnan": 2,
// Ensure that the results of typeof are compared against a valid string.
"valid-typeof": 2,
// disallow the use of object properties of the global object (Math and
// JSON) as functions
"no-obj-calls": 2,
// disallow use of octal escape sequences in string literals, such as
// var foo = "Copyright \251";
"no-octal-escape": 2,
// disallow use of void operator
"no-void": 2,
// Disallow Yoda conditions (where literal value comes first).
"yoda": 2,
// Require a space immediately following the // in a line comment.
"spaced-comment": [2, "always"],
// Require use of the second argument for parseInt().
"radix": 2,
// Require spaces before/after unary operators (words on by default,
// nonwords off by default).
"space-unary-ops": [2, { words: true, nonwords: false }],
// Enforce spacing after semicolons.
"semi-spacing": [2, { before: false, after: true }],
// Disallow the use of Boolean literals in conditional expressions.
"no-unneeded-ternary": 2,
// Disallow use of multiple spaces (sometimes used to align const values,
// array or object items, etc.). It's hard to maintain and doesn't add that
// much benefit.
"no-multi-spaces": 2,
// Require spaces around operators, except for a|0.
// Disabled for now given eslint doesn't support default args yet
// "space-infix-ops": [2, { "int32Hint": true }],
// Require a space around all keywords.
"keyword-spacing": 2,
// Disallow space between function identifier and application.
"no-spaced-func": 2,
// Disallow shadowing of names such as arguments.
"no-shadow-restricted-names": 2,
// Disallow use of comma operator.
"no-sequences": 2,
// Disallow use of assignment in return statement. It is preferable for a
// single line of code to have only one easily predictable effect.
"no-return-assign": 2,
// Require return statements to either always or never specify values
"consistent-return": 2,
// Disallow padding within blocks.
"padded-blocks": [2, "never"],
// Disallow spaces inside parentheses.
"space-in-parens": [2, "never"],
// Require space after keyword for anonymous functions, but disallow space
// after name of named functions.
"space-before-function-paren": [2, { anonymous: "never", named: "never" }],
// Disallow unreachable statements after a return, throw, continue, or break
// statement.
"no-unreachable": 2,
// Always require use of semicolons wherever they are valid.
"semi": [2, "always"],
// Disallow empty statements. This will report an error for:
// try { something(); } catch (e) {}
// but will not report it for:
// try { something(); } catch (e) { /* Silencing the error because ...*/ }
// which is a valid use case.
"no-empty": 2,
// Disallow declaring the same variable more than once (we use let anyway).
"no-redeclare": 2,
// Warn about declaration of variables already declared in the outer scope.
// This isn't an error because it sometimes is useful to use the same name
// in a small helper function rather than having to come up with another
// random name. Still, making this a warning can help people avoid being
// confused.
"no-shadow": 2,
// We use var-only-at-top-level instead of no-var as we allow top level
// vars.
"no-var": 0,
"mozilla/var-only-at-top-level": 1,
// Disallow global and local variables that aren't used, but allow unused function arguments.
"no-unused-vars": [2, { vars: "all", args: "none", varsIgnorePattern: "EXPORTED_SYMBOLS" }],
"mozilla/mark-test-function-used": 1,
// Require padding inside curly braces
"object-curly-spacing": [2, "always"],
// Disallow spaces inside of brackets
"array-bracket-spacing": [2, "never"],
// Disallow control characters in regular expressions
"no-control-regex": 2,
// Disallow invalid regular expression strings in RegExp constructors
"no-invalid-regexp": 2,
// Disallow multiple spaces in regular expression literals
"no-regex-spaces": 2,
// Disallow irregular whitespace
"no-irregular-whitespace": 2,
// Disallow negating the left operand in `in` expressions
"no-negated-in-lhs": 2,
// Allow constant expressions in conditions
// With 2.11.0 we can enable this with checkLoops: false
"no-constant-condition": [2, { checkLoops: false }],
// Disallow Regexs That Look Like Division
"no-div-regex": 2,
// Disallow Iterator (using __iterator__)
"no-iterator": 2,
// Enforce consistent linebreak style
"linebreak-style": [2, "unix"],
// Enforces return statements in callbacks of array's methods
"array-callback-return": 2,
// Verify super() calls in constructors
"constructor-super": 2,
// Disallow modifying variables of class declarations
"no-class-assign": 2,
// Disallow modifying variables that are declared using const
"no-const-assign": 2,
// Disallow duplicate name in class members
"no-dupe-class-members": 2,
// Disallow use of this/super before calling super() in constructors
"no-this-before-super": 2,
// Disallow duplicate imports
"no-duplicate-imports": 2,
// Disallow empty destructuring patterns
"no-empty-pattern": 2,
// Disallow Labeled Statements
"no-labels": 2,
// Disallow Multiline Strings
"no-multi-str": 2,
// Disallow Symbol Constructor
"no-new-symbol": 2,
// Disallow Initializing to undefined
"no-undef-init": 2,
// Disallow control flow statements in finally blocks
"no-unsafe-finally": 2,
// Disallow Unused Labels
"no-unused-labels": 2,
// Disallow unnecessary computed property keys on objects
"no-useless-computed-key": 2,
// Disallow unnecessary constructor
"no-useless-constructor": 2,
// Disallow renaming import, export, and destructured assignments to the
// same name
"no-useless-rename": 2,
// Enforce spacing between rest and spread operators and their expressions
"rest-spread-spacing": [2, "never"],
// Disallow usage of spacing in template string expressions
"template-curly-spacing": [2, "never"],
// Disallow the Unicode Byte Order Mark
"unicode-bom": [2, "never"],
// Enforce spacing around the * in yield* expressions
"yield-star-spacing": [2, "after"],
// Disallow Implied eval
"no-implied-eval": 2,
// Disallow unnecessary function binding
"no-extra-bind": 2,
// Disallow new For Side Effects
"no-new": 2,
// Disallow Self Assignment
"no-self-assign": 2,
// Disallow confusing multiline expressions
"no-unexpected-multiline": 2,
// Require IIFEs to be Wrapped
"wrap-iife": [2, "inside"],
// Disallow Unused Expressions
"no-unused-expressions": 2,
// Disallow function or var declarations in nested blocks
"no-inner-declarations": 2,
// Enforce newline before and after dot
"dot-location": [2, "property"],
// Disallow Use of caller/callee
"no-caller": 2,
// Disallow Case Statement Fallthrough
"no-fallthrough": 2,
// Disallow Floating Decimals
"no-floating-decimal": 2,
// Require Space Before Blocks
"space-before-blocks": 2,
// Operators always before the line break
"operator-linebreak": [2, "after", { overrides: { ":": "before", "?": "ignore" } }],
// Restricts the use of parentheses to only where they are necessary
// Disabled for now since this also removes parens around assignments, e.g. let foo = bar == baz
// "no-extra-parens": [2, "all", { "conditionalAssign": false, "returnAssign": false, "nestedBinaryExpressions": false }],
// Double quotes should be used.
"quotes": [2, "double", { avoidEscape: true }],
// Disallow if as the only statement in an else block.
"no-lonely-if": 2,
// Not more than two empty lines with in the file, and no extra lines at
// beginning or end of file.
"no-multiple-empty-lines": [2, { max: 2, maxEOF: 0, maxBOF: 0 }],
// Make sure all setters have a corresponding getter
"accessor-pairs": 2,
// Enforce spaces inside of single line blocks
"block-spacing": [2, "always"],
// Disallow spaces inside of computed properties
"computed-property-spacing": [2, "never"],
// Require consistent this (using |self|)
"consistent-this": [2, "self"],
// Disallow unnecessary .call() and .apply()
"no-useless-call": 2,
// Require dot notation when accessing properties
"dot-notation": 2,
// Disallow named function expressions
"func-names": [2, "never"],
// Enforce placing object properties on separate lines
"object-property-newline": [2, { allowMultiplePropertiesPerLine: true }],
// Enforce consistent line breaks inside braces
"object-curly-newline": [2, { multiline: true }],
// Disallow whitespace before properties
"no-whitespace-before-property": 2,
// Disallow unnecessary escape usage
"no-useless-escape": 2,
// Disallow mixes of different operators, but allow simple math operations.
"no-mixed-operators": [2, {
groups: [
/* ["+", "-", "*", "/", "%", "**"], */
["&", "|", "^", "~", "<<", ">>", ">>>"],
["==", "!=", "===", "!==", ">", ">=", "<", "<="],
["&&", "||"],
["in", "instanceof"]
]
}],
// Disallow unnecessary concatenation of strings
"no-useless-concat": 2,
// Disallow unmodified conditions of loops
"no-unmodified-loop-condition": 2,
// Suggest using arrow functions as callbacks
"prefer-arrow-callback": [2, { allowNamedFunctions: true }],
// Suggest using the spread operator instead of .apply()
"prefer-spread": 2,
// Quoting style for property names
"quote-props": [2, "consistent-as-needed", { keywords: true }],
// Disallow negated conditions
"no-negated-condition": 2,
// Enforce a maximum number of statements allowed per line
"max-statements-per-line": [2, { max: 2 }],
// Disallow arrow functions where they could be confused with comparisons
"no-confusing-arrow": 2,
// Disallow Unnecessary Nested Blocks
"no-lone-blocks": 2,
// Enforce minimum identifier length
"id-length": [2, {
min: 3,
exceptions: [
/* sorting */ "a", "b",
/* exceptions */ "e", "ex",
/* loop indices */ "i", "j", "k", "n",
/* coordinates */ "x", "y",
/* regexes */ "re",
/* known words */ "rc", "rv", "id", "OS", "os", "db",
/* mail/calendar words */ "to", "cc",
/* Components */ "Ci", "Cc", "Cu", "Cr",
]
}],
// Disallow lexical declarations in case/default clauses
"no-case-declarations": 2,
// Enforce consistent indentation (4-space)
"indent": [2, 4, { SwitchCase: 1 }],
// The following rules will not be enabled currently, but are kept here for
// easier updates in the future.
"no-else-return": 0,
}
};

File diff suppressed because it is too large Load Diff

@ -0,0 +1,289 @@
<?xml version="1.0"?>
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<bindings id="agenda-list-bindings"
xmlns="http://www.mozilla.org/xbl"
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
xmlns:xbl="http://www.mozilla.org/xbl">
<binding id="agenda-base-richlist-item"
extends="chrome://global/content/bindings/richlistbox.xml#richlistitem">
<implementation>
<field name="mOccurrence">null</field>;
<property name="occurrence" readonly="true">
<getter><![CDATA[
return this.mOccurrence;
]]></getter>
</property>
</implementation>
<handlers>
<handler event="click" phase="capturing"><![CDATA[
if (event.detail == 1) {
agendaListbox.onSelect(this);
} else if (event.button == 0) {
// We only care about button 0 doubleclick events
document.getElementById("agenda_edit_event_command").doCommand();
event.stopPropagation();
event.preventDefault();
}
]]></handler>
<handler event="mouseover"><![CDATA[
event.stopPropagation();
onMouseOverItem(event);
]]></handler>
</handlers>
</binding>
<binding id="agenda-checkbox-richlist-item"
extends="chrome://global/content/bindings/richlistbox.xml#richlistitem">
<content>
<xul:treenode-checkbox class="agenda-checkbox" anonid="agenda-checkbox-widget"
flex="1"
xbl:inherits="selected,label,hidden,disabled"/>
</content>
<implementation>
<field name="kCheckbox">null</field>;
<constructor><![CDATA[
this.kCheckbox = document.getAnonymousElementByAttribute(this, "anonid", "agenda-checkbox-widget");
]]></constructor>
<method name="getItem">
<body><![CDATA[
return this.mItem;
]]></body>
</method>
<method name="setItem">
<parameter name="synthetic"/>
<parameter name="showsToday"/>
<body><![CDATA[
this.mItem = synthetic;
let duration = synthetic.duration;
if (showsToday) {
this.kCheckbox.label = this.getAttribute("title");
if (this.id == "nextweek-header") {
if (duration > 7) {
this.kCheckbox.label += " (" + unitPluralForm(duration / 7, "weeks") + ")";
} else {
this.kCheckbox.label += " (" + unitPluralForm(duration, "days") + ")";
}
}
} else if (synthetic.duration == 1) {
this.kCheckbox.label = getDateFormatter().formatDate(synthetic.start);
} else {
this.kCheckbox.label = getDateFormatter().formatInterval(synthetic.start, synthetic.end);
}
]]></body>
</method>
<method name="getCheckbox">
<body><![CDATA[
return this.kCheckbox;
]]></body>
</method>
</implementation>
</binding>
<binding id="agenda-allday-richlist-item"
extends="chrome://calendar/content/agenda-listbox.xml#agenda-base-richlist-item">
<content tooltip="itemTooltip">
<xul:hbox anonid="agenda-container-box"
class="agenda-allday-container-box"
xbl:inherits="selected,disabled"
flex="1">
<xul:vbox pack="center" flex="1">
<xul:label anonid="agenda-allDayEvent-date" class="agenda-event-start"
crop="end" xbl:inherits="selected" hidden="true"/>
<xul:hbox flex="1" align="start">
<xul:image anonid="agenda-multiDayEvent-image" class="agenda-multiDayEvent-image"/>
<xul:calendar-month-day-box-item anonid="allday-item"
flex="1"
flat="true"/>
</xul:hbox>
</xul:vbox>
</xul:hbox>
</content>
<implementation>
<field name="mAllDayItem">null</field>;
<constructor><![CDATA[
this.mAllDayItem = document.getAnonymousElementByAttribute(this, "anonid", "allday-item");
]]></constructor>
<method name="setOccurrence">
<parameter name="aOccurrence"/>
<parameter name="aPeriod"/>
<body><![CDATA[
this.mOccurrence = aOccurrence;
this.mAllDayItem.occurrence = aOccurrence;
let dateFormatter = cal.getDateFormatter();
let periodStartDate = aPeriod.start.clone();
periodStartDate.isDate = true;
let periodEndDate = aPeriod.end;
let startDate = this.mOccurrence[calGetStartDateProp(this.mOccurrence)]
.getInTimezone(calendarDefaultTimezone());
let endDate = this.mOccurrence[calGetEndDateProp(this.mOccurrence)]
.getInTimezone(calendarDefaultTimezone());
let endPreviousDay = endDate.clone();
endPreviousDay.day--;
// Show items's date for long periods but also for "Upcoming"
// period with one day duration.
let showDate = aPeriod.multiday || aPeriod.duration > 1;
let date = "";
let iconType = "";
let allDayDateLabel = document.getAnonymousElementByAttribute(this, "anonid", "agenda-allDayEvent-date");
setBooleanAttribute(allDayDateLabel, "hidden", !showDate);
if (startDate.compare(endPreviousDay) == 0) {
// All day event one day duration.
date = dateFormatter.formatDate(startDate);
} else if (startDate.compare(periodStartDate) >= 0 &&
startDate.compare(periodEndDate) <= 0) {
// All day event spanning multiple days.
iconType = "start";
date = dateFormatter.formatDate(startDate);
} else if (endDate.compare(periodStartDate) >= 0 &&
endDate.compare(periodEndDate) <= 0) {
iconType = "end";
date = dateFormatter.formatDate(endPreviousDay);
} else {
iconType = "continue";
hideElement(allDayDateLabel);
}
let multiDayImage = document.getAnonymousElementByAttribute(this, "anonid", "agenda-multiDayEvent-image");
multiDayImage.setAttribute("type", iconType);
// class wrap causes allday items to wrap its text in today-pane
let addWrap = document.getAnonymousElementByAttribute(this.mAllDayItem, "anonid", "eventbox");
addWrap.classList.add("wrap");
addWrap = document.getAnonymousElementByAttribute(this.mAllDayItem, "anonid", "event-detail-box");
addWrap.classList.add("wrap");
allDayDateLabel.value = date;
]]></body>
</method>
</implementation>
<handlers>
<handler event="dragstart" phase="capturing"><![CDATA[
invokeEventDragSession(this.mAllDayItem.occurrence.clone(), this);
event.stopPropagation();
event.preventDefault();
]]></handler>
</handlers>
</binding>
<binding id="agenda-richlist-item"
extends="chrome://calendar/content/agenda-listbox.xml#agenda-base-richlist-item">
<content tooltip="itemTooltip">
<xul:hbox anonid="agenda-container-box" class="agenda-container-box" xbl:inherits="selected,disabled,current" flex="1">
<xul:hbox>
<xul:vbox>
<xul:image anonid="agenda-calendar-image" class="agenda-calendar-image"/>
<xul:spacer flex="1"/>
</xul:vbox>
</xul:hbox>
<xul:vbox anonid="agenda-description" flex="1">
<xul:hbox align="start">
<xul:image anonid="agenda-multiDayEvent-image" class="agenda-multiDayEvent-image"/>
<xul:label anonid="agenda-event-start" class="agenda-event-start" crop="end" flex="1" xbl:inherits="selected"/>
</xul:hbox>
<xul:label anonid="agenda-event-title" class="agenda-event-title" crop="end" xbl:inherits="selected"/>
</xul:vbox>
</xul:hbox>
</content>
<implementation>
<method name="setOccurrence">
<parameter name="aItem"/>
<parameter name="aPeriod"/>
<body><![CDATA[
this.mOccurrence = aItem;
this.setAttribute("status", aItem.status);
let dateFormatter = Components.classes["@mozilla.org/calendar/datetime-formatter;1"]
.getService(Components.interfaces.calIDateTimeFormatter);
let periodStartDate = aPeriod.start.clone();
periodStartDate.isDate = true;
let periodEndDate = aPeriod.end.clone();
periodEndDate.day--;
let start = this.mOccurrence[calGetStartDateProp(this.mOccurrence)]
.getInTimezone(calendarDefaultTimezone());
let end = this.mOccurrence[calGetEndDateProp(this.mOccurrence)]
.getInTimezone(calendarDefaultTimezone());
let startDate = start.clone();
startDate.isDate = true;
let endDate = end.clone();
endDate.isDate = true;
let endAtMidnight = (end.hour == 0 && end.minute == 0);
if (endAtMidnight) {
endDate.day--;
}
// Show items's date for long periods but also for "Upcoming"
// period with one day duration.
let longFormat = aPeriod.multiday || aPeriod.duration > 1;
let duration = "";
let iconType = "";
if (startDate.compare(endDate) == 0) {
// event that starts and ends in the same day, midnight included
duration = longFormat ? dateFormatter.formatDateTime(start)
: dateFormatter.formatTime(start);
} else if (startDate.compare(periodStartDate) >= 0 &&
startDate.compare(periodEndDate) <= 0) {
// event spanning multiple days, start date within period
iconType = "start";
duration = longFormat ? dateFormatter.formatDateTime(start)
: dateFormatter.formatTime(start);
} else if (endDate.compare(periodStartDate) >= 0 &&
endDate.compare(periodEndDate) <= 0) {
// event spanning multiple days, end date within period
iconType = "end";
if (endAtMidnight) {
duration = dateFormatter.formatDate(endDate) + " ";
duration = longFormat ? duration + calGetString("dateFormat", "midnight")
: calGetString("dateFormat", "midnight");
} else {
duration = longFormat ? dateFormatter.formatDateTime(end)
: dateFormatter.formatTime(end);
}
} else {
iconType = "continue";
}
let multiDayImage = document.getAnonymousElementByAttribute(this, "anonid", "agenda-multiDayEvent-image");
multiDayImage.setAttribute("type", iconType);
let durationbox = document.getAnonymousElementByAttribute(this, "anonid", "agenda-event-start");
durationbox.textContent = duration;
// show items with time only (today & tomorrow) as one line.
if (longFormat) {
let titlebox = document.getAnonymousElementByAttribute(this, "anonid", "agenda-event-title");
titlebox.textContent = aItem.title;
} else {
durationbox.textContent += " " + aItem.title;
}
this.refreshColor();
]]></body>
</method>
<method name="refreshColor">
<body><![CDATA[
let calcolor = (this.mOccurrence &&
this.mOccurrence.calendar.getProperty("color")) ||
"#a8c2e1";
let imagebox = document.getAnonymousElementByAttribute(this, "anonid", "agenda-calendar-image");
imagebox.setAttribute("style", "background-color: " + calcolor + ";");
]]></body>
</method>
</implementation>
<handlers>
<handler event="dragstart"><![CDATA[
invokeEventDragSession(this.mOccurrence.clone(), this);
]]></handler>
</handlers>
</binding>
</bindings>

@ -0,0 +1,924 @@
<?xml version="1.0"?>
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<bindings id="calendar-multiday-view-bindings"
xmlns="http://www.mozilla.org/xbl"
xmlns:html="http://www.w3.org/1999/xhtml"
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
xmlns:xbl="http://www.mozilla.org/xbl">
<binding id="calendar-base-view">
<resources>
<stylesheet src="chrome://calendar-common/skin/calendar-alarms.css"/>
</resources>
<implementation>
<field name="mWeekStartOffset">0</field>
<field name="mRangeStartDate">null</field>;
<field name="mRangeEndDate">null</field>;
<field name="mWorkdaysOnly">false</field>
<field name="mPendingRefreshJobs">null</field>
<field name="mCalendar">null</field>
<field name="mController">null</field>
<field name="mStartDate">null</field>
<field name="mEndDate">null</field>
<field name="mTasksInView">false</field>
<field name="mShowCompleted">false</field>
<field name="mDisplayDaysOff">true</field>
<field name="mDaysOffArray">[0, 6]</field>
<field name="mTimezone">null</field>
<field name="mFlashingEvents">null</field>
<field name="mSelectedItems">[]</field>
<field name="mLongWeekdayTotalPixels">-1</field>
<field name="mResizeHandler">null</field>
<field name="mDropShadowsLength">null</field>
<field name="mShadowOffset">null</field>
<field name="mDropShadows">null</field>
<field name="mMagnifyAmount">0</field>
<field name="mPixelScrollDelta">0</field>
<field name="mViewStart">null</field>
<field name="mViewEnd">null</field>
<field name="mToggleStatus">0</field>
<field name="mLog">null</field>
<field name="mToggleStatusFlag"><![CDATA[
({
WorkdaysOnly: 1,
TasksInView: 2,
ShowCompleted: 4,
})
]]></field>
<field name="mPrefObserver"><![CDATA[
({
calView: this,
observe: function(subj, topic, pref) {
this.calView.handlePreference(subj, topic, pref);
return;
}
})
]]></field>
<field name="mObserver"><![CDATA[
// the calIObserver, calICompositeObserver, and calIAlarmServiceObserver
({
QueryInterface: XPCOMUtils.generateQI([
Components.interfaces.calIObserver,
Components.interfaces.calIAlarmServiceObserver,
Components.interfaces.calICompositeObserver
]),
calView: this,
onStartBatch: function() {
},
onEndBatch: function() {
},
onLoad: function() {
this.calView.refresh();
},
onAddItem: function(aItem) {
if (cal.isToDo(aItem)) {
if (!aItem.entryDate && !aItem.dueDate) {
return;
}
if (!this.calView.mTasksInView) {
return;
}
if (aItem.isCompleted && !this.calView.mShowCompleted) {
return;
}
}
let occs = aItem.getOccurrencesBetween(this.calView.startDate,
this.calView.queryEndDate,
{});
for (let occ of occs) {
this.calView.doAddItem(occ);
}
return;
},
onModifyItem: function(aNewItem, aOldItem) {
if (cal.isToDo(aNewItem) && cal.isToDo(aOldItem) &&
!this.calView.mTasksInView) {
return;
}
let occs;
if (!cal.isToDo(aOldItem) || aOldItem.entryDate || aOldItem.dueDate) {
occs = aOldItem.getOccurrencesBetween(this.calView.startDate,
this.calView.queryEndDate,
{});
for (let occ of occs) {
this.calView.doDeleteItem(occ);
}
}
if (cal.isToDo(aNewItem)) {
if ((!aNewItem.entryDate && !aNewItem.dueDate) || !this.calView.mTasksInView) {
return;
}
if (aNewItem.isCompleted && !this.calView.mShowCompleted) {
return;
}
}
occs = aNewItem.getOccurrencesBetween(this.calView.startDate,
this.calView.queryEndDate,
{});
for (let occ of occs) {
this.calView.doAddItem(occ);
}
},
onDeleteItem: function(aItem) {
if (cal.isToDo(aItem)) {
if (!this.calView.mTasksInView) {
return;
}
if (!aItem.entryDate && !aItem.dueDate) {
return;
}
if (aItem.isCompleted && !this.calView.mShowCompleted) {
return;
}
}
let occs = aItem.getOccurrencesBetween(this.calView.startDate,
this.calView.queryEndDate,
{});
for (let occ of occs) {
this.calView.doDeleteItem(occ);
}
},
onError: function(aCalendar, aErrNo, aMessage) { },
onPropertyChanged: function(aCalendar, aName, aValue, aOldValue) {
switch (aName) {
case "suppressAlarms":
if (!Preferences.get("calendar.alarms.indicator.show", true) ||
aCalendar.getProperty("capabilities.alarms.popup.supported") === false) {
break;
}
// else fall through
case "readOnly":
case "disabled":
// XXXvv we can be smarter about how we handle this stuff
this.calView.refresh();
break;
}
},
onPropertyDeleting: function(aCalendar, aName) {
// Values are not important here yet.
this.onPropertyChanged(aCalendar, aName, null, null);
},
//
// calIAlarmServiceObserver stuff
//
onAlarm: function(aAlarmItem) {
this.calView.flashAlarm(aAlarmItem, false);
},
onRemoveAlarmsByItem: function(aItem) {
// Stop the flashing for the item.
this.calView.flashAlarm(aItem, true);
},
onRemoveAlarmsByCalendar: function(aCalendar) {
// Stop the flashing for all items of this calendar
for (let key in this.calView.mFlashingEvents) {
let item = this.calView.mFlashingEvents[key];
if (item.calendar.id == aCalendar.id) {
this.calView.flashAlarm(item, true);
}
}
},
onAlarmsLoaded: function(aCalendar) {},
//
// calICompositeObserver stuff
// XXXvv we can be smarter about how we handle this stuff
//
onCalendarAdded: function(aCalendar) {
if (!aCalendar.getProperty("disabled")) {
this.calView.addItemsFromCalendar(aCalendar);
}
},
onCalendarRemoved: function(aCalendar) {
if (!aCalendar.getProperty("disabled")) {
this.calView.deleteItemsFromCalendar(aCalendar);
}
},
onDefaultCalendarChanged: function(aNewDefaultCalendar) {
// don't care, for now
}
})
]]></field>
<constructor><![CDATA[
Components.utils.import("resource://gre/modules/Services.jsm");
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
Components.utils.import("resource://gre/modules/Preferences.jsm");
Components.utils.import("resource:///modules/gloda/log4moz.js");
const kWorkdaysCommand = "calendar_toggle_workdays_only_command";
const kTasksInViewCommand = "calendar_toggle_tasks_in_view_command";
const kShowCompleted = "calendar_toggle_show_completed_in_view_command";
const kOrientation = "calendar_toggle_orientation_command";
this.workdaysOnly = (document.getElementById(kWorkdaysCommand)
.getAttribute("checked") == "true");
this.tasksInView = (document.getElementById(kTasksInViewCommand)
.getAttribute("checked") == "true");
this.rotated = (document.getElementById(kOrientation)
.getAttribute("checked") == "true");
this.showCompleted = (document.getElementById(kShowCompleted)
.getAttribute("checked") == "true");
this.mTimezone = calendarDefaultTimezone();
let alarmService = Components.classes["@mozilla.org/calendar/alarm-service;1"]
.getService(Components.interfaces.calIAlarmService);
alarmService.addObserver(this.mObserver);
this.setAttribute("type", this.type);
this.mResizeHandler = () => {
this.onResize(this);
};
this.viewBroadcaster.addEventListener(this.getAttribute("type") + "viewresized", this.mResizeHandler, true);
// add a preference observer to monitor changes
Services.prefs.addObserver("calendar.", this.mPrefObserver, false);
this.weekStartOffset = Preferences.get("calendar.week.start", 0);
this.updateDaysOffPrefs();
this.mPendingRefreshJobs = new Map();
this.mLog = Log4Moz.getConfiguredLogger("calBaseView");
this.mFlashingEvents = {};
]]></constructor>
<destructor><![CDATA[
Components.utils.import("resource://gre/modules/Services.jsm");
if (this.mCalendar) {
this.mCalendar.removeObserver(this.mObserver);
}
let alarmService = Components.classes["@mozilla.org/calendar/alarm-service;1"]
.getService(Components.interfaces.calIAlarmService);
alarmService.removeObserver(this.mObserver);
this.viewBroadcaster.removeEventListener(this.getAttribute("type") + "viewresized", this.mResizeHandler, true);
Services.prefs.removeObserver("calendar.", this.mPrefObserver);
]]></destructor>
<property name="type" readonly="true">
<getter><![CDATA[
let typelist = this.id.split("-");
return typelist[0];
]]></getter>
</property>
<property name="viewBroadcaster" readonly="true"
onget="return document.getElementById('calendarviewBroadcaster')"/>
<property name="labeldaybox" readonly="true"
onget="return document.getAnonymousElementByAttribute(this, 'anonid', 'labeldaybox')"/>
<property name="rotated"
onget="return (this.orient == 'horizontal')"
onset="return (this.orient = (val ? 'horizontal' : 'vertical'))"/>
<property name="supportsRotation" readonly="true"
onget="return false"/>
<property name="displayDaysOff"
onget="return this.mDisplayDaysOff;"
onset="return (this.mDisplayDaysOff = val);"/>
<property name="controller"
onget="return this.mController;"
onset="return (this.mController = val);"/>
<property name="daysOffArray"
onget="return this.mDaysOffArray;"
onset="return (this.mDaysOffArray = val);"/>
<property name="tasksInView"
onget="return this.mTasksInView;"
onset="return (this.mTasksInView = val);"/>
<property name="showCompleted"
onget="return this.mShowCompleted;"
onset="return (this.mShowCompleted = val);"/>
<property name="timezone"
onget="return this.mTimezone;"
onset="return (this.mTimezone = val);"/>
<property name="workdaysOnly"
onget="return this.mWorkdaysOnly;"
onset="return (this.mWorkdaysOnly = val);"/>
<property name="supportsWorkdaysOnly" readonly="true"
onget="return true;"/>
<property name="supportsZoom" readonly="true"
onget="return false;"/>
<property name="selectionObserver" readonly="true"
onget="return this.mSelectionObserver;"/>
<property name="startDay" readonly="true"
onget="return this.startDate;"/>
<property name="endDay" readonly="true"
onget="return this.endDate;"/>
<property name="supportDisjointDates" readonly="true"
onget="return false;"/>
<property name="hasDisjointDates" readonly="true"
onget="return false;"/>
<property name="rangeStartDate"
onget="return this.mRangeStartDate;"
onset="return (this.mRangeStartDate = val);"/>
<property name="rangeEndDate"
onget="return this.mRangeEndDate;"
onset="return (this.mRangeEndDate = val);"/>
<property name="observerID" readonly="true"
onget="return 'base-view-observer';"/>
<property name="weekStartOffset">
<getter><![CDATA[
return this.mWeekStartOffset;
]]></getter>
<setter><![CDATA[
this.mWeekStartOffset = val;
return val;
]]></setter>
</property>
<property name="displayCalendar">
<getter><![CDATA[
return this.mCalendar;
]]></getter>
<setter><![CDATA[
if (this.mCalendar) {
this.mCalendar.removeObserver(this.mObserver);
}
this.mCalendar = val;
this.mCalendar.addObserver(this.mObserver);
this.refresh();
return val;
]]></setter>
</property>
<property name="initialized">
<getter><![CDATA[
let retval;
// Some views throw when accessing an uninitialized startDay
try {
retval = this.displayCalendar && this.startDay &&
this.endDay;
} catch (ex) {
return false;
}
return retval;
]]></getter>
</property>
<method name="goToDay">
<parameter name="aDate"/>
<body><![CDATA[
this.showDate(aDate);
]]></body>
</method>
<method name="getRangeDescription">
<body><![CDATA[
return getDateFormatter().formatInterval(this.rangeStartDate, this.rangeEndDate);
]]></body>
</method>
<!-- This function guarantees that the
labels are clipped in the instance that the overflow occurrs,
avoiding horizontal scrollbars from showing up for a short period. -->
<method name="adjustWeekdayLength">
<parameter name="forceShortName"/>
<body><![CDATA[
let useShortNames = false;
let labeldayboxkids = this.labeldaybox.childNodes;
if (!labeldayboxkids || !labeldayboxkids[0]) {
useShortNames = true;
} else if (forceShortName && forceShortName === true) {
useShortNames = true;
} else {
let clientWidth = document.getAnonymousElementByAttribute(this, "anonid", "mainbox").clientWidth;
let timespacer = document.getAnonymousElementByAttribute(this, "anonid", "headertimespacer");
if (timespacer) {
clientWidth -= timespacer.clientWidth;
}
if (this.getLongWeekdayTotalPixels() > 0.95 * clientWidth) {
useShortNames = true;
}
}
for (let i = 0; i < labeldayboxkids.length; i++) {
labeldayboxkids[i].shortWeekNames = useShortNames;
}
]]></body>
</method>
<method name="today">
<body><![CDATA[
let date = cal.jsDateToDateTime(new Date()).getInTimezone(this.mTimezone);
date.isDate = true;
return date;
]]></body>
</method>
<method name="isVisible">
<body><![CDATA[
return (this.nodeName == currentView().nodeName);
]]></body>
</method>
<method name="refresh">
<body><![CDATA[
if (this.isVisible()) {
this.addItemsFromCalendar(this.mCalendar);
}
]]></body>
</method>
<!-- force refresh visible and invisible views.
This method is added because when only a preference is toggled, the start
and end date of views are unchanged, therefore those views behind the
"scene" might stay the same upon switch to them. -->
<method name="forceRefresh">
<body><![CDATA[
this.addItemsFromCalendar(this.mCalendar);
]]></body>
</method>
<method name="addItemsFromCalendar">
<parameter name="aCalendar"/>
<body><![CDATA[
let refreshJob = {
QueryInterface: XPCOMUtils.generateQI([Components.interfaces.calIOperationListener]),
calView: this,
calendar: null,
calId: null,
operation: null,
cancelled: false,
onOperationComplete: function(aOpCalendar, aStatus, aOperationType, aId, aDateTime) {
this.calView.mLog.info("Refresh complete of calendar " + this.calId);
if (this.calView.mPendingRefreshJobs.has(this.calId)) {
this.calView.mPendingRefreshJobs.delete(this.calId);
}
if (!this.cancelled) {
// Fire event
this.calView.fireEvent("viewloaded", aOperationType);
}
},
onGetResult: function(aOpCalendar, aStatus, aItemType, aDetail, aCount, aItems) {
if (this.cancelled || !Components.isSuccessCode(aStatus)) {
return;
}
for (let item of aItems) {
if (!cal.isToDo(item) || item.entryDate || item.dueDate) {
this.calView.doAddItem(item);
}
}
},
cancel: function() {
this.calView.mLog.info("Refresh cancelled for calendar " + this.calId);
this.cancelled = true;
let operation = cal.wrapInstance(this.operation, Components.interfaces.calIOperation);
if (operation && operation.isPending) {
operation.cancel();
this.operation = null;
}
},
execute: function() {
if (!this.calView.startDate || !this.calView.endDate || !aCalendar) {
return;
}
if (aCalendar.type == "composite") {
// we're refreshing from the composite calendar, so we can cancel
// all other pending refresh jobs.
this.calView.mLog.info("Refreshing composite calendar, cancelling all pending refreshes");
this.calId = "composite";
for (let job of this.calView.mPendingRefreshJobs.values()) {
job.cancel();
}
this.calView.mPendingRefreshJobs.clear();
this.calView.relayout();
} else {
this.calId = aCalendar.id;
if (this.calView.mPendingRefreshJobs.has(this.calId)) {
this.calView.mPendingRefreshJobs.get(this.calId).cancel();
this.calView.mPendingRefreshJobs.delete(this.calId);
}
}
this.calendar = aCalendar;
// start our items query; for a disjoint date range
// we get all the items, and just filter out the ones we don't
// care about in addItem
let filter = this.calendar.ITEM_FILTER_CLASS_OCCURRENCES;
if (this.calView.mShowCompleted) {
filter |= this.calendar.ITEM_FILTER_COMPLETED_ALL;
} else {
filter |= this.calendar.ITEM_FILTER_COMPLETED_NO;
}
if (this.calView.mTasksInView) {
filter |= this.calendar.ITEM_FILTER_TYPE_ALL;
} else {
filter |= this.calendar.ITEM_FILTER_TYPE_EVENT;
}
let operation = this.calendar.getItems(filter,
0,
this.calView.startDate,
this.calView.queryEndDate,
this);
operation = cal.wrapInstance(operation, Components.interfaces.calIOperation);
if (operation && operation.isPending) {
this.operation = operation;
this.calView.mPendingRefreshJobs.set(this.calId, this);
}
}
};
refreshJob.execute();
]]></body>
</method>
<method name="deleteItemsFromCalendar">
<parameter name="aCalendar"/>
<body><![CDATA[
/* This method must be implemented in subclasses. */
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
]]></body>
</method>
<!-- the end date that should be used for getItems and similar queries -->
<property name="queryEndDate" readonly="true">
<getter><![CDATA[
let end = this.endDate;
if (!end) {
return null;
}
end = end.clone();
end.day += 1;
end.isDate = true;
return end;
]]></getter>
</property>
<method name="fireEvent">
<parameter name="aEventName"/>
<parameter name="aEventDetail"/>
<body><![CDATA[
let event = document.createEvent("Events");
event.initEvent(aEventName, true, false);
event.detail = aEventDetail;
this.dispatchEvent(event);
]]></body>
</method>
<method name="removeDropShadows">
<body><![CDATA[
let dropbox = document.getAnonymousElementByAttribute(this, "dropbox", "true");
if (dropbox && dropbox !== undefined) {
dropbox.setAttribute("dropbox", "false");
}
]]></body>
</method>
<method name="getLongWeekdayTotalPixels">
<body><![CDATA[
if (this.mLongWeekdayTotalPixels <= 0) {
let maxDayWidth = 0;
for (let label of this.labeldaybox.childNodes) {
if (label.localName && label.localName == "calendar-day-label") {
label.shortWeekNames = false;
let curPixelLength = label.getLongWeekdayPixels();
maxDayWidth = Math.max(maxDayWidth, curPixelLength);
}
}
if (maxDayWidth > 0) {
this.mLongWeekdayTotalPixels = (maxDayWidth * this.labeldaybox.childNodes.length) + 10;
}
}
return this.mLongWeekdayTotalPixels;
]]></body>
</method>
<!-- A preference handler which is called by the preference observer.
Can be overwritten in derived bindings. -->
<method name="handleCommonPreference">
<parameter name="aSubject"/>
<parameter name="aTopic"/>
<parameter name="aPreference"/>
<body><![CDATA[
// refresh view if categories seem to have changed
if (aPreference.startsWith("calendar.category.color")) {
this.refreshView();
return;
}
switch (aPreference) {
case "calendar.week.d0sundaysoff":
case "calendar.week.d1mondaysoff":
case "calendar.week.d2tuesdaysoff":
case "calendar.week.d3wednesdaysoff":
case "calendar.week.d4thursdaysoff":
case "calendar.week.d5fridaysoff":
case "calendar.week.d6saturdaysoff":
this.updateDaysOffPrefs();
break;
case "calendar.timezone.local":
this.timezone = calendarDefaultTimezone();
this.refreshView();
break;
case "calendar.alarms.indicator.show":
// Break here to ensure the view is refreshed
break;
case "calendar.week.start":
this.weekStartOffset = aSubject.getIntPref(aPreference);
break;
case "calendar.date.format":
this.refreshView();
break;
default:
return;
}
this.refreshView();
]]></body>
</method>
<method name="updateDaysOffPrefs">
<body><![CDATA[
const weekPrefix = "calendar.week.";
const prefNames = ["d0sundaysoff", "d1mondaysoff", "d2tuesdaysoff",
"d3wednesdaysoff", "d4thursdaysoff",
"d5fridaysoff", "d6saturdaysoff"];
const defaults = ["true", "false", "false", "false",
"false", "false", "true"];
let daysOff = [];
for (let i in prefNames) {
if (Preferences.get(weekPrefix + prefNames[i], defaults[i])) {
daysOff.push(Number(i));
}
}
this.daysOffArray = daysOff;
]]></body>
</method>
<method name="refreshView">
<body><![CDATA[
if (!this.startDay || !this.endDay) {
// don't refresh if we're not initialized
return;
}
// Just refresh, the goToDay function will notice
this.goToDay(this.selectedDay);
this.forceRefresh();
]]></body>
</method>
<!-- Default implementations follow, these make things easier for
extensions that don't need certain features. -->
<method name="handlePreference">
<parameter name="aSubject"/>
<parameter name="aTopic"/>
<parameter name="aPref"/>
<body><![CDATA[
// Do nothing by default
]]></body>
</method>
<method name="setDateRange">
<parameter name="aStartDate"/>
<parameter name="aEndDate"/>
<body><![CDATA[
cal.navigationBar.setDateRange(aStartDate, aEndDate);
]]></body>
</method>
<property name="selectedDay"
onget="return this.startDate"
onset="return this.startDate"/>
<method name="getSelectedItems">
<parameter name="aCount"/>
<body><![CDATA[
aCount.value = this.mSelectedItems.length;
return this.mSelectedItems;
]]></body>
</method>
<method name="setSelectedItems">
<parameter name="aCount"/>
<parameter name="aItems"/>
<body><![CDATA[
this.mSelectedItems = aItems.concat([]);
return this.mSelectedItems;
]]></body>
</method>
<method name="getDateList">
<parameter name="aCount"/>
<parameter name="aDates"/>
<body><![CDATA[
let start = this.startDate.clone();
while (start.compare(this.endDate) <= 0) {
dates.push(start);
start.day++;
}
aCount.value = dates.length;
return dates;
]]></body>
</method>
<method name="flashAlarm">
<parameter name="aAlarmItem"/>
<parameter name="aStop"/>
<body><![CDATA[
// Do nothing by default
]]></body>
</method>
<method name="zoomIn">
<parameter name="aLevel"/>
<body><![CDATA[
]]></body>
</method>
<method name="zoomOut">
<parameter name="aLevel"/>
<body