Error with custom Search and Replace function for Google Sites - google-apps-script

I'm trying to use a script to replace a particular string with a different string. I think the code is right, but I keep getting the error "Object does not allow properties to be added or changed."
Does anyone know what could be going wrong?
function searchAndReplace() {
var teams = SitesApp.getPageByUrl("https://sites.google.com/a/directory/teams");
var list = teams.getChildren();
list.forEach(function(element){
page = element.getChildren();
});
page.forEach(function(element) {
var html = element.getHtmlContent();
html.replace(/foo/, 'bar');
element.setHtmlContent = html;
});
};

Try This:
Javascript reference:
The replace() method returns a new string with some or all matches of a pattern replaced by a replacement.
I think the issue here is that forEach cannot change the array that it is called upon. From developer.mozilla.org "forEach() does not mutate the array on which it is called (although callback, if invoked, may do so)."
Try doing it with a regular loop.

Related

How to make new document with JXA?

How to make new document and close? Need this to workaround apple automation buggy insanity. What I try is this:
var app = Application('Keynote')
var doc = app.make(new document) // How to write this correctly?
doc.close({saving: 'no'})
AppleScript and JavaScript syntax is completely different. You have to think more in terms of JavaScript
For example JXA doesn't understand make(new).
You have to create an instance from the class name (note the uppercase spelling) and then call make().
Actually the var keywords and the trailing semicolons are not needed.
keynote = Application('Keynote')
keynote.activate()
newDocument = keynote.Document().make()
Within the parentheses of Document() you can pass parameters similar to AppleScript’s with properties for example
newDocument = keynote.Document({
documentTheme: keynote.themes["Gradient"],
width:1920,
height:1080
})
AppleScript’s multiple word properties like document theme are written as one camelCased word.
To close the frontmost document write
keynote.documents[0].close()

Special JSON binding in WinJS ListView

I have problems binding this JSON to my list view.
http://pubapi.cryptsy.com/api.php?method=marketdatav2
No data is displayed.
Data.js
(function () {
"use strict";
var _list;
WinJS.xhr({ url: 'http://pubapi.cryptsy.com/api.php?method=marketdatav2' }).then(
function (response) {
var json = JSON.parse(response.responseText);
_list = new WinJS.Binding.List(json.return.markets);
},
function (error) {
//handle error
}
);
var publicMembers =
{
itemList: _list
};
WinJS.Namespace.define("DataExample", publicMembers);
})();
HTML:
<section aria-label="Main content" role="main">
<div id="listItemTemplate" data-win-control="WinJS.Binding.Template">
<div class="listItem">
<div class="listItemTemplate-Detail">
<h4 data-win-bind="innerText: label"></h4>
</div>
</div>
</div>
<div id="listView" data-win-control="WinJS.UI.ListView" data-win-options="{itemDataSource : DataExample.itemList, itemTemplate: select('#listItemTemplate'), layout: {type: WinJS.UI.GridLayout}}"></div>
</section>
I feel that the API is not that well formed.
Isnt this part a bit odd?
"markets":{"ADT/XPM":{...}...}
There are three things going on in your code here.
First, a ListView must be bound to a WinJS.Binding.List's dataSource property, not the List directly. So in your HTML you can use itemDataSource: DataExample.itemList.dataSource, or you can make your DataExample.itemList dereference the dataSource at that level.
Second, you're also running into the issue that the declarative binding of itemDataSource in data-win-options is happening well before DataExample.itemList is even populated. At the point that the ListView gets instantiated, _list and therefore itemList will be undefined. This causes a problem with trying to dereference .dataSource.
The way around this is to make sure that DataExample.itemList is initialized with at least an empty instance of WinJS.Binding.List on startup. So putting this and the first bit together, we have this:
var _list = new WinJS.Binding.List();
var publicMembers =
{
itemList: _list.dataSource
};
With this, you can later replace _list with a different List instance, and the ListView will refresh itself.
This brings us to the third issue, populating the List with your HTTP response data. The WinJS.Binding.List takes an array in its constructor, not an object. You're passing the parsed JSON object straight from the HTTP request, which won't work.
Now if you have a WinJS.Binding.List instance already in _list as before, then you can just walk the object and add items directly to the List as follows:
var jm = json.return.markets;
for (var i in jm) {
_list.push(jm[i]);
}
Alternately, you could populate a separate array and then create a new List from that. In this case, however, you'll need to assign that new List.dataSource to the ListView in code:
var jm = json.return.markets;
var markets = [];
for (var i in jm) {
markets.push(jm[i]);
}
_list = new WinJS.Binding.List(markets);
var listview = document.getElementById("listView").winControl;
listview.itemDataSource = _list.dataSource;
Both ways will work (I tested them). Although the first solution is simpler and shorter, you'll need to make sure to clear out the List if you make another HTTP request and repopulate from that. With the second solution you just create a new List with each request and hand that to the ListView, which might work better depending on your particular needs.
Note also that in the second solution you can remove the itemDataSource option from the HTML altogether, and also eliminate the DataExample namespace and its variables because you'll assign the data source in code each time. Then you can also keep _list entirely local to the HTTP request.
Hope that helps. If you want to know more about ListView intricacies, see Chapter 7 of my free ebook from MSPress, Programming Windows Store Apps with HTML, CSS, and JavaScript, Second Edition.

GoogleAppsScript: How do I trim strings after parsing HTML?

What I'm trying to do is parse & extract the movies title, without all the HTML gunk, from the webpage which will eventually get saved into a spreadsheet. My code:
function myFunction() {
var url = UrlFetchApp.fetch("http://boxofficemojo.com/movies/?id=clashofthetitans2.htm")
var doc = url.getContentText()
var patt1 = doc.match(/<font face\=\"Verdana\"\ssize\=\"6\"><b>.*?<\/b>/i);
//var cleaned = patt1.replace(/^<font face\=\"Verdana\" size\=\"6\"><b>/,"");
//Logger.log(cleaned); Didn't work, get "cannot find function in object" error.
//so tried making a function below:
String.trim = function() {
return this.replace(/^\W<font face\=\"Verdana\"\ssize\=\"6\"><b>/,""); }
Logger.log(patt1.trim());
}
I'm very new to all of this (programming and GoogleScripting in general) I've been referencing w3school.com's JavaScript section but many things on there just don't work with Google Scripts. I'm just not sure what's missing here, is my RegEx wrong? Is there a better/faster way to extract this data instead of RegEx? Any help would be great, Thanks for reading!
While trying to parse information out of HTML that's not under your control is always a bit of a challenge, there is a way you could make this easier on yourself.
I noticed that the title element of each movie page also contains the movie title, like this:
<title>Wrath of the Titans (2012) - Box Office Mojo</title>
You might have more success parsing the title out of this, as it is probably more stable.
var url = UrlFetchApp.fetch("http://boxofficemojo.com/movies/?id=clashofthetitans2.htm");
var doc = url.getContentText();
var match = content.match(/<title>(.+) \([0-9]{4}\) -/);
Logger.log("Movie title is " + match[1]);

JSON results into a variable and store in hidden input field

I wrote code below that is working perfectly for displaying the results of my sales tax calculation into a span tag. But, I am not understanding how to change the "total" value into a variable that I can work with.
<script type="text/javascript">
function doStateTax(){
var grandtotalX = $('#GRANDtotalprice').val();
var statetaxX = $('#ddl').val();
$.post('statetax.php',
{statetaxX:statetaxX, grandtotalX:grandtotalX},
function(data) {
data = $.parseJSON(data);
$('.products-placeholder').html(data.products);
$('.statetax-placeholder').html(data.statetax);
$('.total-placeholder').html(data.total);
// ...
});
return false;
};
</script>
Currently, $('.total-placeholder').html(data.total); is successfully placing the total number into here:
<span class="total-placeholder"></span>
but how would I make the (data.total) part become a variable? With help figuring this out, I can pass that variable into a hidden input field as a "value" and successfully give a proper total to Authorize.net
I tried this and id didn't work (see the testtotal part to see what I'm trying to accomplish)..
function(data) {
data = $.parseJSON(data);
$('.products-placeholder').html(data.products);
$('.statetax-placeholder').html(data.statetax);
$('.total-placeholder').html(data.total);
$testtotal = (data.total);
// ...
If you are using a hidden field inside a form, you could do:
//inside $.post -> success handler.
$('.total-placeholder').html(data.total);
$('input[name=yourHiddenFieldName]', yourForm).val(data.total);
This will now be submitted along with the usual submit. Or if you want to access the data elsewhere:
var dataValue = $('input[name=yourHiddenFieldName]', yourForm).val();
The "data" object you are calling can be used anywhere within the scope after you have a success call. Like this:
$.post('statetax.php',
{statetaxX:statetaxX, grandtotalX:grandtotalX},
function(data) {
data = $.parseJSON(data);
var total = data.total;
var tax = data.total * 0.19;
});
return false;
};
Whenever you get an object back always try to see with an alert() or console.log() what it is.
alert(data); // This would return <object> or <undefined> or <a_value> etc.
After that try to delve deeper (when not "undefined").
alert(data.total); // <a_value>?
If you want 'testotal' to be recognized outside the function scope, you need to define it outside the function, and then you can use it somewhere else:
var $testtotal;
function(data) {
data = $.parseJSON(data);
$('.products-placeholder').html(data.products);
$('.statetax-placeholder').html(data.statetax);
$('.total-placeholder').html(data.total);
$testtotal = (data.total);
EDIT:
The comments are becoming too long so i'll try and explain here:
variables defined in javascript cannot be accessed by PHP and vice versa, the only way PHP would know about your javascript variable is if you pass it that variable in an HTTP request (regular or ajax).
So if you want to pass the $testtotal variable to php you need to make an ajax request(or plain old HTTP request) and send the variable to the php script and then use $_GET/$_POST to retrieve it.
Hope that answers your question, if not then please edit your question so it'll be clearer.

Extract the contents of a div using Flash AS3

I have a SFW embedded in a PHP page. There is also a div on the page with id="target".
I want to access the content of that div (ie: the characters inside it) and hold them as a String variable in AS3. How can I do this?
My attempt so far
import flash.external.ExternalInterface;
var myDivContent = ExternalInterface.call("function(){ return document.GetElementById('target');}");
var myDivContent2:String = myDivContent.toString();
test_vars.text = myDivContent2; //Dynamic text output
I don't think you can define a function in the ExternalInterface.call() method. You have to call a function by name which already exists in the JavaScript.
So I'd create some JavaScript code like this:
function getTargetContent()
{
return document.getElementById('target').innerHTML;
}
And then in your Flash,
var myDivContent = ExternalInterface.call("getTargetContent");
Note that document.getElementById('target') only returns the reference to that div, not the contents within. So if you don't return .innerHTML then the Flash will get an object which may not be usable (although I haven't actually tried doing this).
The easiest way to do this is as Allan describes, write a Javascript function to sit on the page and return the required value to you.
Of course, if you can't edit the page content, only the flash, then you do need to pass the function itself, which will actually have to be forced into the page though JavaScript injection. An example for your case, which I have not tested:
//prepare the JavaSctipt as an XML object for Dom insertion
var injectCode:XML =
<script>
<![CDATA[
function() {
getElementContent = function(elementID) {
return document.getElementById(elementID).innerHTML;
}
}
]]>
</script>;
//inject code
ExternalInterface.call(injectCode);
//get contents of 'divA'
var divAContent:String = ExternalInterface.call('getElementContent','divA') as String;
//get contents of 'spanB'
var spanBContent:String = ExternalInterface.call('getElementContent','spanB') as String;
You're almost there :
var res : String = ExternalInterface.call("function(){return document.getElementById('target').outerHTML}");
If you only want the content of your target, use innerHTML instead of outerHTML.