ajax call only once on first time click of an element - javascript

I am designing a chatting application just like WhatsApp web . in that right now I have dummy data for chats. so suppose, if I click on any chat then corresponding chat logs are displayed but these chat logs are dummy data. same way I have done for other chats also but now what I want is if I click on any of the chat then an ajax call should happen and chat logs are rendered and displayed dynamically but this ajax call should happen only one for every chat that means if I click for first time on some chat an ajax call should happen but if click the second time no ajax call should happen.
any suggestions..?

Question: I understood that, once you click on a chat and got data, from the next time ajax call should not be made which will be an extra call.
Solution: The solution for your question will be, first time when you get response from the server, save it in localStorage, A localStorage is a powerful feature of browser which stores data in the browser session.
Implemenatation:
An example api call,
$.post(
"chat-api-url",
{ chat: "chatId" },
function(data) {
localStorage.setItem('chatId', 'data')
}
);
So, now after click in jquery check condition,
if(localStorage.getItem('chatId') == undefined)
{
$.post(
"chat-api-url",
{ chat: "chatId" },
function(data) {
localStorage.setItem('chatId', data)
this.chatData = data;
}
);
} else{
this.chatData = localStorage.getItem('chatId');
}
PS:
localStorage.setItem stores into localstorage
localStorage.getItem retrieves from. localstorage
Here is a documeantation regarding different storages

Related

JavaScript/JQuery publish subscribe not working between two pages but works within a page in below code

I have two html pages and a JavaScript file.
Implementation
First html page publish the message and the second html page subscribe to the published message and performs the action based on the published message in the second page.
Problem Statement
The publish and subscribe works fine within the same html page but has problem when working between two html pages.
The problem is, the subscribed message is being displayed in the First HTML Page but not in the Second HTML Page.
First HTML Page
<script>
function clickMe() {
messageBus.publish('event', 4);
}
</script>
Second HTML Page
<script>
messageBus.subscribe('event', function(data) {
$("#div1").text(data);
});
</script>
<div id="div1"></div>
JS File
var messageBus = {
events: {},
publish: function(eventType, data) {
if (typeof(Storage) !== "undefined") {
var myFunc = localStorage.getItem(eventType);
var e = eval('(' + myFunc + ')');
if(e) {
e(data);
}
}
},
subscribe: function(eventType, fn) {
if (typeof(Storage) !== "undefined") {
localStorage.setItem(eventType, fn);
}
},
unsubscribe: function(eventType) {
if (typeof(Storage) !== "undefined") {
localStorage.removeItem(eventType);
}
}
}
Is there something missed in the implementation? Let me know if there is more stuffs required to make the question clear.
Your publish and subscribe methods are the wrong way around, publish is getting the item and subscribe is writing it. And get rid of that eval!
The main problem
As already pointed out by Adrian Brand in an answer, the code inside your publish method and subscribe method need to be swapped.
Other unrelated but design related problems
Another problem with your messageBus is that it if the publisher publishes more than one message before the subscriber has had a chance to read any of the messages, only the last one of the messages published gets persisted to your message bus; all previous messages are overwritten by the last one and so they never make it to the subscribers.
You're using eval to run just about anything that might be inside the localStorage item. This opens your application up to a security threat.
What if I opened your application in Developer Tools, wrote a malicious function or script and put it in the local storage with the key 'events'? Your code would execute my function. Now, imagine all that I could do with that ability.
I could make AJAX requests to evil websites (I would make them GET requests to bypass CORS), read your cookies, search for and scrape all your form fields, stuff them into a form data object and send that to my server, and a whole lot more.

Reactjs - getting data from server and updating

(reactjs newbie here)...
I'm using Reactjs to create a page where I have
a simple search box
user types in a search text
data is fetched from the server and is displayed
Now, the "searchText" and "data" are my states and I'm trying to figure out how to update the "results" only after the data is received from the server.
I have an event where I handle whenever user types something as a search text
handleUserInput: function(searchText) {
this.loadDataFromServer(searchText);
this.setState({
searchText: searchText,
});
},
But with the above function, the following thing happens
Initial data is loaded
User types in something
The result is IMMEDIATELY updated to only show the the result that contains the search text (code below), BUT at the same time a request is made to the server to fetch results where the result contains the search text
this.props.products.forEach(function(product) {
if(product.name.toLowerCase().indexOf(this.props.searchText) > -1) {
row =
rows.push(row)
}
}.bind(this));
After about a second, new data is received from the server and the result is refreshed again.
Obviously what I want to do is
Load initial data
User types search text
Request data from the server
Receive data from the server
Update the results
What is the proper way of achieving this?
Don't think searchText should be a state itself. You could just use data fetched from the server to set the state.
Let's say, data is a state property. you could pass a callback to the loadDataFromServer and loadDataFromServer calls this callback once data is fetched on it's onsuccess.
this.loadDataFromServer(searchText, function(data) {
this.setState({data: data}};
});
This way, the component will rerender and show the results, once the data is updated.
So, it is just the first refresh that you want to stop right?
If it is already refreshing once the results come from the server, it seems that all you need to do is not filter the results on the client in step 3 - then the same virtual DOM will be generated as in the first place, so the result list will only update the actual DOM once the server responds.

Detecting Unique Browser Tabs

On every page of my sites, I am using AJAX to poll the server and retrieve a list of messages. The server maintains a list of messages and the SessionId (I'm in an ASP.NET environment, but I feel like this question is applicable to any server side technology) that the message is intended for. If a message is found for the particular SessionId, it is returned to the client side script. I use a JavaScript library to create a notification (using noty, a Jquery Notification Plugin). Once it returns a particular message, the server discards that message.
This works well if the user only has a single tab/window open for a particular site. However, let's say they have two open and they do something that causes a warning message to be generated. I have no control over which tab the notification goes to, so the user may not end up seeing the warning message.
Is there a way of uniquely identifying a browser tab? Then I could pass this as one of the parameters in my AJAX call.
Firstly, polling doesn't seem good mechanism. It might hit your server down when you have large number of active users. Ideally you should return a message in the response to the request that was result of invalid action.
Still below solution might work for you. It is inspired by the reply of #SergioGarcia.
Keep a hidden input just before the end of your form tag, which stores a unique ID for identifying a tab uniquely. You will store the messages on server session against unique tabID,
<input type="hidden" id="hiddenInputTabId" value="<%=getValue()%>" />
and then define getValue.
function string getValue() {
var v = getValueFormBodyOrAccessValueDirectlyByMakingInput_a_ServerSideControl();
if (string.IsNullOrWhiteSpace(v)) {
return Guid.NewId();
} else {
return v;
}
}
Because it is a hidden input you should get it's value in the POSTed form body, and for ajax requests below snippet should take care of sending that value in header which you can access on server side.
$.ajaxSetup({
beforeSend: function(xhr) {
xhr.setRequestHeader("tabId", $('#hiddenInputTabId').val());
},
});
Same header can be check while returning the response to your polling requests and only respond message available against the provided tabId should be responded.
You can add a query string parameter called tabId and control it's binding to tab using javascript.
There is a functional prototype below:
$(function () {
// from: https://developer.mozilla.org/en-US/docs/Web/API/Window.location
function getQueryStringParameter (sVar) {
return decodeURI(window.location.search.replace(new RegExp("^(?:.*[&\\?]" + encodeURI(sVar).replace(/[\.\+\*]/g, "\\$&") + "(?:\\=([^&]*))?)?.*$", "i"), "$1"));
}
// from: http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript
function newGuid() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
return v.toString(16);
});
}
window.tabId = getQueryStringParameter('tabId');
// tabId not defined, reload the page setting it
if (!window.tabId) {
window.tabId = newGuid();
}
// on click set the tabId of each link to current page
$(document).on('click', 'a', function (e) {
var $this = $(this);
var newLocation = $(this).attr("href");
// In page links
if (newLocation.match(/^#.+$/)) {
return;
}
// Outbound links
if (newLocation.match(new RegExp("^https?")) && !newLocation.match(new RegExp("^https?://" + window.location.host))) {
return;
}
// Insert tab id
if (newLocation.match(/(\?|&)tabId=[0-9a-f-]+/)) {
newLocation.replace(/(\?|&)tabId=[0-9a-f-]+/, (newLocation.indexOf('?') == -1 ? "?" : "&") + "tabId=" + window.tabId);
} else {
newLocation += (newLocation.indexOf('?') == -1 ? "?" : "&") + "tabId=" + window.tabId;
}
window.location.href = newLocation;
e.preventDefault();
});
});
If you enter a page in your application without setting the tabId parameter on query string, it will be set to a new UUID (Guid).
When the page has a tabId parameter on query string, it defines the window.tabId variable inside your page and you can use that in your application.
When the user click on any link in your page, a javascript event will be triggered and the link url will be redirected to match the current tabId. An right click to open in new tab or a middle click will not trigger that event and the user will be sent to a new tab without the query string parameters, so the new page will create a new tabId in that page.
You can see it working here: http://codepen.io/anon/pen/sCcvK
You can do it by generating a unique tab id with javascript by loading your client.
I strongly recommend you to use something for intertab communication, like intercom.js, which can broadcast the messages from a single tab with a single connection to every other tabs. Intertab works with socket.io, which has long polling fallback, so it may be good in your current system as well. I agree that polling is a poor choice, and you should use websockets instead.
If you use ZMQ on the server, then in the browser you can use NullMQ either (for websockets ofc). I think it does not have intertab support, so you should make your own intertab solution to make it work. It is not so hard to write such a system, you need only a common storage, for example localStorage, but it can be even cookie... If you don't have a storage event, you have to ping that storage for changes with setInterval. You have to store there the messages, and which tab broadcasts them (probably in a semaphore) and when was the last time it pinged the storage. After that you can keep each tab in sync with the others, or by using a unique tab id, you can send customized messages to any of the tabs. If the broadcast tab has a storage timeout (it did not ping the storage for a long while), then it is probably closed, so you should assign the broadcast service to another tab.
So what I ended up doing was changing how my notification framework functioned in order to prevent the need for identifying unique tabs. It's just too hard to layer information on the stateless web.
Instead of using Ajax to pump messages out to the client instantly, I build them up on each page into a List<Message> property. On PreRender I render them to the client with ClientScript.RegisterStartupScript(). But if I need to send the user to another page, I started using Server.Transfer() instead of Response.Redirect() instead so that it will preserve the message queue. The new page checks the old page to see if it exists and if is the correct Type. If it is the correct type, I cast it and retrieve the message queue from the old page and add them to the new page's queue. And since Server.Transfer() doesn't update the URL on the client, I also added a JavaScript function to manually push the state to the URL in supported browsers.
I know I took this in a little different direction than I did on the question, but I think I had been approaching it wrong in the beginning.

Losing context reference

I am encountering a 'small' problem when making a new object in the options page.
In the options page I create a few objects and save them as general settings. These objects have method to communicate with different API's. But as soon as I get one of those objects to work with, I lose the context on the page I am.
For example:
The options page I create an object that has a method 'request' and I send an ajax request to some api with this method. When I call this on an other page the ajax request is logged within the options page. When I close the options page I lose all context of the logs it makes.
Is there a way to force the context reference to the current page? or did I make a mistake with creating objects on the wrong pages/saving them and retrieving them on a page that needs them? (IE Should I only save the data I need to create objects on the page itself? (which seems like alot of overhead for the the same thing(?)).
Thanks in advance.
EDIT
I have an option page which creates an Object lets call it MyApi. I create a new MyApi and store it in chrome.storage.local . When a user has some text selected and clicks on the context menu I open a new page(selectedText.html) which shows the selected text and some API calls are made, which are mostly ajax requests. The moment I get the object from storage in selectedText.html and make any request with MyApi I see no logs in the network tab of the ajax requests, neither any console logs. But with my options page open I see everything in there.
EDIT2
save : function()
{
var obj = {'api':this.data};
chrome.storage.local.set(obj,function() { if(chrome.runtime.lastError) console.warn(chrome.runtime.lastError); });
}
This is in the background script.
You could achieve what you want this way:
Define your object/function/whatever in the background page.
Use chrome.runtime.getBackgroundPage() to get a hold on the background pages window object.
Execute the desired method, passing as argument an object of the local context. (Of course you have to modify the function to accept and make use of such an argument.)
Example:
In background.js:
function myFunc(winObj, msg) {
winObj.console.log(msg);
}
In otherPage.js:
chrome.runtime.getBackgroundPage(function(bgPage) {
bgPage.myFunc(window, "This will be logged in 'otherPage.html' !");
});
It is not the cleanest solution, but it might work...

Continually check for an Oracle record at page load

I basically have a page that when loads, reads an Oracle SQL table for a specific record id that may not currently exist at the point as it may take up to a minute to insert this specific record into the table.
Based on this, I need a means of showing a "Loading Image" while it waits for the record to exist, so has to wait. Once it does, I want to remove the loading image and present the user with the record details. I am using Oracle Application Express 4.2 for this.
My question is not so much the loading/hiding of the image but how to continually check for the record within the Oracle table, during page load.
Either I receive the record successfully and then hide the image or say after 1 minute, I dismiss the checking of the record and present the user with a message indicating that no record was found.
Sorry for my english. I will try help you.
Make your "Loading image" always visible on the page. There is no need to show it on load, you only need to hide it at proper moment.
Add Application Process to your application. Name it for example "GET_MY_ROW". Process must check your event, and return some flag, for example 1 or 0.
Example:
declare
l_cnt number;
begin
select count(*)
into l_cnt
from table1 t
where id = 12345;
if l_cnt > 0 then
htp.p(1);
else
htp.p(0);
end if;
end;
3.3 Add javascript code as page load event (for example by Dynamic Actions):
Javascript code:
var myInterval = setInteral(function {
var get = new htmldb_Get(null,$v('pFlowId'),'APPLICATION_PROCESS=GET_MY_ROW',$v('pFlowStepId'));
get.GetAsync(function(pRequest) {
if (pRequest.readyState == 4) {
if (pRequest.responseText == 1) {
alert('Record loaded successfully');
// add function call, hiding your "Loading image" here
clearInterval(myInterval);
}
};
});
get = null;
}, 5000); //check every 5 seconds
setTimeout(function() {
alert('Sorry, no record was found. Try again later.');
clearInterval(myInterval);
}, 60000); // fail after 1 minute
Since NoGotnu already answered, I'll put this here:
Is there any reason for the procedure to be called through a job? Is it the only way to create the required record? Is the job called anywhere else? Why not call the procedure directly when the required page has been submitted and show the loading icon there? When it finishes, the user knows it has finished. That would involve a lot less fiddling around as you can make apex show a processing graphic on page submit. You could then just inform the user on the other page that the process has not been ran yet and they'd have to do that first.
Secondly, while NoGotnu's answer will work, I'd like to point out that in apex 4.2 you should use the apex.server namespace instead of the never documented htmldb_Get construction. apex.server.process is a clean implementation of the jQuery ajax setup.
NoGotnu's code translated:
apex.server.process( "GET_MY_ROW"
, null
, { dataType: text
, success: function(pData){
if (pData == 1) {
clearInterval(myInterval);
alert('Record loaded successfully');
};
}
}
);
The call doesn't really need to be async though, but ok.
Another option would be to implement a "long poll" instead of firing the ajax event every 5 seconds. A long poll will just initiate a call to the server and wait for a response. As long as the server is busy, the client will wait. To achieve this you could use dbms_alert, as suggested in Waiting for a submitted job to finish in Oracle PL/SQL?
You'd signal an alert in the plsql code of the job, and in the ondemand process code register an interest in the alert and use waitone/any with a 60 second timeout. Presto long poll.

Categories

Resources