🚀 Socket Launch Week Day 5:Introducing Repository Access Permissions and Custom Roles.Learn more
Sign In

view-binary-element

Package Overview
Dependencies
Maintainers
1
Versions
5
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

view-binary-element - npm Package Compare versions

Comparing version
0.0.1
to
0.0.2
+26
CHANGELOG.md
# Change Log
## [0.0.2](https://github.com/grtjn/view-binary-element/tree/0.0.2) (2018-06-07)
[Full Changelog](https://github.com/grtjn/view-binary-element/compare/0.0.1...0.0.2)
**Implemented enhancements:**
- Add HTML Imports polyfill for demo site [\#6](https://github.com/grtjn/view-binary-element/issues/6)
- Document how to use in AngularJS [\#12](https://github.com/grtjn/view-binary-element/issues/12)
- Gracefull decay for lack of Shadow DOM support [\#7](https://github.com/grtjn/view-binary-element/issues/7)
**Fixed bugs:**
- HTML imports is removed from webcomponents in v2 [\#11](https://github.com/grtjn/view-binary-element/issues/11)
- currentScript can be null \(in Chrome\) [\#10](https://github.com/grtjn/view-binary-element/issues/10)
## [0.0.1](https://github.com/grtjn/view-binary-element/tree/0.0.1) (2018-03-22)
**Implemented enhancements:**
- Publish demo site on github io [\#3](https://github.com/grtjn/view-binary-element/issues/3)
- Publish initial version on npm [\#2](https://github.com/grtjn/view-binary-element/issues/2)
- Publish initial version on bower [\#1](https://github.com/grtjn/view-binary-element/issues/1)
\* *This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)*
var functionLogger = {};
functionLogger.log = true;//Set this to false to disable logging
/**
* Gets a function that when called will log information about itself if logging is turned on.
*
* @param func The function to add logging to.
* @param name The name of the function.
*
* @return A function that will perform logging and then call the function.
*/
functionLogger.getLoggableFunction = function(func, name, ns) {
return function() {
if (functionLogger.log) {
var logText = (ns ? (ns + '.') : '') + name + '(';
for (var i = 0; i < arguments.length; i++) {
if (i > 0) {
logText += ', ';
}
logText += arguments[i];
}
logText += ');';
console.log(logText);
}
return func.apply(this, arguments);
}
};
/**
* After this is called, all direct children of the provided namespace object that are
* functions will log their name as well as the values of the parameters passed in.
*
* @param namespaceObject The object whose child functions you'd like to add logging to.
*/
functionLogger.addLoggingToNamespace = function(namespaceObject, ns){
if (functionLogger.log) {
for(var name in namespaceObject){
var potentialFunction = namespaceObject[name];
if(Object.prototype.toString.call(potentialFunction) === '[object Function]'){
namespaceObject[name] = functionLogger.getLoggableFunction(potentialFunction, name, ns);
}
}
}
};
+1
-1
{
"name": "view-binary-element",
"version": "0.0.1",
"version": "0.0.2",
"description": "Native Web Component for previewing a few common types of binary files",

@@ -5,0 +5,0 @@ "main": [

@@ -17,3 +17,11 @@ <!doctype html>

<![endif]-->
<link rel="import" href="https://raw.githubusercontent.com/grtjn/view-binary-element/master/view-binary.html">
<link rel="import" href="https://cdn.rawgit.com/grtjn/view-binary-element/master/view-binary.html">
<!-- For local debugging:
- replace import above with import below
- run something like `python -m SimpleHTTPServer 8888` from project root
- open http://localhost:8888/docs/
<link rel="import" href="../view-binary.html">
-->
<style>

@@ -69,3 +77,4 @@ view-binary {

</view-binary>
<script src="https://cdn.rawgit.com/webcomponents/webcomponentsjs/v1.2.0/webcomponents-hi.js" type="text/javascript" defer></script>
</body>
</html>
{
"name": "view-binary-element",
"version": "0.0.1",
"version": "0.0.2",
"description": "Native Web Component for previewing a few common types of binary files",

@@ -5,0 +5,0 @@ "dependencies": {},

+128
-0
# view-binary-element
Native Web Component for previewing a few common types of binary files
This is essentially a refactored version of https://github.com/grtjn/view-file-ng to eliminate AngularJS. Not yet as feature rich though.
Disclaimer: Work in Progress, and not tested in production. Feedback welcome though.
Check https://caniuse.com/ to verify how well Web Components is covered by current browsers. This component uses Custom Elements v1, (optionally) HTML Imports, HTML Templates, Shadow DOM v1 (gracefull decay would be possible).
## Installation
### CDN and polyfill
Simplest way:
<link rel="import" href="https://cdn.rawgit.com/grtjn/view-binary-element/master/view-binary.html">
Likely together with this polyfill:
<script src="https://cdn.rawgit.com/webcomponents/webcomponentsjs/v1.2.0/webcomponents-hi.js" type="text/javascript" defer></script>
### NPM and html-loader
This component is also published on npm:
npm install --save view-binary-element
Potentially combined with something like:
<%= require('html-loader!../node_modules/view-binary-element/view-binary.html') %>
### Bower, wiredep, and gulp
This component is also published on bower:
bower install --save view-binary-element
You can combine that with gulp and wiredep with something like:
.pipe(gulpWiredep({
fileTypes: {
html: {
block: /(([ \t]*)<!--\s*bower:*(\S*)\s*-->)(\n|\r|.)*?(<!--\s*endbower\s*-->)/gi,
detect: {
js: /<script.*src=['"]([^'"]+)/gi,
css: /<link.*href=['"]([^'"]+)/gi,
html: /<link.*href=['"]([^'"]+)/gi
},
replace: {
js: '<script src="{{filePath}}"></script>',
css: '<link rel="stylesheet" href="{{filePath}}">',
html: '<link rel="import" href="{{filePath}}">'
}
}
}
}))
Add this to your index.html:
<!-- bower:html -->
<link rel="import" href="/bower_components/view-binary-element/view-binary.html">
<!-- endbower -->
<!-- @exclude -->
<script src="https://cdn.rawgit.com/webcomponents/webcomponentsjs/v1.2.0/webcomponents-hi.js" type="text/javascript" defer></script>
<!-- @endexclude -->
This relies on the html-import polyfill loaded from CDN. If you prefer not to rely on that, or if your tooling builds minified versions of everything, you can include the html similarly to html-loader mentioned above in NPM, and strip off the polyfill using gulp-preprocessor roughly like this:
.pipe(gulpReplace(/<link rel="import" href="([^"]+)">/g, '<!-- @include ../$1 -->'))
.pipe(gulpPreprocess())
## Usage
Example:
<view-binary class="audio" src="data/sample-music.mp3" type="audio/mpeg" title="sample-music.mp3">
<a slot="fallback" href="data/sample-music.mp3" target="_blank" download>Download sample-music.mp3</a>
</view-binary>
Does not emit events.
### Plaing HTML and JavaScript
- Assumes CDN and polyfill installation
- In your html:
<style>
view-binary {
display: block;
height: 300px;
}
view-binary.audio {
height: 32px;
}
</style>
<view-binary class="audio" src="data/sample-music.mp3" type="audio/mpeg" title="sample-music.mp3">
<a slot="fallback" href="data/sample-music.mp3" target="_blank" download>Download sample-music.mp3</a>
</view-binary>
### Vue.js
- Import or include the web component in your index.html (see for instance NPM and html-loader installation)
- Add `view-binary` to ignoreElements to stop it from squeaking:
Vue.config.ignoredElements = ["view-binary"];
- Use it in any component:
<view-binary :src="viewUri" :type="contentType" :title="fileName">
<a slot="fallback" class="btn btn-default" :href="downloadUri" target="_blank" download>Download {{ fileName }}</a>
</view-binary>
### AngularJS
- Assumes Bower, wiredep, and gulp installation
- In your html template:
<view-binary src="{{viewUri}}" type="{{contentType}}" title="{{fileName}}">
<a slot="fallback" class="btn btn-default" href="{{downloadUri}}" target="_blank" download>Download {{ fileName }}</a>
</view-binary>
## Test locally
- Uncomment the local import line in docs/index.html
- Run something like `python -m SimpleHTTPServer 8888` from project root
- Open http://localhost:8888/docs/

@@ -14,2 +14,42 @@ <template id="view-binary-template">

}
/* fontawesome (copied because of Shadow DOM isolation) */
.fa {
display: inline-block;
font: normal normal normal 14px/1 FontAwesome;
font-size: inherit;
text-rendering: auto;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.fa-refresh:before {
content: "\F021";
}
.fa-refresh[hidden]:before {
content: "";
}
.fa-spin {
-webkit-animation: fa-spin 2s infinite linear;
animation: fa-spin 2s infinite linear;
}
@-webkit-keyframes fa-spin {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(359deg);
transform: rotate(359deg);
}
}
@keyframes fa-spin {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(359deg);
transform: rotate(359deg);
}
}
</style>

@@ -19,3 +59,3 @@ <div class="view-binary">

<slot name="loading">
Loading... <i class="fa fa-spinner fa-spin"></i>
Loading... <i class="fa fa-refresh fa-spin"></i>
</slot>

@@ -40,301 +80,242 @@ </div>

<script>
// Usage:
// <view-binary src="" type="" title="">
// <a class="btn btn-default" href="" target="_blank" download>Download</a>
// </view-binary>
// Usage:
// <view-binary src="" type="" title="">
// <a class="btn btn-default" href="" target="_blank" download>Download</a>
// </view-binary>
(function() {
var functionLogger = {};
(function() {
functionLogger.log = true;//Set this to false to disable logging
// Make sure to look inside this html fragement (in case of true html import)
const doc = document.currentScript ? (document.currentScript.ownerDocument || document) : document;
/**
* Gets a function that when called will log information about itself if logging is turned on.
*
* @param func The function to add logging to.
* @param name The name of the function.
*
* @return A function that will perform logging and then call the function.
*/
functionLogger.getLoggableFunction = function(func, name, ns) {
return function() {
if (functionLogger.log) {
var logText = (ns ? (ns + '.') : '') + name + '(';
// Inspired by https://developers.google.com/web/fundamentals/web-components/
for (var i = 0; i < arguments.length; i++) {
if (i > 0) {
logText += ', ';
}
logText += arguments[i];
}
logText += ');';
class ViewBinary extends HTMLElement {
console.log(logText);
}
return func.apply(this, arguments);
static get observedAttributes() {
return ["src", "type", "title"];
}
};
/**
* After this is called, all direct children of the provided namespace object that are
* functions will log their name as well as the values of the parameters passed in.
*
* @param namespaceObject The object whose child functions you'd like to add logging to.
*/
functionLogger.addLoggingToNamespace = function(namespaceObject, ns){
if (functionLogger.log) {
for(var name in namespaceObject){
var potentialFunction = namespaceObject[name];
/**
* The element's constructor is run anytime a new instance is created.
* Instances are created either by parsing HTML, calling
* `document.createElement('view-binary')`, or calling `new ViewBinary()`.
* The construtor is a good place to create shadow DOM, though you should
* avoid touching any attributes or light DOM children as they may not
* be available yet.
*/
constructor() {
// always call super first
super();
if(Object.prototype.toString.call(potentialFunction) === '[object Function]'){
namespaceObject[name] = functionLogger.getLoggableFunction(potentialFunction, name, ns);
}
}
}
};
// initialize private properties
this._src = undefined;
this._type = undefined;
this._title = undefined;
// Inspired by https://developers.google.com/web/fundamentals/web-components/
// initialize template placeholders
this.$loading = undefined;
this.$viewer = undefined;
this.$audio = undefined;
this.$video = undefined;
this.$picture = undefined;
this.$object = undefined;
class ViewBinary extends HTMLElement {
// make sure private methods are properly bound to 'this'
this._upgradeProperty = this._upgradeProperty.bind(this);
this._initialize = this._initialize.bind(this);
this._updateRendering = this._updateRendering.bind(this);
}
static get observedAttributes() {
return ["src", "type", "title"];
}
/**
* `connectedCallback()` fires when the element is inserted into the DOM.
* It's a good place to set the initial internal state,
* and install event listeners.
*/
connectedCallback() {
// initialize template
this._initialize();
}
/**
* The element's constructor is run anytime a new instance is created.
* Instances are created either by parsing HTML, calling
* `document.createElement('view-binary')`, or calling `new ViewBinary()`.
* The construtor is a good place to create shadow DOM, though you should
* avoid touching any attributes or light DOM children as they may not
* be available yet.
*/
constructor() {
// always call super first
super();
/**
* `disconnectedCallback()` fires when the element is removed from the DOM.
* It's a good place to do clean up work like releasing references and
* removing event listeners.
*/
disconnectedCallback() {
this._destroy();
}
// initialize private properties
this._src = undefined;
this._type = undefined;
this._title = undefined;
/**
* `adoptedCallback()`: Invoked when the custom element is moved to a new document.
*/
adoptedCallback() {
this._updateRendering();
}
// initialize template placeholders
this.$loading = undefined;
this.$viewer = undefined;
this.$audio = undefined;
this.$video = undefined;
this.$picture = undefined;
this.$object = undefined;
/**
* `attributeChangedCallback()` is called when any of the attributes in the
* `observedAttributes` array are changed. It's a good place to handle
* side effects.
*/
attributeChangedCallback(name, oldValue, newValue) {
switch (name) {
case "src" : {
this._src = newValue;
break;
}
case "type": {
this._type = newValue;
break;
}
case "title": {
this._title = newValue;
break;
}
}
// make sure private methods are properly bound to 'this'
this._upgradeProperty = this._upgradeProperty.bind(this);
this._initialize = this._initialize.bind(this);
this._updateRendering = this._updateRendering.bind(this);
this._updateRendering();
}
// trace logging for debug purposes
if (functionLogger.log) {
this.connectedCallback = this.connectedCallback.bind(this);
this.disconnectedCallback = this.disconnectedCallback.bind(this);
this.adoptedCallback = this.adoptedCallback.bind(this);
this.attributeChangedCallback = this.attributeChangedCallback.bind(this);
// Programmatic access to custom element properties
// Note: this loops back into attributeChangedCallback
set src(value) {
if (value)
this.setAttribute('src', value);
else
this.removeAttribute('src');
}
functionLogger.addLoggingToNamespace(this, 'ViewBinary.this');
}
get src() {
return this._src;
}
/**
* `connectedCallback()` fires when the element is inserted into the DOM.
* It's a good place to set the initial internal state,
* and install event listeners.
*/
connectedCallback() {
// initialize template
this._initialize();
}
set type(value) {
if (value)
this.setAttribute('type', value);
else
this.removeAttribute('type');
}
/**
* `disconnectedCallback()` fires when the element is removed from the DOM.
* It's a good place to do clean up work like releasing references and
* removing event listeners.
*/
disconnectedCallback() {
this._destroy();
}
get type() {
return this._type;
}
/**
* `adoptedCallback()`: Invoked when the custom element is moved to a new document.
*/
adoptedCallback() {
this._updateRendering();
}
set title(value) {
if (value)
this.setAttribute('title', value);
else
this.removeAttribute('title');
}
/**
* `attributeChangedCallback()` is called when any of the attributes in the
* `observedAttributes` array are changed. It's a good place to handle
* side effects.
*/
attributeChangedCallback(name, oldValue, newValue) {
switch (name) {
case "src" : {
this._src = newValue;
break;
}
case "type": {
this._type = newValue;
break;
}
case "title": {
this._title = newValue;
break;
}
get title() {
return this._title;
}
this._updateRendering();
}
// initialize contents of custom element
_initialize() {
if (this.attachShadow) {
// enable Shadow DOM
this.attachShadow({mode: 'open'});
} else {
// instant stub polyfill for shadowRoot
this.shadowRoot = this;
}
// Programmatic access to custom element properties
// Note: this loops back into attributeChangedCallback
set src(value) {
if (value)
this.setAttribute('src', value);
else
this.removeAttribute('src');
}
// get and append template
const template = doc
.getElementById("view-binary-template")
.content
.cloneNode(true);
this.shadowRoot.appendChild(template);
get src() {
return this._src;
}
// get placeholders
this.$loading = this.shadowRoot.querySelector("#view-binary-loading");
this.$viewer = this.shadowRoot.querySelector("#view-binary-viewer");
this.$audio = this.shadowRoot.querySelector("#view-binary-audio");
this.$video = this.shadowRoot.querySelector("#view-binary-video");
this.$picture = this.shadowRoot.querySelector("#view-binary-picture");
this.$object = this.shadowRoot.querySelector("#view-binary-object");
set type(value) {
if (value)
this.setAttribute('type', value);
else
this.removeAttribute('type');
}
// A user may set a property on an _instance_ of an element,
// before its prototype has been connected to this class.
// The `_upgradeProperty()` method will check for any instance properties
// and run them through the proper class setters.
this._upgradeProperty("src");
this._upgradeProperty("type");
this._upgradeProperty("title");
get type() {
return this._type;
}
// initialize rendering
this._updateRendering();
set title(value) {
if (value)
this.setAttribute('title', value);
else
this.removeAttribute('title');
}
// hook up event listeners
//this.$viewer.addEventListener('click', this.onViewerClick);
}
get title() {
return this._title;
}
_destroy() {
// remove event listeners
//this.$viewer.removeEventListener('click', this.onViewerClick);
}
// initialize contents of custom element
_initialize() {
// enable Shadow DOM
this.attachShadow({mode: 'open'});
// trace logging for debug purposes
functionLogger.addLoggingToNamespace(this.shadowRoot, 'ViewBinary.this.shadowRoot');
// Make sure to look inside this html fragement (in case of true html import)
const doc = document.currentScript.ownerDocument;
// get and append template
const template = doc
.getElementById("view-binary-template")
.content
.cloneNode(true);
this.shadowRoot.appendChild(template);
// get placeholders
this.$loading = this.shadowRoot.querySelector("#view-binary-loading");
this.$viewer = this.shadowRoot.querySelector("#view-binary-viewer");
this.$audio = this.shadowRoot.querySelector("#view-binary-audio");
this.$video = this.shadowRoot.querySelector("#view-binary-video");
this.$picture = this.shadowRoot.querySelector("#view-binary-picture");
this.$object = this.shadowRoot.querySelector("#view-binary-object");
// A user may set a property on an _instance_ of an element,
// before its prototype has been connected to this class.
// The `_upgradeProperty()` method will check for any instance properties
// and run them through the proper class setters.
this._upgradeProperty("src");
this._upgradeProperty("type");
this._upgradeProperty("title");
// initialize rendering
this._updateRendering();
// hook up event listeners
//this.$viewer.addEventListener('click', this.onViewerClick);
}
_destroy() {
// remove event listeners
//this.$viewer.removeEventListener('click', this.onViewerClick);
}
// capture property values from unupgraded instances, and delete them
// so they do not shadow the custom element's own property setter.
_upgradeProperty(prop) {
if (this.hasOwnProperty(prop)) {
let value = this[prop];
delete this[prop];
this[prop] = value;
// capture property values from unupgraded instances, and delete them
// so they do not shadow the custom element's own property setter.
_upgradeProperty(prop) {
if (this.hasOwnProperty(prop)) {
let value = this[prop];
delete this[prop];
this[prop] = value;
}
}
}
// update rendering of placeholders
_updateRendering() {
if (this.shadowRoot) {
if (this._src !== undefined && this._type !== undefined) {
this.$loading.hidden = true;
this.$viewer.hidden = false;
// update rendering of placeholders
_updateRendering() {
if (this.shadowRoot) {
if (this.src !== undefined && this.type !== undefined) {
this.$loading.hidden = true;
this.$viewer.hidden = false;
this.$audio.hidden = true;
this.$video.hidden = true;
this.$picture.hidden = true;
this.$object.hidden = true;
this.$audio.hidden = true;
this.$video.hidden = true;
this.$picture.hidden = true;
this.$object.hidden = true;
// there can be only one fallback slot, move it around
var slot = this.shadowRoot.querySelector("#fallback");
slot.parentNode.removeChild(slot);
// there can be only one fallback slot, move it around
var slot = this.shadowRoot.querySelector("#fallback");
slot.parentNode.removeChild(slot);
if (this._type.match(/^audio\//)) {
this.$audio.hidden = false;
this.$audio.setAttribute("src", this._src);
this.$audio.setAttribute("title", this._title || "");
this.$audio.appendChild(slot);
} else if (this._type.match(/^video\//)) {
this.$video.hidden = false;
this.$video.setAttribute("src", this._src);
this.$video.setAttribute("title", this._title || "");
this.$video.appendChild(slot);
} else if (this._type.match(/^image\//)) {
this.$picture.hidden = false;
this.$picture.firstElementChild.setAttribute("src", this._src);
this.$picture.firstElementChild.setAttribute("alt", this._title || "");
this.$picture.appendChild(slot);
if (this.type.match(/^audio\//)) {
this.$audio.hidden = false;
this.$audio.setAttribute("src", this.src);
this.$audio.setAttribute("title", this.title || "");
this.$audio.appendChild(slot);
} else if (this.type.match(/^video\//)) {
this.$video.hidden = false;
this.$video.setAttribute("src", this.src);
this.$video.setAttribute("title", this.title || "");
this.$video.appendChild(slot);
} else if (this.type.match(/^image\//)) {
this.$picture.hidden = false;
this.$picture.firstElementChild.setAttribute("src", this.src);
this.$picture.firstElementChild.setAttribute("alt", this.title || "");
this.$picture.appendChild(slot);
} else {
this.$object.hidden = false;
this.$object.setAttribute("data", this.src);
this.$object.setAttribute("type", this.type);
this.$object.setAttribute("title", this.title || "");
this.$object.appendChild(slot);
}
} else {
this.$object.hidden = false;
this.$object.setAttribute("data", this._src);
this.$object.setAttribute("type", this._type);
this.$object.setAttribute("title", this._title || "");
this.$object.appendChild(slot);
this.$loading.hidden = false;
this.$viewer.hidden = true;
}
} else {
this.$loading.hidden = false;
this.$viewer.hidden = true;
}
}
}
};
};
functionLogger.addLoggingToNamespace(ViewBinary, 'ViewBinary');
// declare the webcomponent
window.customElements.define("view-binary", ViewBinary);
// declare the webcomponent
window.customElements.define("view-binary", ViewBinary);
})();
})();
</script>