I am responding to clicks on li's by using $.post to post to an action method in my MVC application.
I want to send a link back in Json.
Can I have this link render as html rather than text ? how ?
I tried this, just to test the html:
var link = "<b>Hi</b>";
var encoded = Server.HtmlEncode(link);
that came out as <b>Hi</b>
Surely there is just a Json.encode or visual studio method I can use and I don't have to format it myself? Have googled fairly extensively and can't find anything about an Json.encode
var link = "<b>Hi</b>";
var encoded = new JavaScriptSerializer().Serialize(link);
the page rendered "\u003cb\u003eHi\u003c/b\u003e"
If I send just the link variable, i.e:
var link = "<b>Hi</b>"
<b>Hi</b> renders
This is the line which sends it back:
return Json(new {Title = pTitle, Selection = pSelection, Link = pLink}, JsonRequestBehavior.AllowGet);
Starting to get frustrated, wtf!
Silly me, I didn't post enough code where the problem was:
<script type="text/javascript">
function TreeView_onSelect(e) {
...
$.post(url, id, function (data, textStatus) {
...
$("#panel-link").text(data.Link);
}
$("#panel-link").text(data.Link);
obv has to be
$("#panel-link").html(data.Link);
Try using JavaScriptSerializer:
var link = "<b>Hi</b>";
var encoded = new JavaScriptSerializer().Serialize(link);
Try to use javascript's decodeURI() function.
http://www.w3schools.com/jsref/jsref_decodeuri.asp
<script type="text/javascript">
var uri="mytest.asp?name=ståle&car=saab";
document.write(encodeURI(uri)+ "<br />");
document.write(decodeURI(uri));
</script>
The output of the code above will be:
mytest.asp?name=st%C3%A5le&car=saab
mytest.asp?name=ståle&car=saab
I have the same problem with you and killing me whole day,
I solved this problem by using Json.NET
Sample code is :
Newtonsoft.Json.JsonConvert.SerializeObject(link);
Reference
http://json.codeplex.com/documentation
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.
Hi I have the following TextArea to display a JSON string:
<TextArea id="payloadlabel" width="1000px" height='auto' rows='80' />.
My problem is that the JSON string is not well formatted, see example.
I'm using the library vkbeautify as follows:
var myObj = {
"urn.getxxxx": {
"urn.xxxx" : "cxxxxx-44e9-xxxx-a91b-0000xxxx\\xxxxx\\3xx\\xx\\x\\",
"urn.xxxx" : "xxxxx",
"urn.xxxxx" : "x",
"urn.xxxx": "20xx-07-08xxx:03:41+02:00"
}
};
var request = JSON.stringify(myObj);
vkbeautify.json(request);
var tryModel = new sap.ui.model.json.JSONModel();
tryModel.setData(request);
var payloadtxta = sap.ui.getCore().byId(view.createId('payloadlabel'));
payloadtxta.setModel(tryModel);
payloadtxta.setValue(request);
Unfortunately it's not working. The JSON content remains exactly like in the example. What is wrong here?
I have the vkbeautify.js file in my web content and I included it in the index.
<script type="text/javascript" src="vkbeautify.js"></script>
As I get no error for the vkbeautify method I think I included it in the right way. Suggestions are welcomed if you know any other method to format JSON content any other library or idea. Thank you.
You are using the wrong variable (BTW: JSON.stringify is superfluous as you already have a JSON string):
var beautifiedObj = vkbeautify.json(myObj);
var payloadtxta = this.byId(view.createId("payloadlabel"));
payloadtxta.setValue(beautifiedObj);
The model is never used in your example, thus you can remove it or use it as intendend by UI5 and bind the control directly to the model property.
<TextArea id="payloadlabel" value={/request}" width="1000px" height='auto' rows='80' />.
this.setModel(new sap.ui.model.json.JSONModel({
"request" : vkbeautify.json(myObj)
});
Looking at the source of vkbeautify, it is slightly pointless if you are just using that library for this purpose - you can do what you need with standard JavaScript:
var beautifiedTxt = JSON.stringify(myObj, null, 4);
var payloadtxta = sap.ui.getCore().byId(view.createId("payloadlabel"));
payloadtxta.setValue(beautifiedTxt);
Check out the documentation of JSON.stringify on MDN here - https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify
REF source for vkbeautify - https://github.com/vkiryukhin/vkBeautify/blob/master/vkbeautify.js#L152.
I am programming a web application in C# MVC which dynamically loads information from a server in order to improve the speed.
Currently I have some errors and I am unable to diagnose why these are causing issues so I'll try my best to explain what's happening:
This div is created many times and grabs the ID for each project.
<div>
Open:
#{string JiraKey = item.JiraProjectKey;}
<span id="JiraOpen" onload="GetOpenJira"></span>
</div>
Then in the span, the script GetOpenJira is initiated:
<script id="GetOpenJira">
var url = "/HicVault/Projects/GetNumJiraOpenByKey";
var key = $('#JiraKey').val();
$.get(url, { input: key }, function (data) { $("#JiraOpen").html(data) });
</script>
This script SHOULD asynconously ask the controller to complete the function GetNumJiraOpenByKey with the JiraKey being used as a parameter. The function in the controller is:
[HttpGet]
public ActionResult GetNumJiraOpenByKey(string JiraProjectKey)
{
var sJql = "project = \"" + JiraProjectKey + "\" and status = \"Open\"";
var resultFieldNames = new List<string> { "resolution" };
Issues issues = new JiraClient(new JiraAccount()).GetIssuesByJql(sJql, 0, 1000, resultFieldNames);
return PartialView(issues.total);
}
Essentially this function returns an int once it has counted all of the issues for that particular project. I would like this to be done with AJAX using jQuery to load these values after the page has been loaded to vastly increase speed. (Currently without AJAX, pages take >30 sec to load).
Thanks if anyone can help.
EDIT: I suppose I should ask a question, currently with this code the page loads and after around 5 seconds, a server 500 error appears in the console stating there is an Internal Server Error. I know this is a general error, going in deeper points to the line:
"$.get(url, { input: key }, function (data) { $("#JiraOpen").html(data) ".
I am guessing either the logic of my work isn't possible in Razor MVC + JS, or I am getting the fundamentals of jQuery ajax get wrong?
rewrite your script as following...
<script id="GetOpenJira">
var url = "/HicVault/Projects/GetNumJiraOpenByKey";
var key = $('#JiraKey').val();
$.get(url, { JiraProjectKey: key }, function (data) { $("#JiraOpen").html(data) });
</script>
I'm trying to look at the html data returned from a google reverse image search. The URL I'm passing to google contains some characters that get encoded, notably ? changes to %3F, and google doesn't seem to understand the formatted URL (pic_url below). Is there any way to send the URL so that it does not get formatted? Or is there another way around this issue?
My code looks like:
var google_url = "https://www.google.com/searchbyimage?image_url=";
var pic_url = "http://img.cpcdn.com/recipes/_o1f2b886e/50x50c/d9e62798f1c807c1891454bed562e4c9.jpg?u=941483&p=1362455199";
var search_url = google_url + pic_url;
$.getJSON('http://whateverorigin.org/get?url=' +
encodeURIComponent(search_url) + '&callback=?',
function(data){
$("#targetWrapper").html(data.contents);
http_data = data["contents"];
console.log(http_data);
});
The error I get back in the console:
`The requested URL <code>/searchbyimage%3Fimage_url=http%253A%252F%252Fimg.cpcdn.com%252Frecipes%252F_o1f2b886e%252F50x50c%252Fd9e62798f1c807c1891454bed562e4c9.jpg%253Fu%253D941483%2526amp%253Bp%253D1362455199</code>
was not found on this server.
<ins>That’s all we know.</ins>`
But if you just copy and paste https://www.google.com/searchbyimage?image_url=http://img.cpcdn.com/recipes/_o1f2b886e/50x50c/d9e62798f1c807c1891454bed562e4c9.jpg?u=941483&p=1362455199 to the Address Bar it works. Any thoughts?
there is a bug in whateverorigin.org:
https://github.com/ripper234/Whatever-Origin/issues/1
note that the solution proposed doesn't work for me...
var page = UrlFetchApp.fetch(contestURL);
var doc = XmlService.parse(page);
The above code gives a parse error when used, however if I replace the XmlService class with the deprecated Xml class, with the lenient flag set, it parses the html properly.
var page = UrlFetchApp.fetch(contestURL);
var doc = Xml.parse(page, true);
The problem is mostly caused because of no CDATA in the javascript part of the html and the parser complains with the following error.
The entity name must immediately follow the '&' in the entity reference.
Even if I remove all the <script>(.*?)</script> using regex, it still complains because the <br> tags aren't closed.
Is there a clean way of parsing html into a DOM tree.
I ran into this exact same problem. I was able to circumvent it by first using the deprecated Xml.parse, since it still works, then selecting the body XmlElement, then passing in its Xml String into the new XmlService.parse method:
var page = UrlFetchApp.fetch(contestURL);
var doc = Xml.parse(page, true);
var bodyHtml = doc.html.body.toXmlString();
doc = XmlService.parse(bodyHtml);
var root = doc.getRootElement();
Note: This solution may not work if the old Xml.parse is completely removed from Google Scripts.
In 2021, the best way to parse HTML on the .gs side that I know of is...
Click + next to Library
Enter 1ReeQ6WO8kKNxoaA_O0XEQ589cIrRvEBA9qcWpNqdOP17i47u6N9M5Xh0
Click "Look up"
Click Add
Sample usage:
const contentText = UrlFetchApp.fetch('https://www.somesite.com/').getContentText();
const $ = Cheerio.load(contentText);
$('.some-class').first().text();
That's it -- this is probably the closest we'll get to doing jQuery-like DOM selection in GAS. The .first() is important or else you may extract more content than you expected (think of it as using querySelector() instead of querySelectorAll()).
Credit where credit is due: https://github.com/tani/cheeriogs
As of May 2020, you can now use the Cheerio library for Google Apps Script to do this.
Returns the content of Wikipedia's Main Page
const content = getContent_('https://en.wikipedia.org');
const $ = Cheerio.load(content);
Logger.log($('#mp-right').text());
Returns the content of the first paragraph <p> of Wikipedia's Main Page
const content = getContent_('https://en.wikipedia.org');
const $ = Cheerio.load(content);
Logger.log($('p').first().text());
To add to your project:
Select Resources - Libraries... in the Google Apps Script editor. Enter the project key 1ReeQ6WO8kKNxoaA_O0XEQ589cIrRvEBA9qcWpNqdOP17i47u6N9M5Xh0 in the Add a library field, and click "Add". Select the highest version number, and click "Save".
I found that the best way to parse html in google apps is to avoid using XmlService.parse or Xml.parse. XmlService.parse doesn't work well with bad html code from certain websites.
Here a basic example on how you can parse any website easily without using XmlService.parse or Xml.parse. In this example, i am retrieving a list of president from "wikipedia.org/wiki/President_of_the_United_States"
whit a regular javascript document.getElementsByTagName(), and pasting the values into my google spreadsheet.
1- Create a new Google Sheet;
2- Click the menu Tools > Script editor... to open a new tab with the code editor window and copy the following code into your Code.gs:
function onOpen() {
var ui = SpreadsheetApp.getUi();
ui.createMenu("Parse Menu")
.addItem("Parse", "parserMenuItem")
.addToUi();
}
function parserMenuItem() {
var sideBar = HtmlService.createHtmlOutputFromFile("test");
SpreadsheetApp.getUi().showSidebar(sideBar);
}
function getUrlData(url) {
var doc = UrlFetchApp.fetch(url).getContentText()
return doc
}
function writeToSpreadSheet(data) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
var row=1
for (var i = 0; i < data.length; i++) {
var x = data[i];
var range = sheet.getRange(row, 1)
range.setValue(x);
var row = row+1
}
}
3- Add an HTML file to your Apps Script project. Open the Script Editor and choose File > New > Html File, and name it 'test'.Then copy the following code into your test.html
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<input id= "mButon" type="button" value="Click here to get list"
onclick="parse()">
<div hidden id="mOutput"></div>
</body>
<script>
window.onload = onOpen;
function onOpen() {
var url = "https://en.wikipedia.org/wiki/President_of_the_United_States"
google.script.run.withSuccessHandler(writeHtmlOutput).getUrlData(url)
document.getElementById("mButon").style.visibility = "visible";
}
function writeHtmlOutput(x) {
document.getElementById('mOutput').innerHTML = x;
}
function parse() {
var list = document.getElementsByTagName("area");
var data = [];
for (var i = 0; i < list.length; i++) {
var x = list[i];
data.push(x.getAttribute("title"))
}
google.script.run.writeToSpreadSheet(data);
}
</script>
</html>
4- Save your gs and html files and Go back to your spreadsheet. Reload your Spreadsheet. Click on "Parse Menu" - "Parse". Then click on "Click here to get list" in the sidebar.
Xml.parse() has an option to turn on lenient parsing, which helps when parsing HTML. Note that the Xml service is deprecated however, and the newer XmlService doesn't have this functionality.
For simple tasks such as grabbing one value from a webpage, you could use a regular expression. Regex is notoriously bad for parsing HTML as there's all sorts of weird cases it can get tripped up, but if you're confident about the HTML you're accessing this can sometimes be the simplest way.
Here's an example that fetches the contents of the page's <title> tag:
var page = UrlFetchApp.fetch(contestURL);
var regExp = new RegExp("<title>(.*)</title>", "gi");
var result = regExp.exec(page.getContentText());
// [1] is the match group when using parenthesis in the pattern
var value = result ? result[1] : 'No title found';
I know it is not exactly what OP asked, but I found this question when I was looking for some html parsing options - so it might be useful for others as well.
There is an easy to use the library for TEXT parsing. It's useful if you want to get only one piece of information from the html(xml) code.
EDIT 2021: The script library id is:
1Mc8BthYthXx6CoIz90-JiSzSafVnT6U3t0z_W3hLTAX5ek4w0G_EIrNw
It works like in the picture above
function getData() {
var url = "https://chrome.google.com/webstore/detail/signaturesatori-central-s/fejomcfhljndadjlojamaklegghjnjfn?hl=en";
var fromText = '<span class="e-f-ih" title="';
var toText = '">';
var content = UrlFetchApp.fetch(url).getContentText();
var scraped = Parser
.data(content)
.from(fromText)
.to(toText)
.build();
Logger.log(scraped);
return scraped;
}
If you are using
Cheerio library for Google Apps Script
Source code
Library page (⭐ star it!)
Installation by library ID:
1ReeQ6WO8kKNxoaA_O0XEQ589cIrRvEBA9qcWpNqdOP17i47u6N9M5Xh0
A function to get current emojis from unicode.org:
function getEmojis() {
var t = new Date();
var url = 'https://unicode.org/emoji/charts/full-emoji-list.html';
var fetch = UrlFetchApp.fetch(url);
var contentText = fetch.getContentText();
//console.log(new Date() - t);
// Cherio
var $ = Cheerio.load(contentText);
var data = [];
$("table > tbody > tr").each((index, element) => {
var row = [];
$(element).find("td").each((index, child) => {
row.push($(child).text());
});
if (row.length > 0) {
data.push(row);
}
});
//console.log(data);
//console.log(new Date() - t);
// Result
return data;
}
↑ Sample code shows how to parse table and put it into [[array]]
May be used as a custom function:
Bonus
Parsing the site may be a time-consuming operation + you may reach the limit.
Here's a test file with a full version of the script:
https://docs.google.com/spreadsheets/d/1iO7YjYWyfseQu_YCfRbGDPg7NskOgMu_iO1iGjr7KxY/edit#gid=93365395
↑ it uses CasheService to reduce the number of calls.
Natively there's no way unless you do what you already tried which wont work if the html doesnt conform with the xml format.
There are two options
a) One is to use JavaScript's string functions. First locate your tag using string.indexOf() and then extract the data you want using string.substring().
b) The other option is to make use of the Xml Service.
It's not possible to create an HTML DOM server-side in Apps Script. Using regular expressions is likely your best option, at least for simple parsing.