PDA

View Full Version : Resolved Better way to program this - Animate width/height



keyboard
11-21-2012, 08:48 AM
I've got a basic jquery version of one of the old ddscripts, and it works fine, but one of the bits of code is driving me crazy...
I don't want to write all the same code (most of it's the same) twice... is there a way to avoid this without making tonnes of variables to store all the data that changes between the if statements?

js file


$.fn.time_based_progress_bar = function(user_options) {
var default_options = {
duration : 1000,
color : 'blue',
direction : 'horizontal',
complete : function() {
//alert("Complete");
}
};
var args = default_options;
if(typeof user_options === 'object') {
args = $.extend(default_options,user_options);
}
if(default_options.direction == 'vertical') {
$(this).css('position', 'relative');
$(this).html('<div style="height:0%;width:100%;background-color:' + default_options.color + ';position:absolute;bottom:0;left:0;"></div>');
$(this).children().animate({
height : '100%'
}, default_options.duration, default_options.complete);
} else {
$(this).html('<div style="height:100%;width:0%;background-color:' + default_options.color + ';"></div>');
$(this).children().animate({
width : '100%'
}, default_options.duration, default_options.complete);
}
};


html


<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.9.1/jquery-ui.min.js"></script>
<script type="text/javascript" src="time_based.js"></script>
<script type="text/javascript">
$(function() {
$('#time').time_based_progress_bar({
duration : 5000,
color : 'green',
direction : 'vertical',
complete : function() {
alert("Finished.");
}
});
});
</script>
</head>
<body>
<div id="time" style="border:1px solid black;background-color:white;height:20px;"></div>
</body>
</html>


p.s. Is it just me or is the bbcode color button missing?

jscheuer1
11-21-2012, 02:29 PM
I did add one variable ($bar), which seemed prudent. You don't need the UI because you're not using anything from it. The animation function can take an options object and doesn't seem to mind the extra/unrecognized options in your existing object. So you don't have to parse it each time. I added an easing option. If you want more than 'linear' or 'swing' as easing choices, then you would need the UI or at least an extended easing function. The latter exist or you could lift it from an uncompressed version of the UI. The this keyword in a jQuery fn function is already a jQuery object. Chaining can be utilized more. An if statement that has only one action can be done more succinctly as an && statement. An fn function should return the jQuery object it was run on, The appendTo() function is safer than the .html() one. If you want to make sure the parent is empty, you can use the empty() function on it, but since it is empty, I didn't bother. Using the css() function is often more succinct than creating an element as a string with a style attribute in it:


$.fn.time_based_progress_bar = function(user_options) {
var default_options = {
duration : 1000,
color : 'blue',
direction : 'horizontal',
easing: 'swing',
complete : function() {
//alert("Complete");
}
}, $bar = $('<div />');
typeof user_options === 'object' && $.extend(default_options, user_options);
$bar.css({backgroundColor: default_options.color});
if(default_options.direction == 'vertical') {
$bar.css({height: 0, width: '100%', position: 'absolute', bottom: 0, left: 0})
.appendTo(this.css('position', 'relative')).animate({height : '100%'}, default_options);
} else {
$bar.css({height: '100%', width: 0}).appendTo(this).animate({width : '100%'}, default_options);
}
return this;
};


<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script type="text/javascript" src="time_based.js"></script>
<script type="text/javascript">
$(function() {
$('#time').time_based_progress_bar({
duration : 5000,
color : 'green',
direction : 'vertical',
easing: 'linear', // 'linear' or 'swing' defaults to 'swing'
complete : function() {
alert("Finished.");
}
});
});
</script>
</head>
<body>
<div id="time" style="border:1px solid black;background-color:white;height:20px;"></div>
</body>
</html>

BTW - The color option in the editor is there for me. It's a button designated by a capital A. It has no effect if used within HTML or any other bbcode code block other than
.

An even more concise way of doing the javascript:

[CODE]$.fn.time_based_progress_bar = function(user_options) {
var default_options = {
duration : 1000,
color : 'blue',
direction : 'horizontal',
easing: 'swing',
complete : function() { /* alert("Complete"); */ }
}, $bar = $('<div />'), vert;
typeof user_options === 'object' && $.extend(default_options, user_options);
vert = default_options.direction === 'vertical';
$bar.css($.extend({backgroundColor: default_options.color, width: 0, height: 0},
(vert? {width: '100%', position: 'absolute', bottom: 0, left: 0} : {height: '100%'})));
return this.empty().append($bar.animate((vert? {height: '100%'} : {width: '100%'}), default_options)).css('position', 'relative');
};

keyboard
11-22-2012, 07:16 AM
Wow, thanks for that John!
How does this line work?

typeof user_options === 'object' && $.extend(default_options, user_options);
I get what it does, but can't work out how to use it in a different situation...

jscheuer1
11-22-2012, 07:50 AM
An if statement that has only one action can be done more succinctly as an && statement.

The && is all about determining the truth of things and means basically if the first thing is true, consider the second thing. In this context:


typeof user_options === 'object'

will either be true or false. If it's false, the rest of the line will not even be considered. If it's true, the next thing will be evaluated. In this case the next thing is a function, so it will have to be run. Otherwise there's no way to determine its truth or falseness. We don't really care in this case, we just want it run if the first thing is true, and if that first thing is true, the function will be run.

I hope that clears it up. A bare bones example would be:


1 === 1 && alert('Doh!');

There 1 will always equal 1, so it will always fire the alert.

keyboard
11-22-2012, 08:11 AM
Thanks John :)