IE bug with global variables. How to bypass this bug? - javascript

As title says i have some problems with IE8 and Javascript. It's known about its bug in interpretation of global variables: simply it does not get them if you don't declare as:
var variable1 = something;
The problem it's i'm trying to make a script that change the body background clicking on a button and i need a global variable wrapping the actual status (what bg-x.png i'm loading). This script work on FF, Safari and Chrome but not, obviously, on IE. Help? (the problem is on the variable "status")
$('#change').click(function() {
var numStates = 2;
var name = $(this).text();
if(!(status)) {
status = parseInt(1,10);
}
if(status<numStates) {
status = parseInt(status,10) + 1;
}
else {
status = parseInt(1,10);
}
alert(status);
var bgvar = null;
switch(parseInt(status,10)) {
case 1: var bgvar = ' #7097ab url(./img/bg-' + status + '.png) top center repeat';
var name = 'Pattern';
break;
case 2: var bgvar = ' #7097ab url(./img/bg-' + status + '.png) top center repeat-x';
var name = 'Sfumato';
break;
default: alert('Default');
}
$('body').css({
background:bgvar,
});
$(this).text(name);
}
);
Working code even with IE (Thanks to Zeta):
$('#change').click(function() {
var numStates = 2;
var name = $(this).text();
// If data-status isn't defined set it to the initial value
if($('body').data('status') === undefined)
$('body').data('status',1);
// Extract the status
var status = parseInt($('body').data('status'),10);
// Handle the status
if(status < numStates)
status++;
else
status = 1;
// Save the status
$('body').data('status',status);
switch(status) {
case 1: bgvar = ' #7097ab url(./img/bg-' + status + '.png) top center repeat';
name = 'Pattern';
break;
case 2: bgvar = ' #7097ab url(./img/bg-' + status + '.png) top center repeat-x';
name = 'Sfumato';
break;
default: alert('Default');
}
$('body').css({
background:bgvar,
});
$(this).text(name);
}
);

status is a predefined member of the window-object and points to the content of the statusbar. Use another variable-name

Since you're already using jQuery you could use .data() instead of global variables:
$('#change').click(function() {
var numStates = 2;
var name = $(this).text();
// If data-status isn't defined set it to the initial value
if($('body').data('status') === undefined)
$('body').data('status',1);
// Extract the status
var status = parseInt($('body').data('status'),10);
// Handle the status
if(status < numStates)
status++;
else
status = 1;
// Save the status
$('body').data('status',status);
/* ... Rest of your code ... */
Note that this won't work in XML documents in IE (according to the jQuery doc).

Do you know when to use »var«?
I just cleaned your code in the follwing ways:
Add "var status;" to make it a local variable
Delete "var" for already defined variables in your switch statement
Delete the unnecessary comma behind "background: bgvar" which will cause errors in IE
$('#change').click(function () {
var numStates = 2;
var name = $(this).text();
var status;
if (!(status)) {
status = parseInt(1, 10);
}
if (status < numStates) {
status = parseInt(status, 10) + 1;
} else {
status = parseInt(1, 10);
}
alert(status);
var bgvar = null;
switch (parseInt(status, 10)) {
case 1:
bgvar = ' #7097ab url(./img/bg-' + status + '.png) top center repeat';
name = 'Pattern';
break;
case 2:
bgvar = ' #7097ab url(./img/bg-' + status + '.png) top center repeat-x';
name = 'Sfumato';
break;
default:
alert('Default');
}
$('body').css({
background: bgvar
});
$(this).text(name);
});
Does it work now?
P.S. Use http://www.jshint.com/ to prevent those kind of errors.

Related

Script runs extremely slow, needs to be more efficient

Goal:
My script takes every folder and layer in photoshop, gets the center point coordinates, and saves them to a txt file.
Issue:
The script works very well and gives the exact data I need. However, the script runs extremely slow when I have lots of photoshop layers. For example I ran the script on a PSD that has lets say 200 small layers. This took about 20 minutes to get the output text file that I need. MY question, and bare in mind I am not a programmer, is how to increase the efficiency of this code, and have this run faster.
Here is a Sample of the Output Data:
1 -MUD ROOM/GARAGE: 483.5x,559y
130A: 307.5x,681y
Lighting_icon_square_4x copy 19: 382x,749y
Lighting_icon_square_4x copy 19: 382x,681y
Lighting_icon_square_4x copy 19: 382x,613y
Lighting_icon_square_4x copy 18: 233x,749y
Lighting_icon_square_4x copy 17: 233x,681y
Lighting_icon_square_4x copy 13: 233x,613y
The Code:
// Bring application forward
app.bringToFront();
// Set active Document variable and decode name for output
var docRef = app.activeDocument;
var docName = decodeURI(activeDocument.name).slice(0, -4);
// Define pixels as unit of measurement
var defaultRulerUnits = preferences.rulerUnits;
preferences.rulerUnits = Units.PIXELS;
// Define variable for the number of layers in the active document
var layerNum = app.activeDocument.artLayers.length;
// Define variable for the active layer in the active document
var layerRef = app.activeDocument.activeLayer;
// Define varibles for x and y of layers
var x = (layerRef.bounds[2].value) - (layerRef.bounds[0].value);
var y = (layerRef.bounds[3].value) - (layerRef.bounds[1].value);
var coords = "";
// Loop to iterate through all layers
function recurseLayers(currLayers) {
for ( var i = 0; i < currLayers.layers.length; i++ ) {
layerRef = currLayers.layers[i];
x = (layerRef.bounds[2].value) - (layerRef.bounds[0].value);
y = (layerRef.bounds[3].value) - (layerRef.bounds[1].value);
coords += layerRef.name + ": " + (layerRef.bounds[0].value + x/2) + "x" + "," + (layerRef.bounds[1].value + y/2) + "y" + "\n";
//test if it's a layer set
if ( isLayerSet(currLayers.layers[i]) ) {
recurseLayers(currLayers.layers[i]);
}
}
}
//a test for a layer set
function isLayerSet(layer) {
try {
if ( layer.layers.length > 0 ) {
return true;
}
}
catch(err) {
return false;
}
}
// Ask the user for the folder to export to
var FPath = Folder.selectDialog("Save exported coordinates to");
// Detect line feed type
if ( $.os.search(/windows/i) !== -1 ) {
fileLineFeed = "Windows";
}
else {
fileLineFeed = "Macintosh";
}
// Export to txt file
function writeFile(info) {
try {
var f = new File(FPath + "/" + docName + ".txt");
f.remove();
f.open('a');
f.lineFeed = fileLineFeed;
f.write(info);
f.close();
}
catch(e){}
}
// Run the functions
recurseLayers(docRef);
preferences.rulerUnits = defaultRulerUnits; // Set preferences back to user 's defaults
writeFile(coords);
// Show results
if ( FPath == null ) {
alert("Export aborted", "Canceled");
}
else {
alert("Exported " + docName + " x/y coordinates to " + FPath + "/" + docName + ".txt ");
}
For the sake of other readers facing performance bugs, I've shortened your code up a bit. This runs fast on my machine.
function main() {
var file = File.saveDialog("Save exported coordinates");
if (file == null) return;
if (!file.open('w')) {
alert("Aborted", "Could not write file.");
return;
}
write(activeDocument.layers, file);
alert("Exported x/y coordinates to " + file.path);
}
function write(layers, file) {
for (var i = 0; i < layers.length; i++) {
var layer = layers[i];
var width = layer.bounds[2] - layer.bounds[0];
var height = layer.bounds[3] - layer.bounds[1];
file.write(layer.name + ": " + (layer.bounds[0] + width / 2).value +
"x, " + (layer.bounds[1] + height / 2).value + "y\n");
if (layer instanceof LayerSet) {
write(layer.layers, file);
}
}
}
main();

Cannot open file "/dev/ttyO2" when trying to use the serial port on the Beaglebone Black

I am trying to open the serial port 2 on my beagle bone, using the following code:
var b = require('bonescript');
var x = '/dev/ttyO2';
var SerialPort = require("serialport").SerialPort;
var serialPort = new SerialPort('/dev/ttyO2', {
baudrate: 115200,
parser: b.serialParsers.readline("\n")
});
The complete code:
var b = require('bonescript');
var x = '/dev/ttyO2';
var SerialPort = require("serialport").SerialPort;
var serialPort = new SerialPort('/dev/ttyO2', {
baudrate: 115200,
parser: b.serialParsers.readline("\n")
});
b.pinMode("P9_17", b.OUTPUT);
var countTry =2;
var i = 0; // to loop over the array
var waiting_interval = 3000; // waiting for every slave to reply
var deli;
var slaves = ["S1", "S2" , "S3", "S4", "S5", "S6"];
var counter=[0 , 0 , 0 , 0 ,0 ,0];
var slave_exists = false;
serialPort.on('open',function onSerialOpen(){
console.log("opened");
serialPort.on('data', function listenToSlaves(data){
i--;
if(data.search("END" + slaves[i]) ==0){
console.log("ENDED");
slave_exists = true;
counter[i]=0;
}
else{
// if(data!="END" + slaves[i]){
if(data.search("END" + slaves[i])!==0){
deli = data.indexOf(":");
var parameter = data.substring(0, deli);
var value = data.substring(deli +1);
console.log("parameter is: " + parameter + " - Value is: " + value);
}
}
if(slave_exists){
counter[i] =0;
}
i++;
});
writeToSlaves();
});
function writeToSlaves(){
//If the previous slave (the slave before the one I am sending to
//in the next step doesnt exist, add the counter or consideer
//it not existing)
if(!slave_exists){
counter[i-1]+=1;
if(counter[i-1]>=countTry){
console.log("--------counter[" + i + "]: " + counter[i]);
// in case that the slave returned no data after trying
//to send him several times
console.log(slaves[i-1] + " doesn't exist");
}
}
//sending to the following slave
b.digitalWrite("P9_17", b.HIGH);
serialPort.write(slaves[i], function(){ slave_exists = false;});
b.digitalWrite("P9_17", b.LOW);
console.log("I wrote to slave: " + i);
if(i<slaves.length - 1) i++;
else i=0;
setTimeout(writeToSlaves, waiting_interval);
}
but I am always facing this error:events.js:72
throw er; // Unhandled 'error' event
^
Error: Cannot open /dev/ttyO2
I am running another file first (the code down), the I try to rerun the previous code, and it runs perfect. I need to do that whenever I want to run the first code!
The code that runs from the first time is here:
( I tried the following code alone, it writes to the serial port but doesnt recieve, no event at recieption):
var b = require('bonescript');
var rxport = '/dev/ttyO2';
var txport = '/dev/ttyO2';
var options = { baudrate: 115200, parity: 'even', parser: b.serialParsers.readline('\n') };
var teststring = "This is the string I'm sending out as a test";
b.serialOpen(rxport, options, onRxSerial);
function onRxSerial(x) {
console.log('rx.eventrx= ' + x.event);
if(x.err) throw('***FAIL*** ' + JSON.stringify(x));
if(x.event == 'open') {
//readReapeatedly();
b.serialOpen(txport, options, onTxSerial);
}
if(x.event == 'data') {
console.log("I am receiving on rxport");
console.log('rx (' + x.data.length +
') = ' + x.data.toString('ascii'));
}
}
function onTxSerial(x) {
console.log('tx.event = ' + x.event);
if(x.err) throw('***FAIL*** ' + JSON.stringify(x));
if(x.event == 'open') {
writeRepeatedly();
}
if(x.event == 'data') {
// console.log('tx (' + x.data.length +
// ') = ' + x.data.toString('ascii'));
console.log(x.data);
}
}
function printJSON(x) {
console.log(JSON.stringify(x));
}
function writeRepeatedly() {
console.log("write to serial");
b.serialWrite(txport, teststring, onSerialWrite);
console.log("I have sent data");
}
function onSerialWrite(x) {
console.log("Iam in the onSerialWrite function");
if(x.err) console.log('onSerialWrite err = ' + x.err);
if(x.event == 'callback') {setTimeout(writeRepeatedly, 5000);
console.log("HERE");
}
}
The problem was solved.
In /boot/uboot/uEnv.txt, Update the line:"#cape_enable=capemgr.enable_partno= " to be:
"cape_enable=capemgr.enable_partno=BB-UART1,BB-UART2,BB-UART4, BB-UART5 "
or add the last line to the mentioned file. In some cases, you need to try this line instead of the mentioned:
"optargs=capemgr.enable_partno=BB-UART1,BB-UART2,BB-UART4, BB-UART5" (this is my case - but it disabled the HDMI interface of my BBB).
You can specify the UART you want to enable.
A helpful webpage is here.

Activate script only if specified columns change

This thing changes the status of two different columns dependent on each others' values. I want it to only trigger the script when the changes are in these two columns. This spreadsheet will have about 30 people on it and I do not want it activating every time a cell is edited. Please take a look and be aware I'm a complete newbee who pieced this together by Googling.
function onEdit(e) {
var s = e.source.getActiveSheet();
var data = s.getDataRange().getValues();
var data_len = data.length;
var headers = s.getRange(1, 1, 1, s.getLastColumn()).getValues();
var edit_headers = headers[0].indexOf('Edit');
var qc_headers = headers[0].indexOf('QC');
for(var i=0; i<data_len; i++) {
var edit = data[i][edit_headers];
var qc = data[i][qc_headers];
var edit_stat = s.getRange(i+1,edit_headers +1);
var qc_stat = s.getRange(i+1,qc_headers +1);
//Statuses for QC and Edit that change each other
var stat_1 = "Needs QC";
var stat_2 = "Pass";
var stat_3 = "Fail";
var stat_4 = "Fail Fix in Process";
var stat_5 = "Re-QC";
//Switch instead of elseif
switch (edit + qc) //edit + qc stats generate cases below
{
case stat_1: //Needs QC + ""
qc_stat.setValue(stat_1); //qc = Needs QC
break;
case stat_1 + stat_2: //Needs QC + Pass
edit_stat.setValue(stat_2); //edit = Pass
break;
case stat_1 + stat_3: //Needs QC + Fail
edit_stat.setValue(stat_3); //edit = Fail
break;
case stat_4 + stat_3: //Fail Fix in Process + Fail
qc_stat.setValue(stat_4); //qc = Fail Fix in Process
break;
case stat_1 + stat_4: //Needs QC + Fail Fix in Process
qc_stat.setValue(stat_5); //qc = Re-QC
break;
//Below are fail safes
case stat_2 + stat_3: //Pass + Fail; just in case qc Passes a fail
edit_stat.setValue(stat_3); //edit = Fail
break;
case stat_3 + stat_2: //Fail + Pass; just in case qc Fails a Pass
edit_stat.setValue(stat_2); //edit = Pass
break;
}
}
}
You can build an if-statement that checks the columns being edited and return (exit) the script if that column does not match the columns that are allowed to trigger the script (in which case indexOf will return -1).. E.g: let's say you only want to allow column 3 and 6 to trigger the script then do somehting like this:
function onEdit(e) {
var allowedCols = [3, 6];
if (allowedCols.indexOf(e.range.columnStart) === -1) return;
//rest of your code..
...
}
EDIT: If you also want to exclude certain tabs (see question in comments), you can try:
function onEdit(e) {
var allowedCols = [3, 6];
var disallowedTabs = ['Sheet3', 'Sheet5'];
if (allowedCols.indexOf(e.range.columnStart) === -1 || disallowedTabs.indexOf(e.source.getActiveSheet().getName() > -1) return;
//rest of your code..
...

if condition doesn't work with input variable

I have a problem in slideAC(data) function.
If condition seem to have some problem in the picture condition (data[0] == "picture")
I have already try to alert the data for testing the input value by alert(data[0]);
and the result is "picture" as well I have no idea what is the problem??
since other test condition work correctly.
HERE IS THE INPUT DATA IN THE extractData(data <-- array) FUCNCTION
(It's Already Split from other function by use split("\n"))
slide
,- width 400
,- height 300
,- into #slide1
,- picture
,+[pic/001.png]
,+[pic/002.jpg]
,+[pic/003.jpg]
,+[pic/004.jpg]
,
The purpose of the code is extract the words from the above text and generate some code.
function extractData(data){
alert(data);
var n = 0;
var step1 = "";
var step2 = "";
var step3 = "";
var step4 = "";
var picture =[];
//check '#' command by call the first line data
if(data[0].indexOf("slide") !== -1){
for(var i=1; i<data.length; i++){
// alert(n);
switch (n){
case 0:///////////////////////////////////////
// alert("case1");
//extract from '-'
if(data[i].indexOf('-') !== -1){
step1 = data[i].replace('-','');
step2 = step1.split(' ');
step3 = step2.slice(1,step2.length);
//slide Attribute Compiler
n = slideAC(step3);
}else{
alert("out");
}//end of if condition
break;
case 1:///////////////////////////////////////
// alert("case2");
//extract from '+'
if(data[i].indexOf('+') !== -1){
step1 = data[i].replace('+','');
step2 = step1.replace("[","");
step3 = step2.replace("]","");
picture.push(step3);
alert(step3);
}else if(data[i].indexOf('-') !== -1){
step1 = data[i].replace('-','');
step2 = step1.split(' ');
step3 = step2.slice(1,step2.length);
//slide Attribute Compiler
n = slideAC(step3);
}else{
//Error
// alert("wrong pic syntax");
// javascript_abort();
}//end of if condition
break;
}//end of iswitch case
}//end of item for loop
}else if(data[0].indexOf("menu") !== -1){
//Provision
}else if(data[0].indexOf("form") !== -1){
//Provision
}else{
javascript_abort();
}//end of if condition
}//end of syntaxCompiler
//slide Attribute Compiler
function slideAC(data){
// alert(data[0]);
var a = 0
if(data[0] == "width"){
var propWidth = data[1];
// alert(data[0] + " : " + propWidth);
// alert(typeof data);
a = 0;
}else if(data[0] == "height"){
var propHeight = data[1];
// alert(data[0] + " : " + propHeight);
// alert(typeof data);
a = 0;
}else if(data[0] == "into"){
var propInto = data[1];
// alert(data[0] + " : " + propInto);
// alert(typeof data);
a = 0;
}else if(data[0] == "picture"){
a = 1;
}else{
alert("why");
// javascript_abort();
}//end of if condition
return a;
}//end of slide attribute compiler
Do you have some advise ?? Please help
I just want the if condition work correctly
Thanks in advance
PS. Sorry If my wording make you confuse.
I'm guessing there may be space characters around the words. Hard to tell because you haven't shown a good picture of the result of the split, or shown the original input, and how you're splitting it.
If this is the case, you could trim it. I used a switch statement instead of your if/else if/else.
// trim the string-------v
switch(data[0].trim()) {
case "width":
var propWidth = data[1];
// alert(data[0] + " : " + propWidth);
// alert(typeof data);
a = 0;
break;
case "height":
var propHeight = data[1];
// alert(data[0] + " : " + propHeight);
// alert(typeof data);
a = 0;
break;
case "into":
var propInto = data[1];
// alert(data[0] + " : " + propInto);
// alert(typeof data);
a = 0;
break;
case "picture":
a = 1;
break;
default:
alert("why");
// javascript_abort();
}
You'll need a patch for the .trim() method if you support old browsers.
If js says it's false, then it is! You should eval your vars in a debugger to see what is happening. If using Chrome, just place a call to debugger to break and inspect vars values.
http://msdn.microsoft.com/en-us/library/ie/0bwt76sk(v=vs.94).aspx

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