Models/View in Different Files - backbone.js

I just tried to adopt backbone.js to my project with the todo example. In my app.js file I try to instantiate my views/models/collections etc. but I try to I get the error msg: app is not defined in TodoList.
HTML:
<head>
<script type="text/javascript" src="js/json2.js"></script>
<script type="text/javascript" src="js/jquery-1.7.1.min.js"></script>
<script type="text/javascript" src="js/underscore-min.js"></script>
<script type="text/javascript" src="js/backbone-min.js"></script>
<script type="text/javascript" src="js/backbone-localstorage.js"></script>
<script type="text/javascript" src="js/models/models.js"></script>
<script type="text/javascript" src="js/collections/collections.js"></script>
<script type="text/javascript" src="js/views/views.js"></script>
<script type="text/javascript" src="js/views/app.js"></script>
<script type="text/javascript" src="js/app.js"></script>
app.js(root for my application):
var app = {
models:{},
collections:{},
views:{}
};
jQuery(function($) {
var Todos = new app.collections.TodoList;
var test = new Todo;
var test2 = new TodoView;
var appView = new AppView({});
});
collections.js:
app.collections.TodoList = Backbone.Collection.extend({
model: Todo,
localStorage: new Store("todos"),
done: function() {
return this.filter(function(todo) {
return todo.get('done');
});
},
remaining: function() {
return this.without.apply(this, this.done());
},
nextOrder: function() {
if (!this.length) return 1;
return this.last().get('order') + 1;
},
comparator: function(todo) {
return todo.get('order');
}
});

You're trying to use a namespace before it's ready. Two options. First, have 'app.js' first but take out initialization code and put that into a 'bootstrap.js' that's loaded absolute last. Second option, and the one that I generally lothe, define your namespaces that you need in the file if they aren't already there. For example
var app = app || {};
app.collection = app.collection || {};
Basically, the code is loading in one by one. When you say namespace.subspace, the code expects that namespace has already been defined as something - generally an object in most cases that I've seen. Without that base piece the code will just flatline - it'll assume you're trying to do the equivalent of building a castle starting with the roof.

Related

.withButtons() is not a function

Am trying to export my datatable into excel or csv but when I use .withButtons(), I get an error saying its not a function
The dependencies added are:
<script src="{context.links.resourceBaseUrl|s}/vendor/datatables.net-buttons/dataTables.buttons.min.js"></script>
<script src="{context.links.resourceBaseUrl|s}/vendor/datatables.net-buttons-bs/buttons.bootstrap.js"></script>
<script src="{context.links.resourceBaseUrl|s}/vendor/datatables.net-buttons-bs/buttons.bootstrap.min.js"></script>
<script src="{context.links.resourceBaseUrl|s}/vendor/datatables.net-buttons/buttons.colVis.min.js"></script>
<script src="{context.links.resourceBaseUrl|s}/vendor/datatables.net-buttons/buttons.flash.min.js"></script>
<script src="{context.links.resourceBaseUrl|s}/vendor/jszip/jszip.min.js"></script>
<script src="{context.links.resourceBaseUrl|s}/vendor/datatables.net-buttons/buttons.html5.min.js"></script>
<script src="{context.links.resourceBaseUrl|s}/vendor/datatables.net-buttons/buttons.print.min.js"></script>
<script src="{context.links.resourceBaseUrl|s}/vendor/datatables/angular-datatables/plugins/buttons/angular-datatables.buttons.min.js"></script>
And my columns are defined as below
$scope.dtColumnDefs = {
open: [
DTColumnDefBuilder.newColumnDef(1).notSortable(),
DTColumnDefBuilder.newColumnDef(2).notSortable(),
DTColumnDefBuilder.newColumnDef(5).notSortable(),
DTColumnDefBuilder.newColumnDef(6).notSortable(),
DTColumnDefBuilder.newColumnDef(7).notSortable()
],
closed: [
DTColumnDefBuilder.newColumnDef(1).notSortable(),
DTColumnDefBuilder.newColumnDef(2).notSortable(),
DTColumnDefBuilder.newColumnDef(5).notSortable(),
DTColumnDefBuilder.newColumnDef(8).notSortable(),
DTColumnDefBuilder.newColumnDef(9).notSortable(),
DTColumnDefBuilder.newColumnDef(10).notSortable(),
DTColumnDefBuilder.newColumnDef(11).notSortable(),
DTColumnDefBuilder.newColumnDef(12).notSortable()
]
}
And my controller code
$scope.dtOptions = DTOptionsBuilder.newOptions()
.withPaginationType('full_numbers')
.withDOM('Blrtip')
.withButtons([{
title : 'liveissues',
text:'Export To CSV',
exportOptions:
{
columns:[1,2,5]}
}
]);
I do not have datatables and datatables.buttons injected in angular.module. When I add them I get a blank page with out any console error
Can someone help?I tried what ever I know and I could not progress further

Firestore: snapshotChanges is not a function

In reference to this post, I hit a problem where it says snapshotChanges is not a function:
TypeError: db.collection(...).snapshotChanges is not a function
at new <anonymous> (index.js:139)
at Object.instantiate (angular.js:5156)
at angular.js:11719
at Object.link (angular-route.js:1251)
at angular.js:1388
at Ba (angular.js:11266)
at p (angular.js:10585)
at g (angular.js:9832)
at angular.js:9697
at angular.js:10111 "<ng-view autoscroll="true" class="ng-scope">"
Below is my code:
(Note that with or without pipe() will also hit the same error too.)
var db = firebase.firestore();
$scope.accounts = db.collection("Accounts").snapshotChanges().pipe(map(actions => {
return actions.map(a => {
const data = a.payload.doc.data();
const id = a.payload.doc.id;
return { id, ...data };
});
}));
On my SPA index.html, I have the following references defined:
<script defer src="/__/firebase/6.4.1/firebase-app.js"></script>
<script defer src="/__/firebase/6.4.1/firebase-auth.js"></script>
<script defer src="/__/firebase/6.4.1/firebase-firestore.js"></script>
<script defer src="/__/firebase/6.4.1/firebase-messaging.js"></script>
<script defer src="/__/firebase/6.4.1/firebase-storage.js"></script> -->
<script defer src="/__/firebase/init.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.7.8/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.7.8/angular-route.min.js"></script>
<!-- AngularFire -->
<script src="https://cdn.firebase.com/libs/angularfire/2.3.0/angularfire.min.js"></script>
May I know why this error (snapshotChanges is not a function) still appear? I need it to include the doc.id in my mapping result, thank you!
If you're using the plain JavaScript SDK to query Firestore, and you want to attach a listener to a Query, you should be using onSnapshot() for that.
If you want to use the AngularFire API instead and use snapshotChanges, that's going to require a going through its own API (see the link), which is different than the plain JavaScript SDK.

Pulling Shopify data with angularjs

So i've been using a test file to try and pull Shopify data from the store. What I THINK is the problem, is that the api is making the request to fetch the data, but it takes longer to fetch the data than to run through my script. So the variable gets set to null. I'm assuming I need a way to check if the promise is successful and/or write the data to a JSON file. Anyway, here's the code. The page shows up blank when you run it.
App.js
phonecatApp.controller('PhoneListController', function
PhoneListController($scope) {
var products_complete;
var products = [];
//init the client
const client = window.ShopifyBuy.buildClient({
domain: 'some-site.myshopify.com',
storefrontAccessToken: 'xxxxxxxxxxxx'
});
$scope.getShop = function () {
//get the complete product listings from shopify
client.product.fetchAll().then((raw_products) => {
products_complete = raw_products;
reduce_products();
$scope.products = $scope.setProductValue();
});
//reduce the products list down to necessary information
function reduce_products() {
for (var i in products_complete) {
var product_tmp = products_complete[i];
var product = {};
//add name and tags
product['title'] = product_tmp['title'];
product['tags'] = product_tmp['tags'];
product['type'] = product_tmp['productType'];
product['pic_urls'] = [];
//add the images
for (var j in product_tmp['images']) {
if (product_tmp['images'][j]['src'] != null) {
product['pic_urls'].push(product_tmp['images'][j]['src']);
}
}
product['vars'] = []
for (var k in product_tmp['variants']) {
var w = product_tmp['variants'][k]['weight'];
var p = product_tmp['variants'][k]['price'];
var a = product_tmp['variants'][k]['available'];
if (!((typeof w == 'undefined') && (typeof p == 'undefined') && (typeof a == 'undefined'))) {
product['vars'].push({
'weight': w,
'price': p,
'available': a
});
}
}
//add the current product to the final list
if (('title' in product) && ('tags' in product) &&
(product['pic_urls'].length != 0) &&
(product['vars'].length != 0)) {
products.push(product);
}
}
}
return products;
}
index.html
<!doctype html>
<html lang="en" ng-app="phonecatApp">
<head>
<meta charset="utf-8">
<title>Google Phone Gallery</title>
<link rel="stylesheet"
href="bower_components/bootstrap/dist/css/bootstrap.css" />
<link rel="stylesheet" href="app.css" />
<script
src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js">
</script>
<script src="https://sdks.shopifycdn.com/js-buy-sdk/v1/latest/index.umd.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css">
<script src="bower_components/angular/angular.js"></script>
<script src="app.js"></script>
</head>
<body ng-controller="PhoneListController" ng-cloak>
<ul>
<li ng-repeat="product in products">
<p>{{product.title}}</p>
</li>
</ul>
</body>
</html>
Your local variable products is not visible within your HTML. You should use $scope.products within _reduce_products_ function, or return the value and assign it to $scope.products.
The products var you are using in your HTML is $scope.products, that has the value of:
$scope.products = $scope.setProductValue();
So, in your promise success function you should update $scope.products with the products your are reducing in your _reduce_products_ function, or if you're using $scope.products for another thig, you should have another scope variable for that.
client.product.fetchAll().then((raw_products) => {
products_complete = raw_products;
// What's this? $scope.products = $scope.setProductValue();
$scope.products = reduce_products(); // return reduced products array
});

Include multiple module in angularjs

I have a module like this :
var master = angular.module('master', ['DataService'])
master.controller('MasterController', function ($scope, MasterOp) {
$scope.status;
$scope.reports;
$scope.data = {
singleSelect: "all",
flag : "true"
};
$scope.filter = function() {
$scope.data.flag = "false";
};
$scope.groupBy = {
pubid : "false",
sid : "false",
device : "false"
};
$scope.getMasterReports = function() {
$scope.user = JSON.parse(sessionStorage.response);
//alert($scope.groupBy.pubid+"ak");
MasterOp.getMasterReport($scope.sdate,$scope.edate,$scope.user.pubProfile.pubid,$scope.groupBy.pubid,$scope.groupBy.sid,$scope.groupBy.device)
.success(function (data) {
$scope.reports = JSON.parse(data.report);
$scope.metrics= $scope.user.pubProfile.metrics;
})
.error(function (error) {
$scope.status = 'Unable to load customer data: ' + error.message;
});
};
$scope.logout = function(){
window.location.href="/AnalyticsMaster/index.html";
};
$scope.tab2 = function()
{
$scope.groupBy.sid="true";
$scope.groupBy.pubid="false";
$scope.data.flag = "true";
$scope.data.SingleSelect = "all";
$scope.reports=null;
$scope.getMasterReports();
};
$scope.tab3 = function()
{
$scope.groupBy.pubid="true";
$scope.groupBy.sid="false";
$scope.data.SingleSelect = "all";
$scope.data.flag = "true";
$scope.reports=null;
$scope.getMasterReports();
};
$scope.tab1 = function()
{
$scope.groupBy.pubid="false";
$scope.groupBy.sid="false";
$scope.data.flag = "true";
$scope.data.SingleSelect = "all";
$scope.reports=null;
$scope.getMasterReports();
};
});
When i trying to add more module in this it stop working. I am not able to understand why its happening.
For Example if i add like this its not working even adding any other module also its stop working.
var master = angular.module('master',['myApp','DataService'])
var master = angular.module('master',['ui.directives','ui.filters','DataService'])
Both cases it stop working. Please help me to understand what i am doing wrong.
Index.html
when adding multiple modules in your project make sure you have a ref to it in your index html. like this
<!-- Angular Modules -->
<script type="text/javascript" src="app/app.module.js"></script>
<script type="text/javascript" src="app/app.routes.js"></script>
<script type="text/javascript" src="app/components/home/homeCtrl.js"></script>
Or non custom modules
<!-- Angular links -->
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.5/angular.js"></script>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.5/angular-animate.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.15/angular-ui-router.js"></script>
Its the same as adding any script.
Main Module
The second thing you do is add them to your main module like this
var app = angular.module("myApp", [
'ui.bootstrap',
'ngAnimate',
'myAppRouter',
'myAppHomeCtrl',
'myAppHomeService',
'myAppNavbarDirective',
'myAppNavbarService',
'myAppLoginCtrl',
'myAppLoginService'
]);
Live Example
The best practice in angular is to create a module for each of your features. I've been working on a project here is a link to the project, feel free to fork or clone it to get a good look at the structure.
You are declaring the same module name repeatedly.
You only declare a module once. The module function requires the second argument for dependency array when you declare it.
After that when you want to add components to that module you use the module getter which doesn't have the dependency array argument
// declare a new module
angular.module('master', ['DataService']); // has another module dependency
// add components to existing module
angular.module('master').controller(....;
// add the dependency module shown in "master"
angular.module('DataService', []);// might also have different dependencies here

Why does Google App Engine Channel API (jsapi) fail to load in a Chrome extension?

I'm using the Channel API in a Chrome extension.
In Google App Engine Channel API Javascript Reference (Python) page it says that
Include the following in your html page before any JavaScript code
that refers to it:
<script type="text/javascript" src="/_ah/channel/jsapi"></script>
So, I put that in the header of my options.html file:
<html>
<head>
<title>Extension Options</title>
<script type="text/javascript" src="/_ah/channel/jsapi"></script>
</head>
but Chrome throws jsapiFailed to load resource error. What am I doing wrong?
Update
As per Moishe's answer I updated the call to jsapi like this:
<head>
<title>Extension Options</title>
<!-- this does not work because it is local
<script type="text/javascript" src="/_ah/channel/jsapi"></script>
-->
<script type="text/javascript" src="https://talkgadget.google.com/talkgadget/channel.js"></script>
</head>
Update
I added onopen and other properties. Now I get the onopen alert but I am not getting the evt.data alert. What am I doing wrong?
<html>
<head>
<title>Extension Options</title>
<!-- this does not work because it is local url
<script type="text/javascript" src="/_ah/channel/jsapi"></script>
-->
<script type="text/javascript" src="https://talkgadget.google.com/talkgadget/channel.js"></script>
</head>
<body>
<p>Enter your gmail address:</p>
<textarea id="getEmail" style="margin-bottom: 4px; width: 250px; height: 20px">
</textarea><br />
<button id="save">Save</button>
<!--<button id="save">Clear</button>-->
<script>
document.getElementById("getEmail").placeholder = "your gmail address" ;
//save entered gmail address
document.getElementById("save").addEventListener
(
"click",
function ()
{
var userEmail = document.getElementById("getEmail").value;
var formData = new FormData();
formData.append("extension_user", userEmail);
alert("after formData.append")
var channel;
var socket;
var handler =
{
onopen: function () { alert("onopen") },
onerror: function () { alert("onerror") },
onclose: function () { alert("onclose") },
onmessage:
function (evt)
{
//evt.data will be what the server sends in channel.send_message
console.log("evt.data received from authhandler: " + evt.data);
alert("evt.data is: " + evt.data)
}
};
var xhr = new XMLHttpRequest();
//changed to lowercase
xhr.onreadystatechange = function()
{
//alert("xhr.onReadyStateChange")
//error handling etc not included
if (xhr.readyState == 4 && xhr.status == 200)
{
token = xhr.responseText;
alert("token: " + token)
channel = new goog.appengine.Channel(token);
socket = channel.open(handler);
}
};
xhr.open("POST", "http://ting-1.appspot.com/authsender", true);
xhr.send(formData);
console.log("formData sent to authsender: " + formData);
}, false
)
</script>
</body>
</html>
In a chrome extension, you'll need to directly specify the path for the Channel javascript (https://talkgadget.google.com/talkgadget/channel.js). The request for /_ah/channel/jsapi can't be redirected by anything because the file that's trying to load it is local.

Resources