We have a CMS so I don't have access to the header of the HTML page which gets rendered for our extjs implementation. So I had to make a workaround which is like this:
Ext.local = {};
var lang = {
initLang: function (revisionNr) {
var local = localStorage.getItem('localLang')
if (!local) {
AjaxHandlerByClass('ajax/lang/webuser/init', {}, this.loadLangRemote);
} else {
local = JSON.parse(local);
if (local.revisionNr == config.revisionNr && local.lang == config.lang) {
console.log('loading local lang variables');
if (local.date < new Date().getTime() - (24 * 60 * 60 * 1000) * 2) {//2 day caching time before retry
delete window.localStorage.localLangBackup;
}
this.loadLangLocal(local);
} else {
delete window.localStorage.localLang;
AjaxHandlerByClass('ajax/lang/webuser/init', {}, this.loadLangRemote);
}
}
},
loadLangRemote: function (data) {
data.revisionNr = config.revisionNr;
data.lang = config.lang;
data.date = new Date().getTime();
lang.loadLangLocal(data);
localStorage.setItem('localLang', JSON.stringify(data));
},
loadLangLocal: function (data) {
var jsElm = document.createElement("script");
jsElm.type = "application/javascript";
jsElm.src = 'js/freetext-deploy.min.js?rev={/literal}{$revisionNr}{literal}';
document.getElementsByTagName('head')[0].appendChild(jsElm);
Ext.Date.defaultFormat = 'd-m-Y';
if (!debug) {
Ext.Loader.config.disableCaching = true;
}
Ext.application({
name: 'freetextOrder',
appFolder: 'modules/extjs/freetextOrder/app',
controllers: [
'Main'
],
launch: function () {
var freetextOrder = Ext.create('Ext.container.Container', {
renderTo: Ext.get('freetextOrderDiv'),
layout: 'fit',
id: 'catalogAdministrationDiv_ext',
height: 800,
cls: 'x-dig-override',
items: [Ext.create('freetextOrder.view.base.MainView', {})],
layout:'fit'
});
}
});
Ext.local = data;
}
};
lang.initLang();
The problem I'm having is that the minified version gets ignored completely. I see it load on the http request but extjs ignores them.... even though I can see the objects are being created after include (via console log)
Anyone any idea how I can achieve this?
as i see none found the answer so i post my own here wich i came up with.
Since i could for the love of god not load the damn thing i refactored the loader and exported it into a Js. file. wich i reqired and called later on in code.
exported lang.js file:
Ext.define('Lang', {
singleton: true,
ApplicationConf: null,
Launch: function (launchConfig) {
this.ApplicationConf = launchConfig;
var local = localStorage.getItem('localLang');
var me = this;
this.loadLangRemote = function (data) {
debugger;
data.revisionNr = config.revisionNr;
data.lang = config.lang;
data.date = new Date().getTime();
me.loadLangLocal(data);
localStorage.setItem('localLang', JSON.stringify(data));
};
this.loadLangLocal = function (data) {
Ext.local = data;
Ext.lang = function (langId) {
if (Ext.local[langId]) {
return Ext.local[langId];
}
delete window.localStorage.localLang;
localStorage.setItem('localLangBackup', true);
return langId;
}
Ext.application(me.ApplicationConf);
};
if (!local) {
Ext.Ajax.request({
url: 'ajax/lang/webuser/init',
params: {
sid: sid,
},
success: function (data) {
debugger;
me.loadLangRemote(Ext.JSON.decode(data.responseText));
}
})
} else {
local = JSON.parse(local);
if (local.revisionNr == config.revisionNr && local.lang == config.lang) {
console.log('loading local lang variables');
if (local.date < new Date().getTime() - (24 * 60 * 60 * 1000) * 2) {//2 day caching time before retry
delete window.localStorage.localLangBackup;
}
debugger;
me.loadLangLocal(local);
} else {
delete window.localStorage.localLang;
Ext.Ajax.request({
url: 'ajax/lang/webuser/init',
params: {
sid: sid,
},
success: function (data) {
me.loadLangRemote(Ext.JSON.decode(data.responseText));
}
})
}
}
},
})
And IMPORTANT was to add the
Ext.onReady(function () {
Lang.Launch({
name: 'catalogAdministration',
appFold....
To the call of the Launch function in code, bacause it would have been not defined at run time. i added the file to the minified file first and call the Lang.Launch instead Ext.Application.
Hope somone has use of my solution :)
Related
I am using Google Calendar JavaScript API.It works fine for single account.Problem is when user is logged-in into two of my gmail accounts, It asks user every time to select which account user want to use.
I want API to remember my last selection at least for the session or most preferably till user disconnect himself.
Here is my JS file.
var clientId = $("#CalendarClientId").val();
var scopes = 'https://www.googleapis.com/auth/calendar';
var objEventList = [];
var calendarIdAtt;
function InitilizeCalendarAPI() {
// Step 2: Reference the API key
window.setTimeout(checkAuth, 5);
}
function CheckGoogleCalAuth() {
gapi.auth.authorize({ client_id: clientId, scope: scopes }, HandleAuthCallBack);
}
function checkAuth() {
gapi.auth.authorize({ client_id: clientId, scope: scopes }, HandelCalAuthResult);
}
function CheckAuthentication() {
gapi.auth.checkSessionState({ client_id: clientId }, CheckAuthCallback);
}
function CheckAuthCallback(loginDataCallback) {
if (loginDataCallback == false) {
checkAuth();
$("#googleAuthorize-Button").hide();
}
}
function HandelCalAuthResult(authResult) {
if (authResult && !authResult.error) {
/*authorizeButton.style.visibility = 'hidden';*/
$("#googleAuthorize-Button").hide();
if ($("#googleConnected").length > 0) {
$("#googleConnected").show();
}
/*bind listing of google calendar name in addevent page*/
if ($("#divGoogleCalendarNameList").length > 0) {
GetListOfCalendarNameFromGoogle();
}
} else {
$("#googleAuthorize-Button").show();
/*authorizeButton.style.visibility = '';*/
if ($("#googleConnected").length > 0) {
$("#googleConnected").hide();
}
}
if ($('#googleAuthorized-Button').length > 0) {
$("#googleAuthorize-Button").hide();
$('#googleAuthorized-Button').show();
$('#calenderSettingIcon').attr('data-original-title', 'Connected To Google');
}
}
function CheckAutheForEventList() {
gapi.auth.checkSessionState({ client_id: clientId }, CheckAuthCallbackListEvent);
}
function CheckAuthCallbackListEvent(loginDataCallback)
{
gapi.auth.authorize({ client_id: clientId, scope: scopes }, LoadEventListinAPI);
}
function checkAuthEventList() {
ConfirmConnectionToGoogleCalendar(function (isConnect) {
if (isConnect) {
gapi.auth.authorize({ client_id: clientId, scope: scopes }, LoadEventListinAPI);
}
});
}
function LoadEventListinAPI() {
gapi.client.load('calendar', 'v3', GetAllCalendar);
}
function GetAllCalendar() {
gapi.client.load('calendar', 'v3', GetCalendarAndTheirEvents);
}
function GetCalendarAndTheirEvents() {
objEventList = [];
try {
var objDate = GetMinAndMaxDate();
var finalMinDate = (objDate.MinDate).toISOString();;
var finalMaxDate = (objDate.MaxDate).toISOString();;
var request = gapi.client.calendar.calendarList.list();
var tempCount = 0;
request.execute(function (resp) {
var calLength = resp.items.length;
$.each(resp.items, function (index, item) {
if (item.accessRole == "owner") {
try {
calendarIdAtt = item.id;
var request = gapi.client.calendar.events.list({
'calendarId': item.id,
'showDeleted': false,
'singleEvents': true,
'orderBy': 'startTime',
'maxResults': 100,
'timeMin': finalMinDate,
'timeMax': finalMaxDate
});
request.execute(function (resp) {
tempCount = tempCount + 1;
var events = resp.items;
if (events.length > 0) {
objEventList.push(events);
}
if (tempCount == calLength) {
//Binding Kendo Scheduler with Google Calenda Events
var eventsList = BindEventToCalendar();
LoadEventsScheduler(eventsList);
}
});
}
catch (error) {
tempCount = tempCount + 1;
if (tempCount == calLength) {
BindEventToCalendar();
}
}
}
else {
tempCount = tempCount + 1;
if (tempCount == calLength) {
BindEventToCalendar();
}
}
});
});
return objEventList;
}
catch (exception) {
BindEventToCalendar();
return null;
}
}
//Function will display google calendar events in the Kendo Scheduler
function LoadEventsScheduler(eventsList) {
//This will retrun all the google calendar events to the server side for the scheduler
var request = {
EventsList: eventsList, CalendarAccount: calendarIdAtt
};
$.ajax({
type: "POST",
data: JSON.stringify(request),
url: $_SetEventScheduler,
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (msg) {
var data;
if (msg.hasOwnProperty("d")) {
data = msg.d;
}
else
data = msg;
if (data.success) {
$("#scheduler").data("kendoScheduler").dataSource.read();
}
else {
}
}
});
}
I noticed that API show me logged in but calendar is not stored in case of multiple accounts,so it asks me again to select the account.
Summary: I want to save the complete scenario (may be calendar_id or any unique identifier) which can tell API which account and which calendar should be picked up.
If you need more details, please let me know.
I simply used the auth2 implementation and it is working perfect.
Basically current session state function do not work properly in old API. That's why it was asking every time for selecting the account and calendar.
i'm using Angularjs NgTable, with pagination inside of a tab provided by Angularjs Material. this works fine. i've used it in many parts of my project and realoaded it many times in differents parts.
but in this case, i can't reload the tables. and don't know what is the problem or how shoud do the reload.
i have in DistribucionController this functions:
$scope.listaFacturaTierra = function () {
var idFactura = $stateParams.idFactura;
$facturaTierra = distribucionService.getStockTierra(idFactura);
$facturaTierra.then(function (datos) {
$scope.facturaTierra = datos.data;
var data = datos;
$scope.tableFacturaTierra = new NgTableParams({
page: 1,
count: 8
}, {
total: data.length,
getData: function (params) {
data = $scope.facturaTierra;
params.total(data.length);
if (params.total() <= ((params.page() - 1) * params.count())) {
params.page(1);
}
return data.slice((params.page() - 1) * params.count(), params.page() * params.count());
}});
});
};
$scope.listaFacturaBebelandia = function () {
var idFactura = $stateParams.idFactura;
$facturaBebelandia = distribucionService.getStockBebelandia(idFactura);
$facturaBebelandia.then(function (datos) {
var data = datos.data;
$scope.facturaBebelandia = datos.data;
$scope.tableFacturaBebelandia = new NgTableParams({
page: 1,
count: 10
}, {
total: data.length,
getData: function (params) {
data = $scope.facturaBebelandia;
params.total(data.length);
if (params.total() <= ((params.page() - 1) * params.count())) {
params.page(1);
}
return data.slice((params.page() - 1) * params.count(), params.page() * params.count());
}});
});
};
$scope.listaFacturaLibertador = function () {
var idFactura = $stateParams.idFactura;
$facturaLibertador = distribucionService.getStockLibertador(idFactura);
$facturaLibertador.then(function (datos) {
var data = datos.data;
$scope.facturaLibertador = datos.data;
$scope.tableFacturaLibertador = new NgTableParams({
page: 1,
count: 10
}, {
total: data.length,
getData: function (params) {
data = $scope.facturaLibertador;
params.total(data.length);
if (params.total() <= ((params.page() - 1) * params.count())) {
params.page(1);
}
return data.slice((params.page() - 1) * params.count(), params.page() * params.count());
}});
});
};
they are displayed fine, and the pagination is working as well.
i add elements using Angularjs Material ngDialog using 3 functions the make the process.
Show the principal modal:
$scope.distribuirModal = function (producto) {
$rootScope.modalProducto = producto;
ngDialog.open({
template: 'views/modals/distribucion/modal-distribuir.html',
className: 'ngdialog-theme-advertencia',
showClose: false,
controller: 'DistribucionController',
closeByDocument: false,
closeByEscape: false
});
};
make the processs of the data, and show a modal of confirmation:
$scope.confirmarDistribuir = function (modalDistribuir) {
var control = 0;
control = modalDistribuir.tierra + modalDistribuir.bebelandia + modalDistribuir.libertador;
if (control === $rootScope.modalProducto.cantidadTotal) {
if (modalDistribuir.tierra !== null) {
$scope.wrapper.stockTierra.idProducto = $rootScope.modalProducto;
$scope.wrapper.stockTierra.cantidad = modalDistribuir.tierra;
}
if (modalDistribuir.bebelandia !== null) {
$scope.wrapper.stockBebelandia.idProducto = $rootScope.modalProducto;
$scope.wrapper.stockBebelandia.cantidad = modalDistribuir.bebelandia;
}
if (modalDistribuir.libertador !== null) {
$scope.wrapper.stockLibertador.idProducto = $rootScope.modalProducto;
$scope.wrapper.stockLibertador.cantidad = modalDistribuir.libertador;
}
ngDialog.open({
template: 'views/modals/distribucion/confirmacion-distribuir.html',
className: 'ngdialog-theme-advertencia',
showClose: false,
controller: 'DistribucionController',
closeByDocument: false,
closeByEscape: false,
data: {
'wrapper': $scope.wrapper,
'producto': $rootScope.modalProducto
}
});
} else {
$scope.alerts.push({
type: 'danger',
msg: 'La cantidad total de productos a distribuir debe ser igual a la cantidad total de productos en almacen.'
});
}
};
in this modal i execute a function that save the data on my API
$scope.finalizarDistribucion = function () {
$scope.sendWrapper = {
stockTierra: null,
stockBebelandia: null,
stockLibertador: null
};
if ($scope.ngDialogData.wrapper.stockTierra.idProducto !== null && $scope.ngDialogData.wrapper.stockTierra.cantidad) {
$scope.sendWrapper.stockTierra = $scope.ngDialogData.wrapper.stockTierra;
}
if ($scope.ngDialogData.wrapper.stockBebelandia.idProducto !== null && $scope.ngDialogData.wrapper.stockBebelandia.cantidad) {
$scope.sendWrapper.stockBebelandia = $scope.ngDialogData.wrapper.stockBebelandia;
}
if ($scope.ngDialogData.wrapper.stockLibertador.idProducto !== null && $scope.ngDialogData.wrapper.stockLibertador.cantidad) {
$scope.sendWrapper.stockLibertador = $scope.ngDialogData.wrapper.stockLibertador;
}
$distribute = distribucionService.add($scope.sendWrapper);
$distribute.then(function (datos) {
if (datos.status === 200) {
ngDialog.closeAll();
toaster.pop({
type: 'success',
title: 'Exito',
body: 'Se ha distribuido con exito los productos.',
showCloseButton: false
});
}
});
$scope.$emit('updateTables', $scope.ngDialogData.producto);
$scope.$emit('updateStock', {});
};
in this function i do two $emit
the first one update my object Producto in my ProductoController and send a $broadcast to update my principal table
$scope.$on('updateTables', function (event, object) {
var idFactura = parseInt($stateParams.idFactura);
object.estadoDistribucion = true;
$updateProducto = _productoService.update(object);
$updateProducto.then(function (datos) {
if (datos.status === 200) {
$rootScope.$broadcast('updateTableProducto', {'idFactura': idFactura});
}
});
});
this last works fine, reload the table without problems.
the second $emit is the problem, it must reload the another 3 tables
$scope.$on('updateStock', function () {
var idFactura = parseInt($stateParams.idFactura);
$facturaTierra = distribucionService.getStockTierra(idFactura);
$facturaTierra.then(function (datos) {
$scope.facturaTierra = datos.data;
$scope.tableFacturaTierra.reload();
});
$facturaBebelandia = distribucionService.getStockBebelandia(idFactura);
$facturaBebelandia.then(function (datos) {
$scope.facturaBebelandia = datos.data;
$scope.tableFacturaBebelandia.reload();
});
$facturaLibertador = distribucionService.getStockLibertador(idFactura);
$facturaLibertador.then(function (datos) {
$scope.facturaLibertador = datos.data;
$scope.tableFacturaLibertador.reload();
});
});
but my parameters of ngTable are undefined and the reload fails.
have somebody any idea what i'm doing wrong?
Finally after try many times i got the answer.
First in my ProductoController i did a $broadcast to my DistribucionController
$rootScope.$on('updateTableProducto', function (event, object) {
$list = _productoService.searchByIdFactura(object.idFactura);
$list.then(function (datos) {
$scope.productosFactura = datos.data;
$rootScope.$broadcast('updateStock', {});
$scope.tableProductosFactura.reload();
});
});
then on i receive this $broadcast on my another controller using
$scope.$on('updateStock', function (event, object) {
var idFactura = parseInt($stateParams.idFactura);
$facturaTierra = distribucionService.getStockTierra(idFactura);
$facturaTierra.then(function (datos) {
$scope.facturaTierra = datos.data;
$scope.tableFacturaTierra.reload();
});
$facturaBebelandia = distribucionService.getStockBebelandia(idFactura);
$facturaBebelandia.then(function (datos) {
$scope.facturaBebelandia = datos.data;
$scope.tableFacturaBebelandia.reload();
});
$facturaLibertador = distribucionService.getStockLibertador(idFactura);
$facturaLibertador.then(function (datos) {
$scope.facturaLibertador = datos.data;
$scope.tableFacturaLibertador.reload();
});
});
NOTE: if i write $rootScope.on it execute 3 times. so in $scope just make one loop.
I hope this will be helpul to someone.
I have a jquery context menu on my landing page where I have hardcode menu items. Now I want to get the menu items from server. Basically the idea is to show file names in a specified directory in the context menu list and open that file when user clicks it...
This is so far I have reached..
***UPDATE***
C# code
[HttpPost]
public JsonResult GetHelpFiles()
{
List<Manuals> manuals = null;
var filesPath = Server.MapPath(#"\HelpManuals");
var standardPath = new DirectoryInfo(filesPath);
if (standardPath.GetFiles().Any())
{
manuals = standardPath.GetFiles().Select(x => new Manuals
{
Name = GetFileNamewithoutExtension(x.Name),
Path = x.Name
}).ToList();
}
return Json(manuals, JsonRequestBehavior.AllowGet);
}
private string GetFileNamewithoutExtension(string filename)
{
var extension = Path.GetExtension(filename);
return filename.Substring(0, filename.Length - extension.Length);
}
JavaScript Code
$.post("/Home/GetHelpFiles", function (data) {
$.contextMenu({
selector: '#helpIcon',
trigger: 'hover',
delay: 300,
build: function($trigger, e) {
var options = {
callback: function(key) {
window.open("/HelpManuals/" + key);
},
items: {}
};
$.each(data, function (item, index) {
console.log("display name:" + index.Name);
console.log("File Path:" + index.Path);
options.items[item.Value] = {
name: index.Name,
key: index.Path
}
});
}
});
});
Thanks to Matt. Now, the build function gets fire on hover.. but im getting illegal invocation... and when iterating through json result, index.Name and this.Name gives correct result. But item.Name doesn't give anything..
to add items to the context menu dynamically you need to make a couple changes
$.contextMenu({
selector: '#helpIcon',
trigger: 'hover',
delay: 300,
build: function($trigger, e){
var options = {
callback: function (key) {
var manual;
if (key == "adminComp") {
manual = "AdminCompanion.pdf";
} else {
manual = "TeacherCompanion.pdf";
}
window.open("/HelpManuals/" + manual);
},
items: {}
}
//how to populate from model
#foreach(var temp in Model.FileList){
<text>
options.items[temp.Value] = {
name: temp.Name,
icon: 'open'
}
</text>
}
//should be able to do an ajax call here but I believe this will be called
//every time the context is triggered which may cause performance issues
$.ajax({
url: '#Url.Action("Action", "Controller")',
type: 'get',
cache: false,
async: true,
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (_result) {
if (_result.Success) {
$.each(_result, function(item, index){
options.items[item.Value] = {
name: item.Name,
icon: 'open'
}
});
}
});
return options;
}
});
so you use build and inside of that define options and put your callback in there. The items defined in there is empty and is populated in the build dynamically. We build our list off of what is passed through the model but I believe you can put the ajax call in the build like I have shown above. Hopefully this will get you on the right track at least.
I solved this problem the following way.
On a user-triggered right-click I return false in the build-function. This will prevent the context-menu from opening. Instead of opeing the context-menu I start an ajax-call to the server to get the contextMenu-entries.
When the ajax-call finishes successfully I create the items and save the items on the $trigger in a data-property.
After saving the menuItems in the data-property I open the context-menu manually.
When the build-function is executed again, I get the items from the data-property.
$.contextMenu({
build: function ($trigger, e)
{
// check if the menu-items have been saved in the previous call
if ($trigger.data("contextMenuItems") != null)
{
// get options from $trigger
var options = $trigger.data("contextMenuItems");
// clear $trigger.data("contextMenuItems"),
// so that menuitems are gotten next time user does a rightclick
// from the server again.
$trigger.data("contextMenuItems", null);
return options;
}
else
{
var options = {
callback: function (key)
{
alert(key);
},
items: {}
};
$.ajax({
url: "GetMenuItemsFromServer",
success: function (response, status, xhr)
{
// for each menu-item returned from the server
for (var i = 0; i < response.length; i++)
{
var ri = response[i];
// save the menu-item from the server in the options.items object
options.items[ri.id] = ri;
}
// save the options on the table-row;
$trigger.data("contextMenuItems", options);
// open the context-menu (reopen)
$trigger.contextMenu();
},
error: function (response, status, xhr)
{
if (xhr instanceof Error)
{
alert(xhr);
}
else
{
alert($($.parseHTML(response.responseText)).find("h2").text());
}
}
});
// This return false here is important
return false;
}
});
I have finally found a better solution after reading jquery context menu documentation, thoroughly..
C# CODE
public JsonResult GetHelpFiles()
{
List<Manuals> manuals = null;
var filesPath = Server.MapPath(#"\HelpManuals");
var standardPath = new DirectoryInfo(filesPath);
if (standardPath.GetFiles().Any())
{
manuals = standardPath.GetFiles().Select(x => new Manuals
{
Name = GetFileNamewithoutExtension(x.Name),
Path = x.Name
}).ToList();
}
return Json(manuals, JsonRequestBehavior.AllowGet);
}
HTML 5
<div id="dynamicMenu">
<menu id="html5menu" type="context" style="display: none"></menu>
</div>
JavaScript Code
$.post("/Home/GetHelpFiles", function (data) {
$.each(data, function (index, item) {
var e = '<command label="' + item.Name + '" id ="' + item.Path + '"></command>';
$("#html5menu").append(e);
});
$.contextMenu({
selector: '#helpIcon',
trigger: 'hover',
delay: 300,
items: $.contextMenu.fromMenu($('#html5menu'))
});
});
$("#dynamicMenu").on("click", "menu command", function () {
var link = $(this).attr('id');
window.open("/HelpManuals/" + link);
});
Here's my solution using deferred, important to know that this feature is supported for sub-menus only
$(function () {
$.contextMenu({
selector: '.SomeClass',
build: function ($trigger, e) {
var options = {
callback: function (key, options) {
// some call back
},
items: JSON.parse($trigger.attr('data-storage')) //this is initial static menu from HTML attribute you can use any static menu here
};
options.items['Reservations'] = {
name: $trigger.attr('data-reservations'),
icon: "checkmark",
items: loadItems($trigger) // this is AJAX loaded submenu
};
return options;
}
});
});
// Now this function loads submenu items in my case server responds with 'Reservations' object
var loadItems = function ($trigger) {
var dfd = jQuery.Deferred();
$.ajax({
type: "post",
url: "/ajax.php",
cache: false,
data: {
// request parameters are not importaint here use whatever you need to get data from your server
},
success: function (data) {
dfd.resolve(data.Reservations);
}
});
return dfd.promise();
};
How can one remove a whole IndexedDB database from JavaScript, as opposed to just an object store? I'm using the IndexedDB shim, which may use WebSQL as its backend.
I'd mainly like to know how to do this for the PhantomJS (headless) browser, although Chrome, Safari (on iPad) and IE10 are other important browsers.
As far as I can tell, one should use indexedDB.deleteDatabase:
var req = indexedDB.deleteDatabase(databaseName);
req.onsuccess = function () {
console.log("Deleted database successfully");
};
req.onerror = function () {
console.log("Couldn't delete database");
};
req.onblocked = function () {
console.log("Couldn't delete database due to the operation being blocked");
};
I can confirm that it works with PhantomJS 1.9.0 and Chrome 26.0.1410.43.
I found that the following code works OK but to see the DB removed in the Chrome Resources Tab I have had to refresh the page.
Also I found I had problems with the Chrome debug tools running while doing transactions. Makes it harder to debug but if you close it while running code the code seems to work OK.
Significant also is to set a reference to the object store when opening the page.
Obviously the delete part of the code is in the deleteTheDB method.
Code derived from example provided by Craig Shoemaker on Pluralsight.
var IndDb = {
name: 'SiteVisitInsp',
version: 1000,
instance: {},
storenames: {
inspRecords: 'inspRecords',
images: 'images'
},
defaultErrorHandler: function (e) {
WriteOutText("Error found : " + e);
},
setDefaultErrorHandler: function (request) {
if ('onerror' in request) {
request.onerror = db.defaultErrorHandler;
}
if ('onblocked' in request) {
request.onblocked = db.defaultErrorHandler;
}
}
};
var dt = new Date();
var oneInspRecord =
{
recordId: 0,
dateCreated: dt,
dateOfInsp: dt,
weatherId: 0,
timeArrived: '',
timeDeparted: '',
projectId: 0,
contractorName: '',
DIWConsultant: '',
SiteForeman: '',
NoOfStaffOnSite: 0,
FileME: '',
ObservationNotes: '',
DiscussionNotes: '',
MachineryEquipment: '',
Materials: ''
};
var oneImage =
{
recordId: '',
imgSequence: 0,
imageStr: '',
dateCreated: dt
}
var SVInsp = {
nameOfDBStore: function () { alert("Indexed DB Store name : " + IndDb.name); },
createDB: function () {
openRequest = window.indexedDB.open(IndDb.name, IndDb.version);
openRequest.onupgradeneeded = function (e) {
var newVersion = e.target.result;
if (!newVersion.objectStoreNames.contains(IndDb.storenames.inspRecords)) {
newVersion.createObjectStore(IndDb.storenames.inspRecords,
{
autoIncrement: true
});
}
if (!newVersion.objectStoreNames.contains(IndDb.storenames.images)) {
newVersion.createObjectStore(IndDb.storenames.images,
{
autoIncrement: true
});
}
};
openRequest.onerror = openRequest.onblocked = 'Error'; //resultText;
openRequest.onsuccess = function (e) {
//WriteOutText("Database open");
IndDb.instance = e.target.result;
};
},
deleteTheDB: function () {
if (typeof IndDb.instance !== 'undefined') {
//WriteOutText("Closing the DB");
IndDb.instance.close();
var deleteRequest = indexedDB.deleteDatabase(IndDb.name)
deleteRequest.onblocked = function () {
console.log("Delete blocked.");
}
deleteRequest.onerror =
function () {
console.log("Error deleting the DB");
//alert("Error deleting the DB");
};
//"Error deleting the DB";
deleteRequest.onsuccess = function () {
console.log("Deleted OK.");
alert("*** NOTE : Requires page refresh to see the DB removed from the Resources IndexedDB tab in Chrome.");
//WriteOutText("Database deleted.");
};
};
}
}
This could be a very basic Javascript I know but I just can't get it..
Ext.regController('Chat', {
initSocketConnection: function() {
this.chatStore = new App.Store.Chat();
...
this.socket = io.connect(settings.get('server'), {port: 8080});
this.socket.on(
'message',
this.addMessageToChatStore
);
},
addMessageToChatStore: function(message) {
console.log(message);
console.log(this); << console shows the 'this' has become SocketNameSpace
this.chatStore.add(message); << this line error with "Undefined" chatStore
this.send(message);
},
Console print out shows that the "this" in the addMessageToChatStore function is "SocketNamespace"
How to I get rid of the error?
To generalize the problem. I think it's better to describe it as function chain calling dilemma.
A class has some local var that's instance of another class. When this var listens on certain events, it calls the parent's class's method. The problem is when this method is called, it's under the context of the other class and hence the scope has changed and the access to the original parent's class methods are denied.
In javascript, the this variable is determined by the caller. You could use a self executing function to ensure you're referencing the correct entity rather than using this:
Ext.regController('Chat', (function() {
var self = {
initSocketConnection: function() {
self.chatStore = new App.Store.Chat();
...
self.socket = io.connect(settings.get('server'), {port: 8080});
self.socket.on(
'message',
this.addMessageToChatStore
);
},
addMessageToChatStore: function(message) {
console.log(message);
self.chatStore.add(message);
self.send(message);
}
};
return self;
}()));
Update
Based on the full snippet, I'm not sure where the render function is defined, if render is a global function then self.viewChat = render({xtype : 'App.View.Chat'}); will suffice, otherwise it may be defined on this (the this that is defined for the call to index) so the following may suffice self.viewChat = this.render({xtype : 'App.View.Chat'});.
If I were a betting man, I'd go for the latter, so the code would be (with commented out code removed):
Ext.regController('Chat', (function() {
var self = {
index: function() {
if (!self.socket) {
self.initSocketConnection();
}
self.showChat();
},
/**
* init the socket connection to the node.js server
* using user settings
*
*/
initSocketConnection: function() {
self.chatStore = new App.Store.Chat();
self.chatStore.add({
user: "Figo",
message: "Welcome!"
});
self.configStore = Ext.StoreMgr.get('ConfigStore');
var settings = self.configStore.getAt(0);
self.socket = io.connect(settings.get('server'), {
port: 8080
});
// Event Listener
self.socket.on('connect', self.registerUser);
self.socket.on('message', self.addMessageToChatStore);
App.on('newMsg', self.sendMessageToServer);
},
sendMessageToServer: function(msg) {
self.socket.send(msg);
},
addMessageToChatStore: function(message) {
console.log(message);
console.log(this);
console.log(this.parent);
self.chatStore.add(message);
self.socket.send(message);
},
registerUser: function() {
self.configStore = Ext.StoreMgr.get('ConfigStore');
var settings = self.configStore.getAt(0);
var user = {
nickname: settings.get('nickname'),
gravatar: settings.get('gravatar')
};
console.log(user);
self.socket.send(user);
},
/**
* Show chat view
*/
showChat: function() {
if (!self.viewChat) {
self.viewChat = this.render({
xtype: 'App.View.Chat'
});
self.viewChat.query('#settingsButton')[0].on('tap', self.showConfig, self);
}
self.application.viewport.setActiveItem(
self.viewChat, {
type: 'slide',
direction: 'left'
});
},
/**
* Show config View
*/
showConfig: function() {
Ext.dispatch({
controller: 'Viewport',
action: 'showConfig'
});
}
};
return self;
}()));
For #Rich.okelly
Here's the error (highlighted in code)
Uncaught TypeError: Object #<Object> has no method 'render' app.all.js:438
self.showChat app.all.js:438
self.index app.all.js:351
Ext.util.Dispatcher.Ext.extend.dispatch sencha-touch-debug.js:10630
Ext.dispatch sencha-touch-debug.js:10667
Ext.regController.showChat app.all.js:293
fire sencha-touch-debug.js:979
Ext.util.Observable.Ext.extend.fireEvent sencha-touch-debug.js:595
And here's the full code (other code within the same project not shown):
Ext.regController('Chat',(function() {
var self = {
/**
* Index action
*
* #return {void}
*/
index: function() {
if (!self.socket) {
self.initSocketConnection();
}
self.showChat();
},
/**
* init the socket connection to the node.js server
* using user settings
*
*/
initSocketConnection: function() {
self.chatStore = new App.Store.Chat();
self.chatStore.add({user: "Figo", message: "Welcome!"});
self.configStore = Ext.StoreMgr.get('ConfigStore');
//this.configStore = new App.Store.Config()
var settings = self.configStore.getAt(0);
//this.socket = new App.util.Socketio(settings.get('server'), {port: 4000});
//this.socket.connect();
self.socket = io.connect(settings.get('server'), {port: 8080});
/*
this.socket.on('message', function (data) {
console.log(data);
this.parent.addMessageToChatStore(data);
this.emit('message', data);
});
this.socket.on('message',
this.addMessageToChatStore
);
*/
// Event Listener
self.socket.on(
'connect',
self.registerUser
);
self.socket.on(
'message',
self.addMessageToChatStore
);
App.on(
'newMsg',
self.sendMessageToServer
);
},
sendMessageToServer: function(msg){
self.socket.send(msg);
},
addMessageToChatStore: function(message) {
console.log(message);
console.log(this);
console.log(this.parent);
//if (!this.chatStore)
//this.chatStore = new App.Store.Chat();
self.chatStore.add(message);
//App.Controller.Chat.chatStore.add(message);
self.socket.send(message);
},
registerUser: function() {
self.configStore = Ext.StoreMgr.get('ConfigStore');
var settings = self.configStore.getAt(0);
var user = {
nickname: settings.get('nickname'),
gravatar: settings.get('gravatar')
};
console.log(user);
self.socket.send(user);
},
/**
* Show chat view
*/
showChat: function() {
if (!self.viewChat) {
self.viewChat = self.render({ << fails over here
xtype: 'App.View.Chat'
});
self.viewChat.query('#settingsButton')[0].on(
'tap',
self.showConfig,
self
);
}
self.application.viewport.setActiveItem(
self.viewChat,
{
type: 'slide',
direction: 'left'
}
);
},
/**
* Show config View
*/
showConfig: function() {
Ext.dispatch({
controller: 'Viewport',
action : 'showConfig'
});
}
};
return self;
}()));