Keeping an instance of fabric.Image in a variable - javascript

First post here, because I cannot find any answer. I'm working on FabricJS, and I'm trying, for the need of my application, to build objects containing an instance of fabric.Image, and more specifically an instance obtained through the methode fabric.Image.fromURL() (see here for more info)
Until now it seems to work, but if I console.log my object containing the instance of the image, I got an object of type "klass", which seems to have some image-related properties, but not all of them (no position, no source, no rotations, etc).
And when I'm trying to use fabric.Image methods on this object, I got errors concerning non-existing functions.
My question is the following : is this fact known ? Is there any mean to keep an instance of a fabric.Image anywhere else than in a canvas ?
I think my code is not very relevant to post here, but if needed I will sweep up my code to make it concise and show precisely what I want.
Thanks,
Cheitan
EDIT : I tried several other things. The most promising way to do what I want was to instantiate the image object from an URL, but instead of adding it to the canvas through the callback of the function, assigning it to an attribute of my custom object. Something like that :
var that = this;
fabric.Image.fromURL('img/myImg.png', function(img){
that._image = img;
});
But this is not working either, I got the following error from fabric.min.js :
Uncaught TypeError: obj.setupState is not a function
I found several posts on this site or others concerning this error message but none of them are related to what I'm doing, it's more like JSON parsing and rebuilding fabric forms from it. Am I in a wrong way ?

Related

What does .$ mean in javascript

I was in the console trying something when i saw that the .$ can be used along with the document object to access the elements. But i don't know what it actually does.
example :-
After some detective work, my guess it is a special Polymer component property:
Automatic node finding
Polymer automatically builds a map of statically created instance nodes in its local DOM, to provide
convenient access to frequently used nodes without the need to query
for them manually. Any node specified in the element's template with
an id is stored on the this.$ hash by id.
I am not familiar with Polymer, and it is very difficult to find (recent) documentation on this property.
However I believe my guess is correct based on the description above and the screen shot below. As you can see, if you add another . after the $ you get a list of suggested properties. These are all ids in the DOM:
I guess that may be any global object under jquery. Exactly, I don't have any experience with .$ but surf the official docs of Jquery, it may help or another possibility is that it is something coming from backend of from database. There may be a lot of reason. Hope, it helps..
This should be a property added to the element but is not anything special.
An example would be like
let a = {};
a.$ = {
b: 1,
c: 2
};
console.log(a.$);
This will also give you the object properties of $ in a.
A bonus fun fact is, in Javascript, emoji is also valid as property name, and therefore
let a = {};
a.$ = {
"😍": 1,
"😎": 2
};
console.log(a.$["😍"]);
also works

GWT-JSNI passing a JavaScriptObject in an external JS library

I'm desesperatly trying to create an Anno object in a JSNI method but I have a strange problem : the code in the jsni method doesn't work but if I do the same in my browser console, it works fine.
Java Part
I'm using a JSONArray in wich I add some JSONObject (with all the elements, according to Anno doc). Here's my JSNI method :
// I'm using the getJavaScriptObject() on my JSONArray
private static native void launch( JavaScriptObject steps )/*-{
var anno = new $wnd.Anno(steps);
anno.chainIndex().show();
}-*/;
Browser Part
Just to be clear, the method is called on a onShow event, so all the ressources are loaded and rendered. So when the element is displayed and the function called, I have this error in my console :
Couldn't find Anno.target 'h1'. --- anno.js:265
NB : In Anno.js, h1 is the dafault value of target.
But my steps value is right and when I do the same commands in the console it works :
var testAnno = new Anno([{
content: "namespinnerFrequencyA",
position: "center-right",
target: ".dataAuto0"
},{
content: "chooseFrequencyB",
position: "top",
target: ".dataAuto1"}]);
testAnno.show();
I don't understand why it works in one case and not in the other. I've also tried to use JSON.stringify then JSON.parse but it doesn't work either.
EDIT :
I figured something out. While debugging anno.js I figured something : when I initialized Anno in the console, the local scope look like this (bigger image here ) :
But when I use the jsni method, the local scope is absolutely different, my parameter is stored as an actual array instead of being processed normally (bigger image here ) :
The problem is that GWT code runs in an iframe (for sandboxing/isolation) and Anno only supports array types from the same browsing context.
See http://perfectionkills.com/instanceof-considered-harmful-or-how-to-write-a-robust-isarray/ and http://web.mit.edu/jwalden/www/isArray.html for descriptions of the problem.
ECMAScript 5.1 added an Array.isArray() function that solves that issue and has wide browser support (back up to IE9): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray
And jQuery has one too, which makes it incomprehensible (to me) that Anno doesn't use it instead of using the broken if arg.__proto__ is Array.prototype (unless it's by design). So first things first: file an issue on Anno.
As a workaround, it should be possible to use $wnd.Array.apply($wnd.Array, steps) to copy your array into an array from the top window.
It seems to me that the error message says it cant find the target dom element and not that it cant find the target property. Is the element there when your code is fired? make sure it is and get back to me.

Howto: generic test to see if widgets call this.inherited succesfully?

I maintain a custom library consisting of many dijit widgets at the company I work at.
Many of the defects/bugs I have had to deal with were the result of this.inherited(arguments) calls missing from overriden methods such as destroy startup and postCreate.
Some of these go unnoticed easily and are not always discovered until much later.
I suspect I can use dojo\aspect.after to hook onto the 'base' implementation, but I am not sure how to acquire a handle to the _widgetBase method itself.
Merely using .after on the method of my own widget would be pointless, since that wouldn't check whether this.inherited(..) was inded called.
How can I write a generic test function that can be passed any dijit/_WidgetBase instance and checks whether the _widgetBase's methods mentioned above are called from the widget when the same method is called on the subclassing widget itself?
Bottom-line is how do I acquire a reference to the base-implementation of the functions mentioned above?
After reading through dojo's documentation, declare.js code, debugging, googling, debugging and hacking I end up with this piece of code to acquire a handle to a base method of the last inherited class/mix-in, but I am not entirely happy with the hackiness involved in calling getInherited:
Edit 2 I substituted the second param of getInherited with an empty array. While I actually get a reference to the method of the baseclass using aspect doesn't work. It appears this approach is a bust.
require(['dijit/registry','dojo/_base/declare','mycompany/widgets/widgetToTest'],
function(registry,declare,widgetToTest)
{
var widget = registry.byId('widgetToTestId');
var baseStartup = getBaseMethod(widget,'startup');
function getBaseMethod(widget,methodName){
return widget.getInherited(methodName,[]);
}
//This is the method body I want to use .after on to see if it was called, it returns the last overriden class in the array of inherited classes. (a mixin in this case, good enough for me!)
alert(baseStartup);
});
I have given up trying to use dojo/aspect.
I have instead opted to modify the code of our custom base widget to incorporate snippets such as the one below. They are automatically removed when creating a release-build in which console-calls and their content are removed:
console.log(
function(){
(this._debugInfo = this._debugInfo|| {}).postCreate=true;
}.call(this)
);
A simple method in boilerplate code I added near the unittests is available so that I can call it on all mycompany.widgets.basewidget instances in their respective unittests.

Subscribing to changes in siblings with Knockout.js

I'm using inheritance to implmenet a reuseable forms app.
Expression parameter can be dependent on one or more other numeric/constant ot other expression parameters (the relation is many to many so heirarchy wont work here). Once all my dependent parameters evaluated them self (calcualted if expression or validated if user input) I can now calculate my self.
I'm looking for a way to subscribe to my siblings but the problem is that during creation the sibling does not neccasarily exists yet.
I set up a small example on this Fiddle.
To see this not working in action lets change the values from the console
d.parameters()[0].value(10) // expecting parameter C to sum up to 20.
d.parameters()[2].value() // Nothing (this should also update ont he screen).
d.parameters()[1].value(20) // expecting parameter C to sum up to 30.
d.parameters()[2].value() // Still nothing.
So Ive tried sevral things but i think i'm barking up the wrong tree here.
Fetching the parent using ko.dataFor(document.body) or
fetching the object from the DOM using the same function.
I've played around with deferEvaluation as you can see in the code
to force KO to first create the parameters and then apply the
binding. seems to do nothing.
Tried creating a observableArray with the links to the params and a
computed based on the array but the problom remain.
Appreciate any help here.
Bonus question, without losing focus from the main one, somehing I cant explain going on on line 73.

What is a reverse reference to the DOM object?

In this link: http://css-tricks.com/snippets/jquery/jquery-plugin-template/ it has a line of code that says
// Add a reverse reference to the DOM object
base.$el.data("yourPluginName", base);
what does the "reverse reference to the DOM object" mean?
Assuming that you know the jQuery data function:
It's storing a reference to the instance of the class in the data cache of jQuery, meaning that the stored instance can be used to access the initial base object if it in the current context is not available.
This way, the class instance can be used later. However, the use of the prototype keyword upon the initial class that the instance were created from will modify the instance.
EDIT:
Ooops, it seems that Anurag is right, and I was giving wrong information.
Sorry, the information I gave in initial answer was not completely correct. I've updated the answer, so it now tells the truth.
In the comments you're asking:
so you mean its storing the current state of "base" in the data cache but if we make changes to "base" later on then the one in the data wont be affected? so if for some reason we needed to get the original one again we can do data('yourPluginName') to retrieve it? can you give me an example of when this would be helpful?
It seems that none of the statements are correct.
As I did obviously not remember adequately, the thing stored in data is only a reference to the object:
var obj = {};
obj.hello = "Hello";
$("#someElement").data("object", obj);
obj.world = " world.";
alert(
obj.hello +
$("#someElement").data("object").world
); // alerts "Hello world."
BTW, JavaScript variables with names like this base-thing (but, more often seen as that or similar) are typically used to represent the current context, accessed through the this keyword, which on many occasions is more easy to store in another variable due to scoping/context changes, that will make the current context and therefore this, change.
Also due to issues with context, the stored value in data could be used to access the specific object instance from another context (that is, when this represents something else), instead of the version of the base object that was continually used after a copy of it was stored.
I hope this answered you questions :D
The technique and the problem it solves is general and not specific to jQuery plugins. There may be cases where a Javascript object corresponds to a DOM element, and wraps logic specific to that DOM element. This object might be interested in listening to events such as clicks that happen within that DOM element. The information we get in those callbacks is the element that triggered it, and not the associated object. You could use jQuery's data API or any type of map in general to retrieve the corresponding object, and do something with it.

Categories