Can I grab the current template within the javascript console? - javascript

if you have an onRendered callback, you can log the this to get the template.
Template.myTemplate.onRendered(function () {
console.log(this);
});
For debugging purposes, in the javascript console, is it possible to get the current rendered template via some sort of script? Eg:
> var ctx = Template.myTemplate // something like this

In Chrome (and possibly other browsers), after you console.log an object, you can right click on the output in the JavaScript console and click "Store as global variable". That will assign it to a variable (named temp1, temp2, and so on). You can then access that object through the new variable.
Also in Chrome, selecting an element in the developer tools makes it available in the JavaScript console as $0. If you define the following function globally:
getTemplateInstance = function (elem) {
var view = Blaze.getView(elem);
while (!view.templateInstance) {
view = view.parentView;
}
return view.templateInstance();
}
Then you can get any rendered template instance by following these steps:
Right click somewhere on the template
Click "Inspect element"
In the developer tools, switch to the JavaScript console
Enter getTemplateInstance($0) to get the template instance.
If you're careful to only select an element at the top level of the template (not inside a {{#if}}, {{#each}}, etc.) then you can skip the getTemplateInstance function and just run Blaze.getView($0).templateInstance() in the console.
You can also use Blaze.getData($0) to get the data context of an element.

Because its possible to have two of the same template you have explicitly pass on its reference to a global variable.
ctx = null;
Template.myTemplate.onRendered(function () {
ctx = this;
});
This should let you use 'ctx' anywhere. It depends a lot on where you use it, you can get the template instance in events or helpers you can get the template instance from within its own helpers or events:
Template.myTemplate.events({
'click #something': function(e,tmpl) {
console.log(tmpl) //The template instance
console.log(Template.instance()) //just like tmpl
}
});
Template.myTemplate.helpers({
'somehelper': function() {
console.log(Template.instance());
}
});

Related

Detect when a function is getting called in JavaScript

There are several elements on HTML page which triggers a js function HardCoded().
I cannot modify HardCoded() function.
I want to run some custom js code after the HardCoded() function is getting called. How can I do that? Is there any handlers for js functions?
I'm building a chrome extension that's why I cannot modify page source code.
I have access to JQuery.
One way is to find all elements who are calling HardCoded() and attach events to those elements but I would like to avoid this method.
You could do something like this:
var oldFn = HardCoded;
window.HardCoded = function(){
var res = oldFn.apply(this, arguments);
// New Code ....
return res;
}
What this does is to create a reference to the HardCoded function, redefine this function and then call the old implementation using the previously created reference.

Javascript: Reassigning 'this', or alternative?

I am building a small app which is part of a sales-enquiry process. It has 'pages' which the visitor progresses through. I have laid out these pages as part of a large object literal. In the following code, branch-select is one of those pages. As you can see, the init() function sets a sibling value by using this to refer to the parent branch-select. However, the save() function is called from a click event, so instead of using this, it seems I have to laboriously write out the full object reference each time to set values? Please see the code & comments below to illustrate the problem:
// This is part of a larger object called "stepData"
"previous page": {
// ...
}
"branch-select": {
ref: "Select Type",
visited: false,
init: function(){
this.visited = true; // Here I can use "this" to set other values in the parent object
// ....
},
next: "",
save: function(){
branchKey = $(this).attr('data-value'); // this function is invoked from a click event, so "this" refers to the DOM element that was clicked. Therefore throughout the rest of the function if I want to set values on the parent object, I have to write out the full object reference each time...
switch(branchKey){
case "Lodges":
stepData['branch-select'].ref = "Lodges";
stepData['branch-select'].values[0].a = "Lodges";
stepData['branch-select'].next = "lodge-2"; // Do I really have to write out stepData['branch-select'] each time?
break;
case "Caravans":
stepData['branch-select'].ref = "Caravans";
stepData['branch-select'].values[0].a = "Caravans";
stepData['branch-select'].next = "van-2";
break;
}
stepData[stepData['branch-select'].next].init();
}
},
"next page": {
// ...
}
In the interests of DRY (Don't repeat yourself) code, I was wondering if there is any neat solution to this?
EDIT:
Webkit's answer presents a new problem; the clicked DOM element (.branch-select) is dynamically introduced, so to bind the click event, I have to use:
$("#template-holder").on('click', ".branch-select", stepData['branch-select'].save);
(template-holder is the parent element which is always present). How would I integrate the call() method into the above code?
Another way to have "this" reference your object when handling an event is using 'call'.
for example:
var setData = {
save: function(){
// 'this' shall be setData!
var _bs = this['branch-select'];
_bs.ref = "Lodges"...
}
}
then:
$(".someElement").on('click', function() {
setData.save.call(setData)
});
**updated (I'm pretty sure this should work just the same):
$("#template-holder").on('click', ".branch-select", function() {
stepData['branch-select'].save.call(setData)
});

Changing the current closure?

I am trying to get some old code to work properly with minimal modification. The code was written on the assumption that it would run from a particular context. I have the context object.
Original code:
function oldExample(){
console.log(window); //New Error: window is undefined
console.log(gBrowser); //New Error: gBrowser is undefined
}
New, working code:
function fixedExample(){
console.log(this.window);
console.log(this.gBrowser);
}
//Elsewhere
function loadData(context) {
fixedExample.call(context);
}
Notes:
1. loadData and oldExample are defined in separate files.
2. context has other children besides window and gBrowser; This is an example
Is there a way to transition my oldExample code to work properly without needing to stuff this. everywhere? I.e., how can I run oldExample in a different context?
The only way I know how to do this is to define the properties as variables of the current context:
var object = {gBrowser: 'test'};
function oldExample(){
console.log(gBrowser);
}
var gBrowser = object.gBrowser;
oldExample();
This example outputs 'test'
But all this does is move the property access outside of the function definition, doesn't save you anything.
You can use bind method in javascript.
fixedExample.bind (context);
Now you need not use 'this' inside fixedExample and can use window directly.

backbone view this.$ is undefined

I am following a backbone.js tutorial and a part of the code isn't working, maybe because Backbone has changed in the meantime or because I'm doing something wrong. This is the render function of my view.
// grab and populate our main template
render: function () {
// once again this is using ICanHaz.js, but you can use whatever
this.el = ich.app(this.model.toJSON());
// store a reference to our movie list
this.movieList = this.$('#movieList');
return this;
},
The element gets appended into the document later in the code. Subsequently, when the code tries to adds elements to this.movieList, Javascript says it's undefined.
I have tried changing this.el = ... to
this.setElement(ich.app(this.model.toJSON()));
and that helps because this.$el is now defined, but if i try this.$el.find(...) it never finds anything, even though through inspection in Chrome it does appear to contain the HTML elements.
I never used ICanHaz but it it works like the other template languages probably returns HTML code. In that case i'd do something like:
render: function(){
this.$el.html(ich.app(this.model.toJSON()));
}
addMovie: function (movie) {
var view = new MovieView({model: movie});
this.$el.find("#movieList").append(view.render().el);
},
Hope this helps
PS: This is the first time I see this.$('something') in a backbone code o_O. Is he storing the reference of JQuery on the view?

Javascript Object inexplicably bound to Window and Object

I've javascript object
var Bucket = function(id) {
this.id = id
this.items = []
}
Bucket.prototype.add_item = function(item) {
//some uniquness checking code here
this.items.push(item);
}
For some reason, when I instantiate the object and try to add an item, I get an error
var bct = new Bucket
bct.add_item(some_item)
'undefined' is not an object (evaluating 'this.items.push')
This error occurs even though the item is getting added to the array of the bucket
console.log(bct.items)
>> [some_item]
I used console.log(this) inside the add_items method and I see two entries being logged from the same line
>Object myjavascript.js:28
>DOMWindow myjavascript.js:28
There are some other libraries included on the page
Google Analytics
jQuery
Colorbox plugin for jQuery
jQuery Easing
Any ideas what is binding this object to Window?
FOUND IT (Edit)
somewhere else on the page, I was using a jquery ajax call in combination with my object... and it was binding it... sorry for not posting all of the relevant code...
You say "the item is getting added", but that is irrelevant, because according to your logging you have two calls to the method, one of which is correct. You need to focus on the incorrect one.
Make sure you have a debugger in your browser (e.g. Chrome with the Web Inspector opened), and modify your code like so:
Bucket.prototype.add_item = function(item) {
if (this === window) debugger;
//some uniquness checking code here
this.items.push(item);
}
This will automatically pause your code when the erroneous call has occurred. Then, look at the call stack to find out what is calling your add_item function other than as a method.

Categories

Resources