Way to many quotation marks in javascript - javascript

I have a TableA containing brands with names, names are for example: brand1, 123, brand2, 999.
I want to select names, create button with id=name and pass the name to function brandOnOff(name), then alert the name I passed.
When I press button "123" or "999" it works correctly. But buttons "brand1" and "brand2" don't work - they alert: [object HTMLButtonElement]. I think I have I problem with "" and '' and I don't know how to fix it...
When I alert(document.getElementById("demo").innerHTML) I get:
<button id="brand1" onclick="brandOnOff(brand1)">brand1</button><button id="123" onclick="brandOnOff(123)">123</button><button id="brand2" onclick="brandOnOff(brand2)">brand2</button><button id="999" onclick="brandOnOff(999)">999</button>
and I think it should be like: ... onclick="brandOnOff("brand1")"... etc --- Quotation-mark then name then Quotation-mark
but when I try to add Quotation-marks there's an error "Unexpected end of input" and I keep messing it up.
Can somebody help me please? I'm stuck :(
Here is the code:
DB.transaction(function (tx) {
tx.executeSql('SELECT * FROM TableA', [], function (tx, rs) {
var brand;
for (i = 0; i < brands; i++)
{
brand = rs.rows.item(i).name;
document.getElementById("demo").innerHTML = document.getElementById("demo").innerHTML + '<button id="' + brand + '" onclick="brandOnOff(' + brand + ')">' + brand + '</button>';
}
}, function (tx, error) {
console.log('SELECT error: ' + error.message);
});
});
function brandOnOff(brandName) {
alert(brandName);
}

Your main issue is caused by trying to use inline event handlers, when these are generally considered obsolete and addEventHandler is universally supported.
You should also split out your logic somewhat into smaller testable units, that separate HTML page generation from database code:
// event handler - passed the clicked element in ev.target
function brandOnOff(ev) {
alert(ev.target.id);
}
// takes an array of brand names and generates a button for each
function buildBrandButtons(brands) {
let demo = document.getElementById('demo');
brands.forEach(brand => {
let button = document.createElement('button');
button.id = brand;
button.textContent = brand;
button.addEventListener('click', brandOnOff);
demo.addChild(button);
});
}
// converts a result set into an array of the specified field's values
function getResultSetField(rs, field) {
let values = [];
for (let i = 0; i < rs.rows.length; ++i) {
values.push(rs.rows.item(i)[field]);
}
return values;
}
// the meat - gets the brand names, builds the buttons
function processBrands(tx, rs) {
let brands = getResultSetField(rs, 'name');
buildBrandButtons(brands);
}
// generic error handler
function selectError(tx, error) {
console.log('SELECT error: ' + error.message);
}
// the actual database work
DB.transaction(tx => {
tx.executeSql('SELECT * FROM TableA', [], processBrands, selectError);
});
This may look like a lot more code, but each part has a specific responsibility, and some of these functions may be re-used later (e.g. selectError, getResultSetField).
NB: no nested quote marks, or indeed any that aren't around a string constant.

Related

Javascript returning multiple checkbox values

I'm having some trouble trying to get multiple checkbox values. It currently is working, just not in the way I wanted/was hoping it would. Right now anything checked is appended to the bottom of the body and not inline with the function it was aiming to be inserted into.
I'm trying to avoid using JQuery or anything except JavaScript as it's all we've currently covered in our class.
function favMedia(media){
var media = document.forms['mediapref']['media'].value;
return media;
}
function pets(pet){
var pet = document.getElementsByName('pets')
for (var checkbox of pet){
if (checkbox.checked)
document.body.append(checkbox.value + ' ');
}
}
function about(text){
var info = document.forms['personal']['about'].value;
return info;
}
function infoForm(media, pet, text){
document.getElementById('infoset').innerHTML = favMedia(media) + "<br>" + pets(pet) + "<br>" + about(text);
}
Is there some way I can assign it just to a single variable to return and then throw into the last function?
Also please give me any tips or improvements on any aspect of the functions if you have any.
Put it in a string that you return from the function.
function pets(pet) {
var pet = document.querySelector('[name="pets":checked');
let selected = [...pet].map(p => p.value);
return selected.join(', ');
}

Issues with protractor test when finding element array using repeatable

I've created a protractor test for the following html:
<div class="well well-sm" data-ng-repeat="feedback in f.feedbackList">
Rating: {{feedback.rating}}
<blockquote class="small">{{feedback.comment}}</blockquote>
</div>
In the page.js file I have:
"use strict";
module.exports = (function () {
function AdminFeedbackPage() {
this.comments = element.all(by.repeater('feedback in f.feedbackList').column('feedback.comment')).map(function (comments) {
return comments.getText();
});
this.ratings = element.all(by.repeater('feedback in f.feedbackList').column('feedback.rating')).map(function (ratings) {
return ratings.getText();
});
}
return AdminFeedbackPage; })();
and then in the test in my step.js file:
var feedbackFound = false;
var feedbackIndex;
adminFeedbackPage.comments.then(function (commments) {
for (var i = 0; i < commments.length; i++) {
console.log("Comments " + i + ": " + commments[i]);
if (commments[i] == "TestApplicationFeedback") {
feedbackIndex = i;
console.log("FEEDBACK INDEX - " + feedbackIndex)
feedbackFound = true;
break;
}
}
}).then(function () {
expect(feedbackFound).to.be.true;
}).then(function() {
adminFeedbackPage.ratings.then(function (ratings) {
console.log(ratings);
console.log("RATINGS length " + ratings.length + " and rating is " + ratings[feedbackIndex]);
expect(ratings[feedbackIndex]).to.equal(3);
})
});
And I get the following logs:
Comments 0: Decent App
Comments 1: Really like it
Comments 2: TestApplicationFeedback
FEEDBACK INDEX - 2
[]
RATINGS length 0 and rating is undefined
AssertionError: expected undefined to equal 3
This is really confusing my since the comments are being found without any issue, but the ratings are just an empty array and as far as I can tell I have done the same thing for both.
Does anybody have any suggestions/reasons why the ratings aren't being found? I suspect it's something to do with what is in the page.js file, but I have no idea what could be wrong?
Thanks!
Solved this in the comments above, posting as an answer:
It was just a guess/suggestion based on the HTML, one was a child element and the other was directly inside the repeater (this one was failing to be captured). So my suggestion was to try using .evaluate() source, which acts as if on scope of the given element. So replacing .column() seems to work:
element.all(by.repeater('feedback in f.feedbackList')).evaluate('feedback.rating').then(function(val) {
console.log(val) // should return an array of values (feedback.rating)
})

Protractor - Error: Index out of bound exception while using the same function for the second time

I have the following function which selects a category from a list of available categories. This function works fine in my first test. But the same function with a different valid category name in my second test fails with the following error.
Error: Index out of bound. Trying to access element at index: 0, but there are only 0 elements that match locator By.cssSelector(".grid-view-builder__category")
this.categoryElements = element.all(by.css('.grid-view-builder__category'));
this.selectCategory = function (categoryName) {
var filteredCategories = this.categoryElements.filter(function (category) {
return category.getText().then(function (text) {
log.info(text);
return text === categoryName;
})
})
filteredCategories.first().click().then(function () {
log.info("Select Category: " + categoryName);
}).then(null, function (err) {
log.error("Category: " + categoryName + " Not Found !!" + err);
});
}
Spec File
var columnSelect = require('pages/grid/columns/columnselector-page')()
it('Add Publisher ID Column to the Grid & Verify', function () {
var columnCountBefore = columnSelect.getColumnCount();
columnSelect.openColumnSelector();
columnSelect.selectCategory('Advanced');
columnSelect.selectColumn('Publisher ID');
columnSelect.apply();
var columnCountAfter = columnSelect.getColumnCount();
expect(columnCountAfter).toBeGreaterThan(columnCountBefore);
});
The problem might be in the way you are defining and using Page Objects. Here is a quick solution to try - if this would help, we'll discuss on why that is happening.
Make the categoryElements a function instead of being a property:
this.getCategoryElements = function () {
return element.all(by.css('.grid-view-builder__category'));
};
this.selectCategory = function (categoryName) {
var filteredCategories = this.getCategoryElements().filter(function (category) {
return category.getText().then(function (text) {
log.info(text);
return text === categoryName;
})
})
filteredCategories.first().click().then(function () {
log.info("Select Category: " + categoryName);
}).then(null, function (err) {
log.error("Category: " + categoryName + " Not Found !!" + err);
});
}
Or, this could be a "timing issue" - let's add an Explicit Wait via browser.wait() to wait for at least a single category to be present:
var EC = protractor.ExpectedConditions;
var category = element(by.css('.grid-view-builder__category'));
browser.wait(EC.presenceOf(category), 5000);
It looks like this has nothing to do with the code posted here, only that the css selector you're using is not finding any elements

SQL Insert Statement not Working in Javascript

I'm trying to get my WebSQL database to popluate using a JSON array (Object is called myJSONObject, array is called costcodes).
The function runs on click, the database successfully creates, but the data is not inserted into the database. It doesn't even throw and error, it just doesn't do anything.
My initial thought was that the data isn't escaped properly, but I don't know exactly where/how to escape it. So I'm stumped.
localDB = null;
function initDB()
{
if (localDB==null)
{
var shortName = 'Costcode';
var version = '1.0';
var displayName = 'Costcode';
var maxSize = 217802; // in bytes
localDB = window.openDatabase(shortName, version, displayName, maxSize);
}
}
function buildTable()
{
var sQuery = 'CREATE TABLE IF NOT EXISTS Costcode ('+
'id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,' +
'cost_code_no VARCHAR NULL,' +
'row_unique_no VARCHAR NULL,' +
'cost_class_no VARCHAR NULL,' +
'Table_Version VARCHAR DEFAULT "1.0");';
try
{
initDB();
localDB.transaction(function(transaction)
{
transaction.executeSql(sQuery, []);
console.log('sucess');
});
}
catch (e)
{
alert("Error: Unable to create table 'x" + "' " + e + ".");
return;
}
}
function exeSQLFast()
{
initDB();
localDB.transaction(function(transaction)
{
for (var x = 0; x <myJSONObject.costcodes.length; x++)
{
var costcodeno = myJSONObject.costcodes[x].cost_code_no;
var rowuniqueid = myJSONObject.costcodes[x].row_unique_id;
var costclassno = myJSONObject.costcodes[x].cost_class_no;
console.log(costcodeno);
console.log(rowuniqueid);
console.log(costclassno);
transaction.executeSql('INSERT INTO Costcode (cost_code_no, row_unique_id, cost_class_no) VALUES (? , ? , ?)',
[costcodeno,
rowuniqueid,
costclassno]
, function(transaction, results)
{
console.log(costcodeno);
console.log('hooray');
}
)};
}
)}
</script>
</head>
<body onLoad="buildTable();">
<input type="button" onClick="exeSQLFast();" value='button'>
</body>
</html>
The console log shows that the variables are all being properly defined, but it's not running the insert statement. Any ideas?
Here's an example of myJSONObject.costcodes[2]
cost_class_no: " 3"
cost_code_no: " 1000"
row_unique_id: 335
That looks like a problem doesn't it...
The problem was that I called the row_unique_no column row_unique_id in the insert statement. Now I feel stupid.
But if anyone is curious how to populate a WebSQL database properly, this is how you do it. Just don't mistype the column names.

Nested HTML5 Web SQL Query Issued after Entire For Loop Processed

In this query listed below, my for loop is executing 4 values. In the first alert(id), it is alerting those 4 distinct values. However, in the nested query, the alert statement is printing out the last id value only, 4x with different max(b.id) values. I'm confused. Does anyone know what may be happening? Could a race condition be occurring?
My goal is to place an Ajax call in the nested query, which has input values based on both id and b.id. I am currently doing this, but the value in the ajax call for the "id" is the same for all 4 different calls, which messes up the return data. Thanks.
database.db.transaction(function (tx) {
tx.executeSql('SELECT id, name from programs d', [], function (tx, results) {
for (var i = 0; i < results.rows.length; i++) {
var id = results.rows.item(i)['id'];
var name = results.rows.item(i)['name'];
alert(id);
tx.executeSql('SELECT max(b.id) + 1 max from people b where b.sid = ?',
[id],
function (tx, results) {
lastRecord = results.rows.item(0)['max'];
alert(id + "last rec: " + name);
}
);
}
},
function (event) { alert(event.message); });
As per my comments, you to return a closed function to bind the parameter correctly.
A much simpler example is the following:
Running this produces 4 alerts, all showing 4:
for (i=0;i<4;i++) {
setTimeout( function() { alert(i)}, 1000);
}
Running this produces 4 alerts, showing 0/4, 1/4, 2/4, 3/4.
for (i=0;i<4;i++) {
setTimeout(function(inneri) {
return(
function() {
alert(inneri + "/" + i);
}
);
}(i), 1000);
}
where I've named inneri the value that was preserved upon closure. Note that i, itself is still referring to the outer scope, and thus is 4 (which is what is true at time of execution, since that is the value of i when it dumps out of the for loop, as we're delaying the execution using setTimeout().
The first case is a simpler version of what you're doing, whereas you want the second case.
Rewriting your js (and hoping I get all these ( and {'s in the right place :) ) gives:
database.db.transaction(function (tx) {
tx.executeSql('SELECT id, name from programs d', [], function (tx, results) {
for (var i = 0; i < results.rows.length; i++) {
var id = results.rows.item(i)['id'];
var name = results.rows.item(i)['name'];
alert(id);
tx.executeSql('SELECT max(b.id) + 1 max from people b where b.sid = ?',
[id],
function(innerId) {
return (
function (tx, results) {
lastRecord = results.rows.item(0)['max'];
alert(innerId + "last rec: " + name);
}
);
}(id) //be careful to avoid the ";" here!
);
}
},
function (event) { alert(event.message);
});
Where I have inserted:
function(innerId) {
return (
function (tx, results) {
lastRecord = results.rows.item(0)['max'];
alert(innerId + "last rec: " + name);
}
);
}(id)
in. This function is called immediately via the (id) and returns a function that takes tx and results as arguments and does the appropriate action.
I have checked braces/parenthesis, but don't have a direct way to verify that I didn't make any typos.

Categories

Resources