Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Refactor embedding functions, create embed and embed-requirejs bundles.
- Loading branch information
1 parent
8589114
commit 7eed820
Showing
11 changed files
with
209 additions
and
143 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
// Copyright (c) Jupyter Development Team. | ||
// Distributed under the terms of the Modified BSD License. | ||
|
||
import { | ||
renderInlineWidgets | ||
} from './embedlib'; | ||
|
||
|
||
// Populate the requirejs cache with local versions of @jupyter-widgets/base, | ||
// @jupyter-widgets/controls, @jupyter-widgets/html-manager. These are externals | ||
// when compiled with webpack. | ||
require('./base'); | ||
require('./controls'); | ||
require('./index'); | ||
|
||
/** | ||
* Load a package using requirejs and return a promise | ||
* | ||
* @param pkg Package name or names to load | ||
*/ | ||
let requirePromise = function(pkg: string | string[]): Promise<any> { | ||
return new Promise((resolve, reject) => { | ||
let require = (window as any).require; | ||
if (require === undefined) { | ||
reject("Requirejs is needed, please ensure it is loaded on the page."); | ||
} else { | ||
require(pkg, resolve, reject); | ||
} | ||
}); | ||
} | ||
|
||
function requireLoader(moduleName: string, moduleVersion: string) { | ||
return requirePromise([`${moduleName}.js`]).catch((err) => { | ||
let failedId = err.requireModules && err.requireModules[0]; | ||
if (failedId) { | ||
console.log(`Falling back to unpkg.com for ${moduleName}@${moduleVersion}`); | ||
return requirePromise([`https://unpkg.com/${moduleName}@${moduleVersion}/dist/index.js`]); | ||
} | ||
}); | ||
} | ||
|
||
/** | ||
* Render widgets in a given element. | ||
* | ||
* @param element (default document.documentElement) The element containing widget state and views. | ||
*/ | ||
export | ||
function renderWidgets(element = document.documentElement) { | ||
requirePromise(['@jupyter-widgets/html-manager']).then((htmlmanager) => { | ||
let managerFactory = () => { | ||
return new htmlmanager.HTMLManager({loader: requireLoader}); | ||
} | ||
renderInlineWidgets(managerFactory, element); | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,115 +1,18 @@ | ||
// Copyright (c) Jupyter Development Team. | ||
// Distributed under the terms of the Modified BSD License. | ||
|
||
import 'font-awesome/css/font-awesome.css'; | ||
import '@phosphor/widgets/style/index.css'; | ||
import '@jupyter-widgets/controls/css/widgets.built.css'; | ||
|
||
// WidgetModel is *just* used as a typing below | ||
import { | ||
WidgetModel | ||
} from '@jupyter-widgets/base'; | ||
|
||
// Populate the requirejs cache with local versions of @jupyter-widgets/base, | ||
// @jupyter-widgets/controls, @jupyter-widgets/html-manager | ||
require('./base'); | ||
require('./controls'); | ||
require('./index'); | ||
|
||
/** | ||
* Load a package using requirejs and return a promise | ||
* | ||
* @param pkg Package name or names to load | ||
*/ | ||
let requirePromise = function(pkg: string | string[]) { | ||
return new Promise((resolve, reject) => { | ||
let require = (window as any).require; | ||
if (require === undefined) { | ||
reject("Requirejs is needed to run the Jupyter Widgets html manager"); | ||
} else { | ||
require(pkg, resolve, reject); | ||
} | ||
}); | ||
} | ||
|
||
// Element.prototype.matches polyfill for IE | ||
// See https://developer.mozilla.org/en-US/docs/Web/API/Element/matches | ||
if (!Element.prototype.matches) { | ||
Element.prototype.matches = | ||
Element.prototype.msMatchesSelector || | ||
Element.prototype.webkitMatchesSelector; | ||
} | ||
HTMLManager | ||
} from './index'; | ||
|
||
// Load json schema validator | ||
var Ajv = require('ajv'); | ||
var widget_state_schema = require('@jupyter-widgets/schema').v2.state; | ||
var widget_view_schema = require('@jupyter-widgets/schema').v2.view; | ||
|
||
let ajv = new Ajv() | ||
let model_validate = ajv.compile(widget_state_schema); | ||
let view_validate = ajv.compile(widget_view_schema); | ||
|
||
/** | ||
* Render the inline widgets inside a DOM element. | ||
* | ||
* @param element (default document.documentElement) The document element in which to process for widget state. | ||
*/ | ||
export | ||
function renderInlineWidgets(element: HTMLElement = document.documentElement) { | ||
let tags = element.querySelectorAll('script[type="application/vnd.jupyter.widget-state+json"]'); | ||
for (let i=0; i!=tags.length; ++i) { | ||
renderManager(element, JSON.parse(tags[i].innerHTML)); | ||
} | ||
} | ||
|
||
/** | ||
* Create a widget manager for a given widget state. | ||
* | ||
* @param element The DOM element to search for widget view state script tags | ||
* @param widgetState The widget manager state | ||
* | ||
* #### Notes | ||
* | ||
* Widget view state should be in script tags with type | ||
* "application/vnd.jupyter.widget-view+json". Any such script tag containing a | ||
* model id the manager knows about is replaced with a rendered view. | ||
* Additionally, if the script tag has a prior img sibling with class | ||
* 'jupyter-widget', then that img tag is deleted. | ||
*/ | ||
function renderManager(element, widgetState) { | ||
(window as any).require(['@jupyter-widgets/html-manager'], (htmlmanager) => { | ||
let valid = model_validate(widgetState); | ||
if (!valid) { | ||
console.error('Model state has errors.', model_validate.errors); | ||
} | ||
let manager = new htmlmanager.HTMLManager(); | ||
manager.set_state(widgetState).then(function(models) { | ||
let tags = element.querySelectorAll('script[type="application/vnd.jupyter.widget-view+json"]'); | ||
for (let i=0; i!=tags.length; ++i) { | ||
let viewtag = tags[i]; | ||
let widgetViewObject = JSON.parse(viewtag.innerHTML); | ||
let valid = view_validate(widgetViewObject); | ||
if (!valid) { | ||
console.error('View state has errors.', view_validate.errors); | ||
} | ||
let model_id = widgetViewObject.model_id; | ||
// Find the model id in the models. We should use .find, but IE | ||
// doesn't support .find | ||
let model = models.filter( (item : WidgetModel) => { | ||
return item.model_id == model_id; | ||
})[0]; | ||
if (model !== undefined) { | ||
if (viewtag.previousElementSibling && | ||
viewtag.previousElementSibling.matches('img.jupyter-widget')) { | ||
viewtag.parentElement.removeChild(viewtag.previousElementSibling); | ||
} | ||
let widgetTag = document.createElement('div'); | ||
widgetTag.className = 'widget-subarea'; | ||
viewtag.parentElement.insertBefore(widgetTag, viewtag); | ||
manager.display_model(undefined, model, { el : widgetTag }); | ||
} | ||
} | ||
}); | ||
import { | ||
renderInlineWidgets | ||
} from './embedlib'; | ||
|
||
// Render the widgets that we can | ||
if (!(window as any)._jupyter_widget_embedder) { | ||
(window as any)._jupyter_widget_embedder = true; | ||
window.addEventListener('load', () => { | ||
renderInlineWidgets(() => new HTMLManager()) | ||
}); | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
// Copyright (c) Jupyter Development Team. | ||
// Distributed under the terms of the Modified BSD License. | ||
|
||
import 'font-awesome/css/font-awesome.css'; | ||
import '@phosphor/widgets/style/index.css'; | ||
import '@jupyter-widgets/controls/css/widgets.built.css'; | ||
|
||
/* Used just for the typing */ | ||
import { | ||
HTMLManager | ||
} from './index'; | ||
|
||
// Load json schema validator | ||
var Ajv = require('ajv'); | ||
var widget_state_schema = require('@jupyter-widgets/schema').v2.state; | ||
var widget_view_schema = require('@jupyter-widgets/schema').v2.view; | ||
|
||
let ajv = new Ajv() | ||
let model_validate = ajv.compile(widget_state_schema); | ||
let view_validate = ajv.compile(widget_view_schema); | ||
|
||
/** | ||
* Render the inline widgets inside a DOM element. | ||
* | ||
* @param managerFactory A function that returns a new HTMLManager | ||
* @param element (default document.documentElement) The document element in which to process for widget state. | ||
*/ | ||
export | ||
function renderInlineWidgets(managerFactory: () => HTMLManager, element: HTMLElement = document.documentElement) { | ||
let tags = element.querySelectorAll('script[type="application/vnd.jupyter.widget-state+json"]'); | ||
for (let i=0; i!=tags.length; ++i) { | ||
renderManager(element, JSON.parse(tags[i].innerHTML), managerFactory); | ||
} | ||
} | ||
|
||
/** | ||
* Create a widget manager for a given widget state. | ||
* | ||
* @param element The DOM element to search for widget view state script tags | ||
* @param widgetState The widget manager state | ||
* | ||
* #### Notes | ||
* | ||
* Widget view state should be in script tags with type | ||
* "application/vnd.jupyter.widget-view+json". Any such script tag containing a | ||
* model id the manager knows about is replaced with a rendered view. | ||
* Additionally, if the script tag has a prior img sibling with class | ||
* 'jupyter-widget', then that img tag is deleted. | ||
*/ | ||
function renderManager(element: HTMLElement, widgetState: any, managerFactory: () => HTMLManager) { | ||
let valid = model_validate(widgetState); | ||
if (!valid) { | ||
console.error('Model state has errors.', model_validate.errors); | ||
} | ||
let manager = managerFactory(); | ||
manager.set_state(widgetState).then(function(models) { | ||
let tags = element.querySelectorAll('script[type="application/vnd.jupyter.widget-view+json"]'); | ||
for (let i=0; i!=tags.length; ++i) { | ||
let viewtag = tags[i]; | ||
let widgetViewObject = JSON.parse(viewtag.innerHTML); | ||
let valid = view_validate(widgetViewObject); | ||
if (!valid) { | ||
console.error('View state has errors.', view_validate.errors); | ||
} | ||
let model_id: string = widgetViewObject.model_id; | ||
// Find the model id in the models. We should use .find, but IE | ||
// doesn't support .find | ||
let model = models.filter( (item) => { | ||
return item.model_id == model_id; | ||
})[0]; | ||
if (model !== undefined) { | ||
let prev = viewtag.previousElementSibling; | ||
if (prev && prev.tagName === 'img' && prev.classList.contains('jupyter-widget')) { | ||
viewtag.parentElement.removeChild(prev); | ||
} | ||
let widgetTag = document.createElement('div'); | ||
widgetTag.className = 'widget-subarea'; | ||
viewtag.parentElement.insertBefore(widgetTag, viewtag); | ||
manager.display_model(undefined, model, { el : widgetTag }); | ||
} | ||
} | ||
}); | ||
} |
Oops, something went wrong.