This context of this issue is it is a set of measurements needed for review by the user. I'm reviewing some of my code and changing it to bootstrap's classes. I have a php function - reviewSlide(); that prints out the necessary html. From there it calls javascript script - reviewGetMeasurement(); function to grab the measurements the user inputs.
The event that triggers the javascript function is -
<button onclick="slideforms_step17(event);reviewGetMeasurement();" class="mdk_slidesforms_btn"><?= (!empty($button_text)) ? $button_text : 'Next' ?></button>
The function runs then moves into the below function reviewSlide() however if I do have the following code everything runs perfectly and the measurements are gathered and printed to the page.
function reviewSlide() {
<table>
<tr width="33%">
<table class="pktsq_measurement_table_my_account_table">
<tr>
<td colspan="2" class="pktsq_measurement_table_my_account_td pktsq_measurement_table_my_account_td_title">
Personal
</td>
</tr>
<tr>
<td class="pktsq_measurement_table_my_account_td">
Height
</td>
<td class="pktsq_measurement_table_my_account_td pktsq_measurement_table_my_account_td_measurement" id="userHeight"></td>
</tr>
</table>
</tr>
</table>
...
}
If I remove the above table nothing works.
I have tried
function reviewSlide() {
<p id="userHeight"></p>
<p id="userWeight"></p>
...
}
at the top of my function (which is at this stage above the table) and nothing comes up.
I've looked at other people's issues, some of the main problems were the page wasn't loading and you would have to wait for the page to load as the javascript would not see any html. But I believe I have a bit of a quirky problem here regarding the table code
Any help would be grateful. Thank you.
UPDATE and CLARIFICATION (same as comments):
I didn't write this so bear with me but yes reviewSlide is in php. To clarify I have a function stepxx() in a shortcodes.php file. Each step represents a slide and reviewSlide() also represents another slide, in this case the review slide with all the measurements. All this is written in html/php. In stepxx() there is a button tag that calls a javascript function slideforms_stepxx(event);. When each step is complete 1-xx, slidesforms_stepxx(event) is called to check the input.
This is where we come to the review slide. On the slide before the review slide we go into slideforms_step17 check the input and submit the values to the server via jquery. Then we enter the reviewGetMeasurement() function as seen above by <button onclick="slideforms_step17();reviewGetMeasurement();....>. ReviewGetmeasurement's task is to print out the values and this is where my problem lies.
Inside reviewGetMeasurements(), if I print out the value for a variable let's say the height via console.log(height), it'll work and I can see the value in the console. But once if I try to print the value our by doing
document.getElementById("userHeight").innerHTML = height + "cm";
I get null. But I know there is a value height and it's not null. HOWEVER if I put the <table> code from above it will work and the values are printed out. If I use the <p> tags with the right id it won't work.
You can't just blindly put HTML inside of a Javascript or PHP function. What's in those functions must be the appropriate type of code, not HTML.
If it's Javascript, then using Javascript you can create DOM elements and then insert them into the page.
If it's PHP running at page render time on the server, then you can use PHP's echo to insert content into the page.
If it's PHP running in an Ajax call, then you can also use echo to construct a response to the Ajax call.
Here's an example of inserting content into the page from a user event using a Javascript function:
function insertContent(html) {
var div = document.createElement("div");
div.innerHTML = html;
document.body.appendChild(div);
}
document.getElementById("run").addEventListener("click", function() {
insertContent(document.getElementById("newContent").value);
});
<input id="newContent" value="Some Text"> <button id="run">Insert</button>
Related
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.
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>
I've got a little problem and I'm stucking on it for a couple of days.
I downloaded a Javascriptcalendar plugin (Date Input) to add a little calendar in my form.
In this form I added a button wich add another line in this form to let user set severals dates.
<input type="button" value="Ajouter" onclick="ajoutChamp('creneau')" />
I made a little script :
var s = document.createElement('script');
s.type = "text/javascript";
s.text = "DateInput('creneau_2',true,'DD-MON-YYYY')";
$("#test").append(s);
But when I'm doing this, every time I press the button I've got my calendar who appears fullscreen. It's look like the script has been executed but no appened in the html page.
Little piece of my html code :
<table id="liste_creneau" class="add_champ">
<tr id="tr_creneau_1">
<td><label for="creneau_1">creneau 1</label></td>
<td><script id="ref_date">DateInput('creneau_1', true, 'DD-MON-YYYY')</script></td>
</tr>
</table>
<div id="test">
</div>
Atm I wanted to append the calendar in a div but at the end the calendar will be in the table.
I have done other tests too but every piece of code I made ended the same way...
So maybe you could help me! :)
Edit:
Ok I made a little test
var g = document.getElementById('test');
var s = document.getElementById('ref_date');
nb++;
var clone = s.cloneNode(true);
var param = clone.firstChild.data.split('\'');
param[1] = 'creneau_'+nb;
clone.firstChild.data = param.join('\'');
g.appendChild(clone);
After that, when I click on the button, there is a script tag inserted in the div but nothing shows up. When I inspect my html page I can see it but the calendar doesn't apear...
Bye
Edouard
I don't understand why you are not just running the date input line. It should have the same effect.
DateInput('creneau_2',true,'DD-MON-YYYY');
Regardless, you could just try and do it all in jQuery rather than mixing javascript selectors.
$("#test").append("<script type='text/javascript'>DateInput('creneau_2',true,'DD-MON-YYYY');</script>");
Well I chosen to use the jQuery-UI datepicker instead... So I guess it's solved, thanks a lot Agentminlindu and all the others :)
I have a function that gets raw HTML to output to a table, but I want to take out the first three columns and put them in another div.
I am considering making a div on the page that is hidden, setting this div's html to the raw HTML I get, and then using the selector syntax to strip it into each table's div. Is there a way to do this without the intermediate faux-div to hold the raw HTML?
It all depends out what the "function that gets raw HTML" does. Where is it getting the HTML? If it's in some kind of format other than a rendered node, then you should be able to manipulate it as needed prior to rendering it. If you've got it in a string format (and the markup is valid) jQuery is really good at turning strings into traversible objects. For example:
var xml = '<div><span>hello</span></div>';
console.log($(xml).find('span'));
In FireBug, this displays the span as an object node.
I'm not sure exactly why you'd want to do this, rather than arrange your data server-side, but one approach that works is:
$(document).ready(
function(){
$('table').click(
function(){
$('<table />').appendTo('#newTable').addClass('new');
$('table').eq(0).find('tr td:first-child').each(
function(){
$(this).appendTo('.new').wrap('<tr></tr>');
});
});
});
With the (x)html:
<table>
<tr>
<td>1:1</td>
<td>1:2</td>
<td>1:3</td>
</tr>
<tr>
<td>2:1</td>
<td>2:2</td>
<td>2:3</td>
</tr>
<tr>
<td>3:1</td>
<td>3:2</td>
<td>3:3</td>
</tr>
<tr>
<td>4:1</td>
<td>4:2</td>
<td>4:3</td>
</tr>
</table>
<div id="newTable"></div>
JS Fiddle demo
The demo uses jQuery's click() event, but that's just to show it working interactively; it could certainly be placed straight into the DOM-ready/$(document).ready(function(){/* ... */}); event.
The above code would allow repeated clicks (each time moving the first 'column' into a new table), the edit removes that possibility using jQuery's one(), giving the following jQuery:
$(document).ready(
function(){
$('table').one('click',
function(){
$('<table />').appendTo('#newTable').addClass('new');
$('table').eq(0).find('tr td:first-child').each(
function(){
$(this).appendTo('.new').wrap('<tr></tr>');
});
});
});
JS Fiddle demo, featuring one().
I have a table:
<table>
<tr>
<td colspan="2"><h2>Order Awards here:</h2></td>
</tr>
<tr>
<td class="aocBlack">Delivery:</td>
<td>
<select style="width: 200px;" id="deliveryMethod" name="deliveryMethod" size="1" onchange="showMailing()">
<option value="print">I will print it myself.</option>
<option value="mail">Please mail it to me.</option></select>
</td>
</tr>
<tr id="messageText" style="">
<td class="aocBlack" colspan="2">Message to appear on card:</td>
</tr>
<tr id="messageText2" style="">
<td colspan="2"><textarea id="certMessage" name="certMessage" rows="5" cols="10" style="width: 284px;"></textarea></td>
</tr>
</table>
When the select box called deliveryMethod is set to "print", the following two table rows (id messageText and messageText2) should be visible. When it's set to "mail", they should be hidden. I have some javascript that's worked before with no problem, but the id's I was targeting before were always divs. I don't know if table rows behave differently, but I'm getting some strange results. Here's the JS:
function showMailing(){
e = document.getElementById("deliveryMethod");
eVal = e.options[e.selectedIndex].value;
if (eVal == "mail"){
document.getElementById("messageText").style.display="none";
document.getElementById("messageText2").style.display="none";
}else{
document.getElementById("messageText").style.display="inline";
document.getElementById("messageText2").style.display="inline";
}
}
The results are somewhat strange, to my (admittedly javascript/css-rusty) eyes. For example, when the page initially loads, everything displays as it's supposed to: the dropdown's default value is "print", and so the two table rows in question display. When you change the dropdown to "mail", they both disappear. But when you change it back, the fields are all pushed over out of where they're supposed to be. These results are consistent across FF and Chrome (strangely it works correctly in IE) so I have to assume I'm doing something wrong, but I don't know what.
Here are some screenshots (note there are a few fields displayed in the screenshot that I've stripped out of the code shown here just for clarity.) Can anyone help me out here?
On initial load:
After changing from print to mail:
After changing back from mail to print:
The default display value for a table row is table-row(*). If you set it to inline instead you'll be asking the browser to draw table cells inside inline text instead of a row, which will confuse it and give unspecified results.
(*: except on IE<8, which don't support the table-related display values, instead setting them all to block and giving the elements themselves magic layout powers.)
The better way do show/hide, where you don't have to worry about what the default display value might be, is to define a class:
.hidden { display: none; }
and then toggle that class on and off the element.
document.getElementById('deliveryMethod').onchange= function() {
var cls= this.value==='mail'? 'hidden' : '';
document.getElementById('messageText').className= cls;
document.getElementById('messageText2').className= cls;
};
Assigning the handler from script allows you to drop the onchange inline attribute. You also don't need size="1" (that goes without saying for a single-select), or the style="".
The business with reading the select's value using this.options[this.selectedIndex].value you probably don't need any more, unless you're dealing with ancient browsers.
function showMailing(){
e = document.getElementById("deliveryMethod");
eVal = e.options[e.selectedIndex].value;
if (eVal == "mail"){
document.getElementById("messageText").style.display="none";
document.getElementById("messageText2").style.display="none";
}else{
document.getElementById("messageText").style.display="table-row";
document.getElementById("messageText2").style.display="table-row";
}
}
I'd recommend avoiding "eVal" as a variable name, because there's a native JS method called eval(). The capitalization you used is different ("eVal" not "eval"), so it probably won't break things. But it could easily be confusing to a human reader. Also, if you accidentally forget to capitalize the "V" and then need to use the eval() method, it could break your script.
So just in general, avoid using variable names that are similar to the names of existing methods. May I suggest "selectedOption" or "sel" or something?