diff --git a/cms/templates/unit.html b/cms/templates/unit.html index 04d73d8efd..40aaee6b2c 100644 --- a/cms/templates/unit.html +++ b/cms/templates/unit.html @@ -4,6 +4,7 @@ from django.core.urlresolvers import reverse from django.utils.translation import ugettext as _ from xmodule.modulestore.django import loc_mapper %> +<%namespace name='static' file='static_content.html'/> <%namespace name="units" file="widgets/units.html" /> <%block name="title">${_("Individual Unit")} <%block name="bodyclass">is-signedin course unit view-unit @@ -31,6 +32,10 @@ require(["domReady!", "jquery", "js/models/module_info", "coffee/src/views/unit" }); }); + + <%block name="content"> @@ -207,5 +212,7 @@ require(["domReady!", "jquery", "js/models/module_info", "coffee/src/views/unit" + + diff --git a/common/lib/xmodule/xmodule/css/html/display.scss b/common/lib/xmodule/xmodule/css/html/display.scss index a4e5bd6ac0..6ce6ca5ee9 100644 --- a/common/lib/xmodule/xmodule/css/html/display.scss +++ b/common/lib/xmodule/xmodule/css/html/display.scss @@ -145,3 +145,148 @@ th { background: #eee; font-weight: bold; } + + +// image modal +// -------------------- + +// modal - image zoom, fill window +.wrapper-modal-image { + + .modal-ui-icon { + position: absolute; + display: block; + padding: 5px 7px; + cursor: pointer; + border-radius: 5px; + opacity: .9; + background: $white; + color: $black; + border: 2px solid $black; + + .label { + font-weight: bold; + } + + i { + font-style: normal; + } + } + + .image-link { + position: relative; + display: block; + cursor: pointer; + + .action-fullscreen { + display: none; + top: 10px; + left: 10px; + } + + &:hover .action-fullscreen { + display: block; + } + } + + .image-modal { + position: fixed; + top: 0; + left: 0; + display: none; + height: 100%; + width: 100%; + @extend %ui-depth5; + cursor: pointer; + background-color: rgba(0, 0, 0, 0.7); + + .image-content { + position: relative; + top: 2.5%; + display: block; + height: 95%; + width: 95%; + margin: auto; + overflow: hidden; + + .image-wrapper { + position: relative; + + img { + position: relative; + display: block; + max-width: 100%; + max-height: 100%; + margin: auto; + cursor: default; + } + } + + .action-close { + top: 10px; + right: 10px; + } + + .image-controls { + position: absolute; + right: 10px; + bottom: 10px; + margin: 0; + padding: 0; + list-style: none; + + .image-control { + position: relative; + display: inline-block; + margin: 0; + padding: 0; + + .modal-ui-icon { + position: relative; + + &.action-zoom-in { + margin-right: 5px; + } + &.action-zoom-out { + margin-left: 5px; + } + &.is-disabled { + opacity: .5; + cursor: default; + } + } + } + } + } + + &.image-is-fit-to-screen { + display: block; + + // !important used here to override jQuery. + .image-content .image-wrapper { + top: 0 !important; + left: 0 !important; + width: auto !important; + height: auto !important; + + img { + top: 0 !important; + left: 0 !important; + } + } + } + &.image-is-zoomed { + display: block; + + .image-content .image-wrapper { + + img { + max-width: none; + max-height: none; + margin: 0; + cursor: move; + } + } + } + } +} \ No newline at end of file diff --git a/common/lib/xmodule/xmodule/html_module.py b/common/lib/xmodule/xmodule/html_module.py index 03c3ed3372..d00effc7db 100644 --- a/common/lib/xmodule/xmodule/html_module.py +++ b/common/lib/xmodule/xmodule/html_module.py @@ -44,6 +44,10 @@ class HtmlModule(HtmlFields, XModule): resource_string(__name__, 'js/src/javascript_loader.coffee'), resource_string(__name__, 'js/src/collapsible.coffee'), resource_string(__name__, 'js/src/html/display.coffee') + ], + 'js': [ + resource_string(__name__, 'js/src/html/imageModal.js'), + resource_string(__name__, 'js/common_static/js/vendor/draggabilly.pkgd.js') ] } js_module_name = "HTMLModule" diff --git a/common/lib/xmodule/xmodule/js/src/html/imageModal.js b/common/lib/xmodule/xmodule/js/src/html/imageModal.js new file mode 100644 index 0000000000..19953eae03 --- /dev/null +++ b/common/lib/xmodule/xmodule/js/src/html/imageModal.js @@ -0,0 +1,109 @@ +$(function() { + + // Set up on page load + $("a.modal-content").each(function() { + var smallImageObject = $(this).children(); + var largeImageSRC = $(this).attr('href'); + + // if contents of zoomable link is image and large image link exists: setup modal + if (smallImageObject.is('img') && largeImageSRC) { + var data = { + "smallHTML": $(this).html(), + "largeALT": smallImageObject.attr('alt'), + "largeSRC": largeImageSRC + }; + var html = _.template($("#image-modal-tpl").text(), data); + $(this).replaceWith(html); + } + }); + $('.wrapper-modal-image .image-wrapper img').each(function() { + var draggie = new Draggabilly(this, {containment: true}); + draggie.disable(); + $(this).closest('.image-modal').data("draggie", draggie); + }); + + // Opening and closing image modal on clicks + $(".wrapper-modal-image .image-link").click(function() { + $(this).siblings(".image-modal").addClass('image-is-fit-to-screen'); + $('body').css('overflow', 'hidden'); + }); + + // variable to detect when modal is being "hovered". + // Done this way as jquery doesn't support the :hover psudo-selector as expected. + var imageModalImageHover = false; + $(".wrapper-modal-image .image-content img, .wrapper-modal-image .image-content .image-controls").hover(function() { + imageModalImageHover = true; + }, function() { + imageModalImageHover = false; + }); + + // prevent image control button links from scrolling + $(".modal-ui-icon").click(function(event) { + event.preventDefault(); + }); + + //Define function to close modal + function closeModal(imageModal) { + imageModal.removeClass('image-is-fit-to-screen').removeClass('image-is-zoomed'); + $(".wrapper-modal-image .image-content .image-controls .modal-ui-icon.action-zoom-in").removeClass('is-disabled'); + $(".wrapper-modal-image .image-content .image-controls .modal-ui-icon.action-zoom-out").addClass('is-disabled'); + var currentDraggie = imageModal.data("draggie"); + currentDraggie.disable(); + $('body').css('overflow', 'auto'); + } + + // Click outside of modal to close it. + $(".wrapper-modal-image .image-modal").click(function() { + if (!imageModalImageHover){ + closeModal($(this)); + } + }); + + // Click close icon to close modal. + $(".wrapper-modal-image .image-content .action-remove").click(function() { + closeModal($(this).closest(".image-modal")); + }); + + // zooming image in modal and allow it to be dragged + // Make sure it always starts zero position for below calcs to work + $(".wrapper-modal-image .image-content .image-controls .modal-ui-icon").click(function() { + if (!$(this).hasClass('is-disabled')) { + var mask = $(this).closest(".image-content"); + + var imageModal = $(this).closest(".image-modal"); + var img = imageModal.find("img"); + var currentDraggie = imageModal.data("draggie"); + + if ($(this).hasClass('action-zoom-in')) { + imageModal.removeClass('image-is-fit-to-screen').addClass('image-is-zoomed'); + + var imgWidth = img.width(); + var imgHeight = img.height(); + + var imgContainerOffsetLeft = imgWidth - mask.width(); + var imgContainerOffsetTop = imgHeight - mask.height(); + var imgContainerWidth = imgWidth + imgContainerOffsetLeft; + var imgContainerHeight = imgHeight + imgContainerOffsetTop; + + // Set the width and height of the image's container so that the dimensions are equal to the image dimensions + view area dimensions to limit dragging + // Set image container top and left to center image at load. + img.parent().css({ + left: -imgContainerOffsetLeft, + top: -imgContainerOffsetTop, + width: imgContainerWidth, + height: imgContainerHeight + }); + img.css({top: imgContainerOffsetTop / 2, left: imgContainerOffsetLeft / 2}); + + currentDraggie.enable(); + + } else if ($(this).hasClass('action-zoom-out')) { + imageModal.removeClass('image-is-zoomed').addClass('image-is-fit-to-screen'); + + currentDraggie.disable(); + } + + $(".wrapper-modal-image .image-content .image-controls .modal-ui-icon").toggleClass('is-disabled'); + } + }); +}); \ No newline at end of file diff --git a/common/lib/xmodule/xmodule/templates/html/image_modal.yaml b/common/lib/xmodule/xmodule/templates/html/image_modal.yaml new file mode 100644 index 0000000000..73c4419f66 --- /dev/null +++ b/common/lib/xmodule/xmodule/templates/html/image_modal.yaml @@ -0,0 +1,6 @@ +--- +metadata: + display_name: Image Modal +data: | +

Title of Unit (click image to zoom)

+ The Stanford Hills \ No newline at end of file diff --git a/common/templates/js/imageModal.underscore b/common/templates/js/imageModal.underscore new file mode 100644 index 0000000000..40f7432280 --- /dev/null +++ b/common/templates/js/imageModal.underscore @@ -0,0 +1,42 @@ +
+ + +
+
+
+ <%= largeALT %>, <%= gettext('Large') %> +
+ + + + <%= gettext("Close") %> + + + + +
+
+
\ No newline at end of file diff --git a/lms/templates/courseware/courseware.html b/lms/templates/courseware/courseware.html index 070c751d1a..d1ce55a50b 100644 --- a/lms/templates/courseware/courseware.html +++ b/lms/templates/courseware/courseware.html @@ -167,6 +167,10 @@ ${page_title_breadcrumbs(course_name())} % endif + + ${fragment.foot_html()}