Creating SharePoint Site with JavaScript - javascript

I am attempting to use JSOM to create a sub-site (web) on button-click. The function is working - in so far as a site is created with the given configuration. However, despite the fact that a site is indeed being create, the ExecuteQueryAsync call always routes to the failure function. The relevant code is below:
var ctx = SP.ClientContext.get_current();
var web = ctx.get_web();
var webCreationInfo = new SP.WebCreationInformation();
webCreationInfo.set_title(portalName); //note: this variable is defined elsewhere
webCreationInfo.set_description('');
webCreationInfo.set_language(1033);
webCreationInfo.set_url(webUrl); //note: this variable is defined elsewhere
webCreationInfo.set_useSamePermissionsAsParentSite(false);
webCreationInfo.set_webTemplate(templateGuid); //note: this variable is defined elsewhere
web.get_webs().add(webCreationInfo);
web.update();
ctx.load(web);
ctx.executeQueryAsync(
function() {
alert("Created Site");
},
function(sender, args) {
alert('Request failed. ' + args.get_message() + '\n' + args.get_stackTrace());
}
);
This includes a couple variables that are defined elsewhere in my code, but this should not be a part of my problem. The site is properly created, using the correct template, name, and URL.
The 'Request failed' alert is always what pops up for me, despite the site being created correctly. The value of args.get_message() is "Unexpected response from server" and the value of args.get_stackTrace() is 'null'.

The issue here was actually due to the button and not the above code. I needed to add 'event.preventDefault();' to the start of my onClick function. Otherwise, the page attempts to refresh - which happens much faster than the site can be provisioned.

Related

Missing data in PhantomJS screenshots

Im working in a script that get an screenshot of a website every day. I already did it for other sites and it worked correctly but for the first time i have the next problem... my phantomjs script capture almost all the data in the website, but not all (in fact it doesn't print the most important for my case).
Until now i was using this simple script adapted:
var page = require('webpage').create();
page.open('http://www.website.com', function() {
setTimeout(function() {
page.render('render.png');
phantom.exit();
}, 200);
});
But when i run the same script for this site its losing some data. Take the screenshot but miss the prices...
Screenshot of the site with phantomjs
After exploring a bit i saw that if i make a DOM capture (for example using a PHP Simple HTML DOM parser) i can get most of the data but not the prices.
$html = file_get_html('https://www.falabella.com.ar/falabella-ar/category/cat10178/TV-LED-y-Smart-TV');
$prods = $html->find('div[class=fb-pod-group__item]');
foreach ($prods as $prod) {
// For example i can get the title
$title = $prod->find('h4[class=fb-responsive-hdng-5 fb-pod__product-title]',0)->plaintext;
// But not the price
$price = $prod->find('h4[class=fb-price]',0)->plaintext;
}
Exploring the console log i found the javascript objects where these values are. If i return the object fbra_browseProductListConfig.state.searchItemList.resultList[0].prices[0].originalPrice;
i see the price of the first product and so on and so on...:
Console log of the site
also i can get it with a phantomjs script like this:
var page = require("webpage").create();
page.open("https://www.falabella.com.ar/falabella-ar/category/cat10122/Cafeteras-express", function(status) {
var price = page.evaluate(function() {
return fbra_browseProductListConfig.state.searchItemList.resultList[0].prices[0].originalPrice;
});
console.log("The price is " + price);
phantom.exit();
});
In other posts (like this) i read about changing the timeout intervals but its not working for me (i tried all the scripts shared in the quoted post). The problem is not that the website doesn't fully charge. But it seems that this data (the prices) is not printed in the DOM. I even downloaded the full site from the terminal with wget command and the prices are not there o_O.
Edited
When i execute the script i get the next errors:
./phantomjs fala.js
ReferenceError: Can't find variable: Set
https://www.falabella.com.ar/static/assets/scripts/react/vendor.js?vid=111111111:22
https://www.falabella.com.ar/static/assets/scripts/react/vendor.js?vid=111111111:1 in t
https://www.falabella.com.ar/static/assets/scripts/react/vendor.js?vid=111111111:22
https://www.falabella.com.ar/static/assets/scripts/react/vendor.js?vid=111111111:1 in t
https://www.falabella.com.ar/static/assets/scripts/react/vendor.js?vid=111111111:22
https://www.falabella.com.ar/static/assets/scripts/react/vendor.js?vid=111111111:1 in t
https://www.falabella.com.ar/static/assets/scripts/react/vendor.js?vid=111111111:1
TypeError: undefined is not an object (evaluating 't.componentDomId')
https://www.falabella.com.ar/static/assets/scripts/react/productListApp.js?vid=111111111:3
https://www.falabella.com.ar/static/assets/scripts/react/vendor.js?vid=111111111:22
Maybe the problem is there because the script "productListApp.js" executes the prices?

Weird (caching) issue with Express/Node

I've built an angular/express/node app that runs in google cloud which currently uses a JSON file that serves as a data source for my application. For some reason, (and this only happens in the cloud) when saving data through an ajax call and writing it to the json file, everything seems to work fine. However, when refreshing the page, the server (sometimes!) sends me the version before the edit. I can't tell whether this is an Express-related, Node-related or even Angular-related problem, but what I know for sure is that I'm checking the JSON that comes in the response from the server, and it really is sometimes the modified version, sometimes not, so it most probably isn't angular cache-related.
The GET:
router.get('/concerts', function (request, response) {
delete require.cache[require.resolve('../database/data.json')];
var db = require('../database/data.json');
response.send(db.concerts);
});
The POST:
router.post('/concerts/save', function (request, response) {
delete require.cache[require.resolve('../database/data.json')];
var db = require('../database/data.json');
var concert = request.body;
console.log('Received concert id ' + concert.id + ' for saving.');
if (concert.id != 0) {
var indexOfItemToSave = db.concerts.map(function (e) {
return e.id;
}).indexOf(concert.id);
if (indexOfItemToSave == -1) {
console.log('Couldn\'t find concert with id ' + concert.id + 'in database!');
response.sendStatus(404);
return;
}
db.concerts[indexOfItemToSave] = concert;
}
else if (concert.id == 0) {
concert.id = db.concerts[db.concerts.length - 1].id + 1;
console.log('Concert id was 0, adding it with id ' + concert.id + '.');
db.concerts.push(concert);
}
console.log("Added stuff to temporary db");
var error = commit(db);
if (error)
response.send(error);
else
response.status(200).send(concert.id + '');
});
This probably doesn't say much, so if someone is interested in helping, you can see the issue live here. If you click on modify for the first concert and change the programme to something like asd and then save, everything looks fine. But if you try to refresh the page a few times (usually even up to 6-7 tries are needed) the old, unchanged programme is shown. Any clue or advice greatly appreciated, thanks.
To solve: Do not use local files to store data in cloud! This is what databases are for!
What was actually the problem?
The problem was caused by the fact that the App Engine had 2 VM instances running for my application. This caused the POST request to be sent to one instance, it did its job, saved the data by modifying its local JSON file, and returned a 200. However, after a few refreshes, the load balancing causes the GET to arrive at the other machine, which has its individual source code, including the initial, unmodified JSON. I am now using a MongoDB instance, and everything seems to be solved. Hopefully this discourages people who attempt to do the same thing I did.

Issue with variable that persists across multiple HTML files with one JS file

This has been giving me a lot of trouble and so far every stackoverflow question/answer I've found and every other bit of googling hasn't helped me all that much.
I have two HTML files. One is called cs, and the other is called csi. They both are linked to a common js file where I'm trying to implement the variable that will persist across both of them.
The variable is defined in the cs html by user input, and is then brought up in csi.
Here's what the Javascript looks like. I have it to run onlyCS on the cs html on body load, and onlyCSI on the csi html on body load.
The colors persist, and the variable MyApp.str is established in cs, but when it loads to csi, MyApp.str becomes "undefined"
I figured I would've avoided this because I established MyApp.str = strChar, which is itself established as a bit of user input that's only available in cs.
var MyApp = {}; // Globally scoped object
function onlyCS(){
MyApp.color = 'green';
setInterval(strdefine, 3000)
}
function onlyCSI(){
MyApp.color = 'red';
setInterval(bar, 3000)
}
function strdefine(){
alert(MyApp.color); // Alerts 'green'
strChar = parseInt($('#Xdemo').text(), 10);
$('#result').text(strChar);
MyApp.str = strChar;
alert('the myapp global obj (str) is currently ' + MyApp.str);
}
function bar(){
alert(MyApp.color); // Should alert 'red'
alert('the myapp global obj (str) is currently ' + MyApp.str);
}
If anyone could help me out, I'd really appreciate it.
EDIT: The comments help me figure out that using localstorage and variables is a good solution for my problem.
within strdefine I put
strChar = parseInt($('#Xdemo').text(), 10);
localStorage.setItem('str', strChar);
and within bar I put
alert('LS "str" is currently ' + localStorage.str);
var ex = localStorage.getItem('str') || 0;
$('#result').text(ex);
You have choices of:
Persist/read in a cookie
Persist/read in local storage
Persist/read in session storage
send to server then get it back from the server (likely in some session variable)
Just putting a variable in a JavaScript object does NOT persist past a page refresh. You also can use AJAX to read some HTML portion then apply that to your page in some container (not a full page, just some partial like a <div>my new</div> etc. Stored in some server side file

Run Javascript custom function in PhantomJS

I am writing a console application in which I am using Nreco.PhantomJS to load the data. This is a scrapping application for a website containing google map with markers on it. The data I am trying to get is not available on the page before or after it is loaded completely. The data is the simple Latitude and Longitude that is passed from a JavaScript function to the google map and is not rendered on the page. As I am very new to PhantomJS so I am not sure how to achieve this but I am sure this can be done. This small piece of script is run by me in c# code,
try
{
string jsContent = "var system = require('system');" +
"var page = require('webpage').create();" +
"page.open('" + url + "', function(status) {" +
"system.stdout.writeLine(GetLatLang());" +
"}"+
"phantom.exit();" +
"});";
phantomJS.RunScript(jsContent, null, null, ms);
}
finally
{
phantomJS.Abort(); // ensure that phantomjs.exe is stopped
}
When I call Alert(GetLatLang()) function in console tab (Inside google chrome inspector) then it run fines and value is retrieved. However the PhantomJS never finishes running the code and I have to close the application. My understanding is that in the above code PhantomJS immediately try to execute the GetLatLang() function whereas it is not available at that time. Is there any way to execute this function after the page is completely loaded?
You need to call the GetLatLang() function in the page context and not in the phantom context:
"page.open('" + url + "', function(status) {" +
"console.log(page.evaluate(function(){" +
"return GetLatLang();" +
"}));" +
"}"+
page.evaluate() is the only function that provides access to the DOM and the page's window object.
Additionally, your JavaScript has a syntax error. There is only one opening {, but two closing }. You need to remove "}"+.

When does ondevice ready happen, and how can I apply variables I get from it?

In my Phonegap Android app, I have the following Javascript code:
function onDeviceready()
{
window.plugins.webintent.getUri(function(url)
{
alert("WebIntent Fired Up! URL is " + url);
if (url.substring(0, 37) === "https://xxxxxxx.com/confirmation.html")
{
alert("intent matched!");
var params = url.substr(url.indexOf("?") + 1);
params = params.split("&");
var verificationData = params[0].split("=");
var emailData = params[1].split("=");
launchLinkEmail = emailData[1];
launchLinkVerification = verificationData[1];
alert("verification is " + launchLinkVerification);
alert("email is " + launchLinkEmail);
}
});
}
$(document).ready(function() {
document.addEventListener('deviceready', onDeviceready, true);
});
The problem is that the variables launchLinkVerification and launchLinkEmail seem to get set after the page is loaded and the Javascript is finishing up, and so their value is empty when I try to call it anywhere that I want to use them. The alerts always display the information I want, but if I try to display them anywhere in my HTML pages, or set conditionals based on their value, neither work.
On the other hand, it seems that if I use window.plugins.webintent.getUri(function(url) anywhere other than onDeviceready it sometimes doesn't execute at all (or at least not under conditions that I can predict or understand), and again the variables don't get set.
Ultmately, what I want to do is:
Get the data from the URL that WebIntent captures.
If the data from WebIntent matches certain criteria, then switch to another page using window.location = confirmation.html
Fill two fields on the form on confirmation.html with the two variables I got from the URL that WebIntent picked up.
How do I get the data from the Webintent call, switch pages depending on what that data is, and then use that data on the new page?
I haven't used the WebIntent plugin specifically, but if I understand your description correctly, I think you're running into a problem where you're running some JavaScript in the head or maybe in the body to configure the page the way you want it. But that code is dependent upon what happens in your onDeviceready(). The call to onDeviceready() is going to be made asynchronously at anytime PhoneGap feels it is ready. Usually it is called quickly, but quickly is a relative term.
What you likely need is someway for this async code to then trigger the code you want. JQuery provides the $.Deferred() object which you might find helpful. You can setup a Deferred, you add your other code in with Deferred.done(), and when it runs onDeviceready() resolves the object which then runs the callbacks.
http://api.jquery.com/jQuery.Deferred/
I've used this to allow something like onDeviceready() to trigger a series of other behaviors in my application which I may not have wanted to structure into one big function.

Categories

Resources