Prevent an undefined into one line code - javascript

Using document command there are some times which is not exist. Instead of using controls like document contains or type of into one if statement is it possible to make the control into one line and if the command doesn't exist take an NA like this:
document.querySelector('div#name span.fn').textContent || "NA";

You could do something like this:
(document.querySelector('div#name span.fn') || {}).textContent || "NA";
If the querySelector call evaluates to null, it will return the object, which won't have a textContent, so it will return NA.

Create a function for something like this.
function getTextContentOrDefault(selector, defaultValue) {
var element = document.querySelector(selector);
if (!element) return defaultValue;
if (!element.textContent) return defaultValue;
return element.textContent;
}
getTextContentOrDefault('div#name span.fn', 'NA');

Related

JavaScript: Pass conditional condition as value

I have a function that finds elements using jQuery. I then take that element, get a value from it and assign it to a variable. However, sometimes an element will not exist on the document and the function will return undefined. This is expected and if the element returned is undefined then the variable that gets assigned should also be undefined. Since I am using this function to assign variables many times I wanted to make it neat and on one line. I thought using conditionals might be a solution, however, doing this leads to really messy long lines and needing to call the function twice:
let html = $(response.body);
let language = getRowElementFromText('Language', html) ? getRowElementFromText('Language', html).find('a').text() : undefined;
let pages = getRowElementFromText('Page', html) ? parseInt(getRowElementFromText('Page', html).text()) : undefined;
Is it possible to resolve those issues and somehow pass the condition of the conditional to be used as the value? For example, in this pesudo code this would be the value of the conditional:
let html = $(response.body);
let language = getRowElementFromText('Language', html) ? this.find('a').text() : undefined;
let pages = getRowElementFromText('Page', html) ? parseInt(this.text()) : undefined;
If this not possible is there another more readable way I can accomplish this on one line?
It is/will be with the optional chaining operator that's new in ES2020 (available via transpilation today). the code would look like this (it only helps so much with the parseInt cas):
let language = getRowElementFromText('Language', html)?.find('a').text();
// −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−^
let pageText = getRowElementFromText('Page', html)?.text();
// −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−^
let pages = pageText ? parseInt(pageText) : undefined;
language would be undefined if the element wasn't found.
If you can't use it (because your target environments don't have it yet and you're not transpiling), you could pass in a function that getRowElementFromText will call if the element is found:
let html = $(response.body);
let language = getRowElementFromText('Language', html, el => el.find('a').text());
let pages = getRowElementFromText('Page', html, el => parseInt(el.text()));
getRowElementFromText would look like this:
function getRowElementFromText(text, html, callback) {
const result = /*...existing logic...*/;
return result === undefined ? undefined : callback(result);
}
Or perhaps like this (callback is optional):
function getRowElementFromText(text, html, callback) {
const result = /*...existing logic...*/;
return !callback || result === undefined ? result : callback(result);
}
Note: In the above I'm assuming getRowElementFromText does actually return undefined in some cases ("not found"), and returns a jQuery object in other cases (found). I flag this up because if it always returns a jQuery object (which may be empty), jQuery objects are never falsy (not even empty ones).
Add the following function to jQuery prototype. It receives a fallback string as an argument and when element is not found, returns fallback string:
$.prototype.getText = function(fallback = undefined) {
return this.length > 0 ? this.text() : fallback
}
console.log($("#foo").getText())
console.log($("#bar").getText("If the element does not exists, returns given fallback string"))
console.log(`Fallback string default value is: ${$("#baz").getText()}`)
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<label id="foo">If the element exists, return its inner text</label>
Usage:
$(selector).getText(fallbackString);

JavaScript: querySelector Null vs querySelector

What is the main difference between these two methods of referencing?
What are the benefits of using one or the other? Also what kind of usage-case would they each be best suited to?
var selection = document.querySelector('.selector') !== null;
var selection = document.querySelector('.selector');
Is the former solely for browser legacy support?
The first one gets the reference and checks if the element exists, and saves this status as a boolean value in the variable. If the element exists, the variable contains true otherwise false.
You would use the first one if you only want to know if the element exists, but don't need the reference to it.
Example:
var selection = document.querySelector('.selector') !== null;
if (selection) {
alert('The element exists in the page.');
} else {
alert('The element does not exists in the page.');
}
The second one gets the reference and stores in the variable, but doesn't check if the element exists. If the element exists, the variable contains the reference to the element, otherwise the variable contains null.
You would use the second one if you need the reference to the element. If it's possible that the element doesn't exist in the page, you should check if the variable contains null before you try to do something with the reference.
Example:
var selection = document.querySelector('.selector');
if (selection !== null) {
alert('I have a reference to a ' + selection.tagName + ' element.');
} else {
alert('The element does not exists in the page.');
}
you could also do:
[].filter.call([document.querySelector('.single-selected-class')], item => item)
.forEach(item => item.blur());
The first statement contains a bool value depends on document.querySelector('.selector') is null or not
var selection = document.querySelector('.selector') !== null;
the second statement contains the actual value of document.querySelector('.selector');
var selection = document.querySelector('.selector');
You can try to avoid the conditional statement with:
var selection = document.querySelectorAll('.selector');
selection.forEach(function(item) {
alert(item);
});
Caution! querySelectorAll() behaves differently than most common JavaScript DOM libraries, which might lead to unexpected results
Source: https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelectorAll
I was developing a similar solution for CMS EFFCORE and came up with the following:
if (!Node.prototype.hasOwnProperty('querySelector__withHandler')) {
Object.defineProperty(Node.prototype, 'querySelector__withHandler', {
configurable: true,
enumerable : true,
writable : true,
value: function (query, handler) {
var result = this.querySelector(query);
if (result instanceof Node) {
handler(result);
}
}
});
}
document.querySelector__withHandler('a', function(link){
alert(link)
})

Check if an element is closed using a discrete tag with JavaScript

I am getting the child nodes of en element and i want to check if the tags can actually contain text. For example:
<br />, <img />
Should return false and
<span></span>, <div></div>, <li></li>
should return true. Thanks!
Unfortunately, there is no way to detect how a tag was written in the code, since when the JavaScript runs, the HTML code has already been parsed into DOM objects.
However, your question seems to be more about whether a particular element type can contain text. This simple test will give you an answer per element type:
function canElementContainText(tagname) {
try {
var e = document.createElement(tagname);
return e.outerHTML.indexOf("/") != -1;
} catch (ex) {
return false;
}
}
For instance canElementContainText("div") returns true and canElementContainText("img") returns false.
You can then pass the tagName property of any element to this function to test it.
var result = canElementContainText(myElement.tagName);
Following script works just fine (cross-browser issue resolved):
function containTxt(tag) {
var tags = /^(img|video)$/i; // any values which will be in `tags` set will be treated as they can't have a text value
return !tags.test(tag);
}
console.log(containTxt("img")); // returns false
console.log(containTxt("div")); // returns true
use that:
canContainText: function(node) {
if(node.nodeType === 3){
return true;
}
if(node.nodeType === 1){
return /<[^>]+><\/[^>]+>/gi.test(document.createElement(node.nodeName.toLowerCase())).outerHTML;
}
}
Could use RegEx:
// these are samples, get elements text using element.innerHTML;
var one = "<a href='something'>Links</a>";
var two = "Lorem ipsum dolor";
function check(str){
return str.match(/<[a-zA-Z]+.*>(.|\n)*<\/[a-zA-Z]+>/) ? true : false;
}
console.log(check(one)); // true
console.log(check(two)); // false

My function returns empty. why?

I know that this is a basic question but I am stuck with it somewhere in my code. I got that code from somewhere but now I am modifying it according to my need.
What does jQuery('#selector') do? In my code it always return empty.
Here is my code
query: function (selector, context) {
var ret = {}, that = this, jqEls = "", i = 0;
if(context && context.find) {
jqEls = context.find(selector);
} else {
jqEls = jQuery(selector);
}
ret = jqEls.get();
ret.length = jqEls.length;
ret.query = function (sel) {
return that.query(sel, jqEls);
}
return ret;
}
when I call this query function then I pass selector as parameter. When I do console.log(selector) it does have all the selectors which I need in this function. But the problem is on this line jqEls = jQuery(selector);. when I do console.log(jqEls) after this it returns empty thus the whole function returns empty.
Can I use something different then this to make it work?
jquery('#selector') is the equivalent of document.getElementById('selector'). If there is no DOM node with an id of selector, you get an empty result.
e.g.
<div id="selector">...</div>
would return the dom node corresponding to this div. Do you have jquery loaded?
jQuery(selector) is looking for a DOM element that meets the selector criteria.
$('#example') == jQuery('#example')
Both will look for something with id "example"
$(selector).get() will return undefined if no element is found. This is why your function returns undefined. To fix this, you could use a default value if there is no element found:
ret = jqEls.length ? jqEls.get() : {};
This way your function will always return an object that has your length and query properties, but it will not have an element if jQuery did not find one.
After reading your code I have a question : do you put the # in your variable selector ?
A solution to solve this by replacing the bad line by jqEls = jQuery("#" + selector);
If the problem isn't due to that can you say the type of selector ? string ? object ? jQueryObject ?

check if html attribute exist and has right value with jquery

Is there a better way for checking an attribute for:
it exist. so value must be false if attribute doesn't exist
Value is correct (boolean)
var isOwner = false;
if ($(selectedItem).is('[data-isOwner="True"]') || $(selectedItem).is('[data-isOwner="true"]')) {
isOwner = true;
} else {
isOwner = false;
}
Now I need to check for 'True' and 'true'...
Thanks
You can convert the value stored in data-isOwner to lower case and only compare the value to 'true'.
if (($(selectedItem).attr ('data-isOwner') || '').toLowerCase () == 'true')
The above use of <wanted-value> || '' will make it so that if the selectedItem doesn't have the attribute data-isOwner the expression will result in an empty string, on which you can call toLowerCase without errors.
Without this little hack you'd have to manually check so that the attribute is indeed present, otherwise you'd run into a runtime-error when trying to call toLowerCase on an undefined object.
If you find the previously mentioned solution confusing you could use something as
var attr_value = $(selectedItem).attr ('data-isOwner');
if (typeof(attr_value) == 'string' && attr_value.toLowerCase () == 'true') {
...
}

Categories