Is there any definite way to retrieve the xPath of a angleSharp IElement
I'm trying to pass an IElement to a javaScript function, so I need a way to convert the angleSharp element to a javaScript Dom element
function selectLevels(element, name, level){
document.querySelectorAll("*").forEach(e => {
if(e.isEqualNode(element)){
e.setAttribute('level', level);
e.setAttribute('title', name);
}
})
}
I want to call this javaScript function which is in the page by passing an element from the C# code bellow, but I get an angleSharp not found error from the page.
IElement element = mainDoc.QuerySelector("strong");
Page.ClientScript.RegisterStartupScript(this.GetType(), "SelectLevel", "selectLevels('" + element + "', '" + name + "', '" + level + "')", true);
If you have a HTML document with JavaScript code and want to call a (global) function in the JavaScript code from C# then the following example works for me with AngleSharp 0.15 and AngleSharp.Js 0.14:
static async Task Main()
{
var html = #"<!DOCTYPE html>
<html>
<head>
<title>Test</title>
<script>
function selectLevels(element, name, level){
element.dataset.level = level;
element.dataset.title = name;
}
</script>
</head>
<body>
<h1>Test</h1>
<section data-level=1 data-title='section 1'>
<h2>Section test</h2>
</section>
</body>
</html>";
var jsService = new JsScriptingService();
var config = Configuration.Default.With(jsService);
var context = BrowsingContext.New(config);
var document = await context.OpenAsync(req => req.Content(html));
var selectLevels = jsService.GetOrCreateJint(document).GetValue("selectLevels");
var jsElement = JsValue.FromObject(jsService.GetOrCreateJint(document), document.QuerySelector("section"));
selectLevels.Invoke(jsElement, "2", "section 2");
Console.WriteLine(document.DocumentElement.OuterHtml);
}
So basically you get the function with e.g. jsService.GetOrCreateJint(document).GetValue("selectLevels"); and call it with its Invoke method, passing in string arguments for the simple types and the IElement converted with JsValue.FromObject e.g. JsValue.FromObject(jsService.GetOrCreateJint(document), document.QuerySelector("section")).
Related
I have created a HTML form within the google apps script environment. With two files one HTML file including the HTML form and the relevant CSS, and another form including my java script functions.
When the submit button is pressed it calls a function GetSelectedText(), which returns the selected text value of a selection input. This function is within the HTML page.
What I then want to happen is once the GetSelectedText() function is called to call another function projectData() passing over the collected input value from the GetSelectedText().
However it doesn't pass over the variable and in the log it just has 'null'.
Any help on this would be greatly appreciated. Thanks.
<script>
function GetSelectedText(){
var e = document.getElementById("projectNoView");
var result = e.options[e.selectedIndex].text;
projectData(result);
}
</script>
function projectData(result) {
var ss = SpreadsheetApp.openById('10jSs0uoHOgO9VZusCa0ApyXmqISsHqsubIfRXiRPcQg');
var sheet = ss.getSheetByName("Projects Progress");
var data = sheet.getDataRange().getValues();
var search = result;
var optionsHTML = "";
var NICEIC = "0";
Logger.log(search);
for(var i = 0; i<data.length;i++){
if(data[i][0] == search){
var NICEIC = sheet.getRange((i+1), 3).getDisplayValue();
optionsHTML += '<input id = "mytext" name = "NICEIC" type = "text" placeholder="NICEIC" value="' + NICEIC + '" tabindex="2">'
}
};
return optionsHTML;
}
Server side functions can't be called directly from the client side code, you have to use google.script.run to do that. Example from the Google Apps Script guides
Server side code (Code.gs)
function doGet() {
return HtmlService.createHtmlOutputFromFile('Index');
}
function doSomething() {
Logger.log('I was called!');
}
Client side code (Index.html)
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<script>
google.script.run.doSomething();
</script>
</head>
</html>
Reference
HTML Service: Communicate with Server Functions
I'm very new to JavaScript so I apologize if this question has an extremely obvious answer. What I'm trying to do is pass the name of a text box in HTML to a function in Javascript via an onclick button. The goal of the function is to test a given string and highlight it based on certain parameters (for my testing, it is simply length).
There are multiple weird odds and ends within the functions that I'm aware of and working on, I know the functions work as when I remove the parameters and call the code text box directly, it prints exactly what I expect it to. But I want to be able to pass multiple text boxes without needing a specific function per box.
The code I have is as follows. I've included all of it in case the mistake was made somewhere I didn't expect it to be.
<!DOCTYPE html>
<html>
<head>
<style>
.highlight {
background-color: yellow;
}
</style>
</head>
<body>
<label for="wordOne">Word One</label><br>
<input type="text" id="wordOne" name="wordOne"><br>
// Pass the value for the wordOne textbox to verify function
<button type="button" onclick="verify(wordOne,this)">Check</button><br><br>
<label for="wordTwo">Word Two</label><br>
<input type="text" id="wordTwo" name="wordTwo"><br>
// Pass the value for the wordTwo textbox to verify function
<button type="button" onclick="verify(wordTwo,this)">Check</button><br><br>
<p id="test"></p><br>
<p id="error"></p>
<script>
// Highlights any code in a given line.
function highlight(text,id,begin,end) {
// document.getElementById("error").innerHTML = "TEST";
var inputText = document.getElementById(id);
var innerHTML = inputText.innerHTML;
var index = innerHTML.indexOf(text)+begin;
if (index >= 0) {
innerHTML = innerHTML.substring(0,index) + "<span class='highlight'>" + innerHTML.substring(index,index+text.length) + "</span>" + innerHTML.substring(index + text.length-end);
inputText.innerHTML = innerHTML;
return string;
}
}
function verify(button,el){
var begin=1;
var end=1
var id="test";
var string = document.getElementById(button).value;
var len=string.length;
if(len>5)
{
document.getElementById(id).innerHTML = string +" "+len;
highlight(string,id,begin,end);
}
else
{
document.getElementById(id).innerHTML = string;
}
}
</script>
</body>
</html>
I apologize again if this is extremely obvious but I'm honestly not sure what I'm doing wrong. Thanks in advance for any help!
You can get the name of the textbox by the attribute
var x = document.getElementsByTagName("INPUT")[0].getAttribute("name");
And then use it in your function as
var x = document.getElementsByTagName("INPUT")[0].getAttribute("name");
function highlight(x,id,begin,end) {
// document.getElementById("error").innerHTML = "TEST";
var inputText = document.getElementById(id);
var innerHTML = inputText.innerHTML;
var index = innerHTML.indexOf(text)+begin;
if (index >= 0) {
innerHTML = innerHTML.substring(0,index) + "<span class='highlight'>" + innerHTML.substring(index,index+text.length) + "</span>" + innerHTML.substring(index + text.length-end);
inputText.innerHTML = innerHTML;
return string;
}
}
NOTE : By [0] it means the first one that is the first textbox.
These are my Json arrays:
{"0":"1","id":"1","1":"2015-01-11 12:30:45","DateTimeCreated":"2015-01-11 12:30:45","2":"Pending Confirmation","status_desc":"Pending Confirmation","3":"benjiwjh","username":"benjiwjh"}
{"0":"4","id":"4","1":"2015-02-11 09:09:09","DateTimeCreated":"2015-02-11 09:09:09","2":"Pending Confirmation","status_desc":"Pending Confirmation","3":"LSH","username":"LSH"}
{"0":"7","id":"7","1":"2015-12-03 18:30:00","DateTimeCreated":"2015-12-03 18:30:00","2":"Unresolved","status_desc":"Unresolved","3":"SWJH","username":"SWJH"}
{"0":"12","id":"12","1":"2014-12-03 12:10:30","DateTimeCreated":"2014-12-03 12:10:30","2":"Resolved","status_desc":"Resolved","3":"benjiwjh","username":"benjiwjh"}
{"0":"14","id":"14","1":"2014-12-03 12:10:30","DateTimeCreated":"2014-12-03 12:10:30","2":"Resolved","status_desc":"Resolved","3":"CYJM","username":"CYJM"}
How am I supposed to use these to display my code in an HTML file?
I have a function to show the data but it does not work:
function showData(response) {
var data = JSON.parse(response);
var id = data.id;
var DateTimeCreated = data.DateTimeCreated;
var status_desc = data.status_desc;
var username = data.username;
myText.textContent= id + DateTimeCreated + status_desc + username;
}
I think you should have a div tag in your html template.
For example, in your HTML template, there should be a scope of codes:
<div id="sometext">
</div>
And in your JS script,
var textContent = id + DateTimeCreated + status_desc + username
sometext = document.getElementById("sometext");
sometext.innerHTML(textContent);
For more info, please visit http://www.w3schools.com/js/js_output.asp
Hope it would be helpful
Based on the question, I'm not entirely sure when you are using the showData function. However, here's a jsfiddle that shows that it works: https://jsfiddle.net/qyy2nvtz/1/
<p id='hello'></p>
var myText = document.getElementById('hello');
You need to get an element before you can display something in it. So, I've initialized 'myText' with a paragraph element with id 'hello'.
Additionally, make sure that the response that is being passed in to showData is a string before you parse it. If it's already an object, then it won't be parsed.
Here you have an example, you need a div element to refer like "js":
<!DOCTYPE html>
<html>
<head>
<title>Example</title>
</head>
<body>
<div id="js">
</div>
</body>
<script type="text/javascript">
var myText= document.getElementById("js");
var data = JSON.parse(response);
var id = data.id;
var DateTimeCreated = data.DateTimeCreated;
var status_desc = data.status_desc;
var username = data.username;
myText.textContent = id + DateTimeCreated + status_desc +username;
</script>
</html>
Further reading: http://www.w3schools.com/dom/prop_element_textcontent.asp
I have an assignment and I can't seem to figure out this one part:
I have written a Javascript function to preload/precache two images for EACH image tag, from the "img" folder based on the ID of img-html tag. This part works fine.
However the function to change the image on mouseover and mouseout using addEventListener does not seem to work and I just can't seem to figure out why! If I debug, I can see the images are being loaded fine and there is no error. However on mouseover it just doesn't seem to work!
HTML Page:
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="author" content="Nilay Panchal"/>
<meta name="description" content="Part 1 Assignment 3"/>
<title>HomePage</title>
<script src="js/breadcrumb.js"></script>
<script src="js/preloader.js"></script>
<script type="text/javascript">
function animal(name,scientificName,typeOfFood,sleepingPattern,size) {
this.name = {
realName:name,
scientificName:scientificName
};
this.typeOfFood = typeOfFood;
this.sleepingPattern = sleepingPattern;
this.size = size;
}
function makeNewAnimal(name, scientificName, typeOfFood,sleepingPattern,size) {
var animalClicked = new animal(name, scientificName, typeOfFood,sleepingPattern,size);
var finalStringObject = "{"+myOwnRecursiveToStringMethod(animalClicked,"")+"}";
document.getElementById("stringOfObject").value = finalStringObject;
var backToObject = parseStringAndConvertToObject(finalStringObject);
document.getElementById("jsonDisplay").value = backToObject;
}
function myOwnRecursiveToStringMethod(objectToParse, outputString) {
var first = 1;
for(nameOfProperty in objectToParse){
if(objectToParse[nameOfProperty] instanceof Object) {
outputString += nameOfProperty+":{";
outputString = myOwnRecursiveToStringMethod(objectToParse[nameOfProperty],outputString);
outputString += "},";
} else{
outputString = outputString + nameOfProperty +":'"+ objectToParse[nameOfProperty]+"',";
}
}
if(outputString.charAt(outputString.length-1) == ',') {
outputString = outputString.slice(0,-1);
}
return outputString;
}
function parseStringAndConvertToObject(finalString) {
eval("var backToObject = "+finalString);
return backToObject;
}
</script>
</head>
<body>
<h3>Navigation List:</h3>
<nav id="navigationBar" style="border-style: double ;border-width: 10">
<ul>
<li>Assignment 3 Root</li>
<li>All Animals
<ul>
<li>Insects.html</li>
<li>Birds-Aves
<ul>
<li>The Mighty Pelican</li>
</ul>
</li>
<li>The Tall Giraffe</li>
<li>The Hefty Rhinoceros</li>
</ul>
</li>
</ul>
</nav>
<div style="border-style:groove;padding-bottom: 10px;padding-left: 10px">
<h4><u>BREADCRUMB:</u></h4>
<div id="breadcrumb"></div>
</div>
<div style="text-align: center">
<h3><u>Please click on any of the images below and the JSON object of the animals data will be displayed in the text area below!</u></h3>
<img style="width:300px;height:300px" id='pelican' alt="Pelican"/>
<img style="width:500px;height:300px" id="rhino" alt="Rhinoceros"/>
<br>
<img style="width:500px;height:300px" id="giraffe" alt="Giraffe"/>
<img style="width:300px;height:300px" id='owl' alt="Owl"/>
</div>
<hr>
<h5>Animal Objects to String:</h5>
<textarea style="width:100%" id="stringOfObject"></textarea>
<h5>Animal Strings back to Objects</h5>
<textarea style="width:100%" id="jsonDisplay"></textarea>
</body>
<script type="text/javascript">
window.onload = precacheAndLoad();
makeBreadcrumb(location.pathname);
</script>
</html>
Javascript file:
/*
*
* Below I wrote a function to perform all the image operations and precaching too. To add a new image simply do the following:
* 1) Include, the JS file and add a new img tag on the HTML page. The ID of this img tag should be the name of the animal (eg. hippo).
* 2) Save two images named the same as the animal, with a suffix of 1 and 2 for default image and hover over image. (eg. hippo1.jpg and hippo2.jpg)
* The script will take care of the rest!
*/
var allImageVariables = new Array();
function precacheAndLoad() {
var allImages = document.getElementsByTagName("img");
for(imageCount=0; imageCount<allImages.length ; imageCount++) {
currentImageId = allImages[imageCount].id;
eval("var "+currentImageId+"1 = new Image(300,300)");
eval("var "+currentImageId+"2 = new Image(300,300)");
eval(currentImageId+"1.src = 'img/"+currentImageId+"1.jpg'");
eval(currentImageId+"2.src = 'img/"+currentImageId+"2.jpg'");
allImageVariables[imageCount] = eval(currentImageId+"1");
allImageVariables[imageCount+allImages.length] = eval(currentImageId+"2");
allImages[imageCount].src = eval(currentImageId+"1.src");
allImages[imageCount].addEventListener("mouseover", hoverImage(currentImageId,imageCount+allImages.length), false);
allImages[imageCount].addEventListener("mouseout", outImage(currentImageId,imageCount), false);
}
}
function hoverImage(currentImageId, arrayIndexOfImageVariable) {
eval("document.getElementById('"+currentImageId+"').src = allImageVariables[arrayIndexOfImageVariable].src");
}
function outImage(currentImageId, arrayIndexOfImageVariable) {
eval("document.getElementById('"+currentImageId+"').src = allImageVariables[arrayIndexOfImageVariable].src");
}
Because you're executing the function and passing the return result rather than passing a reference to the function when using addEventListener(). When you use () on the function name, it is executed immediately. To pass only a reference, you need to pass just the name of the function or if you need custom arguments like you have, then you need to create a shell function that you can pass.
Furthermore, you're trying to use for loop variables inside an event handler so you need to create a closure in order to preserve the value of those variables for the event handlers long after the for loop has completed:
Change this:
allImages[imageCount].addEventListener("mouseover", hoverImage(currentImageId,imageCount+allImages.length), false);
allImages[imageCount].addEventListener("mouseout", outImage(currentImageId,imageCount), false);
to this (line breaks added for readability):
(function(imageCount, currentImageId) {
allImages[imageCount].addEventListener("mouseover", function() {
hoverImage(currentImageId,imageCount+allImages.length);
}, false);
allImages[imageCount].addEventListener("mouseout", function() {
outImage(currentImageId,imageCount);
}, false);
})(imageCount, currentImageId);
Also, why in the world are you using eval() like you are. You can code without it and have much better code, better performing and, in some cases, safer.
For example, this:
eval("var "+currentImageId+"1 = new Image(300,300)");
eval("var "+currentImageId+"2 = new Image(300,300)");
eval(currentImageId+"1.src = 'img/"+currentImageId+"1.jpg'");
eval(currentImageId+"2.src = 'img/"+currentImageId+"2.jpg'");
Can be this:
var images = [];
images.push(new Image(300,300));
images.push(new Image(300,300));
images[0].src = 'img/'+currentImageId+'1.jpg');
images[1].src = 'img/'+currentImageId+'2.jpg');
Rather than declaring variables with eval(), you can use either an object or an array and put the dynamic variables into them and then reference them from there rather than by a straight variable name. This is a common way of creating dynamic variables.
I have a function in javascript that I intend to use to create/add a link to a 'subLink' div, and add an onclick event to this link that loads associated 'content' to a contentDiv:
function addSubLink(text, name, content) {
// append programLink span to subLinks:
document.getElementById("subLinks").innerHTML += "<span class=\"programLink\" id=\"" + name + "\">" + text + "</span>";
// load program content onclick:
document.getElementById(name).onclick = function () {
// set value of programContent to content's value
document.getElementById("programContent").innerHTML = content;
}
}
This function would be called, for example, by loadAboutPage() to populate the subLink div
var whatContent = "<p>A website!</p>";
var whyContent = "<p>Recreation!</p>";
var howContent = "<p>Kludges.</p>";
addSubLink("WHAT", "whatLink", whatContent);
addSubLink("WHY", "whyLink", whyContent);
addSubLink("HOW", "howLink", howContent);
The problem is that only the last subLink has an onclick event attached to it (content is loaded and css class changed). That is, it creates WHAT, WHY, and HOW links, but only appends the onclick function to the last called: HOW, in this case.
I'm very rusty when it comes to JavaScript, so I have no idea if it's a result of my lack of knowledge about anonymous functions, or using the local 'name' variable incorrectly, or anything else completely different. I've searched for awhile, but it seems I'm too ignorant to even figure out what a similar problem would be!
Anyway, I greatly appreciate your help! Thanks in advance!
EDIT:
Here's a complete HTML example:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>Stack Overflow Example</title>
<script type="text/javascript">
function addSubLink(text, name, content) {
document.getElementById("subLinks").innerHTML += "<span class=\"programLink\" id=\"" + name + "\">" + text + "</span>";
document.getElementById(name).onclick = function () {
document.getElementById("program").innerHTML = content;
}
}
window.onload = function() {
var whatContent = "<p>A website!</p>";
var whyContent = "<p>Recreation!</p>";
var howContent = "<p>Kludges.</p>";
addSubLink("WHAT", "whatLink", whatContent);
addSubLink("WHY", "whyLink", whyContent);
addSubLink("HOW", "howLink", howContent);
}
</script>
</head>
<body>
<div id="container">
<div id="programWindow">
<div id="subLinks"> </div>
<div id="program"> </div>
</div>
</div>
</body>
</html>
The issue is due to:
....innerHTML += "...";
By setting innerHTML, all existing child elements are first removed, then the markup is parsed to create new elements. So, while the original "WHAT" and "WHY" spans did have onclick bindings, they've being replaced by similar elements that don't.
To append a new element and keep state, you'll want to use DOM methods like createElement(), appendChild(), and createTextNode() (or set textContent/innerText):
function addSubLink(text, name, content) {
var span = document.createElement('span');
span.className = 'programLink';
span.id = name;
span.appendChild(document.createTextNode(text));
// append programLink span to subLinks:
document.getElementById('subLinks').appendChild(span);
// load program content onclick:
span.onclick = function () {
// set value of programContent to content's value
document.getElementById("programContent").innerHTML = content;
};
}
Example: http://jsfiddle.net/bG7Dt/