can I use a http string from another website like a document object? [duplicate] - greasemonkey

I'm running GM_xmlhttpRequest (in a Greasemonkey script) and storing the responseText into a newly created HTML element:
var responseHTML = document.createElement('HTML');
...
onload: function() { responseHTML.innerHTML = response.responseText; }
And then I am trying to find an element in responseHTML:
console.log(responseHTML.getElementsByTagName('div'));
console.log(responseHTML.getElementById('result_0'));
The first works fine, but not the second. Any ideas?

Use DOMParser() to convert responseText into a searchable DOM tree.
Also, your attempts to search/use anything derived from responseText, must occur inside the onload function.
Use code like this:
GM_xmlhttpRequest ( {
...
onload: parseAJAX_ResponseHTML,
...
} );
function parseAJAX_ResponseHTML (respObject) {
var parser = new DOMParser ();
var responseDoc = parser.parseFromString (respObject.responseText, "text/html");
console.log (responseDoc.getElementsByTagName('div'));
console.log (responseDoc.getElementById('result_0'));
}
Of course, also verify that a node with id result_0 is actually in the returned HTML. (Using Firebug, Wireshark, etc.)

getElementById is not a method of HTML elements. It is a method of the document node. As such you can't do:
div.getElementById('foo'); // invalid code
You can implement your own function to search the DOM by recursively going through children. On newer browsers you can even use the querySelector method. For minimal development you can use libraries like jQuery or sizzle.js (the query engine behind jQuery).

There is no need to store the response in an element neither use DOMParser()
Just set the responseType to 'document' and the response will be parsed automatically and stored in the responseXML
Example:
var ajax = new XMLHttpRequest();
ajax.open('get','http://www.taringa.net');
ajax.responseType = 'document';
ajax.onload = function(){
console.log(ajax.responseXML); //And this is a document which may execute getElementById
};
ajax.send();

Related

iron-router template data in rendered callback

I'm passing a data object to a template with iron-router but would like to access the data within the Template.name.rendered = function() { ... } callback.
From Meteor data-context with iron-router I've tried UI.getData() but receive an error There is no current view. Using this.data returns null.
How can I get access to the data object passed to the template from the rendered callback?
You were on the right track with looking for the data context, but this is actually how you get access to it:
var ctx = Template.currentData();
Also, I believe Template.x.rendered is about to be deprecated, so if that doesn't work, try using
Template.x.onRendered(function() {
var ctx = Template.currentData();
console.log(ctx);
});

How to transfer DOM node pointer from page to content script

I have extension with content script and script injected into page. Injected script has reference to some DOM node and I want to pass it to content script. I know that injected script and content script live in different contexts, but they share DOM so it must be possible.
Ideally each DOM node would have unique ID, so I can get one, send to content script via message and then retrieve DOM node by this ID. But there is no such ID as far as I know.
My current solution is to send full node path, like root/child#1/child#10/....
Is there more effective solution?
You could dispatch a bubbling event, and use the event.target property to get the node's reference:
// content script
var myEventName = 'whatever' + Math.random(); // Unpredictable, avoid conflicts
document.addEventListener(myEventName, function(event) {
event.stopPropagation(); // No need to bubble further
var element = event.target;
// ... rest of your code
}, true); // <-- Get event at capture phase
// Inject the injected script
var script = document.createElement('script');
script.textContent = '(' + function(myEventName) {
function sendElementToContentScript(element) {
var event = new CustomEvent(myEventName, { bubbles: true });
element.dispatchEvent(event);
}
// ... rest of your code, e.g. sendElementToContentScript(document.body);
} + ')("' + myEventName + '");';
(document.head||document.documentElement).appendChild(script);
script.parentNode.removeChild(script);
If you wish to pass additional information with the event, set the event.detail property:
// set
var event = new CustomEvent(myEventName, {
bubbles: true,
detail: 'any serializable type'
});
// read (in event listener
console.log( event.detail );
For more information, see CustomEvent (MDN) and Building a Chrome Extension - Inject code in a page using a Content script (for those who are unfamiliar with the script injection technique).

Updating $scope after $HTTP.post

new at this.
I have 2 div's;
When I use one to post new value into the server, the post action works fine.
How do ensure this post updates the scope in the other div? (to update the div with the new entry using ng-repeat)
The HTTP.post action seems to be working as the data appears on refresh.
I have tried $scope.apply() but it doesn't appear to be working.
// this is the controller to get the data from the server
app.controller('projectsController',
function projectsController($scope, projectsFactory){
$scope.projects = projectsFactory.query();
});
and the factory to get the data from server
app.factory('projectsFactory',
function($resource,localStorage, $rootScope, $http){
return $resource('/api/project:id', {id: '#id'});
});
This is the controller to take the user input and post to back to the server
app.controller('projectEditController', function($scope, projectEdit){
$scope.projectEdit = projectEdit;
});
And the service to post the data to the server
app.service('projectEdit',
function projectEdit(localStorage,$rootScope, $http) {
var self = this;
self.add = function(newProject,projects) {
newProject = angular.copy(newProject);
var newProject = (JSON.stringify(newProject));
return $http.post('/api/project', newProject )
.then(function(response) {
newProject.id = response.data.id;
});
};
Which seems to be fine as it posts the data to the Sever fine.
What I am trying to figure out is how to get the
"$scope.projects = projectsFactory.query();" to update once the post operation is complete.
this will update the display in the HTML, which is the goal.
Hopefully this is an easy solve for a good developer, but I am stumped!
Thanks for your time.
Conor
Create 1 wrapper div, and set your controller to it with ng-controller.
Put your 2 divs in the wrapper div. Now the scope created by your controller is available in both divs, this is the easy way. When something updates data in that scope, and you have other things in the dom referencing that variable, then the dom will refresh like you want.
If you really want different controllers for each child div, that's fine, just be careful around inherited scopes. It really is much easier to just have one controller in a situation like this.
By the way, I saw that you mentioned scope.apply(). Be careful, apply() is a real javascript function, and NOT the one you want. You should call scope.$apply(), $apply is the angular function, and to avoid confusion, you could call scope.$digest instead.

Chrome Omnibox extension to post form data to a website?

How can an Omnibox extension create and post form data to a website and then display the result?
Here's an example of what I want to do. When you type lookup bieber into the Omnibox, I want my extension to post form data looking like
searchtype: all
searchterm: bieber
searchcount: 20
to the URL http://lookup.com/search
So that the browser will end up loading http://lookup.com/search with the results of the search.
This would be trivial if I could send the data in a GET, but lookup.com expects an HTTP POST. The only way I can think of is to inject a form into the current page and then submit it, but (a) that only works if there is a current page, and (b) it doesn't seem to work anyway (maybe permissions need to be set).
Before going off down that route, I figured that somebody else must at least have tried to do this before. Have you?
You could do this by using the omnibox api:
chrome.omnibox.onInputChanged.addListener(
function(text, suggest) {
doYourLogic...
});
Once you have you extension 'activated' due to a certain keyword you typed you can call something like this:
var q = the params you wish to pass
var url = "http://yourSite.com";
var req = new XMLHttpRequest();
req.open("POST", url, true);
req.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
req.onreadystatechange = function() {
if (req.readyState == 4) {
callback(req.responseXML);
}
}
req.send(q);

CouchDB list "An error occured accessing the list: Invalid JSON" error

I'm trying to call a CouchDB list from JavaScript.
My jQuery call is:
var listItems = $.couch.db('foo').list('foo/barList', 'foo/barView');
If I test this in the FireBug console when I'm on a page that has jquery.couch.js loaded (like Futon) it returns exactly what I want it to (several <input> tags with the appropriate data populated).
However, when I call this from code, I get the error:
An error occured accessing the list: Invalid JSON: [the html]
... where [the html] is the html I want to manipulate in my script. I don't understand why I'm getting a JSON error - I thought the point of lists was to return HTML. Is there a way to force it to return my html to me?
Also, my list function includes the following, so I'm not sure why this doesn't work.
start({
"headers": {
"Content-Type": "text/html"
}
});
According to https://issues.apache.org/jira/browse/COUCHDB-1059 this was a recognized bug and it had been patched. However after making the changes in jquery.couch.js recommended by Jan Lehnardt on the above page, I had to do one thing further.
The page above recommends making the following change in jquery.couch.js :
- var resp = httpData(req, "json");
+ var resp = httpData(req, dataType);
For some reason this didn't work for me but it did when I instead replaced it with the following. Theoretically one could add handlers for different types of content-types below.
var cType = req.getResponseHeader('Content-Type');
switch(cType) {
case 'text/html':
var resp = req.responseText;
break;
default:
var resp = $.parseJSON(req.responseText);
break;
}
If I'm missing something, I welcome recommendations on how to do this more effectively, but this works for me.

Resources