I cannot access to enyo Ui component from function:onComplete in WebOS 3.0.
buttonTapped: function(inSender, inEvent) {
console.log("Button is clicked");
this.$.txt.setContent(inSender.name + " tapped."); // This worked
var request = webOS.service.request("luna://com.webos.service.tv.systemproperty", {
method: "getSystemInfo",
parameters: {"keys": ["modelName", "firmwareVersion", "UHD", "sdkVersion"]},
onComplete: function (inResponse) {
var isSucceeded = inResponse.returnValue;
if (isSucceeded){
console.log("Result: " + JSON.stringify(inResponse));
$.txt.setContent("Result: "+JSON.stringify(inResponse)); // This is not worked
}
}
});
...
Console output
Button clicked
Result{"modelName":"WEBOS1","firmwareVersion":"03.00.00","UHD":"false","sdkVersion":"03.00.00","returnValue":true}
Uncaught TypeError: Cannot read property 'txt' of undefined
I not found any documentation about this.
The reason for the error is that your callback function is not executing in the context of your component. this is not your component (not to mention you're missing the keyword this in front of $.txt...).
What you need to do is bind the context of the callback function or use it to create a closure over a variable that contains a reference to this.
This is a such a common occurrence that Enyo provides a utility method for this: this.bindSafely.
Try the following:
onComplete: this.bindSafely(function (inResponse) {
var isSucceeded = inResponse.returnValue;
if (isSucceeded){
console.log("Result: " + JSON.stringify(inResponse));
this.$.txt.setContent("Result: "+JSON.stringify(inResponse));
}
})
See: http://enyojs.com/docs/latest/#/kind/enyo/CoreObject/Object:bindSafely
Related
I'm new to javascript so can anyone help me figure out why this code is not working?
I have a class and it calls a cordova barcode scanning function. I've got an example that works, however I want to be able to separate out the function(result) and function(error) and use onSuccess(result) and onFailure(error).
I have no idea why this is happening so if anyone can help that would be great.
EDIT: so ive updated the code based on Stradosphere said however im still getting result is not defined errors.
Full error message:
Uncaught ReferenceError: result is not defined at barcodeScanner.scanBarcode (barcodeScanner.js:10) at HTMLButtonElement.myFunction (main.js:18)
var me = this;
class barcodeScanner {
constructor() {
this._barcodeResult = 0;
}
scanBarcode() {
//THIS THROWS result is not defined error
cordova.plugins.barcodeScanner.scan(me.onSuccess(result), me.onFailure(error));
//THIS WORKS
cordova.plugins.barcodeScanner.scan(
function (result) {
me._barcodeResult = result.text;
alert("Barcode Scanned:" + me._barcodeResult);
},
function (error) {
alert("Scanning failed: " + error);
}
);
}
onSuccess(result) {
this._barcodeResult = result.text;
alert("Barcode Scanned:" + this._barcodeResult);
}
onFailure(error) {
alert("Scanning failed: " + error);
}
}
Looking at the docs, it appears that cordova.plugins.barcodeScanner.scan() expects you to pass a function into it. But you are calling it like this:
cordova.plugins.barcodeScanner.scan(me.onSuccess(result), me.onFailure(error));
This is passing the result of the function .onSuccess(result), but result is not defined, so you are getting an error. Additionally, you want this to be the class instance, but by defining me as this outside the class, me won't equal the class instance like you want it to. But you don't need it anyway.
Try passing functions in instead:
cordova.plugins.barcodeScanner.scan((result) => this.onSuccess(result),(error)=> this.onFailure(error))
Maybe a scope issue on your use of this. Try:
var me = this; //(put this at class level)
cordova.plugins.barcodeScanner.scan(me.onSuccess, me.onFailure);
I know that I can change the value of a vue data value from within a method by using this.variable_name. But when I'm trying to do this from within a method with a sub-method (because I'm making an ajax request) I am getting an undefined error.
I have something like
var myvue = new Vue({
name: "MyVue",
el: '#my-vue-id',
data: {
fields: field_list // this is set in another js method elsewhere
},
methods: {
reject: function (index, objectid) {
if (confirm("Are you sure?")) {
$.get("/reject/" + objectid, function (data) {
if (data.success == true) {
$("#" + objectid).fadeOut(400, function() {
this.field_list.splice(index, 1);
});
} else {
alert('Failed to delete.');
}
});
}
}
}
});
I also tried setting var self = this; within the $.get method, then trying to splice self.field_list but in both cases I get an error Cannot read property splice of undefined
EDIT since I may have been unclear-- the field_list is being populated. If I were to do this.field_list.splice outside the ajax function, it works fine. The issue is just how to access external scope from with the vue methods.
A callback function does not get your Vue instance as its context (this) when it is called. Use arrow functions for your callbacks, or save this to a variable and use that.
You need to do the var self = this; outside of the $.get method (before it) as within the $.get method you have a different scope, and that is the root of the problem. Then within the $.get method use self.field_list.splice(index, 1);
I try to change some way to call methods into namespace.
Calling parent methods (I dont think its possible)
Creating and call inheritance function
Calling inside another method (mostly jquery onReady event function) (this.MyFunction() not working)
I split every namespace in files (want to keep it that way)
I try How to call function A from function B within the same namespace? but I didn't succed to split namespaces.
my fiddle sample got only 1 sub-namespace but could be more.
https://jsfiddle.net/forX/kv1w2rvc/
/**************************************************************************
// FILE Master.js
***************************************************************************/
if (!Master) var Master = {};
Master.Print= function(text){
console.log("master.Print :" + text);
$("body").append("<div>master.Print : " + text + "</div>");
}
/**************************************************************************
// FILE Master.Test1.js
***************************************************************************/
if (!Master) var Master = {};
if (!Master.Test1) Master.Test1 = {};
/**************************************************************************
* Descrition :
* Function for managing event load/documentReady
**************************************************************************/
Master.Test1.onReady = function () {
$(function () {
Master.Test1.Function1(); //try to replace because need all namespace.
try {
this.Function2(); //not working
}
catch(err) {
console.log("this.Function2 not working");
$("body").append("<div>this.Function2 not working</div>");
}
try {
this.Print("onReady"); //not working
}
catch(err) {
console.log("this.Print not working");
$("body").append("<div>this.Print not working</div>");
}
try {
Print("onReady"); //not working
}
catch(err) {
console.log("Print not working");
$("body").append("<div>Print not working</div>");
}
});
}
Master.Test1.Function1 = function () {
console.log("Function1");
$("body").append("<div>Function1</div>");
this.Function3(); //working because not inside another function
}
Master.Test1.Function2 = function () {
$("body").append("<div>Function2</div>");
console.log("Function2");
}
Master.Test1.Function3 = function () {
$("body").append("<div>Function3</div>");
console.log("Function3");
Master.Print("Function3"); //try to replace because need all namespace.
}
Master.Test1.onReady();
I use Master.Test1.Function1(); and I want to change that because Function1 is inside the same namespace.
I use Master.Print("Function3"); I dont think I can change that. the way I try to use it, it's more an inheritance function. but I dont know if theres a way to do that?
Maybe I should change the my namespace methode? maybe prototype will do what I want?
You can capture the this in a variable because this inside $(function() {}) will point to document object. The below will work provided you never change the calling context of onReady -- i.e. it is always called on the Test1 object and not called on other context:
Master.Test1.onReady = function () {
var self = this;
$(function () {
self.Function1();
// ..
});
}
To access Print you have to reference using the Master object like: Master.Print() as it won't be available in the Test1 object
this is document within .ready() or jQuery() alias for .ready() where function(){} is parameter $(function() {}). this at this.Function2() will reference document.
"Objects" in javascript are not built the same way as in most object-oriented languages. Essentially, what you are building is a hierarchy of static methods that have no real internal state in-and-of themselves. Therefore, when one of the defined methods is invoked, the context (or state) of that method depends on what object invoked the method.
If you want to have any internal context, you will need to create an "instance" of an "object prototype". At that point, you can use "this.otherFunction" within your other functions. Here is a small example:
var MyObject = function() {};
MyObject.functionOne = function() {
console.log("Function 1");
this.functionTwo();
};
MyObject.functionTwo = function() {
console.log("Function 2");
};
var instanceOne = new MyObject();
instanceOne.functionOne();
You might get some more information about object definition here
Excuse the title but I'm not really sure what this is called (Maybe events?):
I have created a class that someone will use:
function cls_something()
{
this.notify('hello');
}
Now the person using my class creates a method called 'notify' (as instructed by me) in order to listen for notifications and then perform their own custom code using the param I pass:
var something = new cls_something();
something.notify = function(message)
{
console.log('The notification is ' + message);
}
How do I call this method from within the class to give him the notification message?
Fiddle
I'm trying to achieve something like this...
websocket = new WebSocket("ws://localhost:10000");
websocket.onopen = function(e)
{
console.log('you are connected');
}
websocket.onmessage = function(e)
{
console.log('omg wtf ffs, there was an error: ' + e.msg);
}
You can just call this.notify("Message"); You'd probably want to check to see if it's defined first, though.
EDIT 1:
Ok, so your problem here is that you're calling a function straight from the constructor, before it's defined. If it needs to be defined in the constructor, then pass the function as a parameter.
function cls_something(notifyFunction)
{
notifyFunction('hello');
}
EDIT 2:
Just so we're clear, you can have the user of your class define functions later, if you'd like. You just can't run them straight from the constructor, obviously. If you run them from the constructor, they need to be defined before hand.
Say your class was something like
function cls_something()
{
this.someFunctionThatIsRunLater = function() {
this.notify('hello');
}
}
Then your client can write
var something = new cls_something();
something.notify = function(message)
{
console.log('The notification is ' + message);
}
Then, when the client calls
something.someFunctionThatIsRunLater();
Notify will be called.
Solved? Not quite.
https://github.com/jashkenas/backbone/issues/2822
This is a Cordova + Backbone mobile App. I've been banging my head against this one for a while and thought it was time for some help.
App.PhotoButtonView = Backbone.View.extend({
pic: "",
picid: 1,
events : {
"click #addPhotoBtn": "addPhoto"
},
initialize: function( options ) {
this.options = options;
},
render: function() {
var html = JST['photo-button/view']({num: this.options.picid});
$(this.el).html( html );
setTimeout(this.postrender, 0);
return this;
},
postrender: function() {
// reset to default image pic
console.log('addPhotoBtn' + this.options.picid);
document.getElementById('addPhotoBtn' + this.options.picid ).src = this.pic;
var photo = document.querySelector("#addPhotoBtn" + this.options.picid);
},
I'm still getting...
Error: Uncaught TypeError: Cannot read property 'picid' of undefined
but now it's fired by the postrender function. I bet it's something to do with this setTimeout hack.
edit: This is the code in the parent view that initializes the PhotoButtonView
postrender: function() {
$('#submitBtn, .topcoat-button--large').prop('disabled', false);
this.photo = new App.PhotoButtonView({picid: 1});
$('#photoButtons').html(this.photo.render().el);
if (App.activePost.get('photo1')) {
this.photo2 = new App.PhotoButtonView({picid: 2});
$('#photoButtons').append(this.photo2.render().el);
}
if (App.activePost.get('photo2')) {
this.photo3 = new App.PhotoButtonView({picid: 3});
$('#photoButtons').append(this.photo3.render().el);
}
if (App.activePost.get('photo3')){
this.photo4 = new App.PhotoButtonView({picid: 4});
$('#photoButtons').append(this.photo4.render().el);
}
},
Note: A sophomore CS intern wrote this code-base. I'm patching for new functionality.
This looks like a common mistake regarding the binding of this.
Because we're passing the this.postrender callback unbound to setTimout, it will be called "function" style in the scope of the global namespace and this will be bound to the global object, not the view.
There are two ways we could adjust the setTimeout call so that when referencing this in the postrender method it is bound correctly.
Option 1 (call/apply style):
setTimeout(this.postrender.bind(this), 0);
Option 2 (method style):
var that = this;
setTimeout(function () {
that.postrender();
}, 0);
Here's a pretty good article by Yehuda Katz about this and invocation.
http://yehudakatz.com/2011/08/11/understanding-JavaScript-function-invocation-and-this/