fabric js Cannot read property 'src' of undefined - javascript

I have a code that the src property is undefined when I want to change the source image with for loop and switch case to detect the id of image object. this my code.
function buildTable(results) {
var data = results.data;
let gbr;
for (i = 0; i < data.length; i++) {
var c = "<canvas id='can" + i + "' class='printCanvas' ></canvas><br>";
$("body").append(c);
canvas2[i] = new fabric.Canvas('can' + i + '');
canvas2[i].setWidth(298);
canvas2[i].setHeight(420);
if (data[i] != "") {
var row = data[i];
var cells = row.join(",").split(",");
// console.log(cells);
}
canvas2[i].loadFromJSON(canvas.toJSON(['id', 'qrcode']), function() {}, function(o, object) {
switch (object.id) {
case 'id':
object.text = cells[1];
break;
case 'daerah':
object.text = cells[3];
break;
case 'tgl':
object.text = cells[2];
break;
case 'qrcode':
gbr = object;
object.setSrc(makeQR(cells[1]), canvas.renderAll());
break;
default:
break;
}
console.log(gbr.src);
});
canvas2[i].renderAll();
}
}
the cause of error is happen with the following code
console.log(gbr.src);

Related

How to get both mobile and desktop score with PageSpeed

I'm trying to get page speed score for both: desktop and mobile and then pass them to #pgscore && #pgscorem inputs.
Problem is that at the end of script I get always var device == 'mobile'. It looks like it skips for loop. Any idea how could I fix it?
for (var r = 0; r < 2; r++) {
var API_KEY = 'mykey';
var device = '';
switch (r) {
case 0: device='desktop'; break;
case 1: device='mobile'; break;
};
alert(device);
var URL_TO_GET_RESULTS_FOR = 'http://www.stackoverflow.com' + '&strategy=' + device;
var API_URL = 'https://www.googleapis.com/pagespeedonline/v1/runPagespeed?';
var CHART_API_URL = 'http://chart.apis.google.com/chart?';
var callbacks = {}
function runPagespeed() {
var s = document.createElement('script');
s.type = 'text/javascript';
s.async = true;
var query = [
'url=' + URL_TO_GET_RESULTS_FOR,
'callback=runPagespeedCallbacks',
'key=' + API_KEY,
].join('&');
s.src = API_URL + query;
document.head.insertBefore(s, null);
}
function runPagespeedCallbacks(result) {
if (result.error) {
var errors = result.error.errors;
for (var i = 0, len = errors.length; i < len; ++i) {
if (errors[i].reason == 'badRequest' && API_KEY == 'yourAPIKey') {
alert('Please specify your Google API key in the API_KEY variable.');
} else {
alert(errors[i].message);
}
}
return;
}
for (var fn in callbacks) {
var f = callbacks[fn];
if (typeof f == 'function') {
callbacks[fn](result);
}
}
}
setTimeout(runPagespeed, 0);
callbacks.displayPageSpeedScore = function(result) {
var score = result.score;
Function countinues down there. Problem is here... Why I can't get variable device == 'desktop' first and then in second for loop 'mobile'? I get always 'mobile'.
switch (device) {
case 'desktop': $('#pgscore').val(score); break;
case 'mobile': $('#pgscorem').val(score); break;
};
};
};
Since I need only score, I'm using php
$jsonurl="https://www.googleapis.com/pagespeedonline/v1/runPagespeed?url=$url&locale=pl_pl&$key";
$json = file_get_contents($jsonurl);
$json_output = json_decode($json, true);
/* print_r(array_values($json_output));*/
echo $json_output['score'];

How to get rid of double for loop in autocomplete

I am currently making an autocomplete function that retrieves a bunch of information encoded by JSON and allows the user to search through it. There is a slight delay in the search results, and I think that a for loop inside of another for loop is the cause of this issue. Below is the Javascript file:
var username = [];
var businessname = [];
var fname = [];
var lname = [];
var fullname = [];
var clientid = [];
var bankArray = [];
var data_for_post = [];
var focusedArrayElement = "";
var started = false;
var currentSelectedList = 0;
var searchString = "";
$(document).keydown(function(event) {
switch(event.keyCode) {
case 40:
if (!$("#results li:first").hasClass("selected") && !started) {
$("#results li:first").addClass("selected");
started = true;
} else {
if($("#results li.selected").next().length > 0) {
$("#results li.selected").next().addClass("selected");
$("#results li.selected:first").removeClass("selected");
}
}
assign = $(".selected").text();
$(".autocomplete").val(assign);
break;
case 38:
$("#results li.selected").prev().addClass("selected");
$("#results li.selected:last").removeClass("selected");
if(!$("#results").siblings('.selected').length > 0) {
started = false;
}
assign = $(".selected").text();
$(".autocomplete").val(assign);
break;
case 13:
assign = $(".selected").text();
console.log(assign);
$("#results").empty();
$("#inner").text(assign);
break;
}
});
$(document).ready(function() {
$.ajax({
type: "GET",
dataType: "json",
url: "autocomplete.php?search=1",
success: function(data) {
$.each(data.client, function(key, value) {
username.push(value.username);
businessname.push(value.businessname);
fname.push(value.fname);
lname.push(value.lname);
clientid.push(value.clientid);
for(var i = 0; i < fname.length; i++) {
fullname[i] = fname[i] + " " + lname[i];
}
});
bankArray = [username, businessname, fullname, clientid];
console.log(bankArray);
}
});
$(".autocomplete").on("keyup change", function(e) {
console.log(e.keyCode);
if(e.keyCode != 38 && e.keyCode != 40) {
$("#results").empty();
}
currentSearchString = $(".autocomplete").val();
if(currentSearchString) {
//$("#results").css('border-top', '1px solid black');
for(var i = 0; i < bankArray.length; i++) {
for(var j = 0; j < bankArray[i].length; j++) {
focusedArrayElement = bankArray[i][j].toLowerCase();
usernames = bankArray[0];
businessnames = bankArray[2];
fullnames = bankArray[3];
if(focusedArrayElement.indexOf(currentSearchString.toLowerCase()) > -1) {
focused_businessname = bankArray[1][j];
focused_fullname = bankArray[2][j];
focused_clientid = bankArray[3][j];
postedData = focused_fullname + " -- " + focused_businessname;
if (!$(".clientid." + focused_clientid).length) {
$("#results").append("<li id='" + (j + 1) + "' class='clientid " + focused_clientid + "'>" + postedData + "</li>");
}
}
}
}
}
else {
$("#results").empty();
started = false;
}
});
});
The basic principle is that when the document readies, an ajax call pushes all of the JSON data into a multidimensional array with different categories of information. From here, a first for loop searches through each array in the bankArray, and the second searches through each element of the current array. If the current search string in the input field matches the focused element from the array, it appends that information to a div below.
I feel as if the code is inefficient in how it deals with the JSON data and checks through it. If anyone has any suggestions on how to optimize the code, that would be great.

javascript: clean way of converting currencies from an array

Folks!
Currently i have written this below code, which converts one currencies into another , but the problem is i am defining each & every currencies one by one in switch block,
If i have 100 currencies to convert then i have to write 100 switch cases
Is there any i can make this below code dynamic and short?
var currencies = {};
$(document).ready(function(){
yahoo_getdata();
});
function yahoo_getdata() {
var a = new Date();
var b = "http://someAPIurl.com/webservice/v1/symbols/allcurrencies/quote?format=json&random=" + a.getTime() + "&callback=?";
$.getJSON(b, function (e) {
if (e) {
var i, l, r, c;
r = e.list.resources;
for (i = 0, l = r.length; i < l; i += 1) {
c = r[i].resource.fields;
//console.log(c.name, c.price);
switch (c.name) {
case "USD/EUR":
currencies.EUR = c.price;
console.log('USD/EUR = ' + c.price);
break;
case "USD/USD":
currencies.USD = c.price;
console.log('USD/USD = ' + c.price);
break;
case "USD/JPY":
currencies.JPY = c.price;
console.log('USD/JPY = ' + c.price);
break;
case "USD/INR":
currencies.INR = c.price;
console.log('USD/INR = ' + c.price);
break;
}
}
console.log(currencies);
//console.log(e);
//var d = {};
}
});
}
$("#amount1").keyup(function() {
var
usd,
amount1 = $('#amount1').val(),
currency1 = $("#currency1").val(),
currency2 = $("#currency2").val();
// normalize to USD
usd = amount1 / currencies[currency1];
// convert to target currency
$('#amount2').val(usd * currencies[currency2]);
});
Use an object that maps the currency name to the object property name:
var currency_map = {
'USD/EUR': 'EUR',
'USD/USD': 'USD',
'USD/JPY': 'JPY',
...
};
Then:
for (var i = 0, l = r.length; i < l; i++) {
c = r[i].resource.fields;
currencies[currency_map[c.name] || c.name] = c.price;
console.log(c.name + ' = ' + c.price);
}
FIDDLE

each method being skipped in debug mode

here is some JavaScript that I am testing:
var filters;
$(".arrow-up").unbind("click").click(function (event) {
var clickedArrow = $(this);
var id = clickedArrow.attr('data-id');
var select = document.getElementById(id);
var option = select.options[select.selectedIndex];
var filters;
$(".search").each(function () {
var SearchText = this.value;
var id;
if (!checkEmpty(SearchText)) {
switch (this.id) {
case "one":
id = 1;
break;
case "two":
id = 2;
break;
case "three":
id = 3;
break;
case "four":
id = 4;
break;
case "five":
id = 5;
break;
case "six":
id = 6;
break;
case "seven":
id = 7;
break;
case "eight":
id = 8;
break;
}
var filter = document.getElementById(id);
var filterOption = filter.options[filter.selectedIndex].text;
filters += '&col=' + filterOption;
filters += '&col=' + SearchText;
}
});
var cols;
/* Get all of the drop downs for the columns */
for (var i = 1; i <= 8; i++) {
var txt;
var colVal = document.getElementById(i);
txt = colVal.options[colVal.selectedIndex].text;
cols += '&col=' + txt;
}
var url = '/AccountManagement/SortAscend';
var formData = {
option: option,
filters: filters,
cols: cols
}
var posting = $.post(url, formData, function (data, textstatus) {
//spinner = new Spinner(opts).spin(target);
StartSpinner();
}, "json");
posting.done(function (data) {
ReloadTable(data);
StopSpinner();
});
});
When I debug this in chrome, it skips the $(".search").each(function() { part - it just skips to the end of the method, therefore it never goes over any of the eight items and the filters variable remains "undefined" I am not sure why.
Please try these changes and tell me if that still just goes by the each. Because I am using each just as you do and it works perfectly. Maybe I would also change the switch to an "associative array"
var numbers = {"one":1,"two":2...};
And then
id = numbers[$(this).attr("id")]
But first try the code below.
var filters;
$(".arrow-up").unbind("click").click(function (event) {
var clickedArrow = $(this);
var id = clickedArrow.data('id');
var select = $('#'+id);
var option = $(select + '> option:selected');
var filters;
$(".search").each(function () {
var SearchText = $(this).val();
var id;
if (!checkEmpty(SearchText)) {
switch ($(this)attr("id")) {
case "one":
id = 1;
break;
case "two":
id = 2;
break;
case "three":
id = 3;
break;
case "four":
id = 4;
break;
case "five":
id = 5;
break;
case "six":
id = 6;
break;
case "seven":
id = 7;
break;
case "eight":
id = 8;
break;
}
var filter = document.getElementById(id);
var filterOption = filter.options[filter.selectedIndex].text;
filters += '&col=' + filterOption;
filters += '&col=' + SearchText;
}
});
var cols;
/* Get all of the drop downs for the columns */
for (var i = 1; i <= 8; i++) {
var txt;
var colVal = document.getElementById(i);
txt = colVal.options[colVal.selectedIndex].text;
cols += '&col=' + txt;
}
var url = '/AccountManagement/SortAscend';
var formData = {
option: option,
filters: filters,
cols: cols
}
var posting = $.post(url, formData, function (data, textstatus) {
//spinner = new Spinner(opts).spin(target);
StartSpinner();
}, "json");
posting.done(function (data) {
ReloadTable(data);
StopSpinner();
});
});

Suppress JavaScript undefined errors?

I have written a script that checks a set of radiobuttons to be checked. But due to different possibilities different radiobuttons will show. Is there a way to suppress JavaScript errors when it pops undefined/getElementById is null? Something like the #-char does in PHP?
Update:
A bit more background info. I've made a website where users can submit images and another party for whom the images are can select their top 3 of the images. So each image has three radiobuttons. The difficulty here lies in the fact that the radiobuttons must be controlled dimensional (horizontal and vertical), because a submitted image may only be at place 1, 2 or 3. This is my working code. But adding many if(!var == undefined) doesn't make the code prettier. Therefor I'm wondering if there is something like #suppressMe is possible?
function HandleRadioButtons(id, type, idString, img)
{
var idArray = idString.split("|");
var place1 = document.getElementById("G_" + id);
var place2 = document.getElementById("S_" + id);
var place3 = document.getElementById("B_" + id);
var img1 = document.getElementById("Winner1");
var img2 = document.getElementById("Winner2");
var img3 = document.getElementById("Winner3");
switch(type)
{
case "G" :
place2.checked = false;
place2.disabled = true;
place3.checked = false;
place3.disabled = true;
img1.style.background = 'url(' + img + ') no-repeat center center #FFF';
break;
case "S" :
place1.checked = false;
place1.disabled = true;
place3.checked = false;
place3.disabled = true;
img2.style.background = 'url(' + img + ') no-repeat center center #FFF';
break;
case "B" :
place1.checked = false;
place1.disabled = true;
place2.checked = false;
place2.disabled = true;
img3.style.background = 'url(' + img + ') no-repeat center center #FFF';
break;
}
var current1, current2, current3 = "";
for(i = 0; i < idArray.length - 1; i++)
{
var place1 = document.getElementById("G_" + idArray[i]);
var place2 = document.getElementById("S_" + idArray[i]);
var place3 = document.getElementById("B_" + idArray[i]);
if(place1.checked == true)
{
var current1 = idArray[i];
}
if(place2.checked == true)
{
var current2 = idArray[i];
}
if(place3.checked == true)
{
var current3 = idArray[i];
}
}
for(i = 0; i < idArray.length - 1; i++)
{
var place1 = document.getElementById("G_" + idArray[i]);
var place2 = document.getElementById("S_" + idArray[i]);
var place3 = document.getElementById("B_" + idArray[i]);
if(idArray[i] != id && idArray[i] != current1 && idArray[i] != current2 && idArray[i] != current3)
{
switch(type)
{
case "G" :
place1.disabled = false;
place2.disabled = false;
place3.disabled = false;
break;
case "S" :
place1.disabled = false;
place2.disabled = false;
place3.disabled = false;
break;
case "B" :
place1.disabled = false;
place2.disabled = false;
place3.disabled = false;
break;
}
}
}
}
You can easily test for a null or undefined value in JavaScript, as both these values are falsy:
var element = document.getElementById('some-id');
if (element) {
element.value = 'Hello';
}
You could also consider using a try/catch block:
try {
var element = document.getElementById('some-id');
element.value = 'Hello';
// ... the rest of your code here.
}
catch (e) {
if (!(e instanceof TypeError)) {
// The exception is not a TypeError, so throw it again.
throw e;
}
}
However be careful that the above will suppress all the TypeError exceptions and that might make your code more difficult to debug.
you can check if buttons are existing by getElementById and then check its length. Are you using any framework?
Try this
var element = document.getElementById('some-id');
element?.value = 'Hello';

Categories