Google Apps Script, UrlFetchApp and JQuery - javascript

I would like to load a web page every day (perhaps more times a day), parse its data and email results.
To parse the web page I am using a parse.gs script like the following:
var url="http://http://example.com";
var page = UrlFetchApp.fetch(url).getContentText();
var XmlDoc = Xml.parse(page, true);
When I parse XmlDoc I have only getElement/s functions available and I find it difficult to do an effective job. So I would like to use something more productive, like the JQuery selectors.
As far as I understood I have to add a jquery.html page to the project like:
<html>
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.1/jquery.min.js"></script>
</html>
Then add to parse.gs the function:
function doGet() {
return HtmlService.createHtmlOutputFromFile('jquery');
}
After calling doGet, how do I parse XmlDoc? Using lines like $('#content').html(XmlDoc); doesn't work.

As an alternative to jquery, try building on the capabilities of the Xml Service entirely in apps-script.
A previous answer introduced a utility function that locates elements in the XML Document by searching for properties matching the search criteria.
getElementByVal( body, 'input', 'value', 'Go' )
... will find
<input type="submit" name="btn" value="Go" id="btn" class="submit buttonGradient" />
It also showed one possible specialization, for searching 'id' attributes of <div>s:
getDivById( html, 'tagVal' )
... will find <div id="tagVal">
If you are able to identify an element uniquely, as in the above examples, a simple script can get you that element easily:
var url="http://http://example.com";
var page = UrlFetchApp.fetch(url).getContentText();
// Get <div id="content">
var contentDiv = getDivById( pageDoc.getElement().body, 'content' );
...

Related

How can I get an HTML tag’s value to send an HTML.Action()

I have these lines of code:
<span
class="close-modal"
onclick="#Html.Action("SaveNotes", "CallCenter", new { activityId = item.callIdKey, noteText = "test1" })">
×
</span>
Notes: <br />
<textarea name="paragraph_text" rows="5" style="width:90%">
#item.NoteText
</textarea>
I would like to replace test1 from the noteText route variable and instead change it to whatever the value in the <textarea> tag is.
Is there an elegant way of doing this without writing a giant block of jQuery code?
#Html.Action() renders a partial view as an HTML string during page processing (on the server side). It doesn't exist any more in the markup, once the page is sent to the browser. You can't do what you are trying to do this way. At the very least, I'm sure you don't want to render a partial view inside the onclick event of your <span> tag.
Why not instead use an HTML helper for the <textarea> tag? Then you can get whatever value the user typed into it on the server code. You'll want to make the form post itself back to the server on the close-modal element:
<span class="close-modal" onclick="$('form').submit()">×</span>
<form method="post" action="#Url.Action("SaveNotes", "CallCenter", new { activityId=item.callIdKey }">
Notes: <br />
#Html.TextArea("noteText", item.NoteText, new { rows="5", style="width:90%" })
</form>
This assumes you have jQuery already (a common assumption with ASP.NET). You may not need the <form> tags if you already have a form on your page.
A #gunr2171 notes in the comments, the only way to dynamically update a link once it's been rendered to the browser is via some form of client-side scripting, typically JavaScript. In your case, I'd recommend doing something like this:
<span
class="close-modal"
data-href-template="#Url.Action("SaveNotes", "CallCenter", new {activityId = item.callIdKey, noteText="{note}"})"
>
×
</span>
Note: As #HBlackorby notes in his answer, you shouldn't be using #Html.Action() here; I assume you meant #Url.Action().
This way, your JavaScript has a template (data-href-template) that it can work against with a clearly defined token ({note}) to replace, instead of needing to parse the URL in order to identify where the previously replaced text is. Otherwise, you potentially end up in a scenario where you type e.g. CallCenter into your <textarea /> and it's now an ambiguous reference that you can't just blindly replace. Or, worse, you type 'a' and it's really ambiguous.
If you are already using jQuery on your site, the actual replacement might be done using something along the lines of:
$(document).ready(function () {
$('span.close-modal').click(function() {
var noteInput = $('textarea[name="paragraph_text"]');
var encodedNote = encodeURI(noteInput.text());
var template = $(this).data("href-template");
var targetUrl = template.replace("{note}", encodedNote);
window.location.href = targetUrl;
});
});
You can also do this without jQuery, obviously—and should if you're not already depending on it. The point is to illustrate that this doesn't necessarily need to be a "giant block of jQuery code". In fact, this could be done in just a few lines—and probably should be. I deliberately broke it out into multiple steps and variables for the sake of readability.

parse <script> tag with js/jQuery

I have a HTML page where a user is able to edit a HTML resource (using ACE Editor). Within this HTML source, there is a <script>-tag, which does some pretty basic stuff.
Is there any elegant solution to parse the script tag in order to (e.g.) evaluate the variables used within the script tag? For "normal" tags I use parseHTML() to have the html as a jQuery object.
From this example, I would like to retrieve the value of $myVal (which is "f00") and write it to #myLabel:
<textarea id="myScript" rows="5" readonly>
<script>
$myVal = "f00";
</script>
</textarea>
<label id="myLabel">Hello</label>
$(function(){
$scriptVar = $('#myScript').text;
// parse the $scriptVar
// retrieve the value of, $myVal, write it to #myLabel
//$myParsedValue = ???
//$('#myLabel').text('bar!');
});
And here is the fiddle: https://jsfiddle.net/stepdown/jqcut0sn/
Is this possible at all? I don't really care about vanilla js, jQuery, regex or maybe even an external library for that purpose.
Thanks to #JeremyThille, who pointed me to the right direction. I found out, what I want to achieve is possible through jQuerys $.globalEval() - see the official documentation.
Basically what globalEval() does: it runs the script which is written in the <textarea> and makes the variables / functions globally accessible.
IMPORTANT: this implies, that syntax errors (etc) by the user will break the evaluation, and sequential functionality could be flawed. Also, the new variables are GLOBAL, so basically a user could rewrite scripts on the hosting page. (In my case both problems are of minor importance, since this is an internal application for trained users - they also have syntax highlighting through the amazing ACE editor. But I wanted to make sure to point it out. Also, there are several articles regarding the risks/ouch-moments when using eval()...)
I updated the fiddle to achieve what I wanted: https://jsfiddle.net/stepdown/Lxz7q6uv/
HTML:
<textarea id="myScript" rows="5" readonly>
$myVal = "f00";
</textarea>
<hr />
<label id="myLabel">Hello</label>
Script:
$(function(){
var myScriptContent = $('#myScript').text();
$.globalEval(myScriptContent);
console.log($myVal);
$('#myLabel').text($myVal);
});

Dynamic form using HTML and JQuery

I am trying to make a dynamic form using HTML and CSS. I am adding parts of my code below. I can not figure out why the code is not working.
JavaScript:
<script>
$(document).ready(function(e) {
var labelfiled = '<div><label>Label</label><input type="text" name="label[]"></div>';
var valuefiled = '<div><label>Value</label><input type="text" name="value[]"></div>';
var labdiv = $(".labdiv");
var valdiv = $(".valdiv");
var addbutton = $(".add_more");
$(addbutton).click(function(){
$(labdiv).append(labelfiled);
$(valdiv).append(valuefield);
});
</script>
HTML:
<form>
<div class="col-md-6 labdiv">
<div><label>Label</label>
<input type="text" name="label[]">
</div>
</div>
<div class="col-md-5 valdiv">
<div>
<label>Value</label>
<input type="text" name="value[]">
</div>
</div>
<button class="add_more">Add values</button>
</form>
If someone can help it would be great.
I also would like to know how I can process the data when I submit this into a javascript variable in the from of a array. Like for example if i have 2 inputs for value in the from, I want to store them in a javascript array and then convert it into a JSON.
Form must be in method="POST" and if you get in into php function :
if(!empty($_POST) && isset($_POST){ /*try something with $_POST*/ }
Try this
$(".add_more").click(function() {
var postData = {
field1: $("#id_field1").val(),
field2: $("#id_field2").val()
};
$.ajax({
dataType: "json",
data:JSON.stringify(postData),
url: URL,
method: 'POST'
});
});
A few things that may improve your learning:
jQuery and you code
All jQuery code should be wrapped in this...
$(document).ready(function() {
// jQuery
});
On the var's you have created, you have already initialised them as jQuery elements. Therefore, when you reference them again, you do not need (for example) $(addbutton) as addbutton will do. See amended code below)
<script>
$(document).ready(function(e) {
var labelfiled = '<div><label>Label</label><input type="text" name="label[]"></div>';
var valuefiled = '<div><label>Value</label><input type="text" name="value[]"></div>';
var labdiv = $(".labdiv");
var valdiv = $(".valdiv");
var addbutton = $(".add_more");
addbutton.click(function(){
labdiv.append(labelfiled);
valdiv.append(valuefield);
});
});
</script>
The console
On checking the console...
Say, for example, if you write the JS code console.log(1 + 1) in your page somewhere as you want to see that sum. Due to you writing client side code, when your web page loads (and depending where you have put the console.log()) if you check the developer tools in your chosen browser i.e. Chrome or IE, there is a console section where you can see the result of what you printed (i.e. using that example, it would be 2). This console in the browser will also print out errors that it detects (i.e. $ is not defined - if you are trying to reference jQuery but the library isn't included), it's a good tool for web developers (hence the name ;)) for debugging client side code.
Adding elements to array
Code for getting input values on submit of a form: (jQuery)
var array = [];
$("form").on("submit", function() {
$("input").each(function() {
array.push($(this).val();
});
});
I would suggest that you go and read a book/tutorial on jQuery code as well as the basic concepts of web development :)
Examples:
jQuery
For reference to basics if you get stuck, the link above is more reliable:
- w3schools

Extract all classes from body element of AJAX-ed page and replace current page's body classes

I am in the process of AJAX-ing a WordPress theme with a persistent music player. Wordpress uses dynamic classes on the <body> tag. The basic structure is as follows:
<html>
<head>
</head>
<body class="unique-class-1 unique-class-2 unique-class-3">
<div id="site-container">
<nav class="nav-primary">
Other Page 01
Other Page 02
</nav>
<div class="site-inner">
<p>Site Content Here</p>
</div>
</div>
<div id="music-player"></div>
</body>
</html>
I am currently successfully loading the content of /other-page-01/, /other-page-02/, etc, using load('/other-page-01/ #site-container'). However, I need to extract all <body> classes from the AJAX loaded page and replace the current page's <body> classes with them dynamically.
Note: Replacing the entire <body> element is not an option due to the persistent <div id="music-player">. I've tried jQuery.get(), but couldn't get it to work.
How do I extract the <body> classes from the AJAX requested page and replace the current page's <body> classes with them?
I am not very familiar with jQuery or Javascript, so the exact code would be extremely helpful. Any help is greatly appreciated.
Thanks,
Aaron
My typical solution would have been to tell you to throw the AJAX code in to a jQuery object and then read it out like normal:
$(ajaxResult).attr('class');
Interestingly though, it appears you can't do this with a <body> element.
I'd say the easiest solution (if you have control over the resulting HTML) is to just use some good ol' regex:
var matches = ajaxResult.match(/<body.*class=["']([^"']*)["'].*>/),
classes = matches && matches[1];
I say "if you have control over the resulting HTML", because this relies on the HTML being reasonably well formed.
The other method would involve parsing it as a DOMDocument and then extracting what you need, but this would take a lot more and is usually overkill in simple cases like this.
Convert the body within your returned html to a div with a specific ID, then target that id to get the classes of the body (which is now a div.)
modifiedAjaxResult = ajaxResult.replace(/<body/i,'<div id="re_body"')
.replace(/<\/body/i,'</div');
$(modifiedAjaxResult).filter("#re_body").attr("class");
Of course, if the body has an id, this will conflict with it, so an arbitrary data attribute might be less likely to break.
modifiedAjaxResult = ajaxResult.replace(/<body/i,'<div data-re-id="re_body"')
.replace(/<\/body/i,'</div');
$(modifiedAjaxResult).filter("[data-re-id=re_body]").attr("class");
http://jsfiddle.net/N68St/
Of course, to use this method, you'll have to switch to using $.get instead.
$.get("/other-page-01/",function(ajaxResult){
var modifiedAjaxResult = ajaxResult.replace(/<body/i,'<div data-re-id="re_body"')
.replace(/<\/body/i,'</div');
alert($(modifiedAjaxResult).filter("[data-re-id=re_body]").attr("class"));
// the following line replicates what `.load` was doing.
$(someElement).append( $("<div>").html(ajaxResult).find("#site-container") );
});

bookmarklet: cannot find element added to the document

I am playing with bookmarklets. I add a frame to the document, and load some elements, like so:
var myframe=document.createElement("iframe");
myframe.setAttribute('id','a_frame');
myframe.src='http://localhost:81/nframe.html';
document.body.insertBefore(myframe,document.body.firstChild);
this is what nframe.html looks like:
<form id="sr_cart" name="sr_cart" action="localhost:81/dosomething.php">
Item Number: <input type="text" name="ItemNum" id="sr_item" value="" />
<input type="submit" value="Submit" />
</form>
Looks great so far: when I click on my bookmarklet, the document has been modified correctly
Then I try to look up the item number (or the form)
cart = document.getElementById('sr_cart');
I'm perplexed as to why this comes back a null. (looking up sr_item does the same thing. looking up something that is not in my frame works fine)
TIA
You're searching the wrong document. Start from the iframe's document, like so:
var docEl = myframe.contentDocument || myframe.contentWindow.document || myframe.document;
if (docEl) {
var cart = docEl.getElementById('sr_cart'); // this is what you need
}
I'm pretty sure this is what you need to do - I've done it before but I found verification in Closure Tools' code (Google's JS Library) - http://code.google.com/p/doctype/wiki/ArticleFrameContentDocument

Categories