I'm using MaterializeCss Modals (https://materializecss.com/modals.html), and I'm attempting to add a Modal when clicking on a date in a the calendar.
<script>
document.addEventListener('DOMContentLoaded', function() {
var elems = document.querySelectorAll('.modal');
var instances = M.Modal.init(elems);
var calendarEl = document.getElementById('calendar');
var calendar = new FullCalendar.Calendar(calendarEl, {
plugins: [ 'dayGrid', 'interaction' ],
height: 655,
selectable: true,
dateClick: function(info) {
// Not sure what to put here
},
}
);
calendar.render();
});
</script>
The modal opens with the standard HTML given on the Materialize website,
<!-- Modal Trigger -->
<a class="waves-effect waves-light btn modal-trigger" href="#modal1">Modal</a>
<!-- Modal Structure -->
<div id="modal1" class="modal">
<div class="modal-content">
<h4>Modal Header</h4>
<p>A bunch of text</p>
</div>
<div class="modal-footer">
Agree
</div>
</div>
But I need to trigger the Modal opening on the dateClick function.
instances[0].open();
These two lines selects all elements with a class of modal, and intialises them:
var elems = document.querySelectorAll('.modal');
var instances = M.Modal.init(elems);
instances is an array, so we need to select the modal we'd like to open, in our case it's the first (only) one.
https://materializecss.com/modals.html#methods
Related
I dont really know what is causing the error since I'm new to JavaScript. I've referenced the variable in the header with js:
document.addEventListener('DOMContentLoaded', function() {
var calendarEl = document.getElementById('calendar');
var calendar = new FullCalendar.Calendar(calendarEl, {
selectable: true,
selectHelper: true,
select: function date(start, end, alldays){
$("#BookingModal").modal('toggle');
var tgl=moment(start).format('DD-MM-YYYY')
}
});
calendar.render();
});
And when I want to use the variable in the body of the html, it throws the error:
uncaught ReferenceError: tgl is not defined
<h1 class="modal-title fs-5" id="exampleModalLabel"> <script type="text/javascript">document.write(tgl)</script></h1>
The modal title you whish to have is dynamic based on the calendar cell that was clicked.
So you have to wait for the user to click on a calendar cell to know what is the startDate provided in this select callback.
The code below will be exectuted on page load while parsing the HTML...
Long before the rest of your code that will execute after DOMContentLoaded has fired.
<script type="text/javascript">document.write(tgl)</script>
The events are firing in this order and that is how tgl should be used in each of them:
DOMContentLoaded -- tgl is declared
FullCalendar's select -- tgl value is setted
show.bs.modal -- tgl value is used
document.addEventListener("DOMContentLoaded", function () {
// Have the tgl variable at global scope
let tgl;
// On modal open, set the modal title
$("#BookingModal").on("show.bs.modal", function (event) {
$("#BookingModal").find(".modal-title").text(tgl);
});
// FulCalendar
var calendarEl = document.getElementById("calendar");
var calendar = new FullCalendar.Calendar(calendarEl, {
selectable: true,
select: function date(start, end, alldays) {
// Set tgl here
tgl = moment(start.startStr).format("DD-MM-YYYY");
// Open modal
$("#BookingModal").modal("show");
}
});
calendar.render();
});
<link href="https://cdn.jsdelivr.net/npm/bootstrap#4.0.0/dist/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js#1.12.9/dist/umd/popper.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap#4.0.0/dist/js/bootstrap.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/fullcalendar#6.0.2/index.global.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.4/moment.min.js"></script>
<div id="calendar"></div>
<div class="modal fade" id="BookingModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">This title will be replaced</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
Some modal body here...
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary" data-dismiss="modal">Ok</button>
</div>
</div>
</div>
</div>
CodePen
Also, notice I used start.startStr to pass to moment.js. You can console log that start object of FullCalendar to understand why.
I created FullCalendar with Bootstrap Modal, but displayed data is transferred from one modal to another after click.
At first all events have the proper data. But if i click on event, close it and open another
,then context of first clicked event is displayed inside second one.
Any ideas where may be the problem?
JS basic elements:
<script>
function loadCalendar() {
var calendarEl = document.getElementById('calendar');
var calendar = new FullCalendar.Calendar(calendarEl, {
// setup local parameters
selectable: true,
plugins: ['interaction', 'dayGrid'],
firstDay : 1,
header: {
left: 'today',
center: 'title',
right: 'prev, next',
},
// load all events
events: [
{% for event in events %}
{
id: '{{event.id}}',
user: '{{event.user}}',
},
{% endfor %}
],
eventClick: function(event) {
console.log('modal', event);
$('#modal_window').modal();
$('#modal_title').html(event.event.extendedProps.client_name);
}
},
});
calendar.render();
};
// load calendar function
if (document.readyState !== 'complete') {
document.addEventListener('DOMContentLoaded', loadCalendar);
} else {
loadCalendar();
}
</script>
Bootstrap:
<!-- Calendar-->
<div id='calendar'></div>
<!-- Modal -->
<div id="modal_window" class="modal fade bd-example-modal-sm">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-body">
<p id="modal_title"></p>
</div>
<!-- Modal footer -->
<div class="modal-footer">
<button type="button" class="btn btn-danger" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
Thank you all for your time.
I believe I will get a solution here, bootstrap modal does not disappear after form submission. I only want to make bootstrap modal disappear after form submission and when again button is clicked (without refreshing the page) form should open, send data and modal should disappears and so on... This is it !
Here is a bootstrap modal:
<div class="modal fade myPopup" id="basicModal" tabindex="-1" role="dialog"
aria-labelledby="basicModal" aria-hidden="true">
<div class="modal-dialog" id="modal_dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h4 class="modal-title" id="myModalLabel">Add New Board</h4>
</div>
<div class="modal-body">
<form class="create_Category_board" id="myform">
<input type="text"
id="customInput"
class="board_name"
name="board[name]"
placeholder="Board Name ..." />
<input type="text"
class="board_description"
name="board[description]"
placeholder="Board Description ..." />
<input type="hidden"
class="board_description"
id="myCid"
name="board[category_id]" />
<input type="submit" value="Create Board" class="ShowFormButton"/>
</form>
</div>
<div class="modal-footer">
</div>
</div>
</div>
</div>
My form is bound with backbone JS function:
events: {
"submit form.create_Category_board": "createCategoryBoard"
},
createCategoryBoard: function(event) {
event.preventDefault();
var that = this;
// get form attrs, reset form
var $form = $(event.target);
var attrs = $form.serializeJSON();
$form[0].reset();
var board = new Kanban.Models.Board();
// fail if no board name
if (!attrs.board.name) {
var $createContainer = $("div.create_board");
var $nameInput = that.$el.find("input.board_name");
$createContainer.effect("shake", {
distance: 9,
times: 2,
complete: function() {
$nameInput.show();
$nameInput.focus();
}
}, 350);
return false;
}
attrs.board.category_id = myid;
var category = Kanban.categories.get(myid);
var boards = category.get("assigned_boards");
// save list
board.save(attrs.board, {
success: function(data) {
board.get("users").add(Kanban.currentUser);
boards.add(board);
// keep focus on list input
that.$el.find("input.board_name").focus();
}
});
$('#basicModal').modal('hide');
}
As a last line in above function I have tried most popular solution $('#basicModal').modal('hide'); available on web! It makes my modal look like this:
i.e. it not hides the modal, moreover make screen black and change the direction of bootstrap modal from center of screen to little right. May be it is overridden by CSS of JS. But I am not sure.
I am posting my own answer because if some one needs a quicker help, then may be it is helpful:
Just replace: $('#basicModal').modal('hide'); with this line:
$(".modal-header button").click(); which is last line of my JS function.
Cheers :)
Problem is that div.modal-backdrop remains after you hide the modal,
you can see it in developer tools.Try simple remove
$('#basicModal').modal('hide');
$('.modal-backdrop').remove();
Cheers
I have the simple code:
<button class="pswp__button" id="CustomButton" style="background:none;" title="Custom" onclick="CustomClicked()">
<img src="~/CustomImage.jpg"">
</button>
This works as expected on desktop browsers. When I switch to mobile though, I cannot get the event to fire when I tap the button. I've tried attaching every event handler I can think of: tap, click, touch, touchstart, etc, and I can still not get any of the events to fire on mobile.
If I invoke the click event through the console, it works on mobile as well, but I can't seem to get the click event to propagate to that control. I've tried setting its zindex to ridiculous values, and still no luck. Anyone have a clue?
After searching for some solutions online, they all seem to have teh same problem. This one, for instance, doesn't fire on mobile either:
var openPhotoSwipe = function() {
var pswpElement = document.querySelectorAll('.pswp')[0];
// build items array
var items = [
{
src: 'https://farm2.staticflickr.com/1043/5186867718_06b2e9e551_b.jpg',
w: 964,
h: 1024
},
{
src: 'https://farm7.staticflickr.com/6175/6176698785_7dee72237e_b.jpg',
w: 1024,
h: 683
}
];
// define options (if needed)
var options = {
// history & focus options are disabled on CodePen
history: false,
focus: false,
showAnimationDuration: 0,
hideAnimationDuration: 0
};
var gallery = new PhotoSwipe( pswpElement, PhotoSwipeUI_Default, items, options);
gallery.init();
};
openPhotoSwipe();
$(document).on('click', '.pswp__button.pswp__button--close' , function(){
alert('d'); // did not fire?
});
document.getElementById('btn').onclick = openPhotoSwipe;
<button id="btn">Open PhotoSwipe</button>
<!-- Root element of PhotoSwipe. Must have class pswp. -->
<div class="pswp" tabindex="-1" role="dialog" aria-hidden="true">
<!-- Background of PhotoSwipe.
It's a separate element, as animating opacity is faster than rgba(). -->
<div class="pswp__bg"></div>
<!-- Slides wrapper with overflow:hidden. -->
<div class="pswp__scroll-wrap">
<!-- Container that holds slides. PhotoSwipe keeps only 3 slides in DOM to save memory. -->
<div class="pswp__container">
<!-- don't modify these 3 pswp__item elements, data is added later on -->
<div class="pswp__item"></div>
<div class="pswp__item"></div>
<div class="pswp__item"></div>
</div>
<!-- Default (PhotoSwipeUI_Default) interface on top of sliding area. Can be changed. -->
<div class="pswp__ui pswp__ui--hidden">
<div class="pswp__top-bar">
<!-- Controls are self-explanatory. Order can be changed. -->
<div class="pswp__counter"></div>
<button class="pswp__button pswp__button--close" title="Close (Esc)"></button>
<button class="pswp__button pswp__button--share" title="Share"></button>
<button class="pswp__button pswp__button--fs" title="Toggle fullscreen"></button>
<button class="pswp__button pswp__button--zoom" title="Zoom in/out"></button>
<!-- Preloader demo http://codepen.io/dimsemenov/pen/yyBWoR -->
<!-- element will get class pswp__preloader--active when preloader is running -->
<div class="pswp__preloader">
<div class="pswp__preloader__icn">
<div class="pswp__preloader__cut">
<div class="pswp__preloader__donut"></div>
</div>
</div>
</div>
</div>
<div class="pswp__share-modal pswp__share-modal--hidden pswp__single-tap">
<div class="pswp__share-tooltip"></div>
</div>
<button class="pswp__button pswp__button--arrow--left" title="Previous (arrow left)">
</button>
<button class="pswp__button pswp__button--arrow--right" title="Next (arrow right)">
</button>
<div class="pswp__caption">
<div class="pswp__caption__center"></div>
</div>
</div>
</div>
</div>
In order to achieve this functionality, you must edit hte photoswipe-ui-default.js file.
Your custom button must have the class pswp__button--myCustomButtonName as well as pswp__button.
<button class="pswp__button pswp__button--myCustomButtonName" id="CustomButton" style="background:none;" title="Custom" onclick="CustomClicked()">
<img src="~/CustomImage.jpg"">
Inside the photoswipe-ui-default.js file, you'll see a list of controls:
var _uiElements = [
{
name: 'caption',
option: 'captionEl',
onInit: function(el) {
_captionContainer = el;
}
},
{
name: 'myCustomButton',
option: 'customOptionName',
onTap:MyCustomButtonFunction
},
You must then add that button name to the options:
var options = {
history: false,
escKey: false,
closeOnScroll: false,
pinchToClose: false,
closeOnVerticalDrag: false,
customOptionName: true
};
Use :before to apply additional styles to the buttons, or modify the default UI JS file, so it registers click on image too.
By default, it registers tap only on the target element (in your case it's image), and does not propagate up in the DOM tree.
Figured out a way that doesn't involve altering the library. It's just a bit unfortunate the way the click handling is written, since you cannot use preventDefault or stopPropagation to cancel the handler.
// Disable hiding controls when tapping action buttons
pswp.framework.bind(pswp.scrollWrap, 'pswpTap', (e) => {
let el = e.target || e.srcElement;
while ((el = el.parentElement) && !el.classList.contains('action'));
if (el) {
pswp.options.tapToToggleControls = false;
setTimeout(() => {
pswp.options.tapToToggleControls = true;
}, 50);
}
});
I have a list of links that each open their own modal. Each of these modals contents display an html file. Here is a sample;
<div id="how-rtm-works" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h1 id="myModalLabel">How Right to Manage works</h1>
</div>
<div class="modal-body" id="utility_body">
<p>One fine body…this is getting replaced with content that comes from passed-in href</p>
</div>
<div class="modal-footer">
<button class="btn" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
<li><a data-target="#how-rtm-works" href="modal-content/how-RTM-works.html" role="button" data-toggle="modal">How Right to Manage works</a></li>
Because there is more than one modal, each has its own ID which is referenced in the data-target.
Can anyone advise me on how I would target these modals from another page, or in my case all pages as these will be linked in the website footer nav.
First page you'll use:
Open Modal
At the second page you'll insert your modal and the follow script:
<script type='text/javascript'>
(function() {
'use strict';
function remoteModal(idModal){
var vm = this;
vm.modal = $(idModal);
if( vm.modal.length == 0 ) {
return false;
}
if( window.location.hash == idModal ){
openModal();
}
var services = {
open: openModal,
close: closeModal
};
return services;
///////////////
// method to open modal
function openModal(){
vm.modal.modal('show');
}
// method to close modal
function closeModal(){
vm.modal.modal('hide');
}
}
Window.prototype.remoteModal = remoteModal;
})();
$(function(){
window.remoteModal('#myModalLabel');
});
</script>
Well your modals had IDs, I think you can trigger them by adding #how-rtm-works to the end of the link
for example if you have a modal called
id="My_Modal"
you can make a link
Link me to the modal
If that is your question I guess this can help you out !