42

I have been learning to create a chrome extension. I have tried hello world example and it was working fine. Now I have been trying to add custom code and make some changes in the hello world code according to my requirements.

What I am trying to create is when the user clicks on the icon in the address bar, it should open popup.html below address bar as shown in the picture. The screenshot is from extension called raindrop.io

They are doing is within chrome extension. When I click on the icon it opens the right drawer on top of the existing webpage and below the address bar to show all my saved bookmarks. I wanted to achieve the same effect but I don't know where to start. I have heard that there was some experimental side pane but google has removed it.

Raindrop.io extension

EDIT

I have taken the suggestions and tried to implement that. Now I am stuck at two places -

  1. How to open the window when clicked on the icon in the address bar. Right now it just opens automatically by itself. I want it open when the user clicks on the icon.
  2. I am doing all this to create a note taking the extension and I have done creating a note-taking extension but it works in popup interface but I wanted to implement in sidebar interface.

Here is my code for -

A. Side Window Interface in Chrome Extension

manifest.json

    {
    "manifest_version": 2,

    "name": "Hello World",
    "description": "This extension to test html injection",
    "version": "1.0",
    "content_scripts": [{
        "run_at": "document_end",
        "matches": [
            "https://*/*",
            "http://*/*"
        ],
        "js": ["js/jquery-1.11.3.js", "js/content-script.js"],
        "css": ["css/custom.css"]
    }],
    "browser_action": {
        "default_icon": "icon.png"
    },
    "permissions": [
        "activeTab",
        "https://ajax.googleapis.com/"
    ]
  }

Content Script.js

var iframe = document.createElement('iframe'); 
iframe.style.background = "green";
iframe.style.height = "100%";
iframe.style.width = "360px";
iframe.style.position = "fixed";
iframe.style.top = "0px";
iframe.style.right = "0px";
iframe.style.zIndex = "9000000000000000000";
iframe.frameBorder = "none"; 
 
document.body.appendChild(iframe);

B. Note Taking App Extension

popup.html

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="utf-8">
    <title>SideNotes</title>
    <link rel="stylesheet" href="css/style.css">
    <script src="popup.js"></script>
</head>

<body>
    <div class="container">
        <div id="toolbar">
          <p id="title">S I D E N O T E S </p> 
          <img id="logo" src="image/icon.png" alt="">
        </div>
        <div id="all-notes">
            <ul id="todo-items"></ul>
        </div>
        <div id="take-note">
            <form id="new-todo-form" method="POST" action="#">
                <textarea id="new-todo"></textarea>
                <input type="image" src="image/done.svg" id="submitButton">
            </form>
        </div>
    </div>
    <script type="text/javascript" src="js/jquery.min.js"></script>
    <script type="text/javascript" src="js/custom.js"></script>
    <script type="text/javascript" src="js/db.js"></script>
    <script type="text/javascript" src="js/app.js"></script>
</body>

</html>

Screenshot of my app, it works locally enter image description here

Community
  • 1
  • 1
Greyfrog
  • 926
  • 1
  • 8
  • 19
  • 1
    I think you need use [Content Scripts](https://developer.chrome.com/extensions/content_scripts) for that.The Content Scripts allow you add content to a page and you will be able to do a div with side style and effects. – SnakeDrak Sep 21 '16 at 07:41
  • 1
    There are no such panels in Chrome. Opera has the feature. Anyway, this is not a popup but just an injected html element as you can see in the element inspector upon rightclicking the "panel". – wOxxOm Sep 21 '16 at 07:46
  • you can debug thar extension. – Zig Mandel Sep 21 '16 at 12:09
  • @PedroGámez Thanks for the reply. I have done exactly you ask and now I need some more help. Please see my edits .. thanks again. – Greyfrog Sep 24 '16 at 15:26

3 Answers3

49

There is no right-side panel in chrome extension API.

But you may do it in the same way that your example extension does:

  1. Create background.js listening messages from the tab
  2. Create a content script sends the message to background.js if the tab is injectable (if you need your extension work correct on system pages)
  3. If tab is injectable, with chrome.tabs.executeScript inject your menu div to the page / inject listener, which opens your menu.

More details about how to do it below.

  1. Create background.js listening browser icon clicks and notify your content script about clicks.
  2. Prevent showing of popup.html in default popup.

manifest.js

....
"browser_action": {
},
"background": {
    "scripts":["background.js"]
},
...

background.js

chrome.browserAction.onClicked.addListener(function(tab){
    chrome.tabs.sendMessage(tab.id,"toggle");
});
  1. In content-script.js create an invisible iframe, with your popup.html (with zero width on with display:none; style). I use zero width because of you may want to animate your menu display by jquery as example extension does.
  2. In content-script add message listener for receive messages sent from background.js script.
  3. When receiving the message, show or hide menu block

content-script.js

chrome.runtime.onMessage.addListener(function(msg, sender){
    if(msg == "toggle"){
        toggle();
    }
});

var iframe = document.createElement('iframe'); 
iframe.style.background = "green";
iframe.style.height = "100%";
iframe.style.width = "0px";
iframe.style.position = "fixed";
iframe.style.top = "0px";
iframe.style.right = "0px";
iframe.style.zIndex = "9000000000000000000";
iframe.frameBorder = "none"; 
iframe.src = chrome.extension.getURL("popup.html")

document.body.appendChild(iframe);

function toggle(){
    if(iframe.style.width == "0px"){
        iframe.style.width="400px";
    }
    else{
        iframe.style.width="0px";
    }
}
  1. Make popup.html and scripts you load from extension context visible for browser HTML context:

manifest.json

"web_accessible_resources": ["popup.html"]

Read more

  1. Chrome Tabs API: https://developer.chrome.com/extensions/tabs
  2. Chrome message passing: https://developer.chrome.com/extensions/messaging
  3. Browser action click processing: https://developer.chrome.com/extensions/browserAction#event-onClicked
  4. Content script injection: https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/tabs/executeScript
pizzaisdavid
  • 455
  • 3
  • 13
MobDev
  • 1,614
  • 17
  • 17
  • .Please check my updates and suggest me how to proceed. – Greyfrog Sep 24 '16 at 15:25
  • Updated my answer with example. I hope now it answers both of your questions :) – MobDev Sep 25 '16 at 12:30
  • Thanks for the reply. I have completed my first chrome extension. – Greyfrog Sep 27 '16 at 05:41
  • 2
    Is it possible for this iframe to push the actual page to the side? Basically reducing the width of the current page – Jeff Saremi May 30 '18 at 21:50
  • There is no universal way to do it as I know. You may inject CSS to the page, so you may play with CSS to decrease display page size, like set padding-right for body block, set max-width for fixed-positioned blocks, but there are many sites now uses JS-based blocks position, calculated with body.offsetWidth and this method will not work right for it. – MobDev Jun 01 '18 at 00:53
  • Great answer, but what can you do if the tab is not injectable? – colouredFunk Feb 13 '20 at 10:56
  • There is no common way to inject JS to a non-injectable page... You may check if the page is a non-injectable and open bar in a popup window on that case – MobDev Feb 16 '20 at 23:14
  • I just found below extension which does that, not sure how complicated is it to implement this feature in 2020? https://chrome.google.com/webstore/detail/bookmark-sidebar/jdbnofccmhefkmjbkkdkfiicjkgofkdh?hl=en – devvapp May 25 '20 at 04:43
  • I will check it and will update my article if there is something new in API. – MobDev Jul 18 '20 at 09:42
  • Anyone know how to do this when using a React app? The above results in the iframe being rendered 3 times when using React. – Amos Apr 17 '22 at 18:26
  • Chrome now has a built in side panel feature, see my post below. – Joey Grisafe Jun 27 '23 at 03:31
13

The same side panel example with "manifest_version": 3, as version 2 is deprecated.

manifest.json (change EXTENTION-KEY):

{
...
    "version": "1.0",
    "manifest_version": 3,
    "background": {
        "service_worker": "background.js"
    },
    "action": {},
    "content_scripts": [
      {
        "matches": [
            "https://*/*",
            "http://*/*"
        ],
        "js": ["side-panel.js"]
      }
    ],
    "web_accessible_resources": [
      {
        "resources": ["popup.html" ],
        "matches": ["https://*/*", "http://*/*"],
        "extension_ids": ["<EXTENTION-KEY>"]
      }
    ]
  }

background.js:

chrome.action.onClicked.addListener(tab => {
  chrome.tabs.sendMessage(tab.id,"toggle");
  console.log('message sent');
});

side-panel.js:

console.log("side-panel script loaded");

chrome.runtime.onMessage.addListener(function(msg, sender){
    if(msg == "toggle"){
        console.log("message received");
        toggle();
    }
})

var iframe = document.createElement('iframe'); 
iframe.style.background = "green";
iframe.style.height = "100%";
iframe.style.width = "0px";
iframe.style.position = "fixed";
iframe.style.top = "0px";
iframe.style.right = "0px";
iframe.style.zIndex = "9000000000000000000";
iframe.style.border = "0px"; 
iframe.src = chrome.runtime.getURL("popup.html")

document.body.appendChild(iframe);

function toggle(){
    if(iframe.style.width == "0px"){
        iframe.style.width="400px";
    }
    else{
        iframe.style.width="0px";
    }
}

popup.html:

<!DOCTYPE html>
<html>
  <head>
    <link rel="stylesheet" href="popup.css">
  </head>
  <body>
    Content
  </body>
</html>
tarasinf
  • 796
  • 5
  • 17
3

Chrome has now launched its side panel with version 114 and above, you can set a page just like you would with a popup or options page. I've written a blog post with a clonable repository on how you can also use content scripts and dynamically display user interactions by passing messages through port messaging.

enter image description here

Joey Grisafe
  • 336
  • 3
  • 9