I have this JSFiddle code :
http://jsfiddle.net/rnnb32rm/285/
<div ng-app="angularjs-starter" ng-controller="MainCtrl">
<fieldset data-ng-repeat="choice in choicesA">
<input type="text" ng-model="choice.name" name="" placeholder="Enter name">
<button class="addfields" ng-click="addNewChoice()">Add fields</button>
<button class="remove" ng-click="removeChoice()">-</button>
</fieldset>
<div id="choicesDisplay">
{{ choicesA }} <br/>
{{ choicesB }}
</div>
</div>
JS :
var app = angular.module('angularjs-starter', []);
app.controller('MainCtrl', function($scope) {
$scope.choicesA = [{id: 'choice1'}, {id: 'choice2'}];
$scope.choicesB = [];
$scope.addNewChoice = function() {
var newItemNo = $scope.choicesA.length+1;
$scope.choicesA.push({'id':'choice'+newItemNo});
};
$scope.removeChoice = function() {
var lastItem = $scope.choicesA.length-1;
$scope.choicesA.splice(lastItem);
};
});
As you can see, I have a function addNewChoice() which adds objects to the array choicesA, and then Textboxes get added based on objects number on the choicesA array.
I need to add textboxes to the first fieldset only when I click on the Add fields button on the first fieldset, and the data that I write on those generated textboxes is binded and added to seperate objects to the choicesB array. and the same for all the other Add fields buttons (so each Add field button can only add textboxes to its own fieldset tag), which also get generated based on the number of objects in the choicesA array.
I tried everything, I just can't figure it out. I can explain more if it's a bit unclear. Thank you a ton in advance.
EDIT : Thank you all for your great help, let me explain more :
I have a Spring REST API and two Java objects (JPA entities) named Resource & Action, the object Resource contains a List of Actions, and Action contains a reference to a Resource.
When I load a page, I get an array of Resource objects that I already saved return from the database by an $http.get() method,named choicesA, the structure of array is like this :
[
{"idResource":1, "nameResource": "resName1"},
{"idResource":2, "nameResource": "resName2"}
......etc depends oh how much rows I got from the DB
]
I have another method, $http.post() which posts an array of Action objects named choicesB a seperate non nested array. The array structure is like this :
[
{"idAction":1, "nameAction":"nameAction1", "resource":
{"idResource":1, "nameResource": "resName1"},
{"idAction":2, "nameAction":"nameAction2", "resource":
{"idResource":2, "nameResource": "resName2"},
..
}
{...},
{...}
...
]
So the choicesA array contains the Resource objects that I got with the $http.get(), then I want to fill Action objects in the choicesB array and then save the array using $http.post(), every Action should contain a Resource object. If I click to add more actions in the first fieldset tag for example, means that I want to fill the first Action object in choicesB array, and assign to it the first Resource object located in the choicesA array etc..
I want to be able to decide the number of actions and fill them out, then saving them to the choicesB array. but every action is related to a specific Resource object like I described.
I hope it's clear now, I'm sorry & Thank you again.
Maybe I misunderstood your question. Maybe this will help solve your problem.
Live example on jsfiddle.
var app = angular.module('angularjs-starter', []);
app.controller('MainCtrl', function($scope) {
$scope.choicesA = [{
id: 'choice1',
choicesB:[]
}, {
id: 'choice2',
choicesB:[]
}];
$scope.addNewChoice = function() {
var newItemNo = $scope.choicesA.length + 1;
$scope.choicesA.push({
'id': 'choice' + newItemNo,
choicesB:[]
});
};
$scope.removeChoice = function(ind) {
$scope.choicesA.splice(ind,1);
};
$scope.addNewChoiceB = function(choice) {
var newItemNo = choice.choicesB.length + 1;
choice.choicesB.push({
'id': 'choice' + newItemNo
});
};
$scope.removeChoiceB = function(choice,ind) {
choice.choicesB.splice(ind,1);
};
});
fieldset {
background: #FCFCFC;
padding: 16px;
border: 1px solid #D5D5D5;
}
.addfields {
margin: 10px 0;
}
#choicesDisplay {
padding: 10px;
background: rgb(227, 250, 227);
border: 1px solid rgb(171, 239, 171);
color: rgb(9, 56, 9);
}
.remove {
background: #C76868;
color: #FFF;
font-weight: bold;
font-size: 21px;
border: 0;
cursor: pointer;
display: inline-block;
padding: 4px 9px;
vertical-align: top;
line-height: 100%;
}
input[type="text"],
select {
padding: 5px;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="angularjs-starter" ng-controller="MainCtrl">
<button class="addfields" ng-click="addNewChoice()">Add choice</button>
<fieldset data-ng-repeat="choice in choicesA">
<input type="text" ng-model="choice.name" name="" placeholder="Enter name">
<button class="remove" ng-click="removeChoice($index)">-</button>
<button class="addfields" ng-click="addNewChoiceB(choice)">Add fields</button>
<div data-ng-repeat="choiceb in choice.choicesB">
<input type="text" ng-model="choiceb.name" name="" placeholder="Enter field">
<button class="remove" ng-click="removeChoiceB(choice,$index)">-</button>
</div>
</fieldset>
<div id="choicesDisplay">
<pre>choicesA = {{ choicesA }}</pre>
<pre data-ng-repeat="choiceb in choicesA">choicesB = {{ choiceb.choicesB }}</pre>
</div>
</div>
Updated
Live example on jsfiddle.
I believe what you are trying to do is have 2 nested arrays.
Then you would have nested ng-repeat. You keep track of which array by passing that array as argument of function
View
<fieldset data-ng-repeat="group in choices">
<div ng-repeat="choice in group">
<input type="text" ng-model="choice.name" name="" placeholder="Enter name">
<button class="addfields" ng-click="addNewChoice(group)">Add fields</button>
<button class="remove" ng-click="removeChoice(group)">-</button>
</div>
</fieldset>
JS
$scope.choices = [
// first group
[{id: 'choice1'}, { id: 'choice2'}],
//second group
[{}]
];
$scope.addNewChoice = function(group) {
var newItemNo = group.length + 1;
group.push({
'id': 'choice' + newItemNo
});
};
$scope.removeChoice = function(group) {
group.pop();
};
Note you will need to modify your ID system a bit. Normally this would come from server anyway
DEMO
<div ng-app="angularjs-starter" ng-controller="MainCtrl">
<fieldset>
<input data-ng-repeat="choice in choicesA" type="text" ng-model="choice.name" name="" placeholder="Enter name">
<button class="addfields" ng-click="addNewChoice()">Add fields</button>
<button class="remove" ng-click="removeChoice()">-</button>
</fieldset>
First portion of your requirment is solved by this that textbox is added to sepecific fieldset and 2nd requirment is unclear to me replace your htmlcode with this
Related
I'm new at AngularJS. I do know some javascript, but AngularJS seems hard to learn (maybe it's just me).
My problem is as follows...
I have a list of players and I would like to make it possible for a user (coach or whoever) to add their players to the list. I have tried couple of method for these past few days, and I just can't figure it out.
Code is below, and u can check out my plunkr here:
HTML
<!DOCTYPE html>
<html >
<head>
<!-- CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"
integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<link href="style.css" rel="stylesheet" />
<!-- Scripts -->
<script data-require="angular.js#1.2.17" data-semver="1.2.17"
src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.17/angular.min.js"></script>
<script src="script.js"></script>
</head>
<body>
<div ng-app="app">
<div ng-controller="MoveCtrl" class = "container">
<div class = "row">
<div class = "col-xs-4 left-space">
<!--Forgot to add this block of code for input-->
<label>Player name: </label> <input #playerName/>
<button (click) = "add(playerName.value); playerName.value = ''">
Add
</button>
<!--Rest is the same-->
<label class="left-space-title" for="aplayers">Available Players</label>
<select class="left-space-container" size="5" multiple ng-model="available"
ng-options="player as player.name for player in availableplayers">
</select>
</div>
<div class = "col-xs-2 mid-space ">
<input id="moveright" type="button" value=">>"
ng-click="moveItem(available, availableplayers,selectedplayers)" />
<input id="moveleft" type="button" value="<<"
ng-click="moveItem(selected, selectedplayers,availableplayers)" />
</div>
<div class = "col-xs-4 right-space">
<label class="right-space-title" for="splayers">Selected Players</label>
<select class="right-space-container" size="5" multiple ng-model="selected"
ng-options="player as player.name for player in selectedplayers">
</select>
</div>
</div>
</div>
</div>
</body>
</html>
CSS
.mid-space {
margin-top: 30px;
}
.left-space__title,
.right-space__title {
width: 100%;
}
.left-space-container,
.right-space-container {
width: 100%;
min-height: 500px;
}
#moveright,
#moveleft {
width: 100%;
}
Javascript
angular.module('app', []).controller('MoveCtrl', function($scope) {
$scope.moveItem = function(items, from, to) {
items.forEach(function(item) {
var idx = from.indexOf(item);
if (idx != -1) {
from.splice(idx, 1);
to.push(item);
}
});
};
$scope.selectedplayers = [];
$scope.availableplayers = [
{
id: 1,
name: 'foo'
},
{
id: 2,
name: 'boo'
},
{
id: 3,
name: 'goo'
}
];
});
Plunkr is here if you would like to fiddle with the code directly
The plunker has been updated with your working code changes to add the new player to the available players list
add new player plunker
$scope.addItem = function(){
var numberOfplayers = $scope.availableplayers.length;
var newPlayer = {
id : numberOfplayers + 1,
name : $scope.newPlayerName
}
console.log($scope.newPlayerName);
$scope.availableplayers.push(newPlayer);
}
<label>Player name: </label> <input ng-model="newPlayerName"/>
<button ng-click = "addItem(playerName);">
Add
</button>
code changes done .
1.set the ng-model for the input field .
2.get the value of the
input fiend in controllers add player method.
3.create the new
players object with the generated id value.
4.Insert the new player
object to the availableplayers scope variable which inturn pops up
the value in the box.
I have an HTML document. There are 2 fields:
First one is an hidden input field (with a pre selected value)
The other is an empty text input field. It displays the current value of the first one with jQuery.
Between that 2 fields, I have 9 buttons with different texts inside them.
With jQuery, when I click on a button it add his text in the visible field (separated by a coma) and it adds to himself an enabled class. This works.
When I click on the same button, the class is removed (this works).
What is not working:
I would like at the same time it removes his name from the field (with a coma) I With jQuery / JavaScript I have tried to convert with split() each name in the field (coma separated) to an array, to easily delete one of them when needed with splice().
What I haven done yet:
I need to convert-it back to a coma separated string, replacing the existing string value in the field ( I haven done this yet). I am not far.
My code on JS Fiddle
How can I achieve this?
My code in here:
jQuery(document).ready(function($){
if ($('.subscribe-text').val() == ''){
$('.subscribe-text').val($('.subscribe-text-get').val()+',')
}
$('.subscribe-button').click(function(){
if(!$(this).hasClass('enable'))
{
$('.subscribe-text').val($('.subscribe-text').val()+$(this).html()+',');
$(this).addClass('enable');
}
else if($(this).hasClass('enable'))
//
// I would like to remove the name in the field
// when a button is clicked and has 'enable' class
//
{
var myArray = new Array();
var myString = $('.subscribe-text').val();
myArray = myString.split(",");
var myItem = $(this).html()+' ';
var indexPos = myArray.indexOf(myItem);
if(indexPos != -1)
{
myArray = myArray.splice(indexPos, 1);
}
$('.subscribe-text').val(myArray);
$(this).removeClass('enable');
}
});
});
.subscribe-button {
background-color:#ddd
}
#buttons_x3 {
width:500px;
}
.subscribe-text {
width:100%;
font-size:9px;
}
.subscribe-button {
display: inline-block;
text-align:center;
padding:3px;
margin-bottom: 10px;
color: black;
height:20px;
width:100px;
margin:10px 20px 10px;
cursor:pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="my_custom_checkout_field">
<input type="hidden" class="subscribe-text-get" name="my_field_name" value="woo-multi-1">
</div>
<br>
<div id="buttons_x3">
<a class="subscribe-button">woo-single-1</a>
<a class="subscribe-button">woo-single-2</a>
<a class="subscribe-button">woo-single-3</a>
<a class="subscribe-button">woo-multi-1</a>
<a class="subscribe-button">woo-multi-2</a>
<a class="subscribe-button">woo-top-1</a>
<a class="subscribe-button">woo-top-2</a>
<a class="subscribe-button">woo-top-3</a>
<a class="subscribe-button">woo-special</a>
</div>
<br>
<div id="my_custom_checkout_field">
<input type="text" class="subscribe-text" name="my_field_name" value>
Be careful of a few things here:
1) Every time you click a button you are creating a new array with one long string inside.
2) Splice returns the value of the removed item, so each time a button is clicked you are setting the array string to be the item that you just removed.
Instead, initialize the array outside of your click function, and add each new item to the end. Set the value of the input with the toString() method. This will preserve the array of remaining values and their order.
jQuery(document).ready(function($){
var myArray = [];
if ($('.subscribe-text').val() == ''){
myArray[0] = $('.subscribe-text-get').val();
$('.subscribe-text').val( myArray.toString() );
}
var $item, length;
$('.subscribe-button').click(function(){
length = myArray.length;
if(!$(this).hasClass('enable')) {
$item = $(this).html();
myArray[length] = $item;
$('.subscribe-text').val( myArray.toString() );
$(this).addClass('enable');
}
else if($(this).hasClass('enable')) {
var myItem = $(this).html();
var indexPos = myArray.indexOf(myItem);
if(indexPos != -1) {
myArray.splice(indexPos, 1);
}
$('.subscribe-text').val( myArray.toString() );
$(this).removeClass('enable');
}
});
});
.subscribe-button {
background-color:#ddd
}
#buttons_x3 {
width:500px;
}
.subscribe-text {
width:100%;
font-size:9px;
}
.subscribe-button {
display: inline-block;
text-align:center;
padding:3px;
margin-bottom: 10px;
color: black;
height:20px;
width:100px;
margin:10px 20px 10px;
cursor:pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="my_custom_checkout_field">
<input type="hidden" class="subscribe-text-get" name="my_field_name" value="woo-multi-1">
</div>
<br>
<div id="buttons_x3">
<a class="subscribe-button">woo-single-1</a>
<a class="subscribe-button">woo-single-2</a>
<a class="subscribe-button">woo-single-3</a>
<a class="subscribe-button enable">woo-multi-1</a>
<a class="subscribe-button">woo-multi-2</a>
<a class="subscribe-button">woo-top-1</a>
<a class="subscribe-button">woo-top-2</a>
<a class="subscribe-button">woo-top-3</a>
<a class="subscribe-button">woo-special</a>
</div>
<br>
<div id="my_custom_checkout_field">
<input type="text" class="subscribe-text" name="my_field_name" value>
Here is my code on a jsFiddle
Basically I have a row with a couple inputs, like this:
<div class="row collapse-col input-connect" id="custom-field-1">
<div class="col small-4-10"><input type="text" placeholder="Item 1" name="custom_item_1" id="custom-item-1"></div>
<div class="col small-3-10"><input type="number" min="0" max="99999.99" step="0.01" placeholder="Price 1" name="custom_amount_1" id="custom-amount-1"></div>
<div class="col small-3-10"><select name="custom_type_1" id="custom-type-1"><option value="" selected>Options:</option><option value="optdiscount">No Discount</option></select></div>
</div>
I have a script that dynamically adds new rows, which isn't important to show, but just know that it will dynamically add rows so that "custom-field-1" becomes"custom-field-2" and on, and the same with "custom-item-2, "custom-amount-2", and the rest of the attributes that need to be updated. That's all done, that works fine.
I want the "custom-amount-X" inputs to be 'required' if someone starts entering into the "custom-item-X" inputs.
Here is what I have so far:
function formCustomFieldsAllow(e) {
e.preventDefault();
for (var i = 1; document.getElementById("custom-item-"+i); i++) {
var itemEntered = document.getElementById("custom-item-"+i).value;
if (itemEntered) {
document.getElementById("custom-amount-"+i).required = true;
} else {
document.getElementById("custom-amount-"+i).required = false;
}
}
}
document.getElementById('form-button-submit').addEventListener('change', formCustomFieldsAllow);
The idea is that the user clicks on the submit button, this will check to see if any custom-item's are filled and then see if their corrosponding custom-amount's are filled, if it doesn't find a match it will stop the form and make the appropriate custom-amount's 'required'.
My script doesn't work - any help would be appreciated?
Here is a fiddle: https://jsfiddle.net/qa8s4qc4/1/
The approach I'd suggest is the following:
// the function bound as the event-handler for the 'input' event:
function conditionallyRequired(e) {
// e is passed automatically as the first argument via the
// EventTarget.addEventListener() method.
// caching the element upon which the event was triggered:
var trigger = e.target,
// caching the element whose id is equivalent to that of the
// trigger, with the 'item' portion of the id string replaced
// with 'amount':
target = document.getElementById(trigger.id.replace('item', 'amount'));
// setting the required property of the target using an assessment to find
// if the length of the trigger element's value, with leading and trailing
// whitespace removed, is greater than zero; the strings '' and ' ' will
// evaluate to false, whereas 'a' and ' a ' will both evaluate
// to true:
target.required = trigger.value.trim().length > 0;
}
// because rows are added dynamically to the <form> we use event-delegation,
// and bind the event-handler to the ancestor <form> element, although if the
// <form> is loaded dynamically the EventTarget must be bound to the closest
// ancestor that is present in the document on page-load, or be dynamically bound
// when the <form> is added:
document.querySelector('form').addEventListener('input', conditionallyRequired);
.row {
width: 100%;
margin-bottom: 8px;
}
.row .col {
width: 45%;
display: inline-block;
margin-right: 3px;
}
input,
div {
padding: 0;
margin: 0;
}
input {
width: 100%;
}
#form-button-submit {
width: 200px;
max-width: 40%;
min-width: 20px;
}
[required] {
/* adding a style to visually indicate
a required <input> element; adjust
to taste */
border-color: red;
}
<form name="send_price" method="post" action="">
<div class="row" id="custom-field-1">
<div class="col">
<input type="text" placeholder="Item 1" name="custom_item_1" id="custom-item-1">
</div>
<div class="col">
<input type="number" min="0" max="99999.99" step="0.01" placeholder="Price 1" name="custom_amount_1" id="custom-amount-1">
</div>
</div>
<div class="row" id="custom-field-2">
<div class="col">
<input type="text" placeholder="Item 2" name="custom_item_1" id="custom-item-2">
</div>
<div class="col">
<input type="number" min="0" max="99999.99" step="0.01" placeholder="Price 2" name="custom_amount_2" id="custom-amount-2">
</div>
</div>
<input type="submit" id="form-button-submit">
</form>
JS Fiddle demo.
References:
document.getElementById().
document.querySelector().
EventTarget.addEventListener().
String.prototype.replace().
String.prototype.trim().
I believe I've figured it out, here is what I've done:
function formCustomFieldsAllow() {
for (var i = 1; !!document.getElementById("custom-item-"+i); i++) {
var itemEntered = document.getElementById("custom-item-"+i).value;
if (itemEntered) {
document.getElementById("custom-amount-"+i).required = true;
} else {
document.getElementById("custom-amount-"+i).required = false;
}
}
}
document.getElementById('form-button-submit').addEventListener('click', formCustomFieldsAllow);
I changed the eventlistener from change to click, changed the elementId in the for loop to a boolean, and got rid preventDefault.
I have an html page in which I have a textbox (Type your text) and TextArea list. I need to type into the textbox and then click Add button so that whatever is there in textbox goes to my TextArea list. I need to type in this below format in the textbox.
Name=Value
This textbox will be used by the user to quickly add Name Value pairs to the list which is just below that textbox. let's say if we type Hello=World in the above textbox and click add, then in the below list, it should show as
Hello=World
And if we again type ABC=PQR in the same textbox, then in the below list, it should show like this so that means it should keep adding new Name Value pair just below its original entry.
Hello=World
ABC=PQR
But if the syntax is incorrect like if it is not in Name=Value pair then it should not add anything to the list and instead show a pop up that wrong input format. Names and Values can contain only alpha-numeric characters. I also have three more buttons Sort by name, Sort by value and Delete button. Once I click either of these buttons, then it should sort entries in TextArea list using either name or value and delete entries as well. Now I have all above things working fine without any issues.
Here is my jsfiddle. I need to use plain HTML, CSS and Javascript, I don't want to use any library yet as I want to keep it simple as I am still learning. Now I am trying to see whether we can make UI more responsive like the UI should adjust based on what screen size is viewing it. For example, if viewed on a mobile phone (i.e. Android or iPhone), the page should automatically adjust to present the layout in a better way. This also applies to re-sizing the browser on desktop, and viewing the page on a tablet.
What are the changes I need to make in my CSS or HTML to make it more responsive? Any improvements I can make here? Since my UI is very simple so there should be some easy way or some improvements I can make here.
Below is my code:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Test</title>
<style type="text/css">
.main{
background:white;
padding: 35px;
border-radius: 5px;
}
#my-text-box {
font-size: 18px;
height: 1.5em;
width: 585px;
}
#list{
width:585px;
height:300px;
font-size: 18px;
}
.form-section{
overflow:hidden;
width:700px;
}
.fleft{float:left}
.fright{float:left; padding-left:15px;}
.fright button{display:block; margin-bottom:10px;}
html, body {
height: 100%;
font-family: "Calibri";
font-size: 20px;
}
html {
display: table;
margin: auto;
}
body {
display: table-cell;
vertical-align: middle;
background-color: #5C87B2;
}
</style>
<script language="javascript" type="text/javascript">
document.getElementById('add').onclick = addtext;
function addtext() {
var nameValue = document.getElementById('my-text-box').value;
if (/^([a-zA-Z0-9]+=[a-zA-Z0-9]+)$/.test(nameValue)){
var x = document.getElementById("list");
var option = document.createElement("option");
option.text = nameValue;
x.add(option);
}
else
alert('Incorrect Name Value pair format.');
}
document.getElementById('btnDelete').onclick = deleteText;
function deleteText(){
var myList = document.getElementById('list');
var i;
for (i = myList.length - 1; i>=0; i--) {
if (myList.options[i].selected) {
myList.remove(i);
}
}
}
document.getElementById('sortByValue').onclick = sortByValue;
function sortByValue(){
var myList = document.getElementById('list');
var values = new Array();
for (var i=0;i<myList.options.length;i++) {
values[i] = myList.options[i].text;
}
values.sort(function(a, b){
if(a != "" && b != ""){
return a.split('=')[1].localeCompare(b.split('=')[1])
} else {
return 0
}
});
clearList(myList);
fillList(myList, values);
}
document.getElementById('sortByName').onclick = sortByName;
function sortByName(){
var myList = document.getElementById('list');
var values = new Array();
for (var i=0;i<myList.options.length;i++) {
values[i] = myList.options[i].text;
}
values.sort(function (a, b){
if(a != "" && b != ""){
return a.split('=')[0].localeCompare(b.split('=')[0])
} else {
return 0
}
});
clearList(myList);
fillList(myList, values);
}
function clearList(list) {
while (list.options.length > 0) {
list.options[0] = null;
}
}
function fillList(myList, values){
for (var i=0;i<values.length;i++) {
var option = document.createElement("option");
option.text = values[i];
myList.options[i] = option;
}
}
</script>
</head>
<body>
<div class = 'main'>
<h3>Test</h3>
<label for="pair">Type your text</label></br>
<div class="form-section">
<div class="fleft">
<input type='text' id='my-text-box' value="Name=Value" />
</div>
<div class="fright">
<button type="button" id='add' onclick='addtext()'>Add</button>
</div>
</div>
<label for="pairs">Name/Value Pair List</label></br>
<div class="form-section">
<div class="fleft">
<select id="list" multiple></select>
</div>
<div class="fright">
<button type="button" id='sortByName' onclick='sortByName()'>Sort by name</button>
<button type="button" id='sortByValue' onclick='sortByValue()'>Sort by value</button>
<button type="button" id='btnDelete' onclick='deleteText()'>Delete</button>
<button type="button">Show XML</button>
</div>
</div>
</div>
</body>
</html>
W3 have a number of resources on responsive web design:
http://www.w3schools.com/html/html_responsive.asp
http://www.w3schools.com/css/css_responsive_intro.asp
Without using PHP to detect the browser/user agent, your responsive design will typically involve ensuring the site is more fluid and flowing, allowing for changing browser widths (as in the first example above) and/or by delivering differing stylesheets depending on the viewport size and media type in CSS (second example).
I am working on a page with multiple checkboxes, and would like it to return a single div based on any combination of checks. I created a jsfiddle, but even though this is the code on my site that somewhat works, it is not working on jsfiddle:
HTML:
<div id="checkboxes">
<input type="checkbox" id="red" name="color">Red
<input type="checkbox" id="blue" name="color">Blue
<input type="checkbox" id="green" name="color">Green
</div>
<br /><br />
<div id="default" style="display:none;">Show this by default</div><br />
<div id="showred" style="display:none;">This is red</div><br />
<div id="showblue" style="display:none;">This is blue</div><br />
<div id="showgreen" style="display:none;">This is green</div><br />
<div id="showpurple" style="display:none;">This is purple</div>
JS:
$(document).ready(function() {
var r = $('#red');
var b = $('#blue');
var g = $('#green');
var p = r.add(b);
$(r).click(function(){
if ($(r).is(':not(:checked)')) {
$('#showred').show();
$('#showblue').hide();
$('#showgreen').hide();
$('#showpurple').hide();
$('#default').hide();
} else {
$('#showred').hide();
$('#showblue').hide();
$('#showgreen').hide();
$('#showpurple').hide();
$('#default').show();
}
});
$(b).click(function(){
if ($(b).is(':not(:checked)')) {
$('#showred').hide();
$('#showblue').show();
$('#showgreen').hide();
$('#showpurple').hide();
$('#default').hide();
} else {
$('#showred').hide();
$('#showblue').hide();
$('#showgreen').hide();
$('#showpurple').hide();
$('#default').show();
}
});
$(g).click(function(){
if ($(g).is(':not(:checked)')) {
$('#showred').hide();
$('#showblue').hide();
$('#showgreen').show();
$('#showpurple').hide();
$('#default').hide();
} else {
$('#showred').hide();
$('#showblue').hide();
$('#showgreen').hide();
$('#showpurple').hide();
$('#default').show();
}
});
$(p).click(function(){
if ($(r).is(':not(:checked)') && $(b).is(':not(:checked)')) {
$('#showred').hide();
$('#showblue').hide();
$('#showgreen').hide();
$('#showpurple').show();
$('#default').hide();
} else {
$('#showred').hide();
$('#showblue').hide();
$('#showgreen').hide();
$('#showpurple').hide();
$('#default').show();
}
});
});
http://jsfiddle.net/robert316/tu0o1z0s/13/
I would really appreciate any help to get this working correctly, what I would like to happen is:
User clicks "Red" -> Display red div
User clicks "Blue" -> Display blue div
User clicks "Red" and "Blue" -> Only display purple div (no red or blue)
I would also like to fix the behavior that when a user unchecks a box it reverts back to the default div display, ideally, if no boxes are selected it should show default div, and always display the div based on the combination of checkboxes.
Thank you very much for any help with this.
In case anyone finds this question, here is the final code I used to be able to show single divs from multiple checkbox selections:
Code Snippet:
$(document).ready(function () {
// select checkboxes by name
var packages = $("input[name='cc']");
// set main div id
var packageDiv = $("#listings");
// bind to change event
packages.change(function () {
// empty array
var idArr = [];
// get the checked values
var checked = $("input[name='cc']:checked");
// loop and build array
checked.each(function () {
idArr.push($(this).prop("id"));
});
// remove whitespace from multiple checkboxes array
var trimArray = idArr.join("");
toggleShowHide(trimArray, packageDiv);
});
});
function toggleShowHide(arr, elem) {
var arrLen = arr.length;
// clear last selection when unchecking boxes
$(".hide-me").hide();
// set default if array is empty
if (arrLen < 1 ){
setDefault(elem);
}
// run the show hide based on array of selection
for(i = 0; i < arrLen; i++) {
// set the name for the selected div
var temp = "#" + arr + "_div_id";
$(temp).show();
$("#default").hide();
}
// unhide
elem.show();
}
function setDefault(elem){
$("#default").show();
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<!-- Checkbox -->
<input type="checkbox" id="i" name="cc" value="i_div_id" data-ref="i_div_id" />
<label>I</label>
<input type="checkbox" id="c" name="cc" value="c_div_id" data-ref="c_div_id" />
<label>C</label>
<input type="checkbox" id="p" name="cc" value="p_div_id" data-ref="p_div_id" />
<label>P</label>
<br />
<br />
<br />
<br />
<!-- Loaded/hidden content div-->
<div id="listings">
<div class="hide-me" id="default"><strong>This is default copy on page</strong></div>
<div class="hide-me" id="i_div_id" style="display:none;">You ordered: <strong>I Package</strong></div>
<div class="hide-me" id="c_div_id" style="display:none;">You ordered: <strong>C Package</strong></div>
<div class="hide-me" id="p_div_id" style="display:none;">You ordered: <strong>P Package</strong></div>
<div class="hide-me" id="ic_div_id" style="display:none;">You ordered: <strong>I-C Package</strong></div>
<div class="hide-me" id="ip_div_id" style="display:none;">You ordered: <strong>I-P Package</strong></div>
<div class="hide-me" id="cp_div_id" style="display:none;">You ordered: <strong>C-P Package</strong></div>
<div class="hide-me" id="icp_div_id" style="display:none;">You ordered: <strong>I-C-P Package</strong></div>
</div>
Rather than creating a color div for each color, why not use a single color-div and just change its css properties / classes? This would eliminate the need for extraneous show-hide / if-else logic when checkbox selections are made.
This snippet illustrates how you can "return a div based on any combination of checks" - it relies on css to handle setting the properties of a target div but you could very well handle all of this in jQuery as well.
Example:
$(document).ready(function() {
// checkboxes with name 'color', 'color-div', and reset button
var colors = $("input[name='color']");
var colorDiv = $("#color-div");
var reset = $("#reset");
// bind to 'colors' change event:
colors.change(function() {
// empty array to hold the color ids
var idArr = [];
// get the checked colors
var checked = $("input[name='color']:checked");
// loop and build array
checked.each(function() {
idArr.push($(this).prop("id"));
});
// function below
toggleColors(idArr, colorDiv);
});
// reset to defaults
$("#reset").click(function() {
// function below
setDefault(colorDiv);
// back to hidden
colorDiv.hide();
// uncheck the check boxes
$("input[name='color']:checked").removeAttr("checked");
});
});
/// function to add color css classes based on checkbox id array
function toggleColors(arr, elem) {
var arrLen = arr.length;
// set default if array is empty
if (arrLen < 1) {
setDefault(elem);
return;
};
// remove classes, add classes
elem.removeClass();
for (i = 0; i < arrLen; i++) {
elem.addClass(arr[i]);
}
// unhide
elem.show();
}
/// set the color div to "default"
function setDefault(elem) {
elem.removeClass();
elem.addClass("default");
}
/*
using css to handle color and content change!
this will prevent you from having to write complicated "if-else"
jQuery blocks.
*/
#color-div {
height: 100px;
width: 100px;
border: solid 2px #d3d3d3;
margin-bottom: 20px;
}
.default,
.default:after {
background-color: #fff;
content: "Please select a color";
}
.yellow,
.yellow:after {
background-color: yellow;
content: "I am Yellow!";
}
.red,
.red:after {
background-color: red;
content: "I am Red!";
}
.blue,
.blue:after {
background-color: blue;
content: "I am Blue!";
}
.yellow.blue,
.yellow.blue:after {
background-color: green;
content: "I am Green!";
}
.yellow.red,
.yellow.red:after {
background-color: orange;
content: "I am Orange!";
}
.blue.red,
.blue.red:after {
background-color: purple;
content: "I am Purple!";
}
.blue.red.yellow,
.blue.red.yellow:after {
background-color: brown;
content: "I am Brown :(";
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<div id="checkboxes">
<input type="checkbox" id="red" name="color" />
<label>Red</label>
<input type="checkbox" id="blue" name="color" />
<label>Blue</label>
<input type="checkbox" id="yellow" name="color" />
<label>Yellow</label>
</div>
<br />
<br />
<div id="color-div" style="display:none;"></div>
<button id="reset">Reset</button>
If css classes isn't your bag, you could essentially handle the same "toggling" through building an equivalent javascript object.
[Edit - Using a Div for Each Checkbox]
Since you have control over the properties of the checkboxes, you should use one of these properties to tie to the element being loaded by your query. You should also try to avoid using id for more than one element. For example if you have this:
<!-- Checkbox -->
<input type="checkbox" id="burgers" name="color" />
<!-- Loaded/hidden content div-->
<div id="burgerDiv" style="display:none;"></div>
I would suggest adding to your checkbox either a data-* or value attribute that ties to the id of the hidden div. I'm not sure how well the data attribute is supported in all browsers, however. Example:
<!-- Checkbox -->
<input type="checkbox" id="burgers" name="color" value="burgersDiv" data-ref="burgersDiv" />
... Then it's pretty easy to hide/show the div:
fiddle