I want my context menu item to be visible only if the clicked node is a link i.e. and href is either a magnet link or a torrent link. But item is visible for all the links because context function is not executing, can anybody help why context function is not executing?
Here is the code:
exports.main = function() {
var cm = require("sdk/context-menu");
var contextCode = ' self.on("context", function (node) { '+
' while(node.nodeName!="A") { node = node.parentNode; } '+
' var pat_magnet = /^magnet:/i; ' +
' var pat_torrent = /.torrent$/i; ' +
' if(pat_torrent.test(node.href) || pat_magnet.test(node.href)) { return true; } '+
' else { return false; } '+
' }); ';
var clickCode = ' self.on("click", function(node,data){ '+
' while(node.nodeName!="A") { node = node.parentNode; } '+
' var pat_hash = /[0-9abcdef]{32,40}/i; ' +
' var result = node.href.match(pat_hash); '+
' var hash = "" '
' if(result != null) { hash=result[0]; } '+
' var xhr = new XMLHttpRequest(); '+
' if(hash != "") { '+
' var apiCall = "https://www.furk.net/api/dl/add?api_key=*************&info_hash="+hash; '+
' } '+
' else{ '+
' var apiCall = "https://www.furk.net/api/dl/add?api_key=*************&url="+encodeURI(node.href); '+
' } '+
' xhr.open("GET",apiCall,true); '+
' xhr.onreadystatechange = function(){ if(xhr.readyState = 4) { if (xhr.response.status = "ok") { alert("Torrent added to Furk."); } else { alert("Torrent could not be added to Furk."); } } } '+
' xhr.send(null); '+
' });';
cm.Item({
label: "Add to Furk",
context: cm.SelectorContext("a[href]"),
contentScript: contextCode + clickCode
});
};
Please always post self-containied examples that can be directly tried in the future.
Now back to your problem: The content script actually has a syntax error.
The following line:
' var pat_torrent = /.torrent$/i ' +
lacks a semicolon, and should be:
' var pat_torrent = /.torrent$/i; ' +
The reason automatic semicolon insertion (ASI) does not work here is: The "code" is actually a string that has no newlines in it whatsoever. If there were newlines, then ASI would have worked.
Anway, another reason not to have complex content script inline. Have a look at contentScriptFile.
This error is actually logged, but the presentation sucks. In the Browser Console:
[20:57:51.707] [object Error] (expandable)
In terminal:
console.error: context-magnet:
Message: SyntaxError: missing ; before statement
Here is a fixed, reproducible sample:
var cm = require("sdk/context-menu");
var contextCode = ' self.on("context", function (node) { '+
' while(node.nodeName!="A") { node = node.parentNode; } '+
' var pat_magnet = /^magnet:/i; ' +
' var pat_torrent = /.torrent$/i; ' +
' if(pat_torrent.test(node.href) || pat_magnet.test(node.href)) { return true; } '+
' else { return false; } '+
' }); ';
cm.Item({
label: "magnet test",
context: cm.SelectorContext("a[href]"),
contentScript: contextCode
});
Edit ' var hash = "" ' has the same problem, and there are might be other such errors that I missed skimming this new code.
As I already said, please use contentScriptFile and not contentScript for long-ish scripts.
Another edit
Here is a builder using contentScriptFile, where I also fixed a couple of other errors, the most important of which are:
Use permissions so that the XHR will work.
Correctly set up the XHR to use responseType and overrideMimeType().
Use onload/onerror instead of onreadystatechange.
Related
I have a scenario where I am linking all the URLs in a Text in a Hyperlink. But when a user types www., then the browser takes it as a local URL and binds the link to the applications URL.
I want to know how to open local URL in a new Tab.
var replaceTextWithURL = systemNotificationText.replace(/(https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|www\.[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9]+\.[^\s]{2,}|www\.[a-zA-Z0-9]+\.[^\s]{2,})/gi, function(text, link) {
console.log(text, link);
return ' ' + link + ' ';
//var httpUrl = link.startsWith("http");
//var httpsUrl = link.startsWith("https");
//if (httpUrl || httpsUrl) {
// return ' ' + text + ' ';
//}
//else {
// return ' ' + text + ' ';
//}
});
var newLineText = replaceTextWithURL.replace(/\r?\n/g, '<br />');
$("#systemNotificationPreview").html(newLineText);
can you refine your question, it is not pretty clear what you are asking for?
I'm working through a project to show information from a third party api on a map.
I'm not very experienced figuring out what the console is telling me so I'm a little stuck on the error I'm getting. I've declared all the variables outside of the function so result is defined and all of these functions are aspects of a foursquare venue.
Uncaught TypeError: Cannot read property 'hasOwnProperty' of undefined
$.ajax({
url:'https://api.foursquare.com/v2/venues/search',
dataType: 'json',
data: 'limit=1' +
'&ll='+ placeItem.lat() +','+ placeItem.lng() +
'&client_id='+ CLIENT_ID +
'&client_secret='+ CLIENT_SECRET +
'&v=20140806' +
'&m=foursquare',
async: true,
success: function (data) {
result = data.response.venue;
contact = result.hasOwnProperty('contact') ? result.contact : '';
if (contact.hasOwnProperty('formattedPhone')) {
placeItem.phone(contact.formattedPhone || '');
}
location = result.hasOwnProperty('location') ? result.location : '';
if (location.hasOwnProperty('address')) {
placeItem.address(location.address || '');
}
bestPhoto = result.hasOwnProperty('bestPhoto') ? result.bestPhoto : '';
if (bestPhoto.hasOwnProperty('prefix')) {
placeItem.photoPrefix(bestPhoto.prefix || '');
}
if (bestPhoto.hasOwnProperty('suffix')) {
placeItem.photoSuffix(bestPhoto.suffix || '');
}
description = result.hasOwnProperty('description') ? result.description : '';
placeItem.description(description || '');
rating = result.hasOwnProperty('rating') ? result.rating : '';
placeItem.rating(rating || 'none');
url = result.hasOwnProperty('url') ? result.url : '';
placeItem.url(url || '');
placeItem.canonicalUrl(result.canonicalUrl);
// Infowindow code is in the success function so that the error message
// Content of the infowindow
contentString = '<div id="iWindow"><h4>' + placeItem.name() + '</h4><div id="pic"><img src="' +
placeItem.photoPrefix() + '110x110' + placeItem.photoSuffix() +
'" alt="Image Location"></div><p>Information from Foursquare:</p><p>' +
placeItem.phone() + '</p><p>' + placeItem.address() + '</p><p>' +
placeItem.description() + '</p><p>Rating: ' + placeItem.rating() +
'</p><p><a href=' + placeItem.url() + '>' + placeItem.url() +
'</a></p><p><a target="_blank" href=' + placeItem.canonicalUrl() +
'>Foursquare Page</a></p><p><a target="_blank" href=https://www.google.com/maps/dir/Current+Location/' +
placeItem.lat() + ',' + placeItem.lng() + '>Directions</a></p></div>';
// Add infowindows
google.maps.event.addListener(placeItem.marker, 'click', function () {
infowindow.open(map, this);
// Bounce animation
placeItem.marker.setAnimation(google.maps.Animation.BOUNCE);
setTimeout(function () {
placeItem.marker.setAnimation(null);
}, 800);
infowindow.setContent(contentString);
});
},
// Alert the user on error.
error: function (e) {
infowindow.setContent('<h5>Foursquare data is unavailable.</h5>');
document.getElementById("error").innerHTML = "<h4>Foursquare data is unavailable. Please try refreshing.</h4>";
}
});
Not sure what data the call you are making is supposed to return but the error you are getting indicates that you did not get the data you were expecting.
result = data.response.venue;
"venue" is not a defined property of data.response so when you try and access result.hasOwnProperty('contact') it has no idea what to return since result is not defined.
I'm updating my knowledge about JavaScript and I stuck on one lesson task.
I have API that is returning string...
API.workerName = function (worker) {
return worker.firstName + ' ' + worker.lastName;
};
The task is to prefix returning string and not change API, but extend it. I also have to avoid copying & pasting code, because 3rd party code can change. I should re-use it instead.
What I did is change this function after loading API...
API.workerName = function (worker) {
return '(' + worker.position + ') ' + worker.firstName + ' ' + worker.lastName;
};
... but I think I did it wrong.
To extend the method, you should save the old definition and call it from your extension:
API.oldWorkerName = API.workerName;
API.workerName = function(worker) {
return '(' + worker.position + ')' + API.oldWorkerName(worker);
};
Or maybe this is what your lesson is looking for:
API.workerPositionAndName = function(worker) {
return '(' + worker.position + ')' + API.workerName(worker);
};
Another neat way to save the old definition and also make it unavailable to anybody else, would be to do something like this using IIFE to create a closure:
API.workerName = (function() {
var old = API.workerName; // this old version is only available inside your new function
return function(worker) {
return '(' + worker.position + ')' + old(worker);
}
})();
Here's an example:
API = {
workerName: function (worker) {
return worker.firstName + ' ' + worker.lastName;
}
};
API.workerName = (function () {
var old = API.workerName;
return function (worker) {
return '(' + worker.position + ')' + old(worker);
};
})();
alert(API.workerName({firstName: "Joe", lastName: "Blogs", position: "Lackey" }));
Is there a way to debug page.open method of phantomjs ? My application loads some files saved locally but unfortunately the only info one can get when opening the page is if it was loaded successfully or not. What more interesting the very same page loads properly when opened in the browser.
Here's my code :
var system = require('system'),
page = require('webpage').create();
var openPage = function () {
var url = 'http:\\localhost:53794/file.html';
page.open(url, function (status) {
if (status !== 'success') {
console.log("FAIL:" + url);
phantom.exit(2);
}
var date = new Date().getTime();
var outputFilename = outputPath + 'print-' + date + '.png';
setTimeout(function () {
page.render(outputFilename);
outputArray.push(outputFilename);
setTimeout(function () {
phantom.exit(1);
}, 1);
}, 1);
});
}
openPage();
via: http://newspaint.wordpress.com/2013/04/25/getting-to-the-bottom-of-why-a-phantomjs-page-load-fails/
After creating the page variable, but before calling page.open() add the following code:
page.onResourceError = function(resourceError) {
page.reason = resourceError.errorString;
page.reason_url = resourceError.url;
};
Now you can print out the reason for a problem in your page.open() callback, e.g.:
var page = require('webpage').create();
page.onResourceError = function(resourceError) {
page.reason = resourceError.errorString;
page.reason_url = resourceError.url;
};
page.open(
"http://www.nosuchdomain/",
function (status) {
if ( status !== 'success' ) {
console.log(
"Error opening url \"" + page.reason_url
+ "\": " + page.reason
);
phantom.exit( 1 );
} else {
console.log( "Successful page open!" );
phantom.exit( 0 );
}
}
);
Debugging Function
If you read further down the blog, he has some more suggested event handlers to add. I adapted them into a function that you can use to inject the event handlers into your page object (instead of having them defined in your main code)
// this method injects some debugging event handlers
// into a PhantomJS page object.
// usage:
// var page = require('webpage').create();
// var system = require('system');
// addDebugEvents(page,system);
function addDebugEvents(page, system) {
page.onResourceError = function (resourceError) {
page.reason = resourceError.errorString;
page.reason_url = resourceError.url;
};
page.onResourceRequested = function (request) {
system.stderr.writeLine('= onResourceRequested()');
system.stderr.writeLine(' request: ' + JSON.stringify(request, undefined, 4));
};
page.onResourceReceived = function (response) {
system.stderr.writeLine('= onResourceReceived()');
system.stderr.writeLine(' id: ' + response.id + ', stage: "' + response.stage + '", response: ' + JSON.stringify(response));
};
page.onLoadStarted = function () {
system.stderr.writeLine('= onLoadStarted()');
var currentUrl = page.evaluate(function () {
return window.location.href;
});
system.stderr.writeLine(' leaving url: ' + currentUrl);
};
page.onLoadFinished = function (status) {
system.stderr.writeLine('= onLoadFinished()');
system.stderr.writeLine(' status: ' + status);
};
page.onNavigationRequested = function (url, type, willNavigate, main) {
system.stderr.writeLine('= onNavigationRequested');
system.stderr.writeLine(' destination_url: ' + url);
system.stderr.writeLine(' type (cause): ' + type);
system.stderr.writeLine(' will navigate: ' + willNavigate);
system.stderr.writeLine(' from page\'s main frame: ' + main);
};
page.onResourceError = function (resourceError) {
system.stderr.writeLine('= onResourceError()');
system.stderr.writeLine(' - unable to load url: "' + resourceError.url + '"');
system.stderr.writeLine(' - error code: ' + resourceError.errorCode + ', description: ' + resourceError.errorString);
};
page.onError = function (msg, trace) {
system.stderr.writeLine('= onError()');
var msgStack = [' ERROR: ' + msg];
if (trace) {
msgStack.push(' TRACE:');
trace.forEach(function (t) {
msgStack.push(' -> ' + t.file + ': ' + t.line + (t.function ? ' (in function "' + t.function + '")' : ''));
});
}
system.stderr.writeLine(msgStack.join('\n'));
};
}
You should change the URL
from
http:\\localhost:53794/file.html
to
http://localhost:53794/file.html
I am reconfiguring an application that we had running in CRM 4.0 to run in CRM 2011. It was previously called from a toolbar button using javascript.
I have transferred the javascript to a web resource and reconfigured the ribbon to hold the button and call the required function within the library.
When testing this however, I am being prompted for username and password which when entered 3 or so times returns the error "'null' is null or not an object".
I am not sure why I am getting prompted for credentials when this did not happen in CRM 4.0.
Any ideas what may be causing this?
The javascript is below:
try
{
var ADD_LETTER='1';
var SAVE_DOC_IN_CRM='1';
var STORE_TO_PRINT='1';
var SEND_EMAIL='1';
var SHOW_PARAGRAPHS='1';
var xml = '' +'<?xml version=\'1.0\' encoding=\'utf-8\'?>' +'<soap:Envelope xmlns:soap=\'http://schemas.xmlsoap.org/soap/envelope/\' xmlns:xsi=\'http://www.w3.org/2001/XMLSchema-instance\' xmlns:xsd=\'http://www.w3.org/2001/XMLSchema\'>'+GenerateAuthenticationHeader() +' <soap:Body>' +' <RetrieveMultiple xmlns=\'http://schemas.microsoft.com/crm/2007/WebServices\'>' +' <query xmlns:q1=\'http://schemas.microsoft.com/crm/2006/Query\' xsi:type=\'q1:QueryExpression\'>' +' <q1:EntityName>systemuser</q1:EntityName>' +' <q1:ColumnSet xsi:type=\'q1:ColumnSet\'>' +' <q1:Attributes>' +' <q1:Attribute>systemuserid</q1:Attribute>' +' </q1:Attributes>' +' </q1:ColumnSet>' +' <q1:Distinct>false</q1:Distinct>' +' <q1:Criteria>' +' <q1:FilterOperator>And</q1:FilterOperator>' +' <q1:Conditions>' +' <q1:Condition>' +' <q1:AttributeName>systemuserid</q1:AttributeName>' +' <q1:Operator>EqualUserId</q1:Operator>' +' </q1:Condition>' +' </q1:Conditions>' +' </q1:Criteria>' +' </query>' +' </RetrieveMultiple>' +' </soap:Body>' +'</soap:Envelope>' +'';
var xmlHttpRequest = new ActiveXObject('Msxml2.XMLHTTP');
xmlHttpRequest.Open('POST', '/mscrmservices/2007/CrmService.asmx', false);
xmlHttpRequest.setRequestHeader('SOAPAction', 'http://schemas.microsoft.com/crm/2007/WebServices/RetrieveMultiple');
xmlHttpRequest.setRequestHeader('Content-Type', 'text/xml; charset=utf-8');
xmlHttpRequest.setRequestHeader('Content-Length', xml.length);
xmlHttpRequest.send(xml);
var resultXml = xmlHttpRequest.responseXML;
var entityNode = resultXml.selectSingleNode('//RetrieveMultipleResult/BusinessEntities/BusinessEntity');
var useridNode = entityNode.selectSingleNode('q1:systemuserid');
var sUserId = (useridNode == null) ? '' : useridNode.text;
var sGUID = crmForm.ObjectId;
var sEntity = crmForm.ObjectTypeName;
var sURL = '/ISV/Mergedabc/Mergedabc.aspx?org=' + ORG_UNIQUE_NAME + '&guid=' + sGUID + '&ety=' + sEntity + '&userid=' + sUserId + '&indid=' + sGUID + '&indtype=' + crmForm.ObjectTypeCode + '&indtypename=' + sEntity + '&addletter=' + ADD_LETTER + '&docincrm=' + SAVE_DOC_IN_CRM + '&storetoprint=' + STORE_TO_PRINT + '&emaildoc=' + SEND_EMAIL + '&showparas=' + SHOW_PARAGRAPHS;
var objRet = window.showModalDialog(prependOrgName(sURL));
if(objRet != null)
{
if (objRet.length > 0)
{
var o = objRet[0];
if (o.ret == true)
{
alert('Merge Completed.');
}
else {
alert('Unable to merge document.');
}
}
else
{
alert('No merge information returned.');
}
}
}
catch (e)
{
alert(e.message);
}
It looks as though this is happening when it tries to call the CrmService and is causing a 401 error.
Any suggestions on how to fix this will be appreciated,
Thanks!!
Fixed – the issue was the XML-isation of all the %amp; %lt; %gt; instead of %, < and > in the SOAP call.