xsl:call-template within a javascript function? - javascript

I'm really new at coding, sorry if any of this sounds silly or stupid. We have a new project to come up with a new webpage. I have a multiple condition if statement and would like to call a xsl template if condition is met. Here's how I have it now and it doesn't work at all.
<script>
function getSelectedValue()
{
if("document.getElementById('type').value==1 and document.getElementById('cablegroup5').value==9"+
"document.getElementById('cablegroup3').value==22 and document.getElementById('cablelength').value==11")
{
<xsl:call-template name="PN">
<xsl:with-param name="Cable">ABC111-06</xsl:with-param>
</xsl:call-template>
}
}
</script>
I know the first part works, I've tested it with an alert message and that works just fine. These are all activated by a button(onclick) next to multiple drop down menus. Is there a way to get this to work? Any help would be really appreciated. Thanks.

You're confused about the processing model. Is the script element generated by XSLT? If so, the call-template will probably be called at the time the script is generated. It won't be called at the time the script is executed. Javascript code isn't going to magically execute XSLT instructions.

There are a couple of issue within the script that would prevent the if statement executing correctly.
The boolean and operator in JavaScript is && not and. Note the if you use & this would be a bitwise and.
The tests should not be a string. Due to JavaScript type coersion it a string will be converted to a boolean. A null or empty string '' will evaluate false, all other strings will evaluate true. Currently you have
if("test1 and test2")
This should be
if(test1 && test2)
So far your updated script would be
<script>
function getSelectedValue()
{
if(document.getElementById('type').value==1 &&
document.getElementById('cablegroup5').value==9 &&
document.getElementById('cablegroup3').value==22 &&
document.getElementById('cablelength').value == 11)
{
// Process Xml
}
}
</script>
You need to use the browser xml parser to handle your xml. I will assume that you have an xml string, if you have a document object then you will have to change the following slightly, this is from w3schools.
var xmlString = "<Products>" +
"<Product partnumber='foo'>This is product 1</Product>" +
"<Product partnumber='bar'>This is product 2</Product>" +
"</Products>";
// Load into an XML document
var myDoc;
if (window.DOMParser)
{
var parser=new DOMParser();
myDoc=parser.parseFromString(xmlString,"text/xml");
}
else // Internet Explorer
{
myDoc=new ActiveXObject("Microsoft.XMLDOM");
myDoc.async="false";
myDoc.loadXML(xmlString);
}
// Get all product nodes
var products = myDoc.getElementsByTagName('Product');
var i, targetProduct, partNumber;
for(i = 0; i < products.length; i += 1){
// Get the partnumber attribute
partnumber = products[i].attributes.getNamedItem('partnumber');
// Ensure that the partnumber exists and its value is what is wanted
if(partnumber && partnumber.value == 'foo'){
targetProduct = products[i];
// Exit for
break;
}
}
// If the product has been found alert its value.
if(targetProduct != null){
alert(targetProduct.textContent || targetProduct.text);
}
If you were selected a node by id then you could use xmlDoc.getElementById instead of iterating through all nodes of a type and checking attributes.
To select the text value of an xml node most browsers use the property textContent although Internet Explorer uses text. The line
targetProduct.textContent || targetProduct.text
returns textContent if it is present and not null, or the value of text.

Related

How to make a javascript value equal to the value that I receive from my Razor code

I'm new to MVC and am not sure if this is even possible but I want to know how I can make a variable inside of my javscript function be to a equal the value that I am grabbing from my razor code.
Here is my code
function create() {
var site
#if (#so.invSiteID == null) {
var siteRazor = 0;
}
else {
var siteRazor = #so.invSiteID;
}
}
So is it possible for me to make my "siteRazor" equal to my "site" variable?
Also, I tried this
if (#so.invSiteID == null) {
site = 0;
}
else {
site = #so.invSiteID;
}
But it didn't matter if the statments were true or false it would always run through both. If I can get a brief explanation as to why that didn't work that would be awesome
In your Razor code, if you need to take an extra step to ensure that code is included as-is in the output and not treated as C#.
If you don't have an html tag, you can use the <text></text> or #: syntaxes to tell Razor not to run the line(s) as C# code but just treat them as part of the output. See here for details: https://learn.microsoft.com/en-us/aspnet/core/mvc/views/razor?view=aspnetcore-3.1#explicit-delimited-transition
For example, the output of this is nothing. You've assigned a c# variable that is unused.
#if (#so.invSiteID == null) { // note: the second # here is not
// necessary because you are in a c# block
var siteRazor = 0; // << var is a c# keyword and the `if` is a c# block
}
Instead, you could use:
#if (so.invSiteID == null) {
#: var siteRazor = 0;
}
// ... rest of code
My suggestion would be to minimize the amount of C# code as much as possible in your Razor files, and always think about what the output you are creating. (View-source in the browser to see the actual output if needed.)
That said, you can simplify your code greatly if you use the null coalescing operator.
function create() {
var site = #(so.invSiteId ?? 0);
}
Create a hidden field and assign the value of your variable there:
#Html.Hidden("siteId", #myvariable)
Then, in JS, you can reference the value of the hidden field:
var siteIdVal = document.getElementById("siteId").value;

Unchecking and simulating a click on checkboxes in Javascript

I am admittedly a super newbie to programming in general. I am trying to design a quick piece of javascript to inject on a website for a class that will both uncheck and simulate a click on a series of checkboxes. This is nothing malicious, the web form we use to download data for use in this class presents way more variables than necessary, and it would be a lot more convenient if we could 'uncheck' all and only check the ones we want. However, simply unchecking the boxes via javascript injection doesn't yield the desired result. A mouse click must be simulated on each box. I have been trying to use the .click() function to no avail. Any help is greatly appreciated. My code below fails with an error of:
"TypeError: Cannot read property 'click' of null"
CODE:
var getInputs = document.getElementsByTagName("input");
for (var i = 0, max = getInputs.length; i < max; i++){
if (getInputs[i].type === 'checkbox')
getInputs[i].checked = false;
document.getElementById('shr_SUBJECT=VC' + i).click();
}
--------EDIT#1--------------
FYI, this is the website that I am trying to use this on:
http://factfinder2.census.gov/faces/nav/jsf/pages/searchresults.xhtml
if you search for and open up any of these tables they are huge. It would be awesome if I could easily pare down the variables by 'unchecking' and 'clicking' them all at once via javascript.
The code at the bottom ALMOST works.
The problem I am running into now is that it throws an error after the first or second run through the for loop:
"TypeError: document.getElementById(...) is null"
I understand that this is because the value it's trying to find doesn't exist? Sometimes on these tables the checkboxes are greyed out/don't exist or are otherwise 'unclickable'. My theory as to why I am getting this error is because in the table/form the 'available' ID's will start around:
shr_SUBJECT=VC03 or sh_SUBJECT=VC04
and it may then skip to:
shr_SUBJECT=VC06 then skip to shr_SUBJECT=VC09 and so on...
So if the for loop hits an ID that isn't available such as 05 or 07, it returns a null error :(
I did some reading and learned that javascript is able to 'catch' errors that are 'thrown' at it? My question now is that I'm wondering if there is an easy way to simply iterate to the next ID in line if this error is thrown.
Again, any and all help is appreciated, you guys are awesome.
OLD DRAFT OF SCRIPT
var getInputs = document.getElementsByTagName("input");
for (var i = 3, max = getInputs.length; i < max; i++){
if (getInputs[i].type === 'checkbox' && i < 10){
var count = i;
var endid = count.toString();
var begid = "shr_SUBJECT=VC0";
var fullid = begid.concat(endid);
document.getElementById(fullid).click();
}
else if(getInputs[i].type === 'checkbox' && i >= 10){
var count = i ;
var endid = count.toString();
var begid = "shr_SUBJECT=VC";
var fullid = begid.concat(endid);
document.getElementById(fullid).click();
}
}
--------EDIT#2----------
An example of a table that I am trying to manipulate can be found at this URL:
http://factfinder2.census.gov/faces/tableservices/jsf/pages/productview.xhtml?pid=ACS_12_5YR_DP02&prodType=table#
If you click on the 'Modify Table' button, you are able to select/deselect specific variables via the checkboxes. If you right-click on a couple of 'active' checkboxes and inspect the elements, and it looks something like this:
<input id="shr_SUBJECT=VC03" checked="" alt="hide SUBJECT=VC03" name="" value="" onclick="javascript:hiderow('SUBJECT=VC03');" type="checkbox">
<input id="shr_SUBJECT=VC25" checked="" alt="hide SUBJECT=VC25" name="" value="" onclick="javascript:hiderow('SUBJECT=VC25');" type="checkbox">
Thank you so much #Jonathan Steinbeck for the tip about the ternary operator, it really cleaned up my code.
The script works properly, but the problem I am running into now is that it doesn't iterate enough times after the try, catch statement. If there is a gap in the id #'s; say it jumps from shr_SUBJECT=VC19 to shr_SUBJECT=VC=24 the script will stop running. Is there a way to make it keep retrying the try/catch until it gets a valid ID # or one that exists/is an active checkbox?
CURRENT DRAFT OF SCRIPT :
var getInputs = document.getElementsByTagName("input");
for (var i = 3, max = getInputs.length; i < max; i += 1) {
try {
if (getInputs[i].type === 'checkbox'){
document.getElementById("shr_SUBJECT=VC" + (i < 10 ? "0" : "") + i).click();
}
}
catch (err) {
i+=1;
if (getInputs[i].type === 'checkbox'){
if (getInputs[i].type === 'checkbox'){
document.getElementById("shr_SUBJECT=VC" + (i < 10 ? "0" : "") + i).click();
}
}
}
}
When you call document.getElementById() with a non-existing ID, null is returned. Therefore this error means that you're trying to call the .click() method on null, which can't work.
So you should check what the correct ID naming scheme for the elements you want is. Maybe the elements' count starts with 1 instead of 0?
Also, the .click() doesn't work for all elements like you would expect as far as I know. So depending on the kind of element you are trying to retrieve you might have to create and dispatch your own event as suggested by RobG's comment.
EDIT in response to your recent edit:
You can wrap code that throws errors in a try-catch like this:
for (var i = 3, max = getInputs.length; i < max; i += 1) {
try {
document.getElementById("the_ID").click();
}
catch (error) {
console.error(error);
// continue stops the current execution of the loop body and continues
// with the next iteration step
continue;
}
// any code here will only be executed if there's not been an error thrown
// in the try block because of the continue in the catch block
}
Also, what are you doing with the 'i' variable? It doesn't make sense to assign it to so many variables. This does the same:
document.getElementById("shr_SUBJECT=VC" + (i < 10 ? "0" : "") + i).click();
The ... ? ... : ... is an operator (called the 'ternary operator') that works like this: evaluate the expression before the "?" - if it results in a truthy value, the expression between "?" and ":" is evaluated and becomes the result of using the operator; if the condition results to false, the part after the ":" is evaluated as the value of the operator instead. So while "if" is a statement in JavaScript (and statements usually don't result in a value), the ternary operator can be used as an expression because it results in a value.
By concatenating a string with something else, you are forcing the 'something else' to be converted to string. So an expression like this will usually result in a string:
"" + someNonStringVar
Also, it doesn't make sense to define variables in a loop body in JavaScript. JavaScript variables have function scope, not block scope. What this means is that any variables defined in the loop body exist inside the whole function as well. Therefore it is recommended to write all of the "var"s at the top of your function to make it clear what their scope is. This behaviour of JavaScript is called 'hoisting', by the way.
I've furthermore taken a look at the URL you've given in your recent edit but I fail to find the kind of naming scheme for IDs you describe. In which table did you find those?
Edit in response to your second edit:
You shouldn't mess with the 'i' variable inside the body of a for loop. It makes your code much harder to reason about and is probably not what you want to do anyway. You don't need to handle the next step of the iteration in the catch block. The 'i' variable is incremented even if there's an error during fetching the element from the DOM. That's why you use catch in the first place.

Why this code doesn't alert the browser type?

Can you tell me what I am missing in writing this code?
<button onclick="getBrowserName()">You Browser Name?</button>
<script>
function getBrowserName()
{
//Uses external interface to reach out to browser and grab browser useragent info.
var browserAgent:String = ExternalInterface.call("function getBrowser(){return navigator.userAgent;}");
//Determines brand of browser using a find index. If not found indexOf returns (-1).
if(browserAgent != null && browserAgent.indexOf("Firefox")>= 0)
{
alert("Firefox");
}
else if(browserAgent != null && browserAgent.indexOf("Safari")>= 0)
{
alert("Safari");
}
else if(browserAgent != null && browserAgent.indexOf("MSIE")>= 0)
{
alert("IE");
}
else if(browserAgent != null && browserAgent.indexOf("Opera")>= 0)
{
alert("Opera");
}
else
{
alert("Undefined");
}
return 0;
}
</script>
Well, there are a few things wrong here.
var browserAgent: String: it appears that you're using actionscript syntax, but JS uses dynamic typing, so var is all you need. There's no need to explicitly define the variable's data type, and if you try to do it this way in JS, it's going to give you syntax errors.
ExternalInterface.call: this is another carryover from ActionScript: you don't need this. In fact, it won't work at all because there's no ExternalInterface class in standard JS.
Your getBrowser() function is unnecessary. You're setting browserAgent equal to the result of calling a function from an ExternalInterface, but you can do this directly: var browserAgent = window.navigator.userAgent.
When I fixed those things, it worked fine.
Next time, I would recommend checking the browser console, because, if nothing is happening, the errors that appear there will help you solve your issue nine times out of ten.
Demo
If you replace this line
var browserAgent:String = ExternalInterface.call("function getBrowser(){return navigator.userAgent;}");
with this line:
var browserAgent = window.navigator.userAgent;
Then your script works fine on my side.
However, the criteria you use to test the engine are not precise. Have a look at this:
http://www.useragentstring.com/pages/useragentstring.php
There are many browsers that will tell you Firefox even if they another brand. But they are based on each other or they use a specific engine that is built in other browsers too.
If I use your script with a Chrome browser, it says "Safari" instead of "undefined".
About the punctuation: I know of only two places in Javascript where to use the double point:
the conditional operator a = b ? c : d;
the attribute - value assignment in object notation: { name : value }
Your code line containing :String = ExternalInterface... reminds me rather on ActionScript (?).
Im not quite sure what the follow code should be doing. Are you sure its correct?
var browserAgent:String =
ExternalInterface.call("function getBrowser(){return navigator.userAgent;}");
I would expect this code to simply look like this:
var browserAgent = navigator.userAgent;
Below is a example with this change.
http://jsbin.com/lukasere/1/edit

Unable to detect empty paragraph

I am using the following code to check for an empty paragraph but it never returns true. Why?
var isEmpty = pageChildren[i].outerHTML.toUpperCase() === "<P></P>";
var isSpace = pageChildren[i].outerHTML.toUpperCase() === "<P> </P>";
var isNbsp = pageChildren[i].outerHTML.toUpperCase() === "<P>&NBSP;</P>";
if(!isEmpty && !isSpace && !isNbsp){
//do something
}else{
//do something else
}
This is a copy paste of what IE8 debug tools tells me is in the outerHTML: "<P></P>"
This is being read from an iFrame so i need to remove the <p></p> tags also as the function above this triggers off of the number of children elements in the body of the frame.
Additionally this runs in an HTA application on IE only. The userbase/configuration is highly controlled.
If you're sure your object is a paragraph, you should use innerHTML instead :
var isEmpty = pageChildren[i].innerHTML.trim().length==0;
(note that the MDN proposes a replacement for IE8 which lacks trim).
You could also use textContent but the downside is that you have to do a different test for IE.
Since trim() isn't supported by all browsers, I suggest removing all spaces with RegEx:
var isEmpty =
(pageChildren[i].innerHTML.replace(/\s/g, '').length == 0) ? true : false;
It seems that IE < 9 prepends a carriage return, line feed to the outerHTML result, so for example pageChildren[i].outerHTML.toUpperCase() === '\r\n<P></P>' returns true for an empty p element.

How do I store xml as a string variable in javascript?

I trying to store a piece of xml into a string variable in javascript and in IE8 it keeps throwing an error. FireFox doesn't show the error but of course in IE8 it does. Swictching browsers isn't an option so I have to try to solve this one.
The purpose of the function is to check if the items of a list exist in an xml object or not. So if there is a better way to do that check I am open to that as well. The system we pull from has a function to convert the xml to a string. At the bottom is an output of what that retrieves. Here is the function.
function commodityExists(newCommodityCode){
var comExists = new Boolean(0);
newCommodityCode = ">" + newCommodityCode + "<"
var strXML = 'tw.local.aribaHeader.commodities.toXMLString()'; //ERROR HERE
strXML = strXML.toString();
if(strXML.indexOf(newCommodityCode,0)>0){
comExists=true;
}
return comExists;
};
Here is the output from strXML.toString(); but as you can see it is essentially xml.
var strXML = ‘<variable type="NameValuePair[]">
<item type="NameValuePair">
<name type="String"><![CDATA[No Data Found]]></name>
<value type="String"><![CDATA[95990070]]></value>
</item>
</variable>’;
I don't know what you think the code is doing, here is an explanation of what it does:
> function commodityExists(newCommodityCode){
> var comExists = new Boolean(0);
Do you really want a Boolean object? This function might return a Boolean object or primitive depending on what happens later. Consider:
var comExists = false;
.
> newCommodityCode = ">" + newCommodityCode + "<"
That overwrites whatever value was passed to newCommodityCode from the call.
> var strXML = 'tw.local.aribaHeader.commodities.toXMLString()'; //ERROR HERE
I can't see how that throws an error, it's a simple assignment of a string.
> strXML = strXML.toString();
That effectivly does nothing - it calls the toString method of a string, which will just return the same string.
> if(strXML.indexOf(newCommodityCode,0)>0){
That test will always be false, since the value of nweCommodityCode is hard coded in the function and does not exist in the (hard coded) value of strXML.
> comExists = true;
> }
> return comExists; };
The function will always return false (though the original will return a Boolean object with a value of false).
You're creating a string:
var strXML = 'tw.local.aribaHeader.commodities.toXMLString()'; //ERROR HERE
^--- ^---
then converting that string to... a string?
strXML = strXML.toString();
Where would this tw object be defined that you seem to be attempting to use? Because as your code is written now, you're not calling a .toXMLString() method on something in this tw object. You're just assigning the literal text of an object call as a string itself.
The approach I was trying to take will not work because I am dynamically populating the xml so there is no way for me to escape the characters (well there probably is somehow but clearly it is not worth it). Storing HTML or XML code in javascript variables
Instead I am moving the comparison to the server side instead of retrieving the xml and comparing on the client side and posting back the results via ajax unless someone has a better reccomendation.

Categories