jQuery Modal Plugin by Eric Martin

Published by on
Tags:

I was working on a project that required a modal popup up box. After looking at a few different jQuery pluyins I decided to use Simple Modal by Eric Martin. I wanted to use this one because it was the simplest to implement.

The popup itself had to contain an ASP.NET text box and a button, the user would fill out the text box and then click the button and the value would be saved. As with most standard ASP .NET  sites I had to have a form that wraps the majority of the page, I am not a fan of this but sometimes there is no way around this, it also wrapped the my textbox and button but  was outside of the modal container.

Once the page was setup I tried the tool but whenever I clicked the button nothing was saved to the DB. It turns out that the Simple Modal plugin appends the modal container to the end of the body tag, this cause the textbox to be moved outside of the form. Any data entered is therefore not submitted back to the server.

To solve this I downloaded the non-compressed version of the code from http://code.google.com/p/simplemodal/downloads/list. Then located the lines that create the modal container. You are looking for the create function:

		
create: function () {			  
			// get the window properties
			
			w = this.getDimensions();

			// add an iframe to prevent select options from bleeding through
			if (ie6) {
			    
				this.dialog.iframe = $('<iframe src="javascript:false;"></iframe>')
					.css($.extend(this.opts.iframeCss, {
						display: 'none',
						opacity: 0, 
						position: 'fixed',
						height: w[0],
						width: w[1],
						zIndex: this.opts.zIndex,
						top: 0,
						left: 0
					}))
					.appendTo('body');
			}

			// create the overlay
			this.dialog.overlay = $('<div>&nbsp;</div>')
				.attr('id', this.opts.overlayId)
				.addClass('simplemodal-overlay')
				.css($.extend(this.opts.overlayCss, {
					display: 'none',
					opacity: this.opts.opacity / 100,
					height: w[0],
					width: w[1],
					position: 'fixed',
					left: 0,
					top: 0,
					zIndex: this.opts.zIndex + 1
				}))
				.appendTo('body');

			// create the container
			this.dialog.container = $('<div>&nbsp;</div>')
				.attr('id', this.opts.containerId)
				.addClass('simplemodal-container')
				.css($.extend(this.opts.containerCss, {
					display: 'none',
					position: 'fixed', 
					zIndex: this.opts.zIndex + 2
				}))
				.append(this.opts.close 
					? $(this.opts.closeHTML).addClass(this.opts.closeClass)
					: '')
				.appendTo('body');

			this.setPosition();

			// fix issues with IE
			if (ie6 || ieQuirks) {
				this.fixIE();
			}

			// hide the data and add it to the container
			this.dialog.container.append(this.dialog.data.hide());
		},

To solve this problem the modal container needs to be append to the parent of the target container. To do this add the following line at the start of the create function:

var parent  = $(this.dialog.parentNode);

Now replace all the:

 

.appendTo('body');

with:

.appendTo(parent);

This ensures that the modal container is created beneath the form element in the page.

My first jQuery plug-in - Element Expander

Published by on
Tags:

I wanted to have a go at writing a jQuery plug-in. I also wanted to shrink the screen space that some of my blogs took up. So I wanted plug-in that allowed me to shrink a blog entry with a link at the bottom to expand the blog to see the full article.

To download the plug-in click ExperimentsInCode.jQuery.ExpandableElement.js (3.45 kb)

The result was a tool that allowed me to shrink any element to a set size that can then can be expanded, for example:

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam ipsum elit, elementum at, luctus a, scelerisque et, leo. Phasellus purus velit, dictum eget, aliquam in, varius nec, dui. Vestibulum gravida tempus velit. Nullam elementum consectetur nisi. Nulla dapibus, nunc sit amet semper feugiat, leo tortor commodo elit, sit amet congue est ipsum at augue. Quisque in tellus. Nam tellus diam, tincidunt eu, pellentesque at, ultrices et, urna. Donec pretium tempus nunc. Etiam ligula urna, eleifend quis, gravida eu, dictum ut, purus. Phasellus et nibh id arcu vestibulum scelerisque. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Nullam hendrerit facilisis dui. Aenean odio pede, bibendum eu, interdum nec, vehicula sed, nibh. Cras a orci vitae mi consequat elementum. Fusce porta pede et sapien. Maecenas interdum posuere libero. Quisque risus purus, gravida quis, tempus quis, tempus ac, nunc. Maecenas posuere congue quam. Phasellus varius.

The code to get this to work is pretty simple:

$j('#expanderExample1').expandable({
length:50
});

The plugin allows the following parameters to be passed:

Name Description Default
length The length/height that the element should be. Elements that are 110% bigger than this length will be shrunk. For example if I have two elements, element A has a height of 500px and element B has a height of 180px. If I set the length to 200px then element A will be shrunk but element B will not. The system adds 10% to the length value when deciding if it should shrink and element, so for example an element of 210px high would not be shrunk despite being large than 200px. 300px
moreText The link text displayed to expand the element more
lessText The link displayed to shrink the element less
animateOver This is the animation to play when the user hovers over the expandable element. The animation is applied to the link text. The animation is included to draw the user to the link. The default will double the size of the link text. The function that is called must accept a single parameter, this is the link object.
		    function(obj) {
			    $(obj).animate({
			        fontSize: "2em"
			    });
			}
			
animateOff This animation is played when the user moves their mouse off an area that can be expanded. The default is to shrink the text back to it's original size. The function that is called must accept a single parameter, this is the link object.
            function(obj) {
			    $(obj).animate({
			        fontSize: "1em"
			    });
			}
			


To change the default animation we just need to pass in the animationOn and animationOff functions:

In facilisis turpis. Pellentesque eget elit id turpis consequat luctus. Phasellus nibh. Sed eu libero a tellus luctus adipiscing. Ut vel urna. Duis ipsum massa, suscipit vitae, vulputate sed, bibendum in, elit. Donec in pede ut velit ultricies faucibus. Fusce vel nunc eget urna semper sodales. Nullam at risus in urna dictum eleifend. Sed nec nisi. Maecenas vitae erat. Donec non sapien. In accumsan cursus libero. Nulla facilisi. Fusce nisi eros, feugiat at, tristique ac, mattis eu, libero. Maecenas sem mi, ultricies eu, cursus ac, egestas quis, erat. In sed nisl. Vestibulum eleifend ornare metus. Etiam faucibus pulvinar lectus.

The code to get this animation to work is:

$j(function(){
    $j('#expanderExample2').expandable({
        length: 50,
        animateOver: function(obj) {
            $j('#expanderExample2 ~ div > .expandable_link').css("position", "relative");                
            obj.animate({
                "fontSize": "2em",
                "left": "+=50px"
            });
        },
        animateOff: function(obj) {                
            obj.animate({
                "fontSize": "1em",
                "left": "10px"
            });
        }
    });
});

The most important line is:

 $j('#expanderExample2 ~ div > .expandable_link').css("position", "relative");  

This needs to be added before the animation is played so that the move left command will work. If you don't set the position value the text stays where it is. I have to select a sibling and then the link because the expander code creates a container item around the element that needs to be expanded and then adds a link as a child of the new container. This diagram shows you how the elements end up:

    Container
        |-> Your Element
        |-> More Link Container
            |-> More Link

There are still some bits that I am not happy with. In particular having to pass a parameter into the animateOver and animateOff functions. I would prefer to use $(this) within the function but I can't work out how to make it work. I am calling the animations with the following:

        $(link).stop();
        $(link).each(options.animateOver($(link)));
    

It would be nice to do something like:

        $(link).stop();
        $(link).each(options.animateOver());
    

The function would then assume that $(this) would be the link object.

One important part of the code which I had to work on when I started to write the post was the effect of nested expandable elements. Nesting caused the whole thing to fall over, so I added the following code to ensure on the correct link was selected. This to me doesn't seem like the best solution but it works:

        //this ensures that nested expanders don't clash
        var linkAry = $(".expandable_link", newContainer);
        var link = null;
        for (var i = 0; i < linkAry.length; i++) {
            if ($($($(linkAry[i]).parent().get(0)).parent().get(0)).html() == $(newContainer).html()) {
                link = $(linkAry[i]);
            }
        }
    

I have plans to expand on this basic functionality; maybe make it so that you can expand both the width and height.Sometimes it also produces excess white space but that is for later, for now I should go and have breakfast.


 

All blogs tagged with 'jquery'

Projects

Have you read?

Useful Links



Blogs by date