How to stop Kendo UI dropdown from sorting alphabetically - kendo-ui
I have been given the fun job on taking on someone elses code and trying to figure it out...
I have been tearing my hair out trying to figure out how to to stop a Kendo UI dropdown from sorting alphabetically ?
<select id="ddlArtworkStatuses" onlyPreparedValues="true"
readOnlyInput="true" data-bind="idNameOptions: artworkStatuses,
comboboxSelectedValue: artworkStatusId"></select>
For some reason this sorts althabetically but I want it to keep the order in the datasource. I have double checked to make sure it is in the order I want.
It doesn't use the standard way of using Kendo UI and I can't find any examples anywhere of using it this way?
It binds the view to the model with this line at the top of the view I believe?
<!-- ko with: fabricationModel -->
The vm.fabrication file is this:
(function (app) {
app.namespace("models");
var resources = {
unableToDeleteArtworkMessage: "This artwork cannot be deleted because it is linked to one or more of the following: Movements, Shows, POs. Or it has Imported Costs, Sales or Restoration Cases.",
unableToBlankArtworkFullyMessage: "This artwork has some data that will not be blanked if you continue. This could be one or more of the following: Movements, Shows, POs, Imported Costs, Sales or Restoration Cases. Do you want to continue?",
deleteArtworkTitle: "Delete artwork",
blankArtworkTitle: "Blank Artwork",
duplicateTitle: "New artwork form is pre-populated",
duplicateMessage: "You can make changes to Fabrication form fields. Record will be created after you press save button",
saveError: 'An error occured during artwork saving. Changes were not saved.'
};
app.models.FabricationModel = function (datasource) {
var emitter = new app.events.EventEmitter(),
self = this,
duplicateArtwork = ko.observable(false);
this.isNewArtwork = ko.observable(false);
this.isActivated = ko.observable(false);
this.showCreationInformation = ko.observable(true);
this.wipeArtworkModel = new app.models.WipeArtworkDialogModel(datasource);
this.internalArtworkModel = ko.observable();
this.editCategoryModel = new app.models.EditDhCategoryModel();
// alert("data=" + this.artworkStatuses);
this.isReadOnly = ko.computed(function () {
if (!self.internalArtworkModel()) {
return true;
}
return self.internalArtworkModel().isReadOnly();
});
this.canSaveStudioStatusOnly = ko.computed(function () {
if (!self.internalArtworkModel()) {
return false;
}
return self.internalArtworkModel().isUnblockStatusActive()
&& self.internalArtworkModel().isReadOnly()
&& self.internalArtworkModel().isStudioStatusVisible();
});
this.canSaveCatRaisOnly = ko.computed(function () {
if (!self.internalArtworkModel()) {
return false;
}
return self.internalArtworkModel().isReadOnly()
&& self.internalArtworkModel().isArchiveProvenanceWriter();
});
this.isNewOrDuplicating = ko.computed(function () {
return self.isNewArtwork() || duplicateArtwork();
});
this.activate = function (params) {
var id = params.id || 0;
self.isNewArtwork(!id);
return self.loadArtworkDetails(id);
};
this.isValid = function () {
return self.internalArtworkModel() && self.internalArtworkModel().errors().length == 0;
};
this.loadArtworkDetails = function (id) {
var action = self.isNewArtwork() ? datasource.artworks.getEmpty : datasource.artworks.getById;
return action(id)
.done(function (result) {
var mapper = app.mappers["fabrication"],
model = mapper.map(result.data);
self.internalArtworkModel(model);
self.editCategoryModel.categoryId(model.defaultDhCategoryId);
self.editCategoryModel.setModeAsCategoryChanging();
if (self.isNewArtwork()) {
self.editCategoryModel.setModeAsCreation();
self.editCategoryModel.show();
}
self.isActivated(true);
duplicateArtwork(false);
$("a#science-link").attr("href", window.location.href);
triggerLoadEvent();
});
};
this.saveArtwork = function () {
if (self.isValid()) {
return saveInternal($.noop);
}
};
this.editCategory = function () {
self.editCategoryModel.show();
};
this.onLoad = function (callback) {
emitter.subscribe("load", callback);
};
this.onCategoryChanged = function (callback) {
emitter.subscribe("category-changed", callback);
};
this.onDelete = function (callback) {
emitter.subscribe("delete", callback);
};
this.onCreated = function (callback) {
emitter.subscribe("artwork-created", callback);
};
this.onUpdated = function (callback) {
emitter.subscribe("artwork-updated", callback);
};
this.onBlanked = function (callback) {
emitter.subscribe("blanked", callback);
};
this.saveStudioStatusInt = function () {
return saveStudioStatusInternal($.noop);
};
this.saveCatRaisInt = function () {
return saveCatRaisInternal($.noop);
};
this.saveStudioStatus = ko.asyncCommand({
execute: function (complete) {
saveStudioStatusInternal(complete);
},
canExecute: function (isExecuting) {
return !isExecuting && self.canSaveStudioStatusOnly();
}
});
this.saveCatRais = ko.asyncCommand({
execute: function (complete) {
saveCatRaisInternal(complete);
},
canExecute: function (isExecuting) {
return !isExecuting && self.canSaveCatRaisOnly();
}
});
this.save = ko.asyncCommand({
execute: function (complete) {
return saveInternal(complete);
},
canExecute: function (isExecuting) {
if (!self.isValid()) {
showErrors();
}
return !isExecuting && self.isValid();
}
});
function saveStudioStatusInternal(completeCallback) {
var model = self.internalArtworkModel();
triggerSaveStudioStatusEvent();
datasource.artworks.saveStudioStatus(model.artworkId(), model.artworkStatusId(), model.studioStatusId).always(completeCallback);
}
function saveCatRaisInternal(completeCallback) {
var model = self.internalArtworkModel();
triggerSaveStudioStatusEvent();
datasource.artworks.saveCatRais(model.artworkId(), model.inclusion(), model.image(), model.details(), model.crReady(), model.selectedVolume.selected.value).always(completeCallback);
}
this.onSaveStudioStatus = function (callback) {
emitter.subscribe("saveStudioStatus", callback);
};
function triggerSaveStudioStatusEvent() {
emitter.publish("saveStudioStatus");
}
this.beginArtworkDeletion = function () {
if (!self.internalArtworkModel().canBeBlanked) {
jAlert(resources.unableToDeleteArtworkMessage, resources.deleteArtworkTitle);
return;
}
self.wipeArtworkModel.beginArtworkDeletion(self.internalArtworkModel().artworkId());
};
this.beginArtworkBlanking = function () {
if (!self.internalArtworkModel().canBeBlanked) {
//jAlert(resources.unableToBlankArtworkMessage, resources.blankArtworkTitle);
app.alerts.appConfirm(resources.unableToBlankArtworkFullyMessage, resources.blankArtworkTitle, function (ok) {
if (ok) {
self.wipeArtworkModel.beginArtworkBlanking(self.internalArtworkModel().artworkId());
}
});
return;
}
self.wipeArtworkModel.beginArtworkBlanking(self.internalArtworkModel().artworkId());
};
this.duplicateArtwork = function () {
if (!self.internalArtworkModel()) {
return;
}
duplicateArtwork(true);
resetModelBeforeDuplication();
if (self.isValid()) {
showErrors();
}
jAlert(resources.duplicateMessage, resources.duplicateTitle);
};
function saveInternal(completeCallback) {
var mapper = app.mappers["fabrication"];
//alert("saving now...");
var unmappedModel = mapper.toJS(self.internalArtworkModel());
if (duplicateArtwork()) {
return saveDuplicatedArtwork(unmappedModel, completeCallback);
}
if (unmappedModel.artworkId) {
return updateArtwork(unmappedModel, completeCallback);
}
return createArtwork(unmappedModel, completeCallback);
}
function saveDuplicatedArtwork(model, completeCallback) {
return datasource.artworks.duplicate(model)
.always(completeCallback)
.fail(function (response) {
jAlert(resources.saveError);
})
.done(function (id) {
triggerArtworkCreatedEvent(id);
duplicateArtwork(false);
self.showCreationInformation(true);
});
}
function updateArtwork(model, completeCallback) {
return datasource.artworks.save(model)
.always(completeCallback)
.fail(function (response) {
jAlert(resources.saveError);
})
.done(function (result) {
if (!result) {
return;
}
var mapper = app.mappers["fabrication"],
mappedModel = mapper.map(result.data);
triggerUpdateEvent(
{
dhCategory: mappedModel.dhCategory(),
refNumber: mappedModel.refNumber(),
computedTitle: mappedModel.computedTitle()
});
self.internalArtworkModel(mappedModel);
});
}
function createArtwork(model, completeCallback) {
return datasource.artworks.save(model)
.always(completeCallback)
.fail(function (response) {
jAlert(resources.saveError);
})
.done(function (id) {
if (id) {
triggerArtworkCreatedEvent(id);
}
});
}
function triggerLoadEvent() {
var model = self.internalArtworkModel();
emitter.publish("load", {
artworkId: model.artworkId() || 0,
dhCategory: model.dhCategory() || "",
refNumber: model.refNumber() || "",
computedTitle: model.computedTitle() || "",
isForSale: model.isForSale
});
}
function triggerArtworkCreatedEvent(artworkId) {
emitter.publish("artwork-created", artworkId);
}
function triggerCategoryChangedEvent() {
emitter.publish("category-changed", {
name: self.internalArtworkModel().dhCategoryName(),
id: self.internalArtworkModel().dhCategoryId()
});
}
function triggerDeleteEvent(e, artworkId) {
emitter.publish("delete", artworkId);
}
function triggerUpdateEvent(data) {
var model = self.internalArtworkModel();
data.isCategoryChanged = model.initialCategoryId !== model.dhCategoryId();
emitter.publish("artwork-updated", data);
}
function showErrors() {
var model = self.internalArtworkModel();
if (model) {
model.errors.showAllMessages();
}
}
function resetModelBeforeDuplication() {
var model = self.internalArtworkModel();
model.refNumber("");
model.computedTitle("");
model.isOnDisplay(false);
model.isOnRestoration(false);
model.salesStatus("Not set");
model.creationDate("");
model.creatorName("");
model.isFramed(false);
model.framedDate("");
model.framedUserName("");
model.framedUserInitials("");
model.framedUserId(null);
model.locations(null);
model.isInsuranceComponent(false);
model.dateWebsiteWork("");
model.dateWebsiteReady("");
model.dateWebsiteUploaded("");
model.dateRemovedFromWebsite("");
model.collectionListing("");
model.salesStatusChangedDate("");
model.salesStatusChangerUserInitials("");
model.salesStatusChangerUserName("");
self.showCreationInformation(false);
}
function triggerBlanked(artworkId) {
emitter.publish("blanked", { artworkId: artworkId, flag: true });
}
(function () {
self.editCategoryModel.onChanged(function (e, categoryId) {
self.internalArtworkModel().dhCategoryId(categoryId);
triggerCategoryChangedEvent();
});
self.editCategoryModel.onCancel(function () {
if (self.isNewArtwork()) {
self.isNewArtwork(false);
app.router.back();
}
});
self.wipeArtworkModel.onDelete(triggerDeleteEvent);
self.wipeArtworkModel.onBlank(function (e, artworkId) {
self.loadArtworkDetails(artworkId);
triggerBlanked(artworkId);
});
})();
};
})(app);
It also uses a mapper:
(function (app, ko) {
app.namespace("mappers");
var s = app.urls.shared,
datasource = app.datasource;
var mapSettings = {
selectedMedium: {
create: function (options) {
return new ListModel({
isRemoteSource: true,
url: s.get('dictionaryUrl'),
listType: datasource.dictionaryTypes.get("medium"),
currentValue: options.data,
nobutton: true,
templateName: "textAreaTemplate"
});
}
},
artist: {
create: function (options) {
return new ListModel({
isRemoteSource: true,
url: s.get('dictionaryUrl'),
listType: datasource.dictionaryTypes.get("artist"),
currentValue: options.data,
onlyPreparedValues: false
});
}
},
manager: {
create: function (options) {
return new ListModel({
isRemoteSource: true,
url: s.get('dictionaryUrl'),
listType: datasource.dictionaryTypes.get("manager"),
currentValue: options.data,
onlyPreparedValues: false
});
}
},
managerStatus: {
create: function (options) {
return new ListModel({
isRemoteSource: true,
url: s.get('dictionaryUrl'),
listType: datasource.dictionaryTypes.get("managerStatus"),
currentValue: options.data,
onlyPreparedValues: false
});
}
},
selectedVolume: {
create: function (options) {
return new ListModel({
isRemoteSource: true,
url: s.get('dictionaryUrl'),
listType: datasource.dictionaryTypes.get("volume"),
currentValue: options.data,
onlyPreparedValues: false,
readonly: !options.parent.isArchiveProvenanceWriter(),
editable: options.parent.isArchiveProvenanceWriter()
});
}
},
salesStatus: {
create: function (options) {
var value = options.data || "Not set";
return ko.observable(value);
}
},
oldReferences: {
create: function (options) {
return ko.observable(options.data);
}
},
copy: ['defaultDhCategoryId', "canBeDeleted", "canBeBlanked", "isForSale"],
ignore: ["dimensions", "dimensionUnits", "selectedMediumTypes", "selectedSeries", "selectedSubSeries", "selectedAkaNames", "selectedWebSiteMediumTypes", 'selectedWebSiteCategoryIds', "locations", "hasInTransitLocations"]
},
unmapSettings = {
ignore: ["selectedMedium", "artist", "manager", "managerStatus", "mediumTypesModel", "dimensionModel", "seriesModel", "subSeriesModel", "akaModel", "webSiteMediumTypesModel", "webSiteCategoriesModel", "selectedVolume"]
},
map = function (json) {
var convertedObject = ko.utils.parseJson(json);
var model = ko.mapping.fromJS(convertedObject, mapSettings);
model.artworkStatusesModel = new ListModel({
isRemoteSource: false,
currentValue: convertedObject.selectedArtworkStatus,
data: convertedObject.artworkStatuses,
//data: filteredSalesStatuses,
onlyPreparedValues: true,
allowNull: false,
readonly: true
});
alert("mooo=" + model.artworkStatuses()[0].name());
alert("mooo=" + model.artworkStatuses()[1].name());
alert("mooo=" + model.artworkStatuses()[2].name());
//alert("mooo=" + model.artworkStatuses()[3].name());
//alert("mooo=" + model.artworkStatuses()[4].name());
model.dhCategoryName = ko.computed(function () {
var categories = model.dhCategories();
for (var i = 0; i < categories.length; i++) {
var category = categories[i];
if (category.id() == model.dhCategoryId()) {
return category.name();
}
}
return "";
});
model.initialCategoryId = convertedObject.dhCategoryId;
model.dimensionModel = new app.models.DimensionModel(convertedObject.dimensions);
ko.utils.arrayForEach(convertedObject.dimensionUnits, function (unit) {
model.dimensionModel.units.push(unit);
});
model.locations = ko.observable(convertedObject.locations ? {
archivedLocations: $.map(convertedObject.locations, function (elem) {
return elem.isArchived ? elem : null;
}),
activeLocations: $.map(convertedObject.locations, function (elem) {
return elem.isArchived ? null : elem;
}),
hasInTransitLocations: convertedObject.hasInTransitLocations
} : convertedObject.locations);
model.mediumTypesModel = new app.models.MultilistModel(convertedObject.selectedMediumTypes, { url: s.get("mediumTypesUrl") });
model.seriesModel = new app.models.MultilistModel(convertedObject.selectedSeries, { url: s.get("seriesUrl") });
model.subSeriesModel = new app.models.MultilistModel(convertedObject.selectedSubSeries, { url: s.get("subSeriesUrl") });
model.akaModel = new app.models.MultilistModel(convertedObject.selectedAkaNames, { url: s.get("akaUrl") });
model.webSiteMediumTypesModel = new app.models.MultilistModel(convertedObject.selectedWebSiteMediumTypes, { url: s.get("webSiteMediumTypeUrl") });
model.webSiteCategoriesModel = new app.models.MultilistModel(convertedObject.selectedWebSiteCategories, { url: s.get("webSiteCategoryUrl") });
model.isStudioStatusVisible = ko.computed(function () {
var foundStatuses = ko.utils.arrayFilter(model.artworkStatuses(), function (status) {
return status.id() == model.artworkStatusId();
});
var currentStatus = foundStatuses[0];
if (currentStatus) {
return currentStatus.name().toLowerCase() == "in progress";
}
return false;
});
addValidationOptions(model);
return model;
},
toJS = function (artwork) {
var result = ko.mapping.toJS(artwork, unmapSettings);
result.artist = artwork.artist.toJS();
result.manager = artwork.manager.toJS();
result.managerStatus = artwork.managerStatus.toJS();
result.selectedMedium = artwork.selectedMedium.toJS();
result.selectedVolume = artwork.selectedVolume.toJS();
result.dimensions = artwork.dimensionModel.toJS();
result.selectedMediumTypes = artwork.mediumTypesModel.toJS();
result.selectedSeries = artwork.seriesModel.toJS();
result.selectedSubSeries = artwork.subSeriesModel.toJS();
result.selectedAkaNames = artwork.akaModel.toJS();
result.selectedWebSiteMediumTypes = artwork.webSiteMediumTypesModel.toJS();
result.selectedWebSiteCategories = artwork.webSiteCategoriesModel.toJS();
return result;
};
function isValidationRequired(model) {
var artworkStatus = ko.utils.unwrapObservable(model.artworkStatusId);
var dhCategory = ko.utils.unwrapObservable(model.dhCategoryId);
return artworkStatus == app.global.dictionary.get("compiteArtworkStatus")
&& dhCategory != app.global.dictionary.get("ignoreDHCatigory");
}
function addValidationOptions(model) {
model.artworkStatusId.extend({ required: true });
model.title.extend({ required: true });
model.artist.selected.value.extend({ required: true });
model.startYear.extend({
lessEqualThan: {
params: model.endYear,
onlyIf: function () {
return (model.endYear() != undefined && model.endYear() != null);
},
message: 'From Date should be less or equal than a To Date'
}
});
model.endYear.extend({
required: {
params: true,
onlyIf: function () {
return isValidationRequired(model);
},
message: "To Date field is required"
}
});
model.selectedMedium.selected.value.extend({
required: {
params: true,
onlyIf: function () {
return isValidationRequired(model);
},
message: "Medium is required"
}
});
model.mediumTypesModel.hasValue.extend({
equal: {
params: true,
onlyIf: function () {
return isValidationRequired(model);
},
message: "Medium Type is required"
}
});
model.akaModel.hasValue.extend({
equal: {
params: true,
onlyIf: function () {
return isValidationRequired(model);
},
message: "Aka is required"
}
});
model.isInsuranceComponent.extend({
equal: {
params: true,
onlyIf: function () {
return isValidationRequired(model);
},
message: "At least 1 Insurance component should be chosen"
}
});
model.dimensionModel.hasDimensions.extend({
equal: {
params: true,
onlyIf: function () {
return isValidationRequired(model);
},
message: "The Dimension fields should be filled"
}
});
model.errors = ko.validation.group(model, { deep: true });
}
app.mappers.fabrication = {
settings: mapSettings,
map: map,
toJS: toJS
};
})(app, ko);
Where I have the alerts, the items are in the right order, so somewhere they are getting sorted but cant find out where?!
I hope someone can help?
It would be really appreciated.
Many thanks,
David.
Related
how i make a condition with ajax and asp mvc
I want to put a condition if the user want to add a second appointment he receives an alert function SaveEvent(data) { $.ajax({ type: "POST", url: '/home/SaveEvent', data: data, success: function (data) { if (data.status) { //Refresh the calender FetchEventAndRenderCalendar(); $('#myModalSave').modal('hide'); } }, error: function () { alert('Failed'); } }) } }) this is my code in controller : public JsonResult SaveEvent(Event e) { var status = false; if (e.EventID > 0) { //Update the event var v = db.Events.Where(a => a.EventID == e.EventID).FirstOrDefault(); if (v != null) { v.EventTitle = e.EventTitle; v.StartDate = e.StartDate; v.EndDate = e.EndDate; v.EventDescription = e.EventDescription; v.EventID = e.EventID; v.ThemeColor = e.ThemeColor; } else db.Events.Add(e); db.SaveChanges(); status = true; } i want to make the user add one time his event and receive an alert i try but not work
I think i can help: if(Session["appointment"] != "ok")<> { if (e.EventID > 0) { //Update the event var v = db.Events.Where(a => a.EventID == e.EventID).FirstOrDefault(); if (v != null) { v.EventTitle = e.EventTitle; v.StartDate = e.StartDate; v.EndDate = e.EndDate; v.EventDescription = e.EventDescription; v.EventID = e.EventID; v.ThemeColor = e.ThemeColor; } else db.Events.Add(e); db.SaveChanges(); Session["appointment"] = "ok"; return JSON(new{appointment="ok"}); } }else { return JSON(new {appointment="no-good"); } and controller: function SaveEvent(data) { $.ajax({ type: "POST", url: '/home/SaveEvent', data: data, success: function(data) { if (data.appointment == "ok") { //Refresh the calender FetchEventAndRenderCalendar(); $('#myModalSave').modal('hide'); } else { your msg error here } }, error: function() { alert('Failed'); } }) } }) dont not forget Session.Clear(); as the user logs out
How to add my textbox item in the table? in master detail form
I am using MVC to create my Master Detail form, i have tried this to add my detail record in the to show my detail record in the form so that when user click Add button detail data itself shows in a table. JQUERY is not working This is my View: #section script{ //date picker $(function () { $('#orderDate').datepicker({ datepicker: 'mm-dd-yy' }); }); $(document).ready(function() { var orderItems = []; //Add Button click function $('#add').click(function () { //Chk Validation var isValidItem = true; if ($('#itemName').val().trim() == '') { isValidItem = false; $('#itemName').siblings('span.error').css('visibility', 'vissible') } else { $('#itemName').siblings('span.error').css('visibility', 'hidden') } if (!($('#quantity').val().trim() !== '' && !isNaN($('#dvch_nar').val().trim()))) { isValidItem = false; $('#quantity').siblings('span.error').css('visibility', 'vissible') } else { $('#quantity').siblings('span.error').css('visibility', 'hidden') } if (!($('#itemName').val().trim() !== '' && !isNaN($('#dvch_cr_amt').val().trim()))) { isValidItem = false; $('#itemName').siblings('span.error').css('visibility', 'vissible') } else { $('#itemName').siblings('span.error').css('visibility', 'hidden') } if (!($('#rate').val().trim() !== '' && !isNaN($('#dvch_cr_amt').val().trim()))) { isValidItem = false; $('#rate').siblings('span.error').css('visibility', 'vissible') } else { $('#rate').siblings('span.error').css('visibility', 'hidden') } //add item to list if valid if (isValidItem) { orderItems.push( { ItemName: $('#itemName').val().trim(), Quantity:parseInt$('#quantity').val().trim(), Rate: parseInt$('#rate').val().trim(), Total: parseInt($('#quantity').val().trim())* parseFloat($('#rate').val().trim()) }); //clear fields $('#itemName').val('').focus(); $('#quantity').val(''); $('#rate').val(''); } //populate order item GeneratedItemsTable(); } ); //save button click function $('#submit').click(function () { //validation order var isAllValid = true; if(orderItems.length=0) { $('#orderItems').html('<span style="color:red;">Please add another item</span>') isAllValid = false; } if ($('#orderNo').val().trim() == '') { $('#orderNo').siblings('span.error').css('visibility', 'visible') isAllValid = false; } else { $('#orderNo').siblings('span.error').css('visibility', 'hidden') } if ($('#orderDate').val().trim() == '') { $('#orderDate').siblings('span.error').css('visibility', 'visible') isAllValid = false; } else { $('#orderDate').siblings('span.error').css('visibility', 'hidden') } //if ($('') //save if valid if (isAllValid){ var data={ Date: $('#orderNo').val().trim(), Remarks: ('#orderDate').val().trim(), Description:$('description').val().trim(), orderDetails:orderItems } } $(this).val("Please Wait..."); $.ajax( { url: "/Home/SaveOrder", type:"post", data:JSON.stringify(data), dataType:"application/json", success:function(d){ //check is successfully save to database if(d.status==true) { //will send status from server side alert('successfully done.'); //clear form orderItems=[]; $('#orderNo').val(''); $('#orderDate').val(''); $('#orderItems').empty(); } else{ alert('Failed'); } }, error :function(){ alert('Error:Please Try again.'); } } ); }); //function for show added item function GeneratedItemsTable() { if(orderItems.length>0) { var $table = $('<table/>'); $table.append('<thead><tr><th>Item</th><th>Quantity</th><th>Rate</th><th>Total</th></tr></thead>') var $tboday = $('<tbody/>'); $.each(orderItems,function(i,val) { var $row=$('<tr/>'); $row.append($('<tr/>').html(val.ItemName)) $row.append($('<tr/>').html(val.Quantity)) $row.append($('<tr/>').html(val.Rate)) $row.append($('<tr/>').html(val.Total)) $tboday.append($row); }); $table.append($tboday); $('#orderItems').html($table); } } } ); </script> } thanks for quick response
Try this <script src="//code.jquery.com/ui/1.11.4/jquery-ui.js"></script> <script> //Date Picker $(function () { $('#orderDate').datepicker({ dateFormat : 'mm-dd-yy' }); }); $(document).ready(function () { var orderItems = []; //Add button click function $('#add').click(function () { //Check validation of order item var isValidItem = true; if ($('#itemName').val().trim() == '') { isValidItem = false; $('#itemName').siblings('span.error').css('visibility', 'visible'); } else { $('#itemName').siblings('span.error').css('visibility', 'hidden'); } if (!($('#quantity').val().trim() != '' && !isNaN($('#quantity').val().trim()))) { isValidItem = false; $('#quantity').siblings('span.error').css('visibility', 'visible'); } else { $('#quantity').siblings('span.error').css('visibility', 'hidden'); } if (!($('#rate').val().trim() != '' && !isNaN($('#rate').val().trim()))) { isValidItem = false; $('#rate').siblings('span.error').css('visibility', 'visible'); } else { $('#rate').siblings('span.error').css('visibility', 'hidden'); } //Add item to list if valid if (isValidItem) { orderItems.push({ ItemName: $('#itemName').val().trim(), Quantity: parseInt($('#quantity').val().trim()), Rate: parseFloat($('#rate').val().trim()), TotalAmount: parseInt($('#quantity').val().trim()) * parseFloat($('#rate').val().trim()) }); //Clear fields $('#itemName').val('').focus(); $('#quantity,#rate').val(''); } //populate order items GeneratedItemsTable(); }); //Save button click function $('#submit').click(function () { //validation of order var isAllValid = true; if (orderItems.length == 0) { $('#orderItems').html('<span style="color:red;">Please add order items</span>'); isAllValid = false; } if ($('#orderNo').val().trim() == '') { $('#orderNo').siblings('span.error').css('visibility', 'visible'); isAllValid = false; } else { $('#orderNo').siblings('span.error').css('visibility', 'hidden'); } if ($('#orderDate').val().trim() == '') { $('#orderDate').siblings('span.error').css('visibility', 'visible'); isAllValid = false; } else { $('#orderDate').siblings('span.error').css('visibility', 'hidden'); } //Save if valid if (isAllValid) { var data = { OrderNo: $('#orderNo').val().trim(), OrderDate: $('#orderDate').val().trim(), //Sorry forgot to add Description Field Description : $('#description').val().trim(), OrderDetails : orderItems } $(this).val('Please wait...'); $.ajax({ url: '/Home/SaveOrder', type: "POST", data: JSON.stringify(data), dataType: "JSON", contentType: "application/json", success: function (d) { //check is successfully save to database if (d.status == true) { //will send status from server side alert('Successfully done.'); //clear form orderItems = []; $('#orderNo').val(''); $('#orderDate').val(''); $('#orderItems').empty(); } else { alert('Failed'); } $('#submit').val('Save'); }, error: function () { alert('Error. Please try again.'); $('#submit').val('Save'); } }); } }); //function for show added items in table function GeneratedItemsTable() { if (orderItems.length > 0) { var $table = $('<table/>'); $table.append('<thead><tr><th>Item</th><th>Quantity</th><th>Rate</th><th>Total</th><th></th></tr></thead>'); var $tbody = $('<tbody/>'); $.each(orderItems, function (i, val) { var $row = $('<tr/>'); $row.append($('<td/>').html(val.ItemName)); $row.append($('<td/>').html(val.Quantity)); $row.append($('<td/>').html(val.Rate)); $row.append($('<td/>').html(val.TotalAmount)); var $remove = $('Remove'); $remove.click(function (e) { e.preventDefault(); orderItems.splice(i, 1); GeneratedItemsTable(); }); $row.append($('<td/>').html($remove)); $tbody.append($row); }); console.log("current", orderItems); $table.append($tbody); $('#orderItems').html($table); } else { $('#orderItems').html(''); } } }); </script>
WebSocket connection from node module to chrome extension closing automatically in Windows 10
I use https://www.npmjs.com/package/ws npm package to communicate between my npm module and my chrome extension. Connection is getting opened, but closes in few seconds. I researched the topic and I found that I should send messages back and forth between webSocket server and Client to keep it alive. I am sanding this messages every 2 sec but my connection is still closing. Interesting stuff is that close event fires on node module side only, while chrome plugin does not fire the event. Here is a code from my chrome extension: function myPlugin() { myPlugin.prototype.socket = false; myPlugin.prototype.isConnected = false; myPlugin.prototype.port = false; myPlugin.prototype.pluginName = "Tab Reloader"; myPlugin.prototype.init(); }; myPlugin.prototype = { initListeners: function () { chrome.browserAction.onClicked.addListener(function(tab) { if (!this.isConnected) { this.connectToServer(); } else { this.disconnectFromServer(); } }.bind(this)); }, setPort: function () { chrome.storage.sync.get(['port'], function(items) { this.port = items.port || '8001'; }.bind(this)); }, getTabsToReload: function (callback) { var tabsToReload = []; chrome.storage.sync.get(['hostName'], function(items) { if (!items.hostName) { chrome.tabs.query({active: true}, function(tabs) { tabs.forEach(function (tab) { tabsToReload.push(tab); }); callback(tabsToReload); }); } else { chrome.tabs.query({}, function(tabs) { tabs.forEach(function (tab) { if (tab.url.indexOf(items.hostName) != -1) { tabsToReload.push(tab); } }); callback(tabsToReload); }); } }.bind(this)); }, initSocketListeners: function () { var fileExtIndex, fileExt, file; this.socket.onmessage = function (ev) { file = ev.data.toString(); fileExtIndex = file.lastIndexOf('.') + 1; fileExt = file.slice(fileExtIndex), fileNameStandardize = file.replace(/\\/g, '\/'), indexOfLastSeparator = fileNameStandardize.lastIndexOf('/') + 1, fileName = file.slice(indexOfLastSeparator); if (file != 'pong' && file.indexOf('connected to server!!!') == -1) { //do stuff } else { if (file == 'pong') { this.isAlive = true; } } }.bind(this); this.socket.addEventListener('close', function (ev) { console.log('connection Closed') clearInterval(this.aliveInterval); chrome.browserAction.setIcon({ path: { "16": "img/icon_disabled_16.png", "24": "img/icon_disabled_24.png", "32": "img/icon_disabled_32.png" } }); this.isConnected = false; }.bind(this)); }, connectToServer: function () { this.socket = new WebSocket("ws://localhost:" + this.port); this.socket.addEventListener('error', function (ev) { this.isConnected = false; alert('Error connecting to websocket server, make sure it\'s running and port ' + this.port + ' is not occupied by other process'); }.bind(this)); this.socket.addEventListener('open', function (ev) { this.isConnected = true; this.socket.send(this.pluginName + ' connected to server!!!'); this.initSocketListeners(); this.stayConnected(); this.isAlive = true; this.aliveInterval = setInterval(function () { this.checkIfAlive(); }.bind(this), 2500); this.getTabsToReload(function (tabsToReload) { tabsToReload.forEach(function (tab) { chrome.tabs.update(tab.id, {url: tab.url}); }); }); chrome.browserAction.setIcon({ path: { "16": "img/icon_active_16.png", "24": "img/icon_active_24.png", "32": "img/icon_active_32.png" } }); }.bind(this)); }, disconnectFromServer: function () { this.socket.close(); }, stayConnected: function () { setTimeout(function () { this.socket.send('ping'); if (this.isConnected) { this.stayConnected(); } }.bind(this), 1000); }, checkIfAlive: function () { this.isAlive = false; setTimeout(function () { console.log(this.isAlive) if (!this.isAlive) { console.log(this.isAlive) this.disconnectFromServer(); } }.bind(this), 2000); }, init: function () { this.setPort(); this.initListeners(); } } window.onload = new myPlugin(); And here is my node module code: "use strict"; //var WebSocketServer = require('websocketserver'); //var WebSocketServer = require("nodejs-websocket") var WebSocket = require('ws'); class MyModule { constructor(options) { this.options = options; this.server = false; this.pluginName = 'Some'; this.isConnected = false; this.connection = false; this.init(); return this.refreshTab.bind(this); } init() { var port = this.options ? this.options.port : false; this.server = new WebSocket.Server({port: port || 8001}); this.server.on('connection', (websocket) => { console.log('Connection open'); this.websocket = websocket; this.isConnected= true; this.initListeners(); }); } refreshTab(uploadedFiles) { if (this.isConnected) { if (Array.isArray(uploadedFiles)) { uploadedFiles.forEach(function (el) { this.websocket.send(el.toString()); }.bind(this)); } else { this.websocket.send(uploadedFiles ? uploadedFiles.toString() : 'reload'); } } else { console.log('You are not connected to server yet.'); } } initListeners() { this.websocket.on('message', (message) => { if (message == 'ping') { this.websocket.send('pong'); } }); this.websocket.on('close', () => { this.isConnected = false; console.log(this.pluginName + ' connection is closed'); }); } }; module.exports = MyModule; Appreciate any help, Thanks in advance.
So my problem was actually in manifest.json "background": { "scripts": ["js/tab_reloader.js"], "persistent": false } "persistent" was set to false, it transformed my Background page into Event Page. And event page is unloaded from memory after a period of time, which was killing the connection. After I set "persistent" to true the problem got fixed.
Backbone collection fetch error with no information
I have a strange problem with the fetch of a backbone collection I am working with. In one particular instance of my code I perform a fetch (exactly how I do it in other areas of the code which all work fine), the fetch never seems to make it to the server and the developer tools shows the request as red with the word (canceled) in the status/text field. I've walked this through into the backbone sync method and I see the $.ajax being built and everything looks fine. Has anyone run into this problem? here is my code if it helps, this is a function that calls two .ashx services to first check for a file's existence then to open it. The part that isn't working for me is the "me.collection.fetch(). openDocument: function () { var me = this, fileId = me.model.get('id'), userId = Dashboard.Data.Models.UserModel.get("UserInfo").User_ID, fileRequest = '/genericHandlers/DownloadFile.ashx?id=' + fileId + '&userId=' + userId, fileCheck = '/genericHandlers/CheckFileExistance.ashx?id=' + fileId + '&userId=' + userId; //hide tooltip me.hideButtonTooltips(); // Check for file existance $.ajax({ url: fileCheck }) .done(function (data) { if (data && data === "true") { document.location.href = fileRequest; me.collection.fetch(); } else if (!!data && data === "false") { "This file is no longer available.".notify('error'); } }) .fail(function (data) { "Something went wrong during the File Existance check".notify('error'); "Something went wrong during the File Existance check".log(userId, 'error', 'Docs'); }); }, my collection: // docsCollection.js - The collection of ALL the documents available to a given user // Document Collection Dashboard.Collections.DocsCollection = Backbone.Collection.extend({ model: Dashboard.Models.DocumentUploadModel, url: function () { return 'apps/docs/Docs/' + this.userId; }, initialize: function (options) { this.userId = options.userId; this.deferredFetch = this.fetch(); }, comparator: function (model) { return -(new Date(model.get('expirationDate'))); }, getDaysSinceViewedDocuments: function () { return this.filter(function (model) { return model.get('daysSinceViewed') !== null; }); }, getNewDocuments: function () { return this.filter(function (model) { return model.get('isNew'); }); }, getExpiredDocuments: function () { return this.filter(function (model) { return model.get('isExpired'); }); } }); and my model: Dashboard.Models.DocumentUploadModel = Backbone.Model.extend({ defaults: { fileArray: [], name: '', description: '', accesses: [], tags: [], expirationDate: '' }, initialize: function () { this.set({ userId: Dashboard.Data.Models.UserModel.get("UserInfo").User_ID, expirationDate: (this.isNew()) ? buildExpirationDate() : this.get('expirationDate') }, { silent: true }); function buildExpirationDate() { var date = new Date((new Date()).getTime() + 24 * 60 * 60 * 1000 * 7), dateString = "{0}/{1}/{2}".format(date.getMonth() + 1, date.getDate(), date.getFullYear()); return dateString; } }, firstFile: function () { return this.get('fileArray')[0]; }, validate: function (attributes) { var errors = []; if (attributes.name === '' || attributes.name.length === 0) errors.push({ input: 'input.txtName', message: "You must enter a name." }); if (attributes.description === '' || attributes.description.length === 0) errors.push({ input: 'textarea.taDescription', message: "You must enter a description." }); if (errors.length > 0) return errors; return; }, sync: function (method, model, options) { var formData = new FormData(), files = model.get("fileArray"), $progress = $('progress'), success = options.success, error = options.error; // Nothing other than create or update right now if (method !== "create" && method !== "update") return; // Build formData object formData.append("name", model.get("name")); formData.append("description", model.get("description")); formData.append("accesses", model.get("accesses")); formData.append("tags", model.get("tags")); formData.append("expirationDate", model.get("expirationDate")); formData.append("userId", model.get("userId")); formData.append("isNew", model.isNew()); // if not new then capture id if (!model.isNew()) formData.append('id', model.id); for (var i = 0; i < files.length; i++) { formData.append('file', files[i]); } xhr = new XMLHttpRequest(); xhr.open('POST', '/genericHandlers/UploadDocsFile.ashx'); xhr.onload = function () { if (xhr.status === 200) { if (success) success(); } else { if (error) error(); } } if ($progress.length > 0) { xhr.upload.onprogress = function (evt) { var complete; if (evt.lengthComputable) { // Do the division but if you cant put 0 complete = (evt.loaded / evt.total * 100 | 0); $progress[0].value = $progress[0].innerHTML = complete; } } } xhr.send(formData); }, upload: function (changedAttrs, options) { this.save("create", changedAttrs, options); } });
You're assigning a value to document.location.href before you try to fetch your collection: document.location.href = fileRequest; me.collection.fetch(); Changing document.location.href will change the whole page and in the process, any currently running JavaScript will get shutdown so I wouldn't expect your me.collection.fetch() to ever get executed.
Adding new row to SlickGrid
I have a slickgrid using the dataview. From what I can tell, the grid's add new row event isn't called until after the first new row field's editor is complete. The field I was editing is a custom editor that uses a input box with autocomplete and save the selected item "value" to the grid source data. The problem is the new "item" source isn't created until the grid add new row event is fired. I know there is a way around this and just want to know what is the best way to solve for this. Thanks. //Add new row event grid.onAddNewRow.subscribe(function (e, args) { var item = args.item; addnewid = addnewid - 1; item.inventorytransferdetailid = addnewid; $.extend(item, args.item); dataView.addItem(item); }); // Custom editor function Suggest2(args) { var $input; var defaultValue; var scope = this; this.init = function () { $input = $("<INPUT type=text class='editor-text' />") $input.width = args.column.width; $input.appendTo(args.container); $input.focus(); $input.bind("keydown.nav", function (e) { if (e.keyCode === $.ui.keyCode.LEFT || e.keyCode === $.ui.keyCode.RIGHT) { e.stopImmediatePropagation(); } else if ($input.val().length > 0) { $.ajax({ type: "GET", url: "http://localhost:11111/GetProducts/" + $input.val(), dataType: "json", data: "{}", contentType: "application/json; charset=utf-8", success: function (data) { $input.autocomplete({ source: data, select: function (event, ui) { var v = ui.item.value; var l = ui.item.label; //Set "display" field with label args.item[args.column.field] = l; this.value = l; //Set "hidden" id field with value args.item["productid"] = v; return false; } }); }, error: function (XMLHttpRequest, textStatus, errorThrown) { alert(textStatus); } }); } }) }; this.destroy = function () { $input.remove(); }; this.focus = function () { $input.focus(); }; this.getValue = function () { return $input.val(); }; this.setValue = function (val) { $input.val(val); }; this.loadValue = function (item) { defaultValue = item[args.column.field] || ""; $input.val(defaultValue); $input[0].defaultValue = defaultValue; $input.select(); }; this.serializeValue = function () { return $input.val(); }; this.applyValue = function (item, state) { //item[args.column.field] = state; }; this.isValueChanged = function () { return (!($input.val() == "" && defaultValue == null)) && ($input.val() != defaultValue); }; this.validate = function () { if (args.column.validator) { var validationResults = args.column.validator($input.val()); if (!validationResults.valid) { return validationResults; } } return { valid: true, msg: null }; }; this.init(); }
You can try below code. function add_new_row(){ item = { "id": (Math.round(Math.random()*-10000)) }; data_view.insertItem(0, item); } Then, bind with button. <button onclick="add_new_row()">Add Row</button>