2

Seems like I can't access the .popover method inside my script. Unless I screwed up, I should have access to that method from the Bootstrap Native (Jquery-free Bootstrap) file included. ?

All the script does is add links and ideally a popover on that element.

Here is my code:

Manifest:

{
  "name": "foo",
  "description": "Work in Progress",
  "manifest_version": 2,
  "version": "0.8",
  "icons": { 
    "16": "icon16.png",
    "48": "icon48.png",
    "128": "icon128.png" 
  },
  "permissions": [
    "activeTab",
    "http://*/",
    "https://*/"
  ],
  "background": {
    "scripts": ["background.js"],
    "persistent": false
  },
  "browser_action": {
    "default_title": "Click me!"
  }
}

Background: (runs on icon click)

chrome.browserAction.onClicked.addListener(function(tab) {
    chrome.tabs.executeScript(tab.id, {file: "bootstrap-native.js" }, function() {
        chrome.tabs.executeScript(tab.id, {file: "content_script.js"});
});

});

content_script.js:

// Handle page's frame (to allow DOM access)
var page = top.frames["TargetContent"].document;

// Reference every professor listed and modify the registration page
Array.from(page.querySelectorAll("[id^='MTG_INSTR$']") ).forEach( el => {
    if (el.textContent == "Staff") {
        return;
    }

    // For every professor found, search for RMP page
    searchProfessor(el)

});



/**
 * Search for professor on RMP, then pass along to pageCheck
 * 
 * @param {Reference to prof} professorEl 
 */
function searchProfessor(professorEl) {
    var xhr = new XMLHttpRequest();

    xhr.onreadystatechange = function() {
        if (this.readyState == 4 && this.status == 200) {
            pageCheck(this.response,professorEl);

        }
    }

    // Search RMP using CSUF + Prof Name 
    xhr.open('GET', 'https://www.ratemyprofessors.com/search.jsp?queryoption=HEADER&queryBy=teacherName&schoolName=california+state+university+fullerton&schoolID=&query=' + professorEl.textContent +'&_action_search=Search');
    xhr.responseType = 'document';
    xhr.send();
}



/**
 * Verify prof's page exists and modify registration page
 * 
 * @param {DOM Obj} page 
 * @param {Reference to prof} element 
 */
function pageCheck(page,element){

    var ProfURL = page.getElementsByClassName('listing PROFESSOR')[0].childNodes[1].href

    // If the element exists, we have a hit (and the prof's page!)
    if (ProfURL) {
        // Link to the prof's RMP page
        addAnchor(element, ProfURL);    

        // Access the prof's specific RMP page
        var xhr1 = new XMLHttpRequest();

        // Create box to display prof info on hover
        xhr1.onreadystatechange = function() {
            if (this.readyState == 4 && this.status == 200) {
                addTooltip(this.response,element);
            }
        }

        xhr1.open('GET', ProfURL);
        xhr1.responseType = 'document';
        xhr1.send();

    }

}

function addTooltip(profPage,profElement) {

var name = profElement.textContent;
var grade = profPage.getElementsByClassName('grade')[0].textContent;    
var difficulty = profPage.getElementsByClassName('grade')[2].textContent;
var ratings = profPage.getElementsByClassName('table-toggle rating-count active')[0].textContent;
ratings = ratings.trim();
var content = "Grade: " + grade;

profElement.firstChild.setAttribute("data-toggle","popover");
profElement.firstChild.setAttribute("data-trigger","hover");
profElement.firstChild.setAttribute("title",name);
profElement.firstChild.setAttribute("data-content",content);
profElement.popover();

}

/**
 * Assign hyperlink to element 
 * 
 * @param {Element} wrapper 
 * @param {String} URL 
 */
function addAnchor (wrapper, URL) {

    var a = document.createElement('a');
    a.href = URL;
    a.textContent = wrapper.textContent;

    // Opens in new window/tab
    a.setAttribute('target', '_blank');
    wrapper.replaceChild(a, wrapper.firstChild);
}

Link to bootstrap native:

https://github.com/thednp/bootstrap.native

and

http://thednp.github.io/bootstrap.native/

Error:

content_script.js:75 Uncaught TypeError: profElement.popover is not a function
    at addTooltip (content_script.js:75)
    at XMLHttpRequest.xhr1.onreadystatechange (content_script.js:61)

bootstrap-native is the 68kb file from their bootstrap native/dist/ folder you download. I think this could be the issue, because when I stick a variable in this file it is accessable inside the content script, but not the methods.

I'm brand freaking to new to all of this, so maybe the file I have for bootstrap native isn't even the correct one. Or I'm not calling the method correctly, but that shouldn't give me this error.

Tom Aranda
  • 5,919
  • 11
  • 35
  • 51
Kevin
  • 129
  • 11

1 Answers1

1

By default executeScript injects only in the main page, not in iframes.

Specify allFrames: true to inject bootstrap-native in that iframe too:

chrome.tabs.executeScript(tab.id, {allFrames: true, file: "bootstrap-native.js"}, ......
wOxxOm
  • 65,848
  • 11
  • 132
  • 136
  • Why does this apply here? – Xan Aug 08 '17 at 11:00
  • 1
    Because of `top.frames["TargetContent"].document` – wOxxOm Aug 08 '17 at 12:32
  • @wOxxOm Hey, forgot to respond to you that's why I remade it. I tried it out, it didn't solve my problem. I can't seem to use any bootstrap native methods. in my script. I added the allframes true to the first execute script and no dice. – Kevin Aug 16 '17 at 23:47
  • In that case you should have mentioned your attempt in the new question, now closed as a duplicate. Also make sure to use the correct spelling for the allFrames parameter. If you did, the reason might be that bootstrap-native doesn't work across different frames. – wOxxOm Aug 17 '17 at 05:14