I've been working through a wonderful set of tutorials by Derick Bailey and ran into an issue with adding a Router. in IE it describes the error as : SCRIPT5007: Unable to get value of the property 'extend': object is null or undefined (in IE)
Uncaught TypeError: Cannot call method 'extend' of undefined (in Chrome)
I did read this question : uncaught-typeerror-cannot-call-method-extend-of-undefined
The code in question is here:, but I did verify that underscore was loaded in the html of the page via HTTPWatch. Also, about 100 lines earlier in the same file, I invoke underscore for another method. Code is spot on with what is in the tutorial as far as I can tell.
ImageGallery.Router = Backbone.Router.extend({
routes: {
"images/:id": "showImage"
},
initialize: function (options) {
this.collection = options.collection;
},
showImage: function (id) {
var image = this.collection.get(id);
ImageGallery.showImage(image);
}
});
Any insights would be appreciated.
I put the rest of the backbone code on JSFiddle here http://jsfiddle.net/poundingCode/4ekU3/ b/c it was too hard to format.
Related
I am a naive React Developer and facing some difficulty with getting gooogle chart work with react. I am using Google Charts in a ReactJs component with ControlWrapper as shown below.
componentDidMount: function(){
google.charts.load('current', {'packages':['corechart', 'controls']});
this.drawCharts();
},
componentDidUpdate: function(){
google.charts.load('current', {'packages':['corechart', 'controls']});
this.drawCharts();
},
drawCharts: function(){
var cmpt = this;
//Removed detailed code from here due to copyright issues
//adding controls----------------
let dashboard = new google.visualization.Dashboard( document.getElementById(cmpt.props.widgetId) );
let controlId = '${this.props.widgetId}_control';
var controlWrapper = new google.visualization.ControlWrapper({
'controlType' : 'NumberRangeFilter',
'containerId' : controlId,
'options' : {
'filterColumnLabel' : xDataSysName
}
});
var barChart = new google.visualization.ChartWrapper({
'chartType': 'BarChart',
'containerId': this.props.widgetId,
'options': options
});
dashboard.bind(controlWrapper, barChart);
dashboard.draw(data);
if(linkColumn){
let selectionEventHandler = function() {
window.location = data.getValue(barChart.getSelection()[0]['row'], 1 );
};
google.visualization.events.addListener(barChart, 'select', selectionEventHandler);
}
}
},
This is not the whole piece of code but should be enough for the issue I'm facing.
First time I load the page, I get the error in the console saying
google.visualization.Dashboard is not a constructor
I reload the page hitting SHIFT+F5, the error goes away and components load just fine except ones that are dependent on controlWrapper throwing the error as follows
google.visualization.controlWrapper is not a constructor
which never goes away even after reloading the page. I referred to this discussion and tried their solution but I am still getting these error in the manner mentioned above. Please help me figure out how to fix it. Also, I am not able to comprehend why dashboard error goes away on a reload.
need to wait until google charts has fully loaded before trying to use any constructors,
this is done by providing a callback function.
try changing the load statement as follows...
componentDidMount: function(){
google.charts.load('current', {packages:['corechart', 'controls'], callback: this.drawCharts});
},
componentDidUpdate: function(){
google.charts.load('current', {packages:['corechart', 'controls'], callback: this.drawCharts});
},
everything seems correct, but whenever I do the following, I get TypeError: f is undefined in backbone 1.1.2, Also, when I debug, I saw that it was able to receive the correct response, yet when I do categories.toJSON() I get nothing:
var categories = new App.Lookup.CategoryCollection();
categories.url = 'index.php?r=lookupapi/categories';
categories.fetch();
App.Lookup.CategoryCollection = Backbone.Collection.extend({
model: App.Lookup.CategoryModel
});
App.Lookup.CategoryModel = Backbone.Model.extend({
});
What am I doing wrong here?
Update:
I use the development version as suggested by user972 and got the following error message:
TypeError: this.model is undefined
categories.fetch() is the one causing the error, it pointed to this function in backbone:
// Define how to uniquely identify models in the collection.
modelId: function (attrs) {
return attrs[this.model.prototype.idAttribute || 'id'];
},
But I still couldn't figure out why it is undefined.
The declaration of App.Lookup.CategoryModel is not hoisted above App.Lookup.CategoryCollection. You need to define App.Lookup.CategoryModel before you use it.
So change your code to:
App.Lookup.CategoryModel = Backbone.Model.extend();
App.Lookup.CategoryCollection = Backbone.Collection.extend({
model: App.Lookup.CategoryModel
});
var categories = new App.Lookup.CategoryCollection();
categories.url = 'index.php?r=lookupapi/categories';
categories.fetch();
In response to:
I saw that it was able to receive the correct response, yet when I do
categories.toJSON() I get nothing
If you want to see the results of fetch you need to pass a success callback:
categories.fetch({
success: function(collection, response, options) {
console.log(collection.toJSON());
}
});
Just out of curiosity, have you referenced the script files in the proper order? It seems more of from script loading error than the code based.
<script src="underscore-1.6.0-min.js"></script>
<script src="backbone-1.1.2-min.js"></script>
Other thing that might be of help is to use non-min version of backbone and try locating where it is crashing and why?
<script src="http://backbonejs.org/backbone.js"></script>
I'm trying to use Ext.util.DelayedTask to make some timed functions go off. I'm getting the error Uncaught TypeError: undefined is not a function call. It's coming from line 126 of DelayedTask.js in the Sencha source code. Click here to see the source.
Here is the code I wrote which runs the tasks.
var appView = Ext.ComponentQuery.query('.meterreadings_main')[0];
var meterList = Ext.ComponentQuery.query('.mbList[alias="meterListObject"]')[0];
var taskOne = Ext.create('Ext.util.DelayedTask', {
scope: this,
fn:function() {
appView.pop();
}
});
var taskTwo = Ext.create('Ext.util.DelayedTask', {
scope: this,
fn:function() {
meterList.select(meterStore.getCurrentRecordIndex());
}
});
var taskThree = Ext.create('Ext.util.DelayedTask', {
scope: this,
fn:function() {
meterList.config.itemTapHandler(null,meterStore.getCurrentRecordIndex(), null,
meterStore.getCurrentRecord(), null, null);
}
});
appView.pop();
taskOne.delay(500);
taskTwo.delay(1500);
taskThree.delay(2500);
See anything wrong?
Even though the ST2 docs show that you can create a delayed task like how you are currently doing, you actually need to do it the following way:
var taskOne = Ext.create('Ext.util.DelayedTask', function() {
console.log('delayed task');
}, this);
Here are the parameters you can pass, you'll see I already included the scope above:
Parameters
fn : Function
The default function to call.
scope : Object
The default scope (The this reference) in which the function is called. If not specified, this will refer to the browser window.
args : Array
The default Array of arguments.
Good Luck!
My single page web application consists of 4-5 views stacked vertically, when a user chooses a menu item, the page will scroll to the appropriate view. When you come into the application for the first time this is not a problem, however if you deep link to a menu item my page throws a fit because it's trying to access properties of an element that does not yet exists.
The problem I am having is understanding why the elements do not exist at the time the router is trying to scroll the page.
If you load / and then select home no problems, but if you directly hit #home via browser that when I get jQuery undefined errors.
Uncaught TypeError: Cannot read property 'top' of undefined
Inside router I am instantiating and rendering all of my views within the initialize function. The idea is the initialize will always happen before any of my routes, clearly not the case.
Again I've read a few threads that show how to have a before and after function for either all routes of individual routes but even using that approach scrollToById fails because it doesn't know what $(id) is at the time of being called.
define(function (require, exports, module) {
var Backbone = require('backbone');
return Backbone.Router.extend({
initialize: function(){
require(['ui/menu/menu','ui/home/home', 'ui/samples/samples', 'ui/resume/resume', 'ui/contact/contact'],
function(Menu, Home, Samples, Resume, Contact){
var menu = new Menu();
menu.render();
var home = new Home();
home.render();
var samples = new Samples();
samples.render();
var resume = new Resume();
resume.render();
var contact = new Contact();
contact.render();
});
},
routes: {
'' : 'init',
'home' : 'home',
'samples' : 'samples',
'resume' : 'resume',
'contact' : 'contact'
},
init: function(){
},
home: function (){
this.scrollToById($(".home-container"));
},
samples: function(){
this.scrollToById($(".samples-container"));
},
resume: function(){
this.scrollToById($(".resume-container"));
},
contact: function(){
this.scrollToById($(".contact-container"));
},
scrollToById: function(id) {
var val = $(id).offset().top - 127;
$('html, body').animate({
scrollTop: val
}, 2000);
}
});
});
Appreciate any tips or advice.
I think the routes event handlers in the router are getting initialized at the same time as the initialize function. Because of this, route events are getting triggered before the DOM elements are rendered.
I would try making a new function outside of Router that contains everything currently inside the initialize function. Then the final thing in that function can be to create an instance of the router. This will ensure that no routes events are called until your scripts and DOM are loaded.
I'm trying this easy code from Addy's book but I can't make it work:
var TodoRouter = Backbone.Router.extend({
routes: {
"about" : "showAbout",
"search/:query" : "searchTodos",
"search/:query/p:page" : "searchTodos"
},
showAbout: function(){},
searchTodos: function(query, page){
var page_number = page || 1;
console.log("Page number: " + page_number + " of the results for todos containing the wo");
}
});
var myTodoRouter = new TodoRouter();
Backbone.history.start();
The console returns this with an error:
Uncaught TypeError: Property '$' of object #<Object> is not a function backbone-min.js:1
h.extend.start backbone-min.js:1
(anonymous function)
If I comment out Backbone.history.start() there's no error (neither the "app" behaves the way it is supposed to behave).
Any help is appreciated.
[SOLVED] the JS files (JQuery, Underscore and Backbone were added to HTML in the wrong order. The right order for me was: JQuery, Underscore, Backbone, MyOwnJSFiles. Thanks anyone for reading, hope this helps