I have a people section on a website I'm building which uses isotope for filtering. When I click on a person I want to show their full info on the right. When the click happens I grab the id and store it as a variable. I then have variables named to match up with the grabbed IDs.
How do I use the grabbed ID to target the variables stored in my js file? Currently it only prints out the ID grabbed from the clicked div.
var userOne = "<p>userOne info<p>";
var userTwo = "<p>userTwo info<p>";
var userThree = "<p>userThree info<p>";
$('.item').on("click", function(){
var id = $(this).attr('id'); // this grabs the ID of the div eg userOne
var printId = id; //trying to change the variable so I can use it
$('.bio').html(printID); //this is where it should print out
});
You can't access a variable name like that, instead what you can do is to access a object's property with a dynamic key
Assuming the variables userOne/userTwo are in the global scope, you can use the bracket notation like
var userOne = "<p>userOne info<p>";
var userTwo = "<p>userTwo info<p>";
var userThree = "<p>userThree info<p>";
$('.item').on("click", function () {
var printId = window[this.id];
$('.bio').html(printID);
});
another option is to store those values as properties of an object
var user = {
userOne: "<p>userOne info<p>",
userTwo: "<p>userTwo info<p>",
userThree: "<p>userThree info<p>"
};
$('.item').on("click", function () {
var printId = user[this.id];
$('.bio').html(printID);
});
Try
html
<div class="item" data-user="<p>userOne info<p>"></div>
js
$(".item").on("click", function(e) {
$(".bio").html($(this).data("user"))
})
$(".item").on("click", function(e) {
$(".bio").html($(this).data("user"))
})
div:not(.bio) {
border:1px dotted grey;
width: 24px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="item" data-user="<p>userOne info<p>">1</div><br />
<div class="item" data-user="<p>userTwo info<p>">2</div><br />
<div class="item" data-user="<p>userThree info<p>">3</div><br />
<div class="bio"></div>
Related
In vanilla JavaScript how can I bind an element to an object so that if a child element of the object has a value I can update the object with it? Need to be compatible with IE10+ and all other browsers.
With a button I am dynamically adding an element (createElement()) containing a form input. When the element is created it also creates an object that should also be the element so I can update the object with the input value on change.
I then store each new object in an array.
The issue I am having is connecting the input value with the correct object. I tried looping through the array hoping to update each object in turn with the current input value of the event target but couldn't succeed. I tried registering the element (deprecated) and various other things but I cannot quite workout how to link the input to the container object (lineObject).
I could really use some help solving this problem and understanding how to bind an element to an object in the way I need.
//lineNumber *** //
let lineNumber = document.querySelectorAll('.lineNumber');
let numberOfLines = lineNumber.length;
//first instance of input element
let lineText = document.querySelector('.lineText');
//first input value of element
let lineTextValue = document.querySelector('input[name="lineText"]').value;
//create initial lineObject for first line
let lastLine = lineNumber[numberOfLines - 1];
let lineContainer;
//lineNumber object constructor
function LineObject(lineText, writable) {
//set properties
this.lineText = lineText;
this.writable = writable;
}
//new object at new lineNumber element, set values
let lineObject = new LineObject(lineTextValue, true);
//create array containing initial line object
let lineArray = [lineObject];
//line functions
(function lineGeneration(){
//add or remove lines
document.addEventListener('click', function(e) {
//this
let self = e.target;
// has class .addLine
if (hasClass(self, 'addLine')) {
//call function to get variables
insertLineHTML();
//clone new line after the last line\
self.parentElement.parentElement.parentElement.parentElement.parentElement.appendChild(lineObject.cloneNode(true));
//lineNumber input location
let newlineTextInput = self.parentElement.parentElement.parentElement.parentElement.nextElementSibling.querySelector('input[name="lineText"]');
//input value of new element
let lineTextValue = newlineTextInput.value;//normally "" when created unless placeholder text
//new object at new lineNumber element
lineObject = new LineObject(lineTextValue, true);
//add new object to lineArray
lineArray.push(lineObject);
refreshLineNodeList();
}
});
//combine accordion / refresh
function refreshLineNodeList(){
//refresh number of elements in nodelist
lineNumber = document.querySelectorAll('.lineNumber');
//get new length
numberOfLines = lineNumber.length;
}
//line html and vars
function insertLineHTML(){
lineObject = document.createElement('div');
lineObject.setAttribute('class', 'lineNumber');
lineObject.innerHTML = `
<div class="accordion-title">
<h3>Line 2</h3>
</div>
<div class="input-section">
<div class="input-row">
<div class="input-container">
<label>Line 2 :</label>
<input type="text" name="lineText" value="" class="lineText">
</div>
<div class="input-row">
<div class="button-container">
<div class="warning"></div>
<button class="addLine">Add Another Line</button>
</div>
</div>
</div>`;
console.log(lineNumber);
}
})();
//lineText addEventListener update object value
document.addEventListener('keyup', function(e) {
let self = e.target;//input field
let lineTextValue = self.value;
// has class .lineText
if (hasClass(self, 'lineText')) {
//for each lineObject in LineArray
//lineArray.forEach(function(arrayObject) {
//update lineObject HTMLelement.prototype
Object.defineProperty(lineObject, 'lineText', {
//update object value to event target value
get: function() {
return this.lineTextValue;//how can I get the right lineObject object from the array when I update the input
},
set: function(lineTextValue) {
this.lineText = lineTextValue;//how can I aet the right lineObject object in the array when I update the input
}
});
//debugging
//console.log('objectProperty = ' + arrayObject.lineText);
console.log('this.lineText = ' + this.lineText);
console.log('Object.entries(lineObject) - ' + Object.entries(lineObject));
//console.log('lineObject.lineText = '+ lineObject.lineText);
//console.log('lineTextValue = '+ lineTextValue);
//});
};
});
let button = document.getElementById('test');
button.addEventListener( "click", testFunction );
function testFunction(){
button.addEventListener( "click", testFunction );
//console.log('Object.keys(lineObject) - '+ Object.keys(lineObject));
//console.log('Reflect.ownKeys(lineObject) - ' + Reflect.ownKeys(lineObject));
//console.log('Object.values - ' + Object.values(lineObject));
//console.log('lineObject = '+ lineObject.lineText);
//console.log('Object.entries(lineObject) - ' + Object.entries(lineObject));
//console.log('Object.entries(lineObjectClone) - ' + Object.entries(lineObjectClone));
//console.log('lineObjectClone.lineText = ' + lineObject.lineText);
//console.log('lineObjectClone[1].lineText = ' + lineObjectClone.lineText);
//console.log('lineArray[0] = ' + lineArray[0].lineText);
console.log('lineArray = ' + lineArray);
console.log('numberOfLines = ' + numberOfLines);
for(let i = 0; i < numberOfLines; ++i ){
console.log('lineArray[i].lineText = ' + lineArray[i].lineText)
}
};
//does the element have the class specified?
function hasClass(elem, className) {
return elem.classList.contains(className);
};
<section>
<button id="test">Test</button>
<div class="lineNumber">
<div class="accordion-title">
<h3>Line</h3>
</div>
<div class="input-section" style="display: block;">
<div class="input-row">
<div class="input-container">
<label>Line Text :</label>
<input type="text" name="lineText" value="" class="lineText">
</div>
</div>
<div class="input-row">
<div class="button-container">
<div class="warning"></div>
<button class="addLine">Add Another Line</button>
</div>
</div>
</div>
</div>
</section>
One way to do this is to use a closure.
The purpose of a closure is to capture variables from the containing function so those variables can be used later, after the containing function exits.
A simple example could look like this:
let data = {
nameGenerator: 0
};
function addInput() {
// generate a new name and property in data object
let propertyName = String.fromCharCode("a".charCodeAt() + data.nameGenerator++);
// initialize property value to its name
data[propertyName] = propertyName;
// add <div><input value="(property)"></div> to container
let containerElement = document.getElementById("container");
let lineElement = document.createElement("div");
let inputElement = document.createElement("input");
lineElement.appendChild(inputElement);
containerElement.appendChild(lineElement);
// initialize input value (note: this does not bind the two, just initializes)
inputElement.value = data[propertyName];
// create a closure that binds the property to the element
inputElement.addEventListener("keyup", function () {
// inside this function, propertyName and inputElement
// are "captured" in the closure
data[propertyName] = inputElement.value;
})
}
Note that the propertyName and inputElement variables are defined in the outer addInput function, but they are captured in the closure that is created when you assign the anonymous function as an event listener.
Here is a fiddle with a complete working example: https://jsfiddle.net/b3ta60cn/
I have an array where each element refers to a bunch of svgs in another js file. I'm trying to get it so that my alert message uses the same string I use in the array variable.
var illustArr = ['map', 'privacy', 'payment', 'rewards', 'passcode'];
var bmAnim = document.getElementById('illus-'+illustArr[i]);
bmAnim.addEventListener('click', function(){
alert('illus-'+illustArr[i]);
});
Any ideas how to achieve that?
You can do it using a for-loop. Also make sure that you check if element exists so that you wont get an error.
var illustArr = ['map', 'privacy', 'payment', 'rewards', 'passcode'];
for (var i = 0; i < illustArr.length; i++) {
bmAnim = document.getElementById('illus-' + illustArr[i]);
if (bmAnim) { //check if element exists
bmAnim.addEventListener('click', function() {
alert('illus' + this.id);
});
}
}
<div id="illus-map">MAP</div>
<p>
<div id="illus-privacy">PRIVACY</div>
<p>
<div id="illus-payment">PAYMENT</div>
<p>
<div id="illus-rewards">REWARDS</div>
<p>
<div id="illus-passcode">PASSCODE</div>
You need to iterate over the array and assign the click function with the corresponding key in scope.
var illustArr = ['map', 'privacy', 'payment', 'rewards', 'passcode'];
illustArr.forEach(function (key) {
var bmAnim = document.getElementById('illus-' + key);
bmAnim && bmAnim.addEventListener('click', function () {
alert('illus-' + key);
});
});
You should use the Array#forEach function to iterate over the elements in your array before you attach any listeners to the click event. Also, you can use this.id in the event handler to reference the string illus-* with the desired suffix rather than accessing illustArr again.
var illustArr = ['map', 'privacy', 'payment', 'rewards', 'passcode'];
illustArr.forEach(function (e) {
document.getElementById('illus-' + e).addEventListener('click', handler)
})
function handler () {
alert(this.id)
}
<ul>
<li id="illus-map">Map</li>
<li id="illus-privacy">Privacy</li>
<li id="illus-payment">Payment</li>
<li id="illus-rewards">Rewards</li>
<li id="illus-passcode">Passcode</li>
</ul>
I'm creating a Time table generating website as a part of my project and I am stuck at one point.
Using for loop, I am generating user selected text boxes for subjects and faculties. Now the problem is that I cannot get the values of those dynamically generated text boxes. I want to get the values and store it into array so that I can then later on store it to database
If I am using localstorage, then it sometimes shows NaN or undefined. Please help me out.
Following is my Jquery code
$.fn.CreateDynamicTextBoxes = function()
{
$('#DynamicTextBoxContainer, #DynamicTextBoxContainer2').css('display','block');
InputtedValue = $('#SemesterSubjectsSelection').val();
SubjectsNames = [];
for (i = 0; i < InputtedValue; i++)
{
TextBoxContainer1 = $('#DynamicTextBoxContainer');
TextBoxContainer2 = $('#DynamicTextBoxContainer2');
$('<input type="text" class="InputBoxes" id="SubjectTextBoxes'+i+'" placeholder="Subject '+i+' Name" style="margin:5px;" value=""><br>').appendTo(TextBoxContainer1);
$('<input type="text" class="InputBoxes" id="FacultyTextBoxes'+i+'" placeholder="Subject '+i+' Faculty Name" style="margin:5px;" value=""><br>').appendTo(TextBoxContainer2);
SubjectsNames['SubjectTextBoxes'+i];
}
$('#DynamicTextBoxContainer, #UnusedContainer, #DynamicTextBoxContainer2').css('border-top','1px solid #DDD');
}
$.fn.CreateTimeTable = function()
{
for (x = 0; x < i; x++)
{
localStorage.setItem("Main"+x, +SubjectsNames[i]);
}
}
I am also posting screenshot for better understanding
I understand you create 2 text boxes for each subject, one for subject, and second one for faculty. And you want it as a jQuery plugin.
First of all, I think you should create single plugin instead of two, and expose what you need from the plugin.
You should avoid global variables, right now you have InputtedValue, i, SubjectsNames, etc. declared as a global variables, and I believe you should not do that, but keep these variables inside you plugin and expose only what you really need.
You declare your SubjectNames, but later in first for loop you try to access its properties, and actually do nothing with this. In second for loop you try to access it as an array, but it's empty, as you did not assign any values in it.
Take a look at the snippet I created. I do not play much with jQuery, and especially with custom plugins, so the code is not perfect and can be optimized, but I believe it shows the idea. I pass some selectors as in configuration object to make it more reusable. I added 2 buttons to make it more "playable", but you can change it as you prefer. Prepare button creates your dynamic text boxes, and button Generate takes their values and "print" them in result div. generate method is exposed from the plugin to take the values outside the plugin, so you can do it whatever you want with them (e.g. store them in local storage).
$(function() {
$.fn.timeTables = function(config) {
// prepare variables with jQuery objects, based on selectors provided in config object
var numberOfSubjectsTextBox = $(config.numberOfSubjects);
var subjectsDiv = $(config.subjects);
var facultiesDiv = $(config.faculties);
var prepareButton = $(config.prepareButton);
var numberOfSubjects = 0;
prepareButton.click(function() {
// read number of subjects from the textbox - some validation should be added here
numberOfSubjects = +numberOfSubjectsTextBox.val();
// clear subjects and faculties div from any text boxes there
subjectsDiv.empty();
facultiesDiv.empty();
// create new text boxes for each subject and append them to proper div
// TODO: these inputs could be stored in arrays and used later
for (var i = 0; i < numberOfSubjects; i++) {
$('<input type="text" placeholder="Subject ' + i + '" />').appendTo(subjectsDiv);
$('<input type="text" placeholder="Faculty ' + i + '" />').appendTo(facultiesDiv);
}
});
function generate() {
// prepare result array
var result = [];
// get all text boxes from subjects and faculties divs
var subjectTextBoxes = subjectsDiv.find('input');
var facultiesTextBoxes = facultiesDiv.find('input');
// read subject and faculty for each subject - numberOfSubjects variable stores proper value
for (var i = 0; i < numberOfSubjects; i++) {
result.push({
subject: $(subjectTextBoxes[i]).val(),
faculty: $(facultiesTextBoxes[i]).val()
});
}
return result;
}
// expose generate function outside the plugin
return {
generate: generate
};
};
var tt = $('#container').timeTables({
numberOfSubjects: '#numberOfSubjects',
subjects: '#subjects',
faculties: '#faculties',
prepareButton: '#prepare'
});
$('#generate').click(function() {
// generate result and 'print' it to result div
var times = tt.generate();
var result = $('#result');
result.empty();
for (var i = 0; i < times.length; i++) {
$('<div>' + times[i].subject + ': ' + times[i].faculty + '</div>').appendTo(result);
}
});
});
#content div {
float: left;
}
#content div input {
display: block;
}
#footer {
clear: both;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="container">
<div id="header">
<input type="text" id="numberOfSubjects" placeholder="Number of subjects" />
<button id="prepare">
Prepare
</button>
</div>
<div id="content">
<div id="subjects">
</div>
<div id="faculties">
</div>
</div>
</div>
<div id="footer">
<button id="generate">Generate</button>
<div id="result">
</div>
</div>
I was hoping someone can help me figure out what I'm doing wrong... There's this exercise in the Eloquent JS book that asks you to write some code that can suggest words/values to users as they type... The code I've written is below. What happens is that when I run the code, the div element's text content changes to the wrong value. Specifically, it's set to a string of all the elements inside the array 'terms'. I really cant figure out why this happens!
<input type="text" id="field">
<div id="suggestions" style="cursor: pointer"></div>
<script>
// Builds up an array with global variable names, like
// 'alert', 'document', and 'scrollTo'
var terms = [];
for (var name in window)
terms.push(name);
var input = document.querySelector('input');
var div = document.querySelector('#suggestions');
input.addEventListener("input", function(event){
var last = input.value.lastIndexOf(" ")+1;
var check = input.value.slice(last);
var reg = new RegExp(check);
for (var i=0; i<terms.length; i++) {
if (reg.test(terms[i])) {
var text = document.createTextNode(terms[i]);
div.appendChild(text)};
};
})
</script>
I guess you forgot to clean the div before each change in the input.
I also added a space after each word to make the output more readable.
// Builds up an array with global variable names, like
// 'alert', 'document', and 'scrollTo'
var terms = [];
for (var name in window)
terms.push(name);
var input = document.querySelector('input');
var div = document.querySelector('#suggestions');
input.addEventListener("input", function(event){
div.innerHTML = '';
var last = input.value.lastIndexOf(" ")+1;
var check = input.value.slice(last);
var reg = new RegExp(check);
for (var i=0; i<terms.length; i++) {
if (reg.test(terms[i])) {
var text = document.createTextNode(terms[i] + ' ');
div.appendChild(text)};
};
})
<input type="text" id="field">
<div id="suggestions" style="cursor: pointer"></div>
With this code, you will display the name of the properties from the window object that contains the last word from the input. Try it writting "window location document". Is it what you are looking for?
I have project that concerns about calendars, at first i have 1 calendar and now i want to have another one but they have different values.
<div id="cal">
....
</div>
<div id="calq">
....
</div>
my question is, how can I check if div id is "calq" in javascript?
if div.id == "calq" ?
...
at first i have ...
<script type="text/javascript">
monthYear = Date.today();
var cal = new Calendar();
cal.generateHTML();
$('#cal').html(cal.getHTML());
setMonthPrice();
setSpecialPrice()
</script>
then i added
<script type="text/javascript">
monthYear = Date.today();
var calq = new Calendar();
calq.generateHTML();
$('#calq').html(calq.getHTML());
setMonthQuantity();
setSpecialQuantity();
</script>
but the setMonthQuantity() also called by cal, i just want the setMonthQuantity() only for calq
function setMonthQuantity()
{
var weekdayBaseQuantity;
weekdayBaseQuantity = {{ product.quantity }};
$('td.calendar-day').append('<div class="dayquantity">' + weekdayBaseQuantity + '</div>');
$('td.Sat .dayquantity, td.Sun .dayquantity').text( weekdayBaseQuantity );
}
To determine the existence, in clean javascript
if(document.getElementById("calq")!='undefined')
{
// do something, it exists
}
using jquery
if($("#calq").length)
{
// do something, it exists
}
To check the id, in clean javascript
if(this.getAttribute('id')=="calc")
{
// do something, it exists
}
Using jquery
if($(this).attr("id")=="calq")
{
// do something, it exists
}
You can do check it, for example, via Jquery. I suppose that you want to make something like switch and for each div do some operation. If I'm right you can use Jquery's each function for looping against div elements and following condition for checking id's.
if($(this).attr("id")=="calq")
Here you go:
if ($('#calq').length === 1) {
// there is id = calq
}
Seems like the best solution would be to pass in the div to the functions you are calling. That way you know the div you are dealing with.
eg.
<script type="text/javascript">
monthYear = Date.today();
var cal = new Calendar();
cal.generateHTML();
var calDiv = $('#cal');
calDiv.html(cal.getHTML());
setMonthPrice(calDiv);
setSpecialPrice(calDiv)
</script>
<script type="text/javascript">
monthYear = Date.today();
var calq = new Calendar();
var calqDiv = $('#cal');
calqDiv.html(cal.getHTML());
setMonthQuantity(calqDiv);
setSpecialQuantity(calqDiv);
</script>
I am assuming the $('td.calendar-day') is in the calendar HTML? If so setMonthQuantity would be something like
function setMonthQuantity(calDiv)
{
var weekdayBaseQuantity;
weekdayBaseQuantity = {{ product.quantity }};
calDiv.closest('td.calendar-day').append('<div class="dayquantity">' + weekdayBaseQuantity + '</div>');
calDiv.closest('td.Sat .dayquantity, td.Sun .dayquantity').text( weekdayBaseQuantity );
}