I get this error at the very beginning. Not sure how to fix. I also get the expected an assignment or function call and instead saw an expression. Not to mention Expected an identifier and instead saw "var"
<script>
var interactiveSearch = {};
(function() {
interactiveSearch.common = {
init: function() {
interactiveSearch.common.setupDataTableDefaults();
$.ajaxSetup({
cache: false
});
},
setupDataTableDefaults: function() {
$.extend($.fn.dataTable.defaults, {
"sDom": "<'table-header-controls'<'row'<l><f>>r><i>t<'table-footer-controls'<'row'<'span12'p><'span12'i>>>",
"sPaginationType": "bootstrap",
"bJQueryUI": false,
"bProcessing": false,
"bServerSide": true,
"fnServerData": interactiveSearch.common.getTableData
});
},
getTableData: function(sSource, aoData, fnCallback) {
var data = new Array();
var columnCount = _.find(aoData, function(o) {
return o.name == 'iColumns';
}).value;
var echo = _.find(aoData, function(o) {
return o.name == 'sEcho';
}).value;
var skip = _.find(aoData, function(o) {
return o.name == 'iDisplayStart';
}).value;
var take = _.find(aoData, function(o) {
return o.name == 'iDisplayLength';
}).value;
var search = _.find(aoData, function(o) {
return o.name == 'sSearch';
}).value;
var sortCols = _.filter(aoData, function(o) {
return o.name.indexOf('iSortCol_') == 0;
});
var sortDirs = _.filter(aoData, function(o) {
return o.name.indexOf('sSortDir_') == 0;
});
var searches = _.filter(aoData, function(o) {
return o.name.indexOf('sSearch_') == 0;
});
data.push({
"name": "TableEcho",
"value": echo
});
data.push({
"name": "Skip",
"value": skip
});
data.push({
"name": "Take",
"value": take
});
data.push({
"name": "AllSearch",
"value": search
});
var actual = 0;
_.each(sortCols, function(columnSort, sortIndex) {
var columnIndex = columnSort.value;
var columnSearch = searches[columnIndex].value;
var sortDir = sortDirs[sortIndex].value;
data.push({
"name": "Columns[" + actual + "].ColumnIndex",
"value": columnIndex
});
data.push({
"name": "Columns[" + actual + "].SortDirection",
"value": sortDir
});
if (columnSearch != '') {
data.push({
"name": "Columns[" + actual + "].SearchTerm",
"value": columnSearch
});
}
actual++;
});
for (var i = 0; i < columnCount; i++) {
var searchTerm = searches[i].value;
if (searchTerm == '') {
continue;
}
data.push({
"name": "Columns[" + actual + "].ColumnIndex",
"value": i
});
data.push({
"name": "Columns[" + actual + "].SearchTerm",
"value": searchTerm
});
actual++;
}
$.post(sSource, data)
.success(fnCallback);
}
};
})();
$(function() {
interactiveSearch.common.init();
});
(function() {
var product = interactiveSearch.product = {};
product.init = function() {
product.initDataTable();
product.bindEvents();
};
function convertFullRowToDataObject(fullRow) {
return {
Id: fullRow[0],
ProductName: fullRow[1],
Synonym: fullRow[2],
Acronym: fullRow[3],
CasNo: fullRow[4],
EinecsNo: fullRow[5],
Formula: fullRow[6],
MolecularWeight: fullRow[7],
Status: fullRow[8],
MeltingPoint: fullRow[9],
BoilingPoint: fullRow[10],
HasDoc: fullRow[11] !== '',
RelatedDocPath: product.baseUrl + fullRow[11],
HasDImage: fullRow[12] !== '',
ImagePath: product.baseUrl + fullRow[12]
};
}
product.initDataTable = function() {
product.productTable = $("#product-table").dataTable({
aaSorting: [
[1, "asc"]
],
iDisplayLength: 15,
bServerSide: true,
bDestroy: true,
sAjaxSource: interactiveSearch.product.listUrl,
fnRowCallback: function(nRow, aData) {
$(nRow).data('rowInfo', convertFullRowToDataObject(aData));
},
aoColumns: [{
sType: "string",
sClass: "dtAlignLeft",
mData: 1
}]
});
};
product.bindEvents = function() {
_.templateSettings = {
interpolate: /\{\{(.+?)\}\}/g,
evaluate: /\{\[([\s\S]+?)\]\}/g
};
var templateText = $('#productDetailTemplate').html(),
compiledTemplate = _.template(templateText);
$(document).on('click', '#product-table tr', function(e) {
var el = $(this);
var rowData = el.data('rowInfo');
var html = compiledTemplate(rowData);
$('#productDetailContainer').empty().html(html);
$('#product-table tr').removeClass('active');
el.addClass('active');
});
$('#searchClone').on('keyup', function(e) {
var el = $(this);
var mimicEl = $('#product-table_filter input');
mimicEl.val(el.val()).trigger('keyup');
})
$('.btn-reset-filter').on('click', function() {
$('#searchClone').val('').trigger('keyup');
});
};
})();
$(document).ready(function() {
interactiveSearch.product.listUrl = '/pa/Product/ListItems';
interactiveSearch.product.baseUrl = '/pa/';
interactiveSearch.product.init();
});
</script>
In .js files you don't have to put <script>, you can just write your code.
<script> is for HTML files when you have to insert a script in the middle of the page.
So you have to delete <script> and </script> in your file.
Related
I'm looking for some help with syncing 3 line charts similar to this: http://jsfiddle.net/v2t171og/
Here is my code:
https://codepen.io/anon/pen/EerNyO
(function() {
var files = ["https://code.highcharts.com/stock/highstock.js", "https://code.highcharts.com/highcharts-more.js", "https://code.highcharts.com/highcharts-3d.js", "https://code.highcharts.com/modules/data.js", "https://code.highcharts.com/modules/exporting.js", "https://code.highcharts.com/modules/funnel.js", "https://code.highcharts.com/modules/annotations.js", "https://code.highcharts.com/modules/solid-gauge.js"],
loaded = 0;
if (typeof window["HighchartsEditor"] === "undefined") {
window.HighchartsEditor = {
ondone: [cl],
hasWrapped: false,
hasLoaded: false
};
include(files[0]);
} else {
if (window.HighchartsEditor.hasLoaded) {
cl();
} else {
window.HighchartsEditor.ondone.push(cl);
}
}
function isScriptAlreadyIncluded(src) {
var scripts = document.getElementsByTagName("script");
for (var i = 0; i < scripts.length; i++) {
if (scripts[i].hasAttribute("src")) {
if ((scripts[i].getAttribute("src") || "").indexOf(src) >= 0 || (scripts[i].getAttribute("src") === "http://code.highcharts.com/highcharts.js" && src === "https://code.highcharts.com/stock/highstock.js")) {
return true;
}
}
}
return false;
}
function check() {
if (loaded === files.length) {
for (var i = 0; i < window.HighchartsEditor.ondone.length; i++) {
try {
window.HighchartsEditor.ondone[i]();
} catch (e) {
console.error(e);
}
}
window.HighchartsEditor.hasLoaded = true;
}
}
function include(script) {
function next() {
++loaded;
if (loaded < files.length) {
include(files[loaded]);
}
check();
}
if (isScriptAlreadyIncluded(script)) {
return next();
}
var sc = document.createElement("script");
sc.src = script;
sc.type = "text/javascript";
sc.onload = function() {
next();
};
document.head.appendChild(sc);
}
function each(a, fn) {
if (typeof a.forEach !== "undefined") {
a.forEach(fn);
} else {
for (var i = 0; i < a.length; i++) {
if (fn) {
fn(a[i]);
}
}
}
}
var inc = {},
incl = [];
each(document.querySelectorAll("script"), function(t) {
inc[t.src.substr(0, t.src.indexOf("?"))] = 1;
});
function cl() {
if (typeof window["Highcharts"] !== "undefined") {
var options = {
"chart": {
"type": "line",
"height": 220,
"polar": false
},
"rangeSelector": {
"enabled": false
},
"title": {
"text": ""
},
"scrollbar": {
"enabled": false
},
"subtitle": {
"text": ""
},
"series": [{
"name": "RMS",
"_colorIndex": 0,
"_symbolIndex": 0,
"turboThreshold": 0,
"marker": {}
}, {
"name": "Minimum",
"_colorIndex": 1,
"_symbolIndex": 1
}, {
"name": "Maximum",
"_colorIndex": 2,
"_symbolIndex": 2
}, {
"name": "Threshold",
"_colorIndex": 3,
"_symbolIndex": 3
}],
"data": {
"csv": "\"Movement\";\"RMS\";\"Minimum\";\"Maximum\";\"Threshold\"\n1;12.87;12;15;14\n2;13.16;12;15;14\n3;12.92;12;15;14\n4;13.14;12;15;14\n5;12.88;12;15;14\n6;13.03;12;15;14\n7;12.76;12;15;14\n8;13.04;12;15;14\n9;12.72;12;15;14\n10;13.2;12;15;14",
"googleSpreadsheetKey": false,
"googleSpreadsheetWorksheet": false
},
"yAxis": [{
"title": {}
}],
"navigator": {
"adaptToUpdatedData": true,
"enabled": false
},
"pane": {
"background": []
},
"responsive": {
"rules": []
},
"plotOptions": {
"series": {
"animation": false
}
}
};
new Highcharts.StockChart("highcharts-aaf432a9-4966-4429-b3eb-d35fe01e2924", options);
}
}
})();
I've created the graphs but I can't connect them using the highcharts events or hairlines.
Any assistance would be appreciated.
First of all, you should look at the console, you have a few error there, related with the location of the scripts. Next, you need to change highlight method to onMouseOver:
$('#container').bind('mousemove touchmove touchstart', function(e) {
var chart,
point,
i,
event;
for (i = 0; i < Highcharts.charts.length; i++) {
chart = Highcharts.charts[i];
event = chart.pointer.normalize(e.originalEvent); // Find coordinates within the chart
point = chart.series[0].searchPoint(event, true); // Get the hovered point
if (point) {
point.onMouseOver(e);
}
}
});
API: https://api.highcharts.com/class-reference/Highcharts.Point#onMouseOver
Live demo: http://jsfiddle.net/BlackLabel/0gmrf64y/
I'm making a chained select dropdown list and I want the values witch are chosen to be exported to my main app, through email or somehow. I'm not sure what is the best solution. Here is the code example
<script src="http://code.jquery.com/jquery-latest.min.js"></script>
<script src="jquery.chained.js"></script>
<script type="text/javascript"></script>
<select id="year" name="year">
<option value= "">Step 1 - Select Year</option>
<option value="1990">1990</option>
<option value="1991">1991</option>
<option value="1992">1992</option>
</select>
<select id="model" name="model">
<option value="">Step 2 - Select Model</option>
<option value="80" class="1990 1991 1992">80</option>
</select>
<select id="engine" name="engine">
<option value="">Step 3 - Select Engine</option>
<option value="v10" class="80">v10</option>
</select>
<input id="button1" type="button" value="send!" />
<script src="jquery.chained.js" type="text/javascript"></script>
<script type="text/javascript">
$("#model").chained("#year")
$("#engine").chained("#model")
$(document).ready(function (){
$('#button1').click(function (){
alert($(':selected').text());
</script>
The alert is showing the selected options, but i need to export that text somehow so i can send it like a newsletter to my app.
If anyone can tell me what is the best way to do that i will be grateful and sorry if i didn't explain it good or if you can't understand what i mean.
Try this,
(function($) {
$.fn.cDropdown = function(x) {
return this.each(function() {
var wrapper = $(this);
var xx = $.extend({
obj: "",
}, x || {});
var lastCreated;
function initialized() {
var returnedData
$.grep(xx.obj, function(element, index) {
$.each(element, function(e, i) {
if (hasValue(i, "Primary", true)) {
returnedData = hasValue(i, "Primary", true);
return false;
}
})
});
initFirst(returnedData);
creator(xx.obj, returnedData)
clicker(returnedData);
runOrder(returnedData["Id"]);
}
function clicker(obj) {
var selector = obj["Id"] != null ? "#" + obj["Id"] : obj["Name"] != null ? "[Name=\"" + obj["Name"] + "\"]" : ""
$('body').on('change', selector, function() {
var se = $(selector).find('option[value="CPreQVa"]');
if (se.val() != $(this).find('option:selected').val()) {
var target = $(this).attr("class").split("cTrig_")[1];
var v = $(this).find('option:selected').val();
var d;
if ($('#' + target).is('[class*="cTrig_"]')) {
hideFollow($('#' + target))
}
$.each(xx.obj[0], function(i, o) {
if (hasValue(o, "Id", target) != null) {
d = hasValue(o, "Id", target);
return false;
}
});
$('#' + target).find('option').remove();
if (d != null) {
$.each(d["option"], function(i, o) {
var ot = "" + o["trigger"];
if (ot.indexOf(",") != -1) {
var arrot = ot.split(',');
$.each(arrot, function(ii, oo) {
if (v == oo || o["preSelect"] == true) {
$('#' + target).append($("<option></option>")
.attr("value", o["val"])
.text(o["text"]));
return false;
}
})
} else {
if (v == o["trigger"] || o["preSelect"] == true) {
$('#' + target).append($("<option></option>")
.attr("value", o["val"])
.text(o["text"]));
}
}
})
if (d["Sort"] != null && d["Sort"] === true) {
var options = $('#' + target).find("option");
var arr = options.map(function(_, o) {
return {
t: $(o).text(),
v: o.value
};
}).get();
arr.sort(function(o1, o2) {
return o1.t > o2.t ? 1 : o1.t < o2.t ? -1 : 0;
});
options.each(function(i, o) {
o.value = arr[i].v;
$(o).text(arr[i].t);
});
}
var t;
$.each(d["option"], function(i, o) {
t = hasValue(o, "preSelect", true)
return false;
})
if (t != null) {
$('#' + target).find('option[value="CPreQVa"]').prependTo($('#' + target)).attr("selected", true)
}
$('#' + target).show();
var q;
$.each(xx.obj[0], function(i, o) {
if (hasValue(o, "Id", obj["Child"])) {
q = hasValue(o, "Id", obj["Child"]);
return false;
}
})
if (q != null) {
if (q["Child"] != null) {
clicker(q);
}
}
}
} else {
var target = $(this).attr("class").split("cTrig_")[1]
if ($('#' + target).is('[class*="cTrig_"]')) {
hideFollow($('#' + target))
}
$('#' + target).hide();
}
})
};
function hideFollow(obj) {
var target = $(obj).attr("class").split("cTrig_")[1]
if ($('#' + target).is('[class*="cTrig_"]')) {
hideFollow($('#' + target))
}
$('#' + target).hide();
};
function initFirst(obj) {
if (obj["Id"] != null)
wrapper.attr("Id", obj["Id"])
if (obj["Name"] != null)
wrapper.attr("Name", obj["Name"])
if (obj["Class"] != null)
wrapper.addClass(obj["Class"] + " cTrig_" + obj["Child"])
$.each(obj["option"], function(e, i) {
wrapper.append($("<option></option>")
.attr("value", i["val"])
.text(i["text"]));
})
if (obj["Required"] != null)
wrapper.prop('required', true);
if (obj["Sort"] != null && obj["Sort"] === true) {
var options = wrapper.find("option");
var arr = options.map(function(_, o) {
return {
t: $(o).text(),
v: o.value
};
}).get();
arr.sort(function(o1, o2) {
return o1.t > o2.t ? 1 : o1.t < o2.t ? -1 : 0;
});
options.each(function(i, o) {
o.value = arr[i].v;
$(o).text(arr[i].t);
});
}
var t;
$.each(obj["option"], function(i, o) {
t = hasValue(o, "preSelect", true)
return false;
})
if (t != null) {
//$('#MyNiceList option[value="my_option_2"]').insertBefore('#MyNiceList option[value="my_option_1"]');
wrapper.find('option[value="CPreQVa"]').prependTo(wrapper).attr("selected", true)
}
};
function hasValue(o, key, value) {
if (o.hasOwnProperty(key) && o[key] === value)
return o;
};
function creator(ob, fo) {
$.each(ob[0], function(i, o) {
if (o["Id"] != fo["Id"]) {
var sel = $('<select>')
if (o["Id"] != null)
sel.attr("Id", o["Id"])
if (o["Name"] != null)
sel.attr("Name", o["Name"])
if (o["Class"] != null)
sel.addClass(o["Class"])
if (o["Required"] != null)
sel.prop('required', true);
if (o["Child"] != null)
sel.addClass("cTrig_" + o["Child"])
//if (lastCreated == null) {
// sel.hide().insertAfter(wrapper)
// lastCreated = "#" + o["Id"];
//} else {
// sel.hide().insertAfter($(lastCreated))
//}
sel.hide()
wrapper.after(sel)
}
})
};
function runOrder(id) {
var obj;
if ($('#' + id).is('[class*="cTrig_"]')) {
obj = $('#' + id).attr("class").split("cTrig_")[1]
$('#' + id).after($('#' + obj))
runOrder(obj);
}
};
initialized();
});
};
}(jQuery));
$('#cDropdown').cDropdown({
obj: [{
"year": {
"Id": "year",
"Name": "year",
"Primary": true,
"Class": "form-control",
"Child": "Model",
"Sort": true,
"Required": true,
"option": [{
"val": "CPreQVa",
"text": "Step 1 - Select Year",
"preSelect": true
}, {
"val": "1990",
"text": "1990"
}, {
"val": "1991",
"text": "1991"
}, {
"val": "1992",
"text": "1992"
}]
},
"Model": {
"Id": "Model",
"Name": "Model",
"Class": "form-control",
"Child": "Engine",
"Sort": true,
"option": [{
"val": "CPreQVa",
"text": "Step 2 - select Model",
"preSelect": true
}, {
"val": "80",
"text": "80",
"trigger": "1990"
}, {
"val": "80",
"text": "80",
"trigger": "1991"
}, {
"val": "80",
"text": "80",
"trigger": "1992"
}]
},
"Engine": {
"Id": "Engine",
"Name": "Engine",
"Class": "form-control",
"Sort": true,
"option": [{
"val": "CPreQVa",
"text": "Step 3 - Select Engine",
"preSelect": true
}, {
"val": "v10",
"text": "v10",
"trigger": "80"
}]
}
}]
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select id="cDropdown"></select>
[{
"name":"John"
"age":19,
"hobby":"Basketball;play computer"
},
{
"name":"Anderson"
"age":19,
"hobby":"Tennis"
}
]
John have 2 hobbies, it suppose to be in array but I have no control of the source of the api. How can I make the json to be below format?
[{
"name":"John"
"age":19,
"hobby":"Basketball"
},{
"name":"John"
"age":19,
"hobby":"play computer"
},
{
"name":"Anderson"
"age":19,
"hobby":"Tennis"
}
]
I'm new to jquery so here's code I've tried :
var hobbies = "";
$.each(json, function(){
hobbies = this.hobby.split(',');
});
var data = [{
"name": "John",
"age": 19,
"hobby": "Basketball;play computer"
}, {
"name": "Anderson",
"age": 19,
"hobby": "Tennis"
}]
$.each(data, function (index, value) {
if (value.hobby.split(';').length > 1) {
var dataArray = value.hobby.split(';');
value.hobby = dataArray[0];
dataArray.shift();
$.each(dataArray, function (innerIndex, innerValue) {
data.push({
"name": value.name,
"age": value.age,
"hobby": innerValue
});
});
}
});
console.log(data);
Fiddle Demo
var arr = [{
"name":"John",
"age":19,
"hobby":"Basketball;play computer"
},
{
"name":"Anderson",
"age":19,
"hobby":"Tennis"
}
];
$.each(arr, function(i,j){
var temp = j.hobby;
var hobby_arr = temp.split(';');
j.hobby = hobby_arr;
});
Try this. However there is an error in your provided json. There should be a ',' after the 'name' value
Here is a fiddle of your working thing ( assuming that ";" is the separator )
http://jsfiddle.net/swaprks/vcpq8dtr/
var json = [{
"name":"John",
"age":19,
"hobby":"Basketball;play computer"
},
{
"name":"Anderson",
"age":19,
"hobby":"Tennis"
}
];
$(function(){
for ( var i = 0; i < json.length; i++ ) {
var obj = json[i];
if ( obj["hobby"].indexOf(";") != -1 ){
var hobbyArr = obj["hobby"].split(";");
for ( var j = 0; j < hobbyArr.length; j++ ){
var newObj = {};
if ( j == 0 ){
json[i]["hobby"] = hobbyArr[j];
} else {
newObj = {
"name": obj["name"],
"age": obj["age"],
"hobby": hobbyArr[j]
}
json.push(newObj);
}
}
}
}
console.log(json)
});
I have an issue about checking for an existing product in knockoutjs.
The problem is: if the product exists in Cart Line, the product quantity will increase, if not, it will be added to Cart
This is code:
var CartLine = function (productid,productName, price, quantity) {
var self = this;
self.resultId = ko.observable(productid);
self.resultProduct = ko.observable(productName);
self.resultPrice = ko.observable(price);
self.resultQuantity = ko.observable(quantity || 1);
self.subtotal = ko.computed(function () {
return self.resultPrice() * self.resultQuantity();
});
};
$('#addProduct').click(function (line) {
var context = ko.contextFor(this);
var existing = self.find(line.resultId);
var lines = self.lines();
if (existing) {
existing.resultQuantity = existing.resultQuantity() + context.$data.Quantity();
}else{
existing = new CartLine(self.product().productid, self.product().name, self.product().price, context.$data.Quantity());
self.lines.push(existing);
}
return existing;
});
self.find = function (productid) {
return ko.utils.arrayFirst(self.lines(), function (line) {
return line.resultId === productid;
});
};
This is the full code: http://jsfiddle.net/pf9hd3Lg/2/
There are a number of errors with the code you have listed above. The below should work for the scenario you described. I have tried to comment my changes in the code below.
var CartLine = function (productid,productName, price, quantity) {
var self = this;
self.resultId = ko.observable(productid);
self.resultProduct = ko.observable(productName);
self.resultPrice = ko.observable(price);
self.resultQuantity = ko.observable(quantity || 1);
self.subtotal = ko.computed(function () {
return self.resultPrice() * self.resultQuantity();
});
};
var Cart = function() {
var self = this;
self.products = ko.observableArray([{
"productid": "1",
"name": "CAPUCINO ",
"price": 170
},
{
"productid": "2",
"name": "Sữa bò tươi",
"price": 140
}
,
{
"productid": "3",
"name": "Phô mai mặn",
"price": 170
}, {
"productid": "4",
"name": "Bơ đậu phộng ",
"price": 150
},
{
"productid": "5",
"name": "Bạc Hà",
"price": 160
},
{
"productid": "6",
"name": "Dâu Tây",
"price": 160
}
]);
self.product = ko.observable("");
self.Quantity = ko.observable(1).extend({ numeric: 0 });
self.price = ko.observable();
self.productid = ko.observable("");
self.lines = ko.observableArray();
self.grandTotal = ko.pureComputed(function () {
var total = 0;
$(self.lines()).each(function (index, line) { total += line.subtotal() })
return total;
});
$('#addProduct').click(function (line) {
var context = ko.contextFor(this);
var existing = self.find();
var lines = self.lines();
if (existing) {
//existing.resultQuantity is also an observable and should be set this way and not with the = operator
existing.resultQuantity(existing.resultQuantity() + context.$data.Quantity());
}else{
existing = new CartLine(self.product().productid, self.product().name, self.product().price, context.$data.Quantity());
self.lines.push(existing);
}
return existing;
});
self.removeProduct = function (line,event) {
self.lines.remove(line);
};
self.find = function () {
return ko.utils.arrayFirst(self.lines(), function (line) {
//resultId is an observable
//self.product().productid is what you are interested in, no need to pass it into the function
return line.resultId() === self.product().productid;
});
};
}
ko.applyBindings(new Cart());
I'm making an application and I have to display data in a chart. I also only want the last 5 transactions entered to display.
I'm using Backbone.js and Chart.js. In my prototype displaying data was no problem because I just bootstrapped the data. But now that I'm trying to pull the data from my Backbone Collection it's not working. I only get a transparent image
// Model
(function (exports) {
var Transaction = Backbone.Model.extend({
defaults: {
amount: 0,
transactionDate: "",
transactionType: "debit",
category: "miscellaneous",
description: ""
},
categories: [
"salary",
"rent",
"miscellaneous"
],
transactionTypes: [
"credit",
"debit"
],
initialize: function() {
this.set({transactionDate: this.attributes.transactionDate || Date.now()}, {validate: true});
},
validate: function(attrs, options) {
if (attrs['transactionType'] !== undefined &&
!_.contains(this.transactionTypes, attrs['transactionType'].toLowerCase())) {
return 'Invalid type: ' + attrs['transactionType'];
} else if (attrs['category'] !== undefined &&
!_.contains(this.categories, attrs['category'].toLowerCase())) {
return 'Invalid category: ' + attrs['category'];
} else if (attrs['transactionDate'] !== undefined &&
_.isNaN(parseInt(attrs['transactionDate'])) || attrs['transactionDate'] < 0) {
return 'Invalid date: '+ attrs['transactionDate'];
} else if (attrs['amount'] !== undefined &&
_.isNaN(parseInt(attrs['amount'])) || attrs['amount'] < 0) {
return 'Invalid amount: '+ attrs['amount'];
}
return null;
}
});
// export for global use
exports.expensus.Models.Transaction = Transaction;
}(this));
This is the collection I'm using ..
;(function (exports) {
var Transactions = Backbone.Collection.extend({
// stuff and thangs
model: expensus.Models.Transaction,
localStorage: new Backbone.LocalStorage('TransactionsCollection'),
latestFive: function(toJSON) {
this.sortByDate(-1); // sort latest first
if (!toJSON) {
return _.first(this.models, 5);
} else {
var models = _.first(this.models, 5),
idx = -1,
json = [],
model;
while (model = models[++idx]) {
json.push(model.attributes);
}
return json;
}
},
sortByDate: function(dir) {
dir = dir || -1;
this.comparator = function(transaction) {
return dir * transaction.get("transactionDate");
};
this.sort();
},
sortByAmount: function(dir) {
dir = dir || -1;
this.comparator = function(transaction) {
return dir * transaction.get("amount");
};
this.sort();
}
});
exports.expensus.Collections.Transactions = Transactions;
}(this));
And this is the Chart View, I get no errors in dev tools so I'm really at a loss ...
;(function (exports){
var ChartView = Backbone.View.extend({
el: ".home-page",
template: Handlebars.compile($("#chart-template").html()),
chart: null,
initialize: function () {
this.listenTo(this.collection, "add", this.render);
this.listenTo(this.collection, "change", this.render);
this.$(".chart-view-div").html(this.template());
this.chart = new Chart($("#expense-chart")[0].getContext("2d"));
this.render();
},
render: function() {
var self = this;
var data = this.chartData();
self.chart.Doughnut(data, {
responsive: true,
animateScale: true
});
},
chartData: function() {
var collection = this.collection.latestFive(true);
var data = {
vals: [],
labels: [],
allData: []
};
var getData = function(color, highlight, labels, vals, collection) {
var object = {
color: color,
highlight: highlight,
chartData: [
{
value: "",
label: ""
}
]
};
for (var i = 0; i < labels.length; i++ ) {
object.chartData.push(0);
}
for (var j = 0; j < vals.length; j++ ) {
object.chartData.push(0);
}
for (var i = 0; i < collection.length; i++ ) {
var item = collection[i];
var label = labels.indexOf(item.category);
var val = vals.indexOf(item.amount);
object.chartData[ { value: val, label: label } ]++;
}
return object;
};
function getRandomColor() {
var letters = '0123456789ABCDEF'.split('');
var color = '#';
for (var i = 0; i < 6; i++ ) {
color += letters[Math.floor(Math.random() * 16)];
}
return color;
}
for (var i = 0; i < collection.length; i++ ) {
var object = collection[i];
var color = getRandomColor();
var highlight = getRandomColor();
data.labels.push(object.category);
data.vals.push(object.amount);
data.allData.push(getData(color, highlight, data.labels, data.vals, collection));
}
return data;
}
});
exports.expensus.Views.ChartView = ChartView;
}(this));
My Add Transaction View
;(function (exports) {
var AddTransactionView = Backbone.View.extend({
el: "#add-transaction-page",
events: {
"submit .add-transaction-form": "addTransaction"
},
initialize: function() {
this.form = this.$(".add-transaction-form")[0];
},
addTransaction: function(evt) {
if (evt) {
evt.preventDefault();
}
var m = new expensus.Models.Transaction({
transactionDate: Date.now(),
transactionType: this.form["trans-type"].value,
amount: this.form["trans-amount"].value,
description: this.form["trans-description"].value,
category: this.form["trans-category"].value
});
if(m.validationError === null) {
this.collection.add(m);
m.save();
$(this.el).modal("hide");
this.form.reset();
} else {
alert("Model is invalid: " + m.validationError);
}
}
});
exports.expensus.Views.AddTransactionView = AddTransactionView;
}(this));
This is as far as I could get. I've done this before with a different kind of chart but can't for the life of me figure it out with the Doughnut chart.
Thanks, everyone
The main thing i can see is that you pass the chart data which is not in the format that chartjs expects, so it should be an array of objects which have the properties value label and color but you are passing it something different. so a quick fix for that would be to construct an array as described
// Model
var Transaction = Backbone.Model.extend({
defaults: {
amount: 0,
transactionDate: "",
transactionType: "debit",
category: "miscellaneous",
description: ""
},
categories: [
"salary",
"rent",
"miscellaneous"
],
transactionTypes: [
"credit",
"debit"
],
initialize: function() {
this.set({
transactionDate: this.attributes.transactionDate || Date.now()
}, {
validate: true
});
},
validate: function(attrs, options) {
if (attrs['transactionType'] !== undefined && !_.contains(this.transactionTypes, attrs['transactionType'].toLowerCase())) {
return 'Invalid type: ' + attrs['transactionType'];
} else if (attrs['category'] !== undefined && !_.contains(this.categories, attrs['category'].toLowerCase())) {
return 'Invalid category: ' + attrs['category'];
} else if (attrs['transactionDate'] !== undefined && _.isNaN(parseInt(attrs['transactionDate'])) || attrs['transactionDate'] < 0) {
return 'Invalid date: ' + attrs['transactionDate'];
} else if (attrs['amount'] !== undefined && _.isNaN(parseInt(attrs['amount'])) || attrs['amount'] < 0) {
return 'Invalid amount: ' + attrs['amount'];
}
return null;
}
});
var Transactions = Backbone.Collection.extend({
// stuff and thangs
model: Transaction,
latestFive: function(toJSON) {
this.sortByDate(-1); // sort latest first
if (!toJSON) {
return _.first(this.models, 5);
} else {
var models = _.first(this.models, 5),
idx = -1,
json = [],
model;
while (model = models[++idx]) {
json.push(model.attributes);
}
return json;
}
},
sortByDate: function(dir) {
dir = dir || -1;
this.comparator = function(transaction) {
return dir * transaction.get("transactionDate");
};
this.sort();
},
sortByAmount: function(dir) {
dir = dir || -1;
this.comparator = function(transaction) {
return dir * transaction.get("amount");
};
this.sort();
}
});
var ChartView = Backbone.View.extend({
el: ".home-page",
template: Handlebars.compile($("#chart-template").html()),
chart: null,
initialize: function() {
this.listenTo(this.collection, "add", this.render);
this.listenTo(this.collection, "change", this.render);
this.$(".chart-view-div").html(this.template());
this.chart = new Chart(this.$("#expense-chart")[0].getContext("2d"));
this.render();
},
render: function() {
var self = this;
var data = this.chartData();
this.chart.Doughnut(data, {
responsive: true,
animateScale: true
});
},
chartData: function() {
var collection = this.collection.latestFive(true);
var data = [];;
var getData = function(color, highlight, labels, vals, collection) {
var object = {
color: color,
highlight: highlight,
chartData: [{
value: "",
label: ""
}]
};
for (var i = 0; i < labels.length; i++) {
object.chartData.push(0);
}
for (var j = 0; j < vals.length; j++) {
object.chartData.push(0);
}
for (var i = 0; i < collection.length; i++) {
var item = collection[i];
var label = labels.indexOf(item.category);
var val = vals.indexOf(item.amount);
object.chartData[{
value: val,
label: label
}] ++;
}
return object;
};
function getRandomColor() {
var letters = '0123456789ABCDEF'.split('');
var color = '#';
for (var i = 0; i < 6; i++) {
color += letters[Math.floor(Math.random() * 16)];
}
return color;
}
for (var i = 0; i < collection.length; i++) {
var object = collection[i];
var color = getRandomColor();
var highlight = getRandomColor();
data.push({
value: object.amount,
color: color,
label: object.category
});
}
return data;
}
});
var collection = new Transactions([{
amount: 12,
transactionDate: 1417442176000,
transactionType: "debit",
category: "miscellaneous",
description: ""
}, {
amount: 13,
transactionDate: 1417442176000,
transactionType: "credit",
category: "salary",
description: ""
}]);
var view = new ChartView({
collection: collection
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.7.0/underscore-min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/handlebars.js/2.0.0/handlebars.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.1.2/backbone.js"></script>
<script src="http://www.chartjs.org/assets/Chart.min.js"></script>
<script id="chart-template" type="text/x-handlebars-template">
<canvas id="expense-chart"></canvas>
</script>
<div class="home-page">
<div class="chart-view-div"></div>
</div>