knockout js polling not working - json

I am having difficulty with knockout refreshing.
Here's my viewModel;
$(document).ready(function () {
ko.applyBindings(new Task(), document.getElementById('taskSummary'));
setInterval(Task, 2000);
});
function task(name, description, project) {
var self = this;
self.name= ko.observable(name);
self.description = ko.observable(description);
self.project = ko.observable(project);
}
function Task() {
var self = this;
self.tasks = ko.observableArray([]);
self.tasks.removeAll;
$.getJSON("/api/tasks/5", function (data) {
$.each(data, function (key, val) {
self.tasks.push(new task(val.Name, val.Description, val.Project));
});
});
}
It returns data to the view but does not update when I change the data in the back end database.
any help appreciated. Im sure its something small that I'm missing.

For knockout, it might be better if you apply your model to a new Task instance, save that instance, then set up a setInterval loop that can modify the Task's "tasks" observableArray values.
$(document).ready(function () {
var oTask = new Task();
ko.applyBindings(oTask, document.getElementById('taskSummary'));
function onLoop() {
var self = oTask;
$.getJSON("/api/tasks/5", function (data) {
self.tasks.removeAll(); // not sure if you need this...
$.each(data, function (key, val) {
self.tasks.push(new task(val.Name, val.Description, val.Project));
});
});
}
setInterval(onLoop, 2000);
});

Related

IndexedDB transaction always throwing onabort from add() method in Chrome

I just started experimenting with IndexedDB. I copied an example and pared it down to a small HTML page: Push a button; add a record; dump all the records to the console after the transaction completes.
It runs fine in IE11, but not on Chrome.
The request=transaction.objectstore("store").add({k:v})is always executing the request.onsuccess() method, but the transaction is always resolved with transaction.onabort() by Chrome. Same with .put().
This is the code:
<!DOCTYPE html>
<html>
<head>
<script>
//--- globals
var db;
// The initialization of our stuff in body.onload()
function init() {
var dbVersion = 1;
//--- Try to delete any existing database
var delRequest = indexedDB.deleteDatabase("notesDB");
delRequest.onsuccess = function (de) {
dbOpen(); // .... then open a new one
};
delRequest.onerror = function (de) {
dbOpen(); // ... or open a new one if one doesn't exist to delete
};
function dbOpen () {
var openRequest = indexedDB.open("notesDB", dbVersion);
openRequest.onupgradeneeded = function (e) {
var ldb = e.target.result;
console.log("running onupgradeneeded; always start with a fresh object store");
if (ldb.objectStoreNames.contains("note")) {
ldb.deleteObjectStore("note");
}
if (!ldb.objectStoreNames.contains("note")) {
console.log("creating new note data store");
var objectStore = ldb.createObjectStore("note", { autoIncrement: true });
objectStore.createIndex("title", "title", { unique: false });
}
};
openRequest.onsuccess = function (e) {
db = e.target.result;
db.onerror = function (event) {
// Generic error handler for all errors targeted at this database
alert("Database error: " + event.target.errorCode);
console.dir(event.target);
};
console.log("Database opened; dump existing rows (shouldn't be any)");
displayNotes();
};
openRequest.onerror = function (e) {
console.log("Open error");
console.log(e);
console.dir(e);
};
}
function displayNotes() {
console.log("TODO - print something nice on the page");
var tx = db.transaction("note", "readonly");
tx.oncomplete = function (event) { console.log("read only cursor transaction complete"); }
tx.onerror = function (event) { console.log("readonly transaction onerror"); }
tx.onabort = function (event) { console.log("readonly transaction onabort"); }
// --- iterate cursor
console.log("---Start cursor dump---")
var ds = tx.objectStore("note");
ds.openCursor().onsuccess = function (event) {
var cursor = event.target.result;
if (cursor) {
console.log(cursor.key);
console.dir(cursor.value);
cursor.continue();
}
else {
console.log("---End cursor dump---");
}
};
}
document.querySelector("#test").addEventListener("click", function (clickevent) {
try {
var transaction = db.transaction("note", "readwrite");
transaction.oncomplete = function (event) {
console.log("Cursor dump in 'add' read/write transaction oncomplete");
displayNotes();
console.log("add transaction oncomplete done!");
};
transaction.onerror = function (event) {
console.log("add transaction onerror");
};
transaction.onabort = function (event) {
console.log("add transaction onabort");
};
var objectStore = transaction.objectStore("note");
var request = objectStore.add({
title: "note header",
body: "this is random note body content " + Math.floor(Math.random() * 1000)
});
request.onsuccess = function (event) {
console.log("add request onsuccess");
};
request.onerror = function (event) {
console.log("add request onerror");
console.dir(event);
};
}
catch (e) {
console.log('catchall exception');
console.log(e);
alert("bad things done");
}
});
}
</script>
</head>
<body onload="init()">
<h1>IndexedDB simplest example</h1>
<p>
<button id="test">Push To Add Row To IndexedDB</button>
</p>
</body>
</html>
I clicked the button a bunch of times and it worked every time.
What error are you getting when it aborts? Look in event.target.error in the onabort handler to see. It could be a QuotaExceededError, which would mean that either you have very low hard drive space or you have a lot of data stored in Chrome for your domain. If that's the case, it's good you're running into it now, because you do need to gracefully handle this case, otherwise users will hit it and be confused.

Jquery UI autcomplete with Json data source

I am using jquery UI autocomple with json data source but it's not working but when I used same with fixed data it works. Below is my code.
$(document).ready(function () {
var codes = "";
Admin_BasicFeeSchedule.LoadCPTCodes().done(function (response) {
if (response.status != false) {
if (response.CPTCodeCount > 0) {
var CPTCodeLoadJSONData = JSON.parse(response.CPTCodeLoad_JSON);
$.each(CPTCodeLoadJSONData, function (i, item) {
codes = codes + "'" + item.ShortName + "'";
});
//codes = codes + "]";
alert(codes);
}
}
else {
utility.DisplayMessages(response.Message, 3);
}
});
$.widget("ui.autocomplete", $.ui.autocomplete, {
_renderMenu: function (ul, items) {
var that = this;
$.each(items, function (index, item) {
that._renderItemData(ul, item);
});
$(ul).wrap("<div></div>");
},
});
$("input#ddlCPTCode").autocomplete({
source: [codes],//['Tom', 'Alex', 'Patrick'],
});
});
Based on jQueryUI's API, the source option can either be an array or a String that points to an URL or a Function. Furthermore, your code needs to change few things so that the array is handled in appropriate fashion:
$(document).ready(function () {
var codes = []; // array is created
Admin_BasicFeeSchedule.LoadCPTCodes().done(function (response) {
//alert("LoadCPTCodes works") ;
if (response.status != false) {
//alert("response.status true") ;
if (response.CPTCodeCount > 0) {
//alert("CPTCodeCount > 0") ;
var CPTCodeLoadJSONData = JSON.parse(response.CPTCodeLoad_JSON);
$.each(CPTCodeLoadJSONData, function (i, item) {
codes.push(item.ShortName); //add item to an array
});
//codes = codes + "]";
alert(codes);
}
}
else {
utility.DisplayMessages(response.Message, 3);
}
});
$.widget("ui.autocomplete", $.ui.autocomplete, {
_renderMenu: function (ul, items) {
var that = this;
$.each(items, function (index, item) {
that._renderItemData(ul, item);
});
$(ul).wrap("<div></div>");
},
});
$("input#ddlCPTCode").autocomplete({
source: codes // pass an array (without a comma)
});
});
Finally, if those changes related to the array aren't enough to make it work, then I would check the JSON load part. I have added some alert calls that can be uncommented for JSON testing purposes. As I am not familiar with the details of the JSON load functionality that is used in the sample code, then I'm just going to mention that there are alternative ways of loading JSON data such as jQuery's getJSON method.

Integrating tabletop.js with d3.js?

I want to reference a google spreadsheet using tabletop for for the data in my d3 visualization. The best solution I can come up with is this, but I know that it's not quite right.
window.onload = function() { init() };
var public_spreadsheet_url = 'https://docs.google.com/spreadsheet/pub?hl=en_US&hl=en_US&key=0AmYzu_s7QHsmdDNZUzRlYldnWTZCLXdrMXlYQzVxSFE&output=html';
function init() {
Tabletop.init( { key: public_spreadsheet_url,
callback: showInfo,
simpleSheet: true } )
}
d3.json("showInfo", function(data) {
console.log(data);
});
The data comes as an array already (see output below); and so there is no need to apply d3.json. You can start using the array for your d3 visualization right away.
window.onload = function() { init() };
var public_spreadsheet_url = "https://docs.google.com/spreadsheet/pub?hl=en_US&hl=en_US&key=0AmYzu_s7QHsmdDNZUzRlYldnWTZCLXdrMXlYQzVxSFE&output=html";
function init() {
Tabletop.init( { key: public_spreadsheet_url,
callback: showInfo,
simpleSheet: true } )
}
function showInfo(rows) {
console.log(rows);
// build your d3 vis here..
}

Combining AJAX/JSON call with iScroll

I am making a list form my JQM site from JSON data and are having no trouble with this. Now I want to add iScroll to the scene and if I use static list it works just fine, but when I get the list from JSON it won't fetch how many li I have and I can not scroll down to the bottom if I have lets say 20 li. I dont know how to combine my javascript so here is what i got so far [EDIT]:
var myScroll;
$(document).on('pageshow', function (){
var userid=1,
dataUrl = 'http://duefmun.dk/html5data/playermenu.php?callback=?&userid=' + userid,
dataCallback = function (data) {
var content = [];
$.each(data, function (i, val) {
content.push(val.list);
});
$('#games').html(content.join('')).listview('refresh');
},
fetchData = function () {
myScroll = new iScroll('wrapper');
if (myScroll.isReady()){
$.getJSON(dataUrl, dataCallback);
}
};
fetchData();
setInterval(fetchData, 20000);
document.addEventListener('touchmove', function (e) { e.preventDefault(); }, false);
document.addEventListener('DOMContentLoaded', function () { setTimeout(loaded, 200); }, false);
});
Hope this makes sense and any help is appreciated :-)
EDIT: I have edited the post with something I think should be right but it is still not working? Please help :-/
My suggestion is that you should create iScroll after you get your data. So, your code should be:
...
fetchData = function () {
if (myScroll.isReady()){
$.getJSON(dataUrl, dataCallback);
}
};
fetchData();
setInterval(fetchData, 20000);
myScroll = new iScroll('wrapper');
...

Backbone using external js

Hi all I have a site developed in cakephp and I would to integrate backbone on it.
For my scope I would to use external js for backbone to reuse the code.
I have write some lines but I can't append results on my element.
I have tried to print the "el" in this modes:
console.log($(this.el));
console.log(this.el);
console.log(this.$el);
But nothing I can't enter into el to make a simple append!
The container #search-results already exist
This is my main view:
<script type="text/javascript">
var search = {};
search.product = {};
search.product.template = "#results-product-template";
search.product.container = "#search-results";
search.product.defaults = {
id:0,
type:"product",
};
$(function(){
var ProductList = new Search.Collections.Products();
var ProductView = new Search.Views.Product({
// new Search.Collections.Products();
collection:ProductList
,el:$("#search-results")
});
function parseResults () {
var json = {
//my data
}
for (var i = json.products.length - 1; i >= 0; i--) {
ProductList.add([new Search.Models.Product(json.products[i])]);
};
updateResults();
}
function updateResults () {
console.log('updateResults: Ritorno il risultato quando hunter riceve una risposta dal server');
if ($('#search-results').length == 0) {
$('div.main > section:first-child').before('<section id="search-results"> <ul id="product-results"> <li>Contenuto</li> </ul> </section>');
}
ProductView.render();
}
// search
$('#search-results .close').on('click', function () {
$('#search-results').animate({height:0}, 500, function () {
$(this).remove();
})
});
});
</script>
And this is my external js with backbone
var Search = {
Models: {},
Collections: {},
Views: {},
Templates:{}
}
Search.Models.Product = Backbone.Model.extend({
defaults: search.product.defaults || {},
toUrl:function (url) {
return url.replace(" ", "-").toLowerCase();
},
initialize:function () {
console.log("initialize Search.Models.Product");
this.on("change", function (){
console.log("chiamato evento change del Model Search.Models.Product");
});
this.on("change:text", function () {
console.log("chiamato evento change:text del Model Search.Models.Product");
});
}
});
Search.Collections.Products = Backbone.Collection.extend({
model: Search.Models.Product,
initialize:function () {
console.log("initialize Search.Collections.Products");
console.log(this);
console.log(this.length);
console.log(this.models);
}
});
Search.Views.Product = Backbone.View.extend({
initialize:function () {
console.log("initialize Search.Views.Product");
console.log($(search.product.template).html());
},
template:function (data) {
if (data == null) {
data = this.collection.toJSON();
}
var template = Handlebars.compile($(search.product.template).html());
template(data);
},
render:function () {
console.log($(this.el));
$(this.el.append("TEST"));
//HERE IS THE PROBLEM
// I have tried this.$el.append("TEST");
return this;
}
});
Does this change anything?
var ProductView = new Search.Views.Product({
// new Search.Collections.Products();
collection:ProductList,
el:$("#search-results")[0]
});
I think backbone can accept both jQuery wrapped or not wrapped object and be fine, but I don't know what Backbone version you are using, see if this works
EDIT: From backbone 1.0 sources, it seems backbone can indeed take either a jQuery wrapped object or a regular dom element, it should still work
this.$el = element instanceof Backbone.$ ? element : Backbone.$(element);
Do you have something online (JSFiddle?) I will be happy to take a look, but this.$el should work and be equal to $("#search-results") from your code in a quick glance.
Have you tried using ProductView.setElement($("#search-results")) instead? it should be the same, but worth a try as well.