Skip to content

Port OneNote hero sample to this repo #991

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 15 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ Check out these samples if you want to take advantage of the [shared runtime](ht
| [Use a shared library to migrate your Visual Studio Tools for Office add-in to an Office web add-in](Samples/VSTO-shared-code-migration) | Provides a strategy for code reuse when migrating from VSTO Add-ins to Office Add-ins. |
| [Integrate an Azure function with your Excel custom function](Excel-custom-functions/AzureFunction) | Learn how to integrate Azure functions with custom functions to move to the cloud or integrate additional services. |
| [Dynamic DPI code samples](Samples/dynamic-dpi) | A collection of samples for handling DPI changes in COM, VSTO, and Office Add-ins. |
| [Rubric grader task pane add-in for OneNote on the web](Samples/onenote-add-in-rubric-grader/) | Explore the basics of OneNote add-ins with a sample tool for teachers. |

## Learn more

Expand Down
6 changes: 6 additions & 0 deletions Samples/onenote-add-in-rubric-grader/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
bower_components/
node_modules/
.vscode/
npm-debug.log
localhost.crt
localhost.key
24 changes: 24 additions & 0 deletions Samples/onenote-add-in-rubric-grader/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
The MIT License (MIT)

Copyright (c) Microsoft Corporation
All rights reserved.

MIT License:
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
120 changes: 120 additions & 0 deletions Samples/onenote-add-in-rubric-grader/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
---
title: "Rubric grader task pane add-in for OneNote on the web"
page_type: sample
urlFragment: onenote-add-in-rubric-grader
products:
- m365
- office
- office-onenote
languages:
- javascript
extensions:
contentType: samples
technologies:
- Add-ins
createdDate: 6/17/2025 4:00:00 PM
description: Explore the basics of OneNote add-ins with a sample tool for teachers.
---

# Rubric grader task pane add-in for OneNote on the web

## Summary

The Rubric Grader sample shows you how to use the OneNote JavaScript API in a OneNote task pane add-in. The add-in gets page content, adds an outline to the page, and opens a different page.

The add-in helps teachers grade writing assignments based on a grading rubric.

![Rubric Grader task pane add-in in OneNote Online](assets/readme-images/rubric-grader.png)

## Features

- Interact with OneNote through a custom task pane

## Applies to

- OneNote on the web

## Prerequisites

- A Microsoft 365 tenant

## Solution

| Solution | Author(s) |
|---------|----------|
| Rubric grader task pane add-in for OneNote on the web | Microsoft |

## Version history

| Version | Date | Comments |
|---------|------|---------|
| 1.0 | 6-17-2025 | Initial release |

## Run the sample

You can run this sample in Onenote in a browser. The add-in web files are served from this repo on GitHub.

1. Download the **manifest.xml** file from this sample to a folder on your computer.
1. Open [Office on the web](https://office.live.com/).
1. Under **Apps**, choose **OneNote**.
1. Open a notebook that contains a couple of pages. Make sure at least one page has a paragraph of content.
1. Open the **Insert** tab on the ribbon and choose **Office Add-ins**.
1. On the **Office Add-ins** dialog, select the **MY ADD-INS** tab, choose **Upload My Add-in**.
1. Browse to the add-in manifest file, and then select **Upload**.
1. Verify that the add-in loaded successfully. You will see a **Show Taskpane** button on the **Home** tab on the ribbon.

Once the add-in is loaded use the following steps to try out the functionality.

## Run the sample from localhost

If you prefer to configure a web server and host the add-in's web files from your computer, use the following steps.

1. Install a recent version of [npm](https://www.npmjs.com/get-npm) and [Node.js](https://nodejs.org/) on your computer. To verify if you've already installed these tools, run the commands `node -v` and `npm -v` in your terminal.

1. You need http-server to run the local web server. If you haven't installed this yet, you can do this with the following command.

```console
npm install --global http-server
```

1. You need Office-Addin-dev-certs to generate self-signed certificates to run the local web server. If you haven't installed this yet, you can do this with the following command.

```console
npm install --global office-addin-dev-certs
```

1. Clone or download this sample to a folder on your computer, then go to that folder in a console or terminal window.

1. Run the following command to generate a self-signed certificate to use for the web server.

```console
npx office-addin-dev-certs install
```

This command will display the folder location where it generated the certificate files.

1. Go to the folder location where the certificate files were generated, then copy the **localhost.crt** and **localhost.key** files to the cloned or downloaded sample folder.

1. Run the following command.

```console
http-server -S -C localhost.crt -K localhost.key --cors . -p 3000
```

The http-server will run and host the current folder's files on localhost:3000.

1. Now that your localhost web server is running, you can sideload the **manifest-localhost.xml** file provided in the sample folder. Using this file, follow the steps in [Run the sample](#run-the-sample) to sideload and run the add-in.

## Questions and feedback

- Did you experience any problems with the sample? [Create an issue](https://github.com/OfficeDev/Office-Add-in-samples/issues/new/choose) and we'll help you out.
- We'd love to get your feedback about this sample. Go to our [Office samples survey](https://aka.ms/OfficeSamplesSurvey) to give feedback and suggest improvements.
- For general questions about developing Office Add-ins, go to [Microsoft Q&A](https://learn.microsoft.com/answers/topics/office-js-dev.html) using the office-js-dev tag.

## Copyright

Copyright (c) 2025 Microsoft Corporation. All rights reserved.

This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information, see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [[email protected]](mailto:[email protected]) with any additional questions or comments.

<img src="https://pnptelemetry.azurewebsites.net/pnp-officeaddins/samples/onenote-add-in-rubric-grader" />
41 changes: 41 additions & 0 deletions Samples/onenote-add-in-rubric-grader/app/app.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/* Common app styling */

.padding-header {
padding: 30px 30px 20px 20px;
}

.padding-body {
padding: 5px 20px;
}

.padding-top {
padding: 25px 0px 0px 0px;
}

#notification-message {
background-color: #818285;
color: #fff;
position: absolute;
width: 100%;
min-height: 80px;
right: 0;
z-index: 100;
bottom: 0;
display: none; /* Hidden until invoked */
}

#notification-message #notification-message-header {
font-size: medium;
margin-bottom: 10px;
}

#notification-message #notification-message-close {
background-image: url("../Images/Close.png");
background-repeat: no-repeat;
width: 24px;
height: 24px;
position: absolute;
right: 5px;
top: 5px;
cursor: pointer;
}
30 changes: 30 additions & 0 deletions Samples/onenote-add-in-rubric-grader/app/app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
const app = (function(){ // jshint ignore:line
'use strict';

let self = {};

// Common initialization function (to be called from each page)
self.initialize = function(){
jQuery('body').append(
'<div id="notification-message">' +
'<div class="padding">' +
'<div id="notification-message-close"></div>' +
'<div id="notification-message-header"></div>' +
'<div id="notification-message-body"></div>' +
'</div>' +
'</div>');

jQuery('#notification-message-close').click(function(){
jQuery('#notification-message').hide();
});

// After initialization, expose a common notification function
self.showNotification = function(header, text){
jQuery('#notification-message-header').text(header);
jQuery('#notification-message-body').text(text);
jQuery('#notification-message').slideDown('fast');
};
};

return self;
})();
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
/*
* Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license.
* See LICENSE in the project root for license information.
*/

// Helper based on Office UI Fabric dropdown, which hides the original 'select' dropdown and
// creates a "fake" dropdown that can be more easily styled across browsers.
// http://dev.office.com/fabric/components/dropdown
function useFabricDropdown (id) {
var $dropdownWrapper = $('#' + id),
$originalDropdown = $dropdownWrapper.children('.ms-Dropdown-select'),
$originalDropdownOptions = $originalDropdown.children('option'),
newDropdownTitle = '',
newDropdownItems = '',
newDropdownSource = '';

/** Go through the options to fill up newDropdownTitle and newDropdownItems. */
$originalDropdownOptions.each(function (index, option) {

/** If the option is selected, it should be the new dropdown's title. */
if (option.selected) {
newDropdownTitle = option.text;
}

/** Add this option to the list of items. */
newDropdownItems += '<li class="ms-Dropdown-item' + ( (option.disabled) ? ' is-disabled"' : '"' ) + '>' + option.text + '</li>';

});

/** Insert the replacement dropdown. */
newDropdownSource = '<span class="ms-Dropdown-title">' + newDropdownTitle + '</span><ul class="ms-Dropdown-items">' + newDropdownItems + '</ul>';
$dropdownWrapper.append(newDropdownSource);

function _openDropdown(evt) {
if (!$dropdownWrapper.hasClass('is-disabled')) {

/** First, let's close any open dropdowns on this page. */
$dropdownWrapper.find('.is-open').removeClass('is-open');

/** Stop the click event from propagating, which would just close the dropdown immediately. */
evt.stopPropagation();

/** Before opening, size the items list to match the dropdown. */
var dropdownWidth = $(this).parents(".ms-Dropdown").width();
$(this).next(".ms-Dropdown-items").css('width', dropdownWidth + 'px');

/** Go ahead and open that dropdown. */
$dropdownWrapper.toggleClass('is-open');
$('.ms-Dropdown').each(function(){
if ($(this)[0] !== $dropdownWrapper[0]) {
$(this).removeClass('is-open');
}
});

/** Temporarily bind an event to the document that will close this dropdown when clicking anywhere. */
$(document).bind("click.dropdown", function() {
$dropdownWrapper.removeClass('is-open');
$(document).unbind('click.dropdown');
});
}
}

/** Toggle open/closed state of the dropdown when clicking its title. */
$dropdownWrapper.on('click', '.ms-Dropdown-title', function(event) {
_openDropdown(event);
});

/** Keyboard accessibility */
$dropdownWrapper.on('keyup', function(event) {
var keyCode = event.keyCode || event.which;
// Open dropdown on enter or arrow up or arrow down and focus on first option
if (!$(this).hasClass('is-open')) {
if (keyCode === 13 || keyCode === 38 || keyCode === 40) {
_openDropdown(event);
if (!$(this).find('.ms-Dropdown-item').hasClass('is-selected')) {
$(this).find('.ms-Dropdown-item:first').addClass('is-selected');
}
}
}
else if ($(this).hasClass('is-open')) {
// Up arrow focuses previous option
if (keyCode === 38) {
if ($(this).find('.ms-Dropdown-item.is-selected').prev().siblings().size() > 0) {
$(this).find('.ms-Dropdown-item.is-selected').removeClass('is-selected').prev().addClass('is-selected');
}
}
// Down arrow focuses next option
if (keyCode === 40) {
if ($(this).find('.ms-Dropdown-item.is-selected').next().siblings().size() > 0) {
$(this).find('.ms-Dropdown-item.is-selected').removeClass('is-selected').next().addClass('is-selected');
}
}
// Enter to select item
if (keyCode === 13) {
if (!$dropdownWrapper.hasClass('is-disabled')) {

// Item text
var selectedItemText = $(this).find('.ms-Dropdown-item.is-selected').text();

$(this).find('.ms-Dropdown-title').html(selectedItemText);

/** Update the original dropdown. */
$originalDropdown.find("option").each(function(key, value) {
if (value.text === selectedItemText) {
$(this).prop('selected', true);
} else {
$(this).prop('selected', false);
}
});
$originalDropdown.change();

$(this).removeClass('is-open');
}
}
}

// Close dropdown on esc
if (keyCode === 27) {
$(this).removeClass('is-open');
}
});

/** Select an option from the dropdown. */
$dropdownWrapper.on('click', '.ms-Dropdown-item', function () {
if (!$dropdownWrapper.hasClass('is-disabled')) {

/** Deselect all items and select this one. */
$(this).siblings('.ms-Dropdown-item').removeClass('is-selected');
$(this).addClass('is-selected');

/** Update the replacement dropdown's title. */
$(this).parents().siblings('.ms-Dropdown-title').html($(this).text());

/** Update the original dropdown. */
var selectedItemText = $(this).text();
$originalDropdown.find("option").each(function(key, value) {
if (value.text === selectedItemText) {
$(this).prop('selected', true);
} else {
$(this).prop('selected', false);
}
});
$originalDropdown.change();
}
});
}
Loading