How can I shift-select multiple checkboxes like GMail? - javascript

In GMail, the user can click on one checkbox in the email list, hold down the Shift key, and select a second checkbox. The JavaScript will then select/unselect the checkboxes that are between the two checboxes.
I am curious as to how this is done? Is this JQuery or some basic (or complex) JavaScript?

I wrote a self-contained demo that uses jquery:
$(document).ready(function() {
var $chkboxes = $('.chkbox');
var lastChecked = null;
$chkboxes.click(function(e) {
if (!lastChecked) {
lastChecked = this;
return;
}
if (e.shiftKey) {
var start = $chkboxes.index(this);
var end = $chkboxes.index(lastChecked);
$chkboxes.slice(Math.min(start,end), Math.max(start,end)+ 1).prop('checked', lastChecked.checked);
}
lastChecked = this;
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<html>
<head>
</head>
<body>
<input type="checkbox" id="id_chk1" class="chkbox" value="1" />Check 1<br/>
<input type="checkbox" id="id_chk2" class="chkbox" value="2" />Check 2<br/>
<input type="checkbox" id="id_chk3" class="chkbox" value="3" />Check 3<br/>
<input type="checkbox" id="id_chk4" class="chkbox" value="4" />Check 4<br/>
<input type="checkbox" id="id_chk5" class="chkbox" value="5" />Check 5<br/>
<input type="checkbox" id="id_chk6" class="chkbox" value="6" />Check 6<br/>
<input type="checkbox" id="id_chk7" class="chkbox" value="7" />Check 7<br/>
</body>
</html>

This is done through fairly simple javascript.
They keep track of the id of the last checked box and when when another checkbox is checked they use the shiftKey event attribute to see if shift was held while clicking the checkbox. If so they set the checked property of each checkbox in between the two to true.
To determine when a box is checked they probably use an onclick event on the checkboxes

It seems like every answer I can find online is completely dependent on jQuery for this. JQuery adds very little functionality. Here's a quick version that doesn't require any frameworks:
function allow_group_select_checkboxes(checkbox_wrapper_id){
var lastChecked = null;
var checkboxes = document.querySelectorAll('#'+checkbox_wrapper_id+' input[type="checkbox"]');
//I'm attaching an index attribute because it's easy, but you could do this other ways...
for (var i=0;i<checkboxes.length;i++){
checkboxes[i].setAttribute('data-index',i);
}
for (var i=0;i<checkboxes.length;i++){
checkboxes[i].addEventListener("click",function(e){
if(lastChecked && e.shiftKey) {
var i = parseInt(lastChecked.getAttribute('data-index'));
var j = parseInt(this.getAttribute('data-index'));
var check_or_uncheck = this.checked;
var low = i; var high=j;
if (i>j){
var low = j; var high=i;
}
for(var c=0;c<checkboxes.length;c++){
if (low <= c && c <=high){
checkboxes[c].checked = check_or_uncheck;
}
}
}
lastChecked = this;
});
}
}
And then initialize it whenever you need it:
allow_group_select_checkboxes('[id of a wrapper that contains the checkboxes]')

Recently, I wrote a jQuery plugin that provide that feature and more.
After including the plugin you just need to initialize the context of checkboxes with the following code snippet:
$('#table4').checkboxes({ range: true });
Here is the link to the documentation, demo & download: http://rmariuzzo.github.io/checkboxes.js/

Well, the post is quite old but here is a solution I've just come across:
jQuery Field Plug-In

I took the jQuery version from #BC. and transformed it into an ES6 version, since the code is actually pretty elegantly solving the problem, in case anyone still stumbles across this...
function enableGroupSelection( selector ) {
let lastChecked = null;
const checkboxes = Array.from( document.querySelectorAll( selector ) );
checkboxes.forEach( checkbox => checkbox.addEventListener( 'click', event => {
if ( !lastChecked ) {
lastChecked = checkbox;
return;
}
if ( event.shiftKey ) {
const start = checkboxes.indexOf( checkbox );
const end = checkboxes.indexOf( lastChecked );
checkboxes
.slice( Math.min( start, end ), Math.max( start, end ) + 1 )
.forEach( checkbox => checkbox.checked = lastChecked.checked );
}
lastChecked = checkbox;
} ) );
}

Got this solution from http://abcoder.com/javascript/jquery/simple-check-uncheck-all-jquery-function/ (now dead):
JavaScript and HTML code
var NUM_BOXES = 10;
// last checkbox the user clicked
var last = -1;
function check(event) {
// in IE, the event object is a property of the window object
// in Mozilla, event object is passed to event handlers as a parameter
if (!event) { event = window.event }
var num = parseInt(/box\[(\d+)\]/.exec(this.name)[1]);
if (event.shiftKey && last != -1) {
var di = num > last ? 1 : -1;
for (var i = last; i != num; i += di) {
document.forms.boxes['box[' + i + ']'].checked = true;
}
}
last = num;
}
function init() {
for (var i = 0; i < NUM_BOXES; i++) {
document.forms.boxes['box[' + i + ']'].onclick = check;
}
}
<body onload="init()">
<form name="boxes">
<input name="box[0]" type="checkbox">
<input name="box[1]" type="checkbox">
<input name="box[2]" type="checkbox">
<input name="box[3]" type="checkbox">
<input name="box[4]" type="checkbox">
<input name="box[5]" type="checkbox">
<input name="box[6]" type="checkbox">
<input name="box[7]" type="checkbox">
<input name="box[8]" type="checkbox">
<input name="box[9]" type="checkbox">
</form>
</body>

Inspired by the fine answers provided, here's a plain JavaScript version using Array.prototype to coerce nodelists to use array functions, rather than for loops.
(function () { // encapsulating variables with IIFE
var lastcheck = null // no checkboxes clicked yet
// get desired checkboxes
var checkboxes = document.querySelectorAll('div.itemslist input[type=checkbox]')
// loop over checkboxes to add event listener
Array.prototype.forEach.call(checkboxes, function (cbx, idx) {
cbx.addEventListener('click', function (evt) {
// test for shift key, not first checkbox, and not same checkbox
if ( evt.shiftKey && null !== lastcheck && idx !== lastcheck ) {
// get range of checks between last-checkbox and shift-checkbox
// Math.min/max does our sorting for us
Array.prototype.slice.call(checkboxes, Math.min(lastcheck, idx), Math.max(lastcheck, idx))
// and loop over each
.forEach(function (ccbx) {
ccbx.checked = true
})
}
lastcheck = idx // set this checkbox as last-checked for later
})
})
}())
<div class="itemslist">
<input type="checkbox" name="one" value="1">
<input type="checkbox" name="two" value="2">
<input type="checkbox" name="three" value="3">
<input type="checkbox" name="four" value="4">
<input type="checkbox" name="five" value="5">
</div>

I realy liked gyo's example and added some code so it works on all checkboxes with the same name.
I also added a MutationObserver so events are also handled on newly added checkboxes.
$(document).ready(function() {
var previouslyClicked = {};
var rangeEventHandler = function(event) {
if (event.shiftKey && previouslyClicked[this.name] && this != previouslyClicked[this.name]) {
var $checkboxes = $('input[type=checkbox][name='+this.name+']').filter(':visible');
var start = $checkboxes.index( this );
var end = $checkboxes.index( previouslyClicked[this.name] );
// console.log('range', start, end, this, previouslyClicked[this.name]);
$checkboxes.slice(Math.min(start,end), Math.max(start,end)+ 1).prop('checked', previouslyClicked[this.name].checked);
} else {
previouslyClicked[this.name] = this;
}
};
if ("MutationObserver" in window) { // https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver/MutationObserver to refresh on new checkboxes
var mutationCallback = function(mutationList, observer) {
mutationList.forEach((mutation) => {
mutation.addedNodes.forEach((node) => {
if (node.nodeName == 'INPUT' && node.type == 'checkbox') {
$(node).on('click.selectRange', rangeEventHandler);
}
});
});
};
var observer = new MutationObserver(mutationCallback);
observer.observe(document, {
childList: true,
attributes: false, // since name is dynamically read
subtree: true
});
}
$('input[type=checkbox][name]').on('click.selectRange', rangeEventHandler);
});
<html>
<head>
</head>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
First:
<input type="checkbox" name="first">
<input type="checkbox" name="first">
<input type="checkbox" name="first">
<input type="checkbox" name="first">
<input type="checkbox" name="first">
</div>
<div>
Second:
<input type="checkbox" name="second">
<input type="checkbox" name="second">
<input type="checkbox" name="second">
<input type="checkbox" name="second">
<input type="checkbox" name="second">
</div>
</body>
</html>

Found the better solution it works for both select and deselects checkboxes.
Uses a core javascript & Jquery.
$(document).ready(function() {
var $chkboxes = $('.chkbox');
var lastChecked = null;
$chkboxes.click(function(e) {
if(!lastChecked) {
lastChecked = this;
return;
}
if(e.shiftKey) {
var start = $chkboxes.index(this);
var end = $chkboxes.index(lastChecked);
$chkboxes.slice(Math.min(start,end), Math.max(start,end)+ 1).prop('checked', e.target.checked);
}
lastChecked = this;
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<html>
<head>
</head>
<body>
<input type="checkbox" id="id_chk1" class="chkbox" value="1" />Check 1<br/>
<input type="checkbox" id="id_chk2" class="chkbox" value="2" />Check 2<br/>
<input type="checkbox" id="id_chk3" class="chkbox" value="3" />Check 3<br/>
<input type="checkbox" id="id_chk4" class="chkbox" value="4" />Check 4<br/>
<input type="checkbox" id="id_chk5" class="chkbox" value="5" />Check 5<br/>
<input type="checkbox" id="id_chk6" class="chkbox" value="6" />Check 6<br/>
<input type="checkbox" id="id_chk7" class="chkbox" value="7" />Check 7<br/>
</body>
</html>

Here is also another implementation similar to Outlooks multiple selection..
<script type="text/javascript">
function inRange(x, range)
{
return (x >= range[0] && x <= range[1]);
}
$(document).ready(function() {
var $chkboxes = $('.chkbox');
var firstClick = 1;
var lastClick = null;
var range = [];
$chkboxes.click(function(e) {
if(!e.shiftKey && !e.ctrlKey) {
$('#index-' + firstClick).prop('checked', false);
firstClick = $chkboxes.index(this) + 1;
if (firstClick !== null && firstClick !== ($chkboxes.index(this)+1)) {
$('#index-' + firstClick).prop('checked', true);
}
} else if (e.shiftKey) {
lastClick = $chkboxes.index(this) + 1;
if ((firstClick < lastClick) && !inRange(lastClick, range)) {
for (i = firstClick; i < lastClick; i++) {
$('#index-' + i).prop('checked', true);
}
range = [firstClick, lastClick];
} else if ((firstClick > lastClick) && !inRange(lastClick, range)) {
for (i = lastClick; i < firstClick; i++) {
$('#index-' + i).prop('checked', true);
}
range = [lastClick, firstClick];
} else if ((firstClick < lastClick) && inRange(lastClick, range)) {
for (i = 1; i < 100; i++) {
$('#index-' + i).prop('checked', false);
}
for (i = firstClick; i < lastClick; i++) {
$('#index-' + i).prop('checked', true);
}
range = [firstClick, lastClick];
}else if ((firstClick > lastClick) && inRange(lastClick, range)) {
for (i = 1; i < 100; i++) {
$('#index-' + i).prop('checked', false);
}
for (i = lastClick; i < firstClick; i++) {
$('#index-' + i).prop('checked', true);
}
range = [lastClick, firstClick];
}
}
});
});

This is jquery solution that I wrote and use:
All checkboxes have same class named chksel
For faster individual selection a class will carry the order
named chksel_index
Also each checkbox has an attribute named rg that contain same
index
var chksel_last=-1;
$('.chksel').click(function(ev){
if(ev.shiftKey){var i=0;
if(chksel_last >=0){
if($(this).attr('rg') >= chksel_last){
for(i=chksel_last;i<=$(this).attr('rg');i++){$('.chksel_'+i).attr('checked','true')}}
if($(this).attr('rg') <= chksel_last){for(i=$(this).attr('rg');i<=chksel_last;i++){$('.chksel_'+i).attr('checked','true')}}
}
chksel_last=$(this).attr('rg');
}else{chksel_last=$(this).attr('rg');}
})

this solution works for me, also ajax based for DataTables
https://jsfiddle.net/6ouhv7bw/4/
<table id="dataTable">
<tbody>
<tr>
<td><input type="checkbox"></td>
</tr>
<tr>
<td><input type="checkbox"></td>
</tr>
<tr>
<td><input type="checkbox"></td>
</tr>
<tr>
<td><input type="checkbox"></td>
</tr>
</tbody>
</table>
<script>
$(document).ready(function() {
var $chkboxes = $('#dataTable');
var $range = '#dataTable tbody';
var $first = false;
var $indexWrapp = 'tr';
var lastChecked = null;
var $checkboxes = 'input[type="checkbox"]';
$chkboxes.on('click',$checkboxes,function(e) {
if ($first===false) {
lastChecked = $(this).closest($indexWrapp).index();
lastCheckedInput = $(this).prop('checked');
$first=true;
return;
}
if (e.shiftKey) {
var start = lastChecked;
var end = $(this).closest($indexWrapp).index();
$( $range+' '+$indexWrapp).each(function() {
$currIndex=$(this).index();
if( $currIndex>=start && $currIndex<=end ){
$(this).find($checkboxes).prop('checked', lastCheckedInput);
}
})
}
lastCheckedInput = $(this).prop('checked');
lastChecked = $(this).closest($indexWrapp).index();
});
</script>

Here is the Elegant implementation. The idea is to store the first selected input to the lastChecked variable and when the user selects the input field with shiftKey we will run a loop and toggle the inBetween(boolean) and mark all the checkboxes with true value.
Inspired by Wesbos.
let checkboxes = document.querySelectorAll('.wrapper input[type="checkbox"]');
let lastChecked;
function logic(e) {
let inBetween = false;
if (e.shiftKey) {
checkboxes.forEach(checkbox => {
if (checkbox === this || checkbox === lastChecked) {
inBetween = !inBetween;
}
if (inBetween) checkbox.checked = true;
})
}
lastChecked = this;
}
checkboxes.forEach((checkbox, i) => checkbox.addEventListener('click', logic));
.wrapper {
display: flex;
flex-direction: column;
}
<div class="wrapper">
<input type="checkbox" name="one">
<input type="checkbox" name="two">
<input type="checkbox" name="three">
<input type="checkbox" name="four">
<input type="checkbox" name="five">
</div>

Related

Javascript function doesn't run with an if-else statement

I have a few checkboxes:
<input type="checkbox" name="filterby" id="type" value="type" onchange="showFilter();" />Type<br>
<input type="checkbox" name="filterby" id="conseq" value="conseq" onchange="showFilter();" />Consequence<br>
<input type="checkbox" name="filterby" id="group" value="group" onchange="showFilter();" />Group<br>
<input type="checkbox" name="filterby" id="sample" value="sample" onchange="showFilter();" />Sample<br>
and a div for each one, that I want to show and hide when clicked. This is my function:
function showFilter() {
var filterby = ["type", "conseq", "group", "sample"];
for (var i = 0; i < filterby.length; i++) {
var option_on = document.getElementById(filterby[i]).checked;
var filterby_list = filterby[i] + "_list";
if (option_on == true) {
document.getElementById(filterby_list).style.display = "block";
}
else {
document.getElementById(filterby_list).style.display = "none";
}
}
}
I have been looking at it for hours and can't figure out why it doesn't work. If I delete the if-else statement, it runs through, if not, it works for the first checkbox and not the others, it stops when looping over the second. Where is my error?
Thank you.
If I add divs with the correct ID's your script expects, your code works.
So your problem is not with the code shown.
Does your HTML contain the correct id values on the divs you want to show and hide?
function showFilter() {
var filterby = ["type", "conseq", "group", "sample"];
for (var i = 0; i < filterby.length; i++) {
var option_on = document.getElementById(filterby[i]).checked;
var filterby_list = filterby[i] + "_list";
if (option_on == true) {
document.getElementById(filterby_list).style.display = "block";
}
else {
document.getElementById(filterby_list).style.display = "none";
}
}
}
<input type="checkbox" name="filterby" id="type" value="type" onchange="showFilter();" />Type<br>
<input type="checkbox" name="filterby" id="conseq" value="conseq" onchange="showFilter();" />Consequence<br>
<input type="checkbox" name="filterby" id="group" value="group" onchange="showFilter();" />Group<br>
<input type="checkbox" name="filterby" id="sample" value="sample" onchange="showFilter();" />Sample<br>
<div id="type_list">type</div>
<div id="conseq_list">conseq</div>
<div id="group_list">group</div>
<div id="sample_list">sample</div>
You can achieve things either in ways:
either Create the list with name appended with "_list"
OR second option remove "_list" from the javascript like below code:
function showFilter() {
var filterby = ["type", "conseq", "group", "sample"];
for (var i = 0; i < filterby.length; i++) {
var option_on = document.getElementById(filterby[i]).checked;
var filterby_list = filterby[i];
if (option_on == true) {
document.getElementById(filterby_list).style.display = "block";
}
else {
document.getElementById(filterby_list).style.display = "none";
}
}
}

Use JavaScript to Get SelectedValue ASP.NET RadiobuttonList

I have the following radio button list on an .aspx page:
<asp:RadioButtonList ID="rbList" runat="server">
<asp:ListItem Text="I accept" Value="accept" />
<asp:ListItem Text="I decline" Value="decline" Selected="True" />
</asp:asp:RadioButtonList>
The second radio is selected by default. Is there a way for me to determine if a user hasn't selected the first option, i.e., "decline" is still selected when they perform an action?
E.g.:
function checkRbList() {
var rbl = document.getElementById(<%= rbList.ClientID %>);
//if "decline" is still selected, alert('You chose to decline')...
}
The following should do the job:
var rbl = document.getElementById("<%= rbList.ClientID %>");
var value = rbl.value;
if(value === 'decline')
alert()
Assuming you have this HTML rendered:
<label>
I accept
<input id="rbList_0" name="rbList" type="radio" value="accept" />
</label>
<label>
I decline
<input id="rbList_1" name="rbList" checked="true" type="radio" value="decline" />
</label>
You can use document.getElementsByName(). Then by using:
document.getElementsByName("rbList") you'll get a NodeList.
This is the function:
function checkRbList() {
var rbl = document.getElementsByName("rbList"), len = rbl.length;
for (var i = 0; i < len; i++) {
if (rbl[i].checked) { // If checked?
return rbl[i].value; // Returns the selected value.
}
}
}
To check if "decline" is still selected:
var targetValue = "decline";
if (checkRbList() === targetValue) {
alert("You chose to decline.");
}
Something like this:
(function() {
var targetValue = "decline";
function checkRbList() {
var rbl = document.getElementsByName("rbList"),
len = rbl.length;
for (var i = 0; i < len; i++) {
if (rbl[i].checked) { // If checked?
return rbl[i].value; // Returns the selected value.
}
}
}
var btnValidate = document.getElementById("btnValidate");
btnValidate.onclick = function() {
console.log(checkRbList()); // Prints the selected value.
if (checkRbList() === targetValue) {
alert("You chose to decline.");
}
};
})();
<label>
I accept
<input id="rbList_0" name="rbList" type="radio" value="accept" />
</label>
<label>
I decline
<input id="rbList_1" name="rbList" checked="true" type="radio" value="decline" />
</label>
<button id="btnValidate" type="button">Validate</button>
I found a way that is working:
var targetValue = "decline";
$('#<% = myBtn.ClientID %>').click(function () {
var items = $("#<% = rbList.ClientID %> input:radio");
for (var i = 0; i < items.length; i++) {
if (items[i].value == targetValue) {
if (items[i].checked) {
alert(items[i].value);
}
}
}
});

when i select radio button then all radio button is selected. i want only one radio button should be selected

I am trying to do this.
I have three radio buttons, it is working fine when i use all radio button in a single div but it is not working when i divide all radio button in particular div. i click on it then it is selected but next time when i click on it then still radio button is selected.
It should be unselected when i click on it.
Please help. Your help will be appreciated. Thanks a lot.
Here's my code so far.
<html>
<head>
</head>
<body>
<div class="filter_subdivisions">
<div class="popular_city radio mgnb6 clearfix">
<span class="fltl" style="width:70%;padding-top: 6px;">Delhi Airport</span>
<span class="fltr">
<label class="label_radio" for="radio-01"><input name="sample-radio" id="radio-01" value="1" type="radio" checked /> </label>
</span>
</div>
<div class="popular_city radio mgnb6 clearfix">
<span class="fltl" style="width:70%;padding-top: 6px;">Delhi Airport</span>
<span class="fltr">
<label class="label_radio" for="radio-02"><input name="sample-radio" id="radio-02" value="1" type="radio" /> </label>
</span>
</div>
</div>
</body>
</html>
and
<script>
var d = document;
var safari = (navigator.userAgent.toLowerCase().indexOf('safari') != -1) ? true : false;
var gebtn = function(parEl,child) { return parEl.getElementsByTagName(child); };
onload = function() {
var body = gebtn(d,'body')[0];
body.className = body.className && body.className != '' ? body.className + ' has-js' : 'has-js';
if (!d.getElementById || !d.createTextNode) return;
var ls = gebtn(d,'label');
for (var i = 0; i < ls.length; i++) {
var l = ls[i];
if (l.className.indexOf('label_') == -1) continue;
var inp = gebtn(l,'input')[0];
if (l.className == 'label_radio') {
l.className = (safari && inp.checked == true || inp.checked) ? 'label_radio r_on' : 'label_radio r_off';
l.onclick = turn_radio;
};
};
};
var turn_radio = function() {
var inp = gebtn(this,'input')[0];
if (this.className == 'label_radio r_off' || inp.checked) {
var ls = gebtn(this.parentNode,'label');
for (var i = 0; i < ls.length; i++) {
var l = ls[i];
if (l.className.indexOf('label_radio') == -1) continue;
l.className = 'label_radio r_off';
};
this.className = 'label_radio r_on';
if (safari) inp.click();
} else {
this.className = 'label_radio r_off';
if (safari) inp.click();
};
};
</script>
You have to have type="radio" buttons within the same container to make them behave like radio buttons, like as per w3schools example
<form>
<input type="radio" name="sex" value="male">Male<br>
<input type="radio" name="sex" value="female">Female
</form>

getElementByTagName not working

When I click delete button without clicking any checkbox, it should show alert, but in this coding, if first checkbox checked, it doesn't show alert. If second checkbox checked, it show alert.
HTML:
<div id="checkbox">
<input type="CHECKBOX" name="MyCheckbox" class="checkbox" value="This..." >
<input type="CHECKBOX" name="MyCheckbox" class="checkbox" value="This..." >
<input type="CHECKBOX" name="MyCheckbox" class="checkbox" value="This..." >
<input type="CHECKBOX" name="MyCheckbox" class="checkbox" value="This..." >
</div>
<form action="DeleteServer" onsubmit="return checkCheckBoxes(this);">
<input type="SUBMIT" value="Delete!">
</form>
script function:
function checkCheckBoxes() {
var chk = document.getElementById("checkbox").getElementsByTagName("input");
for(var i=0; i<chk.length;i++){
if (document.getElementById("checkbox").getElementsByTagName("input")[i].checked == false)
{
alert ('You didn\'t choose any of the checkboxes!');
return false;
} else {
return true;
}
}
}
getElementsByTagName has an s in it. It is plural. It returns a NodeList not a single Element.
Given your HTML, that NodeList will include 2 separate inputs.
You have to loop over it (as if it was an Array) and test the checked property of each input in turn.
This should solve your problem:
var inputs = document.querySelectorAll('#checkbox input');
is_checked = false;
for(var i = 0; i < inputs.length; i++) {
if(inputs[i].type == 'checkbox' && inputs[i].name == 'MyCheckbox') {
is_checked = inputs[i].checked;
if(is_checked) break;
}
}
if(!is_checked){
alert('You didn\'t choose any of the checkboxes!');
}
Here is a fiddle
function checkCheckBoxes() {
var inputs = document.querySelectorAll('#checkbox input');
is_checked = false;
for(var i = 0; i < inputs.length; i++) {
if(inputs[i].type == 'checkbox') {
is_checked = inputs[i].checked;
if(is_checked) return true;
}
}
if(!is_checked){
alert('You didn\'t choose any of the checkboxes!');
return false;
}
}

spit items into different arrays and retrieving it back

this related to my previous question asked and thanks to every one here who is helping me to learn coding :D
i was previously working on an undo button which kind of works but not there yet :(
here is what i have done click here. But the problem is since it goes step by step backwards it has to wait till the item where the previous color was applied in the same part. Is there a way i can split something like this click here will this idea work out?
here is the test html code:
<div id="colour">
<input type="submit" name="r1" id="r1" value="1" />
<input type="submit" name="r2" id="r2" value="2" />
<input type="submit" name="r3" id="r3" value="3" />
<input type="submit" name="r4" id="r4" value="4" />
<input type="submit" name="r5" id="r5" value="5" />
<input type="submit" name="r6" id="r6" value="6" />
</div>
<div id="map">
<input type="radio" name="radio" id="layer_a" value="a" />
<label for="layer">layer_a</label>
<input type="radio" name="radio" id="layer_b" value="b" />
<label for="layer">layer_b</label>
<input type="radio" name="radio" id="layer_c" value="c" />
<label for="layer">layer_c</label>
<input type="radio" name="radio" id="layer_d" value="d" />
<label for="layer">layer_d</label>
</div>
<input name="selected" id="selected" type="hidden" value="" />
<input type="submit" name="undo" id="undo" value="undo" />
<div id="result"></div>
here is the test jQuery code:
$("#colour input").click(function() {
$("input[name='selected']").val(this.id);
});
var arraymap = [];
var array_a = [];
var array_b = [];
var array_c = [];
var array_d = [];
$("#map input").click(function() {
var mape = $(this).attr('id');
var ccurrent = $("input[name='selected']").val();
arraymap.push(mape);
// trying to split it into diffrent arrays //
if (mape == "layer_a") {
array_a.push(ccurrent);
var araycurrent = array_a;
} else if (mape == "layer_b") {
array_b.push(ccurrent);
var araycurrent = array_b;
} else if (mape == "layer_c") {
array_c.push(ccurrent);
var araycurrent = array_c;
} else if (mape == "layer_d") {
array_d.push(ccurrent);
var araycurrent = array_d;
};
var mapid = arraymap[arraymap.length - 1];
var colid = arraycurrent[arraycurrent.length - 1];
var loca = mapid + colid;
$("#result").append(mapid);
});
$("#undo").click(function() {
arraymap.pop();
var remover_map = arraymap[arraymap.length - 1];
// trying get it back from split arrays //
if (remover_map == "layer_a") {
array_a.pop();
var remover_col = array_a[array_a.length - 1];
} else if (remover_map == "layer_b") {
array_b.pop();
var remover_col = array_b[array_b.length - 1];
} else if (remover_map == "layer_c") {
array_c.pop();
var remover_col = array_b[array_c.length - 1];
} else if (remover_map == "layer_d") {
array_d.pop();
var remover_col = array_a[array_d.length - 1];
};
var remove = remover_map + remover_col;
$("#result").append(remove);
});
You can store you layer arrays in an object to use it as an associative array. That way you can easily reference them by the layer name.
Here's my version of your example: (Working demo: http://jsfiddle.net/qbdyp/)
var step_layer = []; // layers affected by each step
var step_colour = { // selected colours by layer
"a": [],
"b": [],
"c": [],
"d": []
};
var $map = $("#map"), $result = $("#result"); // cache
$("#colour > input").click(function() {
var layer = $map.find("input[name='radio']:checked").val(); // current layer
var colour = this.value; // selected colour
step_layer.push(layer);
step_colour[layer].push(colour);
$result.append("Added " + colour + " to layer " + layer + "<br/>");
});
$("#undo").click(function() {
var layer = step_layer.pop(); // get most recently changed layer
if (typeof layer === "undefined") {
$result.append("(Nothing to undo)<br />");
return;
}
var colour = step_colour[layer].pop(); // get latest change in that layer
$result.append("Removed " + colour + " from layer " + layer + "<br/>");
});
And here's a more elaborate example, one that's hopefully closer to what you're trying to achieve: http://jsfiddle.net/uWUve/

Categories