Reputation: 3065
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.
Upvotes: 6
Views: 109
Reputation: 253318
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');
});
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');
});
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,
});
});
References:
Upvotes: 3
Reputation: 32921
You can just use .slice()
, the only thing you have to watch out for is a negative start index which is easy to get around.
$(document).on("click", "#footer button", function(){
var index = $(this).index(),
range = 9,
startIndex = index - range,
endIndex = index + ( range + 1 );
$("#footer button")
.removeClass('selected')
.slice(startIndex > 0 ? startIndex : 0, endIndex)
.addClass('selected');
});
Small demo: http://jsfiddle.net/x2QJP/9/
Upvotes: 0