In JS, I'm having trouble working out how to split a string coming from an AJAX call.
This is what I have so far:
xmlhttp.onreadystatechange = function()
{
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
feedUpdateResponse = xmlhttp.responseText;
/////...split script.../////
}
}
xmlhttp.open("GET","https://myDomain.com/myScript.aspx",true);
xmlhttp.send();
Where you have /////...split script...///// in my script above, I need to add a little function that splits the string returned from my AJAX call.
The string simply contains names of DIVs, like this:
feedUpdateResponse = "div1/div2/div3/div4"
I would like to first split the string by its slashes (/) and run a loop through the different values and do stuff to those elements on my page.
To give an idea of what I need to achieve, I have given this example which is a mix of ASP & JS - it's the only way I can possibly describe it (and show that I've had an attempt) :)
MyArray = Split(feedUpdateResponse,"/")
For Each X In MyArray
documentGetElementById('updateAvailable_'+x).style.visibility="visible";
Next
On my page I have an ASP script that produces jquery carousels, all contained by separate DIVs. The DIVs are named DIV1, DIV2 etc. Inside DIV1, for example, is a text element called updateAvailable_div1 which will alert the user "There are new photos available for this feed, please click the refresh button".
Could somebody please explain to me how I can change my example above to work in JS? Just need to split the string into an array and loop through the split values...
You can use .split() to split a string on a specified character with the results returned as an array. So then it's just a matter of looping through the array:
// given your existing variable
// feedUpdateResponse = "div1/div2/div3/div4" as set in the
// code in the question, add this:
var a = feedUpdateResponse.split("/"),
i;
for (i = 0; i < a.length; i++) {
document.getElementById("updateAvailable_" + a[i]).style.visibility
= "visible";
}
Get your array via string.split("/"). Iterate your array using your method of choice. I prefer Array.forEach():
feedUpdateResponse.split("/").forEach(function (item) {
document.getElementById(item).style.visibility = "visible";
});
See the compatibility notes for using .forEach() in older browsers.
As an alternative:
for(element of feedUpdateResponse.split("/")){
do_your_thing();
}
Using for..in will end up giving you the indices on the array (keys), while for..on will give you the elements of the array (values).
You can also do:
for ([index, element] of Object.entries(feedUpdateResponse.split("/"))) {
do_your_thing();
}
In the event that you need the index.
The disadvantage is it not being compatible with IE, but for personal projects or a quick automation script it usually does me plenty fine.
Try this code:
var a = feedUpdateResponse.split("/");
for (i in a) {
document.getElementById("updateAvailable_" + a[i]).style.visibility
= "visible";
}
var feedUpdateResponse = "div1/div2/div3/div4";
var feedUpdateSplit = feedUpdateResponse.split("/");
for (var x = 0; x < feedUpdateSplit.length; x++) {
document.getElementById("updateAvailable_" + feedUpdateSplit[x]).style.visibility = "visible";
}
Related
I have a few comma-separated URLs as shown below.
https://drive.google.com/open?id=17kTY2b3XvERC4wqZnLt7sVwMe8ZoDZUD, https://drive.google.com/open?id=1En1tNNLEgz5JiIk2GJnjNb_bhk23YJb2, https://drive.google.com/open?id=2En1tNNLEgz5JiIk3GJnjNb_bhk23YJb2
I need to get just the IDs (Example: 17kTY2b3XvERC4wqZnLt7sVwMe8ZoDZUD) from it in an array.
I'm a rookie coder and would appreciate it if someone can help me with the code.
Use the URL parsing library built-in to the browser. Don't attempt to use regular expressions to pick apart the URL because you don't have to (and you might end up getting it wrong).
var u = new URL("https://drive.google.com/open?id=2En1tNNLEgz5JiIk3GJnjNb_bhk23YJb2");
console.log(u.searchParams.get('id'));
> "2En1tNNLEgz5JiIk3GJnjNb_bhk23YJb2"
You could use string.split("?id=") and get the second element from the array returned (element 0 for everything to the left, 1 for the right)
E.G:
<script>
var myArray = ["https://drive.google.com/open?id=17kTY2b3XvERC4wqZnLt7sVwMe8ZoDZUD",
"https://drive.google.com/open?id=1En1tNNLEgz5JiIk2GJnjNb_bhk23YJb2",
"https://drive.google.com/open?id=2En1tNNLEgz5JiIk3GJnjNb_bhk23YJb2"];
for(var i=0; i<myArray.length; i++)
{
var result = myArray[i].split("?id=")[1];
console.log(result);
}
</script>
I have little to no experience of JavaScript but I do know that the getElementID only carries one value so how can I have 2 values passed?
Can I use it twice like I have down below or would I be better to use another GetElementBy/GetElementsBy method to do it?
<script type="text/javascript">
$(document).ready(function () {
hash();
function hash() {
var hashParams = window.location.hash.substr(1).split('&');
for (var i = 0; i < hashParams.length; i++) {
var p = hashParams[i].split('=');
document.getElementById("<%=start.ClientID%>").value = decodeURIComponent(p[1]);
document.getElementById("<%=end.ClientID%>").value = decodeURIComponent(p[1]);;
}
}
});
</script>
EDIT
So I've decided to use the loop twice and its working but the values I'm passing contain text I need removed. Is there a way in which I can cut off the split after a certain character? Here is my new code
<script type="text/javascript">
$(document).ready(function () {
hash();
function hash() {
var hashParams = window.location.hash.substr(1).split('#');
for (var i = 0; i < hashParams.length; i++) {
var p = hashParams[i].split('=');
document.getElementById("<%=start.ClientID%>").value = decodeURIComponent(p[1]);
}
var hashParams = window.location.hash.substr(1).split('&');
for (var i = 0; i < hashParams.length; i++) {
var p = hashParams[i].split('=');
document.getElementById("<%=end.ClientID%>").value = decodeURIComponent(p[1]);;
}
}
});
</script>
And here is the text that appears in the search bar when forwarded from the previous page.
localhost:56363/Bookings.aspx#start=27/02/2018 12:30&end=27/02/2018 17:30
The start and end input boxes fill with the values but the start input box (27/02/2018 12:30&end) has characters I want cut off (&end).
Is there a way to stop a split after a certain character?
Using it twice as you have is perfectly acceptable. And, if they are separate things, then it makes sense.
While you could also use getElementsByTagName(), getElementsByName() or getElementsByClassName(), usually using document.querySelectorAll() is the more modern choice.
If they have something in common with them (like say a class), you could use it like this:
const nodeList = document.querySelectorAll('.classToGet');
Array.prototype.forEach.call(nodeList, element => element.value = decodeURIComponent(p[1]));
document.querySelectorAll() (as well as the getElementsBy functions) return a NodeList, which is kind of like an Array, but doesn't have an Array's functions, so you need to Array.prototype.forEach.call() to loop over them.
document.querySelectorAll() accepts a string like you would give to CSS, and the NodeList has all elements that match that.
And FYI, there is an equivalent document.querySelector() which gets a single element, so you could use it for IDs:
document.querySelector("#<%=start.ClientID%>")
Note the # like you would have for CSS at the beginning.
ID is a unique identifier, unlike class, so there should be only one of it with the same name in your DOM.
getElementById is intended to find the one element in the DOM with the specified ID.
If you need to get multiple elements, then yes make multiple calls to getElementById.
See here for the documentation on the getElementById method showing that it only accepts a single ID parameter: https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementById
I'm using a javascript function that uses regular expressions to get a list of images without an alt/title attribute:
function AltTitle(aSourceHTML, aResultField) {
try {
regexp = /<img((?:(?!alt)[^<>])*)>/gim;
var vArray = aSourceHTML.match(regexp);
var vLinks = vArray.join("\n\n");
aResultField.value = vLinks;
} catch (err) {
alert("No Images Found");
}
}
Is there any way to get the line numbers along with the image list?
Try using DOM instead to grab the images.
var imgs = [].filter.call(document.images, function(img) {
return !img.alt && !img.title;
});
This will grab all images that don't have alt or title attribute or is empty, but it won't tell you what line the image is at. Try using http://validator.w3.org/ to find that out.
I would say "The Pony He Comes", but this seems to be more dealing with the plain text than the actual HTML.
The way I would do this is to first just split the whole thing on newlines, then loop through each line and run your regex against it. Since you're iterating through the lines, just print out the current iterator value and there you have your line number.
If you already have the source code in a variable, you can split it up by line breaks, and then run your regex against each line.
function AltTitle(aSourceHTML, aResultField) {
aSourceHTML = aSourceHTML.split('\n');
for (var i = 0; i < aSourceHTML.length; i++ {
// run your regex against aSourceHTML[i]...
}
}
If you are trying to do this for a specific page, such as the one you are on, you can do an ajax request for it, and then split that by line breaks and run through it. Try running the following code right here on Stack Overflow in a console. It will show the HTML of this page, with line numbers.
$.get(window.location, function(data){
data = data.split('\n');
for (var i = 0; i < data.length; i++) {
console.log('line ' + i, data[i]);
}
});
But unless you're trying to write a tool for this in javascript, you should just use http://validator.w3.org/. It will find any images without alts/titles for you.
Edit: Wrote an example of how this could work on jsfiddle: http://jsfiddle.net/c8X4K/
I have a form that I want to only submit post data for value which have changed.
So the way I have been doing this is like this:
function submit_form(){
var hd = [];
// hd is a big array that is defined here
// hd ['some id_number'] = 'some value'
// main function
for (var id_number in hd ){
var x=document.getElementById(id_number).selectedIndex;
var y=document.getElementById(id_number).options;
selector_text = y[x].text;
if (hd[id_number] == selector_text){
$(id_number).remove();
}
}
document.forms["my_form"].submit()
}
So the goal is that if the selector equals what is in the array, then don't POST the data.
To do this I have been doing the remove function. Everything up to the remove function works as expected. However when I look at the post data I still get the selected value for the id_numbers that mach the value in hd.
Is there a better way to remove to prevent it from going to the POST data? The id.parent.removeChild(id) method didn't work either.
The jQuery id selector should begin with a #, but yours appears not to:
$('#' + id_number).remove();
Your for-in loop should be a regular incremental for loop, which is the proper way to iterate an array in JavaScript. for-in loops are typically used for iterating object properties rather than array elements.
for (var i=0; i<hd.length; i++) {
// Access hd[i] in the loop
var x=document.getElementById(hd[i]).selectedIndex;
var y=document.getElementById(hd[i]).options;
selector_text = y[x].text;
if (hd[i] == selector_text){
$('#' + hd[i]).remove();
}
}
Since you aren't really using jQuery here except for that line, instead the plain JS version is:
var removeMe = document.getElementById(hd[i]);
removeMe.parentNode.removeChild(removeMe);
A jQuery selector $(".thumb_up") returns a collection of forms like this:
[<form id="like_post_78" ...</form> <form id="like_post_79"> ... </form>]
Ultimately I want to generate a string consisting of the numerical ending portion of the form ids.
"78,79"
What's the most efficient way of getting this?
The easiest way is probably:
var form_ids = $('form').map(function(){return this.id.replace(/[a-z_]/gi,'');}).get().join(', ');
console.log(form_ids); // or alert() or whatever...
JS Fiddle demo.
I've just updated the regex portion of the above, from /[a-z_]/gi to /\D/g (which basically greedily (g) replaces any non-digit characters (\D) with 'nothing'), to give the following code:
var form_ids = $('form').map(function(){return this.id.replace(/\D/g,'');}).get().join(', ');
console.log(form_ids);
JS Fiddle demo.
Edited after thinking on #James Hill's accurate observation (below) that easiest != most efficient:
keep in mind that the OP asks for the most efficient method, not the easiest.
Therefore, using plain JavaScript (which should, to the best of my knowledge, be available cross-browser):
var form_ids = [];
var forms = document.getElementsByTagName('form');
for (var i=0; i<forms.length; i++){
form_ids.push(forms[i].id.replace(/\D/g,''));
}
console.log(form_ids.join(', '));
JS Fiddle demo.
With a comparison of the two over at JS Perf, showing that JavaScript tends to be the faster (which implies it's more efficient, presumably because it's running native JavaScript/ECMAscript, rather than abstracted code that then calls native JavaScript/ECMAscript...)).
References:
map().
get().
join() at the MDN.
replace() at the MDN.
Option 1
Use jQuery's each() function in combination with the class selector:
var aryIDs = [];
$(".thumb_up").each(function(){
//Add ID to the array while stripping off all non-numeric data using RegEx
aryIDs.push(this.id.replace(/\D/g, ""));
});
//Get the ids
var csvIDs = aryIDs.toString();
Option 2
Grab the elements with jQuery and then use a plain old for loop:
var aryIDs = [];
var divs = $(".thumb_up");
for(var i= 0; i < divs.length; i++)
{
aryIDs.push(divs[i].id.replace(/\D/g, ""));
}
var csvIDs = aryIDs.toString();
Here's a working jsFiddle of the latter example.
Performance
As for performance, the for loop should be faster every time. Check out a simple jsPerf I created to compare the performance of .each(), .map(), and a standard for loop.
var str = "";
$(".thumb_up").each(function(){
var id = $(this).attr('id').split('like_post_');
str += id[1] + ',';
});
You'll end up with an extra "," at the end, but you can get to what you want with this basic example.
Just for the record, there is a document.forms collection that is every form in the document, so getting an array of all form ids is as simple as:
var ids = [];
var forms = document.forms;
for (var i = forms.length; i;) {
ids[--i] = forms[i].id;
}
If your definition of "efficiency" means fastest, the above should run rings about any of the jQuery answers (it does). If you only want forms with a particular class, it wouldn't be hard to filter them out with test of the form's className property in the loop.