Why is console giving full jsFiddle link? [duplicate] - javascript

This question already has answers here:
this.href vs $(this).attr('href')
(3 answers)
Closed 5 years ago.
I wrote a little function which basically says to check if some text is exactly this or that:
function doSelect(text) {
return $wikiDOM.find(".infobox th").filter(function() {
return $(this).text() === text;
});
}
The I run this in order to get the last string after /wiki/ of some links like Geum River, Korea
let pattern = new RegExp('^\/wiki\/');
doSelect("Location").siblings('td').find('a').map(function(i, el) {
return console.log(el.href.replace(pattern, ''));
});
But when I check in console I get the whole jsFiddle link
https://fiddle.jshell.net/wiki/Geum_River
https://fiddle.jshell.net/wiki/Korea
I'd expect
Geum_River
Korea

The issue is because you're using the href attribute of the <a>. By doing this you retrieve the full absolute path of the URI, ie: https://fiddle.jshell.net/wiki/Geum_River instead of the relative path: /wiki/Geum_River
To change this behavior, use the attribute value directly, using attr():
let pattern = new RegExp('^\/wiki\/');
doSelect("Location").siblings('td').find('a').map(function(i, el) {
var result = $(this).attr('href').replace(pattern, '');
console.log(result);
return result;
});
Also double check that you're using map() correctly. It's intention is to create an array, but you're not doing anything with it's response. It would be worth using each() instead without the return if all you want to do is loop through the selected elements:
let pattern = new RegExp('^\/wiki\/');
doSelect("Location").siblings('td').find('a').each(function(i, el) {
var result = $(this).attr('href').replace(pattern, '');
console.log(result);
});

You can also try like this:
//let pattern = new RegExp('^\/wiki\/');
doSelect("Location").siblings('td').find('a').each(function(i, el) {
var name = $(this).attr('href').split('wiki/')[1].trim();
console.log(result);
});

Related

Block duplicates when adding to an array in JavaScript

I am beginner in JavaScript. I have this code:
var imageArray = [];
$(document).on("click", ".showPrv", function () {
$("#dropzone").each(function () {
$(".dz-image-preview").each(function () {
$(".dz-image").each(function () {
imageArray.push($(this).find("img").attr("src"))
});
});
});
console.log(imageArray);
})
This code works fine, but I have a problem with duplicates in my array imageArray. How can you block duplicates from being added to this table?
Try to use the includes() function.
Using it will be:
...
$(".dz-image").each(function () {
if(!imageArray.includes($(this).find("img").attr("src")))
imageArray.push($(this).find("img").attr("src"))
});
...
You can check if the value exists in the imageArray before pushing a new one, somewhat like this:
const imgSrc = $(this).find("img").attr("src");
if(!imageArray.includes(imgSrc)) {
imageArray.push(imgSrc);
}
I would recommend using a Set for this, as it allows for a quick lookups (O(1)) in order to check if the value already exists. Using an array forces you to do .includes() which takes O(n) time.
const imageSet = new Set();
...
const imgSrcAttr = $(this).find("img").attr("src");
if(!imageSet.has(imgSrcAttr)) {
imageSet.add(imgSrcAttr);
}
...
If at some point you need to convert the set to an array, you can simply use the spread-operator:
const imageArr = [...imageSet];
If the element was not found, -1 will be returned. Refer to $.inArray():
// If not in your array then
if($.inArray($(this).find("img").attr("src"), imageArray) === -1){
// Add value to imageArray
imageArray.push($(this).find("img").attr("src"));
}
Example of $.inArray() on JSFiddle for better understanding.

HTML DOM check if the text of an element includes specific text?

How to check if an element's innerHTML includes "as me to" (the whole phrase and not just if it includes one of the words)?
I know that it is pretty short, but the question is already stated in the title.
you can use indexOf()
var str = $('some selector id').innerHTML();
var result = str.indexOf("as");
if result is -1 then there is no instance of "as" in the given string.
You can check it using RegExp. If the element has given string, the test() function will return true or false if it's not.
function check(elem, str) {
var element = document.getElementById(elem).innerHTML,
rg = new RegExp(str, 'g'),
res = rg.test(element);
console.log(`Does the ${elem} element contains ${str} - ${res}`);
return res;
}
check('p', 'as');
check('p', 'something');
<p id='p'>ashamed</p>
Try this!
HTML
<div id="source">this word as </div>
JAVASCRIPT
var sourceEl = document.getElementById('source');
if (sourceEl.textContent.includes('as'))
{
alert("Exist");
}
https://jsfiddle.net/n3zkzy1g/5/

Selecting by text with Protractor

I am mostly familiar with java selenium, and I am new to both JS and Protractor. Lets say I am trying to click an option from a list of options with a common identifier..
var options = $('.options');
How could I get all elements with that common identifier, and then select one by its text? I can not do driver.findElements like I could in java since there is no reference to driver..
This is what I have tried so far but its not working and I think its due to my inexperience with JS
this.selectCompanyCode = function(companyCode) {
dropDownMenus[0].click();
var companyCodeOptions = $('[ng-bind-html="companyCode"]');
companyCodeOptions.filter(function (elem) {
return elem.getText().then(function text() {
return text === companyCode;
});
}).first().click();
};
Select all elements with common identifier: $$('.options'); That selects all elements with a class of .options -- equivalent of element.all(by.css('.options')). This returns an ElementArrayFinder. Also see .get() for how to choose an element by index from the ElementArrayFinder.
Find by text, you could use cssContainingText(css, text). For example,
var loginBtn = element(by.cssContainingText('button.ng-scope', 'Login'));
But if for some reason those are not providing the expected results, you can use .filter() (docs here) on an ElementArrayFinder to go through the array of elements and find an element based on a condition you specify. For example,
var allOptions = $$('.options');
allOptions.filter(function (elem) {
return elem.getText().then(function (text) {
return text === 'What you want';
});
}).first().click();
And, although I've never used regular Java Selenium (so I don't know if this is the same), but there is indeed a browser reference (and therefore findElements function): http://www.protractortest.org/#/api?view=ProtractorBrowser.
Hope it helps!
Edit:
Using your code:
this.selectCompanyCode = function(companyCode) {
// where is dropDownMenus defined? This has function no reference to it.
dropDownMenus.get(0).click(); // should be this
var companyCodeOptions = $$('[ng-bind-html="' + companyCode + '"]');
return companyCodeOptions.filter(function (elem) {
return elem.getText().then(function text() {
return text === companyCode;
});
}).first().click();
};
second edit:
Assuming company code is unique, you probably don't need to use filter. Try this:
this.selectCompanyCode = function(companyCode) {
dropDownMenus.get(0).click();
var companyCodeOptions = $('[ng-bind-html="' + companyCode + '"]');
return companyCodeOptions.click();
};
Use cssContainingText
element(by.cssContainingText(".option", "text")).click();
http://www.protractortest.org/#/api?view=ProtractorBy.prototype.cssContainingText

Get "id" values from first three tags only and separate them with "," in output

I have a situation, hope experts here will help me to sort it out. I need to get "id" values for first three tags and than on console.log print the values with comma separated.
I have managed to get the values from tag and print it on output. However, I am not able to comma separate them, and the issue is I am getting id of all the number of articles rather than only 3.
This is the jquery code that I come up with
jQuery(document).ready(function($) {
$("article").each(function() {
var info1 = $(this).attr("id");
var info2 = info1.replace( /[^\d]/g, '');
console.log(info2);
});
});
And this is the test
http://jsfiddle.net/0mvjbkhs/1/
Please note that I am not able to do any changes to html, all I can do is to get things done using jquery.
Please help to fix my code, So my output will looks like
[155569, 155570, 155571]
Thank you,
Use the jQuery .map() method which returns an array; if you need a single comma-delimited string, use the JavaScript .join() method. Don't forget :lt(3) which say you want the first three:
var arr1st3 = $('article:lt(3)').map(function() {
return this.id.replace(/[^\d]/g, '');
}).get();
console.log( arr1st3 );//OUTPUT: ["155569", "155570", "155571"]
//If you want [155569, 155570, 155571] as output
//use return +this.id.replace(/[^\d]/g, ''); instead
DEMO
jQuery(document).ready(function($) {
// search by the attribute
var ids = $('article')
// Take only the first three items
.slice(0, 3)
// Loop them to return an array
.each(function() {
// Get just the id and put that in the array
return this.attr('id');
});
// Format your output
console.log('[' + ids.join(', ') + ']');
});
http://jsfiddle.net/0mvjbkhs/4/
jQuery(document).ready(function($) {
var articles = [];
$("article").each(function() {
var info1 = $(this).attr("id").replace( /[^\d]/g, '');
articles.push(info1);
if (articles.length == 3) {
// break;
return false;
}
});
console.log('[' + articles.join(', ') + ']');
});

Replace() before html() and add "&" between two strings

Please check out this Fiddle Example. It searches for strings that contain "Glucosamine". How can I strip out "Glucosamine" and add an "&" if it returns two strings, like this:
A Item
Sulfate
B Item
Sulfate & HCl
I got an undefined error using .replace("Glucosamine","") after append.
JSON:
[{"title":"A","Ingredient":"Glucosamine Sulfate,Vitamin C"},{"title":"B","Ingredient":"Vitamin D,Glucosamine Sulfate,Glucosamine HCl,Vitamin A"}]
Code:
$.ajax({
url: "text.json",
success: function (data) {
$(data.query.results.json.json).each(function (index, item) {
var title = item.title;
var ingredients = item.Ingredient;
ingredients = ingredients.split(",");
$.each(ingredients,function(i,ingredient){
if (ingredient.indexOf("Glucosamine") >= 0) {
$('.' + title+'glu').append('<h5>'+ingredient+'</h5>')
}
});
});
},
error: function () {}
});
HTML:
<h3>A Item</h3>
<div class="Aglu"></div>
<h3>B Item</h3>
<div class="Bglu"></div>
Answer
The problem is that you are trying (as far as I can tell) to use replace on the jQuery object like so:
// this will not work
$('.' + title+'glu').append('<h5>'+ingredient+'</h5>').replace("Glucosamine","");
The problem is that replace() is a function of the String object in javascript and there is no replace method in the jQuery object. What you want to do is run replace() against the ingredient variable which is a string.
// this will work
$('.' + title+'glu').append('<h5>'+ingredient.replace("Glucosamine","")+'</h5>');
Not answer
However, based on your latest comment, I don't believe this will actually help you. Although it's unrelated to the actual problem you were having, I'll go ahead and quick put down here how I would approach what you are actually trying to do. I would write your function this way:
$(data.query.results.json.json).each(function (index, item) {
var title = item.title;
var ingredients = item.Ingredient;
// this is good. I like the use of split here
ingredients = ingredients.split(",");
// here I would just filter the array. Don't bother with indexOf.
// You can just as easily use regex. I've chosen to use an
// actual regex pattern but you can also use something like this
// just as easily: ingredient.match("Glucosamine");. I just
// chose to use regex for the sake of using i for case insensi-
// tivity. glucosamineBased is now an array of only the glucose
// ingredients
var glucosamineBased = ingredients.filter(function(ingredient){
return ingredient.match(/glucosamine\s/i);
});
// now that we know which ones are actually glucose based, we
// don't need to itterate through them. Instead we can just jump
// on combining them. I use join which works the opposite as
// split above. After they are joined into one big happy string,
// I strip out the glucosamine words. Easy-peasy. Just keep in
// mind that you need g for global (don't just replace the first
// one, but replace all instances of the pattern) and maybe i for
// case insensitivity.
$('.' + title+'glu').append('<h5>' +glucosamineBased.join(' & ').replace(/glucosamine\s/gi, '')+'</h5>');
});
Hope this helps.
Demo
http://jsfiddle.net/HANvQ/
(oops... forgot the demo)
It's trickier to add the ampersand if the array contains more than one instance of the word "Glucosamine", but the following should do the trick:
$(data.query.results.json.json).each(function (index, item) {
var title = item.title;
var ingredients = item.Ingredient;
ingredients = ingredients.split(",");
var string = '';
$.each(ingredients, function (i, ingredient) {
if (ingredient.indexOf("Glucosamine") >= 0) {
ingredient = ingredient.replace("Glucosamine","");
string += (string.length == 0) ? ingredient : " & "+ingredient;
}
});
$('.' + title + 'glu').append('<h5>' + string + '</h5>')
});
http://jsfiddle.net/wDyZd/2/

Categories