How to append modal dialog to div? - javascript

I've designed a modal dialog that opens on the click of a button, here is the javascript and html for it;
JAVASCRIPT
var ModalEffects = (function() {
function init() {
var overlay = document.querySelector( '.md-overlay' );
[].slice.call( document.querySelectorAll( '.md-trigger' ) ).forEach( function( el, i ) {
var modal = document.querySelector( '#' + el.getAttribute( 'data-modal' ) ),
close = modal.querySelector( '.md-close' );
function removeModal( hasPerspective ) {
classie.remove( modal, 'md-show' );
if( hasPerspective ) {
classie.remove( document.documentElement, 'md-perspective' );
}
}
function removeModalHandler() {
removeModal( classie.has( el, 'md-setperspective' ) );
}
el.addEventListener( 'click', function( ev ) {
classie.add( modal, 'md-show' );
overlay.removeEventListener( 'click', removeModalHandler );
overlay.addEventListener( 'click', removeModalHandler );
if( classie.has( el, 'md-setperspective' ) ) {
setTimeout( function() {
classie.add( document.documentElement, 'md-perspective' );
}, 25 );
}
});
close.addEventListener( 'click', function( ev ) {
ev.stopPropagation();
removeModalHandler();
});
} );
}
init();
})();
HTML
<div class="md-modal md-effect-16" id="modal-16">
<div class="md-content">
<h3>Remember Rules</h3>
<div>
<p>There are certain rules you must obey, if you don't your account will be banned:</p>
<ul>
<li><strong>Swearing:</strong> cursing or any other form of cursing is not allowed.</li>
<li><strong>Hacking:</strong> trying to hack any component of the application is a t.o.u violation.</li>
<li><strong>Heckling:</strong> constantly calling a moderator will kick you off the server.</li>
</ul>
<button class="md-close">Close me!</button>
</div>
</div>
</div>
<div id="interface">
<textarea name="para" placeholder="type your paragraph here"></textarea>
</div>
<center><button class="md-trigger" data-modal="modal-16">Blur</button></center>
For some reason I can't get it to append to the "interface" div, I've used the appendTo jquery which failed me, the interface div is 600x200, currently atm the modal dialog which has an overlay behind it, covers the entire body and I'd like it to specifically cover the interface div.
The CSS is very basic, a green dialog box with some text on it and an overlay behind it.

Here is a FIDDLE that at least partially addresses your question.
If you attach a .dialog to an element it tends to "become" or "coverup" that element.
So in the fiddle above, I've attached the .dialog to a smaller div that is not displayed within the larger div, and opened the dialog with a click on the larger div.
If you look at the jQuery documentation for .dialog, you'll see that the purpose of the modal is to block out every potential interaction on the page, forcing the user to interact with the modal only. So when you use the modal, the entire page/body/window with be grayed-out.
I suppose you could write your own modal and just gray-out the large div.
Do you really need to just gray-out the div?
edit: or you could add appendTo: '.bigdiv'
JS
var $dialogpopup = $( ".littlediv" ).dialog({
autoOpen: false,
width: 150,
height: 150,
modal: true,
position: {
my:'top center',
at: 'top center',
of: '.bigdiv'
}
});
$('.bigdiv').on('click', function(){
$dialogpopup.dialog('open');
});

Related

Resize function events fire 2 times more each time the window was resized

On my site, I am trying to fix the navigation so that when the browser is getting resized from desktop to mobile size, the mobile menu works. I have the mobile menu working on initial load, and the desktop navigation working on initial load, but when I run the script in a $(window).on('resize', function() {} and click an item as depicted in my script, the event fires always +1 each time the window was rested after a resize.
What I mean is, if I load the page, scale it into mobile size, click the menu and a dropdown item, the click event will fire once. Resize the window out and then back in, the click event will fire now 2 times, then 3, and so on, depending on how many times the browser was resized.
I'm not sure exactly what is going on in my resize script that is screwing everything up and I'm at my wits end at trying to figure it out. Normally people aren't sitting there resizing their browser from desktop to mobile, but my boss does when he show's clients a beta of their site and wants this to never be an issue.
Here is my resize script:
(function( $ ) {
var id,
$body = $('body'),
$window = $( window ),
$navSlider = $('.nav-slider'),
$navMask = $( '.nav-mask' ),
$navToggler = $( '.navbar-toggler' ),
$parent = $( '.menu-item-has-children' ),
$parentLink = $( '.dropdown-toggle' ),
$childContainer = $( '.dropdown-menu' );
$window.on( 'resize', function( e ) {
clearTimeout(id);
id = setTimeout(function() {
close();
var width = $window.width();
if ( width < 992 ) {
setHeightToNav();
$navMask.on( 'click', function() { close() } );
$navToggler.on( 'click', function() { open() } );
$parentLink.on( 'click', function( e ) {
e.preventDefault();
var $this = $( this );
$this.data( 'clicked', true );
console.log( $this.parent() );
} )
}
if ( width >= 992 ) {
resetNavHeight();
console.clear();
}
}, 500 );
} );
function setHeightToNav() {
if ( $body.hasClass( 'logged-in' ) ) {
var $wpAdminBar = $( '#wpadminbar' ).outerHeight();
$navSlider.css( { top: $wpAdminBar + 'px' } );
}
var $navHeight = $( '#header-container' ).outerHeight();
$navSlider.css( { marginTop: $navHeight + 'px' } );
}
function resetNavHeight() {
if ( $body.hasClass( 'logged-in' ) ) {
$navSlider.css( { top: 0 + 'px' } );
}
$navSlider.css( { marginTop: 0 + 'px' } );
}
function close() {
$body.removeClass( 'has-active-menu' );
setTimeout( function() {
$navSlider.removeClass( 'toggling' );
$parent.removeClass( 'show' );
$parentLink.attr( 'aria-expanded', false );
$childContainer.removeClass( 'show' ).removeAttr( 'style' );
$parentLink.data('clicked', false);
}, 250 );
console.log('close()');
}
function open() {
$body.addClass( 'has-active-menu' );
$navSlider.addClass( 'toggling' );
}
})( jQuery );
I've tried my script both with AND without the setTimeout function and it happens exactly the same.
On the project, we are using Bootstrap 4, with the Bootstraps Dropdown._clearMenus(); function commented out in the right places as it was causing conflicts with the functionality I wanted with the navigation.
A link to a site where you can see this is here. It's a WordPress site as well if that matters for anything.
Any help is appreciated. I've been at this for several hours and am at my wits end.
.on( 'click', function ) does not set the event listener, it adds an event listener. Try doing off('click') before setting it if you really need to set this listener here.
But note that any other 'click' listener for this element will also be removed.
That's for the quick fix. You could do better, but that would require more work (track with a boolean if you just changed "display mode", and add or remove the event listeners only then, for example).

JS Infinite Scroll

I use this https://infinite-scroll.com
For normal scrolling through pages it works great out of the box.
I have a problem though, I have a regular navigation at the top of my page. What I would like to accomplish is this:
Visitor enters site. page-1 is loaded
Visitor clicks Page-3 in my navigation, I would like page-2 to load and then page-3 and automatically scroll down to page-3
each page starts with a div with and ID e.g.
function checkAnchor( anchor ) {
if ( $( anchor ).length ) {
return true;
} else {
$( '.article-feed' ).infiniteScroll( 'loadNextPage' );
checkAnchor( anchor );
}
}
$( document ).on( 'click', 'a[href^="#"]', function ( event ) {
event.preventDefault();
anchor = $.attr( this, 'href' );
while ( checkAnchor( anchor ) == false ) {
$( '.article-feed' ).infiniteScroll( 'loadNextPage' );
}
$( 'html, body' ).animate( {
scrollTop: $( $.attr( this, 'href' ) ).offset().top
}, 700 );
} );
I have tried many different things to accomplish this but I cant seem to get it to work. The next page loads but i have to click to link until page-3 is finally loaded. Any help is welcome
function checkAnchor( anchor ) {
if ( $( anchor ).length ) {
return true;
} else {
setInterval( function () {
$( '.article-feed' ).infiniteScroll( 'loadNextPage' );
var lastAnchor = "#" + $( ".anchor" ).last().attr( 'id' );
if ( anchor == lastAnchor ) {
$( 'html, body' ).animate( {
scrollTop: $( anchor ).offset().top
}, 500 );
return true;
}
}, 100 );
}
}
This kind of did the trick but I feel like I am hacking my way through this

How to display a new modal window hiding the previous one?

Using tympanus.net modals (with greats animations) is easy to delete the backdrop div (<div class="md-overlay"></div>)letting me interact with menu items behind my modal but I don't know how to display just one modal at time as when I open a new one the previous still there and the new appear over it.
Everything is controlled from a class .md-show which is applied to the called modal.
I think what I need to do is delete all .md-show class applied before opening a new one with this same class. Maybe with a script?
UPDATE:
This is the script: Copyright 2013, Codrops //sorry, I can't place comments! They doesn't works!
var ModalEffects = (function() {
function init() {
var overlay = document.querySelector( '.md-overlay' );
[].slice.call( document.querySelectorAll( '.md-trigger' ) ).forEach( function( el, i ) {
var modal = document.querySelector( '#' + el.getAttribute( 'data-modal' ) ),
close = modal.querySelector( '.md-close' );
function removeModal( hasPerspective ) {
classie.remove( modal, 'md-show' );
if( hasPerspective ) {
classie.remove( document.documentElement, 'md-perspective' );
}
}
function removeModalHandler() {
removeModal( classie.has( el, 'md-setperspective' ) );
}
el.addEventListener( 'click', function( ev ) {
classie.add( modal, 'md-show' );
overlay.removeEventListener( 'click', removeModalHandler );
overlay.addEventListener( 'click', removeModalHandler );
if( classie.has( el, 'md-setperspective' ) ) {
setTimeout( function() {
classie.add( document.documentElement, 'md-perspective' );
}, 25 );
}
});
close.addEventListener( 'click', function( ev ) {
ev.stopPropagation();
removeModalHandler();
});
} );
}
init();
})();
I Think I need to remove .md-show here, before opening the new modal:
el.addEventListener( 'click', function( ev ) {
classie.add( modal, 'md-show' );
overlay.removeEventListener( 'click', removeModalHandler );
overlay.addEventListener( 'click', removeModalHandler );
if( classie.has( el, 'md-setperspective' ) ) {
setTimeout( function() {
classie.add( document.documentElement, 'md-perspective' );
}, 25 );
}
});
I made some tries without any success so some help will be appreciate! :) tympanus referring article
Found a funny solution using mousedown and mouseup events!
mousedown will delete all md-show classes
mouseup will add md-show
Easy but it took me 4 days to reach that without any knowledge on scripts!
FULL RIGHT CODE!
var ModalEffects = (function() {
function init() {
var overlay = document.querySelector( '.md-overlay' );
[].slice.call( document.querySelectorAll( '.md-trigger' ) ).forEach( function( el, i ) {
var modal = document.querySelector( '#' + el.getAttribute( 'data-modal' ) ),
close = modal.querySelector( '.md-close' );
function removeModal( hasPerspective ) {
classie.remove( modal, 'md-show' );
if( hasPerspective ) {
classie.remove( document.documentElement, 'md-perspective' );
}
}
function removeModalHandler() {
removeModal( classie.has( el, 'md-setperspective' ) );
}
el.addEventListener( 'mouseup', function( ev ) {
classie.add( modal, 'md-show' );
overlay.removeEventListener( 'click', removeModalHandler );
overlay.addEventListener( 'click', removeModalHandler );
if( classie.has( el, 'md-setperspective' ) ) {
setTimeout( function() {
classie.add( document.documentElement, 'md-perspective' );
}, 25 );
}
});
document.addEventListener( 'mousedown', function( ev ) {
if (classie.has(ev.target, "md-close")) {
ev.stopPropagation();
removeModalHandler();
}
});
} );
}
init();
})();
Please note that you need to add md-close class to md-trigger links!

Multiple "close" buttons on modal

I am using the modals found here on Codrops.
These modals have one close button (also closes when you click outside the modal), but I want to add more. The JavaScript is below:
var ModalEffects = (function() {
function init() {
var overlay = document.querySelector( '.md-overlay' );
[].slice.call( document.querySelectorAll( '.md-trigger' ) ).forEach( function( el, i ) {
var modal = document.querySelector( '#' + el.getAttribute( 'data-modal' ) ),
close = modal.querySelector( '.md-close' );
function removeModal( hasPerspective ) {
classie.remove( modal, 'md-show' );
if( hasPerspective ) {
classie.remove( document.documentElement, 'md-perspective' );
}
}
function removeModalHandler() {
removeModal( classie.has( el, 'md-setperspective' ) );
}
el.addEventListener( 'click', function( ev ) {
classie.add( modal, 'md-show' );
overlay.removeEventListener( 'click', removeModalHandler );
overlay.addEventListener( 'click', removeModalHandler );
if( classie.has( el, 'md-setperspective' ) ) {
setTimeout( function() {
classie.add( document.documentElement, 'md-perspective' );
}, 25 );
}
});
close.addEventListener( 'click', function( ev ) {
ev.stopPropagation();
removeModalHandler();
});
} );
}
init();
})();
I thought by just simply swapping:
close = modal.querySelector( '.md-close' );
With this:
close = modal.querySelectorAll( '.md-close' );
would do the trick -- and every element with the md-close class would close the modal. I was wrong (I'm new to JavaScript if you couldn't tell).
Thanks in advance for any help with this!
Updated Code:
var ModalEffects = (function() {
function init() {
var overlay = document.querySelector( '.md-overlay' );
[].slice.call( document.querySelectorAll( '.md-trigger' ) ).forEach( function( el, i ) {
var modal = document.querySelector( '#' + el.getAttribute( 'data-modal' ) );
function removeModal( hasPerspective ) {
classie.remove( modal, 'md-show' );
if( hasPerspective ) {
classie.remove( document.documentElement, 'md-perspective' );
}
}
function removeModalHandler() {
removeModal( classie.has( el, 'md-setperspective' ) );
}
el.addEventListener( 'click', function( ev ) {
classie.add( modal, 'md-show' );
overlay.removeEventListener( 'click', removeModalHandler );
overlay.addEventListener( 'click', removeModalHandler );
if( classie.has( el, 'md-setperspective' ) ) {
setTimeout( function() {
classie.add( document.documentElement, 'md-perspective' );
}, 25 );
}
});
modal.addEventListener( 'click', function( ev ) {
if (classie.has(ev.target, "md-close")) {
ev.stopPropagation();
removeModalHandler();
}
});
} );
}
init();
})();
The problem is likely that addEventListener only works on a single element at a time and close is a collection of elements. You're probably better off adding an event listener to the modal itself and checking for the md-close class:
modal.addEventListener('click', function (ev) {
if (classie.has(ev.target, "md-close")) {
ev.stopPropagation();
removeModalHandler();
}
});
Then you can ditch your close = ... variable as well.
Change
close.addEventListener( 'click', function( ev ) {
ev.stopPropagation();
removeModalHandler();
});
Into
document.addEventListener( 'click', function( ev ) {
if (classie.has(ev.target, "md-close")) {
ev.stopPropagation();
removeModalHandler();
}
});
And it will works!
NOW... I thought applying this hack solved also my problem as I wanted to add .md-close on my .md-trigger link to close a modal and open a new one but it didn't work! Someone could help me on this?
How to display a new modal window hiding the previous one?
Thanks!

closing a jquery-ui dialog one at a time

I'm having an issue with multiple jQuery UI dialogs. What I want is that I can have multiple dialogs, and a click on a button with the class ".close-modal" will only close the dialog in which that button was located. Now, first for a little background: I have a simple function in the "main" parent of the site, which will open a modal dialog by clicking on a link with the class ".modal";
In the parent
function modal( href, title ) {
var $dialog = $('<div></div>');
$dialog.html('<iframe class="modal" name="' + title + '" style="border: 0px;" src="' + href + '" width="100%" height="100%"></iframe>');
$dialog.dialog({
autoOpen: false,
modal: true,
height: 650,
width: 950,
title: title
});
$dialog.dialog( 'open' );
$(document).bind( 'close-dialog', function( ) {
$dialog.dialog( 'close' );
});
}
$('a.modal').click( function( event ) {
event.preventDefault( );
modal( $(this).attr( 'href' ), $(this).attr( 'title' ) );
}
This code works the way I want it to. To open a dialog from a dialog, I call the parent window's modal function with the correct parameters, so that multiple dialogs can be displayed within the parent:
In the dialog
( function( $ ) {
$(document).ready( function( ) {
$('a.modal').click( function( event ) {
event.preventDefault( );
parent.modal( $(this).attr( 'href' ), $(this).attr( 'title' ) );
}
/** Trigger the close-dialog event on the parent to close the current dialog. */
$('.close-dialog').click( function( ) {
parent.jQuery( parent.document ).trigger( 'close-dialog' );
});
});
})( jQuery );
So, in essence; I've defined an event on the parent window ("close-dialog"), which can be called by the code within the iframe which will call $dialog.dialog( 'close' ); This works brilliantly; I can create multiple dialogs, even from within dialogs, but the issue is that once I click a button.close-dialog, it closes all of my dialogs.
Is there any way to determine from which dialog the event was called? Or bind the event to the current dialog?
You could use jquery modal's buttons option.
<script>
$(function() {
$( ".myModals" ).dialog({
modal: true,
buttons: {
Close: function() {
$( this ).dialog( "close" );
}
}
});
});
</script>
This should do it for all your modals in one go, and the buttons it creates only apply to themselves. Hope that helps!

Categories