clean up $.serializeForm and make it Just Work™, fixes CNVS-7407

the initial implementation had an order-of-operations bug, causing most
disabled or un-named inputs to be serialized, as well as unchecked
checkboxes and radio buttons. radio buttons were also serialized as bools,
which makes absolutely no sense. these weird issues inspired little
patches (and regressions), but the the major underlying problems were
never really fixed, so here we are.

this commit resets $.serializeForm to a straight coffeescript port of
$.serializeArray (no underscore conversion), with just the things we need:

1. a canvas-friendly value mapper (for date pickers, files and tinymce)
2. support for non-forms

additionally, change (almost) every checkbox field in handlebars templates
to use the {{checkbox}} helper (so you get the hidden input right before
it, a la rails)

a notable side effect is that checkboxes are no longer serialized as
booleans, rather as "1" / "0" (or whatever the value is, per the html
spec). so now you can use checkboxes for non-bool scenarios (e.g. multiple
selection), which is nice. the big takeaway is you should *not* do truthy
checks on checkbox values in coffeescript moving forward if you use the
{{checkbox}} helper, since "0" is truthy.

test plan:
1. run specs
2. regression test of checkbox functionality in the following places:
   * gradebook2 dialogs w/ checkboxes, specifically:
     * group weights dialog
     * curve grades dialog
     * submission details
   * create/edit assignment (lots of checkboxes)
     * don't forget turnitin settings
   * create/edit appointment group (scheduler)
   * edit timeslot (scheduler)
   * edit calendar event (specifically section-level dates)
   * create/edit conference
   * conversations (group convo / faculty journal options)
   * add course users dialog (limit-to-section option)
   * discussion settings dialog (index page)
   * create/edit discussion topic (various options)
   * notification preferences (just a couple checkboxes)
3. regression of radio button functionality in the following places:
   * content migrations
   * delete assignment group dialog

Change-Id: Ifa5ef3cea954ca260a899da9fa426f8f833472f8
Reviewed-on: https://gerrit.instructure.com/23096
Tested-by: Jenkins <jenkins@instructure.com>
Product-Review: Marc LeGendre <marc@instructure.com>
QA-Review: Marc LeGendre <marc@instructure.com>
Reviewed-by: Landon Wilkins <lwilkins@instructure.com>
Reviewed-by: Ryan Florence <ryanf@instructure.com>
This commit is contained in:
Jon Jensen 2013-08-06 16:42:42 -06:00
parent 9f93efbdd8
commit c25df1cc50
41 changed files with 305 additions and 327 deletions

View File

@ -20,7 +20,10 @@ define [
$(selector).html editAppointmentGroupTemplate({ $(selector).html editAppointmentGroupTemplate({
title: @apptGroup.title title: @apptGroup.title
contexts: @contexts contexts: @contexts
appointment_group: @apptGroup appointment_group: _.extend(
{use_group_signup: @apptGroup.participant_type is 'Group'}
@apptGroup
)
}) })
@contextsHash = {} @contextsHash = {}
@ -68,7 +71,7 @@ define [
@form.find(".group-signup").toggle(checked) @form.find(".group-signup").toggle(checked)
@form.find(".group-signup-checkbox").change() @form.find(".group-signup-checkbox").change()
$perSlotCheckbox = @form.find('[name="per_slot_option"]') $perSlotCheckbox = @form.find('#appointment-blocks-per-slot-option-button')
$perSlotInput = @form.find('[name="participants_per_appointment"]') $perSlotInput = @form.find('[name="participants_per_appointment"]')
slotChangeHandler = (e) => @perSlotChange($perSlotCheckbox, $perSlotInput) slotChangeHandler = (e) => @perSlotChange($perSlotCheckbox, $perSlotInput)
$.merge($perSlotCheckbox, $perSlotInput).on 'change', slotChangeHandler $.merge($perSlotCheckbox, $perSlotInput).on 'change', slotChangeHandler
@ -149,7 +152,7 @@ define [
'appointment_group[location_name]': data.location 'appointment_group[location_name]': data.location
} }
if data.max_appointments_per_participant_option if data.max_appointments_per_participant_option is '1'
if data.max_appointments_per_participant < 1 if data.max_appointments_per_participant < 1
$('[name="max_appointments_per_participant"]').errorBox( $('[name="max_appointments_per_participant"]').errorBox(
I18n.t('bad_max_appts', 'You must allow at least one appointment per participant')) I18n.t('bad_max_appts', 'You must allow at least one appointment per participant'))
@ -167,7 +170,7 @@ define [
$.dateToISO8601UTC($.unfudgeDateForProfileTimezone(range[1])) $.dateToISO8601UTC($.unfudgeDateForProfileTimezone(range[1]))
]) ])
if data.per_slot_option if data.per_slot_option is '1'
if data.participants_per_appointment < 1 if data.participants_per_appointment < 1
$('[name="participants_per_appointment"]').errorBox( $('[name="participants_per_appointment"]').errorBox(
I18n.t('bad_per_slot', 'You must allow at least one appointment per time slot')) I18n.t('bad_per_slot', 'You must allow at least one appointment per time slot'))

View File

@ -9,7 +9,7 @@ define [
.html(editApptCalendarEventTemplate(@event)) .html(editApptCalendarEventTemplate(@event))
.appendTo('body') .appendTo('body')
$maxParticipantsOption = @form.find('[name=max_participants_option]') $maxParticipantsOption = @form.find('[type=checkbox][name=max_participants_option]')
@$maxParticipants = @form.find('[name=max_participants]') @$maxParticipants = @form.find('[name=max_participants]')
$maxParticipantsOption.change => $maxParticipantsOption.change =>
@ -36,7 +36,7 @@ define [
save: => save: =>
formData = @dialog.getFormData() formData = @dialog.getFormData()
limit_participants = formData.max_participants_option == "on" limit_participants = formData.max_participants_option == "1"
max_participants = formData.max_participants max_participants = formData.max_participants
if limit_participants and max_participants <= 0 if limit_participants and max_participants <= 0

View File

@ -21,7 +21,7 @@ define [
events: events:
'submit form': 'submit' 'submit form': 'submit'
'change [name="use_section_dates"]': 'toggleUseSectionDates' 'change #use_section_dates': 'toggleUseSectionDates'
'click .delete_link': 'destroyModel' 'click .delete_link': 'destroyModel'
'click .switch_event_description_view': 'toggleHtmlView' 'click .switch_event_description_view': 'toggleHtmlView'
@ -75,12 +75,11 @@ define [
submit: (event) -> submit: (event) ->
event?.preventDefault() event?.preventDefault()
eventData = unflatten @$el.getFormData() eventData = unflatten @$el.getFormData()
# force use_section_dates to boolean, so it doesnt cause 'change' if it is '1' eventData.use_section_dates = eventData.use_section_dates is '1'
eventData.use_section_dates = !!eventData.use_section_dates
_.each [eventData].concat(eventData.child_event_data), @setStartEnd _.each [eventData].concat(eventData.child_event_data), @setStartEnd
delete eventData.child_event_data if eventData.remove_child_events == '1' delete eventData.child_event_data if eventData.remove_child_events == '1'
if $('[name=use_section_dates]').prop('checked') if $('#use_section_dates').prop('checked')
dialog = new MissingDateDialogView dialog = new MissingDateDialogView
validationFn: -> validationFn: ->
$fields = $('[name*=start_date]:visible').filter -> $(this).val() is '' $fields = $('[name*=start_date]:visible').filter -> $(this).val() is ''

View File

@ -128,7 +128,7 @@ define [
for key, enabled of options for key, enabled of options
$node = @$form.find(".#{key}_info") $node = @$form.find(".#{key}_info")
$node.showIf(enabled) $node.showIf(enabled)
$node.find("input[name=#{key}]").prop('checked', false) unless enabled $node.find("input[type=checkbox][name=#{key}]").prop('checked', false) unless enabled
toggle: (state) -> toggle: (state) ->
@$form[if state then 'addClass' else 'removeClass']('disabled') @$form[if state then 'addClass' else 'removeClass']('disabled')

View File

@ -245,9 +245,14 @@ define [
# checked="true" # checked="true"
# name="likes[tacos]" # name="likes[tacos]"
# class="foo bar" > # class="foo bar" >
checkbox : (propertyName, {hash}) -> checkbox: (propertyName, {hash}) ->
splitPropertyName = propertyName.split(/\./) splitPropertyName = propertyName.split(/\./)
snakeCase = splitPropertyName.join('_') snakeCase = splitPropertyName.join('_')
if hash.prefix
splitPropertyName.unshift hash.prefix
delete hash.prefix
bracketNotation = splitPropertyName[0] + _.chain(splitPropertyName) bracketNotation = splitPropertyName[0] + _.chain(splitPropertyName)
.rest() .rest()
.map((prop) -> "[#{prop}]") .map((prop) -> "[#{prop}]")
@ -260,11 +265,19 @@ define [
name: bracketNotation name: bracketNotation
, hash , hash
unless inputProps.checked unless inputProps.checked?
value = _.reduce splitPropertyName, ((memo, key) -> memo[key]), this value = _.reduce(splitPropertyName, ((memo, key) -> memo[key] if memo?), this)
inputProps.checked = true if value inputProps.checked = true if value
attributes = _.map inputProps, (val, key) -> "#{htmlEscape key}=\"#{htmlEscape val}\"" for prop in ['checked', 'disabled']
if inputProps[prop]
inputProps[prop] = prop
else
delete inputProps[prop]
attributes = for key, val of inputProps when val?
"#{htmlEscape key}=\"#{htmlEscape val}\""
new Handlebars.SafeString """ new Handlebars.SafeString """
<input name="#{htmlEscape inputProps.name}" type="hidden" value="0" /> <input name="#{htmlEscape inputProps.name}" type="hidden" value="0" />
<input #{attributes.join ' '} /> <input #{attributes.join ' '} />

View File

@ -1,52 +1,58 @@
define [ define ['jquery'], ($) ->
'jquery'
'underscore' rselectTextarea = /^(?:select|textarea)/i
], ($, _) -> rCRLF = /\r?\n/g
rinput = /^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week|file)$/i
# radio / checkbox are not included, since they are handled by the @checked check
elements = ->
if @elements
$.makeArray @elements
else
elements = $(this).find(':input')
if elements.length
elements
else
this
isSerializable = ->
@name and not @disabled and (
@checked or
rselectTextarea.test(@nodeName) or
rinput.test(@type)
)
resultFor = (name, value) ->
value = value.replace(rCRLF, "\r\n") if typeof value is 'string'
{name, value}
getValue = ->
$input = $(this)
value = if @type == 'file'
this if $input.val()
else if $input.hasClass 'datetime_field_enabled'
# datepicker doesn't clear the data date attribute when a date is deleted
if $input.val() is ""
null
else
$input.data('date') or null
else if $input.data('rich_text')
$input.editorBox('get_code', false)
else
$input.val()
if $.isArray(value)
resultFor(@name, val) for val in value
else
resultFor(@name, value)
##
# identical to $.fn.serializeArray, except:
# 1. it works on non-forms (see elements)
# 2. it handles file, date picker and tinymce inputs (see getValue)
$.fn.serializeForm = -> $.fn.serializeForm = ->
rselectTextarea = /^(?:select|textarea)/i @map(elements)
rcheckboxOrRadio = /checkbox|radio/i .filter(isSerializable)
rCRLF = /\r?\n/g
rinput = /^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week|checkbox|radio|file)$/i
isInput = (el) ->
el.name && !el.disabled && rselectTextarea.test(el.nodeName) or rinput.test(el.type)
if this.is('[serialize-radio-value]')
rcheckboxOrRadio = /checkbox/i # return val for radio boxes
rRadio = /radio/i
_isInput = isInput
isInput = (el) -> # only include the checked radio input
_isInput(el) && (!rRadio.test(el.type) || el.checked)
getValue = (el) ->
resultFor = (val) ->
name: el.name
el: el
value: if _.isString(val) then val.replace( rCRLF, "\r\n" ) else val
$input = $(el)
val = if rcheckboxOrRadio.test(el.type)
el.checked
else if el.type == 'file'
el if $input.val()
else if $input.hasClass 'datetime_field_enabled'
# datepicker doesn't clear the data date attribute when a date is deleted
if $input.val() == ""
null
else
$input.data('date') || null
else if $input.data('rich_text')
$input.editorBox('get_code', false)
else
$input.val()
if _.isArray val
_.map val, resultFor
else
resultFor val
_.chain(this[0].elements || this.find(':input'))
.filter(isInput)
.map(getValue) .map(getValue)
.value() .get()

View File

@ -55,7 +55,8 @@ htmlEscape, DiscussionTopic, Announcement, Assignment, $, preventDefault, Missin
isAnnouncement: => @model.constructor is Announcement isAnnouncement: => @model.constructor is Announcement
toJSON: -> toJSON: ->
json = _.extend super, @options, data = super
json = _.extend data, @options,
showAssignment: !!@assignmentGroupCollection showAssignment: !!@assignmentGroupCollection
useForGrading: @model.get('assignment')? useForGrading: @model.get('assignment')?
isTopic: @isTopic() isTopic: @isTopic()
@ -64,6 +65,7 @@ htmlEscape, DiscussionTopic, Announcement, Assignment, $, preventDefault, Missin
canAttach: @permissions.CAN_ATTACH canAttach: @permissions.CAN_ATTACH
canModerate: @permissions.CAN_MODERATE canModerate: @permissions.CAN_MODERATE
isLargeRoster: ENV?.IS_LARGE_ROSTER || false isLargeRoster: ENV?.IS_LARGE_ROSTER || false
threaded: data.discussion_type is "threaded"
json.assignment = json.assignment.toView() json.assignment = json.assignment.toView()
json json
@ -130,14 +132,14 @@ htmlEscape, DiscussionTopic, Announcement, Assignment, $, preventDefault, Missin
getFormData: -> getFormData: ->
data = super data = super
data.title ||= I18n.t 'default_discussion_title', 'No Title' data.title ||= I18n.t 'default_discussion_title', 'No Title'
data.discussion_type = if data.threaded then 'threaded' else 'side_comment' data.discussion_type = if data.threaded is '1' then 'threaded' else 'side_comment'
data.podcast_has_student_posts = false unless data.podcast_enabled data.podcast_has_student_posts = false unless data.podcast_enabled is '1'
assign_data = data.assignment assign_data = data.assignment
delete data.assignment delete data.assignment
if assign_data?.set_assignment if assign_data?.set_assignment is '1'
data.set_assignment = true data.set_assignment = '1'
data.assignment = @updateAssignment(assign_data) data.assignment = @updateAssignment(assign_data)
data.delayed_post_at = '' data.delayed_post_at = ''
data.lock_at = '' data.lock_at = ''
@ -146,12 +148,9 @@ htmlEscape, DiscussionTopic, Announcement, Assignment, $, preventDefault, Missin
# DiscussionTopics get a model created for them in their # DiscussionTopics get a model created for them in their
# constructor. Delete it so the API doesn't automatically # constructor. Delete it so the API doesn't automatically
# create assignments unless the user checked "Use for Grading". # create assignments unless the user checked "Use for Grading".
# We're doing this here because syncWithMultipart doesn't call
# the model's toJSON method unfortunately, so assignment params
# would be sent in the response, creating an assignment.
# The controller checks for set_assignment on the assignment model, # The controller checks for set_assignment on the assignment model,
# so we can't make it undefined here for the case of discussion topics. # so we can't make it undefined here for the case of discussion topics.
data.assignment = {set_assignment: false} data.assignment = {set_assignment: '0'}
# these options get passed to Backbone.sync in ValidatedFormView # these options get passed to Backbone.sync in ValidatedFormView
@saveOpts = multipart: !!data.attachment, proxyAttachment: true @saveOpts = multipart: !!data.attachment, proxyAttachment: true
@ -203,7 +202,7 @@ htmlEscape, DiscussionTopic, Announcement, Assignment, $, preventDefault, Missin
) )
validateBeforeSave: (data, errors) => validateBeforeSave: (data, errors) =>
if @isTopic() && data.set_assignment if @isTopic() && data.set_assignment is '1'
if @assignmentGroupSelector? if @assignmentGroupSelector?
errors = @assignmentGroupSelector.validateBeforeSave(data, errors) errors = @assignmentGroupSelector.validateBeforeSave(data, errors)
unless ENV?.IS_LARGE_ROSTER unless ENV?.IS_LARGE_ROSTER

View File

@ -35,11 +35,12 @@ AssignmentGroupSelector, GroupCategorySelector, toggleAccessibly) ->
SUBMISSION_TYPE = '[name="submission_type"]' SUBMISSION_TYPE = '[name="submission_type"]'
ONLINE_SUBMISSION_TYPES = '#assignment_online_submission_types' ONLINE_SUBMISSION_TYPES = '#assignment_online_submission_types'
NAME = '[name="name"]' NAME = '[name="name"]'
ALLOW_FILE_UPLOADS = '[name="online_submission_types[online_upload]"]' ALLOW_FILE_UPLOADS = '#assignment_online_upload'
RESTRICT_FILE_UPLOADS = '#restrict_file_extensions_container' RESTRICT_FILE_UPLOADS = '#assignment_restrict_file_extensions'
RESTRICT_FILE_UPLOADS_OPTIONS = '#restrict_file_extensions_container'
ALLOWED_EXTENSIONS = '#allowed_extensions_container' ALLOWED_EXTENSIONS = '#allowed_extensions_container'
ADVANCED_ASSIGNMENT_OPTIONS = '#advanced_assignment_options' ADVANCED_ASSIGNMENT_OPTIONS = '#advanced_assignment_options'
TURNITIN_ENABLED = '[name="turnitin_enabled"]' TURNITIN_ENABLED = '#assignment_turnitin_enabled'
ADVANCED_TURNITIN_SETTINGS = '#advanced_turnitin_settings_link' ADVANCED_TURNITIN_SETTINGS = '#advanced_turnitin_settings_link'
ASSIGNMENT_TOGGLE_ADVANCED_OPTIONS = '#assignment_toggle_advanced_options' ASSIGNMENT_TOGGLE_ADVANCED_OPTIONS = '#assignment_toggle_advanced_options'
GRADING_TYPE_SELECTOR = '#grading_type_selector' GRADING_TYPE_SELECTOR = '#grading_type_selector'
@ -61,6 +62,7 @@ AssignmentGroupSelector, GroupCategorySelector, toggleAccessibly) ->
els["#{NAME}"] = '$name' els["#{NAME}"] = '$name'
els["#{ALLOW_FILE_UPLOADS}"] = '$allowFileUploads' els["#{ALLOW_FILE_UPLOADS}"] = '$allowFileUploads'
els["#{RESTRICT_FILE_UPLOADS}"] = '$restrictFileUploads' els["#{RESTRICT_FILE_UPLOADS}"] = '$restrictFileUploads'
els["#{RESTRICT_FILE_UPLOADS_OPTIONS}"] = '$restrictFileUploadsOptions'
els["#{ALLOWED_EXTENSIONS}"] = '$allowedExtensions' els["#{ALLOWED_EXTENSIONS}"] = '$allowedExtensions'
els["#{ADVANCED_ASSIGNMENT_OPTIONS}"] = '$advancedAssignmentOptions' els["#{ADVANCED_ASSIGNMENT_OPTIONS}"] = '$advancedAssignmentOptions'
els["#{TURNITIN_ENABLED}"] = '$turnitinEnabled' els["#{TURNITIN_ENABLED}"] = '$turnitinEnabled'
@ -142,14 +144,14 @@ AssignmentGroupSelector, GroupCategorySelector, toggleAccessibly) ->
@$externalToolsNewTab.prop('checked', data['item[new_tab]'] == '1') @$externalToolsNewTab.prop('checked', data['item[new_tab]'] == '1')
toggleRestrictFileUploads: => toggleRestrictFileUploads: =>
@$restrictFileUploads.toggleAccessibly @$allowFileUploads.prop('checked') @$restrictFileUploadsOptions.toggleAccessibly @$allowFileUploads.prop('checked')
toggleAdvancedTurnitinSettings: (ev) => toggleAdvancedTurnitinSettings: (ev) =>
ev.preventDefault() ev.preventDefault()
@$advancedTurnitinSettings.toggleAccessibly @$turnitinEnabled.prop('checked') @$advancedTurnitinSettings.toggleAccessibly @$turnitinEnabled.prop('checked')
handleRestrictFileUploadsChange: => handleRestrictFileUploadsChange: =>
@$allowedExtensions.toggleAccessibly @$restrictFileUploads.find('input').prop('checked') @$allowedExtensions.toggleAccessibly @$restrictFileUploads.prop('checked')
handleGradingTypeChange: (gradingType) => handleGradingTypeChange: (gradingType) =>
@$gradedAssignmentFields.toggleAccessibly gradingType != 'not_graded' @$gradedAssignmentFields.toggleAccessibly gradingType != 'not_graded'
@ -169,9 +171,11 @@ AssignmentGroupSelector, GroupCategorySelector, toggleAccessibly) ->
this this
toJSON: => toJSON: =>
_.extend @assignment.toView(), data = @assignment.toView()
_.extend data,
kalturaEnabled: ENV?.KALTURA_ENABLED || false kalturaEnabled: ENV?.KALTURA_ENABLED || false
isLargeRoster: ENV?.IS_LARGE_ROSTER || false isLargeRoster: ENV?.IS_LARGE_ROSTER || false
submissionTypesFrozen: _.include(data.frozenAttributes, 'submission_types')
_attachEditorToDescription: => _attachEditorToDescription: =>
@$description.editorBox() @$description.editorBox()
@ -229,7 +233,7 @@ AssignmentGroupSelector, GroupCategorySelector, toggleAccessibly) ->
assignmentData.submission_types = ['not_graded'] assignmentData.submission_types = ['not_graded']
else if assignmentData.submission_type == 'online' else if assignmentData.submission_type == 'online'
types = _.select _.keys(assignmentData.online_submission_types), (k) -> types = _.select _.keys(assignmentData.online_submission_types), (k) ->
assignmentData.online_submission_types[k] assignmentData.online_submission_types[k] is '1'
assignmentData.submission_types = types assignmentData.submission_types = types
else else
assignmentData.submission_types = [assignmentData.submission_type] assignmentData.submission_types = [assignmentData.submission_type]
@ -240,7 +244,7 @@ AssignmentGroupSelector, GroupCategorySelector, toggleAccessibly) ->
_filterAllowedExtensions: (data) => _filterAllowedExtensions: (data) =>
restrictFileExtensions = data.restrict_file_extensions restrictFileExtensions = data.restrict_file_extensions
delete data.restrict_file_extensions delete data.restrict_file_extensions
if restrictFileExtensions if restrictFileExtensions is '1'
data.allowed_extensions = _.select data.allowed_extensions.split(","), (ext) -> data.allowed_extensions = _.select data.allowed_extensions.split(","), (ext) ->
$.trim(ext.toString()).length > 0 $.trim(ext.toString()).length > 0
else else

View File

@ -51,16 +51,20 @@ define [
@showGroupCategoryCreateDialog() @showGroupCategoryCreateDialog()
toJSON: => toJSON: =>
frozenAttributes = @parentModel.frozenAttributes()
groupCategoryId: @parentModel.groupCategoryId() groupCategoryId: @parentModel.groupCategoryId()
groupCategories: @groupCategories groupCategories: @groupCategories
gradeGroupStudentsIndividually: @parentModel.gradeGroupStudentsIndividually() gradeGroupStudentsIndividually: @parentModel.gradeGroupStudentsIndividually()
frozenAttributes: @parentModel.frozenAttributes() frozenAttributes: frozenAttributes
groupCategoryIdFrozen: _.include(frozenAttributes, 'group_category_id')
nested: @nested nested: @nested
prefix: 'assignment' if @nested
filterFormData: (data) => filterFormData: (data) =>
hasGroupCategory = data.has_group_category hasGroupCategory = data.has_group_category
delete data.has_group_category delete data.has_group_category
unless hasGroupCategory unless hasGroupCategory is '1'
data.group_category_id = null data.group_category_id = null
data.grade_group_students_individually = false data.grade_group_students_individually = false
data data

View File

@ -46,9 +46,13 @@ define [
@$peerReviewsAssignAt.datetime_field() @$peerReviewsAssignAt.datetime_field()
toJSON: => toJSON: =>
frozenAttributes = @parentModel.frozenAttributes()
peerReviews: @parentModel.peerReviews() peerReviews: @parentModel.peerReviews()
automaticPeerReviews: @parentModel.automaticPeerReviews() automaticPeerReviews: @parentModel.automaticPeerReviews()
peerReviewCount: @parentModel.peerReviewCount() peerReviewCount: @parentModel.peerReviewCount()
peerReviewsAssignAt: @parentModel.peerReviewsAssignAt() peerReviewsAssignAt: @parentModel.peerReviewsAssignAt()
frozenAttributes: @parentModel.frozenAttributes() frozenAttributes: frozenAttributes
peerReviewsFrozen: _.include(frozenAttributes, 'peer_reviews')
nested: @nested nested: @nested
prefix: 'assignment' if @nested

View File

@ -11,7 +11,7 @@ define [
tagName: 'div' tagName: 'div'
EXCLUDE_SMALL_MATCHES_OPTIONS = '.js-exclude-small-matches-options' EXCLUDE_SMALL_MATCHES_OPTIONS = '.js-exclude-small-matches-options'
EXCLUDE_SMALL_MATCHES = '[name="exclude_small_matches"]' EXCLUDE_SMALL_MATCHES = '#exclude_small_matches'
EXCLUDE_SMALL_MATCHES_TYPE = '[name="exclude_small_matches_type"]' EXCLUDE_SMALL_MATCHES_TYPE = '[name="exclude_small_matches_type"]'
events: do -> events: do ->

View File

@ -16,7 +16,7 @@ define [
events: events:
'change #courseSelect' : 'updateSearch' 'change #courseSelect' : 'updateSearch'
'change [name=include_completed_courses]' : 'toggleConcludedCourses' 'change #include_completed_courses' : 'toggleConcludedCourses'
render: -> render: ->
super super

View File

@ -366,5 +366,5 @@ define [
# for key, enabled of options # for key, enabled of options
# $node = @$form.find(".#{key}_info") # $node = @$form.find(".#{key}_info")
# $node.showIf(enabled) # $node.showIf(enabled)
# $node.find("input[name=#{key}]").prop('checked', false) unless enabled # $node.find("input[type=checkbox][name=#{key}]").prop('checked', false) unless enabled
# #

View File

@ -801,7 +801,7 @@ class ConversationsController < ApplicationController
:forwarded_message_ids => params[:forwarded_message_ids], :forwarded_message_ids => params[:forwarded_message_ids],
:root_account_id => @domain_root_account.id, :root_account_id => @domain_root_account.id,
:media_comment => infer_media_comment, :media_comment => infer_media_comment,
:generate_user_note => params[:user_note] :generate_user_note => value_to_boolean(params[:user_note])
) )
end end

View File

@ -7,5 +7,5 @@
jammit_css :content_migrations jammit_css :content_migrations
%> %>
<form id="migrationConverterContainer" class="form-horizontal" serialize-radio-value></form> <form id="migrationConverterContainer" class="form-horizontal"></form>
<div id="progress" class="span10"></div> <div id="progress" class="span10"></div>

View File

@ -1,6 +1,6 @@
<div title="{{#t "titles.assignment_group_weights"}}Manage assignment group weighting{{/t}}" style="display:none;" id="assignment_group_weights_dialog"> <div title="{{#t "titles.assignment_group_weights"}}Manage assignment group weighting{{/t}}" style="display:none;" id="assignment_group_weights_dialog">
<p style="margin-top: 8px;"> <p style="margin-top: 8px;">
<input type="checkbox" id="group_weighting_scheme" name="group_weighting_scheme"/> {{checkbox "group_weighting_scheme"}}
<label for="group_weighting_scheme">{{#t "weight_final"}}Weight final grade based on groups{{/t}}</label> <label for="group_weighting_scheme">{{#t "weight_final"}}Weight final grade based on groups{{/t}}</label>
</p> </p>
<table> <table>

View File

@ -22,7 +22,7 @@
{{/if}} {{/if}}
</p> </p>
<p> <p>
<input type="checkbox" name="assign_blanks" id="assign_blanks"/> {{checkbox "assign_blanks"}}
<label for="assign_blanks">{{#t "labels.assign_blanks"}}Assign zeroes to unsubmitted students{{/t}}</label> <label for="assign_blanks">{{#t "labels.assign_blanks"}}Assign zeroes to unsubmitted students{{/t}}</label>
</p> </p>
<div class="alert alert-danger"> <div class="alert alert-danger">

View File

@ -49,22 +49,17 @@
<div class="controls"> <div class="controls">
{{#if isTopic}} {{#if isTopic}}
<label class="checkbox"> <label class="checkbox">
<input name="threaded" type="hidden" value="0" /> {{checkbox "threaded"}}
<input type="checkbox"
{{#ifEqual discussion_type "threaded"}}checked{{/ifEqual}}
name="threaded">
{{#t "allow_threaded_replies"}}Allow threaded replies{{/t}} {{#t "allow_threaded_replies"}}Allow threaded replies{{/t}}
</label> </label>
{{/if}} {{/if}}
{{#if contextIsCourse}} {{#if contextIsCourse}}
{{#if isAnnouncement}} {{#if isAnnouncement}}
<label class="checkbox"> <label class="checkbox">
<input name="delay_posting" type="hidden" value="0" /> {{checkbox "delay_posting"
<input type="checkbox" checked=delayed_post_at
{{#if delayed_post_at}}checked{{/if}} class="element_toggler"
name="delay_posting" aria-controls="discussion_topic_delay_post_container"}}
class="element_toggler"
aria-controls="discussion_topic_delay_post_container">
{{#t "delay_posting"}}Delay posting{{/t}} {{#t "delay_posting"}}Delay posting{{/t}}
</label> </label>
<label id="discussion_topic_delay_post_container" <label id="discussion_topic_delay_post_container"
@ -85,12 +80,10 @@
{{/if}} {{/if}}
{{#if canModerate}} {{#if canModerate}}
<label class="checkbox"> <label class="checkbox">
<input name="podcast_enabled" type="hidden" value="0" /> {{checkbox "podcast_enabled"
<input type="checkbox" checked=podcast_url
{{#if podcast_url}}checked{{/if}} class="element_toggler"
name="podcast_enabled" aria-controls="podcast_has_student_posts_container"}}
class="element_toggler"
aria-controls="podcast_has_student_posts_container">
{{#t "enable_podcast_feed"}}Enable podcast feed{{/t}} {{#t "enable_podcast_feed"}}Enable podcast feed{{/t}}
</label> </label>
@ -103,14 +96,11 @@
{{/if}} {{/if}}
{{#if showAssignment}} {{#if showAssignment}}
<label class="checkbox"> <label class="checkbox">
<input name="assignment[set_assignment]" type="hidden" value="0" /> {{checkbox "assignment.set_assignment"
<input type="checkbox" id="use_for_grading"
id="use_for_grading" class="element_toggler"
class="element_toggler" aria-controls="assignment_options"
aria-controls="assignment_options" checked=set_assignment}}
name="assignment[set_assignment]"
{{checkedIf set_assignment}}
value="1">
{{#t "use_for_grading"}}Graded{{/t}} {{#t "use_for_grading"}}Graded{{/t}}
</label> </label>
{{/if}} {{/if}}

View File

@ -65,7 +65,7 @@
<textarea id="add_a_comment" name="comment[text_comment]"></textarea> <textarea id="add_a_comment" name="comment[text_comment]"></textarea>
{{#if assignment.group_category_id}} {{#if assignment.group_category_id}}
<span id="group-comment-container"> <span id="group-comment-container">
<input type="checkbox" id="group_comment" name="comment[group_comment]" /> {{checkbox "comment.group_comment" id="group_comment"}}
<label for="group_comment">{{#t "labels.group_comment"}}Send Comment to the Whole Group{{/t}}</label> <label for="group_comment">{{#t "labels.group_comment"}}Send Comment to the Whole Group{{/t}}</label>
</span> </span>
{{/if}} {{/if}}

View File

@ -80,6 +80,6 @@
{{#if ENV.PERMISSIONS.manage}} {{#if ENV.PERMISSIONS.manage}}
<form data-view="createAssignment" class="form-dialog"></form> <form data-view="createAssignment" class="form-dialog"></form>
<form data-view="editAssignmentGroup" class="form-dialog"></form> <form data-view="editAssignmentGroup" class="form-dialog"></form>
<form data-view="deleteAssignmentGroup" class="form-dialog" serialize-radio-value></form> <form data-view="deleteAssignmentGroup" class="form-dialog"></form>
{{/if}} {{/if}}
</div> </div>

View File

@ -1,7 +1,7 @@
<div class="form-dialog-content"> <div class="form-dialog-content">
<div class="form-horizontal"> <div class="form-horizontal">
<label class="checkbox" id="weight-groups" > <label class="checkbox" id="weight-groups" >
<input type="checkbox" id="apply_assignment_group_weights" name="apply_assignment_group_weights" {{#if apply_assignment_group_weights}}checked="checked"{{/if}} /> {{checkbox "apply_assignment_group_weights"}}
{{#t "weight_groups"}}Weight final grade based on assignment groups{{/t}} {{#t "weight_groups"}}Weight final grade based on assignment groups{{/t}}
</label> </label>

View File

@ -120,10 +120,9 @@
<fieldset> <fieldset>
<div class="control-group controls"> <div class="control-group controls">
<label class="checkbox"> <label class="checkbox">
<input id="assignment_freeze_on_copy" {{checkbox "freezeOnCopy"
name="freeze_on_copy" id="assignment_freeze_on_copy"
{{checkedIf freezeOnCopy}} name="freeze_on_copy"}}
type="checkbox"/>
{{#t "freeze_properties"}}Lock assignment properties when copied{{/t}} {{#t "freeze_properties"}}Lock assignment properties when copied{{/t}}
</label> </label>
</div> </div>
@ -138,10 +137,9 @@
<div style="float: left; min-width: 300px;"> <div style="float: left; min-width: 300px;">
<label class="checkbox" style="text-align:left;"> <label class="checkbox" style="text-align:left;">
<input id="assignment_notify_of_update" {{checkbox "notifyOfUpdate"
name="notify_of_update" id="assignment_notify_of_update"
{{checkedIf notifyOfUpdate}} name="notify_of_update"}}
type="checkbox"/>
{{#t "notify_content_change"}}Notify users that this content has changed{{/t}} {{#t "notify_content_change"}}Notify users that this content has changed{{/t}}
</label> </label>
</div> </div>

View File

@ -1,10 +1,10 @@
<div class="controls"> <div class="controls">
<label class="checkbox"> <label class="checkbox">
<input id="assignment_has_group_category" {{checkbox "has_group_category"
name="{{#if nested}}assignment[has_group_category]{{else}}has_group_category{{/if}}" id="assignment_has_group_category"
type="checkbox" prefix=prefix
{{checkedIf groupCategoryId}} checked=groupCategoryId
{{disabledIfIncludes frozenAttributes "group_category_id"}}/> disabled=groupCategoryIdFrozen}}
{{#t "is_group_assignment"}}This is a Group Assignment{{/t}} {{#t "is_group_assignment"}}This is a Group Assignment{{/t}}
</label> </label>
</div> </div>
@ -13,10 +13,11 @@
<div class="controls"> <div class="controls">
<label class="checkbox" > <label class="checkbox" >
<input name="{{#if nested}}assignment[grade_group_students_individually]{{else}}grade_group_students_individually{{/if}}" {{checkbox "grade_group_students_individually"
type="checkbox" id=null
{{checkedIf gradeGroupStudentsIndividually}} prefix=prefix
{{disabledIfIncludes frozenAttributes "group_category_id"}}/> checked=gradeGroupStudentsIndividually
disabled=groupCategoryIdFrozen}}
{{#t "grade_group_students_individually"}} {{#t "grade_group_students_individually"}}
Assign Grades to Each Student Individually Assign Grades to Each Student Individually
{{/t}} {{/t}}

View File

@ -1,11 +1,11 @@
<div class="controls"> <div class="controls">
<label class="checkbox" for="assignment_peer_reviews"> <label class="checkbox" for="assignment_peer_reviews">
<input id="assignment_peer_reviews" {{checkbox "peer_reviews"
name="{{#if nested}}assignment[peer_reviews]{{else}}peer_reviews{{/if}}" id="assignment_peer_reviews"
type="checkbox" prefix=prefix
checked=peerReviews
aria-controls="peer_reviews_details" aria-controls="peer_reviews_details"
{{checkedIf peerReviews}} disabled=peerReviewsFrozen}}
{{disabledIfIncludes frozenAttributes "peer_reviews"}}/>
{{#t "labels.require_peer_reviews"}}Require Peer Reviews{{/t}} {{#t "labels.require_peer_reviews"}}Require Peer Reviews{{/t}}
</label> </label>
</div> </div>

View File

@ -46,37 +46,28 @@
<div class="control-group"> <div class="control-group">
<div class="controls"> <div class="controls">
<label class="checkbox"> <label class="checkbox">
<input id="s_paper_check" {{checkbox "s_paper_check" checked=sPaperCheck}}
name="s_paper_check" {{#t "turnitin_settings.labels.student_paper_check"}}
{{checkedIf sPaperCheck}} Other Student Papers
type="checkbox"/> {{/t}}
{{#t "turnitin_settings.labels.student_paper_check"}}
Other Student Papers
{{/t}}
</label> </label>
</div> </div>
<div class="controls"> <div class="controls">
<label class="checkbox"> <label class="checkbox">
<input id="internet_check" {{checkbox "internet_check" checked=internetCheck}}
name="internet_check" {{#t "turnitin_settings.labels.internet_check"}}
{{checkedIf internetCheck}} Internet Database
type="checkbox"/> {{/t}}
{{#t "turnitin_settings.labels.internet_check"}}
Internet Database
{{/t}}
</label> </label>
</div> </div>
<div class="controls"> <div class="controls">
<label class="checkbox"> <label class="checkbox">
<input id="journal_check" {{checkbox "journal_check" checked=journalCheck}}
name="journal_check" {{#t "turnitin_settings.labels.journal_check"}}
type="checkbox" Journals, Periodicals, and Publications
{{checkedIf journalCheck}}/> {{/t}}
{{#t "turnitin_settings.labels.journal_check"}}
Journals, Periodicals, and Publications
{{/t}}
</label> </label>
</div> </div>
</div> </div>
@ -91,36 +82,27 @@
<div class="control-group"> <div class="control-group">
<div class="controls"> <div class="controls">
<label class="checkbox"> <label class="checkbox">
<input id="exclude_biblio" {{checkbox "exclude_biblio" checked=excludeBiblio}}
name="exclude_biblio" {{#t "turnitin_settings.labels.exclude_biblio"}}
type="checkbox" Bibliographic Material
{{checkedIf excludeBiblio}}/> {{/t}}
{{#t "turnitin_settings.labels.exclude_biblio"}}
Bibliographic Material
{{/t}}
</label> </label>
</div> </div>
<div class="controls"> <div class="controls">
<label class="checkbox"> <label class="checkbox">
<input id="exclude_quoted" {{checkbox "exclude_quoted" checked=excludeQuoted}}
name="exclude_quoted" {{#t "turnitin_settings.labels.exclude_quoted"}}
type="checkbox" Quoted Material
{{checkedIf excludeQuoted}}/> {{/t}}
{{#t "turnitin_settings.labels.exclude_quoted"}}
Quoted Material
{{/t}}
</label> </label>
</div> </div>
<div class="controls"> <div class="controls">
<label class="checkbox"> <label class="checkbox">
<input id="exclude_small_matches" {{checkbox "exclude_small_matches" checked=excludesSmallMatches}}
name="exclude_small_matches" {{#t "assignments.turnitin_settings.labels.exclude_small_matches"}}
type="checkbox" Small Matches
{{checkedIf excludesSmallMatches}}/> {{/t}}
{{#t "assignments.turnitin_settings.labels.exclude_small_matches"}}
Small Matches
{{/t}}
</label> </label>
<div class="controls js-exclude-small-matches-options" <div class="controls js-exclude-small-matches-options"
style="{{hiddenUnless excludesSmallMatches}}"> style="{{hiddenUnless excludesSmallMatches}}">

View File

@ -32,22 +32,20 @@
<div class="controls"> <div class="controls">
<label class="checkbox"> <label class="checkbox">
<input id="assignment_text_entry" {{checkbox "acceptsOnlineTextEntries"
id="assignment_text_entry"
name="online_submission_types[online_text_entry]" name="online_submission_types[online_text_entry]"
type="checkbox" disabled=submissionTypesFrozen}}
{{checkedIf acceptsOnlineTextEntries}}
{{disabledIfIncludes frozenAttributes "submission_types"}}/>
{{#t "labels.allow_text_entry"}}Allow Text Entry{{/t}} {{#t "labels.allow_text_entry"}}Allow Text Entry{{/t}}
</label> </label>
</div> </div>
<div class="controls"> <div class="controls">
<label class="checkbox"> <label class="checkbox">
<input id="assignment_online_url" {{checkbox "acceptsOnlineURL"
id="assignment_online_url"
name="online_submission_types[online_url]" name="online_submission_types[online_url]"
type="checkbox" disabled=submissionTypesFrozen}}
{{checkedIf acceptsOnlineURL}}
{{disabledIfIncludes frozenAttributes "submission_types"}}/>
{{#t "labels.allow_url"}}Allow Website URL{{/t}} {{#t "labels.allow_url"}}Allow Website URL{{/t}}
</label> </label>
</div> </div>
@ -55,11 +53,10 @@
<div class="controls"> <div class="controls">
{{#if kalturaEnabled}} {{#if kalturaEnabled}}
<label class="checkbox"> <label class="checkbox">
<input id="assignment_media_recording" {{checkbox "acceptsMediaRecording"
id="assignment_media_recording"
name="online_submission_types[media_recording]" name="online_submission_types[media_recording]"
type="checkbox" disabled=submissionTypesFrozen}}
{{checkedIf acceptsMediaRecording}}
{{disabledIfIncludes frozenAttributes "submission_types"}}/>
{{#t "labels.allow_media_recordings"}}Allow Media Recordings{{/t}} {{#t "labels.allow_media_recordings"}}Allow Media Recordings{{/t}}
</label> </label>
{{/if}} {{/if}}
@ -67,12 +64,11 @@
<div class="controls"> <div class="controls">
<label class="checkbox" for="assignment_online_upload"> <label class="checkbox" for="assignment_online_upload">
<input id="assignment_online_upload" {{checkbox "acceptsOnlineUpload"
id="assignment_online_upload"
name="online_submission_types[online_upload]" name="online_submission_types[online_upload]"
type="checkbox"
aria-controls="restrict_file_extensions_container" aria-controls="restrict_file_extensions_container"
{{checkedIf acceptsOnlineUpload}} disabled=submissionTypesFrozen}}
{{disabledIfIncludes frozenAttributes "submission_types"}}/>
{{#t "labels.allow_file_uploads"}}Allow File Uploads{{/t}} {{#t "labels.allow_file_uploads"}}Allow File Uploads{{/t}}
</label> </label>
</div> </div>
@ -82,12 +78,11 @@
style="{{hiddenUnless acceptsOnlineUpload}}"> style="{{hiddenUnless acceptsOnlineUpload}}">
<div class="controls"> <div class="controls">
<label class="checkbox" for="assignment_restrict_file_extensions"> <label class="checkbox" for="assignment_restrict_file_extensions">
<input id="assignment_restrict_file_extensions" {{checkbox "restrictFileExtensions"
id="assignment_restrict_file_extensions"
name="restrict_file_extensions" name="restrict_file_extensions"
type="checkbox"
aria-controls="allowed_extensions_container" aria-controls="allowed_extensions_container"
{{checkedIf restrictFileExtensions}} disabled=submissionTypesFrozen}}
{{disabledIfIncludes frozenAttributes "submission_types"}}/>
{{#t "labels.restrict_file_extensions"}} {{#t "labels.restrict_file_extensions"}}
Restrict Upload File Types Restrict Upload File Types
{{/t}} {{/t}}
@ -118,12 +113,11 @@
<div class="controls" style="{{hiddenUnless turnitinAvailable}}"> <div class="controls" style="{{hiddenUnless turnitinAvailable}}">
<label for="assignment_turnitin_enabled" class="checkbox"> <label for="assignment_turnitin_enabled" class="checkbox">
<input id="assignment_turnitin_enabled" {{checkbox "turnitinEnabled"
id="assignment_turnitin_enabled"
name="turnitin_enabled" name="turnitin_enabled"
type="checkbox"
aria-controls="advanced_turnitin_settings_link" aria-controls="advanced_turnitin_settings_link"
{{checkedIf turnitinEnabled}} disabled=submissionTypesFrozen}}
{{disabledIfIncludes frozenAttributes "submission_types"}}/>
{{#t "label.turnitin_enabled"}}Enable Turnitin Submissions{{/t}} {{#t "label.turnitin_enabled"}}Enable Turnitin Submissions{{/t}}
</label> </label>
@ -155,11 +149,10 @@
<div class="control-group"> <div class="control-group">
<div class="controls"> <div class="controls">
<label for="assignment_external_tool_tag_attributes_new_tab" class="checkbox"> <label for="assignment_external_tool_tag_attributes_new_tab" class="checkbox">
<input id="assignment_external_tool_tag_attributes_new_tab" {{checkbox "externalToolNewTab"
id="assignment_external_tool_tag_attributes_new_tab"
name="external_tool_tag_attributes[new_tab]" name="external_tool_tag_attributes[new_tab]"
type="checkbox" disabled=submissionTypesFrozen}}
{{checkedIf externalToolNewTab}}
{{disabledIfIncludes frozenAttributes "submission_types"}}/>
{{#t "label.external_tool_new_tab"}}Load This Tool In A New Tab{{/t}} {{#t "label.external_tool_new_tab"}}Load This Tool In A New Tab{{/t}}
</label> </label>
</div> </div>

View File

@ -14,7 +14,7 @@
<div class="ag-menu-container"></div> <div class="ag-menu-container"></div>
</div> </div>
<p> <p>
<input type="checkbox" class="group-signup-checkbox" id="group-signup-checkbox" name="use_group_signup" value="1" {{#ifEqual participant_type "Group"}}checked{{/ifEqual}}> {{checkbox "use_group_signup" id="group-signup-checkbox" class="group-signup-checkbox"}}
<label for="group-signup-checkbox">{{#t "group_signup"}}Have students sign up in groups.{{/t}}</label> <label for="group-signup-checkbox">{{#t "group_signup"}}Have students sign up in groups.{{/t}}</label>
</p> </p>
<div class="group-signup" style="display: none"> <div class="group-signup" style="display: none">
@ -51,7 +51,7 @@
<b>Options</b> <b>Options</b>
<ul class="ag-options"> <ul class="ag-options">
<li> <li>
<input type="checkbox" id="appointment-blocks-per-slot-option-button" name="per_slot_option" value="1" /> {{checkbox "per_slot_option" id="appointment-blocks-per-slot-option-button"}}
<label for="appointment-blocks-per-slot-option-button">Limit each time slot to</label> <label for="appointment-blocks-per-slot-option-button">Limit each time slot to</label>
<input type="number" name="participants_per_appointment" value="{{appointment_group.participants_per_appointment}}" min="1" style="width: 40px;" /> <input type="number" name="participants_per_appointment" value="{{appointment_group.participants_per_appointment}}" min="1" style="width: 40px;" />
<label for="appointment-blocks-per-slot-option-button"> <label for="appointment-blocks-per-slot-option-button">
@ -63,10 +63,10 @@
</a> </a>
</li> </li>
<li> <li>
<label for="appointment-blocks-participant-visibility-button"><input type="checkbox" id="appointment-blocks-participant-visibility-button" name="participant_visibility" value="1" /> Allow students to see who has signed up for time slots.</label> <label for="appointment-blocks-participant-visibility-button">{{checkbox "participant_visibility" id="appointment-blocks-participant-visibility-button"}} Allow students to see who has signed up for time slots.</label>
</li> </li>
<li> <li>
<input type="checkbox" id="max-per-student-option" name="max_appointments_per_participant_option" value="1"> {{checkbox "max_appointments_per_participant_option" id="max-per-student-option"}}
<label for="max-per-student-option">Limit participants to attend</label> <label for="max-per-student-option">Limit participants to attend</label>
<input type="number" name="max_appointments_per_participant" value="{{appointment_group.max_appointments_per_participant}}" min="1" style="width: 40px"> <input type="number" name="max_appointments_per_participant" value="{{appointment_group.max_appointments_per_participant}}" min="1" style="width: 40px">
<label for="max-per-student-option">appointment(s).</label> <label for="max-per-student-option">appointment(s).</label>

View File

@ -4,7 +4,7 @@
<textarea name="description">{{description}}</textarea> <textarea name="description">{{description}}</textarea>
</p> </p>
<p> <p>
<input type="checkbox" name="max_participants_option"> {{checkbox "max_participants_option" id=null}}
{{#t "slot_limit"}}Limit this slot to{{/t}} {{#t "slot_limit"}}Limit this slot to{{/t}}
<input type="number" name="max_participants" class="max-participants" min="1" disabled> <input type="number" name="max_participants" class="max-participants" min="1" disabled>
{{#t "users"}}users.{{/t}} {{#t "users"}}users.{{/t}}

View File

@ -14,10 +14,7 @@
{{#if course_sections}} {{#if course_sections}}
<label class="label_with_checkbox"> <label class="label_with_checkbox">
<input type="checkbox" {{checkbox "use_section_dates"}}
name="use_section_dates"
value="1"
{{#if use_section_dates}}checked{{/if}} />
{{#t "different_date_for_each_section"}}Use a different date for each section{{/t}} {{#t "different_date_for_each_section"}}Use a different date for each section{{/t}}
</label> </label>

View File

@ -42,10 +42,9 @@
<div class="controls"> <div class="controls">
<div class="web_conference_user_settings"></div> <div class="web_conference_user_settings"></div>
<label class="checkbox" for="web_conference_long_running"> <label class="checkbox" for="web_conference_long_running">
<input name="web_conference[long_running]" type="hidden" value="0"> {{checkbox "web_conference.long_running"
<input id="web_conference_long_running" name="web_conference[long_running]" type="checkbox" checked=conferenceData.long_running
value="1" {{#if conferenceData.long_running}}checked{{/if}} disabled=settings.disable_duration_changes}}
{{#if settings.disable_duration_changes}}disabled='disabled'{{/if}}>
{{#t "long_running"}}No time limit (for long-running conferences){{/t}} {{#t "long_running"}}No time limit (for long-running conferences){{/t}}
</label> </label>
</div> </div>
@ -58,8 +57,7 @@
</div> </div>
<legend>{{#t "members"}}Members{{/t}}</legend> <legend>{{#t "members"}}Members{{/t}}</legend>
<label class="checkbox" for="user_all"> <label class="checkbox" for="user_all">
<input name="user[all]" type="hidden" value="0"> {{checkbox "user.all" class="all_users_checkbox" checked=inviteAll}}
<input class="all_users_checkbox" id="user_all" name="user[all]" type="checkbox" value="1" {{#if inviteAll}}checked{{/if}}>
{{#t "invite_all"}}Invite All Course Members{{/t}} {{#t "invite_all"}}Invite All Course Members{{/t}}
</label> </label>
<div> <div>

View File

@ -15,7 +15,7 @@
<input id="courseSearchField" type="text" placeholder="Course name" name="courseSearchField" class='span3'/> <input id="courseSearchField" type="text" placeholder="Course name" name="courseSearchField" class='span3'/>
<br> <br>
<label class="checkbox"> <label class="checkbox">
<input type="checkbox" name="include_completed_courses" {{#if include_concluded}}checked{{/if}}> {{checkbox "include_completed_courses" checked=include_concluded}}
{{#t 'include_completed_courses'}}Include completed courses{{/t}} {{#t 'include_completed_courses'}}Include completed courses{{/t}}
</label> </label>
</div> </div>

View File

@ -1,6 +1,6 @@
<div class="controls"> <div class="controls">
<label class="checkbox"> <label class="checkbox">
<input type="checkbox" id="dateShiftCheckbox" name="date_shift_options[shift_dates]"> {{checkbox "date_shift_options.shift_dates" id="dateShiftCheckbox"}}
{{#t "checkbox_label"}}Adjust events and due dates{{/t}} {{#t "checkbox_label"}}Adjust events and due dates{{/t}}
</label> </label>
</div> </div>

View File

@ -39,7 +39,7 @@
<th></th> <th></th>
<td> <td>
<label> <label>
<input type="checkbox" name="group_conversation" value="1" class="group_conversation"> {{checkbox "group_conversation" class="group_conversation"}}
{{#t "labels.group_conversation"}}This is a group conversation. Participants will see everyone's replies{{/t}} {{#t "labels.group_conversation"}}This is a group conversation. Participants will see everyone's replies{{/t}}
</label> </label>
</td> </td>
@ -49,13 +49,11 @@
<th></th> <th></th>
<td> <td>
<label> <label>
<input type="checkbox" {{checkbox "user_note"
name="user_note" data-track-category="Compose Message"
value="1" data-track-action="Edit"
data-track-category="Compose Message" data-track-label="Faculty Journal"
data-track-action="Edit" class="user_note"}}
data-track-label="Faculty Journal"
class="user_note" />
{{#t "labels.add_to_faculty_journal"}}Add as a Faculty Journal entry{{/t}} {{#t "labels.add_to_faculty_journal"}}Add as a Faculty Journal entry{{/t}}
</label> </label>
</td> </td>

View File

@ -121,10 +121,9 @@
<div class='message-header-label'></div> <div class='message-header-label'></div>
<div class='message-header-input'> <div class='message-header-input'>
<label class="checkbox" for="compose-message-group_conversation"> <label class="checkbox" for="compose-message-group_conversation">
<input type="checkbox" id="compose-message-group_conversation" {{checkbox "group_conversation"
name="group_conversation" id="compose-message-group_conversation"
value="1" class="group_conversation"}}
class="group_conversation">
{{#t "labels.group_conversation"}}This is a group conversation. Participants will see everyone's replies{{/t}} {{#t "labels.group_conversation"}}This is a group conversation. Participants will see everyone's replies{{/t}}
</label> </label>
</div> </div>
@ -135,14 +134,12 @@
<div class='message-header-label'></div> <div class='message-header-label'></div>
<div class='message-header-input'> <div class='message-header-input'>
<label class="checkbox" for="compose-message-user_note"> <label class="checkbox" for="compose-message-user_note">
<input type="checkbox" {{checkbox "user_note"
name="user_note" id="compose-message-user_note"
id="compose-message-user_note" data-track-category="Compose Message"
value="1" data-track-action="Edit"
data-track-category="Compose Message" data-track-label="Faculty Journal"
data-track-action="Edit" class="user_note"}}
data-track-label="Faculty Journal"
class="user_note" />
{{#t "labels.add_to_faculty_journal"}}Add as a Faculty Journal entry{{/t}} {{#t "labels.add_to_faculty_journal"}}Add as a Faculty Journal entry{{/t}}
</label> </label>
</div> </div>

View File

@ -34,7 +34,7 @@
<div class="control-group" id="privileges"> <div class="control-group" id="privileges">
<div class="controls"> <div class="controls">
<label class="checkbox"> <label class="checkbox">
<input type="checkbox" id="limit_privileges_to_course_section" name="limit_privileges_to_course_section" value="1" {{#if limit_privileges_to_course_section}}checked{{/if}}> {{checkbox "limit_privileges_to_course_section"}}
{{#t "can_only_grade_students_in_section"}}Can grade students in their section only{{/t}} {{#t "can_only_grade_students_in_section"}}Can grade students in their section only{{/t}}
</label> </label>
</div> </div>

View File

@ -36,11 +36,10 @@
{{#if checkName}} {{#if checkName}}
<div class="user-preference"> <div class="user-preference">
<label class="checkbox" for="{{checkID}}"> <label class="checkbox" for="{{checkID}}">
<input type="checkbox" {{checkbox checkName
id="{{checkID}}" id=checkID
class="user-pref-check" class="user-pref-check"
name="{{checkName}}" checked=checkedState}}
{{#if checkedState}}checked="checked"{{/if}} />
{{checkLabel}} {{checkLabel}}
</label> </label>
</div> </div>

View File

@ -11,7 +11,7 @@
<div class="row-fluid expandee"> <div class="row-fluid expandee">
<div class="span2"> <div class="span2">
<label class="checkbox checkbox-inline"><input type="checkbox" name="graded"> Graded?</label> <label class="checkbox checkbox-inline">{{checkbox "graded"}} Graded?</label>
</div> </div>
<div class="span2"> <div class="span2">

View File

@ -40,7 +40,7 @@
{{#if CAN.EDIT_HIDE}} {{#if CAN.EDIT_HIDE}}
<div class="controls"> <div class="controls">
<label for="hide_from_students" class="checkbox"> <label for="hide_from_students" class="checkbox">
<input id="hide_from_students" type="checkbox" name="wiki_page[hide_from_students]" {{#if hide_from_students}}checked{{/if}}> {{checkbox "hide_from_students" prefix="wiki_page"}}
{{#t "hide_from_students"}}Hide this page from students{{/t}} {{#t "hide_from_students"}}Hide this page from students{{/t}}
</label> </label>
</div> </div>
@ -67,7 +67,7 @@
<div class="form-actions clearfix"> <div class="form-actions clearfix">
<div style="height:30px"> <div style="height:30px">
<label for="notify_of_update" class="checkbox clearfix pull-left" style="margin-top:5px"> <label for="notify_of_update" class="checkbox clearfix pull-left" style="margin-top:5px">
<input id="notify_of_update" type="checkbox" name="wiki_page[notify_of_update]"> {{checkbox "notify_of_update" prefix="wiki_page"}}
{{#t "notify_users_text"}}Notify users that this content has changed{{/t}} {{#t "notify_users_text"}}Notify users that this content has changed{{/t}}
</label> </label>
<a class="btn cancel" tabindex="0" role="button">{{#t "buttons.cancel"}}Cancel{{/t}}</a> <a class="btn cancel" tabindex="0" role="button">{{#t "buttons.cancel"}}Cancel{{/t}}</a>

View File

@ -1,63 +1,56 @@
define [ define [
'jquery' 'jquery'
'underscore'
'compiled/jquery/serializeForm' 'compiled/jquery/serializeForm'
], ($, _) -> ], ($) ->
$sampleForm = $('<form></form>') $sampleForm = $('''
.append('<input type="radio" value="val1" name=radio[1] />') <form>
.append('<input type="radio" value="val2" name=radio[2] />') Radio
.append('<input type="radio" value="val3" name=radio[3] />') <input type="radio" value="group_val_1" name="radio_group" checked />
.append('<input type="radio" value="group_val_1" name="radio_group" id="rg1" />') <input type="radio" value="group_val_2" name="radio_group" />
.append('<input type="radio" value="group_val_2" name="radio_group" id="rg2" />')
.append('<input type="radio" value="group_val_3" name="radio_group" id="rg3" />')
.append('<input type="checkbox" value="checkbox1" name="checkbox[1]" />')
.append('<input type="checkbox" value="checkbox2" name="checkbox[2]" />')
.append('<input type="button" value="button" />')
module "SerializeForm: without serialize-radio-value", Checked checkbox
setup: -> <input type="checkbox" value="checkbox1" name="checkbox[1]" checked />
$sampleForm.find('[name="radio[1]"]').prop('checked', true)
teardown: ->
$sampleForm.find('[name="radio[1]"]').prop('checked', false)
test "Radio button values should be booleans", -> Unchecked checkbox
<input type="checkbox" value="checkbox2" name="checkbox[2]" />
Unchecked checkbox with hidden field (a la rails and handlebars helper)
<input type="hidden" value="0" name="checkbox[3]" />
<input type="checkbox" value="1" name="checkbox[3]" />
Text field
<input type="text" value="asdf" name="text" />
Disabled field
<input type="text" value="qwerty" name="text2" disabled />
Textarea
<textarea name="textarea">hello\nworld</textarea>
Select
<select name="select"><option>1</option><option selected>2</option></select>
Multi-select
<select name="multiselect" multiple>
<option>1</option>
<option selected>2</option>
<option selected>3</option>
</select>
</form>
''')
module "SerializeForm"
test "Serializes valid input items correctly", ->
serialized = $sampleForm.serializeForm() serialized = $sampleForm.serializeForm()
radio1 = _.find serialized, (input) -> input.name == "radio[1]" deepEqual serialized, [
ok radio1.value, "Selected radio value should be true" {name: "radio_group", value: "group_val_1"}
{name: "checkbox[1]", value: "checkbox1"}
test "Serializes all input items", -> {name: "checkbox[3]", value: "0"}
serialized = $sampleForm.serializeForm() {name: "text", value: "asdf"}
ok serialized.length == 8, "There are 8 input elements serialized" {name: "textarea", value: "hello\r\nworld"}
{name: "select", value: "2"}
module "SerializeForm: with serialize-radio-value", {name: "multiselect", value: "2"}
setup: -> {name: "multiselect", value: "3"}
$sampleForm.attr('serialize-radio-value', '') ]
teardown: ->
$sampleForm.removeAttr('serialize-radio-value')
test "Doesnt serialize radio buttons that arent selected", ->
serialized = $sampleForm.serializeForm()
radios = _.filter serialized, (input) ->
input.name == "radio[1]" ||
input.name == "radio[2]" ||
input.name == "radio[3]"
ok radios.length == 0, "No radio selected"
test "Sends the true value of radio buttons that are selected", ->
$sampleForm.find('[name="radio[1]"]').prop('checked', true)
serialized = $sampleForm.serializeForm()
radio1 = _.find serialized, (input) -> input.name == "radio[1]"
equal radio1.value, "val1", "Serializes the true value of radio buttons"
$sampleForm.find('[name="radio[1]"]').prop('checked', false)
test "Serializes true radio button values of a selected group", ->
$sampleForm.find('#rg2').prop('checked', true)
serialized = $sampleForm.serializeForm()
radio2 = _.find serialized, (input) -> input.name == "radio_group"
equal radio2.value, "group_val_2", "Serializes the true value of radio buttons"
$sampleForm.find('#rg2').prop('checked', false)

View File

@ -15,13 +15,13 @@ require File.expand_path(File.dirname(__FILE__) + '/../common')
f('.ag_contexts_done').click f('.ag_contexts_done').click
if opts[:checkable_options] if opts[:checkable_options]
if opts[:checkable_options].has_key?(:per_slot_option) if opts[:checkable_options].has_key?(:per_slot_option)
set_value f('[name="per_slot_option"]'), true set_value f('[type=checkbox][name="per_slot_option"]'), true
end end
if opts[:checkable_options].has_key?(:participant_visibility) if opts[:checkable_options].has_key?(:participant_visibility)
set_value f('[name="participant_visibility"]'), true set_value f('[type=checkbox][name="participant_visibility"]'), true
end end
if opts[:checkable_options].has_key?(:max_appointments_per_participant_option) if opts[:checkable_options].has_key?(:max_appointments_per_participant_option)
set_value f('[name="max_appointments_per_participant_option"]'), true set_value f('[type=checkbox][name="max_appointments_per_participant_option"]'), true
end end
end end
date_field = edit_form.find_element(:css, '.date_field') date_field = edit_form.find_element(:css, '.date_field')

View File

@ -133,21 +133,21 @@ describe "scheduler" do
} }
# assert options are checked # assert options are checked
open_edit_dialog open_edit_dialog
f('[name="per_slot_option"]').selected?.should be_true f('[type=checkbox][name="per_slot_option"]').selected?.should be_true
f('[name="participant_visibility"]').selected?.should be_true f('[type=checkbox][name="participant_visibility"]').selected?.should be_true
f('[name="max_appointments_per_participant_option"]').selected?.should be_true f('[type=checkbox][name="max_appointments_per_participant_option"]').selected?.should be_true
# uncheck the options # uncheck the options
f('[name="per_slot_option"]').click f('[type=checkbox][name="per_slot_option"]').click
f('[name="participant_visibility"]').click f('[type=checkbox][name="participant_visibility"]').click
f('[name="max_appointments_per_participant_option"]').click f('[type=checkbox][name="max_appointments_per_participant_option"]').click
submit_dialog('.ui-dialog-buttonset', '.ui-button') submit_dialog('.ui-dialog-buttonset', '.ui-button')
wait_for_ajaximations wait_for_ajaximations
# assert options are not checked # assert options are not checked
open_edit_dialog open_edit_dialog
f('[name="per_slot_option"]').selected?.should be_false f('[type=checkbox][name="per_slot_option"]').selected?.should be_false
f('[name="participant_visibility"]').selected?.should be_false f('[type=checkbox][name="participant_visibility"]').selected?.should be_false
f('[name="max_appointments_per_participant_option"]').selected?.should be_false f('[type=checkbox][name="max_appointments_per_participant_option"]').selected?.should be_false
end end
it "should delete an appointment group after clicking appointment group link" do it "should delete an appointment group after clicking appointment group link" do
@ -375,7 +375,7 @@ describe "scheduler" do
ag.participants_per_appointment.should == 2 ag.participants_per_appointment.should == 2
open_edit_event_dialog open_edit_event_dialog
f('[name=max_participants_option]').click f('[type=checkbox][name=max_participants_option]').click
fj('.ui-button:contains(Update)').click fj('.ui-button:contains(Update)').click
wait_for_ajaximations wait_for_ajaximations