Consider the structure below
What i want is to select closest 9 buttons on clicking on a button and do lets say changing bg colors. And here's my custom code already doing that
$(document).on("click", "#footer button", function(){
var index = $(this).index();
var len = $("#footer button").length;
$("#footer button").css({
"background-color" : "#ccc"
});
if (index < 5) $("#footer button:lt(9)").css({
"background-color" : "#c99"
});
else if (index > (len - 6)) $("#footer button:gt(-10)").css({
"background-color" : "#c99"
});
else $("#footer button").slice((index -4), (index + 5)).css({
"background-color" : "#c99"
});
});
Now, i find using if .. else ..
blocks for jquery selectors lame somehow. Of course we gotta use it if we have to but in this case do we? Are there any built-in methods to chain for such purpose in jquery?
HERE is the fiddle to play with.
There's no built in method to do this, but it's easily done without using if
/else
:
$(document).on("click", "#footer button", function () {
var that = $(this),
index = that.index(),
prev = that.prevAll('button:lt(4)'),
next = that.nextAll('button:lt(4)');
that.siblings().removeClass('highlight');
that.add(prev).add(next).addClass('highlight');
});
JS Fiddle demo.
Incidentally, a simple plugin could be easily created/used:
(function($){
$.fn.rangedHighlight = function(range,highlight) {
var that = this,
prev = that.prevAll().slice(0,range),
next = that.nextAll().slice(0,range);
that.siblings().addBack().removeClass(highlight);
that.add(prev).add(next).addClass(highlight);
return this;
};
})(jQuery);
$('#footer').on('click', 'button', function(){
$(this).rangedHighlight(4,'highlight');
});
JS Fiddle demo.
Unfortunately I hadn't noticed, until it was pointed out in the comments, the necessity of always highlighting the full specified range of elements, even if that offsets the clicked element from the centre of the highlighted section. There doesn't seem to be any way of doing this without using an if
/else
of some sort (though I'm trying to simplify it).
While the above remains true (there is no built-in method), I did decide to rewrite the plugin to offer the choice to do so (in case it's of any use to you):
(function($){
$.fn.rangedHighlight = function(opts) {
var that = this,
index = that.index(),
s = $.extend({
'range' : 9,
'highlight' : 'highlight',
'highlightClicked' : false,
'alwaysShowFull' : true,
'returnRange' : false
}, opts),
eitherSide = Math.floor(s.range - 1)/2,
all = that.parent().children(),
leftLimited = index < eitherSide,
rightLimited = index > all.length - eitherSide - 1,
rangeMin, rangeMax, returnObject;
that.addClass(s.highlightClicked, 'string' === typeof s.highlightClicked);
if (!leftLimited && !rightLimited) {
rangeMin = index - eitherSide;
rangeMax = index + eitherSide + 1;
}
else if (s.alwaysShowFull && (leftLimited || rightLimited)) {
rangeMin = leftLimited ? 0 : all.length - s.range;
rangeMax = leftLimited ? s.range : all.length;
}
else if (!s.alwaysShowFull && (leftLimited || rightLimited)) {
rangeMin = leftLimited ? 0 : index - eitherSide;
rangeMax = leftLimited ? index + eitherSide + 1 : all.length;
}
that.siblings('.' + s.highlight).removeClass(s.highlight);
all.slice(rangeMin, rangeMax).addClass(s.highlight);
returnObject = s.returnRange === false ? this : all.slice(rangeMin,rangeMax);
return returnObject;
};
})(jQuery);
$('#footer').on('click', 'button', function(){
$(this).rangedHighlight({
// Number: number of elements _in total_ to be highlighted:
'range' : 7,
// String: the class-name to be applied to selected elements:
'highlight' : 'highlight',
// Boolean: shows the full range even if that range 'overlaps'
// the start/end points:
'alwaysShowFull' : true,
// Boolean: return the selected range (true) or the clicked
// element (true), for chaining purposes:
'returnRange' : false,
// String: specific class to add to the clicked element:
'highlightClicked' : false,
});
});
JS Fiddle demo.
References:
condition ? conditionIsTrue : conditionIsFalse
).Math.floor()
. typeof
.add()
.addBack()
.addClass()
.children()
.index()
.:gt()
) selector.:lt()
) selector.nextAll()
.on()
.parent()
.prevAll()
.removeClass()
.siblings()
.slice()
.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With