Can't access array from within protractor callback - javascript

I'm new to both protractor and javascript. I ran into a scoping issue which I can't figure out. In the code segment below, the first array access statement works but the second doesn't. What gives?
for(var i=0;i<=1;i++){
console.log(msgs[i]);
element.all(by.className("form-group")).get(i).element(by.className("alert alert-danger")).getText().then(function(txt){
console.log(msgs[i]);
});
}

You just need to change
... .getText().then(function(txt){ ... });
to
... .getText().then((txt) => { ... });
It's called fat arrow function and it does not have it's own this so you can access your array.

Related

Javascript - pass THIS in function doesnt work

I am very new to Javascript and I just stuck with something that works in python.
The problem is that I have class where I initiate some empty lists as this.data_y_json and etc. If I make normal function inside class like normal_function(){this.data_y_json = 5} it works and the variable is changed.
However, i work with d3, and there is some trick which I cant get through:
// inside class
// in constructor all this.xxx defined
// after object initiation I call set_data()
set_data(){
d3.json("link2.json",function(data) {
for (var i=0;i<data.d.results.length;i++){
this.data_y_json.push(parseFloat(data.d.results[i].PE))
...
//end of function
// end of class
After calling function set_data() an error is raised: SCRIPT5007: Unable to get property 'data_y_json' of undefined or null reference
I am rewriting my visualization into OOP, before this, I had it solved with global variables and it worked fined. In python I would just passed 'self' as an argument to function, but here in javascript, passing THIS doesnt work and raises another error.
Simply said, I know the problem -> this.data_y_json is not recognized propably because of function(data) doesnt pass self of the object, but I dont know how to do it.
Thank in advance for advice
Are you in an ES2015 environment? Changing your callback to be an arrow function should scope this to be what you want
d3.json("link2.json", (data) => {
for (var i=0;i<data.d.results.length;i++){
this.data_y_json.push(parseFloat(data.d.results[i].PE))
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions
For reading up on the arrow function and the scoping of this

How do I use a function as a variable in JavaScript?

I want to be able to put the code in one place and call it from several different events.
Currently I have a selector and an event:
$("input[type='checkbox']").on('click', function () {
// code works here //
});
I use the same code elsewhere in the file, however using a different selector.
$(".product_table").on('change', '.edit_quantity', function () {
// code works here //
});
I have tried following the advice given elsewhere on StackOverflow, to simply give my function a name and then call the named function but that is not working for me. The code simply does not run.
$(".product_table").on('change', '.edit_quantity', function () {
calculateTotals() {
// code does not work //
}
});
So, I tried putting the code into it's own function separate from the event and call it inside the event, and that is not working for me as well.
calculateTotals() {
// code does not work //
}
So what am I doing wrong ?
You could pass your function as a variable.
You want to add listeners for events after the DOM has loaded, JQuery helps with $(document).ready(fn); (ref).
To fix your code:
$(document).ready(function() {
$("input[type='checkbox']").on('click', calculateTotalsEvent)
$(".product_table").on('change', '.edit_quantity', calculateTotalsEvent)
});
function calculateTotalsEvent(evt) {
//do something
alert('fired');
}
Update:
Vince asked:
This worked for me - thank you, however one question: you say, "pass your function as a variable" ... I don't see where you are doing this. Can you explain ? tks. – Vince
Response:
In JavaScript you can assign functions to variables.
You probably do this all the time when doing:
function hello() {
//
}
You define window.hello.
You are adding to Global Namespace.
JavaScript window object
This generally leads to ambiguous JavaScript architecture/spaghetti code.
I organise with a Namespace Structure.
A small example of this would be:
app.js
var app = {
controllers: {}
};
You are defining window.app (just a json object) with a key of controllers with a value of an object.
something-ctlr.js
app.controllers.somethingCtlr.eventName = function(evt) {
//evt.preventDefault?
//check origin of evt? switch? throw if no evt? test using instanceof?
alert('hi');
}
You are defining a new key on the previously defined app.controllers.somethingCtlrcalled eventName.
You can invoke the function with ();.
app.controllers.somethingCtlr.eventName();
This will go to the key in the object, and then invoke it.
You can pass the function as a variable like so.
anotherFunction(app.controllers.somethingCtlr.eventName);
You can then invoke it in the function like so
function anotherFunction(someFn) { someFn();}
The javascript files would be structured like so:
+-html
+-stylesheets
+-javascript-+
+-app-+
+-app.js
+-controllers-+
+-something-ctlr.js
Invoke via chrome developer tools with:
app.controllers.somethingCtlr.eventName();
You can pass it as a variable like so:
$(document).ready(function() {
$('button').click(app.controllers.somethingCtlr.eventName);
});
JQuery (ref).
I hope this helps,
Rhys
It looks like you were on the right track but had some incorrect syntax. No need for { } when calling a function. This code should behave properly once you add code inside of the calculateTotals function.
$(".product_table").on('change', '.edit_quantity', function () {
calculateTotals();
});
$("input[type='checkbox']").on('click',function() {
calculateTotals();
});
function calculateTotals() {
//your code...
}
You could just condense it all into a single function. The onchange event works for both the check box and the text input (no need for a click handler). And jQuery allows you to add multiple selectors.
$('input[type=checkbox], .product_table .edit_quantity').on('change', function() {
console.log('do some calculation...');
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="product_table">
<input type="checkbox">
<input class="edit_quantity">
</div>

Passing a function with parameter to event handler

Let's say I have the following code:
$('#from').focus(listExpand(1));
$('#to').focus(listExpand(3));
It's not working as I expected. I think that it works wrong due to the fact that I'm passing a function result but not the function itself.
So the right syntax would be:
$('#from').focus(listExpand); // no brackets and no parameters
But in this case I can not pass any parameters to a function :(
How can I implement the subject?
Wrap the call to listExpand in a separate function definition:
$('#from').focus(function(){ listExpand(1); });
$('#to').focus(function(){ listExpand(3); })
below will work. use this.
$('#from').focus(function() {listExpand(1) });
$('#to').focus(function(){listExpand(3);})
I found other cool way also that #sudher mentioned. You can check it working in http://jsfiddle.net/kvHDA/
Sample Code
$('#from').focus({x: 1},myfunc);
function myfunc( e){
alert(e.data.x);
}
If a data argument is provided to .on() and is not null or undefined,
it is passed to the handler in the event.data property each time
an event is triggered.
$('#from').on("focus" , {id:1} , listExpand);
$('#to').on("focus" , {id:3} , listExpand);
function listExpand(event){
console.log(event.data.id);
}

Cannot access variable inside jQuery.each

Here is a function that is in one of my objects:
updatePorts: function(nodeKey, portOptions, portArrays) {
var showing_ports = false;
$('#ports li').removeClass('active').hide();
$('#ports .tab-pane').removeClass('active in');
$.each(portOptions, function(side, options) {
if (options.editable) {
$('#ports [href="#'+side+'"]').closest('li').show();
if (!showing_ports) {
$('#ports [href="#'+side+'"]').closest('li').addClass('active');
$('#ports #'+side).addClass('active in');
}
$.each(portArrays[side], function(i,port) {
//do stuff
}
showing_ports = true;
}
})
}
My problem is that outside of the $.each loop I can access the portArrays variable that is passed as an argument into the function. However, I cannot access that same variable inside of the $.each loop.
Am I doing something wrong? How can I gain access to that variable inside the loop?
UPDATE: Added code where portArrays is actually being accessed
portArrays is defined where you're using it, but you're using the wrong index. The side variable is an index into portOptions, not portArrays.
What index should it have? If these two arrays run in parallel with the same index values, that's generally a bad idea - it's better to use a single array of objects - and at least needs to be documented in your code.
BTW, what is the exact error message in the JS console? If my guess isn't right, the error message would give a clue.
I had the problem described in the subject, however it seems the asker had a problem elsewhere in his code. My code is similar to the below and I could not access what I wanted from this. The first log would work, but the log inside the each loop was undefined. I realise now that this is reassigned when using jquery each - http://api.jquery.com/each/
List.prototype.updateList = function(search) {
console.log(this.id);
$.each(this.data, function(item, tags) {
console.log(this.id); //undefined
};
}
I've changed to using for .. in to iterate my this.data object and it's working. Hope this may help someone.
List.prototype.updateList = function(search) {
console.log(this.id);
for(var key in this.data){
console.log(this.id); //hooray
}
}

Why does "this.myFunction" not work when calling a function inside an object?

Here are two samples of code. The first one does not work and the second one does, though I'm completely at a loss as to why. Can someone explain this?
[I'm writing a simple game using a bit of jQuery to be played in a webkit browser (packaged with Titanium later).]
In the first example, Firebug tells me that "this.checkCloud" is not a function.
function Cloud(){
this.checkCloud = function(){
alert('test');
}
$("#"+this.cloudName).click(function(){
this.checkCloud();
});
}
...but then this works:
function Cloud(){
this.checkCloud = function(){
alert('test');
}
var _this = this;
$("#"+this.cloudName).click(function(){
_this.checkCloud();
});
}
This one works perfect.
Why does the first one not work? Is it because "this.checkCloud" is inside of the anonymous function?
in this example:
$("#"+this.cloudName).click(function(){
this.checkCloud();
});
this referrers to the element selected(jquery object).
what you can do is use private functions
var checkCloud = function(){
alert('test');
}
this way you can simply call it inside your anonymous function
$("#"+this.cloudName).click(function(){
checkCloud();
});
That is because the meaning of this can potentially change each time you create a new scope via a function. The meaning of this depends on how the function is invoked (and the rules can be insanely complicated). As you discovered, the easy solution is to create a second variable to which you save this in the scope where this has the expected/desired value, and then reuse the variable rather than this to refer to the same object in new function scopes where this could be different.
Try this:
function Cloud(){
this.checkCloud = function(){
alert('test');
}
var func = this.checkCloud;
$("#" + this.cloudName).click(function(){
func();
});
}
When you assign an even listener to an element, jQuery makes sure that this will refer to the element. But when you create the _this variable, you're creating a closure that jQuery couldn't mess with, even if it wanted to.

Categories