XSS linting, fixes CNVS-17663
no significant issues/vulnerabilities fixed in this commit, rather this is a catch-all so we can enforce linting in the build. to better understand what's going on here, see the following: * public/javascripts/.xssignore * script/xsslint.js * https://github.com/jenseng/xsslint high level summary of what's going on in this commit: 1. .html/.append/etc. now know what to do with a SafeString ... in many cases we now put a $.raw around an .html argument to tell the linter it's ok 2. although translation is an unlikely attack vector, we now htmlEscape I18n.t calls used in html snippets, etc. this is a good thing, as it ensures we don't create a vulnerability later (e.g. by interpolating user content into a translation) 3. many vars were renamed (Html suffix, $ prefix) to let the linter know it's something that was manually vetted 4. in some cases, rather than renaming or creating a superfluous var, we add special xsslint comment overrides test plan: specs should all pass Change-Id: Ide1df825b798d1b0c468a5308802543bf716c0d7 Reviewed-on: https://gerrit.instructure.com/46097 Tested-by: Jenkins <jenkins@instructure.com> QA-Review: Derek Hansen <dhansen@instructure.com> Reviewed-by: Jeremy Stanley <jeremy@instructure.com> Product-Review: Jeremy Stanley <jeremy@instructure.com>
This commit is contained in:
parent
426fc9b1e8
commit
70cdc92bdb
|
@ -31,7 +31,7 @@
|
|||
# PaginatedList expects an empty <ul> wrapped in a <div>. The element
|
||||
# passed to the constructor should be the <div>.
|
||||
|
||||
define ['jquery', 'i18n!paginated_list', 'vendor/spin'], ($, I18n, Spinner) ->
|
||||
define ['jquery', 'i18n!paginated_list', 'vendor/spin', 'str/htmlEscape'], ($, I18n, Spinner, htmlEscape) ->
|
||||
class PaginatedList
|
||||
##
|
||||
# I18n keys used by class
|
||||
|
@ -132,11 +132,11 @@ define ['jquery', 'i18n!paginated_list', 'vendor/spin'], ($, I18n, Spinner) ->
|
|||
##
|
||||
# animate loaded results
|
||||
# @api private
|
||||
animateInResults: (results) ->
|
||||
animateInResults: ($results) ->
|
||||
empty = @el.list.children().length == 0
|
||||
results.css('display', 'none')
|
||||
@el.list.append results
|
||||
results.slideDown()
|
||||
$results.css('display', 'none')
|
||||
@el.list.append $results
|
||||
$results.slideDown()
|
||||
|
||||
##
|
||||
# keep track of what page we're on. when the last page
|
||||
|
@ -146,7 +146,7 @@ define ['jquery', 'i18n!paginated_list', 'vendor/spin'], ($, I18n, Spinner) ->
|
|||
if @hasNextPage()
|
||||
@options.requestParams.page++
|
||||
unless @pageLinkPresent
|
||||
@el.wrapper.append @viewMoreLink()
|
||||
@el.wrapper.append @viewMoreLinkHtml()
|
||||
@pageLinkPresent = true
|
||||
else
|
||||
@el.wrapper.find('.view-more-link').remove()
|
||||
|
@ -162,12 +162,12 @@ define ['jquery', 'i18n!paginated_list', 'vendor/spin'], ($, I18n, Spinner) ->
|
|||
# template for view more link
|
||||
# @return String
|
||||
# @api private
|
||||
viewMoreLink: ->
|
||||
'<a class="view-more-link" href="#">' + @keys.viewMore + '</a>'
|
||||
viewMoreLinkHtml: ->
|
||||
'<a class="view-more-link" href="#">' + htmlEscape(@keys.viewMore) + '</a>'
|
||||
|
||||
##
|
||||
# template for no results notification
|
||||
# @return String
|
||||
# @api private
|
||||
noResults: ->
|
||||
@el.list.append "<li>#{@keys.noResults}</li>"
|
||||
@el.list.append "<li>#{htmlEscape @keys.noResults}</li>"
|
||||
|
|
|
@ -5,7 +5,12 @@ define [
|
|||
'underscore'
|
||||
'jquery'
|
||||
'compiled/behaviors/authenticity_token'
|
||||
], (Backbone, _, $, authenticity_token) ->
|
||||
'str/htmlEscape'
|
||||
], (Backbone, _, $, authenticity_token, htmlEscape) ->
|
||||
###
|
||||
xsslint safeString.identifier iframeId httpMethod
|
||||
xsslint jqueryObject.identifier el
|
||||
###
|
||||
|
||||
Backbone.syncWithoutMultipart = Backbone.sync
|
||||
Backbone.syncWithMultipart = (method, model, options) ->
|
||||
|
@ -35,7 +40,7 @@ define [
|
|||
$el[0]
|
||||
_.flatten(inputs)
|
||||
$form = $("""
|
||||
<form enctype='multipart/form-data' target='#{iframeId}' action='#{options.url ? model.url()}' method='POST'>
|
||||
<form enctype='multipart/form-data' target='#{iframeId}' action='#{htmlEscape options.url ? model.url()}' method='POST'>
|
||||
</form>
|
||||
""").hide()
|
||||
|
||||
|
@ -43,7 +48,7 @@ define [
|
|||
if options.proxyAttachment
|
||||
$form.prepend """
|
||||
<input type='hidden' name='_method' value='#{httpMethod}' />
|
||||
<input type='hidden' name='authenticity_token' value='#{authenticity_token()}' />
|
||||
<input type='hidden' name='authenticity_token' value='#{htmlEscape authenticity_token()}' />
|
||||
"""
|
||||
|
||||
_.each toForm(model.toJSON()), (el) ->
|
||||
|
|
|
@ -250,6 +250,10 @@ define [
|
|||
#
|
||||
# @api private
|
||||
|
||||
###
|
||||
xsslint safeString.method format
|
||||
###
|
||||
|
||||
createBindings: (index, el) =>
|
||||
@$('[data-bind]').each (index, el) =>
|
||||
$el = $ el
|
||||
|
|
|
@ -4,5 +4,5 @@ define ['jquery'], ($) ->
|
|||
for type, unread of ENV.badge_counts
|
||||
if unread > 0
|
||||
type = "grades" if type is "submissions"
|
||||
$badge = $("<b/>").append(unread).addClass("nav-badge")
|
||||
$badge = $("<b/>").text(unread).addClass("nav-badge")
|
||||
$("#section-tabs .#{type}").append($badge)
|
||||
|
|
|
@ -231,6 +231,9 @@ define [
|
|||
$course_syllabus.loadingImage()
|
||||
|
||||
success: (data) ->
|
||||
###
|
||||
xsslint safeString.property syllabus_body
|
||||
###
|
||||
$course_syllabus.loadingImage('remove').html data.course.syllabus_body
|
||||
$course_syllabus.data('syllabus_body', data.course.syllabus_body)
|
||||
$course_syllabus_details.hide()
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
define ['jquery', 'INST'], ($, INST) ->
|
||||
link = null
|
||||
$link = null
|
||||
set = (env) ->
|
||||
link.remove() if link
|
||||
$link.remove() if $link
|
||||
favicon = if env == 'development'
|
||||
'/favicon-green.ico'
|
||||
else if env == 'test'
|
||||
'/favicon-yellow.ico'
|
||||
else
|
||||
'/favicon.ico'
|
||||
link = $('<link />').attr(rel: 'icon', type: 'image/x-icon', href: favicon)
|
||||
$(document.head).append(link)
|
||||
$link = $('<link />').attr(rel: 'icon', type: 'image/x-icon', href: favicon)
|
||||
$(document.head).append($link)
|
||||
set(INST?.environment)
|
||||
set
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# copied from
|
||||
# https://github.com/rails/jquery-ujs
|
||||
|
||||
define ['jquery', 'compiled/behaviors/authenticity_token'], ($, authenticity_token) ->
|
||||
define ['jquery', 'compiled/behaviors/authenticity_token', 'str/htmlEscape'], ($, authenticity_token, htmlEscape) ->
|
||||
|
||||
##
|
||||
# Handles "data-method" on links such as:
|
||||
|
@ -11,12 +11,12 @@ define ['jquery', 'compiled/behaviors/authenticity_token'], ($, authenticity_tok
|
|||
href = link.data('url') || link.attr('href')
|
||||
method = link.data('method')
|
||||
target = link.attr('target')
|
||||
form = $("<form method='post' action='#{href}'></form>")
|
||||
metadataInput = "<input name='_method' value='#{method }' type='hidden' />"
|
||||
metadataInput += "<input name='authenticity_token' type='hidden' />"
|
||||
form = $("<form method='post' action='#{htmlEscape href}'></form>")
|
||||
metadataInputHtml = "<input name='_method' value='#{htmlEscape method}' type='hidden' />"
|
||||
metadataInputHtml += "<input name='authenticity_token' type='hidden' />"
|
||||
|
||||
form.attr('target', target) if target
|
||||
form.hide().append(metadataInput).appendTo('body').submit()
|
||||
form.hide().append(metadataInputHtml).appendTo('body').submit()
|
||||
|
||||
|
||||
# For 'data-confirm' attribute:
|
||||
|
|
|
@ -11,8 +11,8 @@ require [
|
|||
if ENV.DASHBOARD_SIDEBAR_URL
|
||||
rightSide = $('#right-side')
|
||||
rightSide.disableWhileLoading(
|
||||
$.get ENV.DASHBOARD_SIDEBAR_URL , (data) ->
|
||||
rightSide.html data
|
||||
$.get ENV.DASHBOARD_SIDEBAR_URL , (html) ->
|
||||
rightSide.html html
|
||||
newCourseForm()
|
||||
)
|
||||
|
||||
|
|
|
@ -39,9 +39,9 @@ require [
|
|||
$link.hide()
|
||||
$.ajaxJSON $(this).attr("href"), "GET", {}, (data) ->
|
||||
$("#home_page").loadingImage "remove"
|
||||
body = htmlEscape($.trim(data.wiki_page.body))
|
||||
body = htmlEscape(I18n.t("empty_body", "No Content")) if body.length is 0
|
||||
$("#home_page_content").html body
|
||||
bodyHtml = htmlEscape($.trim(data.wiki_page.body))
|
||||
bodyHtml = htmlEscape(I18n.t("empty_body", "No Content")) if bodyHtml.length is 0
|
||||
$("#home_page_content").html bodyHtml
|
||||
$("html,body").scrollTo $("#home_page")
|
||||
|
||||
$(".dashboard_view_link").click (event) ->
|
||||
|
|
|
@ -7,7 +7,7 @@ require [
|
|||
showAllArtifacts.click (event) ->
|
||||
event.preventDefault()
|
||||
$("tr.artifact_details").toggle()
|
||||
if showAllArtifacts.html() is I18n.t("#buttons.show_all_artifacts", "Show All Artifacts")
|
||||
showAllArtifacts.html I18n("#buttons.hide_all_artifacts", "Hide All Artifacts")
|
||||
if showAllArtifacts.text() is I18n.t("#buttons.show_all_artifacts", "Show All Artifacts")
|
||||
showAllArtifacts.text I18n("#buttons.hide_all_artifacts", "Hide All Artifacts")
|
||||
else
|
||||
showAllArtifacts.html I18n.t("#buttons.show_all_artifacts", "Show All Artifacts")
|
||||
showAllArtifacts.text I18n.t("#buttons.show_all_artifacts", "Show All Artifacts")
|
||||
|
|
|
@ -80,10 +80,10 @@ require [
|
|||
@$linkFields ?= @$ '#profile_link_fields'
|
||||
$row = $ """
|
||||
<tr>
|
||||
<td><input aria-label="#{I18n.t("Link title")}" type="text" maxlength="255" name="link_titles[]" value="#{htmlEscape title}"></td>
|
||||
<td><input aria-label="#{htmlEscape I18n.t("Link title")}" type="text" maxlength="255" name="link_titles[]" value="#{htmlEscape title}"></td>
|
||||
<td>→</td>
|
||||
<td><input aria-label="#{I18n.t("Link Url")}" type="text" name="link_urls[]" value="#{htmlEscape url}"></td>
|
||||
<td><a href="#" data-event="removeLinkRow"><span class="screenreader-only">#{I18n.t("Remove")}</span><i class="icon-end"></i></a></td>
|
||||
<td><input aria-label="#{htmlEscape I18n.t("Link Url")}" type="text" name="link_urls[]" value="#{htmlEscape url}"></td>
|
||||
<td><a href="#" data-event="removeLinkRow"><span class="screenreader-only">#{htmlEscape I18n.t("Remove")}</span><i class="icon-end"></i></a></td>
|
||||
</tr>
|
||||
"""
|
||||
@$linkFields.append $row
|
||||
|
|
|
@ -20,8 +20,8 @@ require [
|
|||
if ENV.SUBMISSION_VERSIONS_URL && !ENV.IS_SURVEY
|
||||
versions = $("#quiz-submission-version-table")
|
||||
versions.css(height: "100px")
|
||||
dfd = $.get ENV.SUBMISSION_VERSIONS_URL, (data) ->
|
||||
versions.html(data)
|
||||
dfd = $.get ENV.SUBMISSION_VERSIONS_URL, (html) ->
|
||||
versions.html(html)
|
||||
versions.css(height: "auto")
|
||||
versions.disableWhileLoading(dfd)
|
||||
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
require [
|
||||
'i18n!zip_file_imports' # I18n
|
||||
'jquery' # $
|
||||
'str/htmlEscape'
|
||||
'jquery.ajaxJSON' # getJSON
|
||||
'jquery.instructure_forms' # ajaxJSONFiles
|
||||
'jqueryui/dialog'
|
||||
'compiled/jquery.rails_flash_notifications'
|
||||
'jqueryui/progressbar' # /\.progressbar/
|
||||
], (I18n, $) ->
|
||||
], (I18n, $, htmlEscape) ->
|
||||
|
||||
$(document).ready ->
|
||||
$zipFile = $("#zip_file_import_form #zip_file")
|
||||
|
@ -73,7 +74,7 @@ require [
|
|||
importFailed []
|
||||
else if zfi.workflow_state == 'imported'
|
||||
$("#uploading_progressbar").progressbar 'value', 100
|
||||
$("#uploading_please_wait_dialog").prepend I18n.t('notices.uploading_complete', "Uploading complete!")
|
||||
$("#uploading_please_wait_dialog").prepend htmlEscape I18n.t('notices.uploading_complete', "Uploading complete!")
|
||||
location.href = $("#return_to").val()
|
||||
else
|
||||
pollImport.errorCount = 0
|
||||
|
|
|
@ -156,7 +156,7 @@ define [
|
|||
dayClick: @dayClick
|
||||
addEventClick: @addEventClick
|
||||
titleFormat:
|
||||
week: "MMM d[ yyyy]{ '–'[ MMM] d, yyyy}"
|
||||
week: "MMM d[ yyyy]{ '–'[ MMM] d, yyyy}"
|
||||
viewDisplay: @viewDisplay
|
||||
windowResize: @windowResize
|
||||
drop: @drop
|
||||
|
@ -275,8 +275,8 @@ define [
|
|||
I18n.t('event_event_title', 'Event Title:')
|
||||
|
||||
$element.attr('title', $.trim("#{timeString}\n#{$element.find('.fc-event-title').text()}\n\n#{I18n.t('calendar_title', 'Calendar:')} #{htmlEscape(event.contextInfo.name)}"))
|
||||
$element.find('.fc-event-inner').prepend($("<span class='screenreader-only'>#{I18n.t('calendar_title', 'Calendar:')} #{htmlEscape(event.contextInfo.name)}</span>"))
|
||||
$element.find('.fc-event-title').prepend($("<span class='screenreader-only'>#{screenReaderTitleHint} </span>"))
|
||||
$element.find('.fc-event-inner').prepend($("<span class='screenreader-only'>#{htmlEscape I18n.t('calendar_title', 'Calendar:')} #{htmlEscape(event.contextInfo.name)}</span>"))
|
||||
$element.find('.fc-event-title').prepend($("<span class='screenreader-only'>#{htmlEscape screenReaderTitleHint} </span>"))
|
||||
$element.find('.fc-event-title').toggleClass('calendar__event--completed', event.isCompleted())
|
||||
element.find('.fc-event-inner').prepend($('<i />', {'class': "icon-#{event.iconType()}"}))
|
||||
true
|
||||
|
@ -408,20 +408,20 @@ define [
|
|||
drawNowLine: =>
|
||||
return unless @currentView == 'week'
|
||||
|
||||
if !@nowLine
|
||||
@nowLine = $('<div />', {'class': 'calendar-nowline'})
|
||||
$('.fc-agenda-slots').parent().append(@nowLine)
|
||||
if !@$nowLine
|
||||
@$nowLine = $('<div />', {'class': 'calendar-nowline'})
|
||||
$('.fc-agenda-slots').parent().append(@$nowLine)
|
||||
|
||||
now = $.fudgeDateForProfileTimezone(new Date)
|
||||
midnight = new Date(now.getTime())
|
||||
midnight.setHours(0, 0, 0)
|
||||
seconds = (now.getTime() - midnight.getTime())/1000
|
||||
|
||||
@nowLine.toggle(@isSameWeek(@getCurrentDate(), now))
|
||||
@$nowLine.toggle(@isSameWeek(@getCurrentDate(), now))
|
||||
|
||||
@nowLine.css('width', $('.fc-agenda-slots .fc-widget-content:first').css('width'))
|
||||
@$nowLine.css('width', $('.fc-agenda-slots .fc-widget-content:first').css('width'))
|
||||
secondHeight = $('.fc-agenda-slots').css('height').replace('px', '')/24/3600
|
||||
@nowLine.css('top', seconds*secondHeight + 'px')
|
||||
@$nowLine.css('top', seconds*secondHeight + 'px')
|
||||
|
||||
setDateTitle: (title) =>
|
||||
@header.setHeaderText(title)
|
||||
|
@ -642,7 +642,7 @@ define [
|
|||
@agenda.fetch(@visibleContextList, start)
|
||||
|
||||
renderDateRange: (start, end) =>
|
||||
@setDateTitle(I18n.l('#date.formats.medium', start)+' – '+I18n.l('#date.formats.medium', end))
|
||||
@setDateTitle(I18n.l('#date.formats.medium', start)+' – '+I18n.l('#date.formats.medium', end))
|
||||
# for "load more" with voiceover, we want the alert to happen later so
|
||||
# the focus change doesn't interrupt it.
|
||||
window.setTimeout =>
|
||||
|
@ -671,15 +671,16 @@ define [
|
|||
|
||||
colorizeContexts: =>
|
||||
colors = colorSlicer.getColors(@contextCodes.length, 275, {unsafe: !ENV.SETTINGS.use_high_contrast})
|
||||
html = for contextCode, index in @contextCodes
|
||||
html = (for contextCode, index in @contextCodes
|
||||
color = colors[index]
|
||||
".group_#{contextCode}{
|
||||
color: #{color};
|
||||
border-color: #{color};
|
||||
background-color: #{color};
|
||||
}"
|
||||
).join('')
|
||||
|
||||
$styleContainer.html "<style>#{html.join('')}</style>"
|
||||
$styleContainer.html "<style>#{html}</style>"
|
||||
|
||||
dataFromDocumentHash: () =>
|
||||
data = {}
|
||||
|
|
|
@ -13,24 +13,24 @@ define [
|
|||
constructor: (selector, @event, @contextChangeCB, @closeCB) ->
|
||||
@currentContextInfo = null
|
||||
tpl = if @event.override then editAssignmentOverrideTemplate else editAssignmentTemplate
|
||||
@form = $(tpl({
|
||||
@$form = $(tpl({
|
||||
title: @event.title
|
||||
contexts: @event.possibleContexts()
|
||||
}))
|
||||
$(selector).append @form
|
||||
$(selector).append @$form
|
||||
|
||||
@setupTimeAndDatePickers()
|
||||
|
||||
@form.submit @formSubmit
|
||||
@form.find(".more_options_link").click @moreOptionsClick
|
||||
@form.find("select.context_id").change @contextChange
|
||||
@form.find("select.context_id").triggerHandler('change', false)
|
||||
@$form.submit @formSubmit
|
||||
@$form.find(".more_options_link").click @moreOptionsClick
|
||||
@$form.find("select.context_id").change @contextChange
|
||||
@$form.find("select.context_id").triggerHandler('change', false)
|
||||
|
||||
# Hide the context selector completely if this is an existing event, since it can't be changed.
|
||||
if !@event.isNewEvent()
|
||||
@form.find(".context_select").hide()
|
||||
@form.attr('method', 'PUT')
|
||||
@form.attr('action', $.replaceTags(@event.contextInfo.assignment_url, 'id', @event.object.id))
|
||||
@$form.find(".context_select").hide()
|
||||
@$form.attr('method', 'PUT')
|
||||
@$form.attr('action', $.replaceTags(@event.contextInfo.assignment_url, 'id', @event.object.id))
|
||||
|
||||
contextInfoForCode: (code) ->
|
||||
for context in @event.possibleContexts()
|
||||
|
@ -39,14 +39,14 @@ define [
|
|||
return null
|
||||
|
||||
activate: () =>
|
||||
@form.find("select.context_id").change()
|
||||
@$form.find("select.context_id").change()
|
||||
if @event.assignment?.assignment_group_id
|
||||
@form.find(".assignment_group_select .assignment_group").val(@event.assignment.assignment_group_id)
|
||||
@$form.find(".assignment_group_select .assignment_group").val(@event.assignment.assignment_group_id)
|
||||
|
||||
moreOptionsClick: (jsEvent) =>
|
||||
jsEvent.preventDefault()
|
||||
pieces = $(jsEvent.target).attr('href').split("#")
|
||||
data = @form.getFormData( object_name: 'assignment' )
|
||||
data = @$form.getFormData( object_name: 'assignment' )
|
||||
params = {}
|
||||
if data.title then params['title'] = data.title
|
||||
if data.due_at then params['due_at'] = data.due_at
|
||||
|
@ -56,7 +56,7 @@ define [
|
|||
window.location.href = pieces.join("#")
|
||||
|
||||
setContext: (newContext) =>
|
||||
@form.find("select.context_id").val(newContext).triggerHandler('change', false)
|
||||
@$form.find("select.context_id").val(newContext).triggerHandler('change', false)
|
||||
|
||||
contextChange: (jsEvent, propagate) =>
|
||||
return if @ignoreContextChange
|
||||
|
@ -72,30 +72,30 @@ define [
|
|||
# TODO: support adding a new assignment group from this select box
|
||||
assignmentGroupsSelectOptionsInfo =
|
||||
collection: @currentContextInfo.assignment_groups
|
||||
@form.find(".assignment_group").html(genericSelectOptionsTemplate(assignmentGroupsSelectOptionsInfo))
|
||||
@$form.find(".assignment_group").html(genericSelectOptionsTemplate(assignmentGroupsSelectOptionsInfo))
|
||||
|
||||
# Update the edit and more options links with the new context
|
||||
@form.attr('action', @currentContextInfo.create_assignment_url)
|
||||
@$form.attr('action', @currentContextInfo.create_assignment_url)
|
||||
moreOptionsUrl = if @event.assignment
|
||||
"#{@event.assignment.html_url}/edit"
|
||||
else
|
||||
@currentContextInfo.new_assignment_url
|
||||
@form.find(".more_options_link").attr('href', moreOptionsUrl)
|
||||
@$form.find(".more_options_link").attr('href', moreOptionsUrl)
|
||||
|
||||
setupTimeAndDatePickers: () =>
|
||||
@form.find(".datetime_field").datetime_field()
|
||||
@$form.find(".datetime_field").datetime_field()
|
||||
|
||||
startDate = @event.startDate()
|
||||
endDate = @event.endDate()
|
||||
|
||||
if @event.allDay
|
||||
@form.find(".datetime_field").val(startDate.toString('MMM d, yyyy')).change()
|
||||
@$form.find(".datetime_field").val(startDate.toString('MMM d, yyyy')).change()
|
||||
else if startDate
|
||||
@form.find(".datetime_field").val(startDate.toString('MMM d, yyyy h:mmtt')).change()
|
||||
@$form.find(".datetime_field").val(startDate.toString('MMM d, yyyy h:mmtt')).change()
|
||||
|
||||
formSubmit: (e) =>
|
||||
e.preventDefault()
|
||||
form = @form.getFormData()
|
||||
form = @$form.getFormData()
|
||||
if form['assignment[due_at]']? then @submitAssignment(form) else @submitOverride(form)
|
||||
|
||||
submitAssignment: (form) ->
|
||||
|
@ -104,12 +104,12 @@ define [
|
|||
if dueAtString == ''
|
||||
dueAt = null
|
||||
else
|
||||
dueAt = @form.find("#assignment_due_at").data('date')
|
||||
dueAt = @$form.find("#assignment_due_at").data('date')
|
||||
params = {
|
||||
'assignment[name]': @form.find("#assignment_title").val()
|
||||
'assignment[published]': @form.find("#assignment_published").val() if @form.find("#assignment_published").is(':checked')
|
||||
'assignment[name]': @$form.find("#assignment_title").val()
|
||||
'assignment[published]': @$form.find("#assignment_published").val() if @$form.find("#assignment_published").is(':checked')
|
||||
'assignment[due_at]': if dueAt then $.unfudgeDateForProfileTimezone(dueAt).toISOString() else ''
|
||||
'assignment[assignment_group_id]': @form.find(".assignment_group").val()
|
||||
'assignment[assignment_group_id]': @$form.find(".assignment_group").val()
|
||||
}
|
||||
|
||||
if @event.isNewEvent()
|
||||
|
@ -117,7 +117,7 @@ define [
|
|||
assignment:
|
||||
title: params['assignment[name]']
|
||||
due_at: if dueAt then dueAt.toISOString() else null
|
||||
context_code: @form.find(".context_id").val()
|
||||
context_code: @$form.find(".context_id").val()
|
||||
newEvent = commonEventFactory(objectData, @event.possibleContexts())
|
||||
newEvent.save(params)
|
||||
else
|
||||
|
@ -129,7 +129,7 @@ define [
|
|||
|
||||
submitOverride: (form) ->
|
||||
dueAt = form['assignment_override[due_at]']
|
||||
dueAt = if dueAt is '' then null else @form.find('#assignment_override_due_at').data('date')
|
||||
dueAt = if dueAt is '' then null else @$form.find('#assignment_override_due_at').data('date')
|
||||
params = 'assignment_override[due_at]': if dueAt then $.unfudgeDateForProfileTimezone(dueAt).toISOString() else ''
|
||||
@event.start = dueAt
|
||||
@event.save(params)
|
||||
|
|
|
@ -14,24 +14,24 @@ define [
|
|||
class EditCalendarEventDetails
|
||||
constructor: (selector, @event, @contextChangeCB, @closeCB) ->
|
||||
@currentContextInfo = null
|
||||
@form = $(editCalendarEventTemplate({
|
||||
@$form = $(editCalendarEventTemplate({
|
||||
title: @event.title
|
||||
contexts: @event.possibleContexts()
|
||||
lockedTitle: @event.lockedTitle
|
||||
location_name: @event.location_name
|
||||
}))
|
||||
$(selector).append @form
|
||||
$(selector).append @$form
|
||||
|
||||
@setupTimeAndDatePickers()
|
||||
|
||||
@form.submit @formSubmit
|
||||
@form.find(".more_options_link").click @moreOptionsClick
|
||||
@form.find("select.context_id").change @contextChange
|
||||
@form.find("select.context_id").triggerHandler('change', false)
|
||||
@$form.submit @formSubmit
|
||||
@$form.find(".more_options_link").click @moreOptionsClick
|
||||
@$form.find("select.context_id").change @contextChange
|
||||
@$form.find("select.context_id").triggerHandler('change', false)
|
||||
|
||||
# Hide the context selector completely if this is an existing event, since it can't be changed.
|
||||
if !@event.isNewEvent()
|
||||
@form.find(".context_select").hide()
|
||||
@$form.find(".context_select").hide()
|
||||
|
||||
contextInfoForCode: (code) ->
|
||||
for context in @event.possibleContexts()
|
||||
|
@ -40,20 +40,20 @@ define [
|
|||
return null
|
||||
|
||||
activate: () =>
|
||||
@form.find("select.context_id").change()
|
||||
@$form.find("select.context_id").change()
|
||||
|
||||
getFormData: =>
|
||||
data = @form.getFormData(object_name: 'calendar_event')
|
||||
data = @$form.getFormData(object_name: 'calendar_event')
|
||||
data = _.omit(data, 'date', 'start_time', 'end_time')
|
||||
|
||||
date = @form.find('input[name=date]').data('date')
|
||||
date = @$form.find('input[name=date]').data('date')
|
||||
if date
|
||||
start_time = @form.find('input[name=start_time]').data('date')
|
||||
start_time = @$form.find('input[name=start_time]').data('date')
|
||||
start_at = date.toString('yyyy-MM-dd')
|
||||
start_at += start_time.toString(' HH:mm') if start_time
|
||||
data.start_at = tz.parse(start_at)
|
||||
|
||||
end_time = @form.find('input[name=end_time]').data('date')
|
||||
end_time = @$form.find('input[name=end_time]').data('date')
|
||||
end_at = date.toString('yyyy-MM-dd')
|
||||
end_at += end_time.toString(' HH:mm') if end_time
|
||||
data.end_at = tz.parse(end_at)
|
||||
|
@ -69,9 +69,9 @@ define [
|
|||
data = @getFormData()
|
||||
|
||||
# override parsed input with user input (for 'More Options' only)
|
||||
data.start_date = @form.find('input[name=date]').val()
|
||||
data.start_time = @form.find('input[name=start_time]').val()
|
||||
data.end_time = @form.find('input[name=end_time]').val()
|
||||
data.start_date = @$form.find('input[name=date]').val()
|
||||
data.start_time = @$form.find('input[name=start_time]').val()
|
||||
data.end_time = @$form.find('input[name=end_time]').val()
|
||||
|
||||
if data.title then params['title'] = data.title
|
||||
if data.location_name then params['location_name'] = data.location_name
|
||||
|
@ -84,7 +84,7 @@ define [
|
|||
window.location.href = pieces.join("#")
|
||||
|
||||
setContext: (newContext) =>
|
||||
@form.find("select.context_id").val(newContext).triggerHandler('change', false)
|
||||
@$form.find("select.context_id").val(newContext).triggerHandler('change', false)
|
||||
|
||||
contextChange: (jsEvent, propagate) =>
|
||||
context = $(jsEvent.target).val()
|
||||
|
@ -101,21 +101,21 @@ define [
|
|||
moreOptionsHref = @currentContextInfo.new_calendar_event_url
|
||||
else
|
||||
moreOptionsHref = @event.fullDetailsURL() + '/edit'
|
||||
@form.find(".more_options_link").attr 'href', moreOptionsHref
|
||||
@$form.find(".more_options_link").attr 'href', moreOptionsHref
|
||||
|
||||
setupTimeAndDatePickers: () =>
|
||||
@form.find(".date_field").date_field()
|
||||
@$form.find(".date_field").date_field()
|
||||
# TODO: Refactor this logic that forms a relationship between two time fields into a module
|
||||
@form.find(".time_field").time_field().
|
||||
@$form.find(".time_field").time_field().
|
||||
blur (jsEvent) =>
|
||||
start_time = @form.find(".time_field.start_time").next(".datetime_suggest").text()
|
||||
if @form.find(".time_field.start_time").next(".datetime_suggest").hasClass('invalid_datetime')
|
||||
start_time = @$form.find(".time_field.start_time").next(".datetime_suggest").text()
|
||||
if @$form.find(".time_field.start_time").next(".datetime_suggest").hasClass('invalid_datetime')
|
||||
start_time = null
|
||||
start_time ?= @form.find(".time_field.start_time").val()
|
||||
end_time = @form.find(".time_field.end_time").next(".datetime_suggest").text()
|
||||
if @form.find(".time_field.end_time").next(".datetime_suggest").hasClass('invalid_datetime')
|
||||
start_time ?= @$form.find(".time_field.start_time").val()
|
||||
end_time = @$form.find(".time_field.end_time").next(".datetime_suggest").text()
|
||||
if @$form.find(".time_field.end_time").next(".datetime_suggest").hasClass('invalid_datetime')
|
||||
end_time = null
|
||||
end_time ?= @form.find(".time_field.end_time").val()
|
||||
end_time ?= @$form.find(".time_field.end_time").val()
|
||||
|
||||
startDate = Date.parse(start_time)
|
||||
endDate = Date.parse(end_time)
|
||||
|
@ -128,21 +128,21 @@ define [
|
|||
else
|
||||
if endDate < startDate then endDate = startDate
|
||||
if startDate
|
||||
@form.find(".time_field.start_time").val(startDate.toString('h:mmtt').toLowerCase())
|
||||
@$form.find(".time_field.start_time").val(startDate.toString('h:mmtt').toLowerCase())
|
||||
if endDate
|
||||
@form.find(".time_field.end_time").val(endDate.toString('h:mmtt').toLowerCase())
|
||||
@$form.find(".time_field.end_time").val(endDate.toString('h:mmtt').toLowerCase())
|
||||
|
||||
startDate = @event.startDate()
|
||||
endDate = @event.endDate()
|
||||
|
||||
if !@event.allDay
|
||||
if startDate
|
||||
@form.find(".time_field.start_time").val(startDate.toString('h:mmtt')).change().blur()
|
||||
@$form.find(".time_field.start_time").val(startDate.toString('h:mmtt')).change().blur()
|
||||
if endDate
|
||||
@form.find(".time_field.end_time").val(endDate.toString('h:mmtt')).change().blur()
|
||||
@$form.find(".time_field.end_time").val(endDate.toString('h:mmtt')).change().blur()
|
||||
|
||||
if startDate
|
||||
@form.find(".date_field").val(startDate.toString('MMM d, yyyy')).change()
|
||||
@$form.find(".date_field").val(startDate.toString('MMM d, yyyy')).change()
|
||||
|
||||
formSubmit: (jsEvent) =>
|
||||
jsEvent.preventDefault()
|
||||
|
@ -165,7 +165,7 @@ define [
|
|||
start_at: if data.start_at then data.start_at.toISOString() else null
|
||||
end_at: if data.end_at then data.end_at.toISOString() else null
|
||||
location_name: location_name
|
||||
context_code: @form.find(".context_id").val()
|
||||
context_code: @$form.find(".context_id").val()
|
||||
newEvent = commonEventFactory(objectData, @event.possibleContexts())
|
||||
newEvent.save(params)
|
||||
else
|
||||
|
|
|
@ -7,7 +7,7 @@ define [
|
|||
'jquery.ajaxJSON'
|
||||
'jquery.instructure_date_and_time'
|
||||
'jqueryui/dialog'
|
||||
], (I18n, $, developer_key, developer_key_form, preventDefault) ->
|
||||
], (I18n, $, developer_key, developerKeyFormTemplate, preventDefault) ->
|
||||
page = 0
|
||||
buildKey = (key) ->
|
||||
key.icon_image_url = key.icon_url || "/images/blank.png"
|
||||
|
@ -20,7 +20,7 @@ define [
|
|||
$key.data('key', key)
|
||||
|
||||
buildForm = (key, $orig) ->
|
||||
$form = $(developer_key_form(key || {}))
|
||||
$form = $(developerKeyFormTemplate(key || {}))
|
||||
$form.formSubmit({
|
||||
beforeSubmit: ->
|
||||
$("#edit_dialog button.submit").text(I18n.t('button.saving', "Saving Key..."))
|
||||
|
@ -72,7 +72,7 @@ define [
|
|||
$form = buildForm()
|
||||
$("#edit_dialog").empty().append($form).dialog('open')
|
||||
)
|
||||
$("#edit_dialog").html(developer_key_form({})).dialog({
|
||||
$("#edit_dialog").html(developerKeyFormTemplate({})).dialog({
|
||||
autoOpen: false,
|
||||
width: 350
|
||||
}).on('click', '.cancel', () ->
|
||||
|
|
|
@ -48,7 +48,7 @@ define [
|
|||
|
||||
createCancelButton: ->
|
||||
$('<a/>')
|
||||
.html(I18n.t('cancel', 'Cancel'))
|
||||
.text(I18n.t('cancel', 'Cancel'))
|
||||
.css(marginLeft: '5px')
|
||||
.attr('href', 'javascript:')
|
||||
.addClass('cancel_button')
|
||||
|
|
|
@ -8,8 +8,9 @@ define [
|
|||
'jst/discussions/_reply_attachment'
|
||||
'compiled/fn/preventDefault'
|
||||
'compiled/views/editor/KeyboardShortcuts'
|
||||
'str/stripTags'
|
||||
'tinymce.editor_box'
|
||||
], (Backbone, _, I18n, $, Entry, htmlEscape, replyAttachmentTemplate, preventDefault, KeyboardShortcuts) ->
|
||||
], (Backbone, _, I18n, $, Entry, htmlEscape, replyAttachmentTemplate, preventDefault, KeyboardShortcuts, stripTags) ->
|
||||
|
||||
class Reply
|
||||
|
||||
|
@ -87,7 +88,7 @@ define [
|
|||
submit: =>
|
||||
@hide()
|
||||
@textArea._setContentCode ''
|
||||
@view.model.set 'notification', "<div class='alert alert-info'>#{I18n.t 'saving_reply', 'Saving reply...'}</div>"
|
||||
@view.model.set 'notification', "<div class='alert alert-info'>#{htmlEscape I18n.t 'saving_reply', 'Saving reply...'}</div>"
|
||||
entry = new Entry @getModelAttributes()
|
||||
entry.save null,
|
||||
success: @onPostReplySuccess
|
||||
|
@ -112,7 +113,7 @@ define [
|
|||
now = new Date().getTime()
|
||||
# TODO: remove this summary, server should send it in create response and no further
|
||||
# work is required
|
||||
summary: $('<div/>').html(@content).text()
|
||||
summary: stripTags(@content)
|
||||
message: @content
|
||||
parent_id: if @options.topLevel then null else @view.model.get 'id'
|
||||
user_id: ENV.current_user_id
|
||||
|
|
|
@ -7,6 +7,10 @@ define [
|
|||
'tinymce.editor_box'
|
||||
], (_, I18n, $, Backbone, preventDefault) ->
|
||||
|
||||
###
|
||||
xsslint safeString.property content
|
||||
###
|
||||
|
||||
##
|
||||
# Toggles an element between a rich text editor and itself
|
||||
class EditorToggle
|
||||
|
@ -103,7 +107,7 @@ define [
|
|||
# @api private
|
||||
createDone: ->
|
||||
$('<a/>')
|
||||
.html(@options.doneText)
|
||||
.text(@options.doneText)
|
||||
.attr('href', '#')
|
||||
.addClass('btn edit-html-done edit_html_done')
|
||||
.attr('title', I18n.t('done.title', 'Click to finish editing the rich text area'))
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
define [
|
||||
'i18n!editor_accessibility'
|
||||
'jquery'
|
||||
], (I18n, $) ->
|
||||
'str/htmlEscape'
|
||||
], (I18n, $, htmlEscape) ->
|
||||
##
|
||||
# Used to insert accessibility titles into core TinyMCE components
|
||||
class EditorAccessiblity
|
||||
|
@ -32,7 +33,7 @@ define [
|
|||
|
||||
@$el.find("##{@id_prepend}_instructure_record").attr('aria-disabled', 'true')
|
||||
@$el.find("##{@id_prepend}_instructure_record").removeAttr('role')
|
||||
@$el.find("##{@id_prepend}_instructure_record_voice").append('<br/>').append(I18n.t('accessibles.record', 'This feature is inaccessible for screen readers.'))
|
||||
@$el.find("##{@id_prepend}_instructure_record_voice").append('<br/>').append(htmlEscape(I18n.t('accessibles.record', 'This feature is inaccessible for screen readers.')))
|
||||
@$el.find("##{@id_prepend}_instructure_record img").attr('alt',
|
||||
@$el.find("##{@id_prepend}_instructure_record img").attr('alt') + ", " + I18n.t('accessibles.record', 'This feature is inaccessible for screen readers.'));
|
||||
|
||||
|
|
|
@ -2,13 +2,14 @@ define [
|
|||
'i18n!gradebook2'
|
||||
'jquery'
|
||||
'jst/CurveGradesDialog'
|
||||
'str/htmlEscape'
|
||||
'jquery.disableWhileLoading'
|
||||
'jquery.instructure_forms'
|
||||
'jqueryui/dialog'
|
||||
'jquery.instructure_misc_plugins'
|
||||
'compiled/jquery/fixDialogButtons'
|
||||
'vendor/jquery.ba-tinypubsub'
|
||||
], (I18n, $, curveGradesDialogTemplate) ->
|
||||
], (I18n, $, curveGradesDialogTemplate, htmlEscape) ->
|
||||
|
||||
class CurveGradesDialog
|
||||
constructor: ({@assignment, @students, context_url}) ->
|
||||
|
@ -133,12 +134,12 @@ define [
|
|||
pct = (users.length / maxCount)
|
||||
cnt = users.length
|
||||
color = (if idx == 0 then "#a03536" else "#007ab8")
|
||||
$("#results_list").prepend "<td style='padding: 1px;'><div title='" + cnt + " student" + (if cnt == 1 then "" else "s") + " will get " + idx + " points' style='border: 1px solid #888; background-color: " + color + "; width: " + width + "px; height: " + (100 * pct) + "px; margin-top: " + (100 * (1 - pct)) + "px;'> </div></td>"
|
||||
$("#results_values").prepend "<td style='text-align: center;'>" + idx + "</td>"
|
||||
$("#results_list").prepend "<td style='padding: 1px;'><div title='" + htmlEscape(I18n.t({one: "1 student will get %{num} points", other: "%{count} students will get %{num} points"}, {count: cnt, num: idx})) + "' style='border: 1px solid #888; background-color: " + htmlEscape(color) + "; width: " + htmlEscape(width) + "px; height: " + htmlEscape(100 * pct) + "px; margin-top: " + htmlEscape(100 * (1 - pct)) + "px;'> </div></td>"
|
||||
$("#results_values").prepend "<td style='text-align: center;'>" + htmlEscape(idx) + "</td>"
|
||||
skipCount = 0
|
||||
else
|
||||
skipCount++
|
||||
idx--
|
||||
$("#results_list").prepend "<td><div style='height: 100px; position: relative; width: 30px; font-size: 0.8em;'><img src='/images/number_of_students.png' alt='# of students'/><div style='position: absolute; top: 0; right: 3px;'>" + maxCount + "</div><div style='position: absolute; bottom: 0; right: 3px;'>0</div></div></td>"
|
||||
$("#results_list").prepend "<td><div style='height: 100px; position: relative; width: 30px; font-size: 0.8em;'><img src='/images/number_of_students.png' alt='" + htmlEscape(I18n.t("# of students")) + "'/><div style='position: absolute; top: 0; right: 3px;'>" + htmlEscape(maxCount) + "</div><div style='position: absolute; bottom: 0; right: 3px;'>0</div></div></td>"
|
||||
$("#results_values").prepend "<td> </td>"
|
||||
finalScores
|
||||
|
|
|
@ -410,16 +410,15 @@ define [
|
|||
window.location.reload()
|
||||
|
||||
assignmentGroupHtml: (group_name, group_weight) =>
|
||||
escaped_group_name = htmlEscape(group_name)
|
||||
if @weightedGroups()
|
||||
percentage = I18n.toPercentage(group_weight, precision: 2)
|
||||
"""
|
||||
#{escaped_group_name}<div class='assignment-points-possible'>
|
||||
#{I18n.t 'percent_of_grade', "%{percentage} of grade", percentage: percentage}
|
||||
#{htmlEscape(group_name)}<div class='assignment-points-possible'>
|
||||
#{htmlEscape I18n.t 'percent_of_grade', "%{percentage} of grade", percentage: percentage}
|
||||
</div>
|
||||
"""
|
||||
else
|
||||
"#{escaped_group_name}"
|
||||
htmlEscape(group_name)
|
||||
|
||||
# filter, sort, and build the dataset for slickgrid to read from, then force
|
||||
# a full redraw
|
||||
|
@ -536,7 +535,7 @@ define [
|
|||
(SubmissionCell[assignment.grading_type] || SubmissionCell).formatter(row, col, submission, assignment)
|
||||
|
||||
staticCellFormatter: (row, col, val) =>
|
||||
"<div class='cell-content gradebook-cell'>#{val}</div>"
|
||||
"<div class='cell-content gradebook-cell'>#{htmlEscape(val)}</div>"
|
||||
|
||||
uneditableCellFormatter: (row, col) =>
|
||||
"<div class='cell-content gradebook-cell grayed-out'></div>"
|
||||
|
@ -654,7 +653,7 @@ define [
|
|||
columnDef.name = columnDef.unminimizedName
|
||||
columnDef.minimized = false
|
||||
@$grid.find(".l#{colIndex}").add($columnHeader).removeClass('minimized')
|
||||
$columnHeader.find('.slick-column-name').html(columnDef.name)
|
||||
$columnHeader.find('.slick-column-name').html($.raw(columnDef.name))
|
||||
@assignmentsToHide = $.grep @assignmentsToHide, (el) -> el != columnDef.id
|
||||
userSettings.contextSet('hidden_columns', _.uniq(@assignmentsToHide))
|
||||
|
||||
|
@ -678,7 +677,7 @@ define [
|
|||
# add lines for dropped, late, resubmitted
|
||||
Array::push.apply htmlLines, $.map(SubmissionCell.classesBasedOnSubmission(submission, assignment), (c)=> GRADEBOOK_TRANSLATIONS["#submission_tooltip_#{c}"])
|
||||
else if assignment.points_possible?
|
||||
htmlLines.push I18n.t('points_out_of', "out of %{points_possible}", points_possible: assignment.points_possible)
|
||||
htmlLines.push htmlEscape(I18n.t('points_out_of', "out of %{points_possible}", points_possible: assignment.points_possible))
|
||||
|
||||
$hoveredCell.data('tooltip', $("<span />",
|
||||
class: 'gradebook-tooltip'
|
||||
|
@ -687,7 +686,7 @@ define [
|
|||
top: offset.top
|
||||
zIndex: 10000
|
||||
display: 'block'
|
||||
html: htmlLines.join('<br />')
|
||||
html: $.raw(htmlLines.join('<br />'))
|
||||
).appendTo('body')
|
||||
.css('top', (i, top) -> parseInt(top) - $(this).outerHeight()))
|
||||
|
||||
|
@ -972,7 +971,7 @@ define [
|
|||
|
||||
@parentColumns = [
|
||||
id: 'student'
|
||||
name: I18n.t 'student_name', 'Student Name'
|
||||
name: htmlEscape I18n.t 'student_name', 'Student Name'
|
||||
field: 'display_name'
|
||||
width: 150
|
||||
cssClass: "meta-cell"
|
||||
|
@ -981,7 +980,7 @@ define [
|
|||
formatter: @htmlContentFormatter
|
||||
,
|
||||
id: 'secondary_identifier'
|
||||
name: I18n.t 'secondary_id', 'Secondary ID'
|
||||
name: htmlEscape I18n.t 'secondary_id', 'Secondary ID'
|
||||
field: 'secondary_identifier'
|
||||
width: 100
|
||||
cssClass: "meta-cell secondary_identifier_cell"
|
||||
|
@ -1046,7 +1045,7 @@ define [
|
|||
field: "total_grade"
|
||||
formatter: @groupTotalFormatter
|
||||
name: """
|
||||
#{total}
|
||||
#{htmlEscape total}
|
||||
<div id=total_column_header></div>
|
||||
"""
|
||||
toolTip: total
|
||||
|
@ -1208,6 +1207,10 @@ define [
|
|||
else
|
||||
@totalGradeWarning = null
|
||||
|
||||
###
|
||||
xsslint jqueryObject.identifier createLink
|
||||
xsslint jqueryObject.function showLink hideLink
|
||||
###
|
||||
showCustomColumnDropdownOption: ->
|
||||
linkContainer = $("<li>").appendTo(".gradebook_drop_down")
|
||||
|
||||
|
|
|
@ -9,6 +9,10 @@ define [
|
|||
'jst/gradebook2/outcome_gradebook_student_cell'
|
||||
], (I18n, $, _, HeaderFilterView, OutcomeColumnView, numberCompare, cellTemplate, studentCellTemplate) ->
|
||||
|
||||
###
|
||||
xsslint safeString.method cellHtml
|
||||
###
|
||||
|
||||
Grid =
|
||||
filter: ['mastery', 'near-mastery', 'remedial']
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ define [
|
|||
|
||||
init: () ->
|
||||
submission = @opts.item[@opts.column.field]
|
||||
@$wrapper = $(@cellWrapper("<input #{@ariaLabel(submission.submission_type)} class='grade'/>")).appendTo(@opts.container)
|
||||
@$wrapper = $(@cellWrapper("<input #{htmlEscape @ariaLabel(submission.submission_type)} class='grade'/>")).appendTo(@opts.container)
|
||||
@$input = @$wrapper.find('input').focus().select()
|
||||
|
||||
destroy: () ->
|
||||
|
@ -82,15 +82,15 @@ define [
|
|||
|
||||
if turnitin = extractData(opts.submission)
|
||||
specialClasses.push('turnitin')
|
||||
innerContents += "<span class='gradebook-cell-turnitin #{turnitin.state}-score' />"
|
||||
innerContents += "<span class='gradebook-cell-turnitin #{htmlEscape turnitin.state}-score' />"
|
||||
|
||||
tooltipText = $.map(specialClasses, (c)-> GRADEBOOK_TRANSLATIONS["submission_tooltip_#{c}"]).join ', '
|
||||
|
||||
"""
|
||||
#{ if tooltipText then '<div class="gradebook-tooltip">'+ tooltipText + '</div>' else ''}
|
||||
<div class="gradebook-cell #{ if opts.editable then 'gradebook-cell-editable focus' else ''} #{opts.classes} #{specialClasses.join(' ')}">
|
||||
#{$.raw if tooltipText then '<div class="gradebook-tooltip">'+ htmlEscape(tooltipText) + '</div>' else ''}
|
||||
<div class="gradebook-cell #{htmlEscape if opts.editable then 'gradebook-cell-editable focus' else ''} #{htmlEscape opts.classes} #{htmlEscape specialClasses.join(' ')}">
|
||||
<a href="#" data-user-id=#{opts.submission.user_id} data-assignment-id=#{opts.assignment.id} class="gradebook-cell-comment"><span class="gradebook-cell-comment-label">submission comments</span></a>
|
||||
#{innerContents}
|
||||
#{$.raw innerContents}
|
||||
</div>
|
||||
"""
|
||||
|
||||
|
@ -112,7 +112,7 @@ define [
|
|||
|
||||
@submissionIcon: (submission_type) ->
|
||||
klass = SubmissionCell.iconFromSubmissionType(submission_type)
|
||||
"<i class='icon-#{klass}' ></i>"
|
||||
"<i class='icon-#{htmlEscape klass}' ></i>"
|
||||
|
||||
@iconFromSubmissionType: (submission_type) ->
|
||||
switch submission_type
|
||||
|
@ -135,7 +135,7 @@ define [
|
|||
@$wrapper = $(@cellWrapper("""
|
||||
<div class="overflow-wrapper">
|
||||
<div class="grade-and-outof-wrapper">
|
||||
<input type="text" #{@ariaLabel(submission.submission_type)} class="grade"/><span class="outof"><span class="divider">/</span>#{@opts.column.object.points_possible}</span>
|
||||
<input type="text" #{htmlEscape @ariaLabel(submission.submission_type)} class="grade"/><span class="outof"><span class="divider">/</span>#{htmlEscape @opts.column.object.points_possible}</span>
|
||||
</div>
|
||||
</div>
|
||||
""", { classes: 'gradebook-cell-out-of-formatter' })).appendTo(@opts.container)
|
||||
|
@ -144,7 +144,7 @@ define [
|
|||
class SubmissionCell.letter_grade extends SubmissionCell
|
||||
@formatter: (row, col, submission, assignment) ->
|
||||
innerContents = if submission.score
|
||||
"#{submission.grade}<span class='letter-grade-points'>#{submission.score}</span>"
|
||||
"#{htmlEscape submission.grade}<span class='letter-grade-points'>#{htmlEscape submission.score}</span>"
|
||||
else
|
||||
submission.grade
|
||||
|
||||
|
@ -165,7 +165,7 @@ define [
|
|||
htmlFromSubmission: (options={}) ->
|
||||
cssClass = classFromSubmission(options.submission)
|
||||
SubmissionCell::cellWrapper("""
|
||||
<a data-value="#{cssClass}" class="gradebook-checkbox gradebook-checkbox-#{cssClass} #{'editable' if options.editable}" href="#">#{cssClass}</a>
|
||||
<a data-value="#{htmlEscape cssClass}" class="gradebook-checkbox gradebook-checkbox-#{htmlEscape cssClass} #{htmlEscape('editable' if options.editable)}" href="#">#{htmlEscape cssClass}</a>
|
||||
""", options)
|
||||
|
||||
# htmlFromSubmission = (submission, editable = false) ->
|
||||
|
|
|
@ -53,7 +53,7 @@ define [
|
|||
courseText = I18n.t('#helpers.course', 'Course')
|
||||
courseDatetime = $.datetimeString(datetime, timezone: ENV.CONTEXT_TIMEZONE)
|
||||
if localDatetime != courseDatetime
|
||||
titleText = "#{localText}: #{localDatetime}<br>#{courseText}: #{courseDatetime}"
|
||||
titleText = "#{htmlEscape localText}: #{htmlEscape localDatetime}<br>#{htmlEscape courseText}: #{htmlEscape courseDatetime}"
|
||||
|
||||
if justText
|
||||
new Handlebars.SafeString titleText
|
||||
|
@ -71,7 +71,7 @@ define [
|
|||
else
|
||||
timeTitle = $.datetimeString(datetime)
|
||||
|
||||
new Handlebars.SafeString "<time data-tooltip title='#{timeTitle}' datetime='#{datetime.toISOString()}' #{'pubdate' if pubdate}>#{$.friendlyDatetime(fudged)}</time>"
|
||||
new Handlebars.SafeString "<time data-tooltip title='#{htmlEscape timeTitle}' datetime='#{datetime.toISOString()}' #{$.raw('pubdate' if pubdate)}>#{$.friendlyDatetime(fudged)}</time>"
|
||||
|
||||
|
||||
|
||||
|
@ -79,7 +79,7 @@ define [
|
|||
formattedDate : (datetime, format, {hash: {pubdate}}) ->
|
||||
return unless datetime?
|
||||
datetime = tz.parse(datetime) unless _.isDate datetime
|
||||
new Handlebars.SafeString "<time data-tooltip title='#{$.datetimeString(datetime)}' datetime='#{datetime.toISOString()}' #{'pubdate' if pubdate}>#{datetime.toString(format)}</time>"
|
||||
new Handlebars.SafeString "<time data-tooltip title='#{$.datetimeString(datetime)}' datetime='#{datetime.toISOString()}' #{$.raw('pubdate' if pubdate)}>#{htmlEscape datetime.toString(format)}</time>"
|
||||
|
||||
# IMPORTANT: these next two handlebars helpers emit profile-timezone
|
||||
# human-formatted strings. don't send them as is to the server (you can
|
||||
|
@ -332,11 +332,11 @@ define [
|
|||
attributes = for key, val of inputProps when val?
|
||||
"#{htmlEscape key}=\"#{htmlEscape val}\""
|
||||
|
||||
hiddenDisabled = if inputProps.disabled then "disabled" else ""
|
||||
hiddenDisabledHtml = if inputProps.disabled then "disabled" else ""
|
||||
|
||||
new Handlebars.SafeString """
|
||||
<input name="#{htmlEscape inputProps.name}" type="hidden" value="0" #{hiddenDisabled}>
|
||||
<input #{attributes.join ' '} />
|
||||
<input name="#{htmlEscape inputProps.name}" type="hidden" value="0" #{hiddenDisabledHtml}>
|
||||
<input #{$.raw attributes.join ' '} />
|
||||
"""
|
||||
|
||||
toPercentage: (number) ->
|
||||
|
|
|
@ -85,9 +85,9 @@ define [
|
|||
if newTitle = @$dialog.find("a[href='#{panelId}'] .text").text()
|
||||
newTitle = $("
|
||||
<a class='ui-dialog-header-backlink' href='#help-dialog-options'>
|
||||
#{I18n.t('Back', 'Back')}
|
||||
#{htmlEscape(I18n.t('Back', 'Back'))}
|
||||
</a>
|
||||
<span>#{newTitle}</span>
|
||||
<span>#{htmlEscape(newTitle)}</span>
|
||||
")
|
||||
else
|
||||
newTitle = @defaultTitle
|
||||
|
@ -114,11 +114,12 @@ define [
|
|||
@$dialog.dialog('close')
|
||||
|
||||
$.when(coursesDfd, @helpLinksDfd).done ([courses]) ->
|
||||
options = $.map courses, (c) ->
|
||||
"<option value='course_#{c.id}_admins' #{if ENV.context_id is c.id then 'selected' else ''}>
|
||||
optionsHtml = $.map(courses, (c) ->
|
||||
"<option value='course_#{c.id}_admins' #{$.raw if ENV.context_id is c.id then 'selected' else ''}>
|
||||
#{htmlEscape(c.name)}
|
||||
</option>"
|
||||
$form.find('[name="recipients[]"]').html(options.join '')
|
||||
).join('')
|
||||
$form.find('[name="recipients[]"]').html(optionsHtml)
|
||||
|
||||
initTriggers: ->
|
||||
$('.help_dialog_trigger').click preventDefault @open
|
||||
|
|
|
@ -5,6 +5,9 @@ define [
|
|||
'jquery.ajaxJSON'
|
||||
'jqueryui/dialog'
|
||||
], (I18n, $, Slick) ->
|
||||
###
|
||||
xsslint safeString.identifier klass d out_of runtime_string
|
||||
###
|
||||
|
||||
fillin_job_data = (job) ->
|
||||
$('#show-job .show-field').each (idx, field) =>
|
||||
|
|
|
@ -23,6 +23,9 @@ define [
|
|||
$this.stop(true, true).remove()
|
||||
initFlashContainer() # look for the container on script load
|
||||
|
||||
###
|
||||
xsslint safeString.function escapeContent
|
||||
###
|
||||
escapeContent = (content) ->
|
||||
if content.hasOwnProperty('html') then content.html else htmlEscape(content)
|
||||
|
||||
|
@ -37,10 +40,10 @@ define [
|
|||
|
||||
flashBox = (type, content, timeout, cssOptions = {}) ->
|
||||
$node = $("""
|
||||
<li class="ic-flash-#{type}">
|
||||
<li class="ic-flash-#{htmlEscape(type)}">
|
||||
<i></i>
|
||||
#{escapeContent(content)}
|
||||
<a href="#" class="close_link icon-end">#{I18n.t("close", "Close")}</a>
|
||||
<a href="#" class="close_link icon-end">#{htmlEscape I18n.t("close", "Close")}</a>
|
||||
</li>
|
||||
""")
|
||||
|
||||
|
|
|
@ -26,8 +26,8 @@ define [
|
|||
"#{dimensions.width}/height/#{dimensions.height}/bgcolor/000000/type/2/vid_sec/5"
|
||||
|
||||
$thumbnail = $ "<span
|
||||
style='background-image: url(#{backgroundUrl});'
|
||||
class='media_comment_thumbnail media_comment_thumbnail-#{size}'
|
||||
style='background-image: url(#{htmlEscape(backgroundUrl)});'
|
||||
class='media_comment_thumbnail media_comment_thumbnail-#{htmlEscape(size)}'
|
||||
>
|
||||
<span class='media_comment_thumbnail_play_button'>
|
||||
#{htmlEscape I18n.t 'click_to_view', 'Click to view'}
|
||||
|
|
|
@ -16,8 +16,8 @@ define [
|
|||
if @$fileInput
|
||||
@$fileInput.off 'change', callback
|
||||
@$fileInput.remove()
|
||||
fileInput = "<input id='#{id}' type='file' style='display: none;'>"
|
||||
$(parentId).append(fileInput)
|
||||
fileInputHtml = "<input id='#{id}' type='file' style='display: none;'>"
|
||||
$(parentId).append(fileInputHtml)
|
||||
@$fileInput = $("##{id}")
|
||||
@$fileInput.on 'change', callback
|
||||
|
||||
|
|
|
@ -68,7 +68,7 @@ define [
|
|||
showErrorMessage: (message) ->
|
||||
@hideProgBar()
|
||||
$('#media_upload_feedback').css('visibility', 'visible')
|
||||
$("#media_upload_feedback_text").html(message)
|
||||
$("#media_upload_feedback_text").text(message)
|
||||
|
||||
showProgBar: ->
|
||||
$('#media_upload_progress').css('visibility', 'visible').progressbar()
|
||||
|
|
|
@ -7,7 +7,8 @@ define [
|
|||
'compiled/collections/DiscussionEntriesCollection'
|
||||
'compiled/models/Assignment'
|
||||
'compiled/models/DateGroup'
|
||||
], (I18n, Backbone, $, _, ParticipantCollection, DiscussionEntriesCollection, Assignment, DateGroup) ->
|
||||
'str/stripTags'
|
||||
], (I18n, Backbone, $, _, ParticipantCollection, DiscussionEntriesCollection, Assignment, DateGroup, stripTags) ->
|
||||
|
||||
class DiscussionTopic extends Backbone.Model
|
||||
resourceName: 'discussion_topics'
|
||||
|
@ -116,7 +117,7 @@ define [
|
|||
@entries.reset(entries)
|
||||
|
||||
summary: ->
|
||||
$('<div/>').html(@get('message')).text() || ''
|
||||
stripTags @get('message')
|
||||
|
||||
# TODO: this would belong in Backbone.model, but I dont know of others are going to need it much
|
||||
# or want to commit to this api so I am just putting it here for now
|
||||
|
|
|
@ -7,8 +7,9 @@ define [
|
|||
'jquery'
|
||||
'underscore'
|
||||
'Backbone'
|
||||
'str/stripTags'
|
||||
'jquery.ajaxJSON'
|
||||
], (I18n, $, _, Backbone) ->
|
||||
], (I18n, $, _, Backbone, stripTags) ->
|
||||
|
||||
##
|
||||
# Model representing an entry in discussion topic
|
||||
|
@ -172,8 +173,7 @@ define [
|
|||
##
|
||||
# Computed attribute
|
||||
summary: ->
|
||||
@escapeDiv ||= $('<div/>')
|
||||
@escapeDiv.html(@get('message')).text()
|
||||
stripTags @get('message')
|
||||
|
||||
##
|
||||
# Not familiar enough with Backbone.sync to do this, using ajaxJSON
|
||||
|
|
|
@ -8,10 +8,11 @@ define [
|
|||
'jst/registration/studentDialog'
|
||||
'jst/registration/parentDialog'
|
||||
'compiled/util/addPrivacyLinkToDialog'
|
||||
'str/htmlEscape'
|
||||
'compiled/jquery/validate'
|
||||
'jquery.instructure_forms'
|
||||
'jquery.instructure_date_and_time'
|
||||
], ($, _, I18n, preventDefault, registrationErrors, teacherDialog, studentDialog, parentDialog, addPrivacyLinkToDialog) ->
|
||||
], ($, _, I18n, preventDefault, registrationErrors, teacherDialog, studentDialog, parentDialog, addPrivacyLinkToDialog, htmlEscape) ->
|
||||
|
||||
$nodes = {}
|
||||
templates = {teacherDialog, studentDialog, parentDialog}
|
||||
|
@ -24,19 +25,20 @@ define [
|
|||
"teacher_dialog.agree_to_terms_and_pp"
|
||||
"You agree to the *terms of use* and acknowledge the **privacy policy**."
|
||||
wrappers: [
|
||||
"<a href=\"#{terms_of_use_url}\" target=\"_blank\">$1</a>"
|
||||
"<a href=\"#{privacy_policy_url}\" target=\"_blank\">$1</a>"
|
||||
"<a href=\"#{htmlEscape terms_of_use_url}\" target=\"_blank\">$1</a>"
|
||||
"<a href=\"#{htmlEscape privacy_policy_url}\" target=\"_blank\">$1</a>"
|
||||
]
|
||||
)
|
||||
|
||||
signupDialog = (id, title) ->
|
||||
return unless templates[id]
|
||||
$node = $nodes[id] ?= $('<div />')
|
||||
$node.html templates[id](
|
||||
html = templates[id](
|
||||
account: ENV.ACCOUNT.registration_settings
|
||||
terms_required: ENV.ACCOUNT.terms_required
|
||||
terms_html: termsHtml(ENV.ACCOUNT)
|
||||
)
|
||||
$node.html html
|
||||
$node.find('.date-field').datetime_field()
|
||||
|
||||
$node.find('.signup_link').click preventDefault ->
|
||||
|
|
|
@ -52,9 +52,9 @@ define [
|
|||
th =
|
||||
quoteClump: (lines) ->
|
||||
"<div class='quoted_text_holder'>
|
||||
<a href='#' class='show_quoted_text_link'>#{I18n.t("quoted_text_toggle", "show quoted text")}</a>
|
||||
<a href='#' class='show_quoted_text_link'>#{htmlEscape I18n.t("quoted_text_toggle", "show quoted text")}</a>
|
||||
<div class='quoted_text' style='display: none;'>
|
||||
#{lines.join "\n"}
|
||||
#{$.raw lines.join "\n"}
|
||||
</div>
|
||||
</div>"
|
||||
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
define [
|
||||
'jquery'
|
||||
'underscore'
|
||||
], ($, _) ->
|
||||
'str/htmlEscape'
|
||||
], ($, _, htmlEscape) ->
|
||||
|
||||
# use this method to process any user content fields returned in api responses
|
||||
# this is important to handle object/embed tags safely, and to properly display audio/video tags
|
||||
|
@ -9,9 +10,9 @@ define [
|
|||
$dummy = $('<div />').html(html)
|
||||
# finds any <video/audio class="instructure_inline_media_comment"> and turns them into media comment thumbnails
|
||||
$dummy.find('video.instructure_inline_media_comment,audio.instructure_inline_media_comment').replaceWith ->
|
||||
$node = $("<a id='media_comment_#{$(this).data('media_comment_id')}'
|
||||
data-media_comment_type='#{$(this).data('media_comment_type')}'
|
||||
class='instructure_inline_media_comment #{this.nodeName.toLowerCase()}_comment' />")
|
||||
$node = $("<a id='media_comment_#{htmlEscape($(this).data('media_comment_id'))}'
|
||||
data-media_comment_type='#{htmlEscape($(this).data('media_comment_type'))}'
|
||||
class='instructure_inline_media_comment #{htmlEscape(this.nodeName.toLowerCase())}_comment' />")
|
||||
$node.html $(this).html()
|
||||
$node
|
||||
|
||||
|
@ -34,11 +35,11 @@ define [
|
|||
uuid = _.uniqueId("uc_")
|
||||
action = "/object_snippet"
|
||||
action = "//#{ENV.files_domain}#{action}" if ENV.files_domain
|
||||
$form = $("<form action='#{action}' method='post' class='user_content_post_form' target='#{uuid}' id='form-#{uuid}' />")
|
||||
$form = $("<form action='#{htmlEscape(action)}' method='post' class='user_content_post_form' target='#{htmlEscape(uuid)}' id='form-#{htmlEscape(uuid)}' />")
|
||||
$form.append($("<input type='hidden'/>").attr({name: 'object_data', value: $this.data('uc_snippet')}))
|
||||
$form.append($("<input type='hidden'/>").attr({name: 's', value: $this.data('uc_sig')}))
|
||||
$('body').append($form)
|
||||
setTimeout((-> $form.submit()), 0)
|
||||
$("<iframe class='user_content_iframe' name='#{uuid}' style='width: #{$this.data('uc_width')}; height: #{$this.data('uc_height')};' frameborder='0' />")
|
||||
$("<iframe class='user_content_iframe' name='#{htmlEscape(uuid)}' style='width: #{htmlEscape($this.data('uc_width'))}; height: #{htmlEscape($this.data('uc_height'))};' frameborder='0' />")
|
||||
|
||||
$dummy.html()
|
||||
|
|
|
@ -18,6 +18,10 @@
|
|||
|
||||
define ['underscore'], (_) ->
|
||||
|
||||
###
|
||||
xsslint xssable.receiver.whitelist builder
|
||||
###
|
||||
|
||||
BlobFactory =
|
||||
fromCanvas: (canvas, type = 'image/jpeg') ->
|
||||
url = canvas.toDataURL(type)
|
||||
|
|
|
@ -31,5 +31,5 @@ define [
|
|||
}
|
||||
|
||||
"""
|
||||
$('<div/>').html("<style>#{css.join('')}</style>").appendTo(document.body)
|
||||
$('<div/>').html("<style>#{$.raw(css.join(''))}</style>").appendTo(document.body)
|
||||
|
||||
|
|
|
@ -13,12 +13,12 @@ define [
|
|||
context
|
||||
|
||||
format = (context, linkToContexts) ->
|
||||
str = h(context.name)
|
||||
html = h(context.name)
|
||||
if context.activeFilter
|
||||
str = "<span class='active-filter'>#{str}</span>"
|
||||
html = "<span class='active-filter'>#{html}</span>"
|
||||
if linkToContexts and context.type is "course"
|
||||
str = "<a href='#{h(context.url)}'>#{str}</a>"
|
||||
$.raw str
|
||||
html = "<a href='#{h(context.url)}'>#{html}</a>"
|
||||
$.raw html
|
||||
|
||||
# given a map of ids by type (e.g. {courses: [1, 2], groups: ...})
|
||||
# and a map of possible contexts by type,
|
||||
|
|
|
@ -5,6 +5,10 @@ define [
|
|||
'str/htmlEscape'
|
||||
], (I18n, $, _, h) ->
|
||||
|
||||
###
|
||||
xsslint safeString.identifier i
|
||||
###
|
||||
|
||||
builders =
|
||||
year: (options, htmlOptions) ->
|
||||
step = if options.startYear < options.endYear then 1 else -1
|
||||
|
@ -56,12 +60,11 @@ define [
|
|||
for i in [0...options.order.length]
|
||||
type = options.order[i]
|
||||
tName = name.replace(/(\]?)$/, "(" + position[type] + "i)$1")
|
||||
$result.append(
|
||||
builders[type](
|
||||
options,
|
||||
_.extend({name: tName}, htmlOptions),
|
||||
dateSettings
|
||||
)
|
||||
html = builders[type](
|
||||
options,
|
||||
_.extend({name: tName}, htmlOptions),
|
||||
dateSettings
|
||||
)
|
||||
$result.append(html)
|
||||
delete htmlOptions.id
|
||||
$result
|
||||
|
|
|
@ -61,7 +61,7 @@ define [
|
|||
for i in [0..count-1]
|
||||
iframe = document.createElement('iframe')
|
||||
$(iframe).addClass('hidden kaltura-analytics')
|
||||
$(document.body).append(iframe)
|
||||
$(document.body).append($(iframe))
|
||||
|
||||
# there is no reliable way to know when a remote url has loaded in an
|
||||
# iframe, so just send them every 4 seconds
|
||||
|
@ -160,4 +160,4 @@ define [
|
|||
if pluginSettings && pluginSettings.do_analytics
|
||||
ka = new KalturaAnalytics(mediaId, mediaElement, pluginSettings)
|
||||
ka.addListeners()
|
||||
ka
|
||||
ka
|
||||
|
|
|
@ -17,7 +17,7 @@ define [
|
|||
#{h(I18n.t('other', 'other', count: strOrArray.length))}
|
||||
<span>
|
||||
<ul>
|
||||
#{(('<li>' + h(str) + '</li>') for str in strOrArray).join('')}
|
||||
#{$.raw (('<li>' + h(str) + '</li>') for str in strOrArray).join('')}
|
||||
</ul>
|
||||
</span>
|
||||
</span>
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
# requires $.sameDate, $.dateString, $.timeString, $.datetimeString
|
||||
define ['i18n!dates', 'jquery', 'timezone', 'jquery.instructure_date_and_time'], (I18n, $, tz) ->
|
||||
define ['i18n!dates', 'jquery', 'timezone', 'str/htmlEscape', 'jquery.instructure_date_and_time'], (I18n, $, tz, htmlEscape) ->
|
||||
semanticDateRange = (startISO, endISO) ->
|
||||
unless startISO
|
||||
return """
|
||||
<span class="date-range date-range-no-date">
|
||||
#{I18n.t 'no_date', 'No Date'}
|
||||
#{htmlEscape I18n.t 'no_date', 'No Date'}
|
||||
</span>
|
||||
"""
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ define [
|
|||
'jst/discussions/EntryCollectionView'
|
||||
'jst/discussions/entryStats'
|
||||
'compiled/views/DiscussionTopic/EntryView'
|
||||
], (I18n, $, walk, {View}, template, entryStats, EntryView) ->
|
||||
], (I18n, $, walk, {View}, template, entryStatsTemplate, EntryView) ->
|
||||
|
||||
class EntryCollectionView extends View
|
||||
|
||||
|
@ -110,7 +110,7 @@ define [
|
|||
one: "Show one reply"
|
||||
other: "Show all %{count} replies"
|
||||
{count: stats.total + @collection.options.perPage}
|
||||
@nextLink.html entryStats({stats, moreText, showMore: yes})
|
||||
@nextLink.html entryStatsTemplate({stats, moreText, showMore: yes})
|
||||
@nextLink.addClass 'showMore loadNext'
|
||||
if @options.threaded
|
||||
@nextLink.insertAfter @list
|
||||
|
|
|
@ -17,7 +17,7 @@ define [
|
|||
'compiled/str/convertApiUserContent'
|
||||
'jst/_avatar'
|
||||
'jst/discussions/_reply_form'
|
||||
], ($, _, I18n, MarkAsReadWatcher, walk, Backbone, EntryCollection, entryContentPartial, deletedEntriesTemplate, entryWithRepliesTemplate, entryStats, Reply, EntryEditor, htmlEscape, {publish}, convertApiUserContent) ->
|
||||
], ($, _, I18n, MarkAsReadWatcher, walk, Backbone, EntryCollection, entryContentPartial, deletedEntriesTemplate, entryWithRepliesTemplate, entryStatsTemplate, Reply, EntryEditor, htmlEscape, {publish}, convertApiUserContent) ->
|
||||
|
||||
class EntryView extends Backbone.View
|
||||
|
||||
|
@ -124,11 +124,11 @@ define [
|
|||
stats = @countPosterity()
|
||||
html = """
|
||||
<div class='new-and-total-badge'>
|
||||
<span class="new-items">#{stats.unread}</span>
|
||||
<span class="total-items">#{stats.total}</span>
|
||||
<span class="new-items">#{htmlEscape stats.unread}</span>
|
||||
<span class="total-items">#{htmlEscape stats.total}</span>
|
||||
</div>
|
||||
"""
|
||||
@$headerBadges.append entryStats({stats})
|
||||
@$headerBadges.append entryStatsTemplate({stats})
|
||||
@addedCountsToHeader = true
|
||||
|
||||
toggleDeleted: (model, deleted) =>
|
||||
|
@ -179,10 +179,10 @@ define [
|
|||
|
||||
renderDescendantsLink: ->
|
||||
stats = @countPosterity()
|
||||
@descendantsLink = $ '<div/>'
|
||||
@descendantsLink.html entryStats({stats, showMore: yes})
|
||||
@descendantsLink.addClass 'showMore loadDescendants'
|
||||
@$replies.append @descendantsLink
|
||||
@$descendantsLink = $ '<div/>'
|
||||
@$descendantsLink.html entryStatsTemplate({stats, showMore: yes})
|
||||
@$descendantsLink.addClass 'showMore loadDescendants'
|
||||
@$replies.append @$descendantsLink
|
||||
|
||||
countPosterity: ->
|
||||
stats = unread: 0, total: 0
|
||||
|
|
|
@ -5,7 +5,8 @@ define [
|
|||
'underscore'
|
||||
'jst/ExternalTools/AddAppView'
|
||||
'jquery.disableWhileLoading'
|
||||
], (Backbone, I18n, $, _, template, disableWhileLoading) ->
|
||||
'str/htmlEscape'
|
||||
], (Backbone, I18n, $, _, template, disableWhileLoading, htmlEscape) ->
|
||||
|
||||
class AddAppView extends Backbone.View
|
||||
template: template
|
||||
|
@ -104,14 +105,14 @@ define [
|
|||
addError: (input, message) ->
|
||||
input = @$(input)
|
||||
input.parents('.control-group').addClass('error')
|
||||
input.after("<span class='help-inline'>#{message}</span>")
|
||||
input.after("<span class='help-inline'>#{htmlEscape message}</span>")
|
||||
input.one 'keypress', ->
|
||||
$(this).parents('.control-group').removeClass('error')
|
||||
$(this).parents('.control-group').find('.help-inline').remove()
|
||||
|
||||
onSaveFail: (model) =>
|
||||
message = I18n.t 'generic_error', 'There was an error in processing your request'
|
||||
@$el.prepend("<div class='alert alert-error'>#{message}</span>")
|
||||
@$el.prepend("<div class='alert alert-error'>#{htmlEscape message}</span>")
|
||||
|
||||
onSaveSuccess: (model) =>
|
||||
@app.set('is_installed', true)
|
||||
|
|
|
@ -3,8 +3,9 @@ define [
|
|||
'jquery'
|
||||
'jst/ExternalTools/EditView'
|
||||
'compiled/views/ValidatedFormView'
|
||||
'str/htmlEscape'
|
||||
'compiled/jquery/fixDialogButtons'
|
||||
], (I18n, $, template, ValidatedFormView) ->
|
||||
], (I18n, $, template, ValidatedFormView, htmlEscape) ->
|
||||
|
||||
class EditView extends ValidatedFormView
|
||||
template: template
|
||||
|
@ -64,7 +65,7 @@ define [
|
|||
addError: (input, message) ->
|
||||
input = $(input)
|
||||
input.parents('.control-group').addClass('error')
|
||||
input.after("<span id='#{input.attr("name")}_error_message' class='help-inline'>#{message}</span>")
|
||||
input.after("<span id='#{htmlEscape input.attr("name")}_error_message' class='help-inline'>#{htmlEscape message}</span>")
|
||||
input.attr('aria-describedby', "#{input.attr('name')}_error_message")
|
||||
input.attr('aria-invalid', 'true')
|
||||
input.one 'keypress', ->
|
||||
|
@ -76,7 +77,7 @@ define [
|
|||
onSaveFail: (xhr) =>
|
||||
super
|
||||
message = I18n.t 'generic_error', 'There was an error in processing your request'
|
||||
@$el.prepend("<div class='alert alert-error'>#{message}</span>")
|
||||
@$el.prepend("<div class='alert alert-error'>#{htmlEscape message}</span>")
|
||||
delay = (ms, func) -> setTimeout func, ms
|
||||
delay 1, -> @$("[aria-invalid='true']").first().focus()
|
||||
|
||||
|
|
|
@ -123,7 +123,7 @@ define [
|
|||
view = @$(event.currentTarget).closest('.external_tool_item').data('view')
|
||||
tool = view.model
|
||||
msg = I18n.t 'remove_tool', "Are you sure you want to remove this tool?"
|
||||
dialog = $("<div>#{msg}</div>").dialog
|
||||
dialog = $("<div>#{htmlEscape msg}</div>").dialog
|
||||
modal: true,
|
||||
resizable: false
|
||||
title: I18n.t('delete', 'Delete') + ' ' + tool.get('name') + '?'
|
||||
|
@ -149,4 +149,4 @@ define [
|
|||
@$('[data-installed-state]').removeClass('active')
|
||||
@$('[data-installed-state="' + @appCenterView.targetInstalledState + '"]').addClass('active')
|
||||
@$('[data-installed-state="' + @appCenterView.targetInstalledState + '"] > a').attr('aria-selected', 'true')
|
||||
@appCenterView.render()
|
||||
@appCenterView.render()
|
||||
|
|
|
@ -70,4 +70,4 @@ define [
|
|||
|
||||
showErrorMessage: ->
|
||||
message = I18n.t 'missing_stars', 'You must select a star rating'
|
||||
@$el.prepend("<div class='alert alert-error'>#{message}</span>")
|
||||
@$el.prepend("<div class='alert alert-error'>#{htmlEscape(message)}</span>")
|
||||
|
|
|
@ -44,5 +44,6 @@ define [
|
|||
fullsize: "https://farm#{photo.farm}.static.flickr.com/#{photo.server}/#{photo.id}_#{photo.secret}.jpg"
|
||||
source: "https://secure.flickr.com/photos/#{photo.owner}/#{photo.id}"
|
||||
title: photo.title
|
||||
html = html.join('')
|
||||
|
||||
@$('.flickrResults').showIf(!!photos.length).html html.join('')
|
||||
@$('.flickrResults').showIf(!!photos.length).html html
|
||||
|
|
|
@ -16,8 +16,8 @@ define [
|
|||
|
||||
# you're responsible for rendering the content via HB
|
||||
# and passing it in
|
||||
render: (content) ->
|
||||
@$el.html(content)
|
||||
render: (html) ->
|
||||
@$el.html(html)
|
||||
@
|
||||
|
||||
bindOpenKeys: ->
|
||||
|
|
|
@ -8,7 +8,7 @@ define [
|
|||
'jst/_messageStudentsWhoRecipientList'
|
||||
'underscore'
|
||||
'compiled/jquery/serializeForm'
|
||||
], (I18n, $, DialogFormView, template, wrapperTemplate, Conversation, recipientList, _) ->
|
||||
], (I18n, $, DialogFormView, template, wrapperTemplate, Conversation, recipientListTemplate, _) ->
|
||||
|
||||
class MessageStudentsDialog extends DialogFormView
|
||||
|
||||
|
@ -76,7 +76,7 @@ define [
|
|||
updateListOfRecipients: =>
|
||||
groupName = @$recipientGroupName.val()
|
||||
{recipients} = @_findRecipientGroupByName groupName
|
||||
@$messageRecipients.html recipientList recipients: recipients
|
||||
@$messageRecipients.html recipientListTemplate recipients: recipients
|
||||
|
||||
onSaveSuccess: ->
|
||||
@close()
|
||||
|
|
|
@ -32,9 +32,9 @@ define [
|
|||
# I'm sorry, Voiceover + jQueryUI made me do it
|
||||
# VO won't acknowledge the existance of the re-rendered view
|
||||
# but if we render just the options, it's OK
|
||||
fragment = $(@template @toJSON())
|
||||
opts = fragment.filter('select').find('option')
|
||||
@$('select').empty().append(opts)
|
||||
$fragment = $(@template @toJSON())
|
||||
$opts = $fragment.filter('select').find('option')
|
||||
@$('select').empty().append($opts)
|
||||
|
||||
value: ->
|
||||
@$('select').val()
|
||||
|
|
|
@ -98,11 +98,11 @@ define [
|
|||
|
||||
# attaches child views to @$childContainer
|
||||
attachChildViews: ->
|
||||
container = @$childContainer.detach()
|
||||
$container = @$childContainer.detach()
|
||||
if @parentListView
|
||||
container.append(@parentListView.render().el)
|
||||
container.append(@listView.render().el)
|
||||
@$content.append(container)
|
||||
$container.append(@parentListView.render().el)
|
||||
$container.append(@listView.render().el)
|
||||
@$content.append($container)
|
||||
|
||||
cleanup: =>
|
||||
@parentListView?.remove()
|
||||
|
|
|
@ -3,8 +3,9 @@ define [
|
|||
'jquery'
|
||||
'compiled/fn/preventDefault'
|
||||
'Backbone'
|
||||
'str/htmlEscape'
|
||||
'jquery.instructure_forms'
|
||||
], (I18n, $, preventDefault, Backbone) ->
|
||||
], (I18n, $, preventDefault, Backbone, htmlEscape) ->
|
||||
|
||||
class PublishButton extends Backbone.View
|
||||
disabledClass: 'disabled'
|
||||
|
@ -167,7 +168,7 @@ define [
|
|||
@$el.attr 'aria-pressed', options.buttonClass is @publishedClass
|
||||
@$icon.addClass options.iconClass
|
||||
|
||||
@$text.html " #{options.text}"
|
||||
@$text.html " #{htmlEscape(options.text)}"
|
||||
|
||||
# unpublishable
|
||||
if !@model.get('unpublishable')? or @model.get('unpublishable')
|
||||
|
|
|
@ -85,9 +85,10 @@ define [
|
|||
messages = errors[integerField]
|
||||
control_group.toggleClass('error', messages?)
|
||||
if messages
|
||||
helpInline = $('<span class="help-inline"></span>')
|
||||
helpInline.html((htmlEscape(message) for {message} in messages).join('<br/>'))
|
||||
control_group.find('.controls').append(helpInline)
|
||||
$helpInline = $('<span class="help-inline"></span>')
|
||||
html = (htmlEscape(message) for {message} in messages).join('<br/>')
|
||||
$helpInline.html(html)
|
||||
control_group.find('.controls').append($helpInline)
|
||||
|
||||
findItem: ->
|
||||
@hideErrors()
|
||||
|
|
|
@ -74,6 +74,7 @@ define [
|
|||
messages = errors[integerField]
|
||||
control_group.toggleClass('error', messages?)
|
||||
if messages
|
||||
helpInline = $('<span class="help-inline"></span>')
|
||||
helpInline.html((htmlEscape(message) for {message} in messages).join('<br/>'))
|
||||
control_group.find('.controls').append(helpInline)
|
||||
$helpInline = $('<span class="help-inline"></span>')
|
||||
html = (htmlEscape(message) for {message} in messages).join('<br/>')
|
||||
$helpInline.html(html)
|
||||
control_group.find('.controls').append($helpInline)
|
||||
|
|
|
@ -76,7 +76,7 @@ define [
|
|||
total_weight += v.findWeight() || 0
|
||||
total_weight = round(total_weight,2)
|
||||
|
||||
@$el.find('#percent_total').html(total_weight + "%")
|
||||
@$el.find('#percent_total').text(total_weight + "%")
|
||||
|
||||
clearWeights: ->
|
||||
@weights = []
|
||||
|
@ -87,7 +87,7 @@ define [
|
|||
for v in @weights
|
||||
total_weight += v.findWeight() || 0
|
||||
total_weight = round(total_weight,2)
|
||||
@$el.find('#percent_total').html(total_weight + "%")
|
||||
@$el.find('#percent_total').text(total_weight + "%")
|
||||
|
||||
toJSON: ->
|
||||
data = super
|
||||
|
|
|
@ -72,7 +72,7 @@ define [
|
|||
@dueDateViews.push dueDateView
|
||||
@hideOrShowRemoveButtons()
|
||||
if render
|
||||
row = dueDateView.render().$el
|
||||
@$el.append row
|
||||
$row = dueDateView.render().$el
|
||||
@$el.append $row
|
||||
@reRenderSections()
|
||||
row.find(".section-list").focus()
|
||||
$row.find(".section-list").focus()
|
||||
|
|
|
@ -3,8 +3,9 @@ define [
|
|||
'Backbone'
|
||||
'jquery'
|
||||
'underscore'
|
||||
'str/htmlEscape'
|
||||
'compiled/jquery/fixDialogButtons'
|
||||
], (turnitinSettingsDialog, { View }, $, _) ->
|
||||
], (turnitinSettingsDialog, { View }, $, _, htmlEscape) ->
|
||||
|
||||
class TurnitinSettingsDialog extends View
|
||||
|
||||
|
@ -37,14 +38,15 @@ define [
|
|||
json = super
|
||||
_.extend json,
|
||||
wordsInput: """
|
||||
<input class="span1" id="exclude_small_matches_words_value" name="words" value="#{json.words}" type="text"/>
|
||||
<input class="span1" id="exclude_small_matches_words_value" name="words" value="#{htmlEscape json.words}" type="text"/>
|
||||
"""
|
||||
percentInput: """
|
||||
<input class="span1" id="exclude_small_matches_percent_value" name="percent" value="#{json.percent}" type="text"/>
|
||||
<input class="span1" id="exclude_small_matches_percent_value" name="percent" value="#{htmlEscape json.percent}" type="text"/>
|
||||
"""
|
||||
|
||||
renderEl: =>
|
||||
@$el.html(turnitinSettingsDialog(@toJSON()))
|
||||
html = turnitinSettingsDialog(@toJSON())
|
||||
@$el.html(html)
|
||||
@$el.dialog({width: 'auto', modal: true}).fixDialogButtons()
|
||||
|
||||
getFormValues: =>
|
||||
|
|
|
@ -56,8 +56,7 @@ define [
|
|||
hide: => @show(false)
|
||||
|
||||
setTitle: (new_text) =>
|
||||
# need to use .html instead of .text so – will render correctly
|
||||
@$title.html(new_text)
|
||||
@$title.text(new_text)
|
||||
|
||||
showPicker: (visible = true) ->
|
||||
@_pickerShowing = visible
|
||||
|
|
|
@ -4,15 +4,16 @@ define [
|
|||
'Backbone'
|
||||
'i18n!calendar.edit'
|
||||
'jst/calendar/missingDueDateDialog'
|
||||
'str/htmlEscape'
|
||||
'jqueryui/dialog'
|
||||
'compiled/jquery/fixDialogButtons'
|
||||
], ($, _, {View}, I18n, template) ->
|
||||
], ($, _, {View}, I18n, template, htmlEscape) ->
|
||||
|
||||
class MissingDateDialogView extends View
|
||||
dialogTitle: """
|
||||
<span>
|
||||
<i class="icon-warning"></i>
|
||||
#{I18n.t('titles.warning', 'Warning')}
|
||||
#{htmlEscape I18n.t('titles.warning', 'Warning')}
|
||||
</span>
|
||||
"""
|
||||
|
||||
|
|
|
@ -58,8 +58,8 @@ define [
|
|||
|
||||
render: =>
|
||||
@updateFilter([])
|
||||
collaborators = @collection.map(@renderCollaborator)
|
||||
@$el.html(collaborators.join(''))
|
||||
collaboratorsHtml = @collection.map(@renderCollaborator).join('')
|
||||
@$el.html(collaboratorsHtml)
|
||||
@updateFocus() if @currentIndex? && @hasFocus
|
||||
@hasFocus = false
|
||||
super
|
||||
|
|
|
@ -62,13 +62,14 @@ define [
|
|||
render: =>
|
||||
@removeCurrentUser() if @options.currentUser
|
||||
@updateElementVisibility()
|
||||
collaborators = @collection.map (c) =>
|
||||
collaboratorsHtml = @collection.map (c) =>
|
||||
collaboratorTemplate(extend(c.toJSON(),
|
||||
type: c.modelType or c.get('type'),
|
||||
id: c.get('collaborator_id') or c.get('id')
|
||||
name: c.get('sortable_name') or c.get('name')
|
||||
selected: true))
|
||||
@$list.html(collaborators.join(''))
|
||||
collaboratorsHtml = collaboratorsHtml.join('')
|
||||
@$list.html(collaboratorsHtml)
|
||||
@updateFocus() if @currentIndex? && @hasFocus
|
||||
@hasFocus = false
|
||||
|
||||
|
|
|
@ -4,6 +4,10 @@ define [
|
|||
'i18n!context_modules'
|
||||
'jquery.loadingImg'
|
||||
], (Backbone, $, I18n) ->
|
||||
###
|
||||
xsslint jqueryObject.identifier dragItem dragModule
|
||||
###
|
||||
|
||||
class ContextModules extends Backbone.View
|
||||
@optionProperty 'modules'
|
||||
|
||||
|
|
|
@ -36,8 +36,8 @@ define [
|
|||
#
|
||||
# Returns nothing.
|
||||
render: ->
|
||||
html = _.map(@collection.models, @renderPageView)
|
||||
@$el.append(html.join(''))
|
||||
html = _.map(@collection.models, @renderPageView).join('')
|
||||
@$el.append(html)
|
||||
super
|
||||
|
||||
# Public: Return HTML for a given record.
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
define [
|
||||
'jquery'
|
||||
'Backbone'
|
||||
], ($, Backbone) ->
|
||||
'str/htmlEscape'
|
||||
], ($, Backbone, htmlEscape) ->
|
||||
###
|
||||
xsslint jqueryObject.identifier dragObject current_item
|
||||
###
|
||||
|
||||
class NavigationView extends Backbone.View
|
||||
|
||||
|
@ -47,11 +51,11 @@ define [
|
|||
which_list.children('.navitem').each (key, item) ->
|
||||
if $(item).attr('aria-label') is which_item.attr('aria-label')
|
||||
return
|
||||
options.push('<option value="' + $(item).attr('id') + '">' + $(item).attr('aria-label') + '</option>')
|
||||
options.push('<option value="' + htmlEscape($(item).attr('id')) + '">' + htmlEscape($(item).attr('aria-label')) + '</option>')
|
||||
$select = @$move_dialog.children().find('#move_nav_item_select')
|
||||
# Clear the options first
|
||||
$select.empty()
|
||||
$select.append(options.join(''))
|
||||
$select.append($.raw(options.join('')))
|
||||
# Set the name in the dialog
|
||||
@$move_name.text which_item.attr('aria-label')
|
||||
@$move_dialog.data 'current_item', which_item
|
||||
|
@ -171,4 +175,4 @@ define [
|
|||
|
||||
# Internal: returns whether the element is inside the enabled list
|
||||
disabled: (el) ->
|
||||
el.parent().attr("id") == @$disabled_list.attr("id")
|
||||
el.parent().attr("id") == @$disabled_list.attr("id")
|
||||
|
|
|
@ -62,8 +62,8 @@ define [
|
|||
$link = $token.find('a')
|
||||
$link.attr('href', '#')
|
||||
$link.attr('title', I18n.t("remove_user_from_course_section", "Remove user from %{course_section}", course_section: $token.find('div').attr('title')))
|
||||
$screenreader_span = $('<span class="screenreader-only"></span>').append(I18n.t("remove_user_from_course_section",
|
||||
"Remove user from %{course_section}", course_section: h($token.find('div').attr('title'))))
|
||||
$screenreader_span = $('<span class="screenreader-only"></span>').append(h(I18n.t("remove_user_from_course_section",
|
||||
"Remove user from %{course_section}", course_section: h($token.find('div').attr('title')))))
|
||||
$link.append($screenreader_span)
|
||||
|
||||
update: (e) =>
|
||||
|
|
|
@ -58,10 +58,11 @@ define [
|
|||
|
||||
render: ->
|
||||
@attachEvents()
|
||||
@$el.html if @innerView
|
||||
html = if @innerView
|
||||
@innerView.render().el
|
||||
else if @renderInstructions
|
||||
@instructionsTemplate()
|
||||
@$el.html html
|
||||
this
|
||||
|
||||
attachEvents: ->
|
||||
|
|
|
@ -119,7 +119,7 @@ define [
|
|||
# Returns nothing.
|
||||
onDrop: (dragObject, $destination) ->
|
||||
# TODO: reduce duplication b/w this and OutcomesDirectoryView.initDroppable
|
||||
$target = dragObject.li
|
||||
$target = dragObject.$li
|
||||
model = dragObject.model
|
||||
destinationView = $destination.data('view')
|
||||
originalView = dragObject.parent
|
||||
|
@ -142,13 +142,13 @@ define [
|
|||
$sidebar = $target.parents('.wrapper:first')
|
||||
if dragObject = $sidebar.data('drag')
|
||||
# drop
|
||||
$target.after(dragObject.li)
|
||||
$target.after(dragObject.$li)
|
||||
@onDrop(dragObject, $target.parent())
|
||||
else
|
||||
# drag
|
||||
$target.attr('aria-grabbed', true)
|
||||
dragObject =
|
||||
li: $target,
|
||||
$li: $target,
|
||||
model: $target.data('view').model
|
||||
parent: $target.parent().data('view')
|
||||
$sidebar.data('drag', dragObject)
|
||||
|
@ -161,7 +161,7 @@ define [
|
|||
onEscapeKey: (e, $target) ->
|
||||
$sidebar = $target.parents('.wrapper:first')
|
||||
return unless dataObject = $sidebar.data('drag')
|
||||
dataObject.li.data('parent', null).attr('aria-grabbed', false)
|
||||
dataObject.$li.data('parent', null).attr('aria-grabbed', false)
|
||||
$sidebar.data('drag', null);
|
||||
|
||||
# Internal: Update tabindex on $el and its siblings.
|
||||
|
|
|
@ -89,10 +89,10 @@ define [
|
|||
|
||||
insertRating: (e) =>
|
||||
e.preventDefault()
|
||||
rating = $ criterionTemplate description: '', points: '', _index: 99
|
||||
$(e.currentTarget).closest('.rating').after rating
|
||||
rating.find('.show').hide().next().show(200)
|
||||
rating.find('.edit input:first').focus()
|
||||
$rating = $ criterionTemplate description: '', points: '', _index: 99
|
||||
$(e.currentTarget).closest('.rating').after $rating
|
||||
$rating.find('.show').hide().next().show(200)
|
||||
$rating.find('.edit input:first').focus()
|
||||
@updateRatings()
|
||||
|
||||
# Update rating form field elements and the total.
|
||||
|
@ -106,7 +106,7 @@ define [
|
|||
# reset indices
|
||||
$(i).attr 'name', i.name.replace /\[[0-9]+\]/, "[#{index}]"
|
||||
points = @$('.points_possible')
|
||||
points.html points.html().replace /[0-9/.]+/, total
|
||||
points.html $.raw points.html().replace(/[0-9/.]+/, total)
|
||||
|
||||
showRatingDialog: (e) =>
|
||||
e.preventDefault()
|
||||
|
|
|
@ -26,10 +26,11 @@ define [
|
|||
'compiled/collections/OutcomeGroupCollection'
|
||||
'compiled/views/outcomes/OutcomeGroupIconView'
|
||||
'compiled/views/outcomes/OutcomeIconView'
|
||||
'str/htmlEscape'
|
||||
'jquery.disableWhileLoading'
|
||||
'jqueryui/droppable'
|
||||
'compiled/jquery.rails_flash_notifications'
|
||||
], (I18n, $, _, PaginatedView, OutcomeGroup, OutcomeCollection, OutcomeGroupCollection, OutcomeGroupIconView, OutcomeIconView) ->
|
||||
], (I18n, $, _, PaginatedView, OutcomeGroup, OutcomeCollection, OutcomeGroupCollection, OutcomeGroupIconView, OutcomeIconView, htmlEscape) ->
|
||||
|
||||
# The outcome group "directory" browser.
|
||||
class OutcomesDirectoryView extends PaginatedView
|
||||
|
@ -157,11 +158,12 @@ define [
|
|||
# Overriding
|
||||
paginationLoaderTemplate: ->
|
||||
"<li><a href='#' class='loading-more'>
|
||||
#{I18n.t("loading_more_results", "Loading more results")}</a></li>"
|
||||
#{htmlEscape I18n.t("loading_more_results", "Loading more results")}</a></li>"
|
||||
|
||||
# Overriding to insert into the ul.
|
||||
showPaginationLoader: ->
|
||||
@$el.append(@$paginationLoader ?= $(@paginationLoaderTemplate()))
|
||||
@$paginationLoader ?= $(@paginationLoaderTemplate())
|
||||
@$el.append(@$paginationLoader)
|
||||
|
||||
# Fetch outcomes after all the groups have been fetched.
|
||||
fetchOutcomes: ->
|
||||
|
|
|
@ -130,6 +130,9 @@ define [
|
|||
|
||||
delete @image
|
||||
|
||||
###
|
||||
xsslint xssable.receiver.whitelist req
|
||||
###
|
||||
req.append(k, v) for k, v of preflightResponse.upload_params
|
||||
req.append(preflightResponse.file_param, image, 'profile.jpg')
|
||||
dataType = if preflightResponse.success_url then 'xml' else 'json'
|
||||
|
|
|
@ -2,9 +2,10 @@ define [
|
|||
"underscore"
|
||||
"Backbone"
|
||||
"jquery"
|
||||
"jst/quizzes/LDBLoginPopup",
|
||||
"jst/quizzes/LDBLoginPopup"
|
||||
"str/htmlEscape"
|
||||
"jquery.toJSON"
|
||||
], (_, Backbone, $, Markup) ->
|
||||
], (_, Backbone, $, Markup, htmlEscape) ->
|
||||
|
||||
# Consumes an event and stops it from propagating.
|
||||
consume = (e) ->
|
||||
|
@ -179,7 +180,7 @@ define [
|
|||
|
||||
# Inject the stylesheets.
|
||||
_(styleSheets).each (href) ->
|
||||
$head.append "<link rel=\"stylesheet\" href=\"" + href + "\" />"
|
||||
$head.append "<link rel=\"stylesheet\" href=\"" + htmlEscape(href) + "\" />"
|
||||
return
|
||||
|
||||
# Show the form.
|
||||
|
@ -286,4 +287,4 @@ define [
|
|||
global: false
|
||||
headers:
|
||||
'Content-Type': 'application/json'
|
||||
'Accept': 'application/json'
|
||||
'Accept': 'application/json'
|
||||
|
|
|
@ -6,7 +6,8 @@ define [
|
|||
'jst/roles/manageRoles'
|
||||
'compiled/views/roles/PermissionButtonView'
|
||||
'compiled/views/roles/RoleHeaderView'
|
||||
], (I18n, $, _, Backbone, template, PermissionButtonView, RoleHeaderView) ->
|
||||
'str/htmlEscape'
|
||||
], (I18n, $, _, Backbone, template, PermissionButtonView, RoleHeaderView, htmlEscape) ->
|
||||
class ManageRolesView extends Backbone.View
|
||||
template: template
|
||||
className: 'manage-roles-table'
|
||||
|
@ -40,7 +41,7 @@ define [
|
|||
# called, which should get called when role is added or removed.
|
||||
# @api private
|
||||
renderHeader: ->
|
||||
@$el.find('thead tr').html "<th>#{I18n.t('permissions', 'Permissions')}</th>"
|
||||
@$el.find('thead tr').html "<th>#{htmlEscape(I18n.t('permissions', 'Permissions'))}</th>"
|
||||
|
||||
@collection.each (role) =>
|
||||
roleHeaderView = new RoleHeaderView
|
||||
|
@ -94,20 +95,20 @@ define [
|
|||
|
||||
_.each @permission_groups, (permission_group) =>
|
||||
# Add the headers to the group
|
||||
permission_group_header = """
|
||||
permission_group_header_html = """
|
||||
<tr class="toolbar">
|
||||
<th colspan="#{@collection.length + 1}">#{permission_group.group_name.toUpperCase()}</th>
|
||||
<th colspan="#{htmlEscape(@collection.length + 1)}">#{htmlEscape(permission_group.group_name.toUpperCase())}</th>
|
||||
</tr>
|
||||
"""
|
||||
|
||||
@$el.find('tbody').append permission_group_header
|
||||
@$el.find('tbody').append permission_group_header_html
|
||||
|
||||
# Add each permission item.
|
||||
_.each permission_group.group_permissions, (permission_row) =>
|
||||
|
||||
permission_row_html = """
|
||||
<tr>
|
||||
<th role="rowheader">#{permission_row.label}</th>
|
||||
<th role="rowheader">#{htmlEscape(permission_row.label)}</th>
|
||||
</tr>
|
||||
"""
|
||||
|
||||
|
|
|
@ -335,8 +335,8 @@ define [
|
|||
# 3 = "disabledLocked"
|
||||
# @api private
|
||||
setButtonPreview: (selected_radio) ->
|
||||
icons = @$el.find("label[for=button-#{@cid}-#{selected_radio}] i").clone()
|
||||
@$el.find('a.dropdown-toggle').html icons
|
||||
$icons = @$el.find("label[for=button-#{@cid}-#{selected_radio}] i").clone()
|
||||
@$el.find('a.dropdown-toggle').html $icons
|
||||
|
||||
# Method Summary
|
||||
# Sets the button preview for an dropdown button to the enabled icons
|
||||
|
|
|
@ -5,10 +5,11 @@ define [
|
|||
'Backbone'
|
||||
'compiled/views/tinymce/EquationToolbarView'
|
||||
'jst/tinymce/EquationEditorView'
|
||||
'str/htmlEscape'
|
||||
|
||||
'jqueryui/dialog'
|
||||
'mathquill'
|
||||
], (I18n, $, _, Backbone, EquationToolbarView, template) ->
|
||||
], (I18n, $, _, Backbone, EquationToolbarView, template, htmlEscape) ->
|
||||
|
||||
# like $.text() / Sizzle.getText(elems), except it also gets alt attributes from images
|
||||
getEquationText = (elems) ->
|
||||
|
@ -46,7 +47,7 @@ define [
|
|||
@prevSelection = @editor.selection.getBookmark()
|
||||
|
||||
unless @toolbar = @$el.data('toolbar')
|
||||
nodes = $('<span>').html @editor.selection.getContent()
|
||||
nodes = $('<span>').text @editor.selection.getContent()
|
||||
equation = getEquationText(nodes).replace(/^\s+|\s+$/g, '')
|
||||
@addToolbar(equation)
|
||||
|
||||
|
@ -73,7 +74,7 @@ define [
|
|||
@restoreCaret()
|
||||
|
||||
initialRender: =>
|
||||
nodes = $('<span>').html @editor.selection.getContent()
|
||||
nodes = $('<span>').text @editor.selection.getContent()
|
||||
equation = getEquationText(nodes).replace(/^\s+|\s+$/g, '')
|
||||
|
||||
@$mathjaxMessage.empty()
|
||||
|
@ -83,7 +84,7 @@ define [
|
|||
addToolbar: (equation) ->
|
||||
@$el.append(@template)
|
||||
|
||||
$('#mathjax-preview').html("<script type='math/tex; mode=display'>#{equation}</script>")
|
||||
$('#mathjax-preview').html("<script type='math/tex; mode=display'>#{htmlEscape equation}</script>")
|
||||
@toolbar = new EquationToolbarView
|
||||
el: @$el
|
||||
@toolbar.render()
|
||||
|
@ -138,7 +139,7 @@ define [
|
|||
.mathquill('editor')
|
||||
.mathquill('write', equation)
|
||||
if @$mathquillContainer.mathquill('latex').replace(/\s+/, '') != equation.replace(/\s+/, '')
|
||||
@$mathjaxMessage.html(I18n.t('cannot_render_equation', "This equation cannot be rendered in Basic View."))
|
||||
@$mathjaxMessage.text(I18n.t('cannot_render_equation', "This equation cannot be rendered in Basic View."))
|
||||
return false
|
||||
else if view == 'mathjax'
|
||||
@$mathjaxEditor.val(equation)
|
||||
|
|
|
@ -131,10 +131,10 @@ define [
|
|||
@setSelectedImage src: $(event.currentTarget).val()
|
||||
|
||||
generateImageHtml: ->
|
||||
img_tag = @editor.dom.createHTML("img", @getAttributes())
|
||||
imgHtml = @editor.dom.createHTML("img", @getAttributes())
|
||||
if @flickr_link
|
||||
img_tag = "<a href='#{@flickr_link}'>#{img_tag}</a>"
|
||||
img_tag
|
||||
imgHtml = "<a href='#{h @flickr_link}'>#{imgHtml}</a>"
|
||||
imgHtml
|
||||
|
||||
update: =>
|
||||
@editor.selection.moveToBookmark(@prevSelection)
|
||||
|
|
|
@ -7,7 +7,7 @@ define [
|
|||
|
||||
class WikiPageReloadView extends Backbone.View
|
||||
setViewProperties: false
|
||||
template: -> "<div class='alert alert-#{if @options.warning then 'warning' else 'info'} reload-changed-page'>#{@reloadMessage}</div>"
|
||||
template: -> "<div class='alert alert-#{$.raw if @options.warning then 'warning' else 'info'} reload-changed-page'>#{$.raw @reloadMessage}</div>"
|
||||
|
||||
defaults:
|
||||
modelAttributes: ['title', 'url', 'body']
|
||||
|
|
|
@ -116,7 +116,7 @@ define [
|
|||
# @api private
|
||||
# Build an <option> tag for an item.
|
||||
_buildOption: (item) =>
|
||||
"<option value='#{@_value item}'>#{htmlEscape @_label item}</option>"
|
||||
"<option value='#{htmlEscape @_value item}'>#{htmlEscape @_label item}</option>"
|
||||
|
||||
##
|
||||
# @api private
|
||||
|
|
|
@ -68,7 +68,8 @@ define [
|
|||
$name.append($b, $contextInfo)
|
||||
$span = $('<span />', class: 'details')
|
||||
if data.common_courses?
|
||||
$span.html(@contextList(courses: data.common_courses, groups: data.common_groups))
|
||||
contextListHtml = (@contextList(courses: data.common_courses, groups: data.common_groups))
|
||||
$span.html contextListHtml
|
||||
else if data.user_count?
|
||||
$span.text(I18n.t('people_count', 'person', {count: data.user_count}))
|
||||
else if data.item_count?
|
||||
|
|
|
@ -97,10 +97,10 @@ define [
|
|||
animateGhost: (fromElement, toElement) ->
|
||||
from = fromElement.offset()
|
||||
to = toElement.offset()
|
||||
clone = fromElement.clone()
|
||||
$clone = fromElement.clone()
|
||||
from.position = 'absolute'
|
||||
|
||||
@ghost.append(clone)
|
||||
@ghost.append($clone)
|
||||
@ghost.appendTo(@doc).css(from).animate to, @options.animationDuration, =>
|
||||
@ghost.detach().empty()
|
||||
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
define [
|
||||
'i18n!rubrics'
|
||||
'jquery'
|
||||
'str/htmlEscape'
|
||||
'jqueryui/dialog'
|
||||
'vendor/jquery.ba-tinypubsub'
|
||||
], (I18n, $) ->
|
||||
], (I18n, $, htmlEscape) ->
|
||||
|
||||
assignmentRubricDialog =
|
||||
|
||||
|
@ -23,7 +24,7 @@ define [
|
|||
initDialog: ->
|
||||
@dialogInited = true
|
||||
|
||||
@$dialog = $("<div><h4>#{I18n.t 'loading', 'Loading...'}</h4></div>").dialog
|
||||
@$dialog = $("<div><h4>#{htmlEscape I18n.t 'loading', 'Loading...'}</h4></div>").dialog
|
||||
title: I18n.t("titles.assignment_rubric_details", "Assignment Rubric Details")
|
||||
width: 600
|
||||
modal: false
|
||||
|
|
|
@ -10,85 +10,85 @@ define [
|
|||
constructor: (title, slideshow) ->
|
||||
@title = title
|
||||
@slideshow = slideshow
|
||||
@body = $('<li/>').addClass('slide')
|
||||
@slideshow.slides.append(@body)
|
||||
@$body = $('<li/>').addClass('slide')
|
||||
@slideshow.slides.append(@$body)
|
||||
|
||||
@prevSlide = @slideshow.slideObjects[@slideshow.slideObjects.length - 1]
|
||||
@prevSlide?.nextSlide = this
|
||||
@nextSlide = null
|
||||
|
||||
@indicator = $("<a/>").addClass('slide').attr('href', '#').attr('title', htmlEscape(@title)).html(' ')
|
||||
@indicator.data('slide', this)
|
||||
@slideshow.navigation.append(@indicator)
|
||||
@$indicator = $("<a/>").addClass('slide').attr('href', '#').attr('title', htmlEscape(@title)).html(' ')
|
||||
@$indicator.data('slide', this)
|
||||
@slideshow.navigation.append(@$indicator)
|
||||
slide = this
|
||||
@indicator.click ->
|
||||
@$indicator.click ->
|
||||
slideshow.showSlide(slide)
|
||||
return false
|
||||
|
||||
@hide()
|
||||
|
||||
addParagraph: (text, klass) ->
|
||||
paragraph = $("<p/>")
|
||||
paragraph.addClass(klass) if klass?
|
||||
paragraph.html(htmlEscape(text))
|
||||
@body.append(paragraph)
|
||||
$paragraph = $("<p/>")
|
||||
$paragraph.addClass(klass) if klass?
|
||||
$paragraph.html(htmlEscape(text))
|
||||
@$body.append($paragraph)
|
||||
|
||||
addImage: (src, klass, url) ->
|
||||
image = $("<img/>").attr('src', src)
|
||||
image.addClass(klass) if klass?
|
||||
$image = $("<img/>").attr('src', src)
|
||||
$image.addClass(klass) if klass?
|
||||
if url
|
||||
link = $("<a/>").attr('href', url).attr('target', '_blank')
|
||||
link.append(image)
|
||||
@body.append(link)
|
||||
$link = $("<a/>").attr('href', url).attr('target', '_blank')
|
||||
$link.append($image)
|
||||
@$body.append($link)
|
||||
else
|
||||
@body.append(image)
|
||||
@$body.append($image)
|
||||
|
||||
show: ->
|
||||
@body.show()
|
||||
@indicator.addClass('current_slide')
|
||||
@$body.show()
|
||||
@$indicator.addClass('current_slide')
|
||||
|
||||
hide: ->
|
||||
@indicator.removeClass('current_slide')
|
||||
@body.hide()
|
||||
@$indicator.removeClass('current_slide')
|
||||
@$body.hide()
|
||||
|
||||
class Slideshow
|
||||
constructor: (id) ->
|
||||
slideshow = this
|
||||
@dom = $('<div/>').attr('id', id)
|
||||
@$dom = $('<div/>').attr('id', id)
|
||||
|
||||
@slides = $('<ul/>').addClass('slides')
|
||||
@dom.append(@slides)
|
||||
@$slides = $('<ul/>').addClass('slides')
|
||||
@$dom.append(@$slides)
|
||||
|
||||
@separator = $("<div/>").addClass('separator')
|
||||
@dom.append(@separator)
|
||||
@$separator = $("<div/>").addClass('separator')
|
||||
@$dom.append(@$separator)
|
||||
|
||||
@navigation = $("<div/>").addClass('navigation')
|
||||
@dom.append(@navigation)
|
||||
@$navigation = $("<div/>").addClass('navigation')
|
||||
@$dom.append(@$navigation)
|
||||
|
||||
@backButton = $("<a/>").addClass('back').
|
||||
@$backButton = $("<a/>").addClass('back').
|
||||
attr('href', '#').
|
||||
attr('title', htmlEscape(I18n.t('titles.back', 'Back'))).
|
||||
attr('title', I18n.t('titles.back', 'Back')).
|
||||
html(' ')
|
||||
@navigation.append(@backButton)
|
||||
@backButton.click ->
|
||||
@$navigation.append(@$backButton)
|
||||
@$backButton.click ->
|
||||
slideshow.showPrevSlide()
|
||||
return false
|
||||
|
||||
@forwardButton = $("<a/>").addClass('forward').
|
||||
@$forwardButton = $("<a/>").addClass('forward').
|
||||
attr('href', '#').
|
||||
attr('title', htmlEscape(I18n.t('titles.forward', 'Forward'))).
|
||||
attr('title', I18n.t('titles.forward', 'Forward')).
|
||||
html(' ')
|
||||
@navigation.append(@forwardButton)
|
||||
@forwardButton.click ->
|
||||
@$navigation.append(@$forwardButton)
|
||||
@$forwardButton.click ->
|
||||
slideshow.showNextSlide()
|
||||
return false
|
||||
|
||||
@closeButton = $("<a/>").addClass('close').
|
||||
@$closeButton = $("<a/>").addClass('close').
|
||||
attr('href', '#').
|
||||
attr('title', htmlEscape(I18n.t('titles.close', 'Close'))).
|
||||
attr('title', I18n.t('titles.close', 'Close')).
|
||||
html(' ')
|
||||
@navigation.append(@closeButton)
|
||||
@closeButton.click ->
|
||||
@$navigation.append(@$closeButton)
|
||||
@$closeButton.click ->
|
||||
slideshow.close()
|
||||
return false
|
||||
|
||||
|
@ -102,7 +102,7 @@ define [
|
|||
|
||||
start: ->
|
||||
@showSlide(@slideObjects[0])
|
||||
@dialog = @dom.dialog
|
||||
@$dialog = @$dom.dialog
|
||||
dialogClass: 'slideshow_dialog'
|
||||
height: 529
|
||||
width: 700
|
||||
|
@ -117,13 +117,13 @@ define [
|
|||
@slideShown = slide
|
||||
@slideShown.show()
|
||||
if @slideShown.prevSlide
|
||||
@backButton.removeClass('inactive')
|
||||
@$backButton.removeClass('inactive')
|
||||
else
|
||||
@backButton.addClass('inactive')
|
||||
@$backButton.addClass('inactive')
|
||||
if @slideShown.nextSlide
|
||||
@forwardButton.removeClass('inactive')
|
||||
@$forwardButton.removeClass('inactive')
|
||||
else
|
||||
@forwardButton.addClass('inactive')
|
||||
@$forwardButton.addClass('inactive')
|
||||
|
||||
showPrevSlide: ->
|
||||
@showSlide(@slideShown?.prevSlide)
|
||||
|
@ -132,8 +132,8 @@ define [
|
|||
@showSlide(@slideShown?.nextSlide)
|
||||
|
||||
close: ->
|
||||
@dom.dialog('close')
|
||||
@dom.hide()
|
||||
@$dom.dialog('close')
|
||||
@$dom.hide()
|
||||
@slideShown?.hide()
|
||||
@slideShown = null
|
||||
|
||||
|
|
|
@ -20,6 +20,10 @@
|
|||
# Populates a <select> element with data from an ajax call. Takes two arguments.
|
||||
# The first is a <select> element, the second is an options hash
|
||||
|
||||
###
|
||||
xsslint jqueryObject.property placeholder spinner
|
||||
###
|
||||
|
||||
define [
|
||||
'jquery'
|
||||
'underscore'
|
||||
|
|
18
package.json
18
package.json
|
@ -15,18 +15,20 @@
|
|||
"react-tools": "0.11.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"loom": "~2.0.0",
|
||||
"fleck": "~0.5.1",
|
||||
"testem": "~0.3.30",
|
||||
"karma-qunit": "~0.1.1",
|
||||
"gglobby": "0.0.2",
|
||||
"karma": "~0.10.9",
|
||||
"karma-safari-launcher": "~0.1.1",
|
||||
"karma-opera-launcher": "~0.1.0",
|
||||
"karma-coffee-preprocessor": "0.1.3",
|
||||
"karma-coverage": "~0.1.4",
|
||||
"karma-ie-launcher": "~0.1.1",
|
||||
"karma-osx-reporter": "0.0.4",
|
||||
"karma-firework-reporter": "~0.2.3",
|
||||
"karma-coffee-preprocessor": "0.1.3"
|
||||
"karma-ie-launcher": "~0.1.1",
|
||||
"karma-opera-launcher": "~0.1.0",
|
||||
"karma-osx-reporter": "0.0.4",
|
||||
"karma-qunit": "~0.1.1",
|
||||
"karma-safari-launcher": "~0.1.1",
|
||||
"loom": "~2.0.0",
|
||||
"testem": "~0.3.30",
|
||||
"xsslint": "0.0.2"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
# top level, and plugin ones too
|
||||
jst
|
||||
/bower
|
||||
/jsx/.module-cache
|
||||
/jsx/sample.js
|
||||
/mediaelement
|
||||
/tinymce/jscripts/tiny_mce/langs
|
||||
/tinymce/jscripts/tiny_mce/plugins/*
|
||||
!/tinymce/jscripts/tiny_mce/plugins/instructure*
|
||||
/tinymce/jscripts/tiny_mce/themes
|
||||
/tinymce/jscripts/tiny_mce/tiny_mce*.js
|
||||
/tinymce/jscripts/tiny_mce/utils
|
||||
/vendor
|
||||
|
||||
# need better hinting, skipping this atm due to false positives in vendor code
|
||||
/client_apps
|
|
@ -61,7 +61,7 @@ define([
|
|||
$('#discovery_url_config .delete_url').click(function(){
|
||||
$.ajaxJSON( $(this).data('url'), "DELETE", {}, function(){
|
||||
$('#discovery_url_input').val("");
|
||||
$('#discovery_url_display').html(I18n.t('no_discovery_url', "None set"));
|
||||
$('#discovery_url_display').text(I18n.t('no_discovery_url', "None set"));
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -78,4 +78,4 @@ define([
|
|||
$("#secondary_ldap_config_disabled").val("1");
|
||||
$(".add_secondary_ldap_link").show();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -108,8 +108,8 @@ define([
|
|||
} catch(e) {}
|
||||
$.ajaxJSON(location.protocol + '//' + location.host + "/simple_response.json?rnd=" + Math.round(Math.random() * 9999999), 'GET', {}, function() {
|
||||
if ($.ajaxJSON.isUnauthenticated(request)) {
|
||||
var message = I18n.t('errors.logged_out', "You are not currently logged in, possibly due to a long period of inactivity.")
|
||||
message += "<br\/><a href='/login' target='_new'>" + I18n.t('links.login', 'Login') + "<\/a>";
|
||||
var message = htmlEscape(I18n.t('errors.logged_out', "You are not currently logged in, possibly due to a long period of inactivity."))
|
||||
message += "<br\/><a href='/login' target='_new'>" + htmlEscape(I18n.t('links.login', 'Login')) + "<\/a>";
|
||||
$.flashError({ html: message }, 30000);
|
||||
} else {
|
||||
ajaxErrorFlash(I18n.t('errors.unhandled', "Oops! The last request didn't work out."), request);
|
||||
|
@ -126,12 +126,12 @@ define([
|
|||
window.frames[$obj.attr('id')].document;
|
||||
var $body = $(d).find("body");
|
||||
$body.html($("<h1 />").text(I18n.t('error_heading', 'Ajax Error: %{status_code}', {status_code: status})));
|
||||
$body.append(text);
|
||||
$body.append(htmlEscape(text));
|
||||
$("#instructure_ajax_error_box").hide();
|
||||
var pre = "";
|
||||
message = htmlEscape(message);
|
||||
if(debugOnly) {
|
||||
message = message + "<br\/><span style='font-size: 0.7em;'>(Development Only)<\/span>";
|
||||
message += "<br\/><span style='font-size: 0.7em;'>(Development Only)<\/span>";
|
||||
}
|
||||
if(debugOnly || INST.environment != "production") {
|
||||
message += "<br\/><a href='#' class='last_error_details_link'>" + htmlEscape(I18n.t('links.details', 'details...')) + "<\/a>";
|
||||
|
@ -161,7 +161,7 @@ define([
|
|||
"&Platform=" + escape(navigator.platform) +
|
||||
"&UserAgent=" + escape(navigator.userAgent) +
|
||||
"&Params=" + escape(data.params || "unknown");
|
||||
$("body").append("<img style='position: absolute; left: -1000px; top: 0;' src='" + INST.ajaxErrorURL + txt.substring(0, 2000) + "' />");
|
||||
$("body").append("<img style='position: absolute; left: -1000px; top: 0;' src='" + htmlEscape(INST.ajaxErrorURL + txt.substring(0, 2000)) + "' />");
|
||||
}
|
||||
});
|
||||
$(".last_error_details_link").live('click', function(event) {
|
||||
|
|
|
@ -152,7 +152,7 @@ define([
|
|||
if ( data.multiple_due_dates === "true" && id !== 'assignment_new' ) {
|
||||
var $dateInput = $form.find('.input-append');
|
||||
$dateInput.before($("<span class=vdd_no_edit>" +
|
||||
I18n.t('multiple_due_dates','Multiple Due Dates')+
|
||||
htmlEscape(I18n.t('multiple_due_dates','Multiple Due Dates'))+
|
||||
"</span>"));
|
||||
$dateInput.hide();
|
||||
$form.find('.ui-datepicker-trigger').hide();
|
||||
|
@ -594,7 +594,7 @@ define([
|
|||
$(this).hide();
|
||||
$(this).parents(".assignment_group").find(".hide_info_link").show().end()
|
||||
.find(".more_info").show();
|
||||
var rules = "";
|
||||
var rulesHtml = "";
|
||||
var ruleData = $(this).parents(".assignment_group").find(".rules").text().split("\n");
|
||||
$.each(ruleData, function(idx, rule) {
|
||||
var parts = rule.split(":");
|
||||
|
@ -602,16 +602,16 @@ define([
|
|||
var rule_type = parts[0];
|
||||
var value = parts[1];
|
||||
if(rule_type == "drop_lowest") {
|
||||
rules += htmlEscape(I18n.t('drop_lowest_scores', "Drop the Lowest %{number} Scores", {number: value})) + "<br/>";
|
||||
rulesHtml += htmlEscape(I18n.t('drop_lowest_scores', "Drop the Lowest %{number} Scores", {number: value})) + "<br/>";
|
||||
} else if(rule_type == "drop_highest") {
|
||||
rules += htmlEscape(I18n.t('drop_highest_scores', "Drop the Highest %{number} Scores", {number: value})) + "<br/>";
|
||||
rulesHtml += htmlEscape(I18n.t('drop_highest_scores', "Drop the Highest %{number} Scores", {number: value})) + "<br/>";
|
||||
} else if(rule_type == "never_drop") {
|
||||
var title = $("#assignment_" + value).find(".title").text();
|
||||
rules += htmlEscape(I18n.t('never_drop_scores', "Never Drop %{assignment_name}", {assignment_name: title})) + "<br/>";
|
||||
rulesHtml += htmlEscape(I18n.t('never_drop_scores', "Never Drop %{assignment_name}", {assignment_name: title})) + "<br/>";
|
||||
}
|
||||
}
|
||||
});
|
||||
$(this).parents(".assignment_group").find(".rule_details").html(rules);
|
||||
$(this).parents(".assignment_group").find(".rule_details").html(rulesHtml);
|
||||
});
|
||||
$(".hide_info_link").click(function(event) {
|
||||
event.preventDefault();
|
||||
|
|
|
@ -730,7 +730,7 @@ define([
|
|||
data.description = $event.data('description');
|
||||
$box.fillTemplateData({data: data, htmlValues: ['description']});
|
||||
if (data.lock_info) {
|
||||
$box.find(".lock_explanation").html(INST.lockExplanation(data.lock_info, 'assignment'));
|
||||
$box.find(".lock_explanation").html(htmlEscape(INST.lockExplanation(data.lock_info, 'assignment')));
|
||||
}
|
||||
if ($editEvent.data('dialog')) $editEvent.dialog('close');
|
||||
$box.find(".description").css("max-height", Math.max($(window).height() - 200, 150));
|
||||
|
|
|
@ -18,10 +18,11 @@
|
|||
define([
|
||||
'i18n!content_exports',
|
||||
'jquery' /* $ */,
|
||||
'str/htmlEscape',
|
||||
'jquery.ajaxJSON' /* ajaxJSON */,
|
||||
'jquery.instructure_forms' /* formSubmit */,
|
||||
'jqueryui/progressbar' /* /\.progressbar/ */
|
||||
], function(I18n, $) {
|
||||
], function(I18n, $, htmlEscape) {
|
||||
|
||||
$(document).ready(function(event) {
|
||||
var state = 'nothing';
|
||||
|
@ -30,7 +31,7 @@ $(document).ready(function(event) {
|
|||
$exporter_form = $('#exporter_form');
|
||||
|
||||
function startPoll() {
|
||||
$exporter_form.html(I18n.t('messages.processing', "Processing") + "<div style='font-size: 0.8em;'>" + I18n.t('messages.this_may_take_a_bit', "this may take a bit...") + "</div>")
|
||||
$exporter_form.html(htmlEscape(I18n.t('messages.processing', "Processing")) + "<div style='font-size: 0.8em;'>" + htmlEscape(I18n.t('messages.this_may_take_a_bit', "this may take a bit...")) + "</div>")
|
||||
.attr('disabled', true);
|
||||
$(".instruction").hide();
|
||||
$(".progress_bar_holder").slideDown();
|
||||
|
@ -65,14 +66,14 @@ $(document).ready(function(event) {
|
|||
if(content_export.workflow_state == 'exported') {
|
||||
$exporter_form.hide();
|
||||
$(".export_progress").progressbar('option', 'value', 100);
|
||||
$(".progress_message").html("Your content has been exported.");
|
||||
$("#export_files").append('<p>' + I18n.t('labels.new_export', "New Export:") + ' <a href="' + content_export.download_url + '">' + I18n.t('links.download_plain', "Click here to download") + '</a> </p>')
|
||||
$(".progress_message").text(I18n.t("Your content has been exported."));
|
||||
$("#export_files").append('<p>' + htmlEscape(I18n.t('labels.new_export', "New Export:")) + ' <a href="' + htmlEscape(content_export.download_url) + '">' + htmlEscape(I18n.t('links.download_plain', "Click here to download")) + '</a> </p>')
|
||||
} else if(content_export.workflow_state == 'failed') {
|
||||
code = "content_export_" + content_export.id;
|
||||
$(".progress_bar_holder").hide();
|
||||
$exporter_form.hide();
|
||||
var message = I18n.t('errors.error', "There was an error exporting your content. Please notify your system administrator and give them the following export identifier: \"%{code}\"", {code: code});
|
||||
$(".export_messages .error_message").html(message);
|
||||
$(".export_messages .error_message").text(message);
|
||||
$(".export_messages").show();
|
||||
} else {
|
||||
if(progress == lastProgress) {
|
||||
|
|
|
@ -193,7 +193,8 @@ define([
|
|||
}
|
||||
folderNames = folderNames.sort();
|
||||
for (var idx in folderNames) {
|
||||
$("#copy_files_list").append(folders[folderNames[idx]]);
|
||||
var $folder = folders[folderNames[idx]];
|
||||
$("#copy_files_list").append($folder);
|
||||
}
|
||||
}
|
||||
populateItem(null, null, null, null);
|
||||
|
|
|
@ -82,10 +82,10 @@ define([
|
|||
}
|
||||
if ($("#context_modules_url").length > 0) {
|
||||
html += "<br/>";
|
||||
html += "<a href='" + $("#context_modules_url").attr('href') + "'>";
|
||||
html += I18n.t('messages.visit_modules_page_for_details', "Visit the modules page for information on how to unlock this content.");
|
||||
html += "<a href='" + htmlEscape($("#context_modules_url").attr('href')) + "'>";
|
||||
html += htmlEscape(I18n.t('messages.visit_modules_page_for_details', "Visit the modules page for information on how to unlock this content."));
|
||||
html += "</a>";
|
||||
return html;
|
||||
return $.raw(html);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -113,7 +113,7 @@ define([
|
|||
var data = $(this).data('lock_reason');
|
||||
var type = data.type;
|
||||
var $reason = $("<div/>");
|
||||
$reason.html(INST.lockExplanation(data, type));
|
||||
$reason.html(htmlEscape(INST.lockExplanation(data, type)));
|
||||
var $dialog = $("#lock_reason_dialog");
|
||||
if($dialog.length === 0) {
|
||||
$dialog = $("<div/>").attr('id', 'lock_reason_dialog');
|
||||
|
|
|
@ -266,7 +266,7 @@ define([
|
|||
moduleSelectOptions.push('<option value="' + id + '">' + htmlEscape(name) + '</option>');
|
||||
});
|
||||
$('#move_module_item_module_select').empty();
|
||||
$('#move_module_item_module_select').append(moduleSelectOptions.join(''));
|
||||
$('#move_module_item_module_select').append($.raw(moduleSelectOptions.join('')));
|
||||
|
||||
// Trigger the change to make sure the list is initally populated.
|
||||
$('#move_module_item_module_select').trigger('change');
|
||||
|
@ -307,7 +307,7 @@ define([
|
|||
|
||||
var data = $module.getTemplateData({textValues: ['name', 'unlock_at', 'require_sequential_progress', 'publish_final_grade']});
|
||||
$('#move_context_module_select').empty();
|
||||
$('#move_context_module_select').append(selectOptions.join(''));
|
||||
$('#move_context_module_select').append($.raw(selectOptions.join('')));
|
||||
//$form.fillFormData(data, {object_name: 'context_module'});
|
||||
$form.dialog({
|
||||
autoOpen: false,
|
||||
|
@ -960,7 +960,7 @@ define([
|
|||
var name = $(item).children().find('span.title').text();
|
||||
selectItemOptions.push('<option value="' + id + '">' + htmlEscape(name) + '</option>');
|
||||
});
|
||||
$('#move_module_item_select').append(selectItemOptions.join(''));
|
||||
$('#move_module_item_select').append($.raw(selectItemOptions.join('')));
|
||||
|
||||
// The case where the module has no items.
|
||||
if ($('#move_module_item_select').children().length === 0) {
|
||||
|
@ -1550,7 +1550,7 @@ define([
|
|||
});
|
||||
$row.find(".still_need_completing")
|
||||
.append("<b>"+htmlEscape(I18n.t('still_needs_completing', 'Still Needs to Complete'))+"</b><br/>")
|
||||
.append(unfulfilled.join("<br/>"));
|
||||
.append($.raw(unfulfilled.join("<br/>")));
|
||||
}
|
||||
$row.removeClass('locked').removeClass('in_progress').removeClass('completed')
|
||||
.addClass(type);
|
||||
|
|
|
@ -52,22 +52,22 @@ define([
|
|||
$publish_grades_error = $("#publish_grades_error");
|
||||
if (GradePublishing.status == 'published') {
|
||||
$publish_grades_error.hide();
|
||||
$publish_grades_link.html(I18n.t('links.republish', "Republish grades to SIS"));
|
||||
$publish_grades_link.text(I18n.t('links.republish', "Republish grades to SIS"));
|
||||
$publish_grades_link.removeClass("disabled");
|
||||
} else if (GradePublishing.status == 'publishing' || GradePublishing.status == 'pending') {
|
||||
$publish_grades_error.hide();
|
||||
$publish_grades_link.html(I18n.t('links.publishing', "Publishing grades to SIS..."));
|
||||
$publish_grades_link.text(I18n.t('links.publishing', "Publishing grades to SIS..."));
|
||||
if (!requestInProgress) {
|
||||
setTimeout(GradePublishing.checkup, 5000);
|
||||
}
|
||||
$publish_grades_link.addClass("disabled");
|
||||
} else if (GradePublishing.status == 'unpublished') {
|
||||
$publish_grades_error.hide();
|
||||
$publish_grades_link.html(I18n.t('links.publish', "Publish grades to SIS"));
|
||||
$publish_grades_link.text(I18n.t('links.publish', "Publish grades to SIS"));
|
||||
$publish_grades_link.removeClass("disabled");
|
||||
} else {
|
||||
$publish_grades_error.show();
|
||||
$publish_grades_link.html(I18n.t('links.republish', "Republish grades to SIS"));
|
||||
$publish_grades_link.text(I18n.t('links.republish', "Republish grades to SIS"));
|
||||
$publish_grades_link.removeClass("disabled");
|
||||
}
|
||||
$messages = $("#publish_grades_messages");
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// xsslint jqueryObject.method _createCell _templateCellHTML
|
||||
|
||||
define([
|
||||
'INST' /* INST */,
|
||||
'jquery' /* $ */,
|
||||
|
|
|
@ -199,7 +199,7 @@ define([
|
|||
if(section_type == "rich_text") {
|
||||
code = $(this).find(".edit_section").editorBox('get_code');
|
||||
}
|
||||
$(this).find(".section_content").html(code);
|
||||
$(this).find(".section_content").html($.raw(code));
|
||||
} else if(!$(this).hasClass('read_only')) {
|
||||
$(this).remove();
|
||||
}
|
||||
|
@ -416,7 +416,7 @@ define([
|
|||
},
|
||||
error: function(data) {
|
||||
var $section = $(this).data("section");
|
||||
$section.find(".uploading_file").html(I18n.t('errors.upload_failed', "Upload Failed."));
|
||||
$section.find(".uploading_file").text(I18n.t('errors.upload_failed', "Upload Failed."));
|
||||
$section.addClass('failed');
|
||||
$section.formErrors(data.errors || data);
|
||||
}
|
||||
|
|
|
@ -192,7 +192,7 @@ define([
|
|||
importFailed(zfi.data.errors);
|
||||
} else if(zfi && zfi.workflow_state == 'imported') {
|
||||
$progress.progressbar('value', 100);
|
||||
$dialog.append(I18n.t('messages.extraction_complete', "Extraction complete! Updating..."));
|
||||
$dialog.append(htmlEscape(I18n.t('messages.extraction_complete', "Extraction complete! Updating...")));
|
||||
files.refreshContext(folder.context_string, function() {
|
||||
$dialog.dialog('close');
|
||||
});
|
||||
|
@ -587,6 +587,7 @@ define([
|
|||
$(ui.helper).find(".header .sub_header").html(" ");
|
||||
}
|
||||
},
|
||||
// xsslint jqueryObject.method breadcrumb
|
||||
breadcrumb: function() {
|
||||
var folders = location.hash.substring(1).replace(/\/\//g, "\\").split("/");
|
||||
var $crumbs = $("<div/>");
|
||||
|
@ -1413,11 +1414,11 @@ define([
|
|||
if(node.hasClass('node')) {
|
||||
var folder_url = $.replaceTags($("." + data.context_string + "_folder_url").attr('href'), 'id', data.id);
|
||||
var cancelled = false;
|
||||
var $no_content = $("<li class='message'>" + I18n.t('messages.folder_empty', "Nothing in this Folder") + "</li>");
|
||||
var $no_content = $("<li class='message'>" + htmlEscape(I18n.t('messages.folder_empty', "Nothing in this Folder")) + "</li>");
|
||||
if(node.hasClass('folder')) {
|
||||
if(!data || !data.permissions || !data.permissions.read_contents) {
|
||||
$files_content.find(".content_panel:last")
|
||||
.after("<li class='message'>" + I18n.t('messages.access_denied', "You cannot read the contents of this folder.") + "</li>");
|
||||
.after("<li class='message'>" + htmlEscape(I18n.t('messages.access_denied', "You cannot read the contents of this folder.")) + "</li>");
|
||||
cancelled = true;
|
||||
} else {
|
||||
// add a control panel to the top for adding files, folders to this
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue