feat: add full screen modal option to base_modal (#38001)
Adds a "Fullscreen" button to the iframe editors for advanced XBlocks
This commit is contained in:
@@ -21,6 +21,7 @@
|
||||
* primaryActionButtonType: A string to be used as type for primary action button.
|
||||
* primaryActionButtonTitle: A string to be used as title for primary action button.
|
||||
* showEditorModeButtons: Whether to show editor mode button in the modal header.
|
||||
* showFullscreenButton: Whether to show fullscreen button in the modal header.
|
||||
*/
|
||||
define(['jquery', 'underscore', 'gettext', 'js/views/baseview'],
|
||||
function($, _, gettext, BaseView) {
|
||||
@@ -43,7 +44,8 @@ define(['jquery', 'underscore', 'gettext', 'js/views/baseview'],
|
||||
addPrimaryActionButton: false,
|
||||
primaryActionButtonType: 'save',
|
||||
primaryActionButtonTitle: gettext('Save'),
|
||||
showEditorModeButtons: true
|
||||
showEditorModeButtons: true,
|
||||
showFullscreenButton: false,
|
||||
}),
|
||||
|
||||
initialize: function() {
|
||||
@@ -71,7 +73,8 @@ define(['jquery', 'underscore', 'gettext', 'js/views/baseview'],
|
||||
title: this.getTitle(),
|
||||
modalSRTitle: this.options.modalSRTitle,
|
||||
showEditorModeButtons: this.options.showEditorModeButtons,
|
||||
viewSpecificClasses: this.options.viewSpecificClasses
|
||||
viewSpecificClasses: this.options.viewSpecificClasses,
|
||||
showFullscreenButton: this.options.showFullscreenButton,
|
||||
}));
|
||||
this.addActionButtons();
|
||||
this.renderContents();
|
||||
@@ -83,9 +86,14 @@ define(['jquery', 'underscore', 'gettext', 'js/views/baseview'],
|
||||
},
|
||||
|
||||
renderContents: function() {
|
||||
var contentHtml = this.getContentHtml();
|
||||
const contentHtml = this.getContentHtml();
|
||||
// xss-lint: disable=javascript-jquery-html
|
||||
this.$('.modal-content').html(contentHtml);
|
||||
|
||||
const fullscreenButton = this.$('.fullscreen-button');
|
||||
if (fullscreenButton.length) {
|
||||
fullscreenButton.bind('click', this.toggleFullscreen.bind(this));
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -106,6 +114,7 @@ define(['jquery', 'underscore', 'gettext', 'js/views/baseview'],
|
||||
// after showing and resizing, send focus
|
||||
this.$el.find(this.options.modalWindowClass).focus();
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
hide: function() {
|
||||
@@ -120,6 +129,10 @@ define(['jquery', 'underscore', 'gettext', 'js/views/baseview'],
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
const fullscreenButton = this.$('.fullscreen-button');
|
||||
if (fullscreenButton.length) {
|
||||
fullscreenButton.unbind('click');
|
||||
}
|
||||
|
||||
// Completely remove the modal from the DOM
|
||||
this.undelegateEvents();
|
||||
@@ -195,11 +208,25 @@ define(['jquery', 'underscore', 'gettext', 'js/views/baseview'],
|
||||
this.getActionBar().find('.action-' + type).prop('disabled', true).addClass('is-disabled');
|
||||
},
|
||||
|
||||
toggleFullscreen: function() {
|
||||
this.$('.fullscreen-button .icon').toggleClass('fa-expand fa-compress');
|
||||
this.$('.modal-editor').toggleClass(`modal-${this.options.modalSize} modal-fullscreen`);
|
||||
this.resize();
|
||||
},
|
||||
|
||||
resize: function() {
|
||||
var top, left, modalWindow, modalWidth, modalHeight,
|
||||
availableWidth, availableHeight, maxWidth, maxHeight;
|
||||
|
||||
modalWindow = this.$el.find(this.options.modalWindowClass);
|
||||
if (modalWindow.hasClass('modal-fullscreen')) {
|
||||
// Remove previously set width and height from the modal window
|
||||
modalWindow.css({
|
||||
top: '',
|
||||
left: '',
|
||||
});
|
||||
return;
|
||||
}
|
||||
availableWidth = $(window).width();
|
||||
availableHeight = $(window).height();
|
||||
maxWidth = availableWidth * 0.98;
|
||||
|
||||
@@ -21,7 +21,8 @@ function($, _, Backbone, gettext, BaseModal, ViewUtils, XBlockViewUtils, XBlockE
|
||||
viewSpecificClasses: 'modal-editor confirm',
|
||||
// Translators: "title" is the name of the current component being edited.
|
||||
titleFormat: gettext('Editing: {title}'),
|
||||
addPrimaryActionButton: true
|
||||
addPrimaryActionButton: true,
|
||||
showFullscreenButton: true,
|
||||
}),
|
||||
|
||||
initialize: function() {
|
||||
@@ -127,6 +128,7 @@ function($, _, Backbone, gettext, BaseModal, ViewUtils, XBlockViewUtils, XBlockE
|
||||
} else {
|
||||
this.$('.modal-window-title').text(title);
|
||||
}
|
||||
|
||||
this.getXBlockUpstreamLink();
|
||||
|
||||
// If the xblock is not using custom buttons then choose which buttons to show
|
||||
@@ -292,8 +294,7 @@ function($, _, Backbone, gettext, BaseModal, ViewUtils, XBlockViewUtils, XBlockE
|
||||
$input.focus().select();
|
||||
$(event.target).remove();
|
||||
return true;
|
||||
}
|
||||
|
||||
},
|
||||
});
|
||||
|
||||
return EditXBlockModal;
|
||||
|
||||
@@ -452,12 +452,31 @@ body,
|
||||
line-height: 28px;
|
||||
}
|
||||
|
||||
.fullscreen-button {
|
||||
color: $primary-base;
|
||||
height: 44px;
|
||||
width: 44px;
|
||||
border-radius: 22px;
|
||||
|
||||
&:hover {
|
||||
border-color: $primary-base;
|
||||
}
|
||||
|
||||
&:focus {
|
||||
border-color: $primary-base;
|
||||
}
|
||||
}
|
||||
|
||||
.xblock-actions {
|
||||
border-top: 1px solid $border-color;
|
||||
background-color: $white;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
|
||||
ul {
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.action-button {
|
||||
background-color: $transparent;
|
||||
border: 1px solid $transparent;
|
||||
|
||||
@@ -308,6 +308,14 @@
|
||||
bottom: 30px;
|
||||
}
|
||||
}
|
||||
|
||||
.fullscreen-button {
|
||||
height: 44px;
|
||||
width: 44px;
|
||||
position: absolute;
|
||||
right: 30px;
|
||||
z-index: 10;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -391,6 +399,48 @@
|
||||
}
|
||||
}
|
||||
|
||||
// fullscreen modals - component editors
|
||||
.modal-fullscreen {
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
|
||||
// Set the components to flex so that they can grow
|
||||
div,
|
||||
form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-grow: 1;
|
||||
|
||||
// Set the header to not grow
|
||||
header,
|
||||
&.modal-header {
|
||||
flex-grow: 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ul {
|
||||
flex-grow: 1;
|
||||
|
||||
// Reset the divs inside the ul to preserve previous styling
|
||||
div,
|
||||
form {
|
||||
display: unset;
|
||||
flex-direction: unset;
|
||||
flex-grow: unset;
|
||||
}
|
||||
}
|
||||
|
||||
&.modal-editor {
|
||||
.modal-content {
|
||||
padding: 0px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// specific modal overrides
|
||||
|
||||
@@ -3,6 +3,9 @@
|
||||
role="dialog">
|
||||
<div class="modal-window-overlay"></div>
|
||||
<div class="modal-window <%- viewSpecificClasses %> modal-<%- size %> modal-type-<%- type %>" tabindex="-1" aria-labelledby="modal-window-title">
|
||||
<% if (showFullscreenButton) { %>
|
||||
<button class="btn-default fullscreen-button" aria-label="<%- gettext("Toggle Fullscreen") %>"><span class="icon fa fa-expand"></span></button>
|
||||
<% } %>
|
||||
<div class="<%- name %>-modal">
|
||||
<% if (title || modalSRTitle || showEditorModeButtons) { %>
|
||||
<div class="modal-header">
|
||||
@@ -29,3 +32,4 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user