Custom Parameters get cleared canvas to Json - json

I am adding svg to canvas and want to set custom Element Parameters. I shows custom parameter when we console log getActiveObject() but when we use canvas.toJSON() Element Parameter node values does not change.
var canvas = new fabric.Canvas('designcontainer'),
/* Save additional attributes in Serialization */
var ElementParameters = {
ElementType:'',
imageType:'',
top:'',
left:'',
colors:'',
isBaseTier:'',
atLevel:''
};
fabric.Object.prototype.toObject = (function (toObject) {
return function () {
return fabric.util.object.extend(toObject.call(this), {
ElementParameters:{
ElementType:'',
imageType:'',
top:'',
left:'',
colors:'',
isBaseTier:'',
atLevel:''
},
});
};
})(fabric.Object.prototype.toObject);
/* End : Save additional attributes in Serialization */
var Designer = {
addElement: function(e,p){ /* e = element, image src | p = parameters set for image */
if(p.imageType == "svg"){
if(p.ElementType == "caketier"){
var group = [];
console.log('Before ');
console.log(ElementParameters);
$.extend(ElementParameters,p);
console.log('After ');
console.log(ElementParameters);
fabric.loadSVGFromURL(e,function(objects,options){
var shape = fabric.util.groupSVGElements(objects,options);
var bound = shape.getBoundingRect();
shape.set({
left: p.left,
top: p.top,
width:bound.width+2,
height:bound.height,
angle:0,
centeredScaling:true,
ElementParameters:ElementParameters
});
if(shape.paths && baseColor.length > 0){
for(var i = 0;i<shape.paths.length;i++) shape.paths[i].setFill(baseColor[i]);
}
canvas.add(shape);
shape.setControlsVisibility(HideControls);
canvas.renderAll();
},function(item, object) {
object.set('id',item.getAttribute('id'));
group.push(object);
});
}
}
}
}
$(".tierbox").on('click',function(){
var i = $(this).find('img'),
src = i.attr('src'),
param = i.data('parameters');
Designer.addElement(src,param);
});
Now when I call JSON.stringify(json), Element Parameter node does not get overwrite with values set in shape.set() method.

Replace fabric.Object.prototype.toObject = (function (toObject) { ... } to
fabric.Object.prototype.toObject = (function (toObject) {
return function () {
return fabric.util.object.extend(toObject.call(this), {
ElementParameters:this.ElementParameters
});
};
})(fabric.Object.prototype.toObject);

Related

kendoGrid and multiselectbox column initialization using query string parameters

I am implementing a custom solution that will initialize kendoGrid (and its multiselect columns) by applying filters to the grid using query string parameters. I am using Kendo UI v2014.2.903 and multiselectbox user extension.
To achieve this, I have a custom JavaScript function that parses query string parameters into filter object and applies it to kendoGrid's dataSource property using its filter method. Code snippet below:
var preFilterQueryString = getPreFilterQuery(queryString);
if (preFilterQueryString != '') {
kendoGrid.dataSource.filter(parseFilterString(preFilterQueryString));
}
I am initializing multiselectbox as follows:
args.element.kendoMultiSelectBox({
dataSource: getAutoCompleteDataSource(column.field),
valuePrimitive: true,
selectionChanged: function (e) {
//ignored for brevity
}
});
My problem is if I set filters to multiselectbox using above approach, they are not applied correctly to the data set.
For example, if I pass single filter as "Vancouver", correct result set is displayed. Choices in the multiselectbox are "All" and "Vancouver". However, Vancouver choice is not checked in the multiselectbox. Is that by design? Please see image below.
single filter image
If I pass in two filters Vancouver and Warsaw, only the last filter Warsaw is applied to the grid and data set containing only Warsaw is displayed. Again, none of the choices are checked in the multiselectbox.
two filters image
Below is the filter object that is applied to dataSource.filter() method.
kendoGrid's filter object image
Troubleshooting
Below is condensed version (for brevity) of selectionchanged event handler of a multiselectbox column.
if (e.newValue && e.newValue.length) {
var newValue = e.newValue;
console.log('e.newValue: ' + e.newValue);
filter.filters = [];
for (var i = 0, l = newValue.length; i < l; i++) {
filter.filters.push({field: field,operator: 'contains',value: newValue[i]});
}
kendoGrid.dataSource.filter(allFilters);
}
I noticed that when two filters are passed, e.newValue is "Warsaw" instead of an array - "[Vancouver, Warsaw]"
I spent lot of time troubleshooting why only Warsaw is applied to the data set.
Here's what I found out:
_raiseSelectionChanged function is what raises selection changed event. In that function, I noticed that it sets newValue and oldValue event arguments. To set newValue it uses "Value" function. Value function uses the below code to retrieve all the selected list items and return them.
else {
var selecteditems = this._getSelectedListItems();
return $.map(selecteditems, function (item) {
var obj = $(item).children("span").first();
return obj.attr("data-value");
}).join();
}
_getSelectedListItems function uses jQuery filter to fetch all list items that have css class ".selected"
_getSelectedListItems: function () {
return this._getAllValueListItems().filter("." + SELECTED);
},
There's a _select event which seems to be adding ".selected" class to list items. When I put a breakpoint on line 286, it is hitting it only once and that is for Warsaw. I am unable to understand why it is not getting called for Vancouver. I am out of clues and was wondering if anyone has pointers.
debug capture of _select function
Below is kendoMultiSelectBox user extension for your reference:
//MultiSelect - A user extension of KendoUI DropDownList widget.
(function ($) {
// shorten references to variables
var kendo = window.kendo,
ui = kendo.ui,
DropDownList = ui.DropDownList,
keys = kendo.keys,
SELECT = "select",
SELECTIONCHANGED = "selectionChanged",
SELECTED = "k-state-selected",
HIGHLIGHTED = "k-state-active",
CHECKBOX = "custom-multiselect-check-item",
SELECTALLITEM = "custom-multiselect-selectAll-item",
MULTISELECTPOPUP = "custom-multiselect-popup",
EMPTYSELECTION = "custom-multiselect-summary-empty";
var lineTemplate = '<input type="checkbox" name="#= {1} #" value="#= {0} #" class="' + CHECKBOX + '" />' +
'<span data-value="#= {0} #">#= {1} #</span>';
var MultiSelectBox = DropDownList.extend({
init: function (element, options) {
options.template = kendo.template(kendo.format(lineTemplate, options.dataValueField || 'data', options.dataTextField || 'data'));
// base call to widget initialization
DropDownList.fn.init.call(this, element, options);
var button = $('<input type="button" value="OK" style="float: right; padding: 3px; margin: 5px; cursor: pointer;" />');
button.on('click', $.proxy(this.close, this));
var popup = $(this.popup.element);
popup.append(button);
},
options: {
name: "MultiSelectBox",
index: -1,
showSelectAll: true,
preSummaryCount: 1, // number of items to show before summarising
emptySelectionLabel: '', // what to show when no items are selected
selectionChanged: null // provide callback to invoke when selection has changed
},
events: [
SELECTIONCHANGED
],
refresh: function () {
// base call
DropDownList.fn.refresh.call(this);
this._updateSummary();
$(this.popup.element).addClass(MULTISELECTPOPUP);
},
current: function (candidate) {
return this._current;
},
open: function () {
var self = this;
this._removeSelectAllItem();
this._addSelectAllItem();
if ($(this.ul).find('li').length > 6) {
$(this.popup.element).css({ 'padding-bottom': '30px' });
}
else {
$(this.popup.element).css({ 'padding-bottom': '0' });
}
DropDownList.fn.open.call(this);
//hook on to popup event because dropdown close does not
//fire consistently when user clicks on some other elements
//like a dataviz chart graphic
this.popup.one('close', $.proxy(this._onPopupClosed, this));
},
_onPopupClosed: function () {
this._removeSelectAllItem();
this._current = null;
this._raiseSelectionChanged();
},
_raiseSelectionChanged: function () {
var currentValue = this.value();
var currentValues = $.map((currentValue.length > 0 ? currentValue.split(",") : []).sort(), function (item) { return item.toString(); });
var oldValues = $.map((this._oldValue || []).sort(), function (item) { return item ? item.toString() : ''; });
// store for next pass
this._oldValue = $.map(currentValues, function (item) { return item.toString(); });
var changedArgs = { newValue: currentValues, oldValue: oldValues };
if (oldValues) {
var hasChanged = ($(oldValues).not(currentValues).length == 0 && $(currentValues).not(oldValues).length == 0) !== true;
if (hasChanged) {
//if (this.options.selectionChanged)
// this.options.selectionChanged(changedArgs);
this.trigger(SELECTIONCHANGED, changedArgs);
}
}
else if (currentValue.length > 0) {
//if (this.options.selectionChanged)
// this.options.selectionChanged(changedArgs);
this.trigger(SELECTIONCHANGED, changedArgs);
}
},
_addSelectAllItem: function () {
if (!this.options.showSelectAll) return;
var firstListItem = this.ul.children('li:first');
if (firstListItem.length > 0) {
this.selectAllListItem = $('<li tabindex="-1" role="option" unselectable="on" class="k-item ' + SELECTALLITEM + '"></li>').insertBefore(firstListItem);
// fake a data object to use for the template binding below
var selectAllData = {};
selectAllData[this.options.dataValueField || 'data'] = '*';
selectAllData[this.options.dataTextField || 'data'] = 'All';
this.selectAllListItem.html(this.options.template(selectAllData));
this._updateSelectAllItem();
this._makeUnselectable(); // required for IE8
}
},
_removeSelectAllItem: function () {
if (this.selectAllListItem) {
this.selectAllListItem.remove();
}
this.selectAllListItem = null;
},
_focus: function (li) {
if (this.popup.visible() && li && this.trigger(SELECT, { item: li })) {
this.close();
return;
}
this.select(li);
},
_keydown: function (e) {
// currently ignore Home and End keys
// can be added later
if (e.keyCode == kendo.keys.HOME ||
e.keyCode == kendo.keys.END) {
e.preventDefault();
return;
}
DropDownList.fn._keydown.call(this, e);
},
_keypress: function (e) {
// disable existing function
},
_move: function (e) {
var that = this,
key = e.keyCode,
ul = that.ul[0],
down = key === keys.DOWN,
pressed;
if (key === keys.UP || down) {
if (down) {
if (!that.popup.visible()) {
that.toggle(down);
}
if (!that._current) {
that._current = ul.firstChild;
} else {
that._current = ($(that._current)[0].nextSibling || that._current);
}
} else {
//up
// only if anything is highlighted
if (that._current) {
that._current = ($(that._current)[0].previousSibling || ul.firstChild);
}
}
if (that._current) {
that._scroll(that._current);
}
that._highlightCurrent();
e.preventDefault();
pressed = true;
} else {
pressed = DropDownList.fn._move.call(this, e);
}
return pressed;
},
selectAll: function () {
var unselectedItems = this._getUnselectedListItems();
this._selectItems(unselectedItems);
// todo: raise custom event
},
unselectAll: function () {
var selectedItems = this._getSelectedListItems();
this._selectItems(selectedItems); // will invert the selection
// todo: raise custom event
},
_selectItems: function (listItems) {
var that = this;
$.each(listItems, function (i, item) {
var idx = ui.List.inArray(item, that.ul[0]);
that.select(idx); // select OR unselect
});
},
_selectItem: function () {
// method override to prevent default selection of first item, done by normal dropdown
var that = this,
options = that.options,
useOptionIndex,
value;
useOptionIndex = that._isSelect && !that._initial && !options.value && options.index && !that._bound;
if (!useOptionIndex) {
value = that._selectedValue || options.value || that._accessor();
}
if (value) {
that.value(value);
} else if (that._bound === undefined) {
that.select(options.index);
}
},
_select: function (li) {
var that = this,
value,
text,
idx;
li = that._get(li);
if (li && li[0]) {
idx = ui.List.inArray(li[0], that.ul[0]);
if (idx > -1) {
if (li.hasClass(SELECTED)) {
li.removeClass(SELECTED);
that._uncheckItem(li);
if (this.selectAllListItem && li[0] === this.selectAllListItem[0]) {
this.unselectAll();
}
} else {
li.addClass(SELECTED);
that._checkItem(li);
if (this.selectAllListItem && li[0] === this.selectAllListItem[0]) {
this.selectAll();
}
}
if (this._open) {
that._current(li);
that._highlightCurrent();
}
var selecteditems = this._getSelectedListItems();
value = [];
text = [];
$.each(selecteditems, function (indx, item) {
var obj = $(item).children("span").first();
value.push(obj.attr("data-value"));
text.push(obj.text());
});
that._updateSummary(text);
that._updateSelectAllItem();
that._accessor(value, idx);
// todo: raise change event (add support for selectedIndex) if required
that._raiseSelectionChanged();
}
}
},
_getAllValueListItems: function () {
if (this.selectAllListItem) {
return this.ul.children("li").not(this.selectAllListItem[0]);
} else {
return this.ul.children("li");
}
},
_getSelectedListItems: function () {
return this._getAllValueListItems().filter("." + SELECTED);
},
_getUnselectedListItems: function () {
return this._getAllValueListItems().filter(":not(." + SELECTED + ")");
},
_getSelectedItemsText: function () {
var text = [];
var selecteditems = this._getSelectedListItems();
$.each(selecteditems, function (indx, item) {
var obj = $(item).children("span").first();
text.push(obj.text());
});
return text;
},
_updateSelectAllItem: function () {
if (!this.selectAllListItem) return;
// are all items selected?
if (this._getAllValueListItems().length == this._getSelectedListItems().length) {
this._checkItem(this.selectAllListItem);
this.selectAllListItem.addClass(SELECTED);
}
else {
this._uncheckItem(this.selectAllListItem);
this.selectAllListItem.removeClass(SELECTED);
}
},
_updateSummary: function (itemsText) {
if (!itemsText) {
itemsText = this._getSelectedItemsText();
}
if (itemsText.length == 0) {
this._inputWrapper.addClass(EMPTYSELECTION);
this.text(this.options.emptySelectionLabel);
return;
} else {
this._inputWrapper.removeClass(EMPTYSELECTION);
}
if (itemsText.length <= this.options.preSummaryCount) {
this._textAccessor(itemsText.join(", "));
}
else {
this._textAccessor(itemsText.length + ' selected');
}
},
_checkItem: function (itemContainer) {
if (!itemContainer) return;
itemContainer.children("input").prop("checked", true);
},
_uncheckItem: function (itemContainer) {
if (!itemContainer) return;
itemContainer.children("input").removeAttr("checked");
},
_isItemChecked: function (itemContainer) {
return itemContainer.children("input:checked").length > 0;
},
value: function (value) {
if(value != undefined)
console.log("value", value);
var that = this,
idx,
valuesList = [];
if (value !== undefined) {
if (!$.isArray(value)) {
valuesList.push(value);
this._oldValue = valuesList; // to allow for selectionChanged event
}
else {
valuesList = value;
this._oldValue = value; // to allow for selectionChanged event
}
// clear all selections first
$(that.ul[0]).children("li").removeClass(SELECTED);
$("input", that.ul[0]).removeAttr("checked");
$.each(valuesList, function (indx, item) {
var hasValue;
if (item !== null) {
item = item.toString();
}
that._selectedValue = item;
hasValue = value || (that.options.optionLabel && !that.element[0].disabled && value === "");
if (hasValue && that._fetchItems(value)) {
return;
}
idx = that._index(item);
if (idx > -1) {
that.select(
that.options.showSelectAll ? idx + 1 : idx
);
}
});
that._updateSummary();
}
else {
var selecteditems = this._getSelectedListItems();
return $.map(selecteditems, function (item) {
var obj = $(item).children("span").first();
return obj.attr("data-value");
}).join();
}
},
});
ui.plugin(MultiSelectBox);
})(jQuery);
UPDATE
I came across documentation for multiselectbox's select event that clearly states that the select event is not fired when an item is selected programmatically. Is it relevant to what I am trying to do? But why is it firing for one of the filters even though I am setting them programmatically?
enter link description here

Test angular directive that adds $parser

I have a directive that validates text to be in a specific format:
angular.module('app')
.directive('validNumber', validNumber);
function validNumber() {
var directive = {
restrict: 'A',
require: '?ngModel',
link: linkFunc
};
return directive;
function linkFunc(scope, element, attrs, ngModelCtrl) {
if (!ngModelCtrl) {
return;
}
ngModelCtrl.$parsers.push(function (val) {
if (angular.isUndefined(val)) {
var val = '';
}
var clean = val.replace(/[^0-9\.]/g, '');
var decimalCheck = clean.split('.');
if (!angular.isUndefined(decimalCheck[1])) {
decimalCheck[1] = decimalCheck[1].slice(0, 2);
clean = decimalCheck[0] + '.' + decimalCheck[1];
}
if (val !== clean) {
ngModelCtrl.$setViewValue(clean);
ngModelCtrl.$render();
}
return clean;
});
element.bind('keypress', function (event) {
if (event.keyCode === 32) {
event.preventDefault();
}
});
}
}
Now I want to test the inner parser function I added and I just can't do it. How can I invoke a call to that function? How can I test the result? My very unsuccessful tests are:
describe('validNumber directive specs', function () {
var scope, compile;
var validHtml = '<form name="testForm"><input name="test" type="text" valid-number ng-model="str" /></form>';
beforeEach(function () {
angular.mock.module('dashboardApp');
module(bootstrapperMock);
inject(function (_$rootScope_, _$compile_) {
scope = _$rootScope_.$new();
compile = _$compile_;
});
});
describe('When a key press occures', function () {
it('should :( ', function () {
scope.str = 0;
var element = compile(validHtml)(scope);
var viewValue = 2, input = element.find('input');
scope.str = viewValue;
scope.$digest();
var e = angular.element.Event('keypress keydown');
e.which = 50;
element.trigger(e);
scope.$digest();
});
});
});
I tried both changing the model and triggering a keypress.
Thanks!
The following works:
describe('When a key press occures', function () {
it('when a key press', function () {
var expected = '';
var element = compile(validHtml)(scope);
element.val('asda');
element.trigger('input');
var actual = element.val();
expect(expected).toBe(actual);
});
});
I also updated the html in this spec:
var validHtml = '<input name="test" type="text" valid-number ng-model="str" />';
The magic here is to trigger 'input' for the element.

Automatic text detection on contenteditable div using angular js

what is the best way to do following using angular js
when writing text on a contenteditable div need to detect special word like ' {{FULL_NAME}} ' and covert to tag with pre-deifined constant words
example - if some one write
' His name is {{FULL_NAME}} '
should be instantly convert to ' His name is john smith '
Here is a demo plunker: http://plnkr.co/edit/GKYxXiDKv7fBeaE7rrZA?p=preview
Service:
app.factory('interpolator', function(){
var dict = { .... };
return function(str){
return (str || "").replace(/\{\{([^\}]+)\}\}/g, function(all, match){
return dict[match.trim().toLowerCase()] || all;
});
};
});
Directive:
app.directive('edit',[ 'interpolator', function(interpolator){
return {
restrict: 'A',
require: 'ngModel',
link: function(scope, element, attrs, ngModel) {
element.on('blur', function(e) {
scope.$apply(function() {
var content = interpolator(element.text());
element.text(content);
ngModel.$setViewValue(content);
});
});
ngModel.$formatters.push(interpolator);
ngModel.$render = function() {
element.text(ngModel.$viewValue);
ngModel.$setViewValue(ngModel.$viewValue);
};
}
};
}]);
Here's an example using simple DOM methods, based on other answers I've provided on Stack Overflow. It also uses Rangy to save and restore the selection while doing the substitutions so that the caret does not move.
Demo:
http://jsbin.com/zuvevocu/2
Code:
var editorEl = document.getElementById("editor");
var keyTimer = null, keyDelay = 100;
function createKeyword(matchedTextNode) {
var el = document.createElement("b");
el.style.backgroundColor = "yellow";
el.style.padding = "2px";
el.contentEditable = false;
var matchedKeyword = matchedTextNode.data.slice(1, -1); // Remove the curly brackets
matchedTextNode.data = (matchedKeyword.toLowerCase() == "name") ? "John Smith" : "REPLACEMENT FOR " + matchedKeyword;
el.appendChild(matchedTextNode);
return el;
}
function surroundInElement(el, regex, surrounderCreateFunc) {
// script and style elements are left alone
if (!/^(script|style)$/.test(el.tagName)) {
var child = el.lastChild;
while (child) {
if (child.nodeType == 1) {
surroundInElement(child, regex, surrounderCreateFunc);
} else if (child.nodeType == 3) {
surroundMatchingText(child, regex, surrounderCreateFunc);
}
child = child.previousSibling;
}
}
}
function surroundMatchingText(textNode, regex, surrounderCreateFunc) {
var parent = textNode.parentNode;
var result, surroundingNode, matchedTextNode, matchLength, matchedText;
while ( textNode && (result = regex.exec(textNode.data)) ) {
matchedTextNode = textNode.splitText(result.index);
matchedText = result[0];
matchLength = matchedText.length;
textNode = (matchedTextNode.length > matchLength) ?
matchedTextNode.splitText(matchLength) : null;
surroundingNode = surrounderCreateFunc(matchedTextNode.cloneNode(true));
parent.insertBefore(surroundingNode, matchedTextNode);
parent.removeChild(matchedTextNode);
}
}
function updateKeywords() {
var savedSelection = rangy.saveSelection();
surroundInElement(editorEl, /\{\w+\}/, createKeyword);
rangy.restoreSelection(savedSelection);
}
function keyUpHandler() {
if (keyTimer) {
window.clearTimeout(keyTimer);
}
keyTimer = window.setTimeout(function() {
updateKeywords();
keyTimer = null;
}, keyDelay);
}
editorEl.onkeyup = keyUpHandler;
Related:
https://stackoverflow.com/a/5905413/96100
https://stackoverflow.com/a/4026684/96100
https://stackoverflow.com/a/4045531/96100

jquery cookie code error

I tried to create a cookie for the link but it showed me errors like this....how to fix it...
Uncaught ReferenceError: createCookie is not defined
i am providing my code in fiidle
http://jsfiddle.net/SSMX4/82/ cookie not working
my jquery code is below
// locale selector actions
$('#region-picker').click(function(){
if ($("#locale-select").is(":visible")) return closeSelector('slide');
var foot_height = $('#footer').innerHeight();
var foot_height_css = foot_height-1;
var select_position = '-=' + (Number(700)+18);
console.log("hallo"+select_position);
var $selector = $('#locale-select');
$('#locale_pop').fadeOut();
$selector.css({top:foot_height_css});
$selector.fadeIn(function(){
$(this).addClass('open');
$(this).animate({top:select_position}, 1000);
});
});
$('#select-tab').click(function(e){
e.stopPropagation()
closeSelector('slide');
});
// don't hide when clicked within the box
$('#locale-select').click(function(e){
e.stopPropagation();
});
$(document).click(function(){
if ($('#locale-select').hasClass('open')) {
closeSelector('disappear');
}
});
$('.locale-link').click(function(){
//var $clicked = $(this); //"$(this)" and "this" is the clicked span
$(".locale-select-lable").html($(this).html());
//search for "marginXXXXX"
var flags = $(this).attr("class").match(/(margin\w+)\s/g);
//create new class; add matching value if found
var flagClass = "tk-museo-sans locale-select-lable" + (flags.length ? " " + flags[0] : "");
//set new class definition
$(".locale-select-lable").attr("class", flagClass);
closeSelector('disappear');
//if ($("#locale-select").is(":visible")) return closeSelector('slide');
/*
// var desired_locale = $(this).attr('rel');
// createCookie('desired-locale',desired_locale,360);
// createCookie('buy_flow_locale',desired_locale,360);
//closeSelector('disappear');
*/
}); /* CORRECTED */
$('#locale_pop a.close').click(function(){
var show_blip_count = readCookie('show_blip_count');
if (!show_blip_count) {
createCookie('show_blip_count',3,360);
}
else if (show_blip_count < 3 ) {
eraseCookie('show_blip_count');
createCookie('show_blip_count',3,360);
}
$('#locale_pop').slideUp();
return false;
});
function closeSelector(hide_type){
var foot_height = $('#footer').innerHeight();
var select_position = '+=' + (Number(400)+20);
if (hide_type == 'slide') {
$('#locale-select').animate({top:select_position}, 1000, function(){
$(this).removeClass('open');
$(this).fadeOut()
});
}
else if (hide_type == 'disappear'){
$('#locale-select').fadeOut('fast');
$('#locale-select').removeClass('open');
}
}
$('.locale-link').click(function(){
var desired_locale = $(this).attr('rel');
console.log("cookie....." + desired_locale);
createCookie('desired-locale',desired_locale,360);
createCookie('buy_flow_locale',desired_locale,360);
closeSelector('disappear');
})
$('#locale_pop a.close').click(function(){
var show_blip_count = readCookie('show_blip_count');
if (!show_blip_count) {
createCookie('show_blip_count',3,360);
}
else if (show_blip_count < 3 ) {
eraseCookie('show_blip_count');
createCookie('show_blip_count',3,360);
}
$('#locale_pop').slideUp();
return false;
});
​
I did not find your declaration of the function "createCookie". It seems you copied the code and forgot to copy the function.
Btw: "xxx is not defined" always means the variable/function does not exist ..

Using a computed column with JSON

I am trying to make a computed column on data returned via JSON. I cannot get it to work. I either get a NAN value or it says the column does not exist.
javascript:
function commissionsViewModel() {
var self = this;
self.commissions = ko.observableArray();
ko.applyBindings(self, $("#commissions").get(0));
function LoadcommissionsFromServer() {
$.post(
'/commissions/data',
function (data) {
var results = ko.observableArray();
ko.mapping.fromJS(data, {}, results);
for (var i = 0; i < results().length; i++) {
self.commissions.push(results()[i]);
};
},
'json'
)
}
LoadcommissionsFromServer();
self.ComissionAmount = ko.computed(
function () {
return this.CommissionableAmount * this.Rate * this.Modifier;
});
return self;
}
var viewModel = commissionsViewModel();
What I am trying to accomplish is for it to recalculate the CommissionAmount after I change the modifier or rate.
EDIT
If I manually map the fields I get the NaN
function Commission(data) {
this.Status = ko.observable(data.Status);
this.OriginalCommissionCode = ko.observable(data.OriginalCommissionCode);
this.NewCommissionCode = ko.observable(data.NewCommissionCode);
this.InvoiceNumber = ko.observable(data.InvoiceNumber);
this.CustomerID = ko.observable(data.CustomerID);
this.CommissionableAmount = ko.observable(data.CommissionableAmount);
this.Modifier = ko.observable(data.Modifier);
this.Rate = ko.observable(data.Rate);
this.SalesAmount = ko.observable(data.SalesAmount);
this.NonSalesAmount = ko.observable(data.NonSalesAmount);
this.CommissionAmount = ko.computed(function () {
return this.CommissionableAmount * this.Rate * this.Modifier;
});
}
function commissionsViewModel() {
var self = this;
self.commissions = ko.observableArray();
$.post(
'/commissions/data',
function (allData) {
var mappedTasks = $.map(allData, function (item) { return new Commission(item) });
self.commissions(mappedTasks);
},
'json'
);
}
ko.applyBindings(new commissionsViewModel());
I assume Rate and Modifier are observables (You didn't provide their declaration) so you need to use the this.Rate() and this.Modififer() notations. They are functions, not properties.