Not getting form-elements of external page in FireFox - javascript

I am using weblogic 8.1.6. My problrm is I have a parent page that is using Ajax to call a child page. The Child page is executed Into the Parent Page. Parent page has a form and a javascript function to read all the elements of the form but the javascript function is not able to read the elements of child page. I am using " form.elements[i].name " which is working fine in IE but not in firefox and chorme . What should i use to read the element of child page that is executed inside parenPage.
parent code
<form id="Tab">
<input type="button" onclick="alert('calling AjaX Method');" value="ADD" />
<div id="ChildOutputWillDisplayedHere"></div>
</form>`
childCode
<input class="FormFields" type = "text" name = "NameID" value = "">
click Me `
javascript code
callingJavscriptFunction(){
var form = document.forms['tab'];
for(var i=0; i<form.elements.length; i++)
{
var fieldName = form.elements[i].name;
}
}

It seems, that IE gives you all input-elements in the form, even if they didn't have name-attribute. Your input in Tab however lacks the name-attribute, which you try to read in the function. AFAIK this code will assign undefined to fieldName in IE also.
Looping like this will assign only the name of the last element in the elements-collection to your fieldName-variable. No problem with one input-element, but if there are more...

Related

How to dynamically call a servlet initiated by client interaction to display html in div (not iframe) without triggering page reload

I am writing an extension for a web application. Its API has an interface IFormExtension which needs to be implemented and provides access to the database and has a String render() method, which is called to get the html which will be placed within the existing html of the web application.
I know there are multiple topics on the different aspects mentioned in my question, but until now I am failing to combine the different solutions of each of the "trivial" subtopics to one working solution for my "complex" scenario:
The idea of the extension is to load and display various objects from the database in a list or table, each entry accompanied by a button which causes that additional html (unique to the item it belongs to) gets loaded dynamically from a servlet to be displayed within the existing html - without triggering a reload of the page.
This is my current approach:
// all html I want to pass must be present in the returned String
// of this method due to the API of the web application and will
// be placed within a div in the existing html
public String render(..){
// getting items from database
String html = "..."; // here the html (see below) is build with values from the items where necessary
return html;
}
here the architecture of html that render() will return:
<div>
<table>
<tbody>
<tr>
<!-- the curly braces expressions are a placeholder for values which will be inserted by the java code above -->
<td>
<form onSubmit="return loadFromServlet({itemId});">
<input id="property_{itemid}" type="hidden" value="{itemid.myProperty}">
<input type="image" src="{path_to_image}">
</form>
</td>
</tr>
<!-- more tr's with different itemId's... -->
</tbody>
</table>
</div>
<!-- html from Servlet should show up in this div: -->
<div id="dynamicallyLoadedHtmlHere"/>
<!-- the javascript shows up in the terminal script tag:-->
<script>
// see the javascript below
</script>
here the javascript:
"use strict";
function loadFromServlet(itemId){
var xhr = new XMLHttpRequest();
//xhr.addEventListener("load", showDynamicHtml); // I intuitivly wanted to do something like this, but i can't pass a parameter to showDynamicHtml (or at least I don't know how); therefore:
xhr.open("POST","my/servlet/uri",true);
var params = "ItemId=" + itemId;
params += "&MyProperty=" + document.getElementById("property_"+itemId);
xhr.onload = function (evnt) {
document.getElementById("dynamicallyLoadedHtmlHere").innerHtml = xhr.responseText;
evnt.preventDefault();
}
xhr.send(params);
return false;
}
The image in the form is supposed to work as a submit button, which worked in a previous approach, when the form still had the action="my/servlet/uri" method="POST" target="someIFrameId" attributes before I found the onSubmit approach. I moved away from the first approach because the target should be a div and not an iframe. But now the function loadFromServlet doesnt seem to be executed (when I add console.log("debug")s nothing shows up in console and the whole webpage refreshes - i.e. not the intended or expected behaviour. I'm having doubts, if the script is even in the scope of the form(s)?
Summary:
The html and the script which gets returned from the render() method show up in the target web page just fine.
The javascript code somehow doesn't get executed when clicking the img button though - therefore the servlet isn't called.
I hope I have elaborated sufficiently on my problem.
Try adjusting your onSubmit handler as per below.
I modified the your form to correctly call loadFromServlet and I moved the itemId out of the function parameters and into a data attribute on the form, this way we can use the event object that loadFromServlet will have access to.
We want access to the event object so we can call event.preventDefault() which will stop the page from refreshing.
Then the JS code get the itemId by accessing the data attribute on the form.
Additionally, if you cant get XHR to work for your request, try fetch or even a third-party library like axios.
html
<div>
<table>
<tbody>
<tr>
<!-- the curly braces expressions are a placeholder for values which will be inserted by the java code above -->
<td>
<form onsubmit="loadFromServlet()" data-itemid="{itemId}" data.itemproperty="{itemId.myProperty}">
<input type="image" src="{path_to_image}">
</form>
</td>
</tr>
<!-- more tr's with different itemId's... -->
</tbody>
</table>
</div>
<!-- html from Servlet should show up in this div: -->
<div id="dynamicallyLoadedHtmlHere"/>
js
"use strict";
function loadFromServlet (){
// Stop the form from submitting (and reloading the page)
event.preventDefault(); //event is accessible even though it doesn't show up as function parameter
// Get the parameters
// dataset contains every parameter of a tag prefixed with 'data-'
const itemId = event.currentTarget.dataset.itemid;
const itemProperty = event.currentTarget.dataset.itemproperty;
const URI = 'my/servlet/uri';
// calling encodeURIComponent() on parameter values to escape potential illegal uri characters
const params = '?ItemId=' + encodeURIComponent(itemId);
params += '&myProperty=' + encodeURIComponent(itemProperty);
fetch(URI + params)
.then(response => response.text())
.then(data => {
document.getElementById("dynamicallyLoadedHtmlHere").innerHTML = data;
});
}
Edit:
I fixed some errors in the above code I found while debugging the approach suggested by this answer and added some comments for clarity.

Is there a to change the value of an element using JavaScript

I'm trying to change the value of an element on a third-party web page using a JavaScript Add-on to display a hyperlink
I already have the link on the page i would like to be able to click it
I think I'm on the right track using document.getElementById although I'm not sure how to then change the id into a "a href" and then how to pass it back into the value.
Sorry, this is a bit of a tricky situation so I'll try my best to explain it. On a third-party web-page which we use for our HR related tasks, there is a section titled "File Link" although this isn't a link. When you copy and paste the address into a browser it displays the file. What i am trying to do is create a hyperlink on the "File Link" section to remove the need to copy and paste the link. Because this is a third party website. We have access to the JavaScript on the website and need to change the address into a hyperlink. I'm not entirely sure this is possible.The element id is "__C_cb_file_link" and i would like to insert the link address into the element using a variable then add the link parameters into the variable then reinsert it into the element/value.
function linkIt() {
var intoLink = document.getElementById("__C_cb_file_link");
var hLink = "<a href="+intoLink+"</a>;
intoLink.value = hLink;
}
window.onload = linkIt();
<td><div class="sui-disabled" title="">m-files://view/37FF751C-A23F-4233-BD8B-243834E67731/0-46524?object=C46A7624-D24B-45F3-A301-5117EFC1F674</div>
<input type="hidden" name="__C_cb_file_link" id="__C_cb_file_link" value="m-files://view/37FF751C-A23F-4233-BD8B-243834E67731/0-46524?object=C46A7624-D24B-45F3-A301-5117EFC1F674"/></td></tr>
In below code first we read input value with new link (however we can read this value from other html tags), then we remove this element (and button) and add to parent element (of removed input) the new link
function linkIt() {
let intoLink = __C_cb_file_link.value;
let parent = __C_cb_file_link.parentNode;
__C_cb_file_link.remove();
btn.remove();
parent.innerHTML += `${intoLink}`;
}
<input id="__C_cb_file_link" value="https://example.com">
<button id="btn" onclick="linkIt()">Link It</button>
There are a number of issues with your code:
1) The code snippet in your question doesn't run because of a missing " at the end of the second line of the linkIt() function.
2) intoLink is a hidden field so anything you add to it will not be visible in the page
3) Even if point 2 were not true, setting the value of a form field will not cause HTML to appear on the page (at best you might get some plain text in a textbox).
4) "<a href="+intoLink+"</a>" doesn't work because intoLink is a complex object which represents the entire hidden field element (not just its value property). You can't convert a whole object into a string directly. You need to extract the value of the field.
A better way to do this is by creating a new element for the hyperlink and appending it to the page in a suitable place. Also I recommend not adding your event via onload - when written using this syntax only one onload event can exist in a page at once. Since you're amending another page which isn't under your control you don't want to disable any other load events which might be defined. Use addEventListener instead, which allows multiple handlers to be specified for the same event.
Demo:
function linkIt() {
var intoLink = document.getElementById("__C_cb_file_link");
var hLink = document.createElement("a");
hLink.setAttribute("href", intoLink.value);
hLink.innerHTML = "Click here";
intoLink.insertAdjacentElement('beforebegin', hLink);
}
window.addEventListener('load', linkIt);
<td>
<div class="sui-disabled" title="">m-files://view/37FF751C-A23F-4233-BD8B-243834E67731/0-46524?object=C46A7624-D24B-45F3-A301-5117EFC1F674</div>
<input type="hidden" name="__C_cb_file_link" id="__C_cb_file_link" value="m-files://view/37FF751C-A23F-4233-BD8B-243834E67731/0-46524?object=C46A7624-D24B-45F3-A301-5117EFC1F674" /></td>
</tr>
P.S. m-files:// is not a standard protocol in most browsers, unless some kind of extension has been installed, so even when you turn it into a hyperlink it may not work for everyone.
[UPDATE] I supose that your "__C_cb_file_link" was a paragraph so I get the previous text http://mylink.com and create a link with, is it what you want, right?
function linkIt() {
let fileLink = document.getElementById("__C_cb_file_link");
let hLink = fileLink.textContent;
fileLink.innerHTML = ""+hLink+"";
}
linkIt();
<div>
<p id="__C_cb_file_link">http://myLink.com</p>
</div>

Adding a hidden form field to a dynamically generated Squarespace newsletter block using JS

I'm trying to add a hidden field to my homepage newsletter signup at http://greig.cc/ so that I can track the signup source in Mailchimp.
This is the code that I'm injecting into the page, but it throws an 'Uncaught TypeError: undefined is not a function' error and I can't work out why.
Is it something to do with the fact that the rest of the form is rendered after the page is loaded? (this is why I'm using the class name to target the form).
<script type="text/javascript">
var formcontainer = document.getElementsByClassName('newsletter-form');
var input = document.createElement('input');
input.type = 'hidden';
input.name = 'SOURCE';
input.id = 'SOURCE';
input.value = 'homepage';
formcontainer.appendChild(input);
</script>
Thanks for reading :)
Fixed my doing two things :)
(1) Waiting for the DOM to load before running the script
(2) Iterating through getElementsByClassName to get the first item in the array. {Not bothering to loop through this as I only have 1 form per page}
<script language="JavaScript">
document.addEventListener("DOMContentLoaded", theDomHasLoaded, false);
function theDomHasLoaded(e) {
var formelements = document.getElementsByClassName('newsletter-form');
formelements[0].innerHTML += "<input name='SOURCE' id='SOURCE' type='hidden' value='homepage' />";
}
</script>
document.getElementsByClassName returns an array, so formcontainer contains an array of elements (even if there is only one matching element).
It's likely that formcontainer.appendChild(input) is failing because the formcontainer array won't have a function called appendInput.
Try changing the line formcontainer.appendChild(input); to read formcontainer[0].appendChild(input); and see if that fixes the error.
You can also set a breakpoint in the code using Chrome's Inspector or the Firefox dev tools. To debug an error like this I'd suggest putting the breakpoint on the very first line of your code, and stepping through one line at a time until the error occurs. That'll narrow it down to a single line so you're not looking for a needle in a haystack :)
Just do it the simple way, and add the hidden field right to the form with HTML:
<input type="hidden" value="homepage" />
If for some reason you have to use JavaScript, put this script right before the closing </head> tag:
<script language="JavaScript"> document.getElementById('newsletter-form').innerHTML += "<input type='hidden' value='homepage' />";
</script>
Also, add the id="newsletter-form" attribute to your <form> tag.
This will add the specified HTML code to your form with the specified id.
I hope I helped you :)

Double insert after is permitted, but before doesnt

The following html markup
<div id="parent" class="parent">
<div id="child" class="child">
<input type="text" class="text"/>
<input id="submit" value="submit" type="submit" onclick="doThis()"/>
</div>
<div>
and JS code
function doThis(){
var span= document.createElement("span");
var parent=document.getElementById("parent");
var child=document.getElementById("child");
var submit=document.getElementById("submit");
child.insertBefore(span,submit.nextSibling);
myKeys=[];
myKeys.push(getAllKeyValuePair(submit));
span.innerHTML=myKeys;
}
function getAllKeyValuePair(obj){
var str="";
for(var key in obj){
try{
str=str+"{"+key+", "+obj[key]+"}";
}
catch(e){
console.log(key);
}
}
return str;
}
JSFIDDLE example.
It works fine and it's ok to click 2,3,...etcetera times on submit button, to click on duplcate of submit button... etc. But if we trying to replace child.insertBefore(span,submit.nextSibling); to child.insertBefore(span,submit); (i.e. insert span before submit button rather than after) we can only 1 time to click to submit button. Consequent clicks will caused exception. JSFIDDLE
The question obviously is why in the case of inserting before submit second and consequent clicks will causes exception, but in the case of insert after submit it's work fine. I think, that the reason of duplicating the submit button is not true.
When you do:
span.innerHTML = myKeys;
you're creating another element with id="submit". The next time you click the button,
var submit = document.getElementById("submit");
assigns this element to the variable, rather than the one in the original HTML. This element is not a child of child, so you get an error.
The version with nextSibling also creates these duplicate IDs, but the original submit element is earlier in the DOM than the added elements, so it gets returned by getElementById and you don't get an error. I don't think there's any guarantee that this will work, since duplicate IDs aren't permitted, but it's how most browsers work.
If you don't want the string returned by getAllKeyValuePairs to be parsed as HTML, assign it to span.innerText rather than span.innerHTML.

jQuery equivalent to `return document.getElementById(theVar)'

I've a javascript function
function $m(theVar){
return document.getElementById(theVar)
}
The problem with the above code is, the element I want to pass is generated by ajax so I need something like the .live() in jquery, unless it throws an error
How do I rewrite the above function in jQuery so that any DOM element generated later can also be detected.
Update:
When my page first load, it loads
1) ajaxupload.js with codes
function ajaxUpload(form,url_action,msg){
var id_element= "pop-con";
function $m(theVar){
return document.getElementById(theVar)
}
if($m(id_element)==null){
erro += "The element of 3rd parameter does not exists.\n";
}
}
2) index.php with codes
<div id="popupMargin">
<div class="close">x</div>
<div id="pop-con"></div>
</div>
<div id="ajaxGenerateMarkUp"></div>
3) now on the click of a button, the following markUp is added to the #ajaxGeneratedmarkUp div (mark-up generated through ajax)
<form onSubmit="return disableForm(this);" action="crop/wizecho_upload.php" method="post" name="f" id="wizecho" enctype="multipart/form-data">
<input id="file" type="file" name="file" onChange="return disableForm(this), ajaxUpload(this.form,'crop/wizecho_upload.php', '<br>Uploading image please wait.....<br>'); return false;"/>
</form>
Now on change of this input type file, made the call on in the javascript. Now it shows the error.
[Note: I only posted sections of code I think might affect my question]
Like this:
return $('#' + theVar)[0];
jQuery's selector can detected newly generated items:
$('#id');
So in your case:
var theVar = 'something';
$('#' + theVar); //returns a jQuery object of the select item
$('#' + theVar)[0]; //returns the first DOM object that jQuery finds with that id
I think you need to add a live call somewhere to detect the new AJAX-loaded button. This way, the button will be automatically bound to a handler that works OK as in other answers. From your comment I guess you are doing one of these:
In the AJAX-loaded button you already include some JS logic, that is not working (something like onclick="do_something").
You are binding the second button to a handler withoug the live method.
Here's a working example. Although it doesn't load contents via AJAX, it does load a dynamic button.
http://jsfiddle.net/marcosfromero/VKfKL/
Update: Another example that does load contents via AJAX and binds the newly created button with live:
http://jsfiddle.net/marcosfromero/h9RSC/

Categories