Reputation: 301
I tried searching, but couldn't quite find what I was looking for. Hopefully this is super simple for someone.
This is the code i'm starting with that i'd like to turn into a function. Obviously there is a way to do this so I don't have to repeat.
var fullWidth = $('.full-img').width();
var paddBottom = fullWidth * .75;
$('.full-img').css('padding-bottom', paddBottom);
var thumbWidth = $('.img-box').width();
var thumbBottom = thumbWidth * .75;
$('.img-box').css('padding-bottom', thumbBottom);
Here's what I tried
function aspectRatioFix(main, thumb) {
var fullWidth = main.width();
var paddBottom = fullWidth * .75;
main.css('padding-bottom', paddBottom);
var thumbWidth = thumb.width();
var thumbBottom = thumbWidth * .75;
thumb.css('padding-bottom', thumbBottom);
}
aspectRatioFix('.full-img', '.img-box');
I get the error "Uncaught TypeError: main.width is not a function"
Is there a way to maybe loop through my function to take care of both parts of my script instead of just duplicating what I have? Thanks!
Upvotes: 0
Views: 61
Reputation: 40
function aspectRatioFix(main, thumb) {
var fullWidth = main.width();
var paddBottom = fullWidth * .75;
main.css('padding-bottom', paddBottom);
var thumbWidth = thumb.width();
var thumbBottom = thumbWidth * .75;
thumb.css('padding-bottom', thumbBottom);
}
aspectRatioFix($('.full-img'), $('.img-box'));
Upvotes: -1
Reputation: 7059
What I can suggest is simply caching your jQuery objects. A simple DOM ready event inside an IIFE which can be copy/pasted into a separate js file:
// IIFE
(function(scope, $){
// this configuration
var cfg = {
cache: {
fullImg: '.full-img',
imgBox: '.img-box'
},
options: {
modifier: 0.75,
css: 'padding-bottom'
}
};
// function declaration
function aspectRatioFix(elements, options){
$.each(elements, function(){
var el = $(this),
paddBottom = el.width() * options.modifier;
el.css(options.css, paddBottom);
});
}
// DOM ready to execute
$(function(){
var fullImg = $(cfg.cache.fullImg);
//var imgBox = $(cfg.cache.imgBox);
aspectRatioFix(fullImg, cfg.options);
aspectRatioFix($(cfg.cache.imgBox), cfg.options);
});
}(window, window.jQuery));
The way I refactor things into functional (in this case) and modular approaches is to move every string in the code to cfg
object literal. The code becomes more clear to separate.
And to add real quickly: aspectRatioFix($('.a-new-selector'), cfg.options);
In case of the accepted answer you'll have to edit the function again while you should avoid that.
Upvotes: 1
Reputation: 31682
The function aspectRatioFix
is expecting jQuery objects so you'll have to pass in jQuery objects instead of selectors (strings) like this:
aspectRatioFix($('.full-img'), $('.img-box'));
If you have many images and their thumbs and you want to apply the code for all of them then use .each
like this:
var $mains = $('.full-img'),
$thumbs = $('.img-box');
$mains.each(function(index) {
// this: is the main image
// index: is its index so we can access the according thumb from $thumbs
aspectRatioFix($(this), $($thumbs[index])); // apply the aspectRatioFix on this main image, and on it's thumb from the $thumbs object (both this and $thumbs[index] are node elements so we have to wrap them in a jQuery object using $())
});
Upvotes: 2
Reputation: 511
You are sending plain strings and not selectors to your function, you would have to do it like this:
function aspectRatioFix(main, thumb) {
var fullWidth = main.width();
var paddBottom = fullWidth * .75;
main.css('padding-bottom', paddBottom);
var thumbWidth = thumb.width();
var thumbBottom = thumbWidth * .75;
thumb.css('padding-bottom', thumbBottom);
}
aspectRatioFix($('.full-img'), $('.img-box'));
Upvotes: 2