1
0
mirror of https://github.com/ascribe/onion.git synced 2024-12-22 09:23:13 +01:00

Refactor InjectInHeadMixin to be a util class instead

This commit is contained in:
Brett Sun 2015-11-09 14:32:14 +01:00
parent 3cde6eec95
commit 7c73b7fac7
3 changed files with 84 additions and 88 deletions

View File

@ -3,12 +3,13 @@
import React from 'react';
import Q from 'q';
import { escapeHTML } from '../../utils/general_utils';
import InjectInHeadMixin from '../../mixins/inject_in_head_mixin';
import Panel from 'react-bootstrap/lib/Panel';
import ProgressBar from 'react-bootstrap/lib/ProgressBar';
import AppConstants from '../../constants/application_constants.js';
import AppConstants from '../../constants/application_constants';
import { escapeHTML } from '../../utils/general_utils';
import { InjectInHeadUtils } from '../../utils/inject_utils';
/**
* This is the component that implements display-specific functionality.
@ -54,14 +55,12 @@ let Image = React.createClass({
preview: React.PropTypes.string.isRequired
},
mixins: [InjectInHeadMixin],
componentDidMount() {
this.inject('https://code.jquery.com/jquery-2.1.4.min.js')
InjectInHeadUtils.inject('https://code.jquery.com/jquery-2.1.4.min.js')
.then(() =>
Q.all([
this.inject(AppConstants.baseUrl + 'static/thirdparty/shmui/shmui.css'),
this.inject(AppConstants.baseUrl + 'static/thirdparty/shmui/jquery.shmui.js')
InjectInHeadUtils.inject(AppConstants.baseUrl + 'static/thirdparty/shmui/shmui.css'),
InjectInHeadUtils.inject(AppConstants.baseUrl + 'static/thirdparty/shmui/jquery.shmui.js')
]).then(() => { window.jQuery('.shmui-ascribe').shmui(); }));
},
@ -77,10 +76,8 @@ let Audio = React.createClass({
url: React.PropTypes.string.isRequired
},
mixins: [InjectInHeadMixin],
componentDidMount() {
this.inject(AppConstants.baseUrl + 'static/thirdparty/audiojs/audiojs/audio.min.js').then(this.ready);
InjectInHeadUtils.inject(AppConstants.baseUrl + 'static/thirdparty/audiojs/audiojs/audio.min.js').then(this.ready);
},
ready() {
@ -111,7 +108,7 @@ let Video = React.createClass({
* `false` if we failed to load the external library)
* 2) render the cover using the `<Image />` component (because libraryLoaded is null)
* 3) on `componentDidMount`, we load the external `css` and `js` resources using
* the `InjectInHeadMixin`, attaching a function to `Promise.then` to change
* the `InjectInHeadUtils`, attaching a function to `Promise.then` to change
* `state.libraryLoaded` to true
* 4) when the promise is succesfully resolved, we change `state.libraryLoaded` triggering
* a re-render
@ -129,16 +126,14 @@ let Video = React.createClass({
encodingStatus: React.PropTypes.number
},
mixins: [InjectInHeadMixin],
getInitialState() {
return { libraryLoaded: null, videoMounted: false };
},
componentDidMount() {
Q.all([
this.inject('//vjs.zencdn.net/4.12/video-js.css'),
this.inject('//vjs.zencdn.net/4.12/video.js')])
InjectInHeadUtils.inject('//vjs.zencdn.net/4.12/video-js.css'),
InjectInHeadUtils.inject('//vjs.zencdn.net/4.12/video.js')])
.then(() => this.setState({libraryLoaded: true}))
.fail(() => this.setState({libraryLoaded: false}));
},

View File

@ -1,71 +0,0 @@
'use strict';
import Q from 'q';
let mapAttr = {
link: 'href',
script: 'src'
};
let mapTag = {
js: 'script',
css: 'link'
};
let InjectInHeadMixin = {
/**
* Provide functions to inject `<script>` and `<link>` in `<head>`.
* Useful when you have to load a huge external library and
* you don't want to embed everything inside the build file.
*/
isPresent(tag, src) {
let attr = mapAttr[tag];
let query = `head > ${tag}[${attr}="${src}"]`;
return document.querySelector(query);
},
injectTag(tag, src) {
return Q.Promise((resolve, reject) => {
if (InjectInHeadMixin.isPresent(tag, src)) {
resolve();
} else {
let attr = mapAttr[tag];
let element = document.createElement(tag);
if (tag === 'script') {
element.onload = () => resolve();
element.onerror = () => reject();
} else {
resolve();
}
document.head.appendChild(element);
element[attr] = src;
if (tag === 'link') {
element.rel = 'stylesheet';
}
}
});
},
injectStylesheet(src) {
return InjectInHeadMixin.injectTag('link', src);
},
injectScript(src) {
return InjectInHeadMixin.injectTag('source', src);
},
inject(src) {
let ext = src.split('.').pop();
let tag = mapTag[ext];
if (!tag) {
throw new Error(`Cannot inject ${src} in the DOM, cannot guess the tag name from extension "${ext}". Valid extensions are "js" and "css".`);
}
return InjectInHeadMixin.injectTag(tag, src);
}
};
export default InjectInHeadMixin;

72
js/utils/inject_utils.js Normal file
View File

@ -0,0 +1,72 @@
'use strict';
import Q from 'q';
let mapAttr = {
link: 'href',
script: 'src'
};
let mapTag = {
js: 'script',
css: 'link'
};
function injectTag(tag, src) {
return Q.Promise((resolve, reject) => {
if (isPresent(tag, src)) {
resolve();
} else {
let attr = mapAttr[tag];
let element = document.createElement(tag);
if (tag === 'script') {
element.onload = () => resolve();
element.onerror = () => reject();
} else {
resolve();
}
document.head.appendChild(element);
element[attr] = src;
if (tag === 'link') {
element.rel = 'stylesheet';
}
}
});
}
function isPresent(tag, src) {
let attr = mapAttr[tag];
let query = `head > ${tag}[${attr}="${src}"]`;
return document.querySelector(query);
}
function injectStylesheet(src) {
return injectTag('link', src);
}
function injectScript(src) {
return injectTag('source', src);
}
function inject(src) {
let ext = src.split('.').pop();
let tag = mapTag[ext];
if (!tag) {
throw new Error(`Cannot inject ${src} in the DOM, cannot guess the tag name from extension "${ext}". Valid extensions are "js" and "css".`);
}
return injectTag(tag, src);
}
export const InjectInHeadUtils = {
/**
* Provide functions to inject `<script>` and `<link>` in `<head>`.
* Useful when you have to load a huge external library and
* you don't want to embed everything inside the build file.
*/
isPresent,
injectStylesheet,
injectScript,
inject
};