How can I execute an apex process from javascript - javascript

I am very new to javascript and apex and am learning on the job so to speak.
Let me start of by describing what I want to achieve:
I'm trying to block the Function keys from running/executing the browser functions (F1 to bring up help, F3 for find, etc). I found the javascript code to block them, but do not know what to do after that.
Eg, when a user presses F1 it should not display help, but execute a process in apex.
Such a process could for example be to save all information on the apex page text fields to the database.
How can i do this?
See my example code: instead of the alert, how would I go about executing a process and how do I go about writing such a process?
<script language="javascript">
function my_onkeydown_handler() {
switch (event.keyCode) {
case 112: // 'F1'
document.onhelp = function() {
return (false);
}
window.onhelp = function() {
return (false);
}
alert("F1");
NewEntry();
break;
}
}
</script>

$(document).keydown(function(e){
if(e.which===112){
console.log('F1ed');
//NewEntry();
return false;
};
});
Safe to use jQuery, it comes with apex
Also see
Disable specific function key using jquery
Which can be translated to a dynamic action (you didn't specify an apex version. Dynamic actions were introduced with version 4.0). Why would you use them? They're very handy in that you can use them to easily leverage javascript without really knowing a lot about it, and they can be seen in the page structure. This way you don't need javascript cluttering about in several portions of your page. Even for more advanced javascript for which there are no pre-defined actions, you can still put your own code in by using 'Execute Javascript'. Again, accessibility and maintainability! Leverage it!
Create a new dynamic action.
Event: Key Down
Selection Type: DOM Object
DOM Object: document
Condition: None
As for the (true) action:
Action: Execute Javascript Code
Code:
var e = this.browserEvent;
switch (e.which) {
case 112: // 'F1'
alert("F1");
return false;
}
Much nicer and cleaner. And better you get comfortable with them now! Read up on them too.
On to the second part:
What i mean is that when eg F1 is pressed it must not display help
but execute a process in apex for example I would like to save all
information on the apex page text fields to the database. How would I
go about it. See my little code, instead of the alert, how would I go
about executing a process and how do I go about writing such a
process?
This makes me wonder (and frown, but just a little). How familiar are you with apex already? No offense, but this is rather basic functionality you're asking about.
Say you have a report and a form page, generated by the wizard. Say you have no weird things such as this javascript on it, but just barebones.
You go from the report to the form page. Values are fetched through a process and the page is rendered. Now you alter some values and submit the page. The submitted values are then processed in the page processing, and pass through the row processing process, which will insert/update/delete data.
If you are unfamiliar with that concept, i strongly recommend you to at least follow through the Oracle® Database 2 Day + Application Express Developer's Guide (Oracle Apex documentation). Many developers just jump in head-first without giving this guide a glance. Don't. This SHORT (and really, what are maybe a couple of hours) guide will teach you some of the very basics of apex!
Important things such as session state and submitting the page are crucial to understanding what it does.
Now, assuming we have a form page with this bit of javascript on it. Pressing F1 to update the values (read: press F1 to submit the page and invoke the row processing to process the submitted values), you can use the apex javascript api's: apex.submit('APPLY') (DOC).
This will submit the page with request APPLY. This value is important. Note that buttons will submit with their name set to request value aswell, and the row processing does different processing based on a list of valid request values.
var e = this.browserEvent;
switch (e.which) {
case 112: // 'F1'
alert("F1");
apex.submit('APPLY');
return false;
}
Further elaboration:
There are also AJAX Callbacks. These are processes on the serverside which can be invoked through a javascript call to the server. These processes are PLSQL-code, and can for example be used to return data to the calling javascript function, and avoid a full page refresh/submit.
It can be used to save data too of course. The data has to be passed to the server, and the process then works with that data. For example, when a field has been changed and you want to immediatly save this to the database but do not want a full page submit. The callback would be a plsql block which performs an update on a table.
Ajax callbacks are very interesting and useful, but i'd advise you to first get a good grip on the basics before tackling this!

Modified code: jsfiddle
<script language="javascript">
document.onkeydown = function (e) {
switch (e.keyCode) {
case 112: // 'F1'
e.preventDefault(); // prevent default behavior.
e.returnValue = false; // for IE to prevent default behavior.
alert("F1");
NewEntry();
return false;
}
}
</script>​

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.

When using a string to call a function from another function, how would one go about it?

For clarity:
The user will never be expected to input code. User inputs, aside from name customization (which customized names will NEVER be run through code), will be limited to button presses (which will then potentially activate functions which are waiting in the database entries).
I have one defined constructor in my javascript code, and essentially will have a database which allows the user certain inputs, be they pre-defined inputs (the majority of the time) which will execute other code or customized inputs (which would never have the potential to change anything which can execute code).
An example would be the following code: new DatabaseItem("511", ["feat", "general", "1"], "Armor Proficiency", ["description", "if(database[5][0][0].returnData().includes(0)){possible=["500","Cancel"];database[5][0][0].forEach(function tempFunction(value,index){if(value==0){possible.push(index);}});}else{database[5][0][0].addTrait("invalid");alert("No eligible targets. Please select another feat.");}"])
which would create a new DatabaseItem at position 511 with traits "feat", "general", "1"; the title "Armor Proficiency"; and data of "description" and would execute the following code when triggered:
if(database[5][0][0].returnData().includes(0)) {
possible = ["500", "Cancel"];
database[5][0][0].forEach(
function tempFunction(value, index) {
if(value==0) {possible.push(index);}
}
);
} else {
database[5][0][0].addTrait("invalid");
alert("No eligible targets. Please select another feat.");
}
Then after the user selects a choice (be it "Cancel", or one of the valid indexes) supposing that choosing this was valid in the first place, it would then execute more code based on the user's choice.
Based on what I've read, the eval() function would work (but is generally considered unsafe) but Function() may also work. What would be the recommended course of action?
Relevant information:
-this is a stand-alone webpage-based application. The framework is provided in the html file, and this is an excerpt from the js file.
-nothing is stored after the webpage is closed. Save data is generated via a savestring which implements changes the user makes and the positions of said changes, which the user is then free to copy to a text file. Invalid savestrings would be rejected by the loader.

Change URL data on page load

Hello I have a small website where data is passed between pages over URL.
My question is can someone break into it and make it pass the same data always?
For example let say, when you click button one, page below is loaded.
example.com?clicked=5
Then at that page I take value 5 and get some more data from user through a form. Then pass all the data to a third page. In this page data is entered to a database. While I observe collected data I saw some unusual combinations of records. How can I verify this?
yes. as javascript is open on the website, everyone can hack it.
you will need to write some code on you backend to validade it.
always think that you user/costumer will try to hack you sytem.
so take precautions like, check if user is the user of the session, if he is logged, if he can do what he is trying to do. check if the record that he is trying get exists.
if u are using a stand alone site, that u made the entire code from the ashes, you will need to implement this things by yourself.
like using the standard php session, making the data validation etc.
or you can find some classes that other people have made, you can find a lot o this on google. as it is a common problem of web programing.
if u are using a backed framework that isnt from another world, probably already has one. sp, go check its documentation.
html:
<a id = 'button-one' name = '5'> Button One </a>
javascript:
window.onload = function() {
document.getElementById('button-one').onclick = function() {
changeURL(this.attributes.name.value);
};
};
function changeURL(data) {
location.hash = data;
}

JSF can't invoke Form reset button programmatically, or, reset Session variables

Lots of time spent with other language/templating-engine combinations, however fairly new to JSF and have the "pleasure" of taking over a legacy JSF 1.1 project that uses a basic Sun JSF lib and for political reasons can not be updated to something more modern like JSF 2.2 with PrimeFaces or IceFaces, which I'd personally like to do after reading up on the capabilities of those.
The setup is a simple web app with landing page plus two tabs (Person & Address), each powered by their own Backing Beans and JSF pages. Six total navigation states as each tab starts with a "Search Form" page which leads to a "Search Results" page on submit and then a "View" page onmousedown (click action) of an individual result; for each of Person & Address data. The "Search Form" pages are session-scoped, and designed to pass search parameters around to each other in a header box entitled "User's Search Query". It does this because the "Search Results" page for Address searches is really an overloaded Person search result with Address thrown in for "Search for People by Address". Yes this could all probably be accomplished from a single page with some optional search params, but its not, and for whatever reason I'm not permitted to change the core page structure, just tasked to bug fix.
There's a long-standing bug I've been asked to fix, where one page (Person) always shows search parameters from the other (Address) when both are set, because of some incomplete logic (inside the panelGrid where the search query parameters are displayed):
<h:outputText value="Coverage Type:"/>
<h:outputText value="#{addressSearchUI.searchParameters.coverageType}"
rendered="#{empty personSearchUI.searchParameters.coverageType}"/>
<h:outputText value="#{personSearchUI.searchParameters.coverageType}"
rendered="#{!empty personSearchUI.searchParameters.coverageType}"/>
A little too overly simplistic; if a Person search's Coverage Type was set, use that, but if not, try to use the Address coverageType search parameter. Works great when only one or the other were set.
PROBLEM CASES:
Since they are session scoped, what if both of them were set in separate searches and we're on the Address page? The value from the old Person search displays (and vice versa; this is the main problem). What if neither of them are set yet? It should show a default value of ALL COVERAGE, easy enough to add but doesn't address that main problem.
SOLUTION:
Thought this would be an easy fix but I've hit a major wall trying to do either one of the following two simple things that I think would solve my problem:
A) get the session-scoped value of one page's search parameter and reset it or set to empty string (then that naiive presentation logic could be left as is)
B) call the reset button of one page programmatically from Java when backing bean init() method gets called as we switch tabs (I can call the method but am not sure how to get the original session instance rather than creating a new one, which will fire to a non-existent page UI-wise)
Here's what I've tried so far:
A) Adding an actionListener attribute to the submit button itself and trying to forcibly reset values from the other Search Form.
<h:commandButton
id="personReset"
styleClass="submitButton"
value="Reset"
action="#{transactionSearchUI.resetSearch}"/>
<h:commandButton
id="personSearch"
styleClass="searchButton"
value="Search"
rendered="#{personSearchUI.canDo['performSearch']}"
actionListener="#{addressSearchUI.resetSearch}"
action="#{personSearchUI.performSearch}"/>
B) In the backing bean of each search, try to invoke the reset button of the other:
/* utility method */
private UIComponent findComponent(String id, UIComponent where) {
if (where == null) {
return null;
}
else if (where.getId().equals(id)) {
return where;
}
else {
List<UIComponent> childrenList = where.getChildren();
if (childrenList == null || childrenList.isEmpty()) {
return null;
}
for (UIComponent child : childrenList) {
UIComponent result = null;
result = findComponent(id, child);
if(result != null) {
return result;
}
}
return null;
}
}
//... then inside init() method that is called when Person tab loads
FacesContext facesContext = FacesContext.getCurrentInstance();
UIViewRoot root = facesContext.getViewRoot();
HtmlCommandButton button = (HtmlCommandButton) findComponent("addressReset", root);
ActionEvent actionEvent = new ActionEvent(button);
actionEvent.queue();
Fails with NullPointerException, so clearly can't access one tab from the other's backing bean in this way (unless I'm missing something).
C) JavaScript approach to reset values from one tab to the other:
<script type="text/javascript">
function clearAddressSearchParams() {
document.getElementById('AddressSearch:addressSearch:addressReset').click();
document.forms['AddressSearch:addressSearch'].reset();
return false;
}
window.onload = clearStats;
</script>
Neither of those client-side methods of trying to fire the "Reset" button action are going to work, since again, the "Person" and "Address" Search Forms were setup as two totally separate beans and pages (even though one ultimately extends the other), one won't be active (or available in the DOM) so it won't find the elements.
At this point, I know there is clearly a simpler solution, but I'm at my wits end and probably coming at this from the wrong angle, so I don't know what else to do but put up a bounty for some of the JSF geniuses here. But if anyone can suggest a fix (given my limitations of older JSF technology, no adding external libs and maintaining same basic code structure), you'll get the bounty and tons of appreciation.
EDIT: To summarize all this into a single question, can anyone suggest a reliable (legacy-JSF 1.1 compatible) way to flush a session variable or reset it, independently of its page where it gets set being active?

Filling log in form with zombie in node.js

Evening! I'm trying to log in into a website with zombie.js, but I don't seem to be able to make it work.
Oh and the website is in Finnish, but it's not very hard to understand, two text fields and a button. First is for username, second for password and the button is the log in button.
At the moment my log in code is as follows:
var Browser = require("zombie");
browser = new Browser();
browser.visit("https://www.nordnet.fi/mux/login/startFI.html?cmpi=start-loggain",
function () {
// Here I check the title of the page I'm on.
console.log(browser.text("title"));
// Here I fill the needed information.
browser.document.getElementById("input1").value ="MYUSERNAME";
browser.document.getElementById("pContent").value ="MYPASSWORD";
// And here it fails. I try to submit the form in question.
browser.document.getElementById("loginForm").submit();
setTimeout(function () {
// This is here to check that we've submitted the info and have been
// redirected to a new website.
console.log(browser.text("title"));
}, 2000);
});
Now I know that I maybe should have used zombie's own "fill" method, but I tried that with no luck so I tried something new.
All I get from this is an error:
Y:\IMC\Development\Web\node_modules\zombie\lib\zombie\forms.js:72
return history._submit(_this.getAttribute("action"), _this.getAttribute(
^
TypeError: Cannot call method '_submit' of undefined
Now if I log that browser.document.getElementById("loginForm") it clearly does find the form, but alas, it doesn't like it for some reason.
I also tried the "conventional" method with zombie, which is using that log in button on the web page and pressing it. The problem is that it's not actually a button, just an image which has a link attached to it, and it's all inside <span>. And I have no idea how I can "click" that button.
It has no ID on it, so I can't use that, then I tried to use the text on it, but because it has umlauts on it I can't get it to work. Escaping the ä with /344 only gave an error:
throw new Error("No BUTTON '" + selector + "'");
^
Error: No BUTTON 'Kirjaudu sisään'
So yeah, that didn't work, though I have no idea why it doesn't recognize the escaped umlaut correctly.
This is my first question, the second one is a minor one, but I though why not ask it here too now that I've written this text.
If I get all this to work, can I somehow copy the cookie that this log in gives me, and use that in my YQL for screen scraping? Basically I'm trying to scrape stock market values, but without the log in the values are 15min deferred, which isn't too bad, but I'd like it to be live anyhow.
After couple of tests using zombie I came to the conclusion that it's still to early to use it for serious testing. Nevertheless, I came up with working example of form submit (using regular .submit() method).
var Browser = require("zombie");
var assert = require("assert");
browser = new Browser()
browser.visit("http://duckduckgo.com/", function () {
// fill search query field with value "zombie"
browser.fill('input[name=q]', 'mouse');
// **how** you find a form element is irrelevant - you can use id, selector, anything you want
// in this case it was easiest to just use built in forms collection - fire submit on element found
browser.document.forms[0].submit();
// wait for new page to be loaded then fire callback function
browser.wait().then(function() {
// just dump some debug data to see if we're on the right page
console.log(browser.dump());
})
});
As you can see, the clue is to use construct browser.wait().then(...) after submitting the form, otherwise browser object will still refer to the initial page (the one passed as an argument to visit method). Note: history object will contain address of page you submitted your form to even if you don't wait for the page to load - it confused me for a bit, as I was sure that I should already see the new page.
Edit:
For your site, the zombie seems to be working ok (I could submit the form and get "wrong login or password" alert). There are some JS errors but zombie isn't concerned with them (you should debug those however to see if the script are working ok for regular users). Anyhow, here's the script I used:
var Browser = require("zombie");
var assert = require("assert");
browser = new Browser()
browser.visit("https://www.nordnet.fi/mux/login/startFI.html?cmpi=start-loggain", function () {
// fill in login field
browser.fill('#input1', 'zombie');
// fill in password field
browser.fill('#pContent', 'commingyourway');
// submit the form
browser.document.forms[0].submit();
// wait for new page to be loaded then fire callback function
browser.wait().then(function() {
console.log('Form submitted ok!');
// the resulting page will be displayed in your default browser
browser.viewInBrowser();
})
});
As side note: while I was trying to come up with working example I've tried to user following pages (all have failed for different reasons):
google.com - even though I filled query box with a string and submitted the form I didn't get search results . Reason? Probably google took some measures to prevent automatic tools (such as zombie) to browse through search results.
bing.com - same as google - after submitting the form I didn't get search results. Reason? Probably same as for google.
paulirish.com - After filling in the search query box and submitting the form zombie encountered script errors that prevent it from completing the page (something about missing ActiveX from charts script).
perfectionkills.com - Surprisingly here I've encountered the same problems as with Paul Irish site - page with search results couldn't be loaded due to javascript errors.
Conclusion: It's not so easy to force zombie into doing your work after all... :)

Categories

Resources