982 lines
44 KiB
JavaScript
982 lines
44 KiB
JavaScript
/**
|
|
* Copyright (C) 2011 Instructure, Inc.
|
|
*
|
|
* This file is part of Canvas.
|
|
*
|
|
* Canvas is free software: you can redistribute it and/or modify it under
|
|
* the terms of the GNU Affero General Public License as published by the Free
|
|
* Software Foundation, version 3 of the License.
|
|
*
|
|
* Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
|
* A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
|
* details.
|
|
*
|
|
* You should have received a copy of the GNU Affero General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
define([
|
|
'compiled/views/KeyboardNavDialog',
|
|
'INST' /* INST */,
|
|
'i18n!instructure',
|
|
'jquery' /* $ */,
|
|
'underscore',
|
|
'timezone',
|
|
'compiled/userSettings',
|
|
'str/htmlEscape',
|
|
'wikiSidebar',
|
|
'instructure_helper',
|
|
'jqueryui/draggable',
|
|
'jquery.ajaxJSON' /* ajaxJSON */,
|
|
'jquery.doc_previews' /* filePreviewsEnabled, loadDocPreview */,
|
|
'jquery.dropdownList' /* dropdownList */,
|
|
'jquery.google-analytics' /* trackEvent */,
|
|
'jquery.instructure_date_and_time' /* datetimeString, dateString, fudgeDateForProfileTimezone */,
|
|
'jquery.instructure_forms' /* formSubmit, fillFormData, formErrors */,
|
|
'jqueryui/dialog',
|
|
'jquery.instructure_misc_helpers' /* replaceTags, youTubeID */,
|
|
'jquery.instructure_misc_plugins' /* ifExists, .dim, confirmDelete, showIf, fillWindowWithMe */,
|
|
'jquery.keycodes' /* keycodes */,
|
|
'jquery.loadingImg' /* loadingImage */,
|
|
'compiled/jquery.rails_flash_notifications',
|
|
'jquery.templateData' /* fillTemplateData, getTemplateData */,
|
|
'compiled/jquery/fixDialogButtons',
|
|
'compiled/jquery/mediaCommentThumbnail',
|
|
'tinymce.editor_box' /* editorBox */,
|
|
'vendor/date' /* Date.parse */,
|
|
'vendor/jquery.ba-tinypubsub' /* /\.publish\(/ */,
|
|
'jqueryui/accordion' /* /\.accordion\(/ */,
|
|
'jqueryui/resizable' /* /\.resizable/ */,
|
|
'jqueryui/sortable' /* /\.sortable/ */,
|
|
'jqueryui/tabs' /* /\.tabs/ */,
|
|
'compiled/behaviors/trackEvent',
|
|
'compiled/badge_counts',
|
|
'vendor/scribd.view' /* scribd */,
|
|
'vendor/jquery.placeholder'
|
|
], function(KeyboardNavDialog, INST, I18n, $, _, tz, userSettings, htmlEscape, wikiSidebar) {
|
|
|
|
$.trackEvent('Route', location.pathname.replace(/\/$/, '').replace(/\d+/g, '--') || '/');
|
|
|
|
$(function() {
|
|
|
|
// handle all of the click events that were triggered before the dom was ready (and thus weren't handled by jquery listeners)
|
|
if (window._earlyClick) {
|
|
|
|
// unset the onclick handler we were using to capture the events
|
|
document.removeEventListener('click', _earlyClick);
|
|
|
|
if (_earlyClick.clicks) {
|
|
// wait to fire the "click" events till after all of the event hanlders loaded at dom ready are initialized
|
|
setTimeout(function(){
|
|
$.each(_.uniq(_earlyClick.clicks), function() {
|
|
// cant use .triggerHandler because it will not bubble,
|
|
// but we do want to preventDefault, so this is what we have to do
|
|
var event = $.Event('click');
|
|
event.preventDefault();
|
|
$(this).trigger(event);
|
|
});
|
|
}, 1);
|
|
}
|
|
}
|
|
|
|
///////////// START layout related stuff
|
|
// make sure that #main is at least as big as the tallest of #right_side, #content, and #left_side and ALWAYS at least 500px tall
|
|
$('#main:not(.already_sized)').css({"minHeight" : Math.max($("#left_side").height(), parseInt(($('#main').css('minHeight') || "").replace('px', ''), 10))});
|
|
|
|
var $menu_items = $(".menu-item"),
|
|
$menu = $("#menu"),
|
|
menuItemHoverTimeoutId;
|
|
|
|
function clearMenuHovers(){
|
|
window.clearTimeout(menuItemHoverTimeoutId);
|
|
// this is explicitly finding every time in case
|
|
// someone has added menu items to the list after init
|
|
$menu.find(".menu-item").removeClass("hover hover-pending");
|
|
}
|
|
|
|
function unhoverMenuItem(){
|
|
$menu_items.filter(".hover-pending").removeClass('hover-pending');
|
|
menuItemHoverTimeoutId = window.setTimeout(clearMenuHovers, 400);
|
|
}
|
|
|
|
function hoverMenuItem(event){
|
|
var hadClass = $menu_items.filter(".hover").length > 0;
|
|
clearMenuHovers();
|
|
var $elem = $(this);
|
|
$elem.addClass('hover-pending');
|
|
if(hadClass) { $elem.addClass('hover'); }
|
|
setTimeout(function() {
|
|
if($elem.hasClass('hover-pending')) {
|
|
$elem.addClass("hover");
|
|
}
|
|
}, 300);
|
|
$.publish('menu/hovered', $elem);
|
|
}
|
|
|
|
$menu
|
|
.delegate('.menu-item', 'mouseenter focusin', hoverMenuItem )
|
|
.delegate('.menu-item', 'mouseleave focusout', unhoverMenuItem );
|
|
|
|
|
|
// this stuff is for the ipad, it needs a little help getting the drop menus to show up
|
|
$menu_items.live('touchstart', function(){
|
|
// if we are not in an alredy hovering drop-down, drop it down, otherwise do nothing
|
|
// (so that if a link is clicked in one of the li's it gets followed).
|
|
if(!$(this).hasClass('hover')){
|
|
return hoverMenuItem.call(this, event);
|
|
}
|
|
});
|
|
// If I touch anywhere on the screen besides inside a dropdown, make the dropdowns go away.
|
|
$(document).bind('touchstart', function(event){
|
|
if (!$(event.target).closest(".menu-item").length) {
|
|
unhoverMenuItem();
|
|
}
|
|
});
|
|
|
|
|
|
|
|
// this next block of code adds the ellipsis on the breadcrumb if it overflows one line
|
|
var $breadcrumbs = $("#breadcrumbs"),
|
|
$breadcrumbEllipsis,
|
|
addedEllipsisClass = false;
|
|
function resizeBreadcrumb(){
|
|
var maxWidth = 500,
|
|
// we want to make sure that the breadcrumb doesnt wrap multiple lines, the way we are going to check if it is one line
|
|
// is by grabbing the first (which should be the home crumb) and checking to see how high it is, the * 1.5 part is
|
|
// just in case to ever handle any padding or margin.
|
|
hightOfOneBreadcrumb = $breadcrumbs.find('li:visible:first').height() * 1.5;
|
|
$breadcrumbEllipsis = $breadcrumbEllipsis || $breadcrumbs.find('.ellipsible');
|
|
$breadcrumbEllipsis.css('maxWidth', "");
|
|
$breadcrumbEllipsis.ifExists(function(){
|
|
for (var i=0; $breadcrumbs.height() > hightOfOneBreadcrumb && i < 20; i++) { //the i here is just to make sure we don't get into an ifinite loop somehow
|
|
if (!addedEllipsisClass) {
|
|
addedEllipsisClass = true;
|
|
$breadcrumbEllipsis.addClass('ellipsis');
|
|
}
|
|
$breadcrumbEllipsis.css('maxWidth', (maxWidth -= 20));
|
|
}
|
|
});
|
|
}
|
|
resizeBreadcrumb(); //force it to run once right now
|
|
$(window).resize(resizeBreadcrumb);
|
|
// end breadcrumb ellipsis
|
|
|
|
|
|
//////////////// END layout related stuff
|
|
|
|
$("#ajax_authenticity_token").ifExists(function(){
|
|
if(this.text()) {
|
|
$("input[name='authenticity_token']").val(this.text());
|
|
}
|
|
});
|
|
|
|
KeyboardNavDialog.prototype.bindOpenKeys.call({$el: $('#keyboard_navigation')});
|
|
|
|
$("#switched_role_type").ifExists(function(){
|
|
var context_class = $(this).attr('class');
|
|
var $img = $("<img/>");
|
|
var switched_roles_message = null;
|
|
switch ($(this).data('role')) {
|
|
case 'TeacherEnrollment':
|
|
switched_roles_message = I18n.t('switched_roles_message.teacher', "You have switched roles temporarily for this course, and are now viewing the course as a teacher. You can restore your role and permissions from the course home page.");
|
|
break;
|
|
case 'StudentEnrollment':
|
|
switched_roles_message = I18n.t('switched_roles_message.student', "You have switched roles temporarily for this course, and are now viewing the course as a student. You can restore your role and permissions from the course home page.");
|
|
break;
|
|
case 'TaEnrollment':
|
|
switched_roles_message = I18n.t('switched_roles_message.ta', "You have switched roles temporarily for this course, and are now viewing the course as a TA. You can restore your role and permissions from the course home page.");
|
|
break;
|
|
case 'ObserverEnrollment':
|
|
switched_roles_message = I18n.t('switched_roles_message.observer', "You have switched roles temporarily for this course, and are now viewing the course as an observer. You can restore your role and permissions from the course home page.");
|
|
break;
|
|
case 'DesignerEnrollment':
|
|
switched_roles_message = I18n.t('switched_roles_message.designer', "You have switched roles temporarily for this course, and are now viewing the course as a designer. You can restore your role and permissions from the course home page.");
|
|
break;
|
|
default:
|
|
switched_roles_message = I18n.t('switched_roles_message.student', "You have switched roles temporarily for this course, and are now viewing the course as a student. You can restore your role and permissions from the course home page.");
|
|
};
|
|
$img.attr('src', '/images/warning.png')
|
|
.attr('title', switched_roles_message)
|
|
.css({
|
|
paddingRight: 2,
|
|
width: 12,
|
|
height: 12
|
|
});
|
|
$("#crumb_" + context_class).find("a").prepend($img);
|
|
});
|
|
|
|
$("a.show_quoted_text_link").live('click', function(event) {
|
|
var $text = $(this).parents(".quoted_text_holder").children(".quoted_text");
|
|
if($text.length > 0) {
|
|
event.preventDefault();
|
|
$text.show();
|
|
$(this).hide();
|
|
}
|
|
});
|
|
|
|
$(".custom_search_results_link").click(function(event) {
|
|
event.preventDefault();
|
|
var $dialog = $("#custom_search_results_dialog");
|
|
$dialog.dialog({
|
|
title: I18n.t('titles.search_for_open_resources', "Search for Open Resources"),
|
|
width: 600,
|
|
height: 400
|
|
});
|
|
var control = $dialog.data('searchControl');
|
|
if(control) {
|
|
control.execute($("title").text());
|
|
}
|
|
});
|
|
|
|
$("a.equella_content_link").live('click', function(event) {
|
|
event.preventDefault();
|
|
var $dialog = $("#equella_preview_dialog");
|
|
if( !$dialog.length ) {
|
|
$dialog = $("<div/>");
|
|
$dialog.attr('id', 'equella_preview_dialog').hide();
|
|
$dialog.html("<h2/><iframe style='background: url(/images/ajax-loader-medium-444.gif) no-repeat left top; width: 800px; height: 350px; border: 0;' src='about:blank' borderstyle='0'/><div style='text-align: right;'><a href='#' class='original_link external external_link' target='_blank'>" + htmlEscape(I18n.t('links.view_equella_content_in_new_window', "view the content in a new window")) + "</a>");
|
|
$dialog.find("h2").text($(this).attr('title') || $(this).text() || I18n.t('titles.equella_content_preview', "Equella Content Preview"));
|
|
var $iframe = $dialog.find("iframe");
|
|
setTimeout(function() {
|
|
$iframe.css('background', '#fff');
|
|
}, 2500);
|
|
$("body").append($dialog);
|
|
$dialog.dialog({
|
|
autoOpen: false,
|
|
width: 'auto',
|
|
resizable: false,
|
|
title: I18n.t('titles.equella_content_preview', "Equella Content Preview"),
|
|
close: function() {
|
|
$dialog.find("iframe").attr('src', 'about:blank');
|
|
}
|
|
});
|
|
}
|
|
$dialog.find(".original_link").attr('href', $(this).attr('href'));
|
|
$dialog.dialog('close').dialog('open');
|
|
$dialog.find("iframe").attr('src', $(this).attr('href'));
|
|
});
|
|
|
|
|
|
// Adds a way to automatically open dialogs by just giving them the .dialog_opener class.
|
|
// Uses the aria-controls attribute to specify id of dialog to open because that is already
|
|
// a best practice accessibility-wise (as a side note you should also add "role=button").
|
|
// You can pass in options to the dialog with the data-dialog-options attribute.
|
|
//
|
|
// Examples:
|
|
//
|
|
// <a class="dialog_opener" aria-controls="foobar" role="button" href="#">
|
|
// opens the dialog with id="foobar"
|
|
//
|
|
// <a class="dialog_opener" aria-controls="my_dialog" data-dialog-opts="{resizable:false, width: 300}" role="button" href="#">
|
|
// opens the .my_dialog dialog and passes the options {resizable:false, width: 300}
|
|
|
|
// the :not clause is to not allow users access to this functionality in their content.
|
|
$('.dialog_opener[aria-controls]:not(.user_content *)').live('click', function(event){
|
|
var link = this;
|
|
$('#' + $(this).attr('aria-controls')).ifExists(function($dialog){
|
|
event.preventDefault();
|
|
|
|
// if the linked dialog has not already been initialized, initialize it (passing in opts)
|
|
if (!$dialog.data('dialog')) {
|
|
$dialog.dialog($.extend({
|
|
autoOpen: false,
|
|
modal: true
|
|
}, $(link).data('dialogOpts')));
|
|
$dialog.fixDialogButtons();
|
|
}
|
|
|
|
$dialog.dialog('open');
|
|
});
|
|
});
|
|
|
|
function enhanceUserContent() {
|
|
var $content = $("#content");
|
|
$(".user_content:not(.enhanced):visible").addClass('unenhanced');
|
|
$(".user_content.unenhanced:visible")
|
|
.each(function() {
|
|
var $this = $(this);
|
|
$this.find("img").css('maxWidth', Math.min($content.width(), $this.width()));
|
|
$this.data('unenhanced_content_html', $this.html());
|
|
})
|
|
.find(".enhanceable_content").show()
|
|
.filter(".dialog").each(function(){
|
|
var $dialog = $(this);
|
|
$dialog.hide();
|
|
$dialog.closest(".user_content").find("a[href='#" + $dialog.attr('id') + "']").click(function(event) {
|
|
event.preventDefault();
|
|
$dialog.dialog();
|
|
});
|
|
}).end()
|
|
.filter(".draggable").draggable().end()
|
|
.filter(".resizable").resizable().end()
|
|
.filter(".sortable").sortable().end()
|
|
.filter(".accordion").accordion().end()
|
|
.filter(".tabs").each(function() {
|
|
$(this).tabs();
|
|
}).end()
|
|
.end()
|
|
.find("a:not(.not_external, .external):external").each(function(){
|
|
var externalLink = htmlEscape(I18n.t('titles.external_link', 'Links to an external site.'));
|
|
$(this)
|
|
.not(":has(img)")
|
|
.addClass('external')
|
|
.html('<span>' + $(this).html() + '</span>')
|
|
.attr('target', '_blank')
|
|
.append('<span aria-hidden="true" class="ui-icon ui-icon-extlink ui-icon-inline" title="' + externalLink + '"/>')
|
|
.append('<span class="screenreader-only"> (' + externalLink + ')</span>');
|
|
}).end()
|
|
.find("a.instructure_file_link").each(function() {
|
|
var $link = $(this),
|
|
$span = $("<span class='instructure_file_link_holder link_holder'/>");
|
|
$link.removeClass('instructure_file_link').before($span).appendTo($span);
|
|
if($link.attr('target') != '_blank') {
|
|
$span.append("<a href='" + $link.attr('href') + "' target='_blank' title='" + htmlEscape(I18n.t('titles.view_in_new_window', "View in a new window")) +
|
|
"' style='padding-left: 5px;'><img src='/images/popout.png' alt='" + htmlEscape(I18n.t('titles.view_in_new_window', "View in a new window")) + "'/></a>");
|
|
}
|
|
});
|
|
if ($.filePreviewsEnabled()) {
|
|
$("a.instructure_scribd_file").not(".inline_disabled").each(function() {
|
|
var $link = $(this);
|
|
if ( $.trim($link.text()) ) {
|
|
var $span = $("<span class='instructure_scribd_file_holder link_holder'/>"),
|
|
$scribd_link = $("<a class='scribd_file_preview_link' aria-hidden='true' tabindex='-1' href='" + $link.attr('href') + "' title='" + htmlEscape(I18n.t('titles.preview_document', "Preview the document")) +
|
|
"' style='padding-left: 5px;'><img src='/images/preview.png' alt='" + htmlEscape(I18n.t('titles.preview_document', "Preview the document")) + "'/></a>");
|
|
$link.removeClass('instructure_scribd_file').before($span).appendTo($span);
|
|
$span.append($scribd_link);
|
|
if($link.hasClass('auto_open')) {
|
|
$scribd_link.click();
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
$(".user_content.unenhanced a")
|
|
.find("img.media_comment_thumbnail").each(function() {
|
|
$(this).closest("a").addClass('instructure_inline_media_comment');
|
|
}).end()
|
|
.filter(".instructure_inline_media_comment").removeClass('no-underline').mediaCommentThumbnail('normal').end()
|
|
.filter(".instructure_video_link, .instructure_audio_link").mediaCommentThumbnail('normal', true).end()
|
|
.not(".youtubed").each(function() {
|
|
var $link = $(this),
|
|
href = $link.attr('href'),
|
|
id = $.youTubeID(href || "");
|
|
if($link.hasClass('inline_disabled')) {
|
|
} else if(id) {
|
|
var $after = $('<a href="'+ href +'" class="youtubed"><img src="/images/play_overlay.png" class="media_comment_thumbnail" style="background-image: url(//img.youtube.com/vi/' + id + '/2.jpg)"/></a>')
|
|
.click(function(event) {
|
|
event.preventDefault();
|
|
var $video = $("<span class='youtube_holder' style='display: block;'><object width='425' height='344'><param name='wmode' value='opaque'></param><param name='movie' value='//www.youtube.com/v/" + id + "&autoplay=1&hl=en_US&fs=1&'></param><param name='allowFullScreen' value='true'></param><param name='allowscriptaccess' value='always'></param><embed src='//www.youtube.com/v/" + id + "&autoplay=1&hl=en_US&fs=1&' type='application/x-shockwave-flash' allowscriptaccess='always' allowfullscreen='true' width='425' height='344' wmode='opaque'></embed></object><br/><a href='#' style='font-size: 0.8em;' class='hide_youtube_embed_link'>" + htmlEscape(I18n.t('links.minimize_youtube_video', "Minimize Video")) + "</a></span>");
|
|
$video.find(".hide_youtube_embed_link").click(function(event) {
|
|
event.preventDefault();
|
|
$video.remove();
|
|
$after.show();
|
|
$.trackEvent('hide_embedded_content', 'hide_you_tube');
|
|
});
|
|
$(this).after($video).hide();
|
|
});
|
|
$.trackEvent('show_embedded_content', 'show_you_tube');
|
|
$link
|
|
.addClass('youtubed')
|
|
.after($after);
|
|
}
|
|
});
|
|
$(".user_content.unenhanced").removeClass('unenhanced').addClass('enhanced');
|
|
|
|
setTimeout(function() {
|
|
$(".user_content form.user_content_post_form:not(.submitted)").submit().addClass('submitted');
|
|
}, 10);
|
|
};
|
|
if ($.filePreviewsEnabled()) {
|
|
$("a.scribd_file_preview_link").live('click', function(event) {
|
|
event.preventDefault();
|
|
var $link = $(this).loadingImage({image_size: 'small'}).hide();
|
|
$.ajaxJSON($link.attr('href').replace(/\/download.*/, ""), 'GET', {}, function(data) {
|
|
var attachment = data && data.attachment,
|
|
scribdDocAttributes = attachment && attachment.scribd_doc && attachment.scribd_doc.attributes;
|
|
$link.loadingImage('remove');
|
|
if (attachment &&
|
|
(attachment['scribdable?'] ||
|
|
$.isPreviewable(attachment.content_type, 'google') ||
|
|
attachment.canvadoc_session_url)) {
|
|
var $div = $("<span><br /></span>")
|
|
.insertAfter($link.parents(".link_holder:last"))
|
|
.loadDocPreview({
|
|
canvadoc_session_url: attachment.canvadoc_session_url,
|
|
scribd_doc_id: scribdDocAttributes && scribdDocAttributes.doc_id,
|
|
scribd_access_key: scribdDocAttributes && scribdDocAttributes.access_key,
|
|
mimeType: attachment.content_type,
|
|
public_url: attachment.authenticated_s3_url,
|
|
attachment_scribd_render_url: attachment.scribd_render_url,
|
|
attachment_preview_processing: attachment.workflow_state == 'pending_upload' || attachment.workflow_state == 'processing'
|
|
})
|
|
.append(
|
|
$('<a href="#" style="font-size: 0.8em;" class="hide_file_preview_link">' + htmlEscape(I18n.t('links.minimize_file_preview', 'Minimize File Preview')) + '</a>')
|
|
.click(function(event) {
|
|
event.preventDefault();
|
|
$link.show();
|
|
$div.remove();
|
|
$.trackEvent('hide_embedded_content', 'hide_file_preview');
|
|
})
|
|
);
|
|
$.trackEvent('show_embedded_content', 'show_file_preview');
|
|
}
|
|
}, function() {
|
|
$link.loadingImage('remove').hide();
|
|
});
|
|
});
|
|
} else {
|
|
$("a.scribd_file_preview_link").live('click', function(event) {
|
|
event.preventDefault();
|
|
alert(I18n.t('alerts.file_previews_disabled', 'File previews have been disabled for this Canvas site'));
|
|
});
|
|
}
|
|
|
|
// publishing the 'userContent/change' will run enhanceUserContent at most once every 50ms
|
|
var enhanceUserContentTimeout;
|
|
$.subscribe('userContent/change', function(){
|
|
clearTimeout(enhanceUserContentTimeout);
|
|
enhanceUserContentTimeout = setTimeout(enhanceUserContent, 50);
|
|
});
|
|
|
|
|
|
$(document).bind('user_content_change', enhanceUserContent);
|
|
setInterval(enhanceUserContent, 15000);
|
|
setTimeout(enhanceUserContent, 1000);
|
|
|
|
$(".zone_cached_datetime").each(function() {
|
|
if($(this).attr('title')) {
|
|
var datetime = tz.parse($(this).attr('title'));
|
|
if (datetime) {
|
|
$(this).text($.datetimeString(datetime));
|
|
}
|
|
}
|
|
});
|
|
|
|
$(".show_sub_messages_link").click(function(event) {
|
|
event.preventDefault();
|
|
$(this).parents(".subcontent").find(".communication_sub_message.toggled_communication_sub_message").removeClass('toggled_communication_sub_message');
|
|
$(this).parents(".communication_sub_message").remove();
|
|
});
|
|
$(".show_comments_link").click(function(event) {
|
|
event.preventDefault();
|
|
$(this).closest("ul").find("li").show();
|
|
$(this).closest("li").remove();
|
|
});
|
|
$(".communication_message .message_short .read_more_link").click(function(event) {
|
|
event.preventDefault();
|
|
$(this).parents(".communication_message").find(".message_short").hide().end()
|
|
.find(".message").show();
|
|
});
|
|
$(".communication_message .close_notification_link").live('click', function(event) {
|
|
event.preventDefault();
|
|
var $message = $(this).parents(".communication_message");
|
|
$message.confirmDelete({
|
|
url: $(this).attr('rel'),
|
|
noMessage: true,
|
|
success: function() {
|
|
$(this).slideUp(function() {
|
|
$(this).remove();
|
|
});
|
|
}
|
|
});
|
|
});
|
|
$(".communication_message .add_entry_link").click(function(event) {
|
|
event.preventDefault();
|
|
var $message = $(this).parents(".communication_message");
|
|
var $reply = $message.find(".reply_message").hide();
|
|
var $response = $message.find(".communication_sub_message.blank").clone(true).removeClass('blank');
|
|
$reply.before($response.show());
|
|
var id = _.uniqueId("textarea_");
|
|
$response.find("textarea.rich_text").attr('id', id);
|
|
$(document).triggerHandler('richTextStart', $("#" + id));
|
|
$response.find("textarea:first").focus().select();
|
|
});
|
|
$(document).bind('richTextStart', function(event, $editor) {
|
|
if(!$editor || $editor.length === 0) { return; }
|
|
$editor = $($editor);
|
|
if(!$editor || $editor.length === 0) { return; }
|
|
$editor.editorBox();
|
|
$editor.editorBox('focus', true);
|
|
if(wikiSidebar) {
|
|
wikiSidebar.attachToEditor($editor);
|
|
$("#sidebar_content").hide();
|
|
wikiSidebar.show();
|
|
}
|
|
}).bind('richTextEnd', function(event, $editor) {
|
|
if(!$editor || $editor.length === 0) { return; }
|
|
$editor = $($editor);
|
|
if(!$editor || $editor.length === 0) { return; }
|
|
$editor.editorBox('destroy');
|
|
if(wikiSidebar) {
|
|
$("#sidebar_content").show();
|
|
wikiSidebar.hide();
|
|
}
|
|
});
|
|
|
|
$(".cant_record_link").click(function(event) {
|
|
event.preventDefault();
|
|
$("#cant_record_dialog").dialog({
|
|
modal: true,
|
|
title: I18n.t('titles.cant_create_recordings', "Can't Create Recordings?"),
|
|
width: 400
|
|
});
|
|
});
|
|
|
|
$(".communication_message .content .links .show_users_link,.communication_message .header .show_users_link").click(function(event) {
|
|
event.preventDefault();
|
|
$(this).parents(".communication_message").find(".content .users_list").slideToggle();
|
|
});
|
|
$(".communication_message .delete_message_link").click(function(event) {
|
|
event.preventDefault();
|
|
$(this).parents(".communication_message").confirmDelete({
|
|
noMessage: true,
|
|
url: $(this).attr('href'),
|
|
success: function() {
|
|
$(this).slideUp();
|
|
}
|
|
});
|
|
});
|
|
$(".communication_sub_message .add_conversation_message_form").formSubmit({
|
|
beforeSubmit: function(data) {
|
|
$(this).find("button").attr('disabled', true);
|
|
$(this).find(".submit_button").text(I18n.t('status.posting_message', "Posting Message..."));
|
|
$(this).loadingImage();
|
|
},
|
|
success: function(data) {
|
|
$(this).loadingImage('remove');
|
|
|
|
// message is the message div containing this form, and conversation the
|
|
// owning conversation. we make a copy of this div before filling it out
|
|
// so that we can use it for the next message (if any)
|
|
var $message = $(this).parents(".communication_sub_message")
|
|
var $conversation = $message.parents(".communication_message");
|
|
|
|
// fill out this message, display the new info, and remove the form
|
|
message_data = data.messages[0];
|
|
$message.fillTemplateData({
|
|
data: {
|
|
post_date: $.datetimeString(message_data.created_at),
|
|
message: message_data.body
|
|
},
|
|
htmlValues: ['message']
|
|
});
|
|
$message.find(".message").show();
|
|
$(this).remove();
|
|
|
|
// turn the "add message" button back on
|
|
$conversation.find(".reply_message").show();
|
|
|
|
// notify the user and any other watchers in the document
|
|
$.flashMessage('Message Sent!');
|
|
$(document).triggerHandler('user_content_change');
|
|
if(location.pathname === '/') {
|
|
$.trackEvent('dashboard_comment', 'create');
|
|
}
|
|
},
|
|
error: function(data) {
|
|
$(this).loadingImage('remove');
|
|
$(this).find("button").attr('disabled', false);
|
|
$(this).find(".submit_button").text("Post Failed, Try Again");
|
|
$(this).formErrors(data);
|
|
}
|
|
});
|
|
$(".communication_sub_message .add_sub_message_form").formSubmit({
|
|
beforeSubmit: function(data) {
|
|
$(this).find("button").attr('disabled', true);
|
|
$(this).find(".submit_button").text(I18n.t('status.posting_message', "Posting Message..."));
|
|
$(this).loadingImage();
|
|
},
|
|
success: function(data) {
|
|
$(this).loadingImage('remove');
|
|
var $message = $(this).parents(".communication_sub_message");
|
|
if($(this).hasClass('submission_comment_form')) {
|
|
var user_id = $(this).getTemplateData({textValues: ['submission_user_id']}).submission_user_id;
|
|
var submission = null;
|
|
for(var idx in data) {
|
|
var s = data[idx].submission;
|
|
if(s.user_id == user_id) {
|
|
submission = s;
|
|
}
|
|
}
|
|
if(submission) {
|
|
var comment = submission.submission_comments[submission.submission_comments.length - 1].submission_comment;
|
|
comment.post_date = $.datetimeString(comment.created_at);
|
|
comment.message = comment.formatted_body || comment.comment;
|
|
$message.fillTemplateData({
|
|
data: comment,
|
|
htmlValues: ['message']
|
|
});
|
|
}
|
|
} else {
|
|
var entry = data.discussion_entry;
|
|
entry.post_date = $.datetimeString(entry.created_at);
|
|
$message.find(".content > .message_html").val(entry.message);
|
|
$message.fillTemplateData({
|
|
data: entry,
|
|
htmlValues: ['message']
|
|
});
|
|
}
|
|
$message.find(".message").show();
|
|
$message.find(".user_content").removeClass('enhanced');
|
|
$message.parents(".communication_message").find(".reply_message").removeClass('lonely_behavior_message').show();
|
|
$(document).triggerHandler('richTextEnd', $(this).find("textarea.rich_text"));
|
|
$(document).triggerHandler('user_content_change');
|
|
$(this).remove();
|
|
if(location.href.match(/dashboard/)) {
|
|
$.trackEvent('dashboard_comment', 'create');
|
|
}
|
|
},
|
|
error: function(data) {
|
|
$(this).loadingImage('remove');
|
|
$(this).find("button").attr('disabled', false);
|
|
$(this).find(".submit_button").text(I18n.t('errors.posting_message_failed', "Post Failed, Try Again"));
|
|
$(this).formErrors(data);
|
|
}
|
|
});
|
|
$(".communication_sub_message form .cancel_button").click(function() {
|
|
var $form = $(this).parents(".communication_sub_message");
|
|
var $message = $(this).parents(".communication_message");
|
|
$(document).triggerHandler('richTextEnd', $form.find("textarea.rich_text"));
|
|
$form.remove();
|
|
$message.find(".reply_message").show();
|
|
});
|
|
$(".communication_message,.communication_sub_message").bind('focusin mouseenter', function() {
|
|
$(this).addClass('communication_message_hover');
|
|
}).bind('focusout mouseleave', function(){
|
|
$(this).removeClass('communication_message_hover');
|
|
});
|
|
$(".communication_sub_message .more_options_reply_link").click(function(event) {
|
|
event.preventDefault();
|
|
var $form = $(this).parents("form");
|
|
var params = null;
|
|
if($form.hasClass('submission_comment_form')) {
|
|
params = {comment: ($form.find("textarea:visible:first").val() || "")};
|
|
} else {
|
|
params = {message: ($form.find("textarea:visible:first").val() || "")};
|
|
}
|
|
location.href = $(this).attr('href') + "?message=" + encodeURIComponent(params.message);
|
|
});
|
|
$(".communication_message.new_activity_message").ifExists(function(){
|
|
this.find(".message_type img").click(function() {
|
|
var $this = $(this),
|
|
c = $.trim($this.attr('class'));
|
|
|
|
$this.parents(".message_type").find("img").removeClass('selected');
|
|
|
|
$this
|
|
.addClass('selected')
|
|
.parents(".new_activity_message")
|
|
.find(".message_type_text").text($this.attr('title')).end()
|
|
.find(".activity_form").hide().end()
|
|
.find("textarea, :text").val("").end()
|
|
.find("." + c + "_form").show()
|
|
.find(".context_select").change();
|
|
});
|
|
this.find(".context_select").change(function() {
|
|
var $this = $(this),
|
|
thisVal = $this.val(),
|
|
$message = $this.parents(".communication_message"),
|
|
$form = $message.find("form");
|
|
$form.attr('action', $message.find("." + thisVal + "_form_url").attr('href'));
|
|
$form.data('context_name', this.options[this.selectedIndex].text);
|
|
$form.data('context_code', thisVal);
|
|
$message.find(".roster_list").hide().find(":checkbox").each(function() { $(this).attr('checked', false); });
|
|
$message.find("." + thisVal + "_roster_list").show();
|
|
}).triggerHandler('change');
|
|
this.find(".cancel_button").click(function(event) {
|
|
$(this).parents(".communication_message").hide().prev(".new_activity_message").show();
|
|
});
|
|
this.find(".new_activity_message_link").click(function(event) {
|
|
event.preventDefault();
|
|
$(this).parents(".communication_message").hide().next(".new_activity_message")
|
|
.find(".message_type img.selected").click().end()
|
|
.show()
|
|
.find(":text:visible:first").focus().select();
|
|
});
|
|
this.find("form.message_form").formSubmit({
|
|
beforeSubmit: function(data) {
|
|
$("button").attr('disabled', true);
|
|
$("button.submit_button").text(I18n.t('status.posting_message', "Posting Message..."));
|
|
},
|
|
success: function(data) {
|
|
$("button").attr('disabled', false);
|
|
$("button.submit_button").text("Post Message");
|
|
var context_code = $(this).data('context_code') || "";
|
|
var context_name = $(this).data('context_name') || "";
|
|
if($(this).hasClass('discussion_topic_form')) {
|
|
var topic = data.discussion_topic;
|
|
topic.context_code = context_name;
|
|
topic.user_name = $("#identity .user_name").text();
|
|
topic.post_date = $.datetimeString(topic.created_at);
|
|
topic.topic_id = topic.id;
|
|
var $template = $(this).parents(".communication_message").find(".template");
|
|
var $message = $template.find(".communication_message").clone(true);
|
|
$message.find(".header .title,.behavior_content .less_important a").attr('href', $template.find("." + context_code + "_topic_url").attr('href'));
|
|
$message.find(".add_entry_link").attr('href', $template.find("." + context_code + "_topics_url").attr('href'));
|
|
$message.find(".user_name").attr('href', $template.find("." + context_code + "_user_url").attr('href'));
|
|
$message.find(".topic_assignment_link,.topic_assignment_url").attr('href', $template.find("." + context_code + "_assignment_url").attr('href'));
|
|
$message.find(".attachment_name,.topic_attachment_url").attr('href', $template.find("." + context_code + "_attachment_url").attr('href'));
|
|
var entry = {discussion_topic_id: topic.id};
|
|
$message.fillTemplateData({
|
|
data: topic,
|
|
hrefValues: ['topic_id', 'user_id', 'assignment_id', 'attachment_id'],
|
|
avoid: '.subcontent'
|
|
});
|
|
$message.find(".subcontent").fillTemplateData({
|
|
data: entry,
|
|
hrefValues: ['topic_id', 'user_id']
|
|
});
|
|
$message.find(".subcontent form").attr('action', $template.find("." + context_code + "_entries_url").attr('href'));
|
|
$message.fillFormData(entry, {object_name: 'discussion_entry'});
|
|
$(this).parents(".communication_message").after($message.hide());
|
|
$message.slideDown();
|
|
$(this).parents(".communication_message").slideUp();
|
|
$(this).parents(".communication_message").prev(".new_activity_message").slideDown();
|
|
} else if($(this).hasClass('announcement_form')) { // do nothing
|
|
} else {
|
|
location.reload();
|
|
}
|
|
},
|
|
error: function(data) {
|
|
$("button").attr('disabled', false);
|
|
$("button.submit_button").text(I18n.t('errors.posting_message_failed', "Post Failed, Try Again"));
|
|
$(this).formErrors(data);
|
|
}
|
|
});
|
|
});
|
|
$("#topic_list .show_all_messages_link").show().click(function(event) {
|
|
event.preventDefault();
|
|
$("#topic_list .topic_message").show();
|
|
$(this).hide();
|
|
});
|
|
|
|
// vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
|
|
// vvvvvvvvvvvvvvvvv BEGIN stuf form making pretty dates vvvvvvvvvvvvvvvvvv
|
|
// vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
|
|
var timeAgoEvents = [];
|
|
function timeAgoRefresh() {
|
|
timeAgoEvents = $(".time_ago_date:visible").toArray();
|
|
processNextTimeAgoEvent();
|
|
}
|
|
function processNextTimeAgoEvent() {
|
|
var eventElement = timeAgoEvents.shift();
|
|
if (eventElement) {
|
|
var $event = $(eventElement),
|
|
date = $event.data('parsed_date') || Date.parse($event.data('timestamp') || "");
|
|
if (date) {
|
|
var diff = new Date() - date;
|
|
$event.data('timestamp', date.toISOString());
|
|
$event.data('parsed_date', date);
|
|
var fudgedDate = $.fudgeDateForProfileTimezone(date);
|
|
var defaultDateString = fudgedDate.toString("MMM d, yyyy") + fudgedDate.toString(" h:mmtt").toLowerCase();
|
|
var dateString = defaultDateString;
|
|
if(diff < (24 * 3600 * 1000)) {
|
|
if(diff < (3600 * 1000)) {
|
|
if(diff < (60 * 1000)) {
|
|
dateString = I18n.t('#time.less_than_a_minute_ago', "less than a minute ago");
|
|
} else {
|
|
var minutes = parseInt(diff / (60 * 1000), 10);
|
|
dateString = I18n.t('#time.count_minutes_ago',
|
|
{one: "1 minute ago", other: "%{count} minutes ago"},
|
|
{count: minutes});
|
|
}
|
|
} else {
|
|
var hours = parseInt(diff / (3600 * 1000), 10);
|
|
dateString = I18n.t('#time.count_hours_ago',
|
|
{one: "1 hour ago", other: "%{count} hours ago"},
|
|
{count: hours});
|
|
}
|
|
}
|
|
$event.text(dateString);
|
|
$event.attr('title', defaultDateString);
|
|
}
|
|
setTimeout(processNextTimeAgoEvent, 1);
|
|
} else {
|
|
setTimeout(timeAgoRefresh, 60000);
|
|
}
|
|
}
|
|
setTimeout(timeAgoRefresh, 100);
|
|
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
// ^^^^^^^^^^^^^^^^^^ END stuff for making pretty dates ^^^^^^^^^^^^^^^^^^^
|
|
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
var sequence_url = $('#sequence_footer .sequence_details_url').filter(':last').attr('href');
|
|
if (sequence_url) {
|
|
$.ajaxJSON(sequence_url, 'GET', {}, function(data) {
|
|
var $sequence_footer = $('#sequence_footer');
|
|
if (data.current_item) {
|
|
$('#sequence_details .current').fillTemplateData({data: data.current_item.content_tag});
|
|
$.each({previous:'.prev', next:'.next'}, function(label, cssClass) {
|
|
var $link = $sequence_footer.find(cssClass);
|
|
if (data[label + '_item'] || data[label + '_module']) {
|
|
var tag = (data[label + '_item'] && data[label + '_item'].content_tag) ||
|
|
(data[label + '_module'] && data[label + '_module'].context_module);
|
|
|
|
if (!data[label + '_item']) {
|
|
tag.title = tag.title || tag.name;
|
|
if( tag.workflow_state === "unpublished" ){
|
|
tag.title += " (" + I18n.t("draft", "Draft") + ")"
|
|
}
|
|
tag.text = (label == 'previous' ?
|
|
I18n.t('buttons.previous_module', "Previous Module") :
|
|
I18n.t('buttons.next_module', "Next Module"));
|
|
$link.addClass('module_button');
|
|
}
|
|
$link.fillTemplateData({ data: tag });
|
|
if (data[label + '_item']) {
|
|
$link.attr('href', $.replaceTags($sequence_footer.find('.module_item_url').attr('href'), 'id', tag.id));
|
|
} else {
|
|
$link.attr('href', $.replaceTags($sequence_footer.find('.module_url').attr('href'), 'id', tag.id) + '/items/' + (label === 'previous' ? 'last' : 'first'));
|
|
}
|
|
} else {
|
|
$link.hide();
|
|
}
|
|
});
|
|
$sequence_footer.show();
|
|
$(window).resize(); //this will be helpful for things like $.fn.fillWindowWithMe so that it knows the dimensions of the page have changed.
|
|
}
|
|
});
|
|
} else {
|
|
var draft_state_msf = $('#sequence_footer.draft_state_enabled')
|
|
if (draft_state_msf.length) {
|
|
var el = $(draft_state_msf[0]);
|
|
el.moduleSequenceFooter({
|
|
courseID: el.attr("data-course-id"),
|
|
assetType: el.attr("data-asset-type"),
|
|
assetID: el.attr("data-asset-id")
|
|
});
|
|
}
|
|
}
|
|
|
|
var $wizard_box = $("#wizard_box");
|
|
|
|
function setWizardSpacerBoxDispay(action){
|
|
$("#wizard_spacer_box").height($wizard_box.height() || 0).showIf(action === 'show');
|
|
}
|
|
|
|
var pathname = window.location.pathname;
|
|
$(".close_wizard_link").click(function(event) {
|
|
event.preventDefault();
|
|
userSettings.set('hide_wizard_' + pathname, true);
|
|
$wizard_box.slideUp('fast', function() {
|
|
$(".wizard_popup_link").slideDown('fast');
|
|
$('.wizard_popup_link').focus();
|
|
setWizardSpacerBoxDispay('hide');
|
|
});
|
|
});
|
|
|
|
$(".wizard_popup_link").click(function(event) {
|
|
event.preventDefault();
|
|
$(".wizard_popup_link").slideUp('fast');
|
|
$wizard_box.slideDown('fast', function() {
|
|
$wizard_box.triggerHandler('wizard_opened');
|
|
$wizard_box.focus();
|
|
$([document, window]).triggerHandler('scroll');
|
|
});
|
|
});
|
|
|
|
$wizard_box.ifExists(function($wizard_box){
|
|
|
|
$wizard_box.bind('wizard_opened', function() {
|
|
var $wizard_options = $wizard_box.find(".wizard_options"),
|
|
height = $wizard_options.height();
|
|
$wizard_options.height(height);
|
|
$wizard_box.find(".wizard_details").css({
|
|
maxHeight: height - 5,
|
|
overflow: 'auto'
|
|
});
|
|
setWizardSpacerBoxDispay('show');
|
|
});
|
|
|
|
$wizard_box.find(".wizard_options_list .option").click(function(event) {
|
|
var $this = $(this);
|
|
var $a = $(event.target).closest("a");
|
|
if($a.length > 0 && $a.attr('href') != "#") { return; }
|
|
event.preventDefault();
|
|
$this.parents(".wizard_options_list").find(".option.selected").removeClass('selected');
|
|
$this.addClass('selected');
|
|
var $details = $wizard_box.find(".wizard_details");
|
|
var data = $this.getTemplateData({textValues: ['header']});
|
|
data.link = data.header;
|
|
$details.fillTemplateData({
|
|
data: data
|
|
});
|
|
$details.find(".details").remove();
|
|
$details.find(".header").after($this.find(".details").clone(true).show());
|
|
var url = $this.find(".header").attr('href');
|
|
if(url != "#") {
|
|
$details.find(".link").show().attr('href', url);
|
|
} else {
|
|
$details.find(".link").hide();
|
|
}
|
|
$details.hide().fadeIn('fast');
|
|
});
|
|
setTimeout(function() {
|
|
if(!userSettings.get('hide_wizard_' + pathname)) {
|
|
$(".wizard_popup_link.auto_open:first").click();
|
|
}
|
|
}, 500);
|
|
});
|
|
|
|
// this is for things like the to-do, recent items and upcoming, it
|
|
// happend a lot so rather than duplicating it everywhere I stuck it here
|
|
$("#right-side").delegate(".more_link", "click", function(event) {
|
|
var $this = $(this);
|
|
var $children = $this.parents("ul").children(':hidden').show();
|
|
$this.closest('li').remove();
|
|
|
|
// if they are using the keyboard to navigate (they hit enter on the link instead of actually
|
|
// clicking it) then put focus on the first of the now-visible items--otherwise, since the
|
|
// .more_link is hidden, focus would be completely lost and leave a blind person stranded.
|
|
// don't want to set focus if came from a mouse click because then you'd have 2 of the tooltip
|
|
// bubbles staying visible, see #9211
|
|
if (event.screenX === 0) {
|
|
$children.first().find(":tabbable:first").focus();
|
|
}
|
|
return false;
|
|
});
|
|
$("#right-side, #topic_list").delegate('.disable_item_link', 'click', function(event) {
|
|
event.preventDefault();
|
|
var $item = $(this).parents("li, div.topic_message");
|
|
var url = $(this).data('api-href');
|
|
function remove(delete_url) {
|
|
$item.confirmDelete({
|
|
url: delete_url,
|
|
noMessage: true,
|
|
success: function() {
|
|
$(this).slideUp(function() {
|
|
$(this).remove();
|
|
});
|
|
}
|
|
});
|
|
}
|
|
if($(this).hasClass('grading')) {
|
|
options = {}
|
|
options['<span class="ui-icon ui-icon-trash"> </span> ' + htmlEscape(I18n.t('ignore_forever', 'Ignore Forever'))] = function() { remove(url + "?permanent=1"); };
|
|
options['<span class="ui-icon ui-icon-star"> </span> ' + htmlEscape(I18n.t('ignore_until_new_submission', 'Ignore Until New Submission'))] = function() { remove(url); };
|
|
$(this).dropdownList({ options: options });
|
|
} else {
|
|
remove(url + "?permanent=1");
|
|
}
|
|
});
|
|
|
|
// in 2 seconds (to give time for everything else to load), find all the external links and add give them
|
|
// the external link look and behavior (force them to open in a new tab)
|
|
setTimeout(function() {
|
|
$("#content a:external,#content a.explicit_external_link").each(function(){
|
|
$(this)
|
|
.not(":has(img)")
|
|
.not(".not_external")
|
|
.addClass('external')
|
|
.children("span.ui-icon-extlink").remove().end()
|
|
.html('<span>' + $(this).html() + '</span>')
|
|
.attr('target', '_blank')
|
|
.append('<span class="ui-icon ui-icon-extlink ui-icon-inline" title="' + htmlEscape(I18n.t('titles.external_link', 'Links to an external site.')) + '"/>');
|
|
});
|
|
}, 2000);
|
|
});
|
|
|
|
$('input[placeholder], textarea[placeholder]').placeholder();
|
|
});
|