I am attempting to create a global array in javascript to use in multiple functions. The array does not display when attempting to callback.
var iListCount = 0;
var arrListItems = new Array;
function addItem(){
var list = document.getElementById('spanUser');
var sText = document.getElementById('item-text').value;
if (isNaN(iListCount)){
iListCount = 0;
}
if (sText != "") {
iListCount++;
arrListItems[iListCount] = sText;
list.innerHTML = list.innerHTML+"<li class='list-group-item' id='lis"+iListCount+"'>"+sText+"</li>";
document.getElementById("item-text").value = "";
} else {
document.getElementById("item-text").focus();
alert(arrListItems[1]);
}
}
Edit: Html
<div class="form-group" style="margin-bottom:65px" id="header-div">
<label class="txt-sub pull-left">_items</label>
</div>
<div style="margin-left:40px">
<div class="form-group">
<input type="text" class="form-control pull-left" id="item-text" style="margin-bottom:10px; width:200px;margin-right:10px" onKeyUp="if (event.keyCode == 13) document.getElementById('btnAddItem').click()">
<button class="btn btn-default " onClick="addItem()" id="btnAddItem">add</button>
<button class="btn btn-default pull-right" onClick="removeItem()">remove last item</button>
<ul class="list-group" id="user-item" style="margin-top:10px">
<span id="spanUser">
</span>
</ul>
</div>
</div>
<!--End Items-->
Define a global variables from the window object:
window.iListCount = 0;
window.arrListItems = [];
Are you only using iListCount as an index for arrListItems if so replace:
iListCount++;
arrListItems[iListCount] = sText;
with this:
arrListItems.push(sText);
And replace iListCount references with arrListItems.length.
I used the above suggestions in the following fiddle as well as some other good practice measures:
http://fiddle.jshell.net/2hEby/
Just initialize the array like that:
var arrListItems = [];
If you are checking the array result at the statement
alert(arrListItems[1]);
then make sure that the array has got two elements atleast.
First element of the array can be read using the index 0 and second with 1 and so on.
If you are trying to read first element, use
alert(arrListItems[0]);
Also the statements
iListCount++;
arrListItems[iListCount] = sText;
should be merged to one statement like this
arrListItems[iListCount++] = sText;
so that you can start adding elements to the array from it's first location.
You may also try
arrListItems[arrListItems.length] = sText;
Example for arrListItems[iListCount++] = sText;
Related
How do I get the next element in HTML using JavaScript?
Suppose I have three <div>s and I get a reference to one in JavaScript code, I want to get which is the next <div> and which is the previous.
use the nextSibling and previousSibling properties:
<div id="foo1"></div>
<div id="foo2"></div>
<div id="foo3"></div>
document.getElementById('foo2').nextSibling; // #foo3
document.getElementById('foo2').previousSibling; // #foo1
However in some browsers (I forget which) you also need to check for whitespace and comment nodes:
var div = document.getElementById('foo2');
var nextSibling = div.nextSibling;
while(nextSibling && nextSibling.nodeType != 1) {
nextSibling = nextSibling.nextSibling
}
Libraries like jQuery handle all these cross-browser checks for you out of the box.
Really depends on the overall structure of your document.
If you have:
<div></div>
<div></div>
<div></div>
it may be as simple as traversing through using
mydiv.nextSibling;
mydiv.previousSibling;
However, if the 'next' div could be anywhere in the document you'll need a more complex solution. You could try something using
document.getElementsByTagName("div");
and running through these to get where you want somehow.
If you are doing lots of complex DOM traversing such as this I would recommend looking into a library such as jQuery.
Well in pure javascript my thinking is that you would first have to collate them inside a collection.
var divs = document.getElementsByTagName("div");
//divs now contain each and every div element on the page
var selectionDiv = document.getElementById("MySecondDiv");
So basically with selectionDiv iterate through the collection to find its index, and then obviously -1 = previous +1 = next within bounds
for(var i = 0; i < divs.length;i++)
{
if(divs[i] == selectionDiv)
{
var previous = divs[i - 1];
var next = divs[i + 1];
}
}
Please be aware though as I say that extra logic would be required to check that you are within the bounds i.e. you are not at the end or start of the collection.
This also will mean that say you have a div which has a child div nested. The next div would not be a sibling but a child, So if you only want siblings on the same level as the target div then definately use nextSibling checking the tagName property.
Its quite simple. Try this instead:
let myReferenceDiv = document.getElementById('mydiv');
let prev = myReferenceDiv.previousElementSibling;
let next = myReferenceDiv.nextElementSibling;
There is a attribute on every HTMLElement, "previousElementSibling".
Ex:
<div id="a">A</div>
<div id="b">B</div>
<div id="c">c</div>
<div id="result">Resultado: </div>
var b = document.getElementById("c").previousElementSibling;
document.getElementById("result").innerHTML += b.innerHTML;
Live: http://jsfiddle.net/QukKM/
This will be easy...
its an pure javascript code
<script>
alert(document.getElementById("someElement").previousElementSibling.innerHTML);
</script>
all these solutions look like an overkill.
Why use my solution?
previousElementSibling supported from IE9
document.addEventListener needs a polyfill
previousSibling might return a text
Please note i have chosen to return the first/last element in case boundaries are broken.
In a RL usage, i would prefer it to return a null.
var el = document.getElementById("child1"),
children = el.parentNode.children,
len = children.length,
ind = [].indexOf.call(children, el),
nextEl = children[ind === len ? len : ind + 1],
prevEl = children[ind === 0 ? 0 : ind - 1];
document.write(nextEl.id);
document.write("<br/>");
document.write(prevEl.id);
<div id="parent">
<div id="child1"></div>
<div id="child2"></div>
</div>
You can use nextElementSibling or previousElementSibling properties
<div>
<span id="elem-1">
span
</span>
</div>
<div data-id="15">
Parent Sibling
</div>
const sp = document.querySelector('#elem-1');
let sibling_data_id = sp.parentNode.nextElementSibling.dataset.id;
console.log(sibling_data_id); // 15
Tested it and it worked for me. The element finding me change as per the document structure that you have.
<html>
<head>
<script type="text/javascript" src="test.js"></script>
</head>
<body>
<form method="post" id = "formId" action="action.php" onsubmit="return false;">
<table>
<tr>
<td>
<label class="standard_text">E-mail</label>
</td>
<td><input class="textarea" name="mail" id="mail" placeholder="E-mail"></label></td>
<td><input class="textarea" name="name" id="name" placeholder="E-mail"> </label></td>
<td><input class="textarea" name="myname" id="myname" placeholder="E-mail"></label></td>
<td><div class="check_icon icon_yes" style="display:none" id="mail_ok_icon"></div></td>
<td><div class="check_icon icon_no" style="display:none" id="mail_no_icon"></div></label></td>
<td><div class="check_message" style="display:none" id="mail_message"><label class="important_text">The email format is not correct!</label></div></td>
</tr>
</table>
<input class="button_submit" type="submit" name="send_form" value="Register"/>
</form>
</body>
</html>
var inputs;
document.addEventListener("DOMContentLoaded", function(event) {
var form = document.getElementById('formId');
inputs = form.getElementsByTagName("input");
for(var i = 0 ; i < inputs.length;i++) {
inputs[i].addEventListener('keydown', function(e){
if(e.keyCode == 13) {
var currentIndex = findElement(e.target)
if(currentIndex > -1 && currentIndex < inputs.length) {
inputs[currentIndex+1].focus();
}
}
});
}
});
function findElement(element) {
var index = -1;
for(var i = 0; i < inputs.length; i++) {
if(inputs[i] == element) {
return i;
}
}
return index;
}
that's so simple
var element = querySelector("div")
var nextelement = element.parentElement.querySelector("div+div")
Here is the browser supports https://caniuse.com/queryselector
I have a template that I'm cloning to make Single Page Application. Inside this template are some div's that should have a unique id's so that it should be working individually when I open multiple apps(clone multiple divs)
<template id="templ">
<div id="name"></div>
<div id="btn">
<fieldset id="fld">
<input type="text" id="userMessage"placeholder="Type your messageā¦" autofocus>
<input type="hidden">
<button id="send" >Save</button>
</fieldset>
</div>
</template>
and I'm cloning it like this
var i =0
let template = document.querySelector('#templ')
let clone = document.importNode(template.content, true)
clone.id = 'name' + ++i // I can't change the Id o this name div
document.querySelector('body').appendChild(clone)
Thanks
clone.id is undefined since clone is a #document-fragment with two children.
You need to query the 'name' child and change its id, for example like this:
const template = document.querySelector('#templ')
const body = document.querySelector('body')
function appendClone(index){
let clone = document.importNode(template.content, true)
clone.getElementById('name').id = 'name' + index
// all other elements with IDs
body.appendChild(clone)
}
Then you can iterate over the amount of clones and simply call the function with the loop index:
let clones = 5
for (let i = 0; i < clones; i++){
appendClone(i)
}
store the dynamic HTML data in script element and add when ever required by replaciing with dynamic data.
HTML Data:
<script id="hidden-template" type="text/x-custom-template">
<div id='${dynamicid}'>
<p>${dynamic_data}</p>
</div>
</script>
Script to replace and append.
var template_add = $('#hidden-template').text();
var items = [{
dynamicid: '1',
dynamic_data: '0'
}];
function replaceDynamicData(props) {
return function(tok, i) {
return (i % 2) ? props[tok] : tok;
};
}
var dynamic_HTML = template_add.split(/\$\{(.+?)\}/g);
$('tbody').append(items.map(function(item) {
return dynamic_HTML.map(replaceDynamicData(item)).join('');
}));
I have form which gets clone when user click on add more button .
This is how my html looks:
<div class="col-xs-12 duplicateable-content">
<div class="item-block">
<button class="btn btn-danger btn-float btn-remove">
<i class="ti-close"></i>
</button>
<input type="file" id="drop" class="dropify" data-default-file="https://cdn.example.com/front2/assets/img/logo-default.png" name="sch_logo">
</div>
<button class="btn btn-primary btn-duplicator">Add experience</button>
...
</div>
This my jquery part :
$(function(){
$(".btn-duplicator").on("click", function(a) {
a.preventDefault();
var b = $(this).parent().siblings(".duplicateable-content"),
c = $("<div>").append(b.clone(true, true)).html();
$(c).insertBefore(b);
var d = b.prev(".duplicateable-content");
d.fadeIn(600).removeClass("duplicateable-content")
})
});
Now I want every time user clicks on add more button the id and class of the input type file should be changed into an unique, some may be thinking why I'm doing this, it I because dropify plugin doesn't work after being cloned, but when I gave it unique id and class it started working, here is what I've tried :
function randomString(len, an){
an = an&&an.toLowerCase();
var str="", i=0, min=an=="a"?10:0, max=an=="n"?10:62;
for(;i++<len;){
var r = Math.random()*(max-min)+min <<0;
str += String.fromCharCode(r+=r>9?r<36?55:61:48);
}
return str;
} var ptr = randomString(10, "a");
var className = $('#drop').attr('class');
var cd = $("#drop").removeClass(className).addClass(ptr);
Now after this here is how I initiate the plugin $('.' + ptr).dropify().
But because id is still same I'm not able to produce clone more than one.
How can I change the id and class everytime user click on it? is there a better way?
Working Fiddle.
Problem :
You're cloning a div that contain already initialized dropify input and that what create the conflict when you're trying to clone it and reinitilize it after clone for the second time.
Solution: Create a model div for the dropify div you want to clone without adding dropify class to prevent $('.dropify').dropify() from initialize the input then add class dropify during the clone.
Model div code :
<div class='hidden'>
<div class="col-xs-12 duplicateable-content model">
<div class="item-block">
<button class="btn btn-danger btn-float btn-remove">
X
</button>
<input type="file" data-default-file="http://www.misterbilingue.com/assets/uploads/fileserver/Company%20Register/game_logo_default_fix.png" name="sch_logo">
</div>
<button class="btn btn-primary btn-duplicator">Add experience</button>
</div>
</div>
JS code :
$('.dropify').dropify();
$("body").on("click",".btn-duplicator", clone_model);
$("body").on("click",".btn-remove", remove);
//Functions
function clone_model() {
var b = $(this).parent(".duplicateable-content"),
c = $(".model").clone(true, true);
c.removeClass('model');
c.find('input').addClass('dropify');
$(b).before(c);
$('.dropify').dropify();
}
function remove() {
$(this).closest('.duplicateable-content').remove();
}
Hope this helps.
Try this:
$(function() {
$(document).on("click", ".btn-duplicator", function(a) {
a.preventDefault();
var b = $(this).parent(".duplicateable-content"),
c = b.clone(true, true);
c.find(".dropify").removeClass('dropify').addClass('cropify')
.attr('id', b.find('[type="file"]')[0].id + $(".btn-duplicator").index(this)) //<here
$(c).insertBefore(b);
var d = b.prev(".duplicateable-content");
d.fadeIn(600).removeClass("duplicateable-content")
})
});
Fiddle
This does what you specified with an example different from yours:
<div id="template"><span>...</span></div>
<script>
function appendrow () {
html = $('#template').html();
var $last = $('.copy').last();
var lastId;
if($last.length > 0) {
lastId = parseInt($('.copy').last().prop('id').substr(3));
} else {
lastId = -1;
}
$copy = $(html);
$copy.prop('id', 'row' + (lastId + 1));
$copy.addClass('copy');
if(lastId < 0)
$copy.insertAfter('#template');
else
$copy.insertAfter("#row" + lastId);
}
appendrow();
appendrow();
appendrow();
</script>
Try adding one class to all dropify inputs (e.g. 'dropify'). Then you can set each elements ID to a genereted value using this:
inputToAdd.attr('id', 'dropify-input-' + $('.dropify').length );
Each time you add another button, $('.dropify').length will increase by 1 so you and up having a unique ID for every button.
I'm working on something really simple, a short quiz, and I am trying to make the items I have listed in a 2-d array each display as a <li>. I tried using the JS array.join() method but it didn't really do what I wanted. I'd like to place them into a list, and then add a radio button for each one.
I have taken the tiny little leap to Jquery, so alot of this is my unfamiliarity with the "syntax". I skimmed over something on their API, $.each...? I'm sure this works like the for statement, I just can't get it to work without crashing everything I've got.
Here's the HTML pretty interesting stuff.
<div id="main_">
<div class="facts_div">
<ul>
</ul>
</div>
<form>
<input id="x" type="button" class="myBtn" value="Press Me">
</form>
</div>
And, here is some extremely complex code. Hold on to your hats...
$(document).ready (function () {
var array = [["Fee","Fi","Fo"],
["La","Dee","Da"]];
var q = ["<li>Fee-ing?","La-ing?</li>"];
var counter = 0;
$('.myBtn').on('click', function () {
$('#main_ .facts_div').text(q[counter]);
$('.facts_div ul').append('<input type= "radio">'
+ array[counter]);
counter++;
if (counter > q.length) {
$('#main_ .facts_div').text('You are done with the quiz.');
$('.myBtn').hide();
}
});
});
Try
<div id="main_">
<div class="facts_div"> <span class="question"></span>
<ul></ul>
</div>
<form>
<input id="x" type="button" class="myBtn" value="Press Me" />
</form>
</div>
and
jQuery(function ($) {
//
var array = [
["Fee", "Fi", "Fo"],
["La", "Dee", "Da"]
];
var q = ["Fee-ing?", "La-ing?"];
var counter = 0;
//cache all the possible values since they are requested multiple times
var $facts = $('#main_ .facts_div'),
$question = $facts.find('.question'),
$ul = $facts.find('ul'),
$btn = $('.myBtn');
$btn.on('click', function () {
//display the question details only of it is available
if (counter < q.length) {
$question.text(q[counter]);
//create a single string containing all the anwers for the given question - look at the documentation for jQuery.map for details
var ansstring = $.map(array[counter], function (value) {
return '<li><input type="radio" name="ans"/>' + value + '</li>'
}).join('');
$ul.html(ansstring);
counter++;
} else {
$facts.text('You are done with the quiz.');
$(this).hide();
}
});
//
});
Demo: Fiddle
You can use $.each to iterate over array[counter] and create li elements for your options:
var list = $('.facts_div ul');
$.each(array[counter], function() {
$('<li></li>').html('<input type="radio" /> ' + this).appendTo(list);
}
The first parameter is your array and the second one is an anonymous function to do your action, in which this will hold the current element value.
Also, if you do this:
$('#main_ .facts_div').text(q[counter]);
You will be replacing the contents of your element with q[counter], losing your ul tag inside it. In this case, you could use the prepend method instead of text to add this text to the start of your tag, or create a new element just for holding this piece of text.
I need to do the following (I'm a beginner in programming so please excuse me for my ignorance): I have to ask the user for three different pieces of information on three different text boxes on a form. Then the user has a button called "enter"and when he clicks on it the texts he entered on the three fields should be stored on three different arrays, at this stage I also want to see the user's input to check data is actually being stored in the array. I have beem trying unsuccessfully to get the application to store or show the data on just one of the arrays. I have 2 files: film.html and functions.js. Here's the code. Any help will be greatly appreciated!
<html>
<head>
<title>Film info</title>
<script src="jQuery.js" type="text/javascript"></script>
<script src="functions.js" type="text/javascript"></script>
</head>
<body>
<div id="form">
<h1><b>Please enter data</b></h1>
<hr size="3"/>
<br>
<label for="title">Title</label> <input id="title" type="text" >
<br>
<label for="name">Actor</label><input id="name" type="text">
<br>
<label for="tickets">tickets</label><input id="tickets" type="text">
<br>
<br>
<input type="button" value="Save" onclick="insert(this.form.title.value)">
<input type="button" value="Show data" onclick="show()"> <br>
<h2><b>Data:</b></h2>
<hr>
</div>
<div id= "display">
</div>
</body>
</html>
var title=new Array();
var name=new Array();
var tickets=new Array();
function insert(val){
title[title.length]=val;
}
function show() {
var string="<b>All Elements of the Array :</b><br>";
for(i = 0; i < title.length; i++) {
string =string+title[i]+"<br>";
}
if(title.length > 0)
document.getElementById('myDiv').innerHTML = string;
}
You're not actually going out after the values. You would need to gather them like this:
var title = document.getElementById("title").value;
var name = document.getElementById("name").value;
var tickets = document.getElementById("tickets").value;
You could put all of these in one array:
var myArray = [ title, name, tickets ];
Or many arrays:
var titleArr = [ title ];
var nameArr = [ name ];
var ticketsArr = [ tickets ];
Or, if the arrays already exist, you can use their .push() method to push new values onto it:
var titleArr = [];
function addTitle ( title ) {
titleArr.push( title );
console.log( "Titles: " + titleArr.join(", ") );
}
Your save button doesn't work because you refer to this.form, however you don't have a form on the page. In order for this to work you would need to have <form> tags wrapping your fields:
I've made several corrections, and placed the changes on jsbin: http://jsbin.com/ufanep/2/edit
The new form follows:
<form>
<h1>Please enter data</h1>
<input id="title" type="text" />
<input id="name" type="text" />
<input id="tickets" type="text" />
<input type="button" value="Save" onclick="insert()" />
<input type="button" value="Show data" onclick="show()" />
</form>
<div id="display"></div>
There is still some room for improvement, such as removing the onclick attributes (those bindings should be done via JavaScript, but that's beyond the scope of this question).
I've also made some changes to your JavaScript. I start by creating three empty arrays:
var titles = [];
var names = [];
var tickets = [];
Now that we have these, we'll need references to our input fields.
var titleInput = document.getElementById("title");
var nameInput = document.getElementById("name");
var ticketInput = document.getElementById("tickets");
I'm also getting a reference to our message display box.
var messageBox = document.getElementById("display");
The insert() function uses the references to each input field to get their value. It then uses the push() method on the respective arrays to put the current value into the array.
Once it's done, it cals the clearAndShow() function which is responsible for clearing these fields (making them ready for the next round of input), and showing the combined results of the three arrays.
function insert ( ) {
titles.push( titleInput.value );
names.push( nameInput.value );
tickets.push( ticketInput.value );
clearAndShow();
}
This function, as previously stated, starts by setting the .value property of each input to an empty string. It then clears out the .innerHTML of our message box. Lastly, it calls the join() method on all of our arrays to convert their values into a comma-separated list of values. This resulting string is then passed into the message box.
function clearAndShow () {
titleInput.value = "";
nameInput.value = "";
ticketInput.value = "";
messageBox.innerHTML = "";
messageBox.innerHTML += "Titles: " + titles.join(", ") + "<br/>";
messageBox.innerHTML += "Names: " + names.join(", ") + "<br/>";
messageBox.innerHTML += "Tickets: " + tickets.join(", ");
}
The final result can be used online at http://jsbin.com/ufanep/2/edit
You have at least these 3 issues:
you are not getting the element's value properly
The div that you are trying to use to display whether the values have been saved or not has id display yet in your javascript you attempt to get element myDiv which is not even defined in your markup.
Never name variables with reserved keywords in javascript. using "string" as a variable name is NOT a good thing to do on most of the languages I can think of. I renamed your string variable to "content" instead. See below.
You can save all three values at once by doing:
var title=new Array();
var names=new Array();//renamed to names -added an S-
//to avoid conflicts with the input named "name"
var tickets=new Array();
function insert(){
var titleValue = document.getElementById('title').value;
var actorValue = document.getElementById('name').value;
var ticketsValue = document.getElementById('tickets').value;
title[title.length]=titleValue;
names[names.length]=actorValue;
tickets[tickets.length]=ticketsValue;
}
And then change the show function to:
function show() {
var content="<b>All Elements of the Arrays :</b><br>";
for(var i = 0; i < title.length; i++) {
content +=title[i]+"<br>";
}
for(var i = 0; i < names.length; i++) {
content +=names[i]+"<br>";
}
for(var i = 0; i < tickets.length; i++) {
content +=tickets[i]+"<br>";
}
document.getElementById('display').innerHTML = content; //note that I changed
//to 'display' because that's
//what you have in your markup
}
Here's a jsfiddle for you to play around.