2011-09-28 02:51:26 +08:00
|
|
|
/**
|
|
|
|
* Copyright (C) 2011 Instructure, Inc.
|
|
|
|
*
|
|
|
|
* This file is part of Canvas.
|
|
|
|
*
|
|
|
|
* Canvas is free software: you can redistribute it and/or modify it under
|
|
|
|
* the terms of the GNU Affero General Public License as published by the Free
|
|
|
|
* Software Foundation, version 3 of the License.
|
|
|
|
*
|
|
|
|
* Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
|
|
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
|
|
|
* A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
|
|
|
* details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Affero General Public License
|
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
2011-11-11 00:31:45 +08:00
|
|
|
define([
|
|
|
|
'i18n!instructure',
|
2015-05-07 05:38:32 +08:00
|
|
|
'jquery',
|
2013-09-25 11:49:35 +08:00
|
|
|
'timezone',
|
2011-11-11 00:31:45 +08:00
|
|
|
'str/htmlEscape',
|
refactor into DatetimeField.coffee
refs CNVS-19515
extracts and convert to coffeescript syntax, but also refactors heavily
for clarity and testability, while fixing:
* only aria-hide datepicker when actually added
since the datepicker is inaccessible, we hide the button to open it
(which follows $field) from aria. but we should only do that when we
actually added the datepicker button. if we didn't (i.e. timeOnly), we
accidentally hid $suggest from aria, which I don't think was intended.
* don't add "Local:" to parse error message when subject to dual
timezones
because of that, does not fail to flag @$suggest as invalid nor fail
to speak parse error message through #aria_alerts when subject to dual
timezones
* clear alternate representations on blank/invalid
when the entered datetime is blank or invalid, set data('date'),
data('unfudged-date'), and data('hiddenInput').val(...) to null rather
than leaving them with their old values from the last-known good date
(which made no sense)
* only apply local label if course text exists
* don't treat '02' as '2pm' in a time-only field; take the leading zero
as a hint to treat it as 24-hour time
test-plan:
- full regression on date field input behavior (including time-only
field like the start/end times in a calendar event that are separated
from the date entry)
- find a time-only field (e.g. the calendar event as described above).
the field's suggest text should not be hidden from aria
- for the same time-only field, enter a value of "02". it should be
interpreted as 2:00am (12-hour) or 02:00 (24-hour), as appropriate
for the locale. a value of "2" should still be interpreted as 2:00pm
(12-hour) or 14:00 (24-hour; this is a bug, but intentionally
preserved for now) as appropriate for the locale.
- in a course with a course timezone different than your profile
timezone, edit a due date and enter an invalid datetime. the field's
suggest text should not include "Local:" before "That is not a date!"
- repeat with screenreader enabled; a few seconds after entering the
invalid time, should hear "That is not a date!", same as you would
if the course timezone matched the profile timezone
- in a course with a course timezone different than your profile
timezone, find a date-only field (TODO: does one exist?) and enter a
valid date; the field's suggest text should not include "Local:"
Change-Id: I6a36c7fe07afdb07764b7b556d18d7c3801b3357
Reviewed-on: https://gerrit.instructure.com/51745
Reviewed-by: Ethan Vizitei <evizitei@instructure.com>
Tested-by: Jenkins
QA-Review: Jeremy Putnam <jeremyp@instructure.com>
Product-Review: Jacob Fugal <jacob@instructure.com>
2015-04-07 05:31:05 +08:00
|
|
|
'compiled/widget/DatetimeField',
|
2015-05-07 08:01:08 +08:00
|
|
|
'jsx/shared/render-datepicker-time',
|
2011-11-11 00:31:45 +08:00
|
|
|
'jquery.keycodes' /* keycodes */,
|
|
|
|
'vendor/date' /* Date.parse, Date.UTC, Date.today */,
|
|
|
|
'jqueryui/datepicker' /* /\.datepicker/ */,
|
|
|
|
'jqueryui/sortable' /* /\.sortable/ */,
|
|
|
|
'jqueryui/widget' /* /\.widget/ */
|
2015-08-11 12:36:10 +08:00
|
|
|
], function(I18n, $, tz, htmlEscape, DatetimeField, renderDatepickerTime) {
|
2012-01-04 04:31:58 +08:00
|
|
|
// fudgeDateForProfileTimezone is used to apply an offset to the date which represents the
|
|
|
|
// difference between the user's configured timezone in their profile, and the timezone
|
|
|
|
// of the browser. We want to display times in the timezone of their profile. Use
|
|
|
|
// unfudgeDateForProfileTimezone to remove the correction before sending dates back to the server.
|
2013-09-26 06:30:44 +08:00
|
|
|
$.fudgeDateForProfileTimezone = function(date) {
|
|
|
|
date = tz.parse(date);
|
2013-01-16 00:12:37 +08:00
|
|
|
if (!date) return null;
|
2013-09-26 06:30:44 +08:00
|
|
|
// format true date into profile timezone without tz-info, then parse in
|
|
|
|
// browser timezone. then, as desired:
|
|
|
|
// output.toString('yyyy-MM-dd hh:mm:ss') == tz.format(input, '%Y-%m-%d %H:%M:%S')
|
2015-05-05 07:32:01 +08:00
|
|
|
var year = tz.format(date, '%Y');
|
|
|
|
while (year.length < 4) year = "0" + year;
|
|
|
|
return Date.parse(tz.format(date, year + '-%m-%d %T'));
|
2012-01-04 04:31:58 +08:00
|
|
|
}
|
2012-10-26 04:50:16 +08:00
|
|
|
|
2012-01-04 04:31:58 +08:00
|
|
|
$.unfudgeDateForProfileTimezone = function(date) {
|
2013-09-26 06:30:44 +08:00
|
|
|
date = tz.parse(date);
|
|
|
|
if (!date) return null;
|
|
|
|
// format fudged date into browser timezone without tz-info, then parse in
|
|
|
|
// profile timezone. then, as desired:
|
|
|
|
// tz.format(output, '%Y-%m-%d %H:%M:%S') == input.toString('yyyy-MM-dd hh:mm:ss')
|
|
|
|
return tz.parse(date.toString('yyyy-MM-dd HH:mm:ss'));
|
2012-01-04 04:31:58 +08:00
|
|
|
}
|
2012-10-26 04:50:16 +08:00
|
|
|
|
2013-09-26 10:56:37 +08:00
|
|
|
// this batch of methods assumes *real* dates passed in (or, really, anything
|
|
|
|
// tz.parse() can recognize. so timestamps are cool, too. but not fudged dates).
|
|
|
|
// use accordingly
|
|
|
|
$.sameYear = function(d1, d2) {
|
|
|
|
return tz.format(d1, '%Y') == tz.format(d2, '%Y');
|
|
|
|
};
|
|
|
|
$.sameDate = function(d1, d2) {
|
|
|
|
return tz.format(d1, '%F') == tz.format(d2, '%F');
|
|
|
|
};
|
don't parse datetime_suggest for getFormData
refs CNVS-19515
getFormData (and things that use its result, e.g. processData on formSubmit)
now returns iso8601 values for datetime_fields instead of the formatted suggest
string. this means they no longer need to be parsed and reformatted before
submission from forms, inclusion in redirect parameters, etc.
to support this, and for general use, a datetime_field now has two additional
data attributes:
iso8601: an iso8601 formatting version of the unfudged date value
invalid: a boolean indicating if the form had an invalid input (distinct from
valid but blank input; both would cause the date data attribute to
be null)
also removed a couple calls to getFormData that weren't even used
also cleans up some nearby code around the "course concludes at midnight"
warning, so that it displays if the conclude_at is set to midnight in the
context timezone (or profile timezone if no context timezone) instead
midnight in the browser timezone.
test-plan:
- regression tests, particularly around browser vs. profile timezone,
for:
* setting term start/end dates
* setting course start/conclude dates
* setting section start/end dates
* setting unlock at on new context module
* "add assignment" form from the assignment list:
- preservation of due date when clicking "more options"
- setting due date on form submission
* editing assignment due date from calendar
* editing assignment overridden due date from calendar
* create a quiz, lock it, then unlock it until a specific date
* changing attachment and folder lock/unlock dates
- set profile timezone to differ from browser timezone. set course
conclude at to midnight in profile timezone; should show "course
ends at midnight" warning
- set course conclude at to midnight in browser timezone; should not
show "course ends at midnight" warning
- set course timezone to differ from profile timezone. set course
conclude at to midnight in course timezone; should show "course ends
at midnight" warning
- set course conclude at to midnight in profile timezone; should not
show "course ends at midnight" warning
Change-Id: I55179d4416eb07cdda0e94abc79d2c9f948a5387
Reviewed-on: https://gerrit.instructure.com/53188
Tested-by: Jenkins
Reviewed-by: Ethan Vizitei <evizitei@instructure.com>
QA-Review: Jeremy Putnam <jeremyp@instructure.com>
Product-Review: Jacob Fugal <jacob@instructure.com>
2015-04-10 01:06:47 +08:00
|
|
|
$.midnight = function(date, options) {
|
2015-08-18 03:18:33 +08:00
|
|
|
return tz.isMidnight(date, options);
|
2011-09-28 02:51:26 +08:00
|
|
|
};
|
form to interact with mg_p api - read action
Create a form to view grading periods, for
Accounts and Courses. This commit only
focuses on 'viewing' the grading periods;
other tickets will handle the creation,
deletion, and updating of grading periods.
closes CNVS-17842
test plan:
1. Set up data. Create a grading period group and a few grading
periods for a course using the rails console. For
example:
$ bundle exec rails console
$ course = Course.find(1) #grab any Course you want. here i'm getting
the course with ID 1
$ course.grading_period_groups.create!
$ course.grading_period_groups.first.grading_periods.
create!(title: "Course Grading Period 1",
start_date: Time.zone.now,
end_date: 30.days.from_now,
weight: 0.50)
$ course.grading_period_groups.first.grading_periods.
create!(title: "Course Grading Period 2",
start_date: 30.days.from_now,
end_date: 60.days.from_now,
weight: 0.50)
Next, add a few grading periods at the Account-level:
$ course.root_account.grading_period_groups.create!
$ course.root_account.grading_period_groups.first.
grading_periods.create!(title: "Account Grading Period 1",
start_date: Time.zone.now,
end_date: 30.days.from_now,
weight: 0.50)
$ course.grading_period_groups.first.grading_periods.
create!(title: "Account Grading Period 2",
start_date: 30.days.from_now,
end_date: 60.days.from_now,
weight: 0.50)
2. Turn on the multiple grading periods feature flag
3. Go to the grading_standards page for the course
'/courses/:course_id/grading_standards'.
Verify the page shows the two Course-level grading periods
you created (it will not show the Account-level
grading periods; this is being addressed in another ticket).
Note: the date-picker buttons, input fields,
update button, and delete icon will not be functional. Just check
to make sure you can _see_ the correct
information - you should not be able to update it.
4. Go to the grading_standards page for the account
'/accounts/:account_id/grading_standards'.
Verify the page shows the two Account-level grading periods
you created, and does NOT show the Course-level
grading periods that were created. Note: the date-picker buttons,
input fields, update button, and delete icon will not be
functional. Just check to make sure you can _see_ the correct
information - you should not be able to update it.
5. Ensure the pages are accessible-friendly, with appropriate
labels, navigation, etc. The datepicker icons
are not tabbable right now; this will be addressed with
the ticket that involves getting 'update' functionality
to work. Let me know if you have any questions!
Change-Id: I260bb6a870a0d56c1488823de67fd7d8522006cc
Reviewed-on: https://gerrit.instructure.com/47094
Reviewed-by: Cameron Sutter <csutter@instructure.com>
Tested-by: Jenkins
QA-Review: Amber Taniuchi <amber@instructure.com>
Product-Review: Spencer Olson <solson@instructure.com>
2015-01-14 01:02:14 +08:00
|
|
|
$.dateString = function(date, options) {
|
2014-05-14 07:48:56 +08:00
|
|
|
if (date == null) return "";
|
form to interact with mg_p api - read action
Create a form to view grading periods, for
Accounts and Courses. This commit only
focuses on 'viewing' the grading periods;
other tickets will handle the creation,
deletion, and updating of grading periods.
closes CNVS-17842
test plan:
1. Set up data. Create a grading period group and a few grading
periods for a course using the rails console. For
example:
$ bundle exec rails console
$ course = Course.find(1) #grab any Course you want. here i'm getting
the course with ID 1
$ course.grading_period_groups.create!
$ course.grading_period_groups.first.grading_periods.
create!(title: "Course Grading Period 1",
start_date: Time.zone.now,
end_date: 30.days.from_now,
weight: 0.50)
$ course.grading_period_groups.first.grading_periods.
create!(title: "Course Grading Period 2",
start_date: 30.days.from_now,
end_date: 60.days.from_now,
weight: 0.50)
Next, add a few grading periods at the Account-level:
$ course.root_account.grading_period_groups.create!
$ course.root_account.grading_period_groups.first.
grading_periods.create!(title: "Account Grading Period 1",
start_date: Time.zone.now,
end_date: 30.days.from_now,
weight: 0.50)
$ course.grading_period_groups.first.grading_periods.
create!(title: "Account Grading Period 2",
start_date: 30.days.from_now,
end_date: 60.days.from_now,
weight: 0.50)
2. Turn on the multiple grading periods feature flag
3. Go to the grading_standards page for the course
'/courses/:course_id/grading_standards'.
Verify the page shows the two Course-level grading periods
you created (it will not show the Account-level
grading periods; this is being addressed in another ticket).
Note: the date-picker buttons, input fields,
update button, and delete icon will not be functional. Just check
to make sure you can _see_ the correct
information - you should not be able to update it.
4. Go to the grading_standards page for the account
'/accounts/:account_id/grading_standards'.
Verify the page shows the two Account-level grading periods
you created, and does NOT show the Course-level
grading periods that were created. Note: the date-picker buttons,
input fields, update button, and delete icon will not be
functional. Just check to make sure you can _see_ the correct
information - you should not be able to update it.
5. Ensure the pages are accessible-friendly, with appropriate
labels, navigation, etc. The datepicker icons
are not tabbable right now; this will be addressed with
the ticket that involves getting 'update' functionality
to work. Let me know if you have any questions!
Change-Id: I260bb6a870a0d56c1488823de67fd7d8522006cc
Reviewed-on: https://gerrit.instructure.com/47094
Reviewed-by: Cameron Sutter <csutter@instructure.com>
Tested-by: Jenkins
QA-Review: Amber Taniuchi <amber@instructure.com>
Product-Review: Spencer Olson <solson@instructure.com>
2015-01-14 01:02:14 +08:00
|
|
|
var timezone = options && options.timezone;
|
|
|
|
var format = options && options.format;
|
2015-04-02 05:01:43 +08:00
|
|
|
format = (format !== 'medium') && $.sameYear(date, new Date()) ? 'date.formats.short' : 'date.formats.medium';
|
form to interact with mg_p api - read action
Create a form to view grading periods, for
Accounts and Courses. This commit only
focuses on 'viewing' the grading periods;
other tickets will handle the creation,
deletion, and updating of grading periods.
closes CNVS-17842
test plan:
1. Set up data. Create a grading period group and a few grading
periods for a course using the rails console. For
example:
$ bundle exec rails console
$ course = Course.find(1) #grab any Course you want. here i'm getting
the course with ID 1
$ course.grading_period_groups.create!
$ course.grading_period_groups.first.grading_periods.
create!(title: "Course Grading Period 1",
start_date: Time.zone.now,
end_date: 30.days.from_now,
weight: 0.50)
$ course.grading_period_groups.first.grading_periods.
create!(title: "Course Grading Period 2",
start_date: 30.days.from_now,
end_date: 60.days.from_now,
weight: 0.50)
Next, add a few grading periods at the Account-level:
$ course.root_account.grading_period_groups.create!
$ course.root_account.grading_period_groups.first.
grading_periods.create!(title: "Account Grading Period 1",
start_date: Time.zone.now,
end_date: 30.days.from_now,
weight: 0.50)
$ course.grading_period_groups.first.grading_periods.
create!(title: "Account Grading Period 2",
start_date: 30.days.from_now,
end_date: 60.days.from_now,
weight: 0.50)
2. Turn on the multiple grading periods feature flag
3. Go to the grading_standards page for the course
'/courses/:course_id/grading_standards'.
Verify the page shows the two Course-level grading periods
you created (it will not show the Account-level
grading periods; this is being addressed in another ticket).
Note: the date-picker buttons, input fields,
update button, and delete icon will not be functional. Just check
to make sure you can _see_ the correct
information - you should not be able to update it.
4. Go to the grading_standards page for the account
'/accounts/:account_id/grading_standards'.
Verify the page shows the two Account-level grading periods
you created, and does NOT show the Course-level
grading periods that were created. Note: the date-picker buttons,
input fields, update button, and delete icon will not be
functional. Just check to make sure you can _see_ the correct
information - you should not be able to update it.
5. Ensure the pages are accessible-friendly, with appropriate
labels, navigation, etc. The datepicker icons
are not tabbable right now; this will be addressed with
the ticket that involves getting 'update' functionality
to work. Let me know if you have any questions!
Change-Id: I260bb6a870a0d56c1488823de67fd7d8522006cc
Reviewed-on: https://gerrit.instructure.com/47094
Reviewed-by: Cameron Sutter <csutter@instructure.com>
Tested-by: Jenkins
QA-Review: Amber Taniuchi <amber@instructure.com>
Product-Review: Spencer Olson <solson@instructure.com>
2015-01-14 01:02:14 +08:00
|
|
|
if (typeof timezone == 'string' || timezone instanceof String) {
|
|
|
|
return tz.format(date, format, timezone) || '';
|
|
|
|
} else {
|
|
|
|
return tz.format(date, format) || '';
|
|
|
|
}
|
2011-09-28 02:51:26 +08:00
|
|
|
};
|
form to interact with mg_p api - read action
Create a form to view grading periods, for
Accounts and Courses. This commit only
focuses on 'viewing' the grading periods;
other tickets will handle the creation,
deletion, and updating of grading periods.
closes CNVS-17842
test plan:
1. Set up data. Create a grading period group and a few grading
periods for a course using the rails console. For
example:
$ bundle exec rails console
$ course = Course.find(1) #grab any Course you want. here i'm getting
the course with ID 1
$ course.grading_period_groups.create!
$ course.grading_period_groups.first.grading_periods.
create!(title: "Course Grading Period 1",
start_date: Time.zone.now,
end_date: 30.days.from_now,
weight: 0.50)
$ course.grading_period_groups.first.grading_periods.
create!(title: "Course Grading Period 2",
start_date: 30.days.from_now,
end_date: 60.days.from_now,
weight: 0.50)
Next, add a few grading periods at the Account-level:
$ course.root_account.grading_period_groups.create!
$ course.root_account.grading_period_groups.first.
grading_periods.create!(title: "Account Grading Period 1",
start_date: Time.zone.now,
end_date: 30.days.from_now,
weight: 0.50)
$ course.grading_period_groups.first.grading_periods.
create!(title: "Account Grading Period 2",
start_date: 30.days.from_now,
end_date: 60.days.from_now,
weight: 0.50)
2. Turn on the multiple grading periods feature flag
3. Go to the grading_standards page for the course
'/courses/:course_id/grading_standards'.
Verify the page shows the two Course-level grading periods
you created (it will not show the Account-level
grading periods; this is being addressed in another ticket).
Note: the date-picker buttons, input fields,
update button, and delete icon will not be functional. Just check
to make sure you can _see_ the correct
information - you should not be able to update it.
4. Go to the grading_standards page for the account
'/accounts/:account_id/grading_standards'.
Verify the page shows the two Account-level grading periods
you created, and does NOT show the Course-level
grading periods that were created. Note: the date-picker buttons,
input fields, update button, and delete icon will not be
functional. Just check to make sure you can _see_ the correct
information - you should not be able to update it.
5. Ensure the pages are accessible-friendly, with appropriate
labels, navigation, etc. The datepicker icons
are not tabbable right now; this will be addressed with
the ticket that involves getting 'update' functionality
to work. Let me know if you have any questions!
Change-Id: I260bb6a870a0d56c1488823de67fd7d8522006cc
Reviewed-on: https://gerrit.instructure.com/47094
Reviewed-by: Cameron Sutter <csutter@instructure.com>
Tested-by: Jenkins
QA-Review: Amber Taniuchi <amber@instructure.com>
Product-Review: Spencer Olson <solson@instructure.com>
2015-01-14 01:02:14 +08:00
|
|
|
|
|
|
|
$.timeString = function(date, options) {
|
2014-05-14 07:48:56 +08:00
|
|
|
if (date == null) return "";
|
form to interact with mg_p api - read action
Create a form to view grading periods, for
Accounts and Courses. This commit only
focuses on 'viewing' the grading periods;
other tickets will handle the creation,
deletion, and updating of grading periods.
closes CNVS-17842
test plan:
1. Set up data. Create a grading period group and a few grading
periods for a course using the rails console. For
example:
$ bundle exec rails console
$ course = Course.find(1) #grab any Course you want. here i'm getting
the course with ID 1
$ course.grading_period_groups.create!
$ course.grading_period_groups.first.grading_periods.
create!(title: "Course Grading Period 1",
start_date: Time.zone.now,
end_date: 30.days.from_now,
weight: 0.50)
$ course.grading_period_groups.first.grading_periods.
create!(title: "Course Grading Period 2",
start_date: 30.days.from_now,
end_date: 60.days.from_now,
weight: 0.50)
Next, add a few grading periods at the Account-level:
$ course.root_account.grading_period_groups.create!
$ course.root_account.grading_period_groups.first.
grading_periods.create!(title: "Account Grading Period 1",
start_date: Time.zone.now,
end_date: 30.days.from_now,
weight: 0.50)
$ course.grading_period_groups.first.grading_periods.
create!(title: "Account Grading Period 2",
start_date: 30.days.from_now,
end_date: 60.days.from_now,
weight: 0.50)
2. Turn on the multiple grading periods feature flag
3. Go to the grading_standards page for the course
'/courses/:course_id/grading_standards'.
Verify the page shows the two Course-level grading periods
you created (it will not show the Account-level
grading periods; this is being addressed in another ticket).
Note: the date-picker buttons, input fields,
update button, and delete icon will not be functional. Just check
to make sure you can _see_ the correct
information - you should not be able to update it.
4. Go to the grading_standards page for the account
'/accounts/:account_id/grading_standards'.
Verify the page shows the two Account-level grading periods
you created, and does NOT show the Course-level
grading periods that were created. Note: the date-picker buttons,
input fields, update button, and delete icon will not be
functional. Just check to make sure you can _see_ the correct
information - you should not be able to update it.
5. Ensure the pages are accessible-friendly, with appropriate
labels, navigation, etc. The datepicker icons
are not tabbable right now; this will be addressed with
the ticket that involves getting 'update' functionality
to work. Let me know if you have any questions!
Change-Id: I260bb6a870a0d56c1488823de67fd7d8522006cc
Reviewed-on: https://gerrit.instructure.com/47094
Reviewed-by: Cameron Sutter <csutter@instructure.com>
Tested-by: Jenkins
QA-Review: Amber Taniuchi <amber@instructure.com>
Product-Review: Spencer Olson <solson@instructure.com>
2015-01-14 01:02:14 +08:00
|
|
|
var timezone = options && options.timezone;
|
make on-the-hour time formats the same in js <-> ruby
fixes SD-1051
some places in JS (handlebars) were already consistent w/ ruby, others
were not. now if the time is on the hour, we omit the minutes everywere
(e.g. 1pm, not 1:00pm)
also fix most (all?) brittle specs that fail on the minute, hour, at
midnight, around DST, and at/near the new year ... 30+ are fixed by virtue
of this change alone, others required a little more TLC.
problematic specs were uncovered by freezing and/or traveling time to
interesting timestamps (see earlier patchset builds w/ timecop and
timecop.js).
note that some spec changes weren't technically necessary (many of the
format_date_for_view), but they are being tweaked regardless so we can
add a linter to discourage strftime calls in specs.
test plan:
n/a, see specs
Change-Id: I9edd65226ff37f9a3d94e2e03e1a01ab36aad639
Reviewed-on: https://gerrit.instructure.com/77295
Tested-by: Jenkins
Reviewed-by: Landon Wilkins <lwilkins@instructure.com>
Product-Review: Jon Jensen <jon@instructure.com>
QA-Review: Jon Jensen <jon@instructure.com>
2016-04-19 05:24:21 +08:00
|
|
|
|
|
|
|
// match ruby-side short format on the hour, e.g. `1pm`
|
|
|
|
// can't just check getMinutes, cuz not all timezone offsets are on the hour
|
|
|
|
var format = tz.format(date, '%M') === '00' ?
|
|
|
|
'time.formats.tiny_on_the_hour' :
|
|
|
|
'time.formats.tiny';
|
|
|
|
|
form to interact with mg_p api - read action
Create a form to view grading periods, for
Accounts and Courses. This commit only
focuses on 'viewing' the grading periods;
other tickets will handle the creation,
deletion, and updating of grading periods.
closes CNVS-17842
test plan:
1. Set up data. Create a grading period group and a few grading
periods for a course using the rails console. For
example:
$ bundle exec rails console
$ course = Course.find(1) #grab any Course you want. here i'm getting
the course with ID 1
$ course.grading_period_groups.create!
$ course.grading_period_groups.first.grading_periods.
create!(title: "Course Grading Period 1",
start_date: Time.zone.now,
end_date: 30.days.from_now,
weight: 0.50)
$ course.grading_period_groups.first.grading_periods.
create!(title: "Course Grading Period 2",
start_date: 30.days.from_now,
end_date: 60.days.from_now,
weight: 0.50)
Next, add a few grading periods at the Account-level:
$ course.root_account.grading_period_groups.create!
$ course.root_account.grading_period_groups.first.
grading_periods.create!(title: "Account Grading Period 1",
start_date: Time.zone.now,
end_date: 30.days.from_now,
weight: 0.50)
$ course.grading_period_groups.first.grading_periods.
create!(title: "Account Grading Period 2",
start_date: 30.days.from_now,
end_date: 60.days.from_now,
weight: 0.50)
2. Turn on the multiple grading periods feature flag
3. Go to the grading_standards page for the course
'/courses/:course_id/grading_standards'.
Verify the page shows the two Course-level grading periods
you created (it will not show the Account-level
grading periods; this is being addressed in another ticket).
Note: the date-picker buttons, input fields,
update button, and delete icon will not be functional. Just check
to make sure you can _see_ the correct
information - you should not be able to update it.
4. Go to the grading_standards page for the account
'/accounts/:account_id/grading_standards'.
Verify the page shows the two Account-level grading periods
you created, and does NOT show the Course-level
grading periods that were created. Note: the date-picker buttons,
input fields, update button, and delete icon will not be
functional. Just check to make sure you can _see_ the correct
information - you should not be able to update it.
5. Ensure the pages are accessible-friendly, with appropriate
labels, navigation, etc. The datepicker icons
are not tabbable right now; this will be addressed with
the ticket that involves getting 'update' functionality
to work. Let me know if you have any questions!
Change-Id: I260bb6a870a0d56c1488823de67fd7d8522006cc
Reviewed-on: https://gerrit.instructure.com/47094
Reviewed-by: Cameron Sutter <csutter@instructure.com>
Tested-by: Jenkins
QA-Review: Amber Taniuchi <amber@instructure.com>
Product-Review: Spencer Olson <solson@instructure.com>
2015-01-14 01:02:14 +08:00
|
|
|
if (typeof timezone == 'string' || timezone instanceof String) {
|
make on-the-hour time formats the same in js <-> ruby
fixes SD-1051
some places in JS (handlebars) were already consistent w/ ruby, others
were not. now if the time is on the hour, we omit the minutes everywere
(e.g. 1pm, not 1:00pm)
also fix most (all?) brittle specs that fail on the minute, hour, at
midnight, around DST, and at/near the new year ... 30+ are fixed by virtue
of this change alone, others required a little more TLC.
problematic specs were uncovered by freezing and/or traveling time to
interesting timestamps (see earlier patchset builds w/ timecop and
timecop.js).
note that some spec changes weren't technically necessary (many of the
format_date_for_view), but they are being tweaked regardless so we can
add a linter to discourage strftime calls in specs.
test plan:
n/a, see specs
Change-Id: I9edd65226ff37f9a3d94e2e03e1a01ab36aad639
Reviewed-on: https://gerrit.instructure.com/77295
Tested-by: Jenkins
Reviewed-by: Landon Wilkins <lwilkins@instructure.com>
Product-Review: Jon Jensen <jon@instructure.com>
QA-Review: Jon Jensen <jon@instructure.com>
2016-04-19 05:24:21 +08:00
|
|
|
return tz.format(date, format, timezone) || '';
|
form to interact with mg_p api - read action
Create a form to view grading periods, for
Accounts and Courses. This commit only
focuses on 'viewing' the grading periods;
other tickets will handle the creation,
deletion, and updating of grading periods.
closes CNVS-17842
test plan:
1. Set up data. Create a grading period group and a few grading
periods for a course using the rails console. For
example:
$ bundle exec rails console
$ course = Course.find(1) #grab any Course you want. here i'm getting
the course with ID 1
$ course.grading_period_groups.create!
$ course.grading_period_groups.first.grading_periods.
create!(title: "Course Grading Period 1",
start_date: Time.zone.now,
end_date: 30.days.from_now,
weight: 0.50)
$ course.grading_period_groups.first.grading_periods.
create!(title: "Course Grading Period 2",
start_date: 30.days.from_now,
end_date: 60.days.from_now,
weight: 0.50)
Next, add a few grading periods at the Account-level:
$ course.root_account.grading_period_groups.create!
$ course.root_account.grading_period_groups.first.
grading_periods.create!(title: "Account Grading Period 1",
start_date: Time.zone.now,
end_date: 30.days.from_now,
weight: 0.50)
$ course.grading_period_groups.first.grading_periods.
create!(title: "Account Grading Period 2",
start_date: 30.days.from_now,
end_date: 60.days.from_now,
weight: 0.50)
2. Turn on the multiple grading periods feature flag
3. Go to the grading_standards page for the course
'/courses/:course_id/grading_standards'.
Verify the page shows the two Course-level grading periods
you created (it will not show the Account-level
grading periods; this is being addressed in another ticket).
Note: the date-picker buttons, input fields,
update button, and delete icon will not be functional. Just check
to make sure you can _see_ the correct
information - you should not be able to update it.
4. Go to the grading_standards page for the account
'/accounts/:account_id/grading_standards'.
Verify the page shows the two Account-level grading periods
you created, and does NOT show the Course-level
grading periods that were created. Note: the date-picker buttons,
input fields, update button, and delete icon will not be
functional. Just check to make sure you can _see_ the correct
information - you should not be able to update it.
5. Ensure the pages are accessible-friendly, with appropriate
labels, navigation, etc. The datepicker icons
are not tabbable right now; this will be addressed with
the ticket that involves getting 'update' functionality
to work. Let me know if you have any questions!
Change-Id: I260bb6a870a0d56c1488823de67fd7d8522006cc
Reviewed-on: https://gerrit.instructure.com/47094
Reviewed-by: Cameron Sutter <csutter@instructure.com>
Tested-by: Jenkins
QA-Review: Amber Taniuchi <amber@instructure.com>
Product-Review: Spencer Olson <solson@instructure.com>
2015-01-14 01:02:14 +08:00
|
|
|
} else {
|
make on-the-hour time formats the same in js <-> ruby
fixes SD-1051
some places in JS (handlebars) were already consistent w/ ruby, others
were not. now if the time is on the hour, we omit the minutes everywere
(e.g. 1pm, not 1:00pm)
also fix most (all?) brittle specs that fail on the minute, hour, at
midnight, around DST, and at/near the new year ... 30+ are fixed by virtue
of this change alone, others required a little more TLC.
problematic specs were uncovered by freezing and/or traveling time to
interesting timestamps (see earlier patchset builds w/ timecop and
timecop.js).
note that some spec changes weren't technically necessary (many of the
format_date_for_view), but they are being tweaked regardless so we can
add a linter to discourage strftime calls in specs.
test plan:
n/a, see specs
Change-Id: I9edd65226ff37f9a3d94e2e03e1a01ab36aad639
Reviewed-on: https://gerrit.instructure.com/77295
Tested-by: Jenkins
Reviewed-by: Landon Wilkins <lwilkins@instructure.com>
Product-Review: Jon Jensen <jon@instructure.com>
QA-Review: Jon Jensen <jon@instructure.com>
2016-04-19 05:24:21 +08:00
|
|
|
return tz.format(date, format) || '';
|
form to interact with mg_p api - read action
Create a form to view grading periods, for
Accounts and Courses. This commit only
focuses on 'viewing' the grading periods;
other tickets will handle the creation,
deletion, and updating of grading periods.
closes CNVS-17842
test plan:
1. Set up data. Create a grading period group and a few grading
periods for a course using the rails console. For
example:
$ bundle exec rails console
$ course = Course.find(1) #grab any Course you want. here i'm getting
the course with ID 1
$ course.grading_period_groups.create!
$ course.grading_period_groups.first.grading_periods.
create!(title: "Course Grading Period 1",
start_date: Time.zone.now,
end_date: 30.days.from_now,
weight: 0.50)
$ course.grading_period_groups.first.grading_periods.
create!(title: "Course Grading Period 2",
start_date: 30.days.from_now,
end_date: 60.days.from_now,
weight: 0.50)
Next, add a few grading periods at the Account-level:
$ course.root_account.grading_period_groups.create!
$ course.root_account.grading_period_groups.first.
grading_periods.create!(title: "Account Grading Period 1",
start_date: Time.zone.now,
end_date: 30.days.from_now,
weight: 0.50)
$ course.grading_period_groups.first.grading_periods.
create!(title: "Account Grading Period 2",
start_date: 30.days.from_now,
end_date: 60.days.from_now,
weight: 0.50)
2. Turn on the multiple grading periods feature flag
3. Go to the grading_standards page for the course
'/courses/:course_id/grading_standards'.
Verify the page shows the two Course-level grading periods
you created (it will not show the Account-level
grading periods; this is being addressed in another ticket).
Note: the date-picker buttons, input fields,
update button, and delete icon will not be functional. Just check
to make sure you can _see_ the correct
information - you should not be able to update it.
4. Go to the grading_standards page for the account
'/accounts/:account_id/grading_standards'.
Verify the page shows the two Account-level grading periods
you created, and does NOT show the Course-level
grading periods that were created. Note: the date-picker buttons,
input fields, update button, and delete icon will not be
functional. Just check to make sure you can _see_ the correct
information - you should not be able to update it.
5. Ensure the pages are accessible-friendly, with appropriate
labels, navigation, etc. The datepicker icons
are not tabbable right now; this will be addressed with
the ticket that involves getting 'update' functionality
to work. Let me know if you have any questions!
Change-Id: I260bb6a870a0d56c1488823de67fd7d8522006cc
Reviewed-on: https://gerrit.instructure.com/47094
Reviewed-by: Cameron Sutter <csutter@instructure.com>
Tested-by: Jenkins
QA-Review: Amber Taniuchi <amber@instructure.com>
Product-Review: Spencer Olson <solson@instructure.com>
2015-01-14 01:02:14 +08:00
|
|
|
}
|
2013-09-26 10:56:37 +08:00
|
|
|
};
|
2014-05-14 07:48:56 +08:00
|
|
|
$.datetimeString = function(datetime, options) {
|
2014-04-17 05:19:20 +08:00
|
|
|
datetime = tz.parse(datetime);
|
|
|
|
if (datetime == null) return "";
|
2015-08-11 12:36:10 +08:00
|
|
|
var dateValue = $.dateString(datetime, options);
|
|
|
|
var timeValue = $.timeString(datetime, options);
|
|
|
|
return I18n.t('#time.event', '%{date} at %{time}', { date: dateValue, time: timeValue });
|
2011-09-28 02:51:26 +08:00
|
|
|
};
|
2013-09-26 10:56:37 +08:00
|
|
|
// end batch
|
|
|
|
|
2011-09-28 02:51:26 +08:00
|
|
|
$.friendlyDatetime = function(datetime, perspective) {
|
|
|
|
var today = Date.today();
|
|
|
|
if (Date.equals(datetime.clone().clearTime(), today)) {
|
|
|
|
return I18n.l('#time.formats.tiny', datetime);
|
|
|
|
} else {
|
|
|
|
return $.friendlyDate(datetime, perspective);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
$.friendlyDate = function(datetime, perspective) {
|
|
|
|
if (perspective == null) {
|
|
|
|
perspective = 'past';
|
|
|
|
}
|
|
|
|
var today = Date.today();
|
|
|
|
var date = datetime.clone().clearTime();
|
|
|
|
if (Date.equals(date, today)) {
|
|
|
|
return I18n.t('#date.days.today', 'Today');
|
|
|
|
} else if (Date.equals(date, today.add(-1).days())) {
|
|
|
|
return I18n.t('#date.days.yesterday', 'Yesterday');
|
|
|
|
} else if (Date.equals(date, today.add(1).days())) {
|
|
|
|
return I18n.t('#date.days.tomorrow', 'Tomorrow');
|
|
|
|
} else if (perspective == 'past' && date < today && date >= today.add(-6).days()) {
|
|
|
|
return I18n.l('#date.formats.weekday', date);
|
|
|
|
} else if (perspective == 'future' && date < today.add(7).days() && date >= today) {
|
|
|
|
return I18n.l('#date.formats.weekday', date);
|
|
|
|
}
|
|
|
|
return I18n.l('#date.formats.medium', date);
|
|
|
|
};
|
2014-01-21 06:26:52 +08:00
|
|
|
|
2011-09-28 02:51:26 +08:00
|
|
|
$.datepicker.oldParseDate = $.datepicker.parseDate;
|
|
|
|
$.datepicker.parseDate = function(format, value, settings) {
|
2015-08-11 12:36:10 +08:00
|
|
|
// try parsing with tz.parse first. if it can, its return is an unfudged
|
|
|
|
// value, but the datepicker expects a fudged one, so fudge it. if it can't
|
|
|
|
// parse it, fallback to the datepicker's original parseDate (which returns
|
|
|
|
// already fudged)
|
|
|
|
var datetime = tz.parse(value);
|
|
|
|
if (datetime) {
|
|
|
|
return $.fudgeDateForProfileTimezone(datetime);
|
|
|
|
} else {
|
|
|
|
return $.datepicker.oldParseDate(format, value, settings);
|
|
|
|
}
|
2011-09-28 02:51:26 +08:00
|
|
|
};
|
|
|
|
$.datepicker._generateDatepickerHTML = $.datepicker._generateHTML;
|
|
|
|
$.datepicker._generateHTML = function(inst) {
|
|
|
|
var html = $.datepicker._generateDatepickerHTML(inst);
|
|
|
|
if(inst.settings.timePicker) {
|
2015-05-07 08:01:08 +08:00
|
|
|
html += renderDatepickerTime(inst.input);
|
2011-09-28 02:51:26 +08:00
|
|
|
}
|
|
|
|
return html;
|
|
|
|
};
|
|
|
|
$.fn.realDatepicker = $.fn.datepicker;
|
|
|
|
var _originalSelectDay = $.datepicker._selectDay;
|
|
|
|
$.datepicker._selectDay = function(id, month, year, td) {
|
|
|
|
var target = $(id);
|
|
|
|
if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
var inst = this._getInst(target[0]);
|
|
|
|
if(inst.settings.timePicker && !$.datepicker.okClicked && !inst._keyEvent) {
|
|
|
|
var origVal = inst.inline;
|
|
|
|
inst.inline = true;
|
|
|
|
$.data(target, 'datepicker', inst);
|
|
|
|
_originalSelectDay.call(this, id, month, year, td);
|
|
|
|
inst.inline = origVal;
|
|
|
|
$.data(target, 'datepicker', inst);
|
|
|
|
} else {
|
|
|
|
_originalSelectDay.call(this, id, month, year, td);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
$.fn.datepicker = function(options) {
|
|
|
|
options = $.extend({}, options);
|
|
|
|
options.prevOnSelect = options.onSelect;
|
|
|
|
options.onSelect = function(text, picker) {
|
|
|
|
if(options.prevOnSelect) {
|
|
|
|
options.prevOnSelect.call(this, text, picker);
|
|
|
|
}
|
|
|
|
var $div = picker.dpDiv;
|
|
|
|
var hr = $div.find(".ui-datepicker-time-hour").val() || $(this).data('time-hour');
|
|
|
|
var min = $div.find(".ui-datepicker-time-minute").val() || $(this).data('time-minute');
|
|
|
|
var ampm = $div.find(".ui-datepicker-time-ampm").val() || $(this).data('time-ampm');
|
2015-05-07 08:01:08 +08:00
|
|
|
if(hr || min) {
|
2015-10-23 06:04:29 +08:00
|
|
|
text += " " + hr + ":" + (min || "00");
|
2015-12-30 05:39:14 +08:00
|
|
|
if (tz.useMeridian()) {
|
2015-10-23 06:04:29 +08:00
|
|
|
text += " " + (ampm || I18n.t('#time.pm'));
|
2015-05-07 08:01:08 +08:00
|
|
|
}
|
2011-09-28 02:51:26 +08:00
|
|
|
}
|
|
|
|
picker.input.val(text).change();
|
|
|
|
};
|
|
|
|
if(!$.fn.datepicker.timepicker_initialized) {
|
|
|
|
$(document).delegate('.ui-datepicker-ok', 'click', function(event) {
|
|
|
|
var cur = $.datepicker._curInst;
|
|
|
|
var inst = cur;
|
|
|
|
var sel = $('td.' + $.datepicker._dayOverClass +
|
|
|
|
', td.' + $.datepicker._currentClass, inst.dpDiv);
|
|
|
|
if (sel[0]) {
|
|
|
|
$.datepicker.okClicked = true;
|
|
|
|
$.datepicker._selectDay(cur.input[0], inst.selectedMonth, inst.selectedYear, sel[0]);
|
|
|
|
$.datepicker.okClicked = false;
|
|
|
|
} else {
|
|
|
|
$.datepicker._hideDatepicker(null, $.datepicker._get(inst, 'duration'));
|
|
|
|
}
|
|
|
|
});
|
|
|
|
$(document).delegate(".ui-datepicker-time-hour", 'change keypress focus blur', function(event) {
|
|
|
|
var cur = $.datepicker._curInst;
|
|
|
|
if(cur) {
|
|
|
|
var val = $(this).val();
|
|
|
|
cur.input.data('time-hour', val);
|
|
|
|
}
|
|
|
|
}).delegate(".ui-datepicker-time-minute", 'change keypress focus blur', function(event) {
|
|
|
|
var cur = $.datepicker._curInst;
|
|
|
|
if(cur) {
|
|
|
|
var val = $(this).val();
|
|
|
|
cur.input.data('time-minute', val);
|
|
|
|
}
|
|
|
|
}).delegate(".ui-datepicker-time-ampm", 'change keypress focus blur', function(event) {
|
|
|
|
var cur = $.datepicker._curInst;
|
|
|
|
if(cur) {
|
|
|
|
var val = $(this).val();
|
|
|
|
cur.input.data('time-ampm', val);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
$(document).delegate(".ui-datepicker-time-hour,.ui-datepicker-time-minute,.ui-datepicker-time-ampm", 'mousedown', function(event) {
|
|
|
|
$(this).focus();
|
|
|
|
});
|
|
|
|
$(document).delegate(".ui-datepicker-time-hour,.ui-datepicker-time-minute,.ui-datepicker-time-ampm", 'change keypress focus blur', function(event) {
|
|
|
|
if(event.keyCode && event.keyCode == 13) {
|
|
|
|
var cur = $.datepicker._curInst;
|
|
|
|
var inst = cur;
|
|
|
|
var sel = $('td.' + $.datepicker._dayOverClass +
|
|
|
|
', td.' + $.datepicker._currentClass, inst.dpDiv);
|
|
|
|
if (sel[0]) {
|
|
|
|
$.datepicker.okClicked = true;
|
|
|
|
$.datepicker._selectDay(cur.input[0], inst.selectedMonth, inst.selectedYear, sel[0]);
|
|
|
|
$.datepicker.okClicked = false;
|
|
|
|
} else {
|
|
|
|
$.datepicker._hideDatepicker(null, $.datepicker._get(inst, 'duration'));
|
|
|
|
}
|
|
|
|
} else if(event.keyCode && event.keyCode == 27) {
|
|
|
|
$.datepicker._hideDatepicker(null, '');
|
|
|
|
}
|
|
|
|
});
|
|
|
|
$.fn.datepicker.timepicker_initialized = true;
|
|
|
|
}
|
|
|
|
this.realDatepicker(options);
|
|
|
|
$(document).data('last_datepicker', this);
|
|
|
|
return this;
|
|
|
|
};
|
|
|
|
$.fn.date_field = function(options) {
|
|
|
|
options = $.extend({}, options);
|
|
|
|
options.dateOnly = true;
|
|
|
|
this.datetime_field(options);
|
|
|
|
return this;
|
|
|
|
};
|
|
|
|
$.fn.time_field = function(options) {
|
|
|
|
options = $.extend({}, options);
|
|
|
|
options.timeOnly = true;
|
|
|
|
this.datetime_field(options);
|
|
|
|
return this;
|
|
|
|
};
|
Fully adopt Bootstrap & update css to work with it, closes: #CNVS-1344
this commit does the following:
* upgrade bootstrap-sass gem to most recent version
* switches to using bootstrap's normalize.css and forms.css
which fixes a whole bunch of misformatting of how bootstrap
stuff is supposed to look, but changing those 2 affects
a lot of our old stylesheets.
* gets rid of unified_buttons.sass and just uses bootstraps buttons.
.ui-button @extends these because we still have to support .ui-button
for modals & buttonsets. but .button is no longer supported.
* a lot of css file reorganization (there's no more 'blue' and
'normal canvas', there's just canvas)
* a bunch of files had to be tweaked to look good with these changes.
test plan:
This change touches every page in canvas so, no kidding, we need to make
sure every page looks OK. In order to do that:
1. each sprint team needs to give a +1 after they make sure all the
pages in the features they are over look good.
2. the QA person on each team needs to look at the pages for their
teams features for a QA +1
things to look for specifically when testing:
* buttons: this gets rid of all those red 'cancel' links
that are actually buttons, make sure all the buttons you see
look right. if you see 2 plain gray buttons next to each other
like [Save] [Cancel], we should make the primary one blue (by
adding the .btn-primary class)
* Forms: a lot of this change has to do with how form elements look,
especially <select>s, <input>s and <label>s. look at the diffs
for the ones that have the most changes and make sure those look
good, but also check for the ones I missed and make sure those
look good too.
* and just random style changes, if something looks ugly or broken
(and it didn't before), we should fix that.
Also:
just use a link instead of a drop-menu for adding event from sidebar
we used to have a drop down menu for adding events
to cal2 from the sidebar where you'd hit a cog
and it'd ask you if you wanted to add an event or
an assignment. this just simplifies it to an add
icon.
this: http://cl.ly/image/133a2A3q3q1M
instead of: http://cl.ly/image/46463o2s3W0g
Change-Id: I384fe273934bca96bf28423afb1402c7792d8766
Reviewed-on: https://gerrit.instructure.com/15422
Tested-by: Jenkins <jenkins@instructure.com>
Reviewed-by: Ryan Florence <ryanf@instructure.com>
QA-Review: Ryan Florence <ryanf@instructure.com>
2012-12-21 14:46:28 +08:00
|
|
|
|
|
|
|
// add bootstrap's .btn class to the button that opens a datepicker
|
|
|
|
$.datepicker._triggerClass = $.datepicker._triggerClass + ' btn';
|
|
|
|
|
2011-09-28 02:51:26 +08:00
|
|
|
$.fn.datetime_field = function(options) {
|
|
|
|
options = $.extend({}, options);
|
|
|
|
this.each(function() {
|
refactor into DatetimeField.coffee
refs CNVS-19515
extracts and convert to coffeescript syntax, but also refactors heavily
for clarity and testability, while fixing:
* only aria-hide datepicker when actually added
since the datepicker is inaccessible, we hide the button to open it
(which follows $field) from aria. but we should only do that when we
actually added the datepicker button. if we didn't (i.e. timeOnly), we
accidentally hid $suggest from aria, which I don't think was intended.
* don't add "Local:" to parse error message when subject to dual
timezones
because of that, does not fail to flag @$suggest as invalid nor fail
to speak parse error message through #aria_alerts when subject to dual
timezones
* clear alternate representations on blank/invalid
when the entered datetime is blank or invalid, set data('date'),
data('unfudged-date'), and data('hiddenInput').val(...) to null rather
than leaving them with their old values from the last-known good date
(which made no sense)
* only apply local label if course text exists
* don't treat '02' as '2pm' in a time-only field; take the leading zero
as a hint to treat it as 24-hour time
test-plan:
- full regression on date field input behavior (including time-only
field like the start/end times in a calendar event that are separated
from the date entry)
- find a time-only field (e.g. the calendar event as described above).
the field's suggest text should not be hidden from aria
- for the same time-only field, enter a value of "02". it should be
interpreted as 2:00am (12-hour) or 02:00 (24-hour), as appropriate
for the locale. a value of "2" should still be interpreted as 2:00pm
(12-hour) or 14:00 (24-hour; this is a bug, but intentionally
preserved for now) as appropriate for the locale.
- in a course with a course timezone different than your profile
timezone, edit a due date and enter an invalid datetime. the field's
suggest text should not include "Local:" before "That is not a date!"
- repeat with screenreader enabled; a few seconds after entering the
invalid time, should hear "That is not a date!", same as you would
if the course timezone matched the profile timezone
- in a course with a course timezone different than your profile
timezone, find a date-only field (TODO: does one exist?) and enter a
valid date; the field's suggest text should not include "Local:"
Change-Id: I6a36c7fe07afdb07764b7b556d18d7c3801b3357
Reviewed-on: https://gerrit.instructure.com/51745
Reviewed-by: Ethan Vizitei <evizitei@instructure.com>
Tested-by: Jenkins
QA-Review: Jeremy Putnam <jeremyp@instructure.com>
Product-Review: Jacob Fugal <jacob@instructure.com>
2015-04-07 05:31:05 +08:00
|
|
|
var $field = $(this);
|
|
|
|
if (!$field.hasClass('datetime_field_enabled')) {
|
|
|
|
$field.addClass('datetime_field_enabled');
|
|
|
|
new DatetimeField($field, options);
|
2011-09-28 02:51:26 +08:00
|
|
|
}
|
|
|
|
});
|
|
|
|
return this;
|
|
|
|
};
|
Fully adopt Bootstrap & update css to work with it, closes: #CNVS-1344
this commit does the following:
* upgrade bootstrap-sass gem to most recent version
* switches to using bootstrap's normalize.css and forms.css
which fixes a whole bunch of misformatting of how bootstrap
stuff is supposed to look, but changing those 2 affects
a lot of our old stylesheets.
* gets rid of unified_buttons.sass and just uses bootstraps buttons.
.ui-button @extends these because we still have to support .ui-button
for modals & buttonsets. but .button is no longer supported.
* a lot of css file reorganization (there's no more 'blue' and
'normal canvas', there's just canvas)
* a bunch of files had to be tweaked to look good with these changes.
test plan:
This change touches every page in canvas so, no kidding, we need to make
sure every page looks OK. In order to do that:
1. each sprint team needs to give a +1 after they make sure all the
pages in the features they are over look good.
2. the QA person on each team needs to look at the pages for their
teams features for a QA +1
things to look for specifically when testing:
* buttons: this gets rid of all those red 'cancel' links
that are actually buttons, make sure all the buttons you see
look right. if you see 2 plain gray buttons next to each other
like [Save] [Cancel], we should make the primary one blue (by
adding the .btn-primary class)
* Forms: a lot of this change has to do with how form elements look,
especially <select>s, <input>s and <label>s. look at the diffs
for the ones that have the most changes and make sure those look
good, but also check for the ones I missed and make sure those
look good too.
* and just random style changes, if something looks ugly or broken
(and it didn't before), we should fix that.
Also:
just use a link instead of a drop-menu for adding event from sidebar
we used to have a drop down menu for adding events
to cal2 from the sidebar where you'd hit a cog
and it'd ask you if you wanted to add an event or
an assignment. this just simplifies it to an add
icon.
this: http://cl.ly/image/133a2A3q3q1M
instead of: http://cl.ly/image/46463o2s3W0g
Change-Id: I384fe273934bca96bf28423afb1402c7792d8766
Reviewed-on: https://gerrit.instructure.com/15422
Tested-by: Jenkins <jenkins@instructure.com>
Reviewed-by: Ryan Florence <ryanf@instructure.com>
QA-Review: Ryan Florence <ryanf@instructure.com>
2012-12-21 14:46:28 +08:00
|
|
|
|
2011-09-28 02:51:26 +08:00
|
|
|
/* Based loosely on:
|
|
|
|
jQuery ui.timepickr - 0.6.5
|
|
|
|
http://code.google.com/p/jquery-utils/
|
|
|
|
|
|
|
|
(c) Maxime Haineault <haineault@gmail.com>
|
|
|
|
http://haineault.com
|
|
|
|
|
|
|
|
MIT License (http://www.opensource.org/licenses/mit-license.php */
|
|
|
|
$.fn.timepicker = function() {
|
|
|
|
var $picker = $("#time_picker");
|
|
|
|
if($picker.length === 0) {
|
|
|
|
$picker = $._initializeTimepicker();
|
|
|
|
}
|
|
|
|
this.each(function() {
|
|
|
|
$(this).focus(function() {
|
|
|
|
var offset = $(this).offset();
|
|
|
|
var height = $(this).outerHeight();
|
|
|
|
var width = $(this).outerWidth();
|
|
|
|
var $picker = $("#time_picker");
|
|
|
|
$picker.css({
|
|
|
|
left: -1000,
|
|
|
|
height: 'auto',
|
|
|
|
width: 'auto'
|
|
|
|
}).show();
|
|
|
|
var pickerOffset = $picker.offset();
|
|
|
|
var pickerHeight = $picker.outerHeight();
|
|
|
|
var pickerWidth = $picker.outerWidth();
|
|
|
|
$picker.css({
|
|
|
|
top: offset.top + height,
|
|
|
|
left: offset.left
|
|
|
|
}).end();
|
|
|
|
$("#time_picker .time_slot").removeClass('ui-state-highlight').removeClass('ui-state-active');
|
|
|
|
$picker.data('attached_to', $(this)[0]);
|
|
|
|
var windowHeight = $(window).height();
|
|
|
|
var windowWidth = $(window).width();
|
|
|
|
var scrollTop = $.windowScrollTop();
|
|
|
|
if((offset.top + height - scrollTop + pickerHeight) > windowHeight) {
|
|
|
|
$picker.css({
|
|
|
|
top: offset.top - pickerHeight
|
|
|
|
});
|
|
|
|
}
|
|
|
|
if(offset.left + pickerWidth > windowWidth) {
|
|
|
|
$picker.css({
|
|
|
|
left: offset.left + width - pickerWidth
|
|
|
|
});
|
|
|
|
}
|
|
|
|
$("#time_picker").hide().slideDown();
|
|
|
|
}).blur(function() {
|
|
|
|
if($("#time_picker").data('attached_to') == $(this)[0]) {
|
|
|
|
$("#time_picker").data('attached_to', null);
|
|
|
|
$("#time_picker").hide()
|
|
|
|
.find(".time_slot.ui-state-highlight").removeClass('ui-state-highlight');
|
|
|
|
}
|
|
|
|
}).keycodes("esc return", function(event) {
|
|
|
|
$(this).triggerHandler('blur');
|
|
|
|
}).keycodes("ctrl+up ctrl+right ctrl+left ctrl+down", function(event) {
|
|
|
|
if($("#time_picker").data('attached_to') != $(this)[0]) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
event.preventDefault();
|
|
|
|
var $current = $("#time_picker .time_slot.ui-state-highlight:first");
|
|
|
|
var time = $($("#time_picker").data('attached_to')).val();
|
|
|
|
var hr = 12;
|
|
|
|
var min = "00";
|
|
|
|
var ampm = "pm";
|
|
|
|
var idx;
|
|
|
|
if(time && time.length >= 7) {
|
|
|
|
hr = time.substring(0, 2);
|
|
|
|
min = time.substring(3, 5);
|
|
|
|
ampm = time.substring(5, 7);
|
|
|
|
}
|
|
|
|
if($current.length === 0) {
|
|
|
|
idx = parseInt(time, 10) - 1;
|
|
|
|
if(isNaN(idx)) { idx = 0; }
|
|
|
|
$("#time_picker .time_slot").eq(idx).triggerHandler('mouseover');
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if(event.keyString == "ctrl+up") {
|
|
|
|
var $parent = $current.parent(".widget_group");
|
|
|
|
idx = $parent.children(".time_slot").index($current);
|
|
|
|
if($parent.hasClass('ampm_group')) {
|
|
|
|
idx = min / 15;
|
|
|
|
} else if($parent.hasClass('minute_group')) {
|
|
|
|
idx = parseInt(hr, 10) - 1;
|
|
|
|
}
|
|
|
|
$parent.prev(".widget_group").find(".time_slot").eq(idx).triggerHandler('mouseover');
|
|
|
|
} else if(event.keyString == "ctrl+right") {
|
|
|
|
$current.next(".time_slot").triggerHandler('mouseover');
|
|
|
|
} else if(event.keyString == "ctrl+left") {
|
|
|
|
$current.prev(".time_slot").triggerHandler('mouseover');
|
|
|
|
} else if(event.keyString == "ctrl+down") {
|
|
|
|
$parent = $current.parent(".widget_group");
|
|
|
|
idx = $parent.children(".time_slot").index($current);
|
|
|
|
var $list = $parent.next(".widget_group").find(".time_slot");
|
|
|
|
idx = Math.min(idx, $list.length - 1);
|
|
|
|
if($parent.hasClass('hour_group')) {
|
|
|
|
idx = min / 15;
|
|
|
|
} else if($parent.hasClass('minute_group')) {
|
|
|
|
idx = (ampm == "am") ? 0 : 1;
|
|
|
|
}
|
|
|
|
$list.eq(idx).triggerHandler('mouseover');
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
return this;
|
|
|
|
};
|
|
|
|
$._initializeTimepicker = function() {
|
|
|
|
var $picker = $(document.createElement('div'));
|
|
|
|
$picker.attr('id', 'time_picker').css({
|
|
|
|
position: "absolute",
|
|
|
|
display: "none"
|
|
|
|
});
|
|
|
|
var pickerHtml = "<div class='widget_group hour_group'>";
|
|
|
|
pickerHtml += "<div class='ui-widget ui-state-default time_slot'>01</div>";
|
|
|
|
pickerHtml += "<div class='ui-widget ui-state-default time_slot'>02</div>";
|
|
|
|
pickerHtml += "<div class='ui-widget ui-state-default time_slot'>03</div>";
|
|
|
|
pickerHtml += "<div class='ui-widget ui-state-default time_slot'>04</div>";
|
|
|
|
pickerHtml += "<div class='ui-widget ui-state-default time_slot'>05</div>";
|
|
|
|
pickerHtml += "<div class='ui-widget ui-state-default time_slot'>06</div>";
|
|
|
|
pickerHtml += "<div class='ui-widget ui-state-default time_slot'>07</div>";
|
|
|
|
pickerHtml += "<div class='ui-widget ui-state-default time_slot'>08</div>";
|
|
|
|
pickerHtml += "<div class='ui-widget ui-state-default time_slot'>09</div>";
|
|
|
|
pickerHtml += "<div class='ui-widget ui-state-default time_slot'>10</div>";
|
|
|
|
pickerHtml += "<div class='ui-widget ui-state-default time_slot'>11</div>";
|
|
|
|
pickerHtml += "<div class='ui-widget ui-state-default time_slot'>12</div>";
|
|
|
|
pickerHtml += "<div class='clear'></div>";
|
|
|
|
pickerHtml += "</div>";
|
|
|
|
pickerHtml += "<div class='widget_group minute_group'>";
|
|
|
|
pickerHtml += "<div class='ui-widget ui-state-default time_slot'>00</div>";
|
|
|
|
pickerHtml += "<div class='ui-widget ui-state-default time_slot'>15</div>";
|
|
|
|
pickerHtml += "<div class='ui-widget ui-state-default time_slot'>30</div>";
|
|
|
|
pickerHtml += "<div class='ui-widget ui-state-default time_slot'>45</div>";
|
|
|
|
pickerHtml += "<div class='clear'></div>";
|
|
|
|
pickerHtml += "</div>";
|
|
|
|
pickerHtml += "<div class='widget_group ampm_group'>";
|
2011-11-11 00:31:45 +08:00
|
|
|
pickerHtml += "<div class='ui-widget ui-state-default time_slot'>" + htmlEscape(I18n.t('#time.am', "am")) + "</div>";
|
|
|
|
pickerHtml += "<div class='ui-widget ui-state-default time_slot'>" + htmlEscape(I18n.t('#time.pm', "pm")) + "</div>";
|
2011-09-28 02:51:26 +08:00
|
|
|
pickerHtml += "<div class='clear'></div>";
|
|
|
|
pickerHtml += "</div>";
|
|
|
|
$picker.html(pickerHtml);
|
|
|
|
$("body").append($picker);
|
|
|
|
$picker.find(".time_slot").mouseover(function() {
|
|
|
|
$picker.find(".time_slot.ui-state-highlight").removeClass('ui-state-highlight');
|
|
|
|
$(this).addClass('ui-state-highlight');
|
|
|
|
var $field = $($picker.data('attached_to') || "none");
|
|
|
|
var time = $field.val();
|
|
|
|
var hr = 12;
|
|
|
|
var min = "00";
|
|
|
|
var ampm = "pm";
|
|
|
|
if(time && time.length >= 7) {
|
|
|
|
hr = time.substring(0, 2);
|
|
|
|
min = time.substring(3, 5);
|
|
|
|
ampm = time.substring(5, 7);
|
|
|
|
}
|
|
|
|
var val = $(this).text();
|
|
|
|
if(val > 0 && val <= 12) {
|
|
|
|
hr = val;
|
|
|
|
} else if(val == "am" || val == "pm") {
|
|
|
|
ampm = val;
|
|
|
|
} else {
|
|
|
|
min = val;
|
|
|
|
}
|
|
|
|
$field.val(hr + ":" + min + ampm);
|
|
|
|
}).mouseout(function() {
|
|
|
|
$(this).removeClass('ui-state-highlight');
|
|
|
|
}).mousedown(function(event) {
|
|
|
|
event.preventDefault();
|
|
|
|
$(this).triggerHandler('mouseover');
|
|
|
|
$(this).removeClass('ui-state-highlight').addClass('ui-state-active');
|
|
|
|
}).mouseup(function() {
|
|
|
|
$(this).removeClass('ui-state-active');
|
|
|
|
}).click(function(event) {
|
|
|
|
event.preventDefault();
|
|
|
|
$(this).triggerHandler('mouseover');
|
|
|
|
if($picker.data('attached_to')) {
|
|
|
|
$($picker.data('attached_to')).focus();
|
|
|
|
}
|
|
|
|
$picker.stop().hide().data('attached_to', null);
|
|
|
|
});
|
|
|
|
return $picker;
|
|
|
|
};
|
2014-05-14 07:48:56 +08:00
|
|
|
|
2011-11-11 00:31:45 +08:00
|
|
|
});
|