My requirement is that I need to show a modal window as a form to be filled by user. But the height of that modal should be not more then window size.
So if the entries in form are too much then the modal becomes scrollable. The problem is that while validating the entries in the form the error message is shown at the top of the modal above the first entry. If user is at last property then he will not be knowing that some validation error had occurred unless the modal is scrolled to top on the error event.
I have tried :
$(window).scrollTop();
// and
$('#modalId').scrollTop();
this is the modal code:
<div class="modal hide" id="groupModal" tabindex="-1" role="dialog" aria-hidden="true" >
<div class="modal-header">
</div>
<div class="modal-body" style="max-height: 300px;">
<div class="grpForm">
<div class="alert alert-error hide">
<span class="errMsg"></span>
</div>
<div class="alert alert-success hide">
<span class="successMsg"></span>
</div>
<form class = "formFieldHolder" id="groupInfoForm"></form>
</div>
</div>
<div class="modal-footer">
<button class="btn cancelFormBtn" data-dismiss="modal" aria-hidden="true" msgkey="common.cancel.label"></button>
<button class="btn btn-primary submitGroupFormBtn" type="submit" msgkey="common.submit.label"></button>
</div>
</div>
$('#modalId').scrollTop(0);
scrollTop() only returns the value; scrollTop(0) sets the value to 0 (all the way to the top)
To scroll the page to the modal, select html, body and scroll to the offset top of the modal
$("html, body").scrollTop($("#modalId").offset().top);
If you want to scroll the modal div to the top use
$("#modalId").scrollTop(0);
Example on jsFiddle
You can combine both to scroll the page and the modal to a visible area for the user if needed.
References
jQuery scrollTop
jQuery offset
This is a solution without using JQuery, first you get your modal by the id and then, the function scrollIntoView will move to the top of the element you selected, in this case your modal.
let element = document.getElementById('groupModal');
element.scrollIntoView(true);
To avoid rough movement to the top I would prefer to use (animated movement):
$('#modalId').animate({
scrollTop : 0
}, 'slow');
<script type="text/javascript">
$(document).ready(function(){
$('.scroll_top').hide();
$(window).scroll(function(){
if ($(this).scrollTop() > 100) {
$('.scroll_top').fadeIn();
} else {
$('.scroll_top').fadeOut();
}
});
$('.scroll_top').click(function(){
$("html, body").animate({ scrollTop: 0 }, 500);
return false;
});
});
</script>
You have to include "jquery-1.7.1.min.js" file in your page.
http://code.jquery.com/jquery-1.7.1.min.js
Related
I'm hoping someone has done this before and has some guidance.
I'm using bootstrap on a site, and right now I have a working modal that loads in a set of pictures, currently 2. This works fine and I have them linked with anchor tags.
However, I'm trying to find the best way to take the selection of the image and once the user clicks it, apply it to the background image css for the container.
SO right now I just have a test image for the background, but basically I want the selection of an image from the modal to create a bgImg variable, so to speak, and apply it to the background of my container div in real time. So this should apply some javascript, but I don't really know what specifically to use. Or for that matter, how to create a variable from the selection and then apply it to CSS.
Basically if I select image 1 from the modal, the modal should close and image one's URL should now take the place of the CSS for the background image url, if that makes sense
CSS for the background in question:
.my-container>.middle {
flex-grow: 1;
padding:30px;
background-image: /*this would be the bgImg for the href*/;
background-size: cover;
}
HTML for the modal and the images that I want to apply to the background
Choose Page Background
<div class="modal fade" id="exampleModal" 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" id="exampleModalLabel">Choose an image:</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<img style="width: 200px; height: 200px;" src="images/bg_orange.svg">
<img style="width: 200px; height: 200px;" src="images/bg_green.svg">
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary">Save changes</button>
</div>
</div>
</div>
</div>
UPDATE:
adding JS
<script type="text/javascript">
const images = document.querySelectorAll('some-image-selector');
images.forEach(img => img.addEventListener('click', setBackground));
function setBackground(e) {
const container = document.querySelector('.my-container > .middle')
container.style.background = `url(${e.target.src}) center center no-repeat`
};
</script>
So to make this work, you'll want to add a click event listener to each image.
const images = document.querySelectorAll('some-image-selector')
images.forEach(img => img.addEventListener('click', setBackground))
something along those lines ^^
Then within setBackground, update the css
function setBackground(e) {
const container = document.querySelector('.my-container > .middle')
container.style.background = `url(${e.target.src}) center center no-repeat`
}
You'll have to do this with Javascript. In jQuery:
//prevent default action
$('.modal-body a').click(function(e) {
e.preventDefault();
});
$('.modal-body img').on('click', function(e){
//store the target url in a variable
let source = $(this).attr('src');
console.log(source);
//set the user-selected image to the proper spot on the page
$('.my-container > .middle').attr('src', source);
//now close the modal
closeModal();
});
function closeModal(){
$('#exampleModal').hide();
}
You can tweak how you want to close the modal by using a function like slideToggle() instead of hide().
I am playing around with Bootstrap modal and I want to change content of div when clicking a button. Here is the code :
html code of modal content
<div class="modal-content">
<div class="modal-body">
<div id="login-box" class="animated fadeIn">
Login form
<button id="show-register">Register</button>
</div>
<div id="register-box" class="animated fadeIn">
Register form
<button id="show-login">Login</button>
</div>
</div>
</div>
css styling
#register-box {
display: none;
}
javascript function to hide/show div
$(document).ready(function(){
loginRegisterSwitch();
});
function loginRegisterSwitch(){
var registerBtn = $("#show-register");
var loginBtn = $("#show-login");
var registerBox = $("register-box");
var loginBox = $("#login-box");
registerBtn.on('click',function(){
loginBox.hide();
registerBox.css('display','block');
});
loginBtn.on('click', function(){
registerBox.hide();
loginBox.css('display','block');
});
}
When user clicks register button, login-form div hides and register box shows.I can't get this code working(When user click register button , register div shows but login div does not hide). I would like to know if there is a better way to achieve this for example using jQuery html()
You're missing the # in the selector for the registerBox.
Change var registerBox = $("register-box"); to var registerBox = $("#register-box");
I've got a single page site with two div modules that expand when clicked.
The first is at the top, in the Hero section and with the current code works as desired. The second is much further down the page in another section. Currently this second module closes as soon as the scroll takes place.
What I need to do is get the documents scroll coordinates when the div is clicked. Then once the user scrolls 200px up or down the div closes back up. Regardless of where it (the div) is on the site.
All the questions I found here and elsewhere only refer to setting the scroll tolerance relative to the window position on page load. But for me that's no goon. This site is responsive, and as it changes the initial positions of the div's will / can be unknown. I need someway of dynamically storing the viewports scroll position when the div's are clicked and assigning the 200px tolerance then.
I hope that makes sense. I've been at this for like 12+hrs now. SOS :)
Here's the Fiddle
If you don't want to go over to Fiddle, Here's the requisite code
HTML:
<body>
<section id="hero">
<div>
<div class="module-cta hero-cta">
<a class="module-cta__button"><!-- Fallback location -->
<span class="module-cta__text">PRESS ME</span>
</a>
<div class="module-cta__open">
<div class="module-cta__open-inner">
<div class="hero-cta__contact-points">
<div class="phone">
<div class="hero-cta_contact_logo">
<span><!-- phone.svg" --></span>
</div><!-- .service-logo -->
<div class="contact_trigger">
<a>Scroll down to 200px to see</a>
</div><!-- .contact_trigger -->
</div><!-- .phone -->
<div class="email">
<div class="hero-cta_contact_logo">
<span><!-- email.svg --></span>
</div><!-- .service-logo -->
<div class="contact_trigger">
<a>this div fold back up</a>
</div><!-- .contact_trigger -->
</div><!-- .email -->
</div><!-- .hero-cta__contact-points -->
<button class="module-cta__close module-cta__cancel"><i class="icon"><span></span></i></button>
</div><!-- .hero-cta__open-inner -->
</div><!-- .hero-cta__open -->
</div><!-- .hero-cta -->
</div>
</section>
<section class="spacer"></section>
<section id="service_area">
<div class="area_input">
<div class="module-cta area-cta wow fadeInUp" id="form_module">
<a class="module-cta__button area-cta__button">
<span class="module-cta__text area-cta__text">NOW PRESS ME</span>
</a>
<div class="module-cta__open area-cta__open">
<div class="module-cta__open-inner area-cta__open-inner">
<div class="area-cta__search">
<form class="postcode_form" id="postcode_form" name="postcode_form" action="#">
<input type="number" id="your_postcode" class="your_postcode" name="postcode" placeholder="3???">
<button type="button" class="area-btn"><span></span></button>
<a class="call-now">##########</a>
</form>
</div><!-- .area-cta__search -->
<button class="module-cta__close module-cta__cancel"><i class="icon"><span></span></i></button>
</div><!-- .area-cta__open-inner -->
</div><!-- .area-cta__open -->
</div><!-- .area-cta -->
</div><!-- .area_input -->
</section>
<section class="spacer"></section>
</body>
Script:
I'm sure a lot of this can be cleaned up and shrunk, but for now I'm just trying to get it all going.
// opens & closes modules by clicking module name
$('.module-cta__button').on('click', function(){
if($(this).parent().hasClass('hero-cta')){
$(this).parent().toggleClass('module-cta--active');
} else {
if($(this).parent().hasClass('area-cta')){
$(this).parent().toggleClass('module-cta--active');
}
}
});
// closes modules with .module-cta__close btn
$('.module-cta__close').on('click', function(){
if($(this).closest('div .module-cta').hasClass('module-cta--active')){
$(this).closest('div .module-cta').removeClass('module-cta--active');
}
});
// closes modules on scroll.
// * works but doesn't apply scroll tolerance of 200px for #area
$(window).scroll(function(){
var currentPos = $(window).scrollTop();
var module = $('div .module-cta');
if(module.hasClass('module-cta--active') && module.position().top <= currentPos+200){
$('div .module-cta--active').removeClass('module-cta--active');
}
});
// closes modules when escape key is pressed
$(window).keydown(function(escape){
var key = escape.which;
if(key == 27){
$('div .module-cta--active').removeClass('module-cta--active');
}
});
see Fiddle for css
Thanks for any help or useful suggestions in advanced.
I've put together a much smaller and simpler demonstration, just to show you what variables you need to accomplish this. Essentially, when a div is clicked, capture the current document scroll position using $(document).scrollTop(). Also store a refference to the current div that has been clicked.
When scrolling, check the difference between the current scroll and the new scroll, and using your clicked div reference, shrink the div when the difference is 200 or greater. JS fiddle below;
https://jsfiddle.net/jLqu4pas/
Code from Fiddle;
var currentScroll;
var lastClickedDiv;
$('section').click(function(){
$(this).css({'height' : '400'})
currentScroll = $(document).scrollTop();
lastClickedDiv = $(this);
console.log(currentScroll);
})
$(window).scroll(function(){
if($(document).scrollTop() > currentScroll + 200){
lastClickedDiv.css({'height' : 0})
}
})
So I've put together a script that will potentially help you.
I've done some basic testing on it, but if you come across any problems make a comment.
// Generate offsets and return them as an object
function generateOffsets($element, tolerance)
{
var offsets = $element.offset(),
offsetTop = offsets.top;
return {
scrollPos: offsetTop,
toleranceTop: offsetTop - tolerance,
toleranceBottom: offsetTop + tolerance
};
}
// Run a callback when the user leaves the scroll tolerance of a set of elements
function closeOnScroll($elements, tolerance, callback)
{
$elements.each(function() {
var $element = $(this),
offsets = generateOffsets($element, tolerance),
resizeEvent;
// On resize, regenerate the offsets so they stay up to date
$(window).on('resize', function(e) {
resizeEvent = e;
offsets = generateOffsets($element, tolerance);
});
// On scroll check if we've left the tolerance area, if so run the event and unbind
$(window).on('scroll', function(e) {
var windowPos = $(this).scrollTop();
if (windowPos < offsets.toleranceTop || windowPos > offsets.toleranceBottom) {
callback($element);
$(this).unbind(e);
$(this).unbind(resizeEvent);
}
});
});
}
// Example: Apply the event to a set of elements
$('.btn').click(function() {
closeOnScroll($('div .module-cta'), 200, function($element) {
$element.removeClass('module-cta--active');
});
});
The thing to remember with thie script is that it needs to be applied EVERY time the user clicks your button. You may say, WHY WOULD YOU DO THAT - but it actually has some serious performance implications.
The events rely on both scroll and resize, both of which are very slow, especially if not debounced like in this script. However, what I do in the script is unbind the events once it has occured. Otherwise, the resize and scroll would keep happening for each and every one of your buttons until the end of time. By 'unbinding' the event, you ensure long running performance of your page.
Wouldn't want to ruin those pretty animations would we?
I want to force the user to read all the agreement inside the modal. The idea is simple, if they don't scroll to the last line of the text. The button still disable. But the button is not enable. This is my code:
Javascript:
$('#agreement').scroll(function () {
if ($(this).scrollTop() == $(this)[0].scrollHeight - $(this).height()) {
$('#closeBtn').removeAttr('disabled');
}
});
As for the clearer picture. I put the code in js here : http://jsfiddle.net/h3WDq/1129/
This is an update version from #BG101. The button enable when I scroll to the bottom but it keeps enable even the modal button is click again. http://jsfiddle.net/h3WDq/1132/
your modal-body need the scroll event, and you need a small change to the if:-
$('.modal-body').scroll(function () {
if ($('#agreement').height() == ($(this).scrollTop() + $(this).height())) {
$('#closeBtn').removeAttr('disabled');
}
});
working snippet below (updated to toggle on/off)
$('.modal-body').scroll(function() {
var disable = $('#agreement').height() != ($(this).scrollTop() + $(this).height());
$('#closeBtn').prop('disabled', disable);
});
.btn-group {
z-index: 1051;
}
.modal-body {
height: 300px;
overflow: auto
}
<link href="http://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/2.3.1/css/bootstrap.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/2.3.1/js/bootstrap.min.js"></script>
<div class="container">
<h3>User Agreement</h3>
<!-- Button to trigger modal -->
<div>
Launch Modal
</div>
<!-- Modal -->
<div id="myModal1" class="modal hide" tabindex="-1" role="dialog">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h3>User Agreement</h3>
</div>
<div class="modal-body">
<div id="agreement" style="height:1000px;">
A very long agreement
</div>
</div>
<div class="modal-footer">
<button id="closeBtn" class="btn btn-primary" data-dismiss="modal" aria-hidden="true" disabled>I Accept</button>
</div>
</div>
</div>
#terms-page - is the ID of the particular div
You can try the following:
$("#terms-page").scroll(function () {
var ele = document.getElementById('terms-page');
if (ele.scrollHeight - ele.scrollTop === ele.clientHeight)
{
$('#closeBtn').removeAttr('disabled');
}
});
Why not put a hidden element at the bottom of the agreement and detect when the offset of that element is scrolled to the top?
$('#agreement').scroll(function () {
var target = $("#target").offset().top;
if ($(this).scrollTop() >= target) {
$('#closeBtn').removeAttr('disabled');
}
});
Remove Height from div and paste the below code and it will work super
$('.modal-body').scroll(function() {
var height = $('#agreement').height();
console.log(height);
var scroll = $(this).scrollTop() + $(this).height();
console.log(scroll);
if (height>scroll) {
$('#closeBtn').prop('disabled', true);
} else {
$('#closeBtn').prop('disabled', false);
}
});
I'm currently using the bootstrap modal plugin to display long legal messages on a website I'm designing, but the problem is that if you open one modal after the other, the second one will already be scrolled to whatever position the first one was. So I'm looking for a way to scroll a div to the top with JS/JQuery. This is the code I'm using currently:
HTML:
<!--MODAL-->
<div id="modal" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="modalTitle" aria-hidden="true">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h3 id="modalTitle"></h3>
</div>
<div id="modal-content" class="modal-body">
</div>
<div class="modal-footer">
<button id="modalPrint" class="btn btn-info hidden-phone" onClick=''>Print</button>
<button class="btn" data-dismiss="modal" aria-hidden="true">Close</button>
</div>
</div>
Javascript:
function openModal(heading, url) {
$.ajax({
url: url,
cache: false
}).done(function( html ) {
$("#modal-content").html(html);
$("#modalTitle").html(heading);
$('#modalPrint').attr('onClick', 'loadPrintDocument(printCookies, {attr : "href", url : '+ url +', showMessage: false, message: "Please wait while we create your document"})');
$('#modal').modal('show');
$("#modal-content").scrollTop(0);
});
}
As you can see, I've tried scrolling to the top after the modal has been shown. Any ideas?
Now with bootstrap 3 the events has change an can be achieved like this (plus a smooth animation to the top)
$('#modal').on('shown.bs.modal', function () {
$('#modal').animate({ scrollTop: 0 }, 'slow');
});
Okay I've answered my own question. For anyone else with this issue, simply add this function to your JS!
$('#modal').on('shown', function () {
$("#modal-content").scrollTop(0);
});
I will leave this question up, as there isn't one similar (that I could find) and it may help someone
On Bootstrap 4 (v4.0.0-alpha.6) the following worked well for me:
$('#Modal').show().scrollTop(0);
Please note as of bootstrap-4.0.0-beta.1 and Firefox 56.0.1 this does not seem to work correctly;
I checked IE11, MS Edge and Chrome and this works fine.
In Bootstrap 4, the following works for me:
$('.modal-body').scrollTop(0);
You need to scrollTop on the modal-body because the parent elements (modal, modal-dialog, modal-content) are containers and do not scroll with the user.
However, if you prefer a less jerky movement, try the animation route:
$('.modal-body').animate({scrollTop: 0},400);
Scroll up button has a class of: .page-scroll
Modal with a class of: .modal
JS to make scroll happen with the modal (JS could be simplified):
$('body').on('click', '.page-scroll', function(event) {
var $anchor = $(this);
$('html, body, .modal').stop().animate({
scrollTop: $($anchor.attr('href')).offset().top
}, 1500, 'easeInOutExpo');
event.preventDefault();
});
There was change in boostrap where you need to use: on shown.bs.modal
Call a function when you show the modal window (I opted for this method)
<button onclick="showSMSSummary(); return false;"
data-toggle="tooltip" title="Click To View Summary"
class="btn btn-primary btn-sm">SMS Summary</button>
function showSMSSummary()
{
$('#HelpScreenModalContent').modal('show');
$('#HelpScreenModal').animate({ scrollTop: 0 }, 'fast');
}
ScrollTop bootbox modal on fadeIn The answer is in this issue.
When setting up bootbox dialog add .off("shown.bs.modal");this at the end.
bootbox.dialog({ ... }).off("shown.bs.modal");
It will scroll be at top when open dialog.