Only include a variable in an if statement, if another variable exists? - javascript

The following function is meant to check to see if a custom Date widget (javascript) is empty or not. Problem is, there are many variations of this widget where M/D/Y fields display, or it could be M/D or, M/Y.
Of course, I could hard code all the combinations as if checks, but is there a better way of saying "there are 3 possible nodes, that might have values...if x out of 3 nodes exist AND they all have values, set empty to false."
checkIfEmpty: function () {
var empty = true;
var mNode = this.getNode('month');
var month = mNode ? mNode.value : null;
var dNode = this.getNode('day');
var day = dNode ? dNode.value : null;
var yNode = this.getNode('year');
var year = yNode ? yNode.value : null;
if (month && day && year) {
empty = false;
}
return empty;
}

checkIfEmpty: function () {
var empty = true;
var dateParts = [];
var mNode = this.getNode('month');
if(mNode && mNode.value){
dateParts.push('month');
}
var dNode = this.getNode('day');
if(dNode && dNode.value){
dateParts.push('day');
}
var yNode = this.getNode('year');
if(yNode && yNode.value){
dateParts.push('year');
}
if (dateParts.length) {
empty = false;
}
return empty;
}

You can add to see if the node does not exist
if ( (!mNode || month) && (!dNode || day) && (!yNode || year) ) {

checkIfEmpty: function () {
var empty = false;
var mNode = this.getNode('month');
if(mNode && !mNode.value) {
empty = true;
}
var dNode = this.getNode('day');
if(dNode && !dNode.value) {
empty = true;
}
var yNode = this.getNode('year');
if(yNode && !yNode.value) {
empty = true;
}
return empty;
}
Trying to solve my own question - so far, this is the most efficient way of achieving what I am trying to do. Anyone, suggestions on how to make it even more efficient?

If the value property exists for all valid nodes then:
if(mNode && dNode && yNode){
empty = false;
}
Otherwise:
if(mNode && mNode.value && dNode && dNode.value && yNode && yNode.value){
empty = false;
}
I am not sure if I followed, but if you need that at least one to be true so empty is false then:
if(mNode || dNode || yNode) {
empty = false;
}
Again, if the value property is not standard for all nodes:
if((mNode && mNode.value) || (dNode && dNode.value) || (yNode && yNode.value)){
empty = false;
}
I think it's clearer if you think about it this way:
If (node && node.value) returns a truthy value then the date property exists otherwise the date property doesn't exist.

Related

javascript inner/sub function returns issue

My Problem is that if validation_form function return false it stop execute and does not process other statement.
I need to execute all statement at once.
My code for validating form is as below.
jQuery("#submitsuggestevent").click(function (e) {
e.preventDefault();
var flag = true;
var event_title = $('#title');
var country = $('select[name="country"]');
var state = $('select[name="state"]');
var venue = $('select[name="venue"]');
var category = $('select[name="category"]');
flag = flag && validation_form(event_title);
flag = flag && validation_form(country);
flag = flag && validation_form(state);
flag = flag && validation_form(venue);
flag = flag && validation_form(category);
if(flag){
$('#frmevents').submit();
}
});
function validation_form(ele) {
if ($.trim(ele.val()) == '' || typeof(ele.val()) === 'undefined') {
return false;
}
else {
return true;
}
}
This could be the problem
flag = flag && validation_form(event_title);
flag = flag && validation_form(country);
flag = flag && validation_form(state);
flag = flag && validation_form(venue);
flag = flag && validation_form(category);
javascript runtime may be smarter and convert above code block to
flag=validation_form(event_title)&&validation_form(country)&&validation_form(state)&&validation_form(venue)&&validation_form(category);
As you know in && operations if left side evaluated to false right side is ignored(as false&&whatever is false anyway).
Solution is to have something like
var val_title = validation_form(event_title);
var val_country = validation_form(country);
etc and finally
flag = val_title&& val_country&&....

JavaScript true false not executing correctly in if else statement

For some reason when I'm using the true/false values and checking if at least one of the values is true, the if/else statement is not working correctly.
I have this:
$scope.checkValues = function (qId) {
var airport = $scope.airports[0].questID;
var destAirport = $scope.destAirports[0].questID;
var airportVal = isFalseOrUndefined($scope.answers[airport]);
var destAirportVal = isFalseOrUndefined($scope.answers[destAirport])
if (airportVal == false || destAirportVal == false) {
$surveyNav.skipPage = true;
}
}
function isFalseOrUndefined(val) {
if(val == null || val === false) {
return true;
} else {
return false;
}
}
In this image below, as you can see the value for airportVal is true, the other value for destAirportVal in that same scenario is true, but I'm still able to get correctly in to the if condition and set the scope value.
Does anyone see any issue?
You should be using === and !== operators when checking for equality in Javascript.
Javascript Comparison and Logical operators
op1 === op2 - Will check if op1 is explicitly equal to op2
op1 !== op2 - Will check if op1 is not explicitly equal to op2
Also: you can condense you isFalseOrUndefined function
Note 1: you are not actually checking if val is undefined.
To check if something is undefined: typeof val === 'undefined'
This is different than checking if a variable is null
Note 2: Keep in mind that your variables are not entirely clear here. airportVal will be equal to true when $scope.answers[airport] is false or null. Is this your intention?
$scope.checkValues = function (qId) {
var airport = $scope.airports[0].questID;
var destAirport = $scope.destAirports[0].questID;
var airportVal = isFalseOrUndefined($scope.answers[airport]);
var destAirportVal = isFalseOrUndefined($scope.answers[destAirport])
if (airportVal === false || destAirportVal === false) {
$surveyNav.skipPage = true;
}
}
function isFalseOrUndefined(val) {
return (val === null || val === false);
}
Your function should probably do what it claims to do:
function isFalseOrUndefined(val) {
return typeof val === 'undefined' || val === false || val === null || val === ''/* add this if you think it should be falsy*/;
}
But then, testing for !val should be sufficient:
$scope.checkValues = function (qId) {
var airport = $scope.airports[0].questID;
var destAirport = $scope.destAirports[0].questID;
if (!airport || !destAirport) {
$surveyNav.skipPage = true;
}
}

Restrict duplicate entries in json localstorage using Javascript

I went through few link, but that didnt help me. I have to restrict duplicate titles in json array. What is way to do here??
function submitForm(){
var titleInput=document.getElementById('titleName').value;
var messageInput=document.getElementById('titleDesc').value;
var oldItems = JSON.parse(localStorage.getItem('itemsArray')) || [];
var newItem = {
"title":titleInput ,
"desc": messageInput
};
if(!(titleInput=="" || messageInput=="")){
oldItems.push(newItem);
}
}
Try this:
if (!(titleInput == "" || messageInput == "")) {
var repeated = false;
for (var i = 0; i < oldItems.length; i++) {
if (oldItems[i].titleInput == titleInput) {
repeated = true;
break;
}
}
if (repeated == false) {
oldItems.push(newItem);
}
}
You could simply check wheter the item is there before adding it.
var alreadyExists = oldItems.some(function (item) { return item.title == titleInput; });
if(!(titleInput=="" || messageInput=="") && !alreadyExists) {
oldItems.push(newItem);
}
Then perhaps you should make the concept more explicit by encapsulating that logic within an ItemStore or something similar.
function ItemStore(items) {
this._items = [];
this._titleMap = {};
this.addAll(items || []);
}
ItemStore.prototype = {
constructor: ItemStore,
hasItemTitled: function (title) {
return !!this._titleMap[title];
},
add: function (item) {
var title = item.title;
if (this.hasItemTitled(title)) throw new Error("the store already contains an item titled '" + title + "'");
this._titleMap[title] = true;
this._items.push(item);
},
addAll: function (items) {
items.forEach(this.add.bind(this));
},
items: function () { return this._items.slice(); }
//other useful methods such as itemAt, remove...
};
Then your code becomes as simple as...
var titleInput=document.getElementById('titleName').value;
var messageInput=document.getElementById('titleDesc').value;
var oldItems = new ItemStore(JSON.parse(localStorage.getItem('itemsArray')) || []);
var newItem = {
"title":titleInput ,
"desc": messageInput
};
var shouldAddItem = titleInput != "" && messageInput !="" && !oldItems.hasItemTitled(newItem.title);
if (shouldAddItem) oldItems.add(newItem);
Now obviously, your function is still doing too much since it:
knows how to retrieve and create a new item from the user's input
knows how to rehydrate the item store
knows what to check to validate if an item is valid and should be added or not
You should be reading about the Single Responsability Principle, which isin't only applicable in OO.

Javascript IE 7 getting OBJECT element

I'm making a code that removes a videoplayer from the page and then places it back when needed (even if the element doesn't have an id).
I'm finding issues with IE7
Here is my code:
var weboElem, weboElemPar, weboElemIndex, weboStored;
function weboRemoveVideoplayer(vpId){
weboElem = document.getElementById(vpId);
if(!weboElem) return false;
weboElemPar = weboElem.parentNode;
weboElemIndex = 0;
var child = weboElem;
while( (child = child.previousSibling) != null )
weboElemIndex++;
weboElemPar.removeChild(weboElem);
return true;
}
function weboPlaceVideoplayerBack(){
if(weboElemPar.insertBefore !== undefined && weboElemPar.childNodes !== undefined)
{
weboElemPar.insertBefore(weboElem, weboElemPar.childNodes[weboElemIndex]);
return true;
}
return false;
}
var result = document.evaluate(
'//*/param[contains(#value, "autoplay=1")]/..', // XPath expression
document, // context node
null, // namespace resolver
XPathResult.ORDERED_NODE_SNAPSHOT_TYPE
);
if(result.snapshotLength > 0)
{
var node = result.snapshotItem(0);
node.id = "webo";
document.getElementById('info').innerHTML = node.nodeName.toLowerCase()+" -> "+node.id;
} else document.getElementById('info').innerHTML = "not found";
(Note that document.evaluate WORKS because I imported javascript-xpath library)
On IE7 if the XPath finds an IFRAME there are no problems and it works but if it finds an OBJECT does nothing and stops at weboElem = document.getElementById(vpId); as if it didn't find the id.
I tried modifying the code like this:
if(result.snapshotLength > 0)
{
var node = result.snapshotItem(0);
node.id = "webo";
node.parentNode.removeChild(node);
document.getElementById('info').innerHTML = node.nodeName.toLowerCase()+" -> "+node.id;
if(node.nodeName.toLowerCase() == "object") weboStored = node;
else weboStored = null;
} else document.getElementById('info').innerHTML = "not found";
and it works, the videoplayer disappears at page load. I want to use the function though, so I edited everything like this (storing the node into a global var that later I get in the weboRemoveVideoplayer function):
var weboElem, weboElemPar, weboElemIndex, weboStored;
function weboRemoveVideoplayer(vpId){
if(!weboStored) weboElem = document.getElementById(vpId);
else weboElem = weboStored;
if(!weboElem) return false;
weboElemPar = weboElem.parentNode;
weboElemIndex = 0;
var child = weboElem;
while( (child = child.previousSibling) != null )
weboElemIndex++;
weboElemPar.removeChild(weboElem);
alert("5");
return true;
}
function weboPlaceVideoplayerBack(){
if(weboElemPar.insertBefore !== undefined && weboElemPar.childNodes !== undefined)
{
weboElemPar.insertBefore(weboElem, weboElemPar.childNodes[weboElemIndex]);
return true;
}
return false;
}
// bind XPath methods to document and window objects
// NOTE: This will overwrite native XPath implementation if it exists
//XPathJS.bindDomLevel3XPath(); //solo per xpathJs
var result = document.evaluate(
'//*/param[contains(#value, "autoplay=1")]/..', // XPath expression
document, // context node
null, // namespace resolver
XPathResult.ORDERED_NODE_SNAPSHOT_TYPE
);
if(result.snapshotLength > 0)
{
var node = result.snapshotItem(0);
node.id = "webo";
node.parentNode.removeChild(node);
document.getElementById('info').innerHTML = node.nodeName.toLowerCase()+" -> "+node.id;
if(node.nodeName.toLowerCase() == "object") weboStored = node;
else weboStored = null;
} else document.getElementById('info').innerHTML = "not found";
This way the code blocks itself when trying to retrieve the parent node.
Could someone suggest me what to do here?
PS: with chrome and firefox the code works perfectly in the first version I posted.
Fixed it!
I solved the issue by wrapping the OBJECT inside a div with an id of my choice which I can retrieve whenever I want. I do this in the resolveXpath function.
Here the code:
var weboElem, weboElemPar, ieObject = false;
var weboElemIndex = 0;
function weboRemoveVideoplayer(vpId){
var child;
if(!ieObject) weboElem = document.getElementById(vpId);
else weboElem = document.getElementById('my_usage');
if(!weboElem) return false;
weboElemPar = weboElem.parentNode;
weboElemIndex = 0;
child = weboElem;
while( (child = child.previousSibling) != null ) weboElemIndex++;
if(typeof weboElemPar.removeChild !== 'undefined') weboElemPar.removeChild(weboElem);
else return false;
return true;
}
function weboPlaceVideoplayerBack(){
if(typeof weboElemPar.insertBefore !== 'undefined' && typeof weboElemPar.childNodes !== 'undefined' && typeof weboElemPar.appendChild !== 'undefined'){
if(weboElemPar.childNodes.length > 0 && weboElemIndex < weboElemPar.childNodes.length) weboElemPar.insertBefore(weboElem, weboElemPar.childNodes[weboElemIndex]);
else weboElemPar.appendChild(weboElem);
return true;
}
return false;
}
function resolveXpath(path)
{
//XPathJS.bindDomLevel3XPath(); //solo per xpathJs
var result = document.evaluate(path,document,null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE);
if(result.snapshotLength > 0){
var child, node = result.snapshotItem(0);
if(node.nodeName.toLowerCase() == 'object'){
ieObject = true;
child = node;
while( (child = child.previousSibling) != null ) weboElemIndex++;
var div = document.createElement('div');
div.id = 'my_usage';
if(typeof node.parentNode.insertBefore !== 'undefined' && typeof node.parentNode.childNodes !== 'undefined' && typeof node.parentNode.appendChild !== 'undefined'){
if(node.parentNode.childNodes.length > 0 && weboElemIndex < node.parentNode.childNodes.length) node.parentNode.insertBefore(div,node.parentNode.childNodes[weboElemIndex]);
else node.parentNode.appendChild(div);
div.appendChild(node);
} else return false;
} else node.id = 'my_usage';
return true;
} else return false;
}
resolveXpath('//*/param[contains(#src, "autoplay=1")]/..');

What is expected from a SlickGrid editor factory?

Should the return value of SomeEditorFactory.getEditor(column) be a function or an object?
From the code
function getEditor(row, cell) {
var column = columns[cell];
var rowMetadata = data.getItemMetadata && data.getItemMetadata(row);
var columnMetadata = rowMetadata && rowMetadata.columns;
if (columnMetadata && columnMetadata[column.id] && columnMetadata[column.id].editor !== undefined) {
return columnMetadata[column.id].editor;
}
if (columnMetadata && columnMetadata[cell] && columnMetadata[cell].editor !== undefined) {
return columnMetadata[cell].editor;
}
return column.editor || (options.editorFactory && options.editorFactory.getEditor(column));
}
Not immediately obvious.
It should be an object that implements getEditor(columnDefinition) and returns the editor for a given column.
See https://github.com/mleibman/SlickGrid/wiki/Writing-custom-cell-editors and https://github.com/mleibman/SlickGrid/blob/master/slick.editors.js.
When SlickGrid calls YourEditorFactory.getEditor(column), it expects a function.

Categories