Executing a Function from a separate page - javascript

I'm not entire sure that this is possible, but here's what I'm looking at doing.
I have a list of buttons, that when pressed, modify a database that they are attached to, (for example, clicking button 1 would add 10 points to the score of player 1)
What I am looking to do in tandem, is to call a javascript function that lives on a separate page, a sort of a visual confirmation that the points were added to player 1's account.
Why am I organizing it like this?
I am running a Twitch channel where I am building a series of web views to display stats and information. I wish to control WHAT the audience sees from one page, and have the results display on a different page.
Here's what I have so far:
HTML (admin page):
<button class="addPoints" data-id="player1" data-name="Player 1">Player 1</button>
JS (admin page):
$(".addPoints").on('click', function(){
var $id = $(this).data('id');
var $name = $(this).data('name');
//AJAX MAGIC TO INSERT POINTS INTO DATABASE SO I CAN KEEP SCORE//
tallyPopup($id, $name);
});
HTML (display page):
<div class="displayScreen"></div>
JS (display page):
function tallyPopup(member, name){
$('.displayScreen').append(<div class='tallyPopup' id='"+member+"'><div class='portrait' id='"+member+"'></div><span class='name'>"+name+"</span><span class='score'>+10</span></div>);
$('.tallyPopup').animate({
opacity: 1
}, 3000, function(){
$(this).remove();
});
}
I know what I have does not connect the two pages, because I haven't the first clue on how to do that, if it's even possible. OR, is there a way for the Display HTML to check if the database has been updated and THEN run the tallyPopup function?
Thanks in advance.

You cannot call a function on another client (including your own clients) running your website.
To continuously check for points on the display page, use var intv = setInterval(function () {}, nMilliseconds) to repeatedly run a function until you call clearInterval(intv), which you might not do since you may want this to run forever, but perhaps only once every minute (nMilliseconds = 60000).
setInterval(function () { $.get('/point-count').then(tallyPopup) }, 60000)
tallyPopup would receive the data argument from the AJAX response.
Of course on the admin side you must fill in that line to update the amount of points via AJAX, either by PUT, POST, or PATCH. I would consider using PATCH just as a matter of semantics.
Also consider storing the return value of $(this) (var $this = $(this)) instead calling it multiple times, use promises, use CSS animations instead of $.animate (these perform much better). Consider making the element opaque and then visible (perhaps off screen when invisible), instead of using $.remove (also a performance improvement).

Related

Attempting to use a global array inside of a JS file shared between 2 HTML files and failing

So I have one HTML page which consists of a bunch of form elements for the user to fill out. I push all the selections that the user makes into one global variable, allTheData[] inside my only Javascript file.
Then I have a 2nd HTML page which loads in after a user clicks a button. This HTML page is supposed to take some of the data inside the allTheData array and display it. I am calling the function to display allTheData by using:
window.onload = function () {
if (window.location.href.indexOf('Two') > -1) {
carousel();
}
}
function carousel() {
console.log("oh");
alert(allTheData.toString());
}
However, I am finding that nothing gets displayed in my 2nd HTML page and the allTheData array appears to be empty despite it getting it filled out previously in the 1st HTML page. I am pretty confident that I am correctly pushing data into the allTheData array because when I use alert(allTheData.toString()) while i'm still inside my 1st HTML page, all the data gets displayed.
I think there's something happening during my transition from the 1st to 2nd HTML page that causes the allTheData array to empty or something but I am not sure what it is. Please help a newbie out!
Web Storage: This sounds like a job for the window.sessionStorage object, which along with its cousin window.localStorage allows data-as-strings to be saved in the users browser for use across pages on the same domain.
However, keep in mind that they are both Cookie-like features and therefore their effectiveness depends on the user's Cookie preference for each domain.
A simple condition will determine if the web storage option is available, like so...
if (window.sessionStorage) {
// continue with app ...
} else {
// inform user about web storage
// and ask them to accept Cookies
// before reloading the page (or whatever)
}
Saving to and retrieving from web storage requires conversion to-and-from String data types, usually via JSON methods like so...
// save to...
var array = ['item0', 'item1', 2, 3, 'IV'];
sessionStorage.myApp = JSON.stringify(array);
// retrieve from...
var array = JSON.parse(sessionStorage.myApp);
There are more specific methods available than these. Further details and compatibility tables etc in Using the Web Storage API # MDN.
Hope that helps. :)

Converting text to hyperlinks on the fly or store them in a DB?

I have a comments section on a webpage (similar to like on SO) where people can leave text but also links. It works using a standard textfield which does not allow HTML to be included. There is no formatting options etc.
Because no HTML is allowed, I need to parse links (basically text that begins with http or www) and then wrap it in an <a> tag.
To do this on the server would mean using something like JSoup to parse the text and then do the wrapping before inserting it with the rest of the comment text into my DB.
Alternatively, I was thikning that JQuery could scan ALL the comments on the page and wrap anything beginning with a http or www with the <a> tag.
Which one is the correct/better/more efficient method? I have a hunch that the JQuery way will cause some page slowdowns because its updating the DOM constantly on the fly but would like some confirmation from an expert!
When you consider you might at some point want to parse markdown or replace emoticons with images etc., thinking about the performance impact is a good decision.
Usually, you have 3 options:
1. Transform hyperlinks in the backend
I'll assume PHP here, but the principle stays the same:
function renderComment($comment) {
$commentHtml = transformLinks($comment->comment_text);
// render $commentHtml
}
This has the disadvantage of having to replace texts for every comment, on every page request, and is therefore not recommended. On the plus side, compared to option 2, you only have to store the comment text once.
2. Transform hyperlinks in the backend and store them in the database
Assuming PHP and MySQL:
CREATE TABLE comments (id ..., comment_text TEXT, comment_html TEXT, ...)
^^^^^^^^^^^^
function saveComment($createdOrChangedComment) {
$comment->comment_html = transformLinks($comment->comment_text);
saveToDatabase($comment);
}
function renderComment($comment) {
$commentHtml = $comment->comment_html;
// render $commentHtml
}
This means you have to store the comment text twice in the database, once as text, once as html - assuming you want some sort of "edit" button; if not, only saving the html is fine.
While taking up a bit more database space, this solution only fetches the pre-rendered HTML from the database and is therefore better performance-wise.
3. Transforming hyperlinks in the front-end
jQuery(document).ready(function(){
jQuery('.comment').each(function(commentElement) {
// Do magic
transformCommentToHTML(commentElement);
});
});
This should be fine performance-wise when you only have a few hundred comments.
If there are thousands of comments loaded to the DOM at once (which might be a performance hit in itself, but let's ignore that for now), the parsing might be noticable since it happens synchronously and blocks the browser.
In such a case you can parse/replace one pack of comments at a time (e.g. 300) and return the control back to the browser between parsing.
3.b Transform hyperlinks in the frontend, batch-by-batch
jQuery(document).ready(function(){
var $comments = jQuery('.comment');
var currentComment = 0;
(function transformCommentBatch() {
for (var batchLimit = currentComment + 300; currentComment < $comments.length && currentComment < batchLimit; currentComment++) {
// Do magic
transformCommentToHTML($comments[currentComment]);
}
if (currentComment < $comments.length) {
// Don't freeze the browser, continue in the next frame
setTimeout(transformCommentBatch, 1);
}
}());
});
That way, the browser can handle events and does not appear "frozen" to the user, while your first 300 comments in the DOM are transformed first - these are most likely on top of the page and the only ones visible on page load.

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.

Javascript Auto Update

In my stream page, I have one current song script, but it doesn't update... The user needs to refresh the page.
the script is:
<script name="whasong" id="whasongid" src="http://xxxx.xxxx.net/js/song/u4:2134" type="text/javascript">
You appear to have javascript turned off.
</script>
src="http://xxxx.xxxx.net/js/song/u4:2134" code:
document.write('SONG NAME');
Is it possible to autoupdate just this script without refreshing the whole page ?
You might be in need of Ajax functionality. Do you mean that, at the end of a song playing, you want to modify the page content to reflect the song change? If it is so, you might gain a lot by looking into a JavaScript framework like jQuery or Backbone.js and bind some behavior to the state change in question. So you will want the song change (for example) to trigger a certain function you will have prepared, which will use jQuery to query the server via Ajax to update the page, and change the DOM accordingly.
EDIT: If instead of waiting for an explicit state change in your web page, you wanted to update it periodically, you might be looking for such a strategy :
function updatePage(/* arguments */) {
// Call the server to get some data ...
// Update the page accordingly ...
if (/* continue updating the page? */) setTimeout(60000 /* 60 seconds */, updatePage);
}
If you were using jQuery for your Ajax needs for instance, that function could look like so :
function updatePage(/* arguments */) {
jQuery.get("/your/url", {foo: "bar"}, function(data) {
// Update the page accordingly ...
if (/* continue updating the page? */) setTimeout(60000 /* 60 seconds */, updatePage);
});
}
If you want some more specific help, don't hesitate to be more precise as to what your issue is.

jQuery $.each()-problem

im making a wordpress plugin and i have a function where i import images, this is done with a $.each()-loop that calls a .load()-function every iteration. The load-function page the load-function calls is downloading the image and returns a number. The number is imported into a span-element. The source and destination Arrays is being imported from LI-elemnts of a hidden ULs.
this way the user sees a counter counting from zero up to the total number of images being imported. You can se my jQuery code below:
jQuery(document).ready(function($) {
$('#mrc_imp_img').click(function(){
var dstA = [];
var srcA = [];
$("#mrc_dst li").each(function() { dstA.push($(this).text()) });
$("#mrc_src li").each(function() { srcA.push($(this).text()) });
$.each(srcA, function (i,v) {
$('#mrc_imgimport span.fc').load('/wp-content/plugins/myplugin/imp.php?num='+i+'&dst='+dstA[i]+'&src='+srcA[i]);
});
});
});
This works pretty good but sometimes it looks like the load function isn't updating the DOM as fast as it should because sometimes the numbers that the span is updated with is lower than the previous and almost everytime a lower number is replacing the last number in the end. How can i prevent this from happening and how can i make it hide '#mrc_imp_img' when the $.each-loop is ready?
AJAX calls which have been called earlier are not guaranteed to finish earlier so the smaller number can overwrite the bigger. One solution is to simply increment the counter on each successful call:
jQuery(function($) {
$('#mrc_imp_img').click(function(){
var dstList = $("#mrc_dst li");
var srcList = $("#mrc_src li");
dstList.each(function(i) {
var dst = $(this).text();
var src = srcList[i].text();
$.post('/wp-content/plugins/myplugin/imp.php?num='+i+'&dst='+dst+'&src='+src, function() {
$('#mrc_imgimport span.fc').text($('#mrc_imgimport span.fc').text()+1);
});
});
});
});
(Changed the code to avoid unnecessary array operations, changed onready call to use shorthand, changed AJAX call to use POST which should be used for operations that change state.)
Most servers likely have a finite number of threads running. If you're firing off 10 calls at once, and your server only has 5 threads, 5 of them will fail.
Also - once you max out all the running threads, no other users can access the server, so you're essentially DOS-ing the server.
If you don't mind slowing it down to one call at a time, do what Tgr recommended which serializes the calls, waiting until each one completes before starting the next one.
I would prefer what Yoda suggested. What you can do is turn it into one server call that processes the entire array. If you really want to update a counter client-side, that one server call can update a counter in the database - and then a 2nd ajax call can poll the server every few seconds to find out where the counter is. Obviously wont be guaranteed to be sequential but will be better for your server health. You could also fake the sequential aspect (if you're on #3 and the next call yields a #6 - increment it client side one by one)
As far as not seeing an alert, there is probably a javascript error before or on the alert line. Try using firebug and the console.log statement, or even bette, step through it with the firebug debugger.

Categories

Resources