开发者

Chrome Extension: popup.html dynamically create via contentscript.js

I've read Google's Message passing page and I've also read similar questions here on StackOverflow.

The full source for what I am working on is available on google code.

I right now have the contentscript.js insert links next to dates on a webpage that directs the user to Google's calendar event creation page with the date/time already filled out.

contentscript.js

    /*
 * Copyright (c) 2010 Thomas Wolfe. All rights reserved.  Use of this
 * source code is governed by a Simplified BSD license that can be found in the
 * LICENSE file.
 */
/*
 * Regex Matches
 * 12/31/2002     | Dec 31, 2002 | December 31 2002 | 12-31-2002 | 2002/12/31 (ISO 8601) | 12/31/2002 20:00 | 12/31/2002 08:00 PM
 * Non-Matches
 * 12/31/02  | 15/12/2002 (day month year) | 2002/12/3 (needs a two digit day in this case to prevent breaking 2 digit day)
 */
var regex = /(((([0]?[1-9]|1[0-2])|(Jan|January|Feb|February|Mar|March|Apr|April|May|Jun|June|Jul|July|Aug|August|Sep|September|Oct|October|Nov|November|Dec|December))(\/|-|\.| |, )([0-2]?[0-9]|3[0-1])(\/|-|\.| |, )([1-2]\d{3}))|(([1-2]\d{3})(\/|-|\.| |, )(([0]?[1-9]|1[0-2])|(Jan|January|Feb|February|Mar|March|Apr|April|May|Jun|June|Jul|July|Aug|August|Sep|September|Oct|October|Nov|November|Dec|December))(\/|-|\.| |, )([0-2]?[0-9]|3[0-1]){2}))( (([0-1]?\d)|(2[0-3])):[0-5]\d)?( AM| am| PM| pm)?/ig;
// Removes duplicate values from an array
function unique(inputArray){
    var outputArray = new Array();
    o: for (var i = 0; i < inputArray.length; i++) {
        for (var x = 0; x < outputArray.length; x++) {
            if (outputArray[x] == inputArray[i]) 
                continue o;
        }
        outputArray[outputArray.length] = inputArray[i];
    }
    return outputArray;
}

// Converts the given time into UTC, returns this in a string
function getUTCDateString(y, m, d, h, min){
    var timeObj = new Date(y, m - 1, d, h, min);
    var dateStr = "" + timeObj.getUTCFullYear();
    dateStr += stringPad(timeObj.getUTCMonth() + 1);
    dateStr += stringPad(timeObj.getUTCDate());
    dateStr += "T" + stringPad(timeObj.getUTCHours());
    dateStr += stringPad(timeObj.getUTCMinutes()) + "00Z";
    return dateStr;
}

// Add a leading '0' if string is only 1 char
function stringPad(str){
    var newStr = "" + str;
    if (newStr.length == 1) {
        newStr = "0" + newStr;
    }
    return newStr;
}

function getMonthByName(str){
    var newStr = "" + str;
    var month;
    switch (newStr) {
        case "Jan":
        case "January":
            month = 1;
            break;
        case "Feb":
        case "February":
            month = 2;
            break;
        case "Mar":
        case "March":
            month = 3;
            break;
        case "Apr":
        case "April":
            month = 4;
            break;
        case "May":
            month = 5;
            break;
        case "Jun":
        case "June":
            month = 6;
            break;
        case "Jul":
        case "July":
            month = 7;
            break;
        case "Aug":
        case "August":
            month = 8;
            break;
        case "Sep":
        case "September":
            month = 9;
            break;
        case "Oct":
        case "October":
            month = 10;
            break;
        case "Nov":
        case "November":
            month = 11;
            break;
        default:
            month = 12;
    }
    return month;
}

function indiciesOfText(stringToSearch, searchFor)
{
 var regex = new RegExp(searchFor,"g"), result, indices = [];
 while ( (result = regex.exec(stringToSearch)) ) {
     indices.push(result.index+searchFor.length);
 }
 return indices;
}
function createLinkImg(dateStr)
{
 var dateImg = document.createElement("IMG");
 dateImg.title = "Add this event to your Google Calendar";
 dateImg.src = chrome.extension.getURL("Config-date-16.png")
 var dateLink = document.createElement("A");
 dateLink.target = "_blank";
 dateLink.href = "http://www.google.com/calendar/event?action=TEMPLATE&text=someevent&dates=" + dateStr + "&details=&location=&trp=false&sprop=&sprop=";
 dateLink.appendChild(dateImg);
 return dateLink;
}
function replaceText(dateStr, dateTxt, tobeReplacedNode) {
 dateLink = createLinkImg(dateStr);
 // if textNode search and replace
 if (tobeReplacedNode.nodeType == 3) {
  if (tobeReplacedNode.textContent.search(new RegExp(dateTxt,"g")) != -1) {
   var splitTxtNode = indiciesOfText(tobeReplacedNode.textContent,dateTxt);
   for (var k = 0; k < splitTxtNode.length; k++) {
    if (k == 0) {
     var txtAfterOffsetNode = tobeReplacedNode.splitText(splitTxtNode[k]);
     tobeReplacedNode.parentNode.insertBefore(dateLink, tobeReplacedNode.nextSibling);
    }
    else {
     var txtAfterOffsetNode = txtAfterOffsetNode.splitText(splitTxtNode[k]-splitTxtNode[k-1]);
     txtAfterOffsetNode.parentNode.insertBefore(dateLink, txtAfterOffsetNode.nextSibling);
    }
   }
  }
 }
 if (tobeReplacedNode.hasChildNodes() && splitTxtNode == null) {
  //recall this function
  for (var j = 0; j < tobeReplacedNode.childNodes.length; j++) {
   replaceText(dateStr, dateTxt, tobeReplacedNode.childNodes[j]);
  }
 }
 //return tobeReplacedNode;
}
function getMonthDayYearHourMin(date) {
 var arraySplits = date.split(/(\/|-|\.| |, |:)/gi);

 // set time (hour/min)
 if (arraySplits.length > 5) {
  hour = arraySplits[6];
  min = arraySplits[8];
  if (arraySplits.length > 9) {
   ampm = arraySplits[10];
   if (ampm == "pm" | "PM") {
    hour = 12 + parseInt(hour);
    hour = hour.toString();
   }
  }
 }
 else // no time provided, set to 00:00
 {
  hour = "00";
  min = "00";
 }
 // if the year is not the first element day/year/month are in different locations
 if (arraySplits[0].length != 4 | (arraySplits[0] == "June" | "July")) {
  year = arraySplits[4];

  if (parseInt(arraySplits[0]) > 12) {
   if (arraySplits[2].length < 3) {
    month = arraySplits[2];
   }
   else {
    month = getMonthByName(arraySplits[2]);
   }
   day = arraySplits[0];
  }
  if (arraySplits[0].length < 3) {
   month = arraySplits[0];
  }
  else {
   month = getMonthByName(arraySplits[0]);
  }
  day = arraySplits[2];
 }
 else {
  year = arraySplits[0];
  if (parseInt(arraySplits[2]) > 12) {
   day = arraySplits[2];
   month = arraySplits[4];
  }
  else {
   month = arraySplits[2];
   day = arraySplits[4];
  }
 }
 return getUTCDateString(year, month, day, hour, min);
}
function replaceBody(date, bodyElement) {
 initDateString = getMonthDayYearHourMin(date);
    dateString = initDateString + "/" + initDateString;

 replaceText(dateString, date, bodyElement);
 return dateString;
}

// Test the text of the body element against our regular expression.
if (regex.test(document.body.innerText)) {
    var bodyElement = document.getElementsByTagName("BODY")[0];
    var nonUniqueArrayDates = document.body.innerText.match(regex); // array of date/time values
    var arrayDates = unique(nonUniqueArrayDates);
 var arrayDateStr = new Array();

 // FIXME: ugly hack for this for loop to deal with issue 9 which I cannot figure out
 for (var i = 0; i < Math.min(arrayDates.length,20); i++) {
  arrayDateStr.push(replaceBody(arrayDates[i], bodyElement));
 }
 /* The regular expression produced a match, so notify the background page
  * and send the array of dateStrings.
  */
    chrome.extension.sendRequest({dates: JSON.stringify(arrayDateStr)}, function(response){
    });
}
else {
    // No match was found.
}

I also have the contentscript send a request to the background.html page to show the page_action button.

background.html:

    <!DOCTYPE html>
<!--
 * Copyright (c) 2010 The Chromium Authors. All rights reserved.  Use of this
 * source code is governed by a BSD-style license that can be found in the
 * LICENSE file.
-->
<html>
  <head>
    <script>
      // Called when a message is passed.  We assume that the content script
      // wants to show the page action.
      function onRequest(request, sender, sendResponse) {
        // Show the page action for the tab that the sender (content script)
        // was on.
        chrome.pageAction.show(sender.tab.id);
  var arrayDateStr = JSON.parse(request.dates);
        // Return nothing to let the connection be cleaned up.
        sendResponse({});
      };

      // Listen for the content script to send a message to the background page.
      chrome.extension.onRequest.addListener(onRequest);

   // Google Analytics, registers a view once per browser session
   var _gaq = _gaq || [];
     _gaq.push(['_setAccount', 'UA-2551829-4']);
     _gaq.push(['_trackPageview']);

     (function() {
       var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
       ga.src = 'https://ssl.google-analytics.com/ga.js';
       var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
     })();
    </script>
  </head>
</html>

I'm now trying to create a popup.html which contains a list of all of the dates on a webpage and again a link to create an event in the users calendar.

popup.html

<head>
<style>
body {
  margin: 0px;
  padding: 0px;
}
#cal {
  width: 312px;
  height: 312px;
}
</style>
<script>
function createLink(dateStr)
{
 var parElem = document.createElement("P");
 var textNode = document.createTextNode(dateStr);
 var dateLink = document.createElement("A");
 dateLink.target = "_blank";
 dateLink.href = "http://www.google.com/calendar/event?action=TEMPLATE&text=someevent&dates=" + dateStr + "&details=&location=&trp=false&sprop=&sprop=";
 dateLink.appendChild(textNode);
 parElem.appendChild(dateLink);
 return parElem;
}
function cal() {
  var arrayDateStr = chrome.extension.getBackgroundPage().arrayDateStr;
  var cal = document.getElementById("cal");
  for(i=0; i<arrayDateStr.length; i++)
  {
   cal.appendChild(createLink(arrayDateStr[i]));
  }
}
</script>
</h开发者_开发知识库ead>
<body onload="cal()">
<p id="cal"></p>
</body>

For some reason var arrayDateStr = chrome.extension.getBackgroundPage().arrayDateStr; arrayDateStr does not seem to ever be defined.

I'm just really confused right now and cannot find any examples that I understand. I'm thinking I need to do something else with message passing because I don't think getBackgroundPage() would know which tab it should be associated with.

Any ideas or suggestions would be appreciated. Thank you.


I figured it out, sorry if I wasted anyones time. I had to move var arrayDateStr = null; before the onRequest function in background.html Hopefully this may help someone in the future.

very minor change:

    <!DOCTYPE html>
<!--
 * Copyright (c) 2010 The Chromium Authors. All rights reserved.  Use of this
 * source code is governed by a BSD-style license that can be found in the
 * LICENSE file.
-->
<html>
  <head>
    <script>
      var arrayDateStr = null;
      // Called when a message is passed.  We assume that the content script
      // wants to show the page action.
      function onRequest(request, sender, sendResponse) {
        // Show the page action for the tab that the sender (content script)
        // was on.
        chrome.pageAction.show(sender.tab.id);
        arrayDateStr = JSON.parse(request.dates);
        // Return nothing to let the connection be cleaned up.
        sendResponse({});
      };

      // Listen for the content script to send a message to the background page.
      chrome.extension.onRequest.addListener(onRequest);

      // Google Analytics, registers a view once per browser session
      var _gaq = _gaq || [];
     _gaq.push(['_setAccount', 'UA-2551829-4']);
     _gaq.push(['_trackPageview']);

     (function() {
       var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
       ga.src = 'https://ssl.google-analytics.com/ga.js';
       var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
     })();
    </script>
  </head>
</html>
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜