Image Modal CMS HTML Block subtype
- Added YAML file for the HTML template code for the modal to work - Added CSS and JS code for modal to look and function properly - Updated code to take comments into account. - Simplified HTML template and expanded JS to set up image modal on load. - Added preliminary drag script. - Converted jQuery UI draggable to Draggabilly
This commit is contained in:
@@ -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>
|
||||
<%block name="bodyclass">is-signedin course unit view-unit</%block>
|
||||
@@ -31,6 +32,10 @@ require(["domReady!", "jquery", "js/models/module_info", "coffee/src/views/unit"
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<script type="text/template" id="image-modal-tpl">
|
||||
<%static:include path="js/imageModal.underscore" />
|
||||
</script>
|
||||
|
||||
</%block>
|
||||
<%block name="content">
|
||||
@@ -207,5 +212,7 @@ require(["domReady!", "jquery", "js/models/module_info", "coffee/src/views/unit"
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</%block>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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"
|
||||
|
||||
109
common/lib/xmodule/xmodule/js/src/html/imageModal.js
Normal file
109
common/lib/xmodule/xmodule/js/src/html/imageModal.js
Normal file
@@ -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');
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
metadata:
|
||||
display_name: Image Modal
|
||||
data: |
|
||||
<h2>Title of Unit (click image to zoom)</h2>
|
||||
<a href="http://static.class.stanford.edu/stanford-hills-big.jpg" class="modal-content"><img alt="The Stanford Hills" src="http://static.class.stanford.edu/stanford-hills-small.jpg" /></a>
|
||||
42
common/templates/js/imageModal.underscore
Normal file
42
common/templates/js/imageModal.underscore
Normal file
@@ -0,0 +1,42 @@
|
||||
<div class="wrapper-modal wrapper-modal-image">
|
||||
<section class="image-link">
|
||||
<%= smallHTML%>
|
||||
<a href="#" class="modal-ui-icon action-fullscreen" role="button">
|
||||
<span class="label">
|
||||
<i class="icon-fullscreen icon-large"></i> <%= gettext("Fullscreen") %>
|
||||
</span>
|
||||
</a>
|
||||
</section>
|
||||
|
||||
<section class="image-modal">
|
||||
<section class="image-content">
|
||||
<div class="image-wrapper">
|
||||
<img alt="<%= largeALT %>, <%= gettext('Large') %>" src="<%= largeSRC %>" />
|
||||
</div>
|
||||
|
||||
<a href="#" class="modal-ui-icon action-close" role="button">
|
||||
<span class="label">
|
||||
<i class="icon-remove icon-large"></i> <%= gettext("Close") %>
|
||||
</span>
|
||||
</a>
|
||||
|
||||
<ul class="image-controls">
|
||||
<li class="image-control">
|
||||
<a href="#" class="modal-ui-icon action-zoom-in" role="button">
|
||||
<span class="label">
|
||||
<i class="icon-zoom-in icon-large"></i> <%= gettext("Zoom In") %>
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="image-control">
|
||||
<a href="#" class="modal-ui-icon action-zoom-out is-disabled" role="button">
|
||||
<span class="label">
|
||||
<i class="icon-zoom-out icon-large"></i> <%= gettext("Zoom Out") %>
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
</section>
|
||||
</div>
|
||||
@@ -167,6 +167,10 @@ ${page_title_breadcrumbs(course_name())}
|
||||
</script>
|
||||
% endif
|
||||
|
||||
<script type="text/template" id="image-modal-tpl">
|
||||
<%static:include path="js/imageModal.underscore" />
|
||||
</script>
|
||||
|
||||
${fragment.foot_html()}
|
||||
|
||||
</%block>
|
||||
|
||||
Reference in New Issue
Block a user