Oracle APEX Dynamic Actions locks page - javascript

I have a dynamic action in Oracle APEX PAGE, that executes PL/SQL CODE (a stored procedure that creates a BLOB)
So when the users clicks on it, the javascript behind (dynamic actions, 'runs' the PL and the page is 'locked' until everything finishes)
How can I make something that doesn't lock the browser entirely until this process is finished?
Thank you

One straight-forward way, if you haven't moved to version 5 yet is to use the APEX_PLSQL_JOB package.
Define the functionality you need inside the database, in a function or procedure in a package.
Then, start the function in the background using the API.
For example, if you have defined a procedure upload_pending inside a package PROJECTX_IO, then you can start it with:
declare
p_job number
begin
p_job := apex_plsql_job.submit_process(
p_sql => 'BEGIN PROJECTX_IO.upload_pending; END;',
p_status => 'Uploading');
end;
You are currently not doing anything with the job id returned in p_job. What works, if you know you only have a single background job running at any time, is to add it to a one-row table in the database. This simply goes to the bottom of the code snippet above (before the end;):
delete from t_job;
insert into t_job values ( p_job );
Then, inside the background process, you have access to the job id of the process. You could change the job status at the end with:
select job into p_job from t_job;
apex_plsql_job.update_job_status(p_job,
'Upload complete');
How to deal with multiple background jobs?

Related

How to transfer array values in JS to html before the file switches using Ajax

This is the HTML code in file 1, which is calling the function. It is linked to javascript
<form id='next' action='file2.html'>
<button id="nextTwo" onclick="nextTwo()">next2</button>
</form>
This is the JS code that receives the function.
function nextTwo(){
document.getElementById('question').innerHTML=question
}
It is searching for the id before the file changes to where the id is.
Every time I press the button that calls the function it gives me:
"TypeError: Cannot set properties of null (setting 'innerHTML')"
This is because it is searching for the id of "question" in file 1, but the id is in file 2. It tries to find the id in file 1, then it switches to file 2, where the id of "question" is.
How do I make it so that is switches to file 2 first, then searches for the id.
Maybe an if statement with a condition, if the file is switched, although I don't know the how to write that.
Thanks for your help.
This is my Js code, how do I place the arrays value into the file 2 using ajax?
let ants;
let question;
let squestion;
function check() //CHECK
{
switch(1){ //different header number is fine but do '' BUT input box will still be there
case 0:
ants = ['calculations']
question=["Element Symbol that has the atomic number of... ","atomic mass of (round to nearest whole number)..."]
squestion=["1. 50","2. 2","3. 20","4. K"]
case 1:
ants = ["0 (all atoms have a charge of 0)","11","11","4","9","Be","8","8","8"]
question=["Sodium has 11 protons and an mass of 23. What is the...","An atom has an atomic# of 4 and 5 neutrons What is the...", "Oxygen has 8 electrons and a mass of 16"]
squestion=["charge","atomic#","#of electrons", "#of protons","Mass","element symbol", "#of protons", "atomic#", "#of neutrons"]
// ants = ["Sn ","He ","Ca ","39 ", "32 ","Sn ","He ","Ca",]
// question=["Element Symbol that has the atomic number of... ","atomic mass of (round to nearest whole number)..."]
// squestion=["1. 50","2. 2","3. 20","4. K"]
break;
case 2:
ants = ["Carbon", "Chlorine", "Bromine",'Br',"Li","Sc","2","8","8" ]
question=["Carbon", "Chlorine", "Bromine", "Helium",'Br',"Li","Sc" ]
squestion=[]
}
There is a better way to go about this.
By design, forms do not communicate two-way. They take the data entered by the user and carry it over to the processing file (defined by the action= parameter on the form tag). The user is navigated away from the first webpage, and the view changes to that processing file - and it isn't supposed to go back to the first file again. Forms are very basic, primitive constructs.
This is why forms have been almost entirely replaced by AJAX. AJAX is a very simple JavaScript construct (made even simpler via jQuery - TANGENT: although jQuery is no longer recommended because modern JavaScript has made the process much easier - but the jQuery $.ajax() method still works fine and there is tons of info about how to use it).
AJAX allows you to send data from a web page to a back-end (server-side) file that receives any data you send it (optional), does something (optional), and returns new data (optional). The page the user is on need not change, blink or flash. New data received from the server-side file can be received and actively used before returning control to the user... So this sounds like exactly what you need it to do.
The back-end (AJAX) processing file is written in a server-side language (PHP, NodeJS, ASP.Net, Python, etc - PHP is a very popular one for AJAX), but you did not specify which one you wish to use, which is likely why no one responded to your question sooner.
Here are some references that might help. I chose jQuery examples because the AJAX code block $.ajax( //code goes here ).done() is very simple. To do AJAX in pure JavaScript, look for information regarding the Fetch API (newest), and XmlHTTPRequest (older).
Simple jQuery example
Ajax explained with jQuery
Another simple example with explanation
Here is a pure javascript video tutorial (5 mins)
After reviewing the examples, you can construct a basic AJAX test on your side and, if you have any trouble with it, ask another question specifying which language you are trying to do this with, and showing your code so far.

Attempting to use .get method on java variable in javascript

I'm trying to create a webpage (using the play framework) which displays the user's name, date of birth etc. Where I am getting stuck is attempting to display a list of unknown size in an html page. I currently have:
#(currentUser : Profile)
#main("Profile") {
<div>
<h1><b>#currentUser.getFirstName() #currentUser.getLastName()</b></h1>
<p>#currentUser.getDateofBirth</p>
<b>Nationalities</b>
<ul><p id="natInput"></p></ul>
<script>
for (var i = 0; i < "#currentUser.getNationalities().size()"; i++) {
document.getElementById("natInput").innerHTML += "<li>" + "#currentUser.getNationalities().get(i)" + "</li>";
}
</script>
</div>
}
Profile is a basic java class which only contains getters and setters, and .getNationalities returns a List.
#Main is another html file which stores the base design of the website, not really relevant to this.
As you can see, I'm trying to use the .get method to loop through the list of nationalities for the user, but unfortunately the "i" variable used in the get is not recognised, as it is a javascript variable in html.
Every other part of this code appears to work as expected, and the .get works when the "i" is replaced with an integer, such as 0 or 1.
Any ideas how I could get each individual element of this list? Any help would be greatly appreciated
The problem is that you are messing up different step of the page generation.
First of all we should clear out the processing steps from a render command in a Play controller to a fully rendered page in the browser.
Twirl is a template engine that allow you to generate HTML pages with Scala.
This step is performed on server side, before the HTML page is sent to the browser.
In this step the Javascript code is not being considered.
So the first step after the render command, the twirl template is picked and rendered, evaluating each Twirl/Scala instructions. This will generate an HTML file with no more Scala code.
This generated page is sent to the browser. Then the page is loaded into the browser and the Javascript code is evaluated as any other HTML page with JS.
This would explain why you are not able to render the page the way you are doing.
A proper way, if your page is static, is to use only twirl instructions to iterate over the array Twirl Template - Iterating
You should be able to rewrite your list generation like the following if getNationalities() method returns a Scala List
<ul>
#for(nationality <- currentUser.getNationalities()) {
<li>#nationality</li>
}
</ul>

Check when a Oracle 11gR2 scheduled job has completed and alert the user in Oracle APEX

Within Oracle APEX v4.2, I have an application by where a user presses a button which then goes off and submits a scheduled background job, allowing the user to continue working within the application. The job is kicked off using Oracle's DBMS_SCHEDULER.
My question is and want to keep it within the Oracle APEX space - assuming there is a table that stores when the job was initiated as well as when it eventually completes, how can I interact with this table, check whether the job has completed (i.e. somehow poll the table and stop when the "COMPLETE" status is found) and then, provide an 5 second alert that slides in and then slides out, notifying the user that the job has completed.
Can I use JavaScript (callback) via Dynamic Actions?
If you don't want to go down the plugin route, you can use the following code in an Application Process, called ProgressCheck in this instance:
DECLARE
CURSOR c_time_elapsed
IS
SELECT SUBSTR(elapsed_time,6,2)||'hrs '
||SUBSTR(elapsed_time,9,2)||'mins '
||SUBSTR(elapsed_time,12,2)||'secs' ELAPSED_TIME
FROM user_scheduler_running_jobs
WHERE job_name = 'XX_YOUR_JOB_NAME'
UNION ALL
SELECT '00:00'
FROM DUAL
WHERE NOT EXISTS (SELECT SUBSTR(elapsed_time,9) ELAPSED_TIME
FROM user_scheduler_running_jobs
WHERE job_name = 'XX_YOUR_JOB_NAME');
BEGIN
FOR r_time IN c_time_elapsed LOOP
htp.p('<p>Time elapsed: '||r_time.ELAPSED_TIME);
END LOOP;
htp.p('');
END;
In the Page header, include the following JavaScript:
<script type="text/javascript">
<!--
var myInterval;
function f_ProgressCheck(){
var get = new htmldb_Get(null,$v('pFlowId'),'APPLICATION_PROCESS=ProgressCheck',$v('pFlowStepId'));
gReturn = get.get();
get = null;
gReturn = (!gReturn)?'null':gReturn;
$s('P1_PROGRESS_RESULT',gReturn);
}
function f_myInterval(){
myInterval = setInterval ( "f_ProgressCheck()", 5000 );
}
//-->
</script>
This will call the Application Process every five seconds once your page has loaded and will put the results of the check into P1_PROGRESS_RESULT.
You can amend the Application Process to suit your requirements, perhaps returning something else or additionally checking for completion, like in the following code:
DECLARE
CURSOR c_job_count
IS
SELECT COUNT(*) TOTAL
FROM user_scheduler_job_log
WHERE job_name = 'XX_YOUR_JOB_NAME'
AND log_date >= (SYSDATE - 1/1440);
BEGIN
FOR r_job_count IN c_job_count LOOP
IF r_job_count.total = 1 THEN
htp.p('<p>Your data is ready to view.');
htp.p('<p>Click Go to view the report.');
htp.p('<input type="button" onclick="javascript:this.disabled=true;this.value=''Please wait...'';doSubmit(''REPORT'');" value="Go" class="RelevantAPEXClass" />');
ELSE
htp.p('<p>');
END IF;
END LOOP;
END;
You could also combine the PLSQL to deliver everything in one process.
You could also call the PLSQL (preferably) using a Dynamic Action.

Asynchronous AJAX Calls in orderd manner

Hi firstly sorry for my bad English. I Already searched in SO. but i didn't get the exact answer i needed.
My issue is i need to synch the Ajax request. i know we can use the "asynch : false ".
but this will make browser locked. I have a folder tree(i am using "tafel tree" js) in my web. the tree nodes are generated at run-time. each time
user click a node it will send request to server and add the node to the tree.
but issue is if the page is refreshed by clicking f5 then i need to load the tree structure that i already selected previously.
i implemented it using "asynch : false ". but this will makes browser too slow.
and here what i have
function loadPage() {
/* some other codes are here*/
/* here i call an ajax for get the inside folder list in correct order.(i am usig protoype)*/
new Ajax.Request(ajaxGetInsideFolderIdsUrl,
{
parameters: {branchId: CurrentSelectfolderId},
onSuccess: function(res) {
/* onSuccess i call another function*/
var brs = res.responseText.split(","); // branch ids in correct order.
syncFolder(brs)
}
}
function syncFolder(brs){
for(var i= 0 ; i < brs.length; i ++){
var tempbranch = tree.getBranchById(brs[i].getId());
selectAfterChange( tempbranch)
/*
selectAfterChange function is used for selecting current branch. calling "tafle tree" select() function in side it.
i just created an copy of "select()","_openPopulate()" functions used in "tafle tree" and modified it with "asynch : false ".and now its working fine.
*/
}
}
function selectAfterChange(brs){
brs.chk_select();
/* for selecting the branch (created a copy of current "select()" function used in "tafle tree" js
and modified it with "asynch : false "and now its working fine.) */
showList();// for listing items in side that folder (in another Ajax page).
}
My problem is if a user opened a long branch.
And then refresh the page it will take too much time to load because of synch Ajax call.
Taking too much time is not an big issue to me. but the browser is get locked until all the request executed.
is there any other way to do this.
I'm not familiar with the tree library you're using, but in general, the way you'd solve this is to store the currently expanded path(s) in the browser (local storage, or cookies, or wherever), and when you refresh the page, load just the nodes that are visible.
Let's say that the user is currently looking at path one/two/three/four. You save that path somewhere, and then when the page loads again, you create a queue of paths to request from the back end, by splitting the path, and appending the components of the path one by one:
["one", "one/two", "one/two/three"]
You then send the AJAX request for "one", and when you get the result back, update that node in the tree, and send a request for "one/two". When that request returns, update the tree, and send the request for "one/two/three".
Depending on your design, you can then start filling in the rest of the tree with more async requests...

YUI Datatable - call arbitrary function *once* on sort

We're using a lot of YUI data tables to display data, and rather than using the built-in pagination we've done our own so we can paginate on the server side using AJAX without downloading the whole data set (which is often huge).
Whenever we use the data table's sorting funcionality, though, it will only sort the one page because from YUI's point of view that's the entire data set.
I need to be able to call an arbitrary function to reload the page data whenever the user tries to sort the data. I've looked into DataTable's sortFunction parameter and it's not ideal because it gets called multiple times (once for each row combination it needs) and I need to do it just once.
There are probably plenty of hacky ways I could do this, but what's the "nicest" way of going about this?
Ideally, you would sort on the server side.
when create the datatable, one of the config options is generateRequest (see this example: http://developer.yahoo.com/yui/examples/datatable/dt_bhm.html )
generateRequest is a meant to be a function which generates a URL which returns the correct data set with which to fill the table. You probably have this.
For me, whenever I click on the column header (to sort), it makes a new request to the server, getting the correct page of sorted data.
Why not write a custom function and close over a variable that tracks whether it's been called?
var hasBeenCalled = false;
function mySortFunction(){
if(!hasBeenCalled){
// do something
hasBeenCalled = true;
}
}
Then replace the sortFunction with that.

Categories

Resources