0

How do I get a reference to the dom of a cross domain iframe/frame?

I want to do some stuff to disqus comments with an extension.

My manifest has the following:

"all_frames": true,
"matches": ["*://*.disqus.com/*","*://disqus.com/*", "http://somesite.com"]

I am not trying to communicate outside of the frame - that is the js will take care of the work without needing to 'tell' me anything.

all_frames should inject the listed js files into every frame, no?

When I do this:

if (window != window.top){
  alert('In an IFRAME: ' + window.location.href);
}

...I get the expected disqus URLs.

But when I do this:

var btnCommentBlock = document.getElementsByClassName('dsq-comment-buttons');
alert('btnCommentBlock length: ' + $(btnCommentBlock).length);

...I get 0 for length.

Darin
  • 2,071
  • 2
  • 17
  • 14
  • possible duplicate of [Javascript to access Disqus comment textbox?](http://stackoverflow.com/questions/4504709/javascript-to-access-disqus-comment-textbox) – Mohamed Mansour Jun 19 '11 at 03:56
  • Actually, I found that question and tried that code and it did not work for some reason. – Darin Jun 19 '11 at 05:43
  • Mohamed, you answered the other question?! Can you see anything I am doing wrong? When you tested the other code what site did you test it against? – Darin Jun 19 '11 at 12:49
  • They changed the selector to a div instead of a textarea. Updated my answer and tested locally. Added source code below. – Mohamed Mansour Jun 19 '11 at 13:53

2 Answers2

1

I updated my answer to Javascript to access Disqus comment textbox?

Basically, Disqus changed the selector. They no longer use textarea, they use contenteditable divs.

Something like this should work:

// We just need to check if the IFrame origin is from discus.com
if (location.hostname.indexOf('.disqus.com') != -1) {
  // Extract the textarea (there must be exactly one)
  var commentBox = document.querySelector('#comment');
  if (commentBox) {
    // Inject some text!
    commentBox.innerText = 'Google Chrome Injected!';
  }
}

Source Code: https://gist.github.com/1034305

Community
  • 1
  • 1
Mohamed Mansour
  • 39,445
  • 10
  • 116
  • 90
  • You are saying that 'document' is the way just like any other web page, right? Do I need to add some sort of delay before trying to access the frame's dom? – Darin Jun 19 '11 at 14:26
  • No delay! You inject the manifest at "document_end". The Iframe is already loaded, the Source Code above (just place the files in a folder and load that folder in chrome://extensions) you will see the comment box change text. Just place in your content script manifest `"run_at": "document_end"` The code above is simple, and tested to work. – Mohamed Mansour Jun 20 '11 at 04:04
  • Yes, I understand that Mohamed. Unfortunately, I wanted to do more than add 'Google Chrome Injected' to the default editable div. – Darin Jun 21 '11 at 04:44
  • Using your code it failed every time. Once I added the delay it worked. As I said, I'd already found your other answer and played with it trying to get it to work. – Darin Jun 21 '11 at 04:46
  • By the way, I was the one that gave you the up vote for taking the time to try to answer my question. I appreciate the help and the link that led me to a working solution for my issue. – Darin Jun 21 '11 at 04:49
  • Ah. I wasn't imagining it. There is a problem if you do not have a delay: http://stackoverflow.com/questions/2885972/disqus-change-captions-after-success-with-jquery/6420965#6420965 – Darin Jun 21 '11 at 05:59
  • It works everytime here :) You must have done something incorrect cause that delay is clearly not needed. If it is needed, then there is a bug in Chrome that you need to file. – Mohamed Mansour Jun 22 '11 at 01:38
  • Yes, it works to write 'chrome injected'. Try to manipulate some of the dom in the iframe and you'll see what I mean. For sure the site I'm tinkering with failed every time without the delay. :) – Darin Jun 22 '11 at 02:35
0

Woohoo! I found the answer on github:

https://gist.github.com/471999

The working code is:

$(document).ready(function() {
  window.disqus_no_style = true;

  $.getScript('http://sitename.disqus.com/embed.js', function() {
    var loader = setInterval(function() {
      if($('#disqus_thread').html().length) {
        clearInterval(loader);
        disqusReady();
      }
    }, 1000);
  });

  function disqusReady() {
    //whatever you can imagine
  }
});

I put this in the disqusReady() function:

var aTestHere = document.getElementsByClassName('dsq-comment-body');
alert(aTestHere[0].innerHTML);

...and got back the innerHTML as expected.

Mohamed, I'd really like to thank you for taking the time to interact with my question. If you hadn't posted that link to github there's no telling when if ever I'd have figured it out or found the other code.


edit: After a few minutes of experimenting it looks like it is not necessary to call getScript so you should be able to comment that out.

Also unnecessary is window.disqus_no_style so I commented that out too.

I'll experiment some more and update the answer later. One of those two things prevented me from being able to actually post a comment at the disqus site I use. //them out still allows access to the dom and the ability to post.

Darin
  • 2,071
  • 2
  • 17
  • 14
  • No further modifications needed. You can refer to the dom as usual once disqusReady trips. – Darin Jun 21 '11 at 04:42