I have a problem to insert html into document using javascript.
Code that trying to insert html into document:
function loadTaskPage(taskId){
fetch("https://localhost:44321/api/Tasks/1")
.then(function(response){
return response.text();
}).then(function(data){
document.body.insertAdjacentHTML('beforeend', data);
}).catch(function(error){
alert(error);
})
}
This code part I took from tutorial, source code of tutorial could be found in this link: https://github.com/bstavroulakis/progressive-web-apps/blob/master/car-deals/js/carService.js
If I will try to open this link https://localhost:44321/api/Tasks/1 in browser I receive normally styled web page, but when I try to insert it to document, html code got escaped and don't display anything.
Inserted html looks like:
<div id="\"myModal\"" class="\"modal" fade\"="">...
The code below is bootstrap modal copied from code examples. As you see there appeared symbols \" that escapes quotes.
Response with html I receive from my ASP.Net Web Api with header: text/html
How should I insert this html code into document using javascript?
How to insert html to document using javascript?
You can find that answer here:
You can use
document.getElementById("parentID").appendChild(/*..your content created using DOM methods..*/)
or
document.getElementById("parentID").innerHTML+= "new content"
As mentioned in the comments, this didn't seem to work and left the elements without style, this is because the escaping in the string being added to the innerHTML is off: there are too many ".
In the provided HTML example <div id="\"myModal\"" class="\"modal" fade\"="">... each attribute is surrounded by "\" ... \"" which means that if you were to look at the string of the attribute's value it would look something like '" ... "', which is what is causing the styles to not be added.
If you remove the extra " the HTML should be appended as expected:
<div id=\"myModal\" class=\"modal fade\">...
See this example showing what happens with the different escaping:
document.getElementById("foo").innerHTML += '<div class="\"bar\"">Hello World!</div>'; // Escaped with too many `"`
document.getElementById("foo").innerHTML += '<div class=\"bar\">Hello World!</div>'; // Properly escaped
.bar {
color: red;
}
<div id="foo">
</div>
The insertAdjacentHTML() method of the Element interface parses
the specified text as HTML or XML and inserts the resulting nodes into
the DOM tree at a specified position. It does not reparse the element
it is being used on, and thus it does not corrupt the existing
elements inside that element. This avoids the extra step of
serialization, making it much faster than direct innerHTML
manipulation.
Ok, looks like problem was in api service. In some reasons in debug mode showed to me correct html that I return to user. So after a few changes of api code all works as should.
If someone interested in ASP.Net Web API how to return view as a string and be able to add it to html all you need is to add Reference to RazorEngine and use the following code:
var response = new HttpResponseMessage(HttpStatusCode.OK);
var viewPath = HttpContext.Current.Server.MapPath(#"~/Views/Tasks/TaskDetails.cshtml");
var template = File.ReadAllText(viewPath);
var key = new NameOnlyTemplateKey("TaskDetails", ResolveType.Global, null);
if(!Engine.Razor.IsTemplateCached(key, null))
Engine.Razor.AddTemplate(key, new LoadedTemplateSource(template));
StringBuilder sb = new StringBuilder();
StringWriter sw = new StringWriter(sb);
Engine.Razor.RunCompile(key, sw, null, model);
response.Content = new StringContent(sb.ToString());
response.Content.Headers.ContentType = new MediaTypeHeaderValue("text/html");
return response;
P.S. Code is not completely correct. It requires some optimizations.
Related
I'm building several carousels on a webpage with jQuery by calling all the information I need from YouTube with the Youtube Data API v3.
After doing the designing and the functions I'm struggling with one simple thing that I cannot understand.
I use append(``) so that I can append all the HTML that I need to the element that I want, and also inserting other informations with the variables in the ${var} notation.
Everything works fine EXCEPT for a single string variable preview. It's like it not recognized as a variable and in the final output is rendered like a string chunck.
Now some code.
This is the preparation for calling the function that loads everything:
jQuery(document).ready(function () {
var apikey = 'my-api-key';
var URL = 'https://www.googleapis.com/youtube/v3/playlistItems';
var playlists = {
1: 'PL549CFEF61BF98279',
2: 'PLX_IxBH-yGtonzSE2zyplhI2oky7FWvbE',
3: 'PL038B3F56D598DD61',
4: 'PLDDFDDD10E5584056',
5: 'PLD4F65416EB11640F',
}
loadVids(apikey, URL, playlists);
});
Next loadVids, for every youtube playlist call getJSON() and retrieve the data:
function loadVids(apikey, URL, playlists) {
for (const menuid in playlists) {
var options = { part: 'snippet', key: apikey, maxResults: 20, playlistId: playlists[menuid] }
jQuery.getJSON(URL, options, function (data) {
resultsLoop(data, menuid, apikey);
});
}
}
then resultLoop using each() puts all the information inside some HTML to be appended somewhere in the webpage (i stripped all the original attributes to keep it readable).
function resultsLoop(data, menuid) {
jQuery.each(data.items, function () {
var alttext = this.snippet.title;
var title = alttext.substring(0, 57) + '…'
var vid = this.snippet.resourceId.videoId;
var preview = this.snippet.thumbnails.standard.url;
jQuery("#carousel-" + menuid + " ul")
.append(`
<li>
<article>
<div>
<a href="//www.youtube.com/watch?v=${vid}&fs=1&autoplay=0&rel=0">
<img alt="${alttext}" src="${preview}">
</a>
</div>
<div>
<h4>${title}</h4>
</div>
</article>
</li>
`);
});
}
At the end of it the <img> tag is
<img alt="some text" src="/$%7Bpreview%7D">
I tried to:
change the name of the variable
console logging it before, after append(), without issues
typeof says it's a normal string
it gives me the same result on every browser
I really don't understand what I'm doing wrong, and only preview doesn't work, all the other variables in the append() are working properly.
Why you are not using concat as you have already did for jQuery("#carousel-" + menuid + " ul") !!
Example: (Please use this code for append and check, I have used single quote and not backquote as it is not accepted by js validation)
jQuery("#carousel-" + menuid + " ul").append('<li><article><div><img alt="'+alttext+'" src="'+preview+'"></div><div><h4>'+title+'</h4></div></article></li>');
and remove all white spaces from the append string. I hope it is what looking for.
Just to let you know, all the above was working on a Joomla page.
Taking all the code, apart from the jQuery(document).ready(function(){...loadVids()...}, and putting it on a .js file resolved everything.
I think there is some filter that won't let you inject external resources like https://i.ytimg.com/vi/lmuUD9_eDnY/sddefault.jpg in the page with javascript alone (and that's clever), but the filter doesn't apply if you include a .js file within the website itself.
A mediocre workaround for a mediocre javascript code. Thanks to Rory in the comments that gave me some insight.
I asked this earlier but I wanted to rephrase the question. I am trying to make a scraper for my project. I would like to have it display a certain part of a link. The only part of the link that changes is the number. This number is what I would like to scrape. The link looks like this:
<a href="/link/player.jsp?user=966354" target="_parent" "="">
As mentioned I am trying to scrap only the 966354 part of the link. I have tried several ways to do this but cant figure it out. When I add
<a href="/link/player.jsp?user="
to the code below it breaks
List<string> player = new List<string>();
string html = webControl2.ExecuteJavascriptWithResult("document.getElementsByTagName('a')[0].innerHTML");
MatchCollection m1 = Regex.Matches(html, "<a href=\\s*(.+?)\\s*</a>", RegexOptions.Singleline);
foreach (Match m in m1)
{
string players = m.Groups[1].Value;
player.Add(players);
}
listBox.DataSource = player;
So I removed it, it shows no errors until I go to run the program then I get this error:
"An unhandled exception of type 'System.InvalidOperationException' occurred in Awesomium.Windows.Forms.dll"
So I tried this and it some what works:
string html = webControl2.ExecuteJavascriptWithResult("document.getElementsByTagName('html')[0].innerHTML");
This code scraps but not the way I would like, Could someone lend a helping hand please.
I would use HtmlAgilityPack (install it via NuGet) and XPath queries to parse HTML.
Something like this:
string html = webControl2.ExecuteJavascriptWithResult("document.getElementsByTagName('html')[0].innerHTML");
var htmlDoc = new HtmlAgilityPack.HtmlDocument();
htmlDoc.LoadHtml(html);
var playerIds = new List<string>();
var playerNodes = htmlDoc.DocumentNode.SelectNodes("//a[contains(#href, '/link/profile-view.jsp?user=')]");
if (playerNodes != null)
{
foreach (var playerNode in playerNodes)
{
string href = playerNode.Attributes["href"].Value;
var parts = href.Split(new char[] { '=' }, StringSplitOptions.RemoveEmptyEntries);
if (parts.Length > 1)
{
playerIds.Add(parts[1]);
}
}
id.DataSource = playerIds;
}
Also you may find these two simple helper classes useful: https://gist.github.com/AlexP11223/8286153
The first one is extension methods for WebView/WebControl and the second one has some static methods to generate JS code for retrieving elements (JSObject) by XPath + getting coordinates of JSObject)
Using a sample html file such as below, I was unable to duplicate the exception.
<html>
test
</html>
However, the javascript
document.getElementsByTagName('a')[0].innerHTML
will return "test" in my example. What you probably want is
document.getElementsByTagName('a')[0].href
which will return the href portion.
The 'innerHTML' property will return everything between the start and end tags (such as <html> </html>). This is probably the reason you have better success when getting the 'html' element - you end up parsing the entire <a> </a> link.
FYI, as a test you can use your browser to test out the javascript output.
In my server application (on Parse Cloud Code), I want save some string data. There are HTML entities here, which I want to encode.
So i find a solution with Javascript:
var txt = document.createElement("textarea");
txt.innerHTML = html;
return txt.value;
This code work perfectly on html pages, where document exists. But there isn't such variable on server.
How can i declare document variable? Or maybe you know another solutions for encoding HTML entities.
You could use html-entities on Node, install it like:
npm install html-entities
then you got entities.encode(..) and entities.decode(..) functions:
var Entities = require('html-entities').XmlEntities;
entities = new Entities();
console.log(entities.encode('<>"\'&©®')); // <>"'&©®
there are more examples in usage part on gihub repo.
function encode(r){
return r.replace(/[\x26\x0A\<>'"]/g,function(r){return"&#"+r.charCodeAt(0)+";"})
}
test.value=encode('How to encode\nonly html tags &<>\'" nice & fast!');
/*************
* \x26 is &ersand (it has to be first),
* \x0A is newline,
*************/
<textarea id=test rows=11 cols=55>www.WHAK.com</textarea>
Since I asked this question, I learned JavaScript and AJAX. So, my suggestion will be using AJAX and JSON for communication between browser and server-side.
I have a method that adds javascript to the end of partial views if it's an ajax request.
My problem though is that when the script is returned, the script tags have been removed and the function I want to execute is written in plain text.
if (httpContext.Request.IsAjaxRequest())
{
script = "MyNamespace.globals.initFunctions.push(function() { " + script + " });";
return new HtmlString(#"<script type=""text/javascript"">" + script + "</script>");
}
So, instead of getting the desired result of
<script type="text/javascript">MyNamespace.globals.initFunctions.push(function() { MyNamespace.init(); });</script>
I get MyNamespace.globals.initFunctions.push(function() { MyNamespace.init(); }); in plain text.
What could be the reason?
Edit:
Trying it with Html.Raw() did not help. While the script string does contain the script tags, they are still removed when rendered.
#{
string script = ViewUtilities.AddScript("MyNamespace.init();", this.ViewContext.HttpContext);
}
#Html.Raw(script);
Edit 2:
Now I've tried writing it all in the view like this,
<script type="text/javascript">
MyNamespace.globals.initFunctions.push(function() { MyNamespace.init(); });
</script>
and it still removes the tags around the script and renders it as plain text.
I don't know where to go from here...
When I exam the response with Firebug it looks fine but looking at the html it's not.
The HTML is being encoded which happens auto-magically with ASP.NET MVC.
Using #Html.Raw("htmlstring") should give you the raw HTML value of the string without stripping the tags.
You want to use #Html.Raw(whatever function you call)
I think you also probably want to return return MvcHtmlString.Create(fullscript);
If you convert this to an HtmlHelper method, it will work. Change your ViewUtilities class as follows:
public static class ViewUtilities
{
public static MvcHtmlString AddScript(this HtmlHelper htmlHelper, string script)
{
if (htmlHelper.ViewContext.HttpContext.Request.IsAjaxRequest())
return new MvcHtmlString(#"<script type=""text/javascript"">" + script + "</script>");
return new MvcHtmlString("");
}
}
Then, in the web.config file in the Views folder (and in any Views folders in any Areas), add the following to the namespaces list in the <pages pageBaseType="System.Web.Mvc.WebViewPage"> element:
<add namespace="{namespace where ViewUtilities class is located}"/>
Finally, in your view:
#Html.AddScript("MyNamespace.init();")
I am creating a webapp and I have been using tag in my JSPs to ensure that all my links (both to pages and to resources such as images/css) are always consistent from the root of the application, and not relative to my current location.
Some of the content I am creating using jQuery, for example, I am creating a HTML table by parsing a JSON object and using jquery.append() to insert it in to a div.
My question is, if I want to dynamically create a link using jquery how can I achieve a consistent URL regardless of the page being executed? I have tried just building the html with the tag in it, but no joy.
Thanks!
var baseURL = "/* Server-side JSP code that sets the base URL */";
$("<a />", { href: baseURL+"/my/resource/here.jsp" }); //Your proper link
Or you could do:
var baseURL = "http://"+location.host+"/my/base/url/";
//Which gives you something like http://mySite.com/my/base/url/
Get the root value of your webapp into a string using a jsp tag inside your javascript.
var root = < %=myRootVariable%> //This evaluates to http://www.myapp.com
var dynamicBit = "/foo/bar"
var dynamicLinkUrl = root + dynamicBit
var $newa = $("Hello, world");
$someJQElement.append($newa)
Hopefully none of this will occur in the global namespace. Just sayin'