Concurrent call to a simplemodal object - javascript

I have to make a function concurrent to multiple open/close modal requests.
For exemple: When i call showAjaxLoading(true), it's showing the modal, and showAjaxLoading(false) it's disposing the modal.
The Problem: When i make a first long request to showing the modal, and another one quick request will close it. I want to be able keeping in a array all the requests and disposing the modal only when the last request is ended.
SimpleModal: The object simplemodal is unique. When you create the modal it return the object itself. But when you have a modal already open, it returns false. url: http://www.ericmmartin.com/projects/simplemodal/
var showAjaxLoading = function (show) {
var ajaxModal;
if (show) {
var aModal = $("#ajaxLoading").modal({ overlayId: 'ajaxloading-overlay', containerId: 'ajaxloading-container', closeClass: 'ajaxloading-close', close: false, escClose: false });
if (aModal !== false) {
ajaxModal = aModal;
};
} else {
if (ajaxModal !== undefined && $.isFunction(ajaxModal.close)) {
ajaxModal.close();
};
};
};
What the is the best solution to solve this problem ?

var modalDialog = {
_requestsInProcess: 0,
showAjaxLoading : function()
{
if ( this._requestsInProcess == 0 )
{
// open overlay here
}
this._requestsInProcess++;
},
hideAjaxLoading : function()
{
this._requestsInProcess--;
if ( this._requestsInProcess == 0 )
{
// hide overlay here
}
}
}
Try something like this/ Now you can call modalDialog.showAjaxLoading() each time you making AJAX request and modalDialog.hideAjaxLoading() each time your request is completed.

Related

chrome.tabs.update stops working when called from extension

I tried the following code. It basically takes a screenshot from all tabs open in the current window:
function captureWindowTabs(windowId, callbackWithDataUrlArray) {
var dataUrlArray = [];
// get all tabs in the window
chrome.windows.get(windowId, { populate: true }, function(windowObj) {
var tabArray = windowObj.tabs;
// find the tab selected at first
for(var i = 0; i < tabArray.length; ++i) {
if(tabArray[i].active) {
var currentTab = tabArray[i];
break;
}
}
// recursive function that captures the tab and switches to the next
var photoTab = function(i) {
chrome.tabs.update(tabArray[i].id, { active: true }, function() {
chrome.tabs.captureVisibleTab(windowId, { format: "png" }, function(dataUrl) {
// add data URL to array
dataUrlArray.push({ tabId:tabArray[i].id, dataUrl: dataUrl });
// switch to the next tab if there is one
if(tabArray[i+1]) {
photoTab(i+1);
}
else {
// if no more tabs, return to the original tab and fire callback
chrome.tabs.update(currentTab.id, { active: true }, function() {
callbackWithDataUrlArray(dataUrlArray);
});
}
});
});
};
photoTab(0);
});
}
When I call this code from popup.html opened as a webpage, it works as expected (I trigger this from a button click in the popup.html). When I call it from the browser extension, it just gets interrupted from the first tab it selects. Any idea why that is? I can't share errors, since the debugger gets closed when called from the extension.
Supplementary, is there a way to achieve desired result without needing the visual tab switching?
While updating the next tab as active tab. make sure current tab is no more active tab by doing
chrome.tabs.update(tabArray[i-1].id, { active: false }, ()=>{});
Moving the extension to a background script fixed the problem.
Reasoning is that the popup will close once the tab switches. Hence it is required to run in the background where it is not interrupted when the popup closes.

Wait until ajax request is completed

I have a form with several comboboxes within a window.
If I display the window and close it immediately (with a button close method), sometimes I have poor connection to the server and the request to load the data in comboboxes is interrupted.
Response is "Failed to load response data".
Sometimes, the same happens when a combobox is expanded and the store has not yet been loaded.
For these cases, in my Application.js file I have the following function which displays an error message.
Ext.util.Observable.observe(Ext.data.Connection, {
requestexception: function (connection, response, options) {
Ext.Ajax.abort(store.operation.request);
Ext.Msg.show({
title: 'Error!',
msg: 'Message...',
icon: Ext.Msg.ERROR,
buttons: Ext.Msg.OK
});
}
}
});
I'm trying to prevent the window from being closed until the requests were completed and the data was loaded into the comboboxs.
I do not want to use setTimeout().
Maybe use a mask in window and do the unmask when the request is completed ou disabled/enable de close button.
I appreciated suggestions for finding a solution to this.
EDITED:
Another possibility, probably simpler, is to iterate through all the combobox of the form and check if, in each combobox, the store.isLoading (): If yes, it displays a message to wait until the load is finished.
EDITED
If the form has only one combobox the following handler seems to solve the problem: it creates an initial mask and unmasks it after the store is loaded:
handler: function (btn) {
var win = Ext.widget('winSearch', {
animateTarget: this
}).showBy(this, 'bl');
win.getEl().mask('Loading...');
var store = Ext.getStore('storeCombo1Id');
if(store.isLoading()){
store.on('load', function() {
win.getEl().unmask();
});
}else{
win.getEl().unmask();
}
}
The problem is to iterate through several combobox: I tried the following code, without success (the stores are in a viewmodel):
handler: function (btn) {
var win = Ext.widget('winSearch', {
animateTarget: this
}).showBy(this, 'bl');
win.getEl().mask('Loading...');
// var store1 = Ext.getStore('storeCombo1Id');
// var store2 = Ext.getStore('storeCombo2Id');
// var store3 = Ext.getStore('storeCombo3Id');
// var allComboboxStores = [store1, store2, store3];
var allComboboxStores = ['storeCombo1Id', 'storeCombo2Id', 'storeCombo3Id'];
Ext.each(allComboboxStores, function(storeId) {
var store = Ext.getStore(storeId);
console.log(store); //console show 3 stores
if(store.isLoading()){
store.on('load', function() {
win.getEl().unmask();
});
}else{
win.getEl().unmask();
}
});
}
The problem with this solution is that if the store of one of the comboboxs is loaded it triggers the unmask method independently of other comboboxs still to be loaded.
How to wait until all stores are loaded?
EDITED
I have tried different types of iterations and loops and the following solution seems to work.
handler: function () {
var win = Ext.widget('mywindow', {
animateTarget: this
}).showBy(this, 'bl');
win.getEl().mask('Loading...');
var allComboboxStores = ['storeCombo1Id', 'storeCombo2Id', 'storeCombo3Id'];
var indexStores = 0;
Ext.each(allComboboxStores, function(storeId) {
var store = Ext.getStore(storeId);
if(store){
if(store.isLoading()){
indexStores++
store.on('load', function() {
indexStores--;
if (indexStores == 0){
win.getEl().unmask();
}
});
}
else if(!store.isLoading() && indexStores == 0){
win.getEl().unmask();
}
}
});
}
I appreciated suggestions to improve this solution or suggestions to do otherwise.
If jQuery is not a problem ... I suggest using Promises
Description: Return a Promise object to observe when all actions of a certain type bound to the collection, queued or not, have finished.

NW.js open a new window and close it on event

I'm migrating my NW.js v0.12.3 to the new NW.js v0.17.3.
In my old app, I used to open a window to show an incoming call notification. And if the user answered the call or hangs up I closed the window based in a special event listener.
This is my code which works with no problems in v0.12.3:
var notificationWin;
window.onload = function () {
var messageHandler = function(event) {
if(event.data.key == 'incomingCall'){
win.requestAttention(1);
notificationWin = gui.Window.open('notification.html', {
frame: false,
toolbar: false,
focus: true,
icon: "app/imgs/traywinaz.png",
title:"Incoming Call"
});
notificationWin.on ('loaded', function(){
....
});
}else if(event.data.key == 'callRejected' || event.data.key == 'callAnswered' || event.data.key == 'callCanceled' ){
notificationWin.close();
}
}
window.addEventListener('message', messageHandler, false);
}
But in the new version I cant close the window in the call rejected or answered events. I can't get the notification window to close it.
My new code looks like this:
var messageHandler = function(event) {
if(event.data.key == 'incomingCall'){
win.requestAttention(1);
nw.Window.open('app/notification.html', {
frame: false,
focus: true,
icon: "app/imgs/traywinaz.png",
id: "callNotification"
}, function(new_notification) {
new_notification.setAlwaysOnTop(true);
new_notification.setVisibleOnAllWorkspaces(true);
new_notification.on ('loaded', function(){
....
});
});
}else if(event.data.key == 'callRejected' || event.data.key == 'callAnswered' || event.data.key == 'callCanceled' ){
try{
notificationWin = nw.Window.get('app/notification.html');
notificationWin.close();
}catch(e){
console.log(e);
}
}
};
I can only get the window inside the callback so I also tried to do something like this inside the callback:
notificationWin = new_notification;
but this closes my main window.
Any ideas of what I am doing wrong or how can I achieve this?
The documentation http://docs.nwjs.io/en/latest/References/Window/#windowgetwindow_object says Window.get([window_object]) but no idea how to get the [window_object] parameter in the new version.
Coming back to this, I resolved it by saving the reference inside de callback : "notificationWin = new_notification;" and then just calling notificationWin.close();
The first time I tried this it closed my main window but now works : )

Prevent calling ajax on scroll when already called

I have a plugin that tells me if an element is visible in the viewport with $('#element').visible() (set to true when visible).
Now I want to create a function that I scroll down a page and load new content with ajax. I have this so far:
window.onscroll = function() {
console.log($('#ele').visible());
if ($('#ele').visible()) {
//ajax call comes here
}
};
As soon as I see the element my log shows true:
I don't have problems implementing the ajax-request now, but shouldn't I block this function to occur only once? How could I prevent that a new element that already has been loaded to load again (prevent using ajax again)?
I thought of using a boolean-variable, but my problem is that I don't know how to implement that because if I set a variable, how would the browser know it's value? Because on every move of my mousewheel it cant remember what that variable's value was?
EDIT:
I tried the code of Ismail and it never reaches the ajax call (alert won't show).
window.onscroll = function() {
var ajaxExecuted = false;
var ele = $('#load_more').visible();
console.log(ele);
return function() {
if (ajaxExecuted) return;
if (ele) {
alert("OK");
var ajaxArray;
ajaxArray = { page: 2 }
ajaxLoadContent(ajaxArray, "load_more", "ajax_load");
ajaxExecuted = true;
}
}
};
You can use this:
window.onscroll = (function() {
var ajaxExecuted = false;
return function() {
if(ajaxExecuted) return;
if ($('#ele').visible()) {
$.ajax({...}).success(function() {
//Your code here;
ajaxExecuted = true;
});
}
}
})();
One easy solution: set a boolean to true when the element first becomes visible and set it to false when it stops being visible. Only fire the request if those states mismatch (i.e. if it's visible but the boolean is false - that means it's the first time you've seen the window. You'd then set the bool afterwards so it won't fire off anymore until it disappears and reappears again).

Collect async calls and submit the last one

I try to create an image depend on an input field. The image created on the server, I get it by an async call, and it have to be generated after every keyup in the input field. If the user hit another key while the previous call isn't finished, this call have to be stucked. After the first call is finished, this stacked have to be called. The point, if the user hit a tons of keys while the first call is not finished, only the last one have to be called once.
I created a fiddle for it, where I simulated the async call with a settimeout function. I can't figure out, why it isn't working.
var isRequestInProgress = false;
var nextRequest = null;
var submit = function(content) {
console.log('isRequestInProgress: ' + isRequestInProgress); // It should be true in the second turn
if (isRequestInProgress === true) {
nextRequest = content;
return false;
}
isRequestInProgress = true;
setTimeout(function() {
isRequestInProgress = true;
if (nextRequest !== null) {
submit(nextRequest);
}
nextRequest = null;
isRequestInProgress = false;
}, 2000);
};
$('button').click(function() {
isRequestInProgress = false;
submit($(this).text());
});
The isRequestInProgress should be true, if I press a button after another, in 2 mins. But it false, and I don't know, why...
if you know why, or you have a better solution to solve this problem, I would glad to hear it!
Thanks in advance!
If i get it right:
var isRequestInProgress = false,
timeout;
var submit = function(content) {
if (isRequestInProgress === true) {
clearTimeout(timeout);
}
isRequestInProgress = true;
timeout = setTimeout(function() {
console.log('content: ' + content);
isRequestInProgress = false;
}, 2000);
};
$('button').click(function() {
submit($(this).text());
});
Use .abort() method of XMLHttpRequest object to stop an AJAX request.
Assuming you're using setTimeout, clear the timer using clearTimeout before submitting
http://jsfiddle.net/27gmpjj2/1/
If you're using Ajax, use abort(), as suggested by seva.rubbo
http://jsfiddle.net/27gmpjj2/2/
If you want to submit an ajax request only on the last button-press, then you can use the setTimeout approach. This will delay the request until we're sure the user has stopped pressing buttons.
http://jsfiddle.net/27gmpjj2/5/

Categories