In a demo site I have four text boxes which are grouped into two pairs of two (two dimensions, each dimension has two sets). I use only IDs and a naming scheme to get javascript to read each one individually. Is there a cleaner way of using element selectors to avoid having so many similarly named IDs and duplicated code? Can CSS selectors be used for this purpose?
Example HTML
<form id="user-dimension-form" action="javascript:processDimensionInput();plotScatter()" autocomplete="off">
<div class="user-dimension-area">
<label>Dimension 1 Name
<!-- TODO: better naming scheme in CSS -->
<input class="user-dimension-name" id="user-dimension-feature1-name-input" type="text">
</label>
<div class="user-dimension-entry">
<textarea class="user-dimension-feature-set" id="user-dimension-feature1-set1" rows="16"></textarea>
<textarea class="user-dimension-feature-set" id="user-dimension-feature1-set2" rows="16"></textarea>
</div>
</div>
<div class="user-dimension-area">
<label>Dimension 2 Name
<input class="user-dimension-name" id="user-dimension-feature2-name-input" type="text">
</label>
<div class="user-dimension-entry">
<textarea class="user-dimension-feature-set" id="user-dimension-feature2-set1" rows="16"></textarea>
<textarea class="user-dimension-feature-set" id="user-dimension-feature2-set2" rows="16"></textarea>
</div>
</div>
<button type="submit">Submit</button>
<span id="user-dimension-message"></span>
</form>
Example javascript reading the textareas showing the duplicated code. Should I avoid manually concat together HTML ID strings?
const feature1Set1Input = parseInput("user-dimension-feature1-set1");
const feature1Set2Input = parseInput("user-dimension-feature1-set2");
const feature2Set1Input = parseInput("user-dimension-feature2-set1");
const feature2Set2Input = parseInput("user-dimension-feature2-set2");
Given the above html, I suppose you could do something like the following:
let form = document.getElementById('user-dimension-form');
let inputs = form.querySelectorAll('textarea');
let values = [];
inputs.forEach( input => values.push(input.value) );
Not sure that I would though. Can't see any benefit.
The method I came up with is to use CSS selectors. So each input is named has class something like "user-feature-words feature0 set0" and it is selected by something like
document.querySelector(`.user-feature-words.feature${i}.set${j}`)
Of course since I'm combining CSS selectors, I could've used the same string to get a unique ID.
Related
Edit: Thanks for the helpful answers so far! I'm still struggling to print the input to the "right" div, though. What am I missing?
Next to the input field, there is an option to select either "left" or "right". Depending on the selection, the input is to be printed eiether left or right on the click of a button. This is what I have - but it only prints to the left, no matter the selection.
jQuery(document).ready(function(){
$('.button').click(function(){
$('.input').val();
if ($('select').val() == "left"){
$('div.left').html($('.input').val());
}
else {
$('div.right').html($('.input').val());
}
});
});
</script>
Sorry if this is very basic - I am completely new to JS and jQuery.
I'm trying to print input from a form into a div. This is part of the source HTML modify (it's for a university class):
<input type="text" class="input">
<div class="left">
</div>
<div class="right">
</div>
Basically, text is entered into the field, and I need to print this text either to the "left" or the "right" div when a button is clicked.
So far, I have only ever dealt with divs that had IDs, so I used
document.getElementById("divId").innerHTML = ($('.input').val());
But what do I do now when I don't have an ID? Unfortunately, changes to the HTML source are not an option.
Thanks in advance!
Just use normal selectors, like css and jQuery does.
https://api.jquery.com/category/selectors/
in your case:
$('div.left').html($('.input').val());
As you see there are many ways to do this. You can get elements by tag name, class, id...
But the most powerful way is to get it with querySelector
function save() {
var input = document.querySelector('input').value;
document.querySelector('div.left').innerHTML = input;
}
<input type="text" class="input">
<button onclick="save()">Save</button>
<div class="left"></div>
<div class="right"></div>
There are plenty of other ways to target HTML elements, but the one you're looking for in this case is getElementsByTagName(). Note that this returns a NodeList collection of elements, so you'll additionally need to specify the index that you wish to target (starting at 0). For example, if you want to target the second <div> element, you can use document.getElementsByTagName("div")[1].
This can be seen in the following example:
let input = document.getElementsByTagName("input")[0];
let button = document.getElementsByTagName("button")[0];
let div2 = document.getElementsByTagName("div")[1];
button.addEventListener("click", function(){
div2.innerHTML = input.value;
});
<input type="text">
<button>Output</button>
<br /><br />
<div>Output:</div>
<div></div>
Since you have unique class names for each element, document.getElementsByClassName can be used. This will return an array of elements containing the class. Since you only have one element with each class name, the first element of the returned array will be your target.
<input type="text" class="input">
<button onclick="save()">Save</button>
<div class="left"></div>
<div class="right"></div>
<script>
function save() {
var input = document.getElementsByClassName('input')[0].value;
document.getElementsByClassName('left')[0].innerHTML = input;
}
</script>
This is one of the many ways to do what you want:-
Write the following in console:
document.getElementsByTagName("div");
now you can see the total number of div elements used in your current document/page.
You can select one of your choice to work on by using "index number"(as in array index) for that particular div.
Lets say your div having class name = "right" is the 3rd one among the other div elements in your document.
This will be used to access that div element.
document.getElementsByTagName("right")[2].innerHTML = "whatever you want to write";
Attempted to log a label to console via
var labelTest = document.getElementById('js_8').label;
console.log(labelTest);
However it is returning undefined.
Edit: correcting some stuff, sorry at work and trying to do this in between other tasks. What my end result needs to be is targeting the inner html of the js_8 ID, but with React it is different for each of the Pages that it is on. So I want to add an extra stipulatoin of having that label attribute.
HTML:
<span data-reactroot="" label="1715724762040702" class="_xd6" data-pitloot-persistonclick="true" display="inline" data-hover="tooltip" data-tooltip-content="Copy Text to Clipboard" id="js_8"><div class="_xd7">1715724762040702</div></span>
I'm not sure exactly what you're after, but this is a way to connect a <label> and <input> together via JavaScript.
var some_id = 'someid',
my_label = getLabel(some_id);
function getLabel(id) {
return document.querySelector('[for=' + id + ']')
}
my_label.click();
<label for='someid'>My Label</label>
<input type='text' id='someid' />
You can associate a <label> with an <input>, <output>, <select> or <textarea> element in one of two ways:
The for attribute:
<label for="js_8">Test</label>
<input id="js_8">
Or by wrapping the element with a label:
<label>Test<input id="js_8"></label>
You can then access the associated label(s) as an array like this:
var labelsTest = document.getElementById('js_8').labels;
// labelsTest will be an array of 0 or more HTMLLabelElement objects
console.log(labelsTest);
Label-able elements can have more than one label.
So essentially I believe I am going to want to utilize var x = getAttribute("label") . The fact that the attribute was titled label confused me, and in turn I goof'd.
I have an HTML form where users can add an unlimited amount of a pair of text fields. I have used some Javascript so that each new text input has a Div surrounding it with a unique ID to identify each text field separately. Like this:
<div id="1">
<textarea name="firstTextArea"></textarea>
<textarea name="secondTextArea"></textarea>
</div>
<div id="2">
<textarea name="firstTextArea"></textarea>
<textarea name="secondTextArea"></textarea>
</div>
<div id="3">
<textarea name="firstTextArea"></textarea>
<textarea name="secondTextArea"></textarea>
</div>
and so forth.
How can I request this data from the form into Flask? It would be easy if there was a fixed number of inputs but the number of inputs will vary depending on what the user chooses.
One way I have thought of doing this is to count the number of input fields of the HTML form though I'm not sure how to count it using Javascript and then sending/requesting it to Flask along with the text field data.
What would be the best way to go about this?
I found a way to solve this issue using this code:
firstTextArea = []
secondTextArea = []
x = 1
while True:
try:
firstTextArea.append(request.form['firstTextArea' + str(x)])
secondTextArea.append(request.form['secondTextArea' + str(x)])
except:
break
x += 1
Instead of naming the DIVs, I uniquely named each textarea, so that I can identify them in the code above.
So I have a div that is drawing in dynamic elements at its bottom and I want to hide these elements, no matter what their IDs are using javaScript/jQuery. Basically my HTML looks like this:
<div class="right-panel">
<div class="info">Text</div>
<form id="the-form">
<input type="hidden" name="first-name" value="">
<input type="hidden" name="last-name" value="">
<input type="hidden" name="state" value="">
</form>
<script>javaScript</script>
<div id="dynamic-id-1">Advertisement 1</div>
<div id="dynamic-id-2">Advertisement 2</div>
</div>
I'd like to ensure that the "dynamic-id-1" and "dynamic-id-2" divs are always removed or hidden no matter what their ID's are (their IDs are subject to change). How do I target these elements without targeting their IDs?
Edit--I tried this, but my approach seems limited, and I couldn't get it to work with multiple divs, even when chaining:
$('#the-form').next().hide();
(Note: unfortunately they don't have a class, there are multiple divs, and the IDs are always completely different. I was hoping there might be novel way to target the last two divs of the wrapping div and hide them)
If the script tag is always before the div's that need removing you could do this -
$('.right-panel > script').nextAll('div').remove();
http://jsfiddle.net/w6d8K/1/
Based on what you tried you could do this -
$('#the-form').nextAll('div').hide();
http://jsfiddle.net/w6d8K/2/
Here are the docs for nextAll() - https://api.jquery.com/nextAll/
The simplest route would be to add classes to the dynamic elements. Something like:
<div class="removable-element" id="dynamic-id-1">Advertisement 1</div>
Then, you can do something like:
$(".right-panel .removable-element").remove()
If only one div at a time is generated dynamically. Add this to dynamic generation:
$('#the-form + div').hide();
Another method to achieve the same (not preferred) is:
$('#the-form').next('div').remove();
You are saying you don't want to target their "id", but is there some specific part in the id that will remain the same ?
like for instance "dynamic-id-" ?
If this is the case you can target them by using a "like selector". The code below would target all divs whose ID is starting with "dynamic-id"
$('div[id^=dynamic-id]').each(function () {
//do something here
});
Target the class instead of the dynamic ID.
<div class="element-to-remove" id="dynamic-id-1" />
<div class="element-to-remove" id="dynamic-id-2" />
$('.right-panel . element-to-remove').remove();
I want to search multiple HTML files from a separate page, where I search for text from all the divs which has a specific id for each, whole id containing matched search term will be displayed on the search page in list.
The div list looks like this :
<body>
<div class='vs'>
<div id='header 1'>content 1 here </div>
<div id='header 2'>another text </div>
<div id='header 3'>whatever </div>
</div>
</body>
Please note that I want to perform search from different page and want to display results there with links to the searchable page.
For now I was searching like this :
HTML
<body>
<input type="text" id='search' />
<div class='vs'>
<div id='header 1'>content 1 here </div>
<div id='header 2'>another text </div>
<div id='header 3'>whatever </div>
</div>
</body>
JavaScript
$('#search').on('input', function () {
var text = $(this).val();
$('.vs div').show();
$('.vs div:not(:contains(' + text + '))').hide();
});
It is working on the fiddle here, but I don't want it to work like this, I want to do the search from a separate page remotely and display results there with link to this page.
Solution with jQuery and AJAX:
<form id="searchForm">
<input type="text" id="search"/>
<input type="submit" name="Search!" />
</form>
<div id="resultContainer">
</div>
<script type="text/javascript">
$("#searchForm").submit(function(e) {
e.preventDefault();
var results = $("#resultContainer");
var text = $("#search").val();
results.empty();
$.get("http://example.com/", function(data) {
results.append($(data).find("div:contains(" + text + ")"));
});
});
</script>
Fiddle (This fiddle enables you to search for content on the jsfiddle page, try for example JSFiddle as search term.)
Note however that this does not work cross-domain, because browsers will prevent cross-site scripting. You didn't describe your use-case clear enough for me to know whether you're okay with that.
You'll want to look at using PHP file_get_contents to retrieve the HTML contents of the external page, and from there analyze the data in the <div>s that you are interested in. Ultimately, you'll want to store each individual search term in a JavaScript array (you can create JavaScript arrays dynamically using PHP), and then create search functionality similar to example you posted to search all the elements in your array.
So on page load, you'll want to have a <div> in which you are going to list all the elements from the array. You can list these by looping through the array and displaying each individual element. From there, you will want to call a function every time the user enters or deletes a character in the <input> box. This function will update the <div> with an updated list of elements that match the string in the <input> box.
This is the theory behind what you are trying to accomplish. Hopefully it will give you some direction as to how to write your code.
Update:
If you're looking for a JavaScript only solution, check out a JavaScript equivalent of PHP's file_get_contents: http://phpjs.org/functions/file_get_contents/
From here, you can maybe look at using .split to break up the list. Ultimately, you're still trying to store each individual search term as an element in an array, it's just the method that you retrieve these terms is different (JavaScript as opposed to PHP).
Perhaps I was emphasizing too much on PHP, perhaps it's because it's the web development language I'm most familiar with. Hope this JavaScript-only solution is helpful.