Ajax for "load on scroll" script delivers 403 - javascript

I'm building a blog on the hubspot cos. We want the blog posts to load on scroll. I found a script that states that it does this and is specifically for Hubspot.
That being said, I'm getting a 403 in the console when I activate the script by scrolling. I don't think this is a hubspot issue as much as an Ajax issue.
The script I am using:
www.uvm .edu/~enewbury/swoosh/
The script on our hubspot cdn:
http://cdn2.hubspot.net/hub/1739321/hub_generated/template_assets/1452520555218/custom/page/JS/Swoosh.min.js
The blog:
http://insights.signetaccel.com/blog
The only thing that sticks out to me is that the ajax request is cross domain, but this is a normal thing in hubspot between files and the company domain so if this script was built for use in hubspot I would think the owner would have accounted for this.
I've looked all of for an answer, and I've come up empty handed. It should be noted that a php proxy wouldn't work as server side programming is not an option with hubspot.
I would really appreciate some an answer or some tips on what to do here.
$(document).ready(function(){
$(".grid").swoosh();
});
(function(a) {
a.fn.swoosh = function(f, k) {
if (!f) {
f = "Loading..."
}
if (k == null) {
k = -1
}
var c = this;
var e = false;
var j = 2;
var d = window.location.href.toString().split("/");
var i = d[0] + "//" + d[2] + "/" + d[3] + "/";
var h = i + "page/";
var g = "";
var b = false;
if (f != "Loading...") {
c.parent().append('<div class="loading"><img src="' + f + '"></div>')
} else {
c.parent().append('<div class="loading">' + f + "</div>")
}
a(".loading").hide();
a(document).scroll(function() {
if (b || e || j == 0) {
return false
}
if (a(window).scrollTop() >= a(document).height() - a(window).height() - a(".footer-container-wrapper").height() - 150) {
b = true;
a(".loading").fadeIn(200);
g = h + j;
a.post(g, function(m) {
var l = a(m).find(".grid-item");
if (l.length) {
console.log(f);
a(".loading").fadeOut(200, function() {
l.appendTo(".grid")
});
j++;
a(".next-posts-link").attr("href", h + j)
} else {
e = true;
a(".next-posts-link").after('<div class="next-posts-link unactive">Next</div>');
a(".next-posts-link:not(.unactive)").remove();
a(".loading").fadeOut(200)
}
b = false;
setTimeout(function() {
twttr.widgets.load();
IN.parse();
FB.XFBML.parse();
gapi.plusone.go()
}, 350)
})
}
})
}
})(jQuery);
(function() {
return window.SIG_EXT = {};
})()

TL;DR -- You're getting a 403 because the script is using jQuery's .post instead of .get; an http POST to a HubSpot COS/blog page is not allowed. This appears in line 45 of the raw js example here: http://www.uvm.edu/~enewbury/swoosh/swoosh.js
Switch out the HTTP method for a GET, then continue debugging. The script is unofficial and, though intended to be generic, relies on specific body structure generated by HubSpot's COS/blog and classing of elements. More debugging may be required to get it working.
Details:
The way this script works is a bit kludgey. Its not fetching blog content from an API or other efficient resource -- instead, it grabs the full HTML of /page/2, /page/3, etc as you scroll, parsing out the blog post HTML from the response it retrieves, and injecting the posts it finds in the async fetch into the current page.
Using a POST rather than a GET to fetch this content is generating a 403 Forbidden.
There may be more issues as the script depends very much on certain elements being classed a specific way, but this fixes your immediate 403 issue.

Related

extra texts in javascript mime-type (Other than several recognized js mime types)

While inspecting the source code of this website: http://www.flipkart.com/ , I found this line <script type="text/javascript+fk-onload"> . I know there are many different mime types for javascript but this one has some added texts that goes over my mind. Could anyone explain the purpose of this extra text and when can it be used?
The +-suffix defines a subtype. They are using it to execute that particular script onload:
FKART.utils.runOnload = function(a) {
FKART.utils.runSnippet("fk-onload", a)
};
FKART.utils.runSnippet = function(a, c) {
c = c || "script[type='text/javascript+" + a + "']";
$(c).each(function() {
var d = $(this);
if (d.attr("data-src")) {
$script(d.attr("data-src"), b.curry(this))
}
else {
b(this)
}
});
function b(d) {
FKART.utils.evalScript(d.text || d.textContent || d.innerHTML);
d.type = d.type + "-executed"
}
};

How to work with the results of api.php using javascript?

I have searched around and can't seem to find what I'm looking for.
How can I use the results of api.php?action=query&list=allusers&augroup=sysop&aulimit=max&format=json in a javascript?
What I'm trying to do is create a script to simply change the color of usernames on the wiki if they are in certain groups, like sysop, bureaucrat, etc.
Although I'm usually pretty good at figuring these things out, I've been working on this all day and I've gotten nowhere with it. Can anyone help me out with maybe some examples or something? If it can be done with mostly jQuery that would be preferable.
Thanks in advance.
Edit: (in response to comment by ahren):
Well I started out trying to clean up and modify a script written by someone else to add more functionality/make it work as expected, but I had trouble making sense out of it:
/* HighlightUsers by Bobogoobo
* Changes color of links to specified groups and users
* TODO: redo but much better (recursive would be easier - I've learned a lot since I wrote this thing)
*/
function highlightUsers () {
"use strict";
var highlight = window.highlight || {}, selector = '', that, userstr,
indices = [],
i = 0,
user,
ns,
x,
y;
for (ns in mw.config.get('wgNamespaceIds')) {
if (i === 4) {
userstr = ns;
}
i++;
}
userstr = userstr.charAt(0).toUpperCase() + userstr.substring(1);
if (highlight['selectAll']) {
selector = 'a[href$=":';
} else {
selector = 'a[href="/wiki/' + userstr + ':';
}
for (y in highlight) {
indices.push(y);
}
for (x in highlight) {
that = highlight[x];
if (x === 'selectAll') {
continue;
} else if (x === 'users') {
for (user in that) {
$(selector + user.replace(/ /g, '_') + '"]').css({
'color': that[user],
'font-weight': 'bold'
}).attr('data-highlight-index',
$.inArray('users', indices));
}
} else {
(function (userColor, userGroup) { //JavaScript doesn't like to cooperate with me
$.getJSON('/api.php?action=query&list=allusers&augroup=' + userGroup +
'&aulimit=max&format=json', function (data) {
var stuff = data.query.allusers, //, select = '';
user;
for (user in stuff) {
//select += selector + stuff[user].name.replace(/ /g, '_') + '"], ';
$(selector + stuff[user].name.replace(/ /g, '_') + '"]').each(function () {
if (($(this).attr('data-highlight-index') || -1) < $.inArray(userGroup, indices)) {
$(this).attr('data-highlight-index', $.inArray(userGroup, indices));
$(this).css({
'color': userColor,
'font-weight': 'bold'
});
}
});
}
//select = select.substring(0, select.length - 2);
//$(select).css('color', userColor);
});
}(that, x));
}
}
}
That is my latest draft of it, I managed to accomplish a few things, like making the names bold, and correcting syntax mishaps, but I've decided I may be better off starting from scratch than trying to understand someone else's code.
i would prefer using jQuery AJAX functionality.
Usage is simple :
$.ajax({
url : 'api.php',
type : 'post',
datatype : 'json',
data : {
'list' : allusers,
'augroup' : 'sysop'
},
success : function(success_record) {
//here you can do Js dom related modifications like changing color etc.
// after php(server side) completes
}
});
I tried the AJAX solution described by Markrand, but unfortunately I wasn't able to get it to work. First off I was getting "allusers is not defined", so I wrapped it in quotes so that it wasn't treated as a var, then I had to add change 'api.php' to '/api.php' because it was becoming '/wiki/api.php' which doesn't exist, and adding the slash got it to use the base URL. It would then execute and return an object, however there was nothing useful in that object that I could use (such as an array of usernames), all it gave me was the API documentation... So I ended up doing this instead:
function highlightAdmins() {
$.getJSON('/api.php?action=query&list=allusers&augroup=sysop&aulimit=max&format=json',
function(data) {
for (var i = 0; i < data.query.allusers.length; i++) {
$('a[href$="User:' + data.query.allusers[i].name + '"]').css('color', '#FF6347');
}
});
}
This gave me an object containing the results of the query, in this case an array of sysop usernames (data.query.allusers[i].name) which I could iterate though and perform actions with.

Async calls to service in javascript

In my project I am calling same service for more than 2-3 times for finding distance & time for my route in javascript using cloudmode service.
I am having one polyline, I am getting each point of polyline & passing two consecutive points to service to get response from it.
What I am doing is
function showPointsRoutes(e)
{
var a = e.target.getLatLngs();
for(var i = 1 ; i < a.length ; i++)
{
var as ="http://routes.cloudmade.com/BC9A493B41014CAABB98F0471D759707/api/0.3/" + a[i-1].lat+","+a[i-1].lng+","+a[i].lat+","+a[i].lng + "/car/shortest.js?callback=getRouteResponse";
addScript(as);
}
}
function getRouteResponse(response)
{
mytimeArray.push[response.route_summary.total_time];
myDistancArray.push[response.route_summary.total_distance];
}
function addScript(url)
{
var script = document.createElement('script');
script.type="text/javascript";
script.src=url;
document.getElementsByTagName('head') [0].appendChild(script);
}
But sometimes what happens is that response for some requests comes late.
due to this I am not getting proper times & distance between points.
Can any one suggest some way so that I get values in array as sequence in which request was made.
The reason they give you different callback names is so that you can differentiate requests by using a different callback for each one. Try something like this:
Note: #Rodrigo Assis's suggestion would be better in this case since the API supports this. Code below demonstrates a way to handle this when the API forces using multiple requests.
function showPointsRoutes(e)
{
var a = e.target.getLatLngs();
for(var i = 1 ; i < a.length ; i++)
requestRoute(i, a[i-1], a[i]);
}
function requestRoute(i, a, b)
{
window["getRouteResponse" + i] = function(response)
{
mytimeArray[i] = response.route_summary.total_time;
myDistancArray[i] = response.route_summary.total_distance;
};
var as ="http://routes.cloudmade.com/BC9A493B41014CAABB98F0471D759707/api/0.3/" + a.lat+","+a.lng+","+b.lat+","+b.lng + "/car/shortest.js?callback=getRouteResponse" + i;
addScript(as);
}
function addScript(url)
{
var script = document.createElement('script');
script.type="text/javascript";
script.src=url;
document.getElementsByTagName('head') [0].appendChild(script);
}

SDK GridRefresh Call Throwing Exception

I'm going to try to explain this as best I can, please feel free to ask for clarifications as required.
Using IE10, CRM Online with RU12.
I am playing about with subgrids and getting them to refresh. Consider the following script, which I have nicked wholesale from MSDN (and wrapped in a try/catch block)
function start() {
try {
var controls = Xrm.Page.ui.controls.get(isSubGrid);
if (controls.length > 0) {
var subGridNames = "";
for (var i in controls) {
controls[i].refresh();
subGridNames += (" - " + controls[i].getName() + "\n");
}
alert("The following subgrids were refreshed: \n" + subGridNames);
}
else {
alert("There are no subgrid controls on the current form.");
}
}
catch (ex) {
alert(ex);
}
}
function isSubGrid (control)
{
return control.getControlType() == "subgrid";
}
Nothing special going on there - get all controls of type subgrid (this returns 10 elements as expected) and call refresh() on them.
However this is consistently failing on the first call to refresh().
The exception details is fairly straightforward
TypeError: Unable to get property 'Refresh' of undefined or null reference
Which suggests that the control[i] is null when called in the loop at this point here
for (var i in controls) {
controls[i].refresh();//error thrown here - suggests controls[i] is null
subGridNames += (" - " + controls[i].getName() + "\n");
}
However I can see that it isn't null (and has the method refresh as expected).
I can make it work by using setInterval
function waitAndThenRefresh(gridname) {
var grid = Xrm.Page.ui.controls.get(gridname);
var intervalId = setInterval(function () {
if (grid === null || grid._control === null || grid._control._element === null) {
return;
}
if (grid._control._element.readyState === 'complete') {
window.clearInterval(intervalId);
if (grid != null) {
grid.refresh();
}
}
}, 1000);
}
But that is pretty hideous, not to mention does not explain with the SDK call doesn't work as expected.
So I guess the question is: has anyone else seen this issue? Or can you replicate it on another instance? Am I missing something? There is nothing in the SDK that suggests you need to defer calling refresh until the inner control's readyState is complete?
The code block you are using,
for (var i in controls) {
controls[i].refresh();
subGridNames += (" - " + controls[i].getName() + "\n");
}
should be replaced with the following:
for (var i in controls) {
i.refresh();
subGridNames += (" - " + i.getName() + "\n");
}
or:
for (var i = 0; i < controls.length; i++) {
controls[i].refresh();
subGridNames += (" - " + controls[i].getName() + "\n");
}
You are getting the exception because controls[i] is undefined in your case, i being the control (the element of the array controls).
I asked a CRM-buddy of mine. He said that the issue depends on the new refreshment Engine. According to him, it's sort of a bug but not really. If I got it right, the refresh has been reengineered to accommodate the new perpetual saving functionality.

Using new Image().src for click tracking

I am attempting to figure out why this click tracker isn't working. The code was written by another developer so I am not entirely sure if this ever did work.
function trackSponsor(o, p) {
(new Image()).src = PATH_BASE + 'click/' + p + '/' + o + "?_cache=" + (+(new Date()));
return false;
}
From what I can gather is that when this function is called it 'creates a new image' to fire a php script asynchronously. According to Firebug, the request is made however it is 'aborted' ~30ms in. The odd thing is that it will 'sometimes' work as in 1 in every 10+ regardless of the browser.
I would much rather fix this so that it works instead of re-writing it as an ajax request.
Any help is appreciated.
Thanks in advance.
EDIT
Because of tvanfosson's post that got me thinking. I have included the line which calls the click tracker below.
<a onclick="trackSponsor(60, 15077); goToNextStep(1988, 15077, 0); return false;" href="#">view</a>
the goToNextStep() actually changes the page. I am under the impression that it would only be executed after trackSponsor() had finished.
It's actually pretty trivial to rewrite as a get request using jQuery. Rewriting it will certainly help the next developer understand what's happening and might fix your problem. I'd need to know more about the contents of the variables -- perhaps they need to be urlEncoded? -- before I could help you any more on it. You might try urlEncoding them and see what happens.
function trackSponsor(o, p) {
var url = PATH_BASE + 'click/' + p + '/' + o + "?_cache=" + (+(new Date()));
$.get(url);
return false;
}
EDIT: you might want to check that another handler isn't redirecting the browser to a new location when the event triggering the tracking is invoked. This would abort any pending requests on the page -- and might allow a few to succeed based on the timing of the requests and if the results are delivered before the page is unloaded.
"(new Image()).src = url;" just asks for browser to hit the url.
You should delay for a 50-100ms in order to be sure that tracking info were sent to the server.
function delay(a) {
for (var b = +new Date, c = 1; 0 < c; c++) {
if (0 == c % 1E3) {
var e = +new Date;
if (b > e) break;
if (e - b > a) break;
}
}
}
function trackSponsor(o, p) {
(new Image()).src = PATH_BASE + 'click/' + p + '/' + o + "?_cache=" + (+(new Date()));
delay(100);
return false;
}
I poked around Google Analytics’ ga.js, which does use the new Image() method similar to your script.
The only difference that I could see was in how the object is created. Google's script assigns the object to a variable.
var d=new Image(1,1);d.src=f;
Maybe give that a shot?
function trackSponsor(o, p) {
var i = new Image(1,1);
i.src = PATH_BASE + 'click/' + p + '/' + o + "?_cache=" + (+(new Date()));
return false;
}
It shouldn't make a difference, but is worth a shot.
Maybe try this, for avoiding Garbage Collection to make your log not be lost.
var sendLog = (function () {
var _unique = (function () { /* 产生唯一标识*/
var time = (new Date()).getTime() + '_',
i = 0;
return function () {
return time + (i++);
}
}());
var run = function (url) {
var data = window['imgLogData'] || (window['imgLogData'] = {}),
img = new Image(),
uid = _unique();
data[uid] = img; /* 防止img被垃圾处理*/
img.onload = img.onerror = function () { /* 成功或失败后销毁对象*/
img.onload = img.onerror = null;
img = null;
delete data[uid];
};
img.src = url + '&_cache=' + uid; /* 发送统计内容*/
};
return run;
}());
sendLog('http://log_');

Categories

Resources