How to get the index of an element without 'this'? - javascript

I have a form that looks kind of like this:
<div>
<div class="contact">
<h1>Person's name</h1>
<!-- more stuff goes here -->
<form method="post" action="myurl">
<input type="submit" value="go" />
</form>
</div>
<div class="contact">
<h1>Another name</h1>
<!-- more stuff goes here -->
<form method="post" action="myOtherUrl">
<input type="submit" value="go" />
</form>
</div>
</div>
I'm using jQuery to capture the form's submit event and need to get the index of the div containing the button that submitted it. Normally I'd use jQuery's index() function like so:
var i = $(this).parents('.contact').index(this);
Unfortunately, the this operator in this case refers to the form that is being submitted. I think there's probably something simple I'm missing, but my mind's drawing a blank on this one.

Keep it simple:
var parent = $(this).closest('div.contact'); // get containing DIV
var i = $('div.contact').index(parent); // get index relative to the rest

var i = $(this).parents('.contact:first').prevAll('.contract').length

Related

How to manipulate a API endpoint address based on user input

I am playing around with some HTML and JavaScript with the end goal of creating a simple website that displays the current weather. I haven't used API's before and I have limited knowledge of JavaScript so this might be a very bad question. Can I change the endpoint address based on a user input?
I have written some front-end which displays a simple form.
<section id="weather">
<div id="nav">
<div id="locate">
<div id="container">
<form action="index.js">
<label for="location">Location:</label>
<input type="text" id="location" name="location" required>
<input type="submit" value="Let's Go!">
</form>
</div>
</div>
<div id="output">
<div id="container">
<!-- Output of API -->
</div>
</div>
</div>
</section>
I was thinking that this could run a JavaScript file that gathers the input of the form HTML file and do something like this:
const location = document.getElementById(location)
http://api.openweathermap.org/data/2.5/weather?q=${location}&APPID=API
I tried programming something to do this but as I have limited knowledge of both javascript and API's I keep failing. Before I was a lot of time on this can someone tell me if this is even possible?
By the way I have set-up an API key but I just haven't shown it.
Thanks,
mrt
So this is just a very lengthy way to do it so that you can understand each step
Step 1: First you want to get access to the input element:
const locationInput = document.getElementById("location");
Step 2: Then you want to grab the value of that input element
const locationValue = locationInput.value;
Step 3: Then you'd want to use that value in the URL
const url = http://api.openweathermap.org/data/2.5/weather?q=${locationValue}&APPID=API
function fetchAPIData() {
const locationInput = document.getElementById('location');
const locationValue = locationInput.value;
const url = `http://api.openweathermap.org/data/2.5/weather?q=${locationValue}&APPID=API`
// do the URL Request
}
document.addEventListener('DOMContentLoaded', () => {
document.querySelector('input[type=submit]').addEventListener('click', fetchAPIData);
});
<section id="weather">
<div id="nav">
<div id="locate">
<div id="container">
<form action="index.js">
<label for="location">Location:</label>
<input type="text" id="location" name="location" required>
<input type="submit" value="Let's Go!">
</form>
</div>
</div>
<div id="output">
<div id="container">
<!-- Output of API -->
</div>
</div>
</div>
</section>
A much shorter way would be:
const url = `http://api.openweathermap.org/data/2.5/weather?q=${document.querySelector("#location").value}&APPID=API`;

How to stop my page from reseting after the page is submited

I have a code, who helps me switch between forms, however, when I submit the form, the page will reset and display first(default) tab again. Could anyone help me understand how I can make it so the tab I submit the form from stays there if the submision fails or even if the submision was successfull?
Forms are switching using a little JS code and are submited from a PHP POST method form.
Please find the code below:
Javascript responsible for switching between tabs:
function onTabClick(event) {
let activeTabs = document.querySelectorAll('.active');
// deactivate existing active tab
for (let i = 0; i < activeTabs.length; i++) {
activeTabs[i].className = activeTabs[i].className.replace('active', '');
}
// activate new tab
event.target.parentElement.className += 'active';
document.getElementById(event.target.href.split('#')[1]).className += 'active';
}
const elements = document.getElementsByClassName('nav-tab-element');
for (let i = 0; i < elements.length; i++) {
elements[i].addEventListener('click', onTabClick, false);
}
CSS:
.tab-content {
display: none;
}
.tab-content.active {
display: block;
}
And here is the HTML forms:
<body>
<header>
<h1 class="main-header">
Add a New Product
</h1>
</header>
<main>
<ul id="nav-tab" class="nav">
<li class="active">
<a class="nav-tab-element" href="#books">Books</a>
</li>
<li>
<a class="nav-tab-element" href="#dvds">DVD's</a>
</li>
<li>
<a class="nav-tab-element" href="#furniture">Furniture</a>
</li>
</ul>
<form method="POST">
<div class="tab-content active" id="books">
<div class="book-tab">
<input type="text" name="sku" placeholder="test form for books" autocomplete="off">
</div>
<div class="btn">
<input type="submit" value="Submit">
</div>
</div>
</form>
<form method="POST">
<div class="tab-content " id="dvds">
<div class="dvd-tab">
<input type="text" name="sku" placeholder="test form for DVD" autocomplete="off">
</div>
<div class="btn">
<input type="submit" value="Submit">
</div>
</div>
</form>
<form method="POST">
<div class="tab-content " id="furniture">
<div class="furniture-tab">
<input type="text" name="sku" placeholder="test form for furniture" autocomplete="off">
</div>
<div class="btn">
<input type="submit" value="Submit">
</div>
</div>
</form>
</main>
<script src="main.js"></script>
</body>
Clicking submit submits the form data to the page given in the action attribute in form. If you don't put this attribute in (as you have not done) the default is to submit to the current page.
To fix the issue you have, I would suggest that rather than using vanilla form submit, you do you submission via ajax. Making an ajax call is quite simple in jQuery, so I recommend you look into that.
There is an event that is triggered when you send a form. You can prevent your page to reload doing the following:
event.preventDefault()
you can find more about here: https://www.w3schools.com/jsref/event_preventdefault.asp
or here https://www.w3schools.com/jquery/event_preventdefault.asp
All you have to do is add event.preventDefault() to the first line of your onTabClick(event) function. After you preventDefault you can run whatever logic you want right there.
The way vanilla html/js interact is: On form submission, the page attempts to send the info to a server and then it refreshes to update with new information. The rise of SPAs has shifted the desired behavior, and you need to override the browser default behavior to stop the refresh.
Adding Ajax/Axios would work as most of those API libraries have built in functions to override the default, but it is not necessary.

How to clear a form within an angular app that appears on click?

I have seen several tutorials on how to clear angular (version 1.4.0) forms, however.. none of them seem to work in my case. I am puzzled. The following form is display: none; to begin with, but comes into existence when the 'Add' button is clicked.
<div id="..." class="displayNone ...">
<form class="..." name="addFooForm">
<div class="...">
<div class="row">
<div class="col-md-offset-3 col-md-6">
<br>
<div class="form-group">
<label>Foos</label>
<input type="text" class="..." id="..." ng-model="foo.value">
</div>
</div>
</div>
</div>
<div class="...">
...
<input type="button" value="Cancel" class="..." ng-click="resetAddFooForm()">
</div>
</form>
</div>
And in my controller, I have the following.
$scope.resetAddFooForm = function () {
// XXX:
console.log('about to reset the form');
$scope.foo = {};
// $scope.addFooForm.$setValidity();
// $scope.addFooForm.$setPristine();
// $scope.addFooForm.$setUntouched();
};
But, although the console.log message is being displayed. The form field is not being cleared. I have have even tried doing it directly as follows.
$scope.resetAddFooForm = function () {
// XXX:
console.log('about to reset the form');
$scope.fooVal = '';
// $scope.addFooForm.$setValidity();
// $scope.addFooForm.$setPristine();
// $scope.addFooForm.$setUntouched();
};
.. with the above html modified as follows.
<div class="form-group">
<label>Foos</label>
<input type="text" class="..." id="foo" ng-model="fooVal">
</div>
But nothing seems to be working. Is it perhaps because the $scope is different due to the form being dynamically inserted? But then how do I tackle that?
I just want to be able to clear the fields (and also clear the angular properties like dirty/pristine, etc) of this dynamically generated form.
Update:
I was able to send this from the html back to the controller, and then use it do what I wanted. So it appears that the problem may actually be to do with differing scopes.
<div class="...">
...
<input type="button" value="Cancel" class="..." ng-click="resetAddFooForm(this)">
</div>
And then have this retrieved the controller.
$scope.resetAddFooForm = function (elem) {
elem.foo = {};
elem.$setValidity();
elem.$setPristine();
elem.$setUntouched();
};
Any hints? Why do I need to send this, when I should really be able to simply use $scope. Why doesn't that work?
Initially declare empty object on your controller
$scope.foo = {}
then try empty it on reset
You can manually reset fields value.

find form id div is in

Bit of a weird question. I have got a form and inside this form the controls are div's with onClick events instead of buttons. I can't use buttons as I can't use page reloads, instead I have to send all data using ajax.
Plus half of the buttons just increase counters, below is my code. How would I go about using JavaScript to find the form ID that the element clicked on is in. So as an example:
<form id="20">
...
<div onClick="doSomething(this)">
...
</form>
The doSomething will then keep moving up levels of parents or something like that until it finds the form, and then a variable will have the form id assigned to it.
<form id="50">
<div class="image_container background">
<div style="text-align:center; font-size:12px;">image1</div>
<input type="hidden" id="imgId" value="50" />
<div class="image" style="background-image:url(images/image3.JPG);"></div>
<div class="selected_product">
<span>KR</span>
</div>
<input type="hidden" id="applied_products" value="KR" />
</div>
<div class="controls_container background">
<div id="selected">KR</div>
<a class="button arrow expandProducts">
<span>
<div class="products">
<span>KR</span>
<span>A5</span>
<span>CC</span>
</div>
</span>
</a>
<hr />
<span class="button plus" onClick="sale(this)"></span>
<input type="text" id="amount" disabled="disabled" value="0"/>
<span class="button minus"></span>
<hr />
<input type="text" id="total" disabled="disabled" value="£0"/>
</div>
</form>
Your doSomething function could continue navigating through it's parents until it finds a form, like so:
function doSomething( elem )
{
var parent = elem.parentNode;
if( parent && parent.tagName != 'FORM' )
{
parent = doSomething(parent);
}
return parent.id;
}
Also, if you use <button type="button">...</button> it won't cause a page refresh, since the default button type is submit.
If you are going straight javascript and not jquery or some other library. Each DOM Element has a parentNode Property
var elm = document.getElementById(yourDivId);
var parent = elm.parentNode;
From there you can cycle through each parent, until you get back to the form element and then pull out the id.
How about something like that:
function handler(target) {
var parent = target.parentNode;
// loop until parent is a form or browser crashes :)
while (parent.tagName != 'FORM') {
parent = parent.parentNode;
}
var formId = parent.id; // the id you wanted
// do stuff
}

innerHTML won't change element

I have an div element ("main") on my page who's contents changes back and forth between two different screens (their id's are "readout" and "num"), the contents of which are stored as hidden div elements (using display:none). Each screen has a button which sets mainto the other hidden div.
Since I struggled to get javascript to put num.innerHTML into main on load, I've ended up putting virtually identical content to num (with a different form name) into main:
<p>Number of Passengers per Carriage:</p>
<form method="post" action="javascript:void(0);" name="applesForm" onSubmit="setPassengers();">
<input type="text" name="numApples" id="numPassengers" />
<br/><br/>
<input type="submit" name="Submit" value="OK!"/>
</form>
setPassengers() successfully sets main's contents to readout. readout successfully sets main's contents to num (virtually identical to the original content of main). But then it won't go back to readout.
Here are setPassengers() and setPassengersAgain(), which is the same but for a different form name:
function setPassengers()
{
passengers=document.applesForm.numPassengers.value;
document.getElementById('main').innerHTML=readout.innerHTML;
}
function setPassengersAgain()
{
passengers=document.applesFormAgain.numPassengers.value;
document.getElementById('main').innerHTML=readout.innerHTML;
}
So my question is:
1)Why isn't num changing to readout?
2)Is there a way to load num straight away on page load so as to simplify the code?
EDIT: I can use onload, which means that num is the only bit that's broken...
EDIT 2: Here are the hidden div's:
<div id="readout" style="display:none">
<p>Throughput per hour:</p>
<p id="output">--</p>
<p>Average Dispatch Time:</p>
<p id="avDisTime">--</p>
<form method="post" action="javascript:void(0);" name="dispatchForm" onSubmit="dispatch();i++;">
<input type="submit" name="Submit" value="Press on Dispatch!"/>
</form>
<br/>
<form method="post" action="javascript:void(0);" name="resetTimesForm" onSubmit="resetTimes();">
<input type="submit" name="Submit" value="Reset Times"/>
</form>
<form method="post" action="javascript:void(0);" name="resetAllForm" onSubmit="resetAll();">
<input type="submit" name="Submit" value="Reset All"/>
</form>
</div>
<!--back to default page-->
<div id="num" style="display:none">
<p>Number of Passengers per Carriage:</p>
<form method="post" action="javascript:void(0);" name="applesFormAgain" onSubmit="setPassengersAgain();">
<input type="text" name="numApples" id="numPassengers" />
<br/><br/>
<input type="submit" name="Submit" value="OK!"/>
</form>
</div>
You didn't post your HTML code, so I don't know how it looks like, but you could use somethin like:
HTML:
<button id="changeMain">Change #main</button>
<div id="main">
<div id="readout" class="screen show">
Readout
</div>
<div id="num" class="screen">
Num
</div>
</div>
CSS:
#main>.screen{display:none;}
#main>.screen.show{display:block;}
JavaScript:
var els=[document.getElementById('readout'),document.getElementById('num')],current;
function addClass(el,c){
var arr=el.className.split(' ');
if(arr.indexOf(c)>-1){return;}
arr.push(c);
el.className=arr.join(' ');
}
function delClass(el,c){
var arr=el.className.split(' ');
var i=arr.indexOf(c);
if(i===-1){return;}
arr.splice(i,1);
el.className=arr.join(' ');
}
document.getElementById('changeMain').onclick=function(){
if(!current){
for(var i=0,l=els.length;i<l;i++){
if(els[i].className.indexOf('show')>-1){
current=i;
break;
}
}
}
delClass(els[current],'show');
current=(current+1)%els.length;
addClass(els[current],'show');
}
DEMO: http://jsfiddle.net/CUgqh/
Explanation:
If you want some content insode #main, you should place inside it (hidden or shown). Then, we hide all .screen with #main>.screen{display:none;} except .screen.show: #main>.screen.show{display:block;}.
Then, JavaScript code:
First we create an array with the elements:
var els=[document.getElementById('readout'),document.getElementById('num')],current;
And a function which adds/removes a class c to the element el:
function addClass(el,c){
var arr=el.className.split(' ');
if(arr.indexOf(c)>-1){return;}
arr.push(c);
el.className=arr.join(' ');
}
function delClass(el,c){
var arr=el.className.split(' ');
var i=arr.indexOf(c);
if(i===-1){return;}
arr.splice(i,1);
el.className=arr.join(' ');
}
And we create an event to the button:
document.getElementById('changeMain').onclick=function(){
if(!current){
for(var i=0,l=els.length;i<l;i++){
if(els[i].className.indexOf('show')>-1){
current=i;
break;
}
}
}
delClass(els[current],'show');
current=(current+1)%els.length;
addClass(els[current],'show');
}
The code above does:
If it's the first time the current els' index (current) is undefined, we search which element has the class show by default.
It removes the class show to the current shown element, so it disappears.
It adds 1 to current (or it becomes 0 if it was the last els' element
It add class show to the current element, so it appears.

Categories