I'm trying to show and hide divs using a button. This code works just fine in Firefox and IE, but for some reason it's not working in Chrome or Safari. The site is using Bootstrap.
function newAdd(addId, rowId) {
var add = "#" + addId.id;
var row = "#" + rowId.id;
var nextNum = Number(add.charAt(4));
nextNum++;
var next = "#add" + nextNum;
$(add).addClass("dontShow");
$(next).removeClass("dontShow");
$(row).removeClass("dontShow");
}
.dontShow {
display: none;
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="row" id="row1">
<div class="col-sm-12 col-md-12">
<div class="form-group">
<label for="000-000">Item Name:</label>
<br />
<input type="text" class="form-control" value="">
</div>
</div>
</div>
<div class="row" id="add1">
<div class="col-sm-1 col-md-1"> </div>
<div class="col-sm-2 col-md-2">
<a onclick="newAdd(add1,row2)">
<button class="btn" style="text-decoration: none; color: #ffffff;" id="add1" type="button">Add another item?</button>
</a>
</div>
<div class="col-sm-9 col-md-9"> </div>
</div>
<div class="row" id="row2">
<div class="col-sm-12 col-md-12">
<div class="form-group">
<label for="000-000">Item Name:</label>
<br />
<input type="text" class="form-control" value="">
</div>
</div>
</div>
<div class="row" id="add2">
<div class="col-sm-1 col-md-1"> </div>
<div class="col-sm-2 col-md-2">
<a onclick="newAdd(add1,row2)">
<button class="btn" style="text-decoration: none; color: #ffffff;" id="add1" type="button">Add another item?</button>
</a>
</div>
<div class="col-sm-9 col-md-9"> </div>
</div>
<div class="row" id="row3">
<div class="col-sm-12 col-md-12">
<div class="form-group">
<label for="000-000">Item Name:</label>
<br />
<input type="text" class="form-control" value="">
</div>
</div>
</div>
So what should happen is, the user sees the first row and first button and everything else is hidden. They fill out the first row, then click on the button. When clicked, the button goes away and the next row and next button appear showing two rows with one add button at the bottom. If they click it again, then the last row should appear and the add button goes away completely.
There are 2 solutions possible to achieve the result.
Solution 1
There are 2 updates that need to be done in your code
In HTML
There should be quotes for stirngs like newAdd('add1','row2')
In JS, no need for addId.id
var add = "#" + addId;
Solution 2
No html update. Only in JS, update
var add = "#" + addId.id;
to
var add = "#" + addId[0].id;
Solution 1 - You are passing the id of the element and accessing it in javascript.
Solution 2 - You are passing the HTML Object Collection and then accessing the element and its id property.
Now which solution to go for?
In case you only need Id, you can go for solution 1, as it makes no sense to pass the complete collection just to extract the id which can otherwise be send with the same parameters with just quotes around them.
However, if you need to get some other properties of the element, then go for solution 2.
The reason why it doesn't work in Chrome or Safari is that add1, which you are passing to the function, i.e.
addNew(add1, row1);
does not refer to a single element, but to an element collection:
Why? Because you have multiple elements with the same ID. IDs have to be unique!
Firefox on the other hand simply takes the first element with that ID (which is what I would have expected).
There are a couple of ways to solve this, one of them shown in the other answer, but you should definitely ensure that you are only using unique IDs. I highly recommend to read up on binding event handlers with jQuery: http://learn.jquery.com/events/event-basics/
Related
I want to target a parent div using document.querySelectorAll. But not if the div contains a nested div, with a particular class.
For example, in the example below, I want to grab the parent first and last floatContainer divs. But not this second, because it contains dropdown-container class.
document.querySelectorAll(".ej-form-field:not([dropdown-container])") does not seem to be working.
console.log(document.querySelectorAll(".ej-form-field:not([dropdown-container])"))
<!-- GRAB THIS -->
<div id="floatContainer" class="ej-form-field">
<label for="floatField">First name</label>
<div class="input-container">
<input id="floatField" class="ej-form-field-input-textbox" type="text">
</div>
</div>
<!-- NOT THIS -->
<div id="floatContainer" class="ej-form-field">
<label for="floatField">Last name</label>
<div class="dropdown-container input-container">
<input id="floatField" class="ej-form-field-input-textbox" type="text">
</div>
</div>
<!-- GRAB THIS -->
<div id="floatContainer" class="ej-form-field">
<label for="floatField">Telephone</label>
<div class="input-container">
<input id="floatField" class="ej-form-field-input-textbox" type="text">
</div>
</div>
this code solve your problem.
console.log(document.querySelectorAll(".ej-form-field>div:not(.dropdown-container)"))
you must target a specific class not an attribute, ie:
document.querySelectorAll(".ej-form-field:not(.dropdown-container))
I also found this option, which seemed to work as well:
document.querySelectorAll("div.ej-form-field + :not(.dropdown-container)")
Am working on the frontend part of an application whereby I have
some form inputs (wrapped in divs). Each div has a button called
Add Beneficiary. Basically when the user clicks on the button, the div
below it should be displayed (which is hidden by default) and the
sequence continues (each button on a div clicked the div below it
displays).
On the button of each div I have writen some logic whereby on click event
a function called addBeneficiary is triggered. I parse the id of the
button clicked. Next in the function I manipulate the DOM by reaching
out to the parent div and displaying it but the logic does not
work.
~ Kindly assist?
Markup
<!--Person One-->
<div class="container mg-t-30" id="beneficiary1">
<div class="row col-11 mx-auto">
<div class="col-12">
<div class="row">
<div class="col-6">
<label> Category</label>
<input type="email" class="form-control" placeholder="Enter email">
</div>
<div class="col-6">
<label>Family Size</label>
<input type="password" class="form-control" placeholder="Password">
</div>
</div>
<div class="row">
<div class="col-12">
<button class="float-right btn btn-primary" id="btnBen1" onclick="addBeneficiary(this.id)">Add Beneficiary</button>
</div>
</div>
</div>
</div>
</div>
<!--Person Two-->
<div class="container mg-t-30" style="display:none;" id="beneficiary1">
<div class="row col-11 mx-auto">
<div class="col-12">
<div class="row">
<div class="col-6">
<label> Category</label>
<input type="email" class="form-control" placeholder="Enter email">
</div>
<div class="col-6">
<label>Family Size</label>
<input type="password" class="form-control" placeholder="Password">
</div>
</div>
<div class="row">
<div class="col-12">
<button class="float-right btn btn-primary" id="btnBen1" onclick="addBeneficiary(this.id)">Add Beneficiary</button>
</div>
</div>
</div>
</div>
</div>
Logic
function addBeneficiary(beneficiary){
let check = $('#' + beneficiary).parents('div').last().prop('id');
//console.log(check);
$("check").css("display", "block");
}
Its not working because both parents div id is "beneficiary1". And you can't use same id with multiple tag. It should be unique like beneficiary1, beneficiary2 & so on... And also little bit change into your script.
function addBeneficiary(beneficiary){
let check = $('#' + beneficiary).parents('div').next('div');
//console.log(check);
check.css("display", "block");
}
jsfiddle https://jsfiddle.net/y2mva6es/
In my site, everything is working well on the desktop version but when I switch to the mobile version a button only works once. It doesn't do anything after 1 click.
If I press enter it works fine, but pressing on the button won't trigger the button again. I specifically don't want my page to reload.
onClick not working on mobile (touch)
This answer involves reloading the page.
$("#quiz").on('touchstart click', 'button', function(e){
e.preventDefault();
});
<h1 class="title">Quote Game!</h1>
<div class="container">
<form id="quiz" name="quiz" autocomplete="off"><br>
<container class="cont1">
<p class="questionp">Which hero does this quote belong to? </p>
<div class="row">
<!--<div class="form-group float-label-control">-->
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
<p class="question" id="questionquote"></p>
</div>
<div class="col-6 col-lg-2 col-md-2 col-sm-2 col-xs-2 ">
<p id = "number_correct" class="green"></p>
</div>
<script class="score">document.getElementById("number_correct").innerHTML = "Your Score: " + correct;</script>
<div class="col-6 col-lg-2 col-md-2 col-sm-2 col-xs-2">
<!-- <img src="transparent.gif" height="90" width="90" class="pull-right"> penguin picture-->
</div>
<input class="form-control" id="question1" name="question1" placeholder="Hero Name" onclick="IsEmpty();" >
<br> </br>
<!--<input class="answer" id="question1" name="question1"></input><br> </br>-->
<div class="col-6 col-lg-2 col-md-2 col-sm-2 col-xs-2">
<!--<input id="button" class="btn btn-primary" type="submit" value="Check" onclick = "check(); ">-->
<button id ="button" value="Check" class="btn btn-primary " onclick = "check(); ">Check</button>
</div>
</div>
</container>
</form>
<div class="text-center">
<img id="result" class="correct_answer" src="" height="350" width="90%">
</div>
</div>
Tried your code under Chrome 68 for Android and the button is working everytime. However, a few hints:
Use addEventListener (or jQuery.on()) rather than using inline javascript in HTML.
If what you want is to not submit the form after running your code, you can use return false instead of e.preventDefault().
I don't get the point on attaching an event handler to the form only to filter it to the button and adding another inline javascript function to the button itself. If what you want is to call two different functions at once, use one function to call both.
try setting button type to button (instead of submit)
that way the button won't be disabled by browser after a click
<button type="button" id ="button" value="Check" class="btn btn-primary " >Check</button>
also, e.preventDefault is not needed anymore and you'll have to submit this form with js if you wan't to
i have a, in my opinion really tricky form. The form changes div's, hidden fields & id's on every reload. and i cant find a pattern how it changes.
here's an example for the class .box.box500:
<div class="box box500" style="float:left;display:none;">
<span class="errorText"></span>
<br>
<input id="czoyNToiaWhfYlNEaDg0ZGNkVi00bUxtckxLZ2cuLiI7" type="text" name="czoyNToiaWhfYlNEaDg0ZGNkVi00bUxtckxLZ2cuLiI7" value="">
</div>
<div id="boxFirma" style="display: none;margin-top: 20px;">
<div class="" style="float:left;left;margin-left:10px;display:none;">
<a name="personal"></a>
<div style="overflow:hidden; margin-top: 20px;">
<div class="box box500 " style="display:none;">
<input id="czoyNToiaWhfYlNEaDg0ZGNkUjh3d2tOOFJFd2cuLiI7" type="text" value="" name="czoyNToiaWhfYlNEaDg0ZGNkUjh3d2tOOFJFd2cuLiI7">
<br>
<span class="errorText"></span>
</div>
<div class="box box500 " style="float: left;">
<input id="czoyNToiaWhfYlNEaDg0ZGNlVFpMRjFVWjZicEEuLiI7" type="hidden" value="" name="czoyNToiaWhfYlNEaDg0ZGNlVFpMRjFVWjZicEEuLiI7">
<input id="czoyNToiaVhxemVtUGRZOHluMkNxdE9pWEd1Y1EuLiI7" type="text" value="" name="czoyNToiaVhxemVtUGRZOHluMkNxdE9pWEd1Y1EuLiI7">
<br>
<span class="errorText"></span>
</div>
<div class="box box502 " style="float: left;margin-left: 20px;">
<input id="czoxMzoiaXgtQTNQT3VWVmprLiI7" type="text" value="" name="czoxMzoiaXgtQTNQT3VWVmprLiI7">
<br>
<span class="errorText"></span>
</div>
</div>
sometimes the first hidden div is there, and sometimes not. the id changes on every reload. The hidden input is sometimes the first child, sometimes the second.also the div, sometimes on the frist positionen sometimes on the second. i've really no idea how to identify the input fields.
is it maybe possible to select a input filed like:
this.sendKeys('.box.box500:nth-child(2):style="float: left;" > input:nth-child(2):type="text"', 'text');
Could you not use the selector:
this.sendKeys('div.box.box500 input[type="text"]:not([style*="display: none"])', ...);
I believe this would find all of the specific inputs type="text" regardless of the order on the page.
this is working:
this.sendKeys('div.box.box500:not([style*="none"]) input[type="text"]', ...);
I'm hitting a scoping issue when using the ng-repeat functionality of AngularJS.
please see the plnkr
I have an array of objects 'boxCollection' and a list of items 'itemCollection' which I display in a drop down.
$scope.boxCollection = [];
$scope.itemCollection =
[
{name: 'item1'},
{name: 'item2'},
{name: 'item3'}
];
Now I have my view as
<script type="text/ng-template" id="addBox.html">
<div class="box-controls">
<span class="glyphicon glyphicon-plus pull-left" ng-click="addBox()"></span>
<span class="glyphicon glyphicon-minus pull-left" ng-class="{disable_div:boxCollection.length < 2} " ng-click="removeBox($index)"></span>
</div>
<div class="box-container">
<div class="box-details">
<div class="boxItem">
<form class="form-horizontal">
<div class="form-group">
<label class="control-label col-md-3">Item</label>
<div class="col-md-8">
<select class="form-control" ng-options="item.name for item in itemCollection" ng-model="boxCollection[$index].item" ng-disabled="false">
<option value=""> None </option>
</select>
</div>
</div>
<div class=" form-group ">
<label class="control-label col-md-3">Item Desc</label>
<div class="col-md-8">
<input type="text " class="form-control " ng-model="boxCollection[$index].item.desc ">
</div>
</div>
</form>
</div>
</div>
<div class="clearfix "></div>
</div>
</script>
The view is wrapped in a script tag with an id and is called with an ng-repeat.
I have one function to add a box element into my view 'addBox()'. It generates one entry in 'boxCollection' array and another entry in 'boxTmplList' array. 'boxTmplList' is responsible for showing the views.
Now if you select let's say 'item1' from the drop down in box1 and add a value in the input field, add another box in the view using the '+' button and select 'item1' again in the another instance. It displays the value of input field 1 in the input field 2.
enter image description here
On further analysis I found that Angular tracks the objects with similar 'item' name using the same $hashkey.
I'm using a workaround by adding another property to the object 'boxCollection[$index].itemDesc' instead of 'boxCollection[$index].item.desc' and then later on modify the object using another function, but I feel that's not the most efficient way.
Any insight on this would be greatly appreciated.
You need to change ng-model="boxCollection[$index].item" to ng-model="boxCollection[$index].item.name" , like as-
<select class="form-control" ng-options="item.name for item in itemCollection" ng-model="boxCollection[$index].item.name" ng-disabled="false">
Working Plnkr
Change ng-model="boxCollection[$index].item.desc" to ng-model="itemCollection[$index].name".
<div class=" form-group ">
<label class="control-label col-md-3">Item Desc</label>
<div class="col-md-8">
<input type="text " class="form-control " ng-model="itemCollection[$index].name">
</div>
</div>