someone have any idea how i should modify the payment-lines in the POS,I want to add a type of credit card(like a many2one, I did it) but every time I add a line my option change to the first and also when the order is finished not save the value in pos.order -> statement_id.
enter image description here
here is my code:
function POS_CashRegister (instance, local) {
var pos = instance.point_of_sale;
var _t = instance.web._t;
var QWeb = instance.web.qweb;
var round_pr = instance.web.round_precision
const ParentOrder = pos.Order;
pos.PosModel.prototype.models.push({ //loaded model
model: 'pos.credit.card',
fields: ['id', 'name'],
domain: [['pos_active','=',true]],
loaded: function(self,credit_cards){ //pass parameters
self.credit_cards = credit_cards;
},
});
pos.PaymentScreenWidget = pos.PaymentScreenWidget.extend({
validate_order: function(options) {
var self = this;
var currentOrder = self.pos.get('selectedOrder');
var plines = currentOrder.get('paymentLines').models;
for (var i = 0; i < plines.length; i++) {
if(plines[i].cashregister.journal_id[1] === 'Tarjeta de Credito (PEN)')
{
var value = plines[i].node.firstElementChild.nextElementSibling.nextElementSibling.firstElementChild.value;
plines[i].set_credit_card(parseInt(value));
//console.log(plines[i].node.firstElementChild.nextElementSibling.nextElementSibling.firstElementChild.value);
//plines[i].node
}
}
console.log(currentOrder);
self._super(options);
},
render_paymentline: function (line) {
var self = this;
if(line.cashregister.journal_id[1] !== 'Tarjeta de Credito (PEN)'){
if (line.cashregister.currency[1] !== 'USD') {
return this._super(line);
} else {
var el_html = openerp.qweb.render('Paymentline', {widget: this, line: line});
el_html = _.str.trim(el_html);
var el_node = document.createElement('tbody');
el_node.innerHTML = el_html;
el_node = el_node.childNodes[0];
el_node.line = line;
el_node.querySelector('.paymentline-delete')
.addEventListener('click', this.line_delete_handler);
el_node.addEventListener('click', this.line_click_handler);
var sourceInput = el_node.querySelector('.source-input');
var convertedInput = el_node.querySelector('.converted-input');
sourceInput.addEventListener('keyup', function (event) {
el_node.line.set_usd_amount(event.target.value);
convertedInput.value = el_node.line.get_amount_str();
});
line.node = el_node;
return el_node;
}
}else {
return this._super(line);
}
},
});
pos.Paymentline = pos.Paymentline.extend({
initialize: function(attributes, options) {
this.amount = 0;
this.cashregister = options.cashregister;
this.name = this.cashregister.journal_id[1];
this.selected = false;
this.credit_card = false;
this.pos = options.pos;
},
set_credit_card: function(value){
this.credit_card = value;
this.trigger('change:credit_card',this);
},
get_credit_card: function(){
return this.credit_card;
},
export_as_JSON: function(){
return {
name: instance.web.datetime_to_str(new Date()),
statement_id: this.cashregister.id,
account_id: this.cashregister.account_id[0],
journal_id: this.cashregister.journal_id[0],
amount: this.get_amount(),
credit_card_id: this.get_credit_card(),
};
},
});
}
any suggestions?
You can create 2 journals here too. One for visa and another for master If you don't want that drop down there. Another way is you have to store selected option in a variable and then print that variable in front.
To store selected option initially assigned ids to each values of option and after then while validating order you can get that id of that field and from that id you can get your value. By this way also you can do that.
Related
This question regarding a web app built using the ArcGIS Javascript API 3.18. I am trying to add an dojo select to the title of an infoWindow. The select box is intended to be populated with the list of identified results. I'm trying two different ways:
1) Adding the combobox declaratively using html:
var template = new esri.InfoTemplate(layerName + "<br/><select id="id_select" data-dojo-type="dijit/form/Select"</select>,"<br/> FID : ${FID}");
The combobox is there, but I don't know how to access the combobox to add the options dynamically (via addOptions). I would normally do dijit.byId("id_select"), but considering it doesn't exist until it's created...I'm not sure how to go about this way.
2) Programmatically
With the code below, the title displays information regarding the dijit/form/select widget (It displays: [object HTML TableElement]), but not the widget itself. Wondering if this can be rectified using dijitStartup(), but I can't haven't figured out how to use it (currently trying something along the lines of myTemplate.startupDijits(mySelectBox)--not with these variable names). I tried using domConstruct like this example
var identifyTask, identifyParams, idPoint;
var identifyResults;
require([
"esri/dijit/Popup",
"esri/tasks/IdentifyTask",
"esri/tasks/IdentifyParameters",
"dijit/form/Select",
"dojo/dom-construct",
"dojo/promise/all",
"dojo/domReady!"
], function (
Popup, IdentifyTask, IdentifyParameters, Select, domConstruct, All
) {
var identifySelect;
//dojo.connect(window.myMap, "onLoad", mapReady);
mapReady(window.myMap);
function mapReady(map) {
dojo.connect(window.myMap, "onClick", runIdentifies);
}
function runIdentifies(evt) {
identifyResults = [];
idPoint = evt.mapPoint;
var layers = dojo.map(window.myMap.layerIds, function (layerId) {
return window.myMap.getLayer(layerId);
});
layers = dojo.filter(layers, function (layer) {
if (layer.visibleLayers[0] !== -1) {
return layer.getImageUrl && layer.visible
}
}); //Only dynamic layers have the getImageUrl function. Filter so you only query visible dynamic layers
var tasks = dojo.map(layers, function (layer) {
return new IdentifyTask(layer.url);
}); //map each visible dynamic layer to a new identify task, using the layer url
var defTasks = dojo.map(tasks, function (task) {
return new dojo.Deferred();
}); //map each identify task to a new dojo.Deferred
var params = createIdentifyParams(layers, evt);
var promises = [];
for (i = 0; i < tasks.length; i++) {
promises.push(tasks[i].execute(params[i])); //Execute each task
}
var allPromises = new All(promises);
allPromises.then(function (r) { showIdentifyResults(r, tasks); });
}
function showIdentifyResults(r, tasks) {
var results = [];
var taskUrls = [];
var resultNames = [];
r = dojo.filter(r, function (result) {
return r[0];
});
for (i = 0; i < r.length; i++) {
results = results.concat(r[i]);
for (j = 0; j < r[i].length; j++) {
taskUrls = taskUrls.concat(tasks[i].url);
}
}
results = dojo.map(results, function (result, index) {
var feature = result.feature;
var layerName = result.layerName;
var serviceUrl = taskUrls[index];
resultNames.push({
value: result.layerName,
label: result.layerName
});
feature.attributes.layerName = result.layerName;
var identifiedList = getIdentifiedList(resultNames);
console.log(identifiedList);
var template = new esri.InfoTemplate();
template.setTitle(identifiedList);
feature.setInfoTemplate(template);
var resultGeometry = feature.geometry;
var resultType = resultGeometry.type;
return feature;
});
if (results.length === 0) {
window.myMap.infoWindow.clearFeatures();
} else {
window.myMap.infoWindow.setFeatures(results);
}
window.myMap.infoWindow.show(idPoint);
identifySelect.on('change', function(evt) {
var identIndex = identifySelect.get("value");
console.log(identIndex);
window.myMap.infoWindow.select(identIndex);
});
return results;
}
function getIdentifiedList(options) {
identifySelect = new Select({
name: "identifySelect",
id: "id_select",
options: options
}, domConstruct.create("select"));
return identifySelect.domNode;
}
function createIdentifyParams(layers, evt) {
var identifyParamsList = [];
identifyParamsList.length = 0;
dojo.forEach(layers, function (layer) {
var idParams = new esri.tasks.IdentifyParameters();
idParams.width = window.myMap.width;
idParams.height = window.myMap.height;
idParams.geometry = evt.mapPoint;
idParams.mapExtent = window.myMap.extent;
idParams.layerOption = esri.tasks.IdentifyParameters.LAYER_OPTION_VISIBLE;
var visLayers = layer.visibleLayers;
if (visLayers !== -1) {
var subLayers = [];
for (var i = 0; i < layer.layerInfos.length; i++) {
if (layer.layerInfos[i].subLayerIds == null)
subLayers.push(layer.layerInfos[i].id);
}
idParams.layerIds = subLayers;
} else {
idParams.layerIds = [];
}
idParams.tolerance = 5;
idParams.returnGeometry = true;
identifyParamsList.push(idParams);
});
return identifyParamsList;
}
});
Hi this is kinda old but i'll give it a shot. I hope this answers your question.
So if the problem is accessing the infoWindow what you need to do is set up a listener for when it is created.
on(map.infoWindow, "show", function () {
// do something
})
I have a fiddle that shows how to access infoWindow upon creation:
https://jsfiddle.net/kreza/jpLj5y4h/
I want to increment my i value to save different value to local storage. But i always = 0, what can I do to change this behavior?
(function() {
var i = 0;
var storage = new Storage();
window.onload = function() {
document.getElementById('buttonCreate').onclick = function() {
var topicValue = document.getElementById("create-topic").value;
var statusValue = document.getElementById("create-status").value;
var descriptionValue = document.getElementById("create-description").value;
var ticket = {
topic: topicValue,
status: statusValue,
description: descriptionValue
};
storage.set("task-"+i, ticket);
i++;
}
}
})();
function Storage() {
this._ITEMS_DESCRIPTOR = 'items';
}
Storage.prototype.get = function() {
var fromStorage = localStorage.getItem(this._ITEMS_DESCRIPTOR);
return fromStorage ? JSON.parse(fromStorage) : [];
};
Storage.prototype.set = function(key, items) {
localStorage.setItem(key, JSON.stringify(items));
};
Declare the var i = 0 outside of the function. Right now it is being reset to 0 every time to function is run.
I need to increment key value when I'm saving data to localstorage because when I click button key is same for all records and record just update,doesn't creating new. I know I can do this with closures bit I'm fresh in JS and dont know how to do it correct.
(function() {
window.onload = function() {
document.getElementById('buttonCreate').onclick = function() {
var topicValue = document.getElementById("create-topic").value;
var statusValue = document.getElementById("create-status").value;
var descriptionValue = document.getElementById("create-description").value;
var key = 0;
var storage = new Storage();
var ticket = {
topic: topicValue,
status: statusValue,
description: descriptionValue
};
storage.set(key, ticket);
return (function() {
key++;
return key;
}());
}
}
})();
function Storage() {
this._ITEMS_DESCRIPTOR = 'items';
}
Storage.prototype.get = function() {
var fromStorage = localStorage.getItem(this._ITEMS_DESCRIPTOR);
return fromStorage ? JSON.parse(fromStorage) : [];
};
Storage.prototype.set = function(key, items) {
localStorage.setItem(key, JSON.stringify(items));
};
You need declare the variable before the function, to save the value and add 1+.
(function() {
window.onload = function() {
var key = 0; //move var key to here
document.getElementById('buttonCreate').onclick = function() {
var topicValue = document.getElementById("create-topic").value;
var statusValue = document.getElementById("create-status").value;
var descriptionValue = document.getElementById("create-description").value;
// var key = 0; remove these line
var storage = new Storage();
var ticket = {
topic: topicValue,
status: statusValue,
description: descriptionValue
};
storage.set(key, ticket);
return (function() {
key++;
return key;
}());
}
}
})();
I have a javascript compositer pattern which i implemented (see code below).
In my main class i instantiate either the MenuItem or the Menu. I have to call the method update() on the component and they should return the corresponding code.
However it doesnt return the correct amount of totalitems. it alwasy returns the default value 0 which is defined in MenuComponent.
I think it has something to do with the this keyword but i can not find the exact solution.
MenuItem:
//MENU ITEM
//----------
var MenuItem = function(id) {
MenuComponent.apply(this, [id, name]);
};
MenuItem.prototype = Object.create(MenuComponent.prototype);
MenuItem.prototype.constructor = MenuItem;
MenuItem.prototype.update = function() {
//works
console.log(this.ingredients)
//Doesnt work, this should display same as this.ingredients
console.log(this.calculateIngredients())
console.log("--------------")
};
Menu:
//MENU
//--------
var Menu = function(id, name) {
MenuComponent.apply(this, [id, name]);
this.menuitems = [];
};
Menu.prototype = Object.create(MenuComponent.prototype);
Menu.prototype.constructor = Menu;
Menu.prototype.add = function(menuitem) {
this.menuitems.push(menuitem);
};
Menu.prototype.remove = function(menuitem) {
for(var s, i = 0; s = this.getMenuItem(i); i++) {
if(s == menuitem) {
this.menuitems.splice(i, 1);
return true;
}
if(s.remove(menuitem)) {
return true;
}
}
return false;
};
Menu.prototype.getMenuItem = function(i) {
return this.menuitems[i];
};
Menu.prototype.calculateIngredients = function() {
this.ingredients = 0;
for(var key in this.menuitems) {
this.ingredients += this.menuitems[key].calculateIngredients();
}
return this.ingredients;
};
MenuComponent
//MenuComponent
//-------------
var MenuComponent = function(id, name) {
if(this.constructor === MenuComponent) {
throw new Error("Can't instantiate abstract class");
}
this.id = id;
this.name = name;
this.ingredients = 0;
};
MenuComponent.prototype.calculateIngredients = function() {
return this.ingredients;
};
MenuComponent.prototype.update = function() {
console.log(this.ingredients)
console.log("-----------------")
};
example
// HANDLER
var menuitem1 = new MenuItem(1)
, menuitem2 = new MenuItem(2)
, menuitem3 = new MenuItem(3)
, menuitem4 = new MenuItem(4)
, menuitem5 = new MenuItem(5)
, menuitem6 = new MenuItem(6)
, menuitem7 = new MenuItem(7)
, menu = new Menu(1);
menu.add(menuitem1);
menu.add(menuitem2);
menu.add(menuitem3);
menu.add(menuitem4);
menuitem1.ingredients = 1
menuitem2.ingredients = 5
menuitem3.ingredients = 7;
menuitem4.ingredients = 2
// lets say i want to update the ingredient count of the following
menuitem1.update();
menuitem2.update();
menu.update();
//the update goes wrong, it doesnt display the correct amount, it alwasy displays 0 on the amounts where i commented
JSFiddle
Instead of
MenuComponent.prototype.update = function() {
console.log(this.ingredients) // 0
};
You want to call
MenuComponent.prototype.update = function() {
console.log(this.calculateIngredients()) // 15
};
whole code on jsfiddle: http://jsfiddle.net/krzysztof_safjanowski/gjTb4/
The code below is simplified, see the fiddle: http://jsfiddle.net/QTUqD/7/
Basically I'm setting the device name under the data-bind, but I also need to specify the optionsValue for sending off to the database, but when I set it, the display data-bind is blank.
<script id="extItems" type="text/html">
<tr>
<td data-bind="text: device() && device().name"></td>
</tr>
</script>
<script id="editExts" type="text/html">
<tr>
<td>
<select data-bind="options: $root.devicesForItem($data), optionsText: 'name', value: device, optionsValue: 'id'"></select>
</td>
</tr>
</script>
window.ExtListViewModel = new function () {
var self = this;
window.viewModel = self;
self.list = ko.observableArray();
self.pageSize = ko.observable(10);
self.pageIndex = ko.observable(0);
self.selectedItem = ko.observable();
self.extQty = ko.observable();
self.devices = ko.observableArray();
self.addressList = ko.observableArray(['addressList']);
self.availableDevices = ko.computed(function() {
var usedQuantities = {}; // for each device id, store the used quantity
self.list().forEach(function(item) {
var device = item.device();
if (device) {
usedQuantities[device.id] = 1 + (usedQuantities[device.id] || 0);
}
});
return self.devices().filter(function(device) {
var usedQuantity = usedQuantities[device.id] || 0;
return device.qty > usedQuantity;
});
});
// need this to add back item's selected device to its device-options,
// and to maintain original order of devices
self.devicesForItem = function(item) {
var availableDevices = self.availableDevices();
return self.devices().filter(function(device) {
return device === item.device() || availableDevices.indexOf(device) !== -1;
});
}
self.edit = function (item) {
if($('#extMngForm').valid()) {
self.selectedItem(item);
}
};
self.cancel = function () {
self.selectedItem(null);
};
self.add = function () {
if($('#extMngForm').valid()) {
var newItem = new Extension();
self.list.push(newItem);
self.selectedItem(newItem);
self.moveToPage(self.maxPageIndex());
}
};
self.remove = function (item) {
if (confirm('Are you sure you wish to delete this item?')) {
self.list.remove(item);
if (self.pageIndex() > self.maxPageIndex()) {
self.moveToPage(self.maxPageIndex());
}
}
$('.error').hide();
};
self.save = function () {
if($('#extMngForm').valid()) {
self.selectedItem(null);
};
};
self.templateToUse = function (item) {
return self.selectedItem() === item ? 'editExts' : 'extItems';
};
self.pagedList = ko.dependentObservable(function () {
var size = self.pageSize();
var start = self.pageIndex() * size;
return self.list.slice(start, start + size);
});
self.maxPageIndex = ko.dependentObservable(function () {
return Math.ceil(self.list().length / self.pageSize()) - 1;
});
self.previousPage = function () {
if (self.pageIndex() > 0) {
self.pageIndex(self.pageIndex() - 1);
}
};
self.nextPage = function () {
if (self.pageIndex() < self.maxPageIndex()) {
self.pageIndex(self.pageIndex() + 1);
}
};
self.allPages = ko.dependentObservable(function () {
var pages = [];
for (i = 0; i <= self.maxPageIndex() ; i++) {
pages.push({ pageNumber: (i + 1) });
}
return pages;
});
self.moveToPage = function (index) {
self.pageIndex(index);
};
};
ko.applyBindings(ExtListViewModel, document.getElementById('extMngForm'));
function Extension(extension, name, email, vmpin, device, macAddress, shipTo){
this.extension = ko.observable(extension);
this.name = ko.observable(name);
this.email = ko.observable(email);
this.vmpin = ko.observable(vmpin);
this.device = ko.observable(device);
this.macAddress = ko.observable(macAddress);
this.shipTo = ko.observable(shipTo);
}
When you use optionsValue, KO writes the property value to whatever you have bound against value. So, it would now populate value with the id rather than the object.
There are a couple of ways to tackle this scenario where you want both the value (for sending to the DB) and the object (for binding other parts of the UI against).
A pretty typical solution is to create a computed observable on your object that takes the currently selected object and returns the id.
So, in your Extension you would do something like:
this.device = ko.computed({
read: function() {
var device = this.device.asObject();
return device && device.id;
},
deferEvaluation: true, //deferring evaluation, as device.asObject has not been created yet
}, this);
//create this as a sub-observable, so it just disappears when we turn this into JSON and we are just left with the id to send to the DB
this.device.asObject = ko.observable(device);
Then remove the optionsValue and bind value against device.asObject
In this case, I added the asObject sub-observable, so it will just drop off when you turn this into JSON (ko.toJSON) to send to the server. The only tricky part about this technique is that if you are loading existing data from the server, then you would need to populate asObject with the appropriate choice from your options.
Here is a sample: http://jsfiddle.net/rniemeyer/Q3PEv/
Another option that I have used is to continue to use optionsValue, but then to create a custom binding that tracks the object in a separate observable. Here is a custom binding that creates an asObject sub-observable for whatever is bound against value. This way you really don't need to mess with it at all in your view model.
//when using optionsValue, still track the select object in a different observable
ko.bindingHandlers.valueAsObject = {
init: function(element, valueAccessor, allBindingsAccessor) {
var value = allBindingsAccessor().value,
prop = valueAccessor() || 'asObject';
//add an "asObject" sub-observable to the observable bound against "value"
if (ko.isObservable(value) && !value[prop]) {
value[prop] = ko.observable();
}
},
//whenever the value or options are updated, populated the "asObject" observable
update: function(element, valueAccessor, allBindingsAccessor) {
var prop = valueAccessor(),
all = allBindingsAccessor(),
options = ko.utils.unwrapObservable(all.options),
value = all.value,
key = ko.utils.unwrapObservable(value),
keyProp = all.optionsValue,
//loop through the options, find a match based on the current "value"
match = ko.utils.arrayFirst(options, function(option) {
return option[keyProp] === key;
});
//set the "asObject" observable to our match
value[prop](match);
}
};
Sample here: http://jsfiddle.net/rniemeyer/E2kvM/