mirror of
https://github.com/openSUSE/osem.git
synced 2026-08-13 19:54:02 +00:00
Get off off rails-assets
Just moving the things we currently use (and should drop in the ASAP) to vendor/assets
This commit is contained in:
parent
9fd0807a9a
commit
b6560dbb34
659 changed files with 129299 additions and 67 deletions
114
vendor/assets/javascripts/holderjs/gulpfile.js
vendored
Normal file
114
vendor/assets/javascripts/holderjs/gulpfile.js
vendored
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
var gulp = require('gulp');
|
||||
var concat = require('gulp-concat');
|
||||
var uglify = require('gulp-uglify');
|
||||
var header = require('gulp-header');
|
||||
var jshint = require('gulp-jshint');
|
||||
var todo = require('gulp-todo');
|
||||
var gulputil = require('gulp-util');
|
||||
var replace = require('gulp-replace');
|
||||
var webpack = require('webpack-stream');
|
||||
var beautify = require('gulp-jsbeautifier');
|
||||
var rename = require('gulp-rename');
|
||||
|
||||
var moment = require('moment');
|
||||
var pkg = require('./package.json');
|
||||
|
||||
var banner =
|
||||
'/*!\n\n' +
|
||||
'<%= pkg.officialName %> - <%= pkg.summary %>\nVersion <%= pkg.version %>+<%= build %>\n' +
|
||||
'\u00A9 <%= year %> <%= pkg.author.name %> - <%= pkg.author.url %>\n\n' +
|
||||
'Site: <%= pkg.homepage %>\n' +
|
||||
'Issues: <%= pkg.bugs.url %>\n' +
|
||||
'License: <%= pkg.license %>\n\n' +
|
||||
'*/\n';
|
||||
|
||||
function generateBuild() {
|
||||
var date = new Date;
|
||||
return Math.floor((date - (new Date(date.getFullYear(), 0, 0))) / 1000).toString(36)
|
||||
}
|
||||
|
||||
var build = generateBuild();
|
||||
|
||||
gulp.task('jshint', function() {
|
||||
return gulp.src([
|
||||
'src/lib/*.js',
|
||||
'src/lib/renderers/*.js',
|
||||
'src/renderers/*.js',
|
||||
'src/index.js'
|
||||
])
|
||||
.pipe(jshint())
|
||||
.pipe(jshint.reporter('default'));
|
||||
});
|
||||
|
||||
gulp.task('todo', function() {
|
||||
return gulp.src([
|
||||
'src/lib/*.js',
|
||||
'src/lib/renderers/*.js',
|
||||
'src/renderers/*.js',
|
||||
'src/index.js'
|
||||
])
|
||||
.pipe(todo())
|
||||
.pipe(gulp.dest('./'));
|
||||
});
|
||||
|
||||
gulp.task('build', ['jshint'], function() {
|
||||
return gulp.src('src/index.js')
|
||||
.pipe(webpack({
|
||||
output: {
|
||||
library: 'Holder',
|
||||
filename: 'holder.js',
|
||||
libraryTarget: 'umd'
|
||||
}
|
||||
}))
|
||||
.pipe(gulp.dest('./'));
|
||||
});
|
||||
|
||||
gulp.task('bundle', ['build'], function() {
|
||||
return gulp.src([
|
||||
'src/lib/vendor/polyfills.js',
|
||||
'holder.js',
|
||||
'src/meteor/shim.js'
|
||||
])
|
||||
.pipe(concat('holder.js'))
|
||||
.pipe(gulp.dest('./'));
|
||||
});
|
||||
|
||||
gulp.task('minify', ['bundle'], function() {
|
||||
return gulp.src('holder.js')
|
||||
.pipe(uglify())
|
||||
.pipe(rename('holder.min.js'))
|
||||
.pipe(gulp.dest('./'));
|
||||
});
|
||||
|
||||
gulp.task('banner', ['minify'], function() {
|
||||
return gulp.src(['holder*.js'])
|
||||
.pipe(replace('%version%', pkg.version))
|
||||
.pipe(header(banner, {
|
||||
pkg: pkg,
|
||||
year: moment().format('YYYY'),
|
||||
build: build
|
||||
}))
|
||||
.pipe(gulp.dest('./'));
|
||||
});
|
||||
|
||||
gulp.task('beautify', function() {
|
||||
return gulp.src(['src/lib/*.js'])
|
||||
.pipe(beautify())
|
||||
.pipe(gulp.dest('src/lib/'));
|
||||
});
|
||||
|
||||
gulp.task('meteor', function() {
|
||||
return gulp.src('src/meteor/package.js')
|
||||
.pipe(replace('%version%', pkg.version))
|
||||
.pipe(replace('%summary%', pkg.description))
|
||||
.pipe(gulp.dest('./'));
|
||||
});
|
||||
|
||||
gulp.task('watch', function() {
|
||||
gulp.watch('src/*.js', ['default']);
|
||||
});
|
||||
|
||||
gulp.task('default', ['todo', 'bundle', 'minify', 'banner', 'meteor'], function() {
|
||||
gulputil.log('Finished build ' + build);
|
||||
build = generateBuild();
|
||||
});
|
||||
3070
vendor/assets/javascripts/holderjs/holder.js
vendored
Normal file
3070
vendor/assets/javascripts/holderjs/holder.js
vendored
Normal file
File diff suppressed because it is too large
Load diff
12
vendor/assets/javascripts/holderjs/package.js
vendored
Normal file
12
vendor/assets/javascripts/holderjs/package.js
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
Package.describe({
|
||||
summary: 'Holder uses SVG to render image placeholders entirely in browser.',
|
||||
version: '2.9.6',
|
||||
name: 'imsky:holder',
|
||||
git: 'https://github.com/imsky/holder',
|
||||
});
|
||||
|
||||
Package.onUse(function(api) {
|
||||
api.versionsFrom('0.9.0');
|
||||
api.export('Holder', 'client');
|
||||
api.addFiles('holder.js', 'client');
|
||||
});
|
||||
6
vendor/assets/javascripts/holderjs/src/index.js
vendored
Normal file
6
vendor/assets/javascripts/holderjs/src/index.js
vendored
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
/*
|
||||
Holder.js - client side image placeholders
|
||||
(c) 2012-2015 Ivan Malopinsky - http://imsky.co
|
||||
*/
|
||||
|
||||
module.exports = require('./lib');
|
||||
202
vendor/assets/javascripts/holderjs/src/lib/color.js
vendored
Normal file
202
vendor/assets/javascripts/holderjs/src/lib/color.js
vendored
Normal file
|
|
@ -0,0 +1,202 @@
|
|||
var Color = function(color, options) {
|
||||
//todo: support rgba, hsla, and rrggbbaa notation
|
||||
//todo: use CIELAB internally
|
||||
//todo: add clamp function (with sign)
|
||||
if (typeof color !== 'string') return;
|
||||
|
||||
this.original = color;
|
||||
|
||||
if (color.charAt(0) === '#') {
|
||||
color = color.slice(1);
|
||||
}
|
||||
|
||||
if (/[^a-f0-9]+/i.test(color)) return;
|
||||
|
||||
if (color.length === 3) {
|
||||
color = color.replace(/./g, '$&$&');
|
||||
}
|
||||
|
||||
if (color.length !== 6) return;
|
||||
|
||||
this.alpha = 1;
|
||||
|
||||
if (options && options.alpha) {
|
||||
this.alpha = options.alpha;
|
||||
}
|
||||
|
||||
this.set(parseInt(color, 16));
|
||||
};
|
||||
|
||||
//todo: jsdocs
|
||||
Color.rgb2hex = function(r, g, b) {
|
||||
function format (decimal) {
|
||||
var hex = (decimal | 0).toString(16);
|
||||
if (decimal < 16) {
|
||||
hex = '0' + hex;
|
||||
}
|
||||
return hex;
|
||||
}
|
||||
|
||||
return [r, g, b].map(format).join('');
|
||||
};
|
||||
|
||||
//todo: jsdocs
|
||||
Color.hsl2rgb = function (h, s, l) {
|
||||
var H = h / 60;
|
||||
var C = (1 - Math.abs(2 * l - 1)) * s;
|
||||
var X = C * (1 - Math.abs(parseInt(H) % 2 - 1));
|
||||
var m = l - (C / 2);
|
||||
|
||||
var r = 0, g = 0, b = 0;
|
||||
|
||||
if (H >= 0 && H < 1) {
|
||||
r = C;
|
||||
g = X;
|
||||
} else if (H >= 1 && H < 2) {
|
||||
r = X;
|
||||
g = C;
|
||||
} else if (H >= 2 && H < 3) {
|
||||
g = C;
|
||||
b = X;
|
||||
} else if (H >= 3 && H < 4) {
|
||||
g = X;
|
||||
b = C;
|
||||
} else if (H >= 4 && H < 5) {
|
||||
r = X;
|
||||
b = C;
|
||||
} else if (H >= 5 && H < 6) {
|
||||
r = C;
|
||||
b = X;
|
||||
}
|
||||
|
||||
r += m;
|
||||
g += m;
|
||||
b += m;
|
||||
|
||||
r = parseInt(r * 255);
|
||||
g = parseInt(g * 255);
|
||||
b = parseInt(b * 255);
|
||||
|
||||
return [r, g, b];
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets the color from a raw RGB888 integer
|
||||
* @param raw RGB888 representation of color
|
||||
*/
|
||||
//todo: refactor into a static method
|
||||
//todo: factor out individual color spaces
|
||||
//todo: add HSL, CIELAB, and CIELUV
|
||||
Color.prototype.set = function (val) {
|
||||
this.raw = val;
|
||||
|
||||
var r = (this.raw & 0xFF0000) >> 16;
|
||||
var g = (this.raw & 0x00FF00) >> 8;
|
||||
var b = (this.raw & 0x0000FF);
|
||||
|
||||
// BT.709
|
||||
var y = 0.2126 * r + 0.7152 * g + 0.0722 * b;
|
||||
var u = -0.09991 * r - 0.33609 * g + 0.436 * b;
|
||||
var v = 0.615 * r - 0.55861 * g - 0.05639 * b;
|
||||
|
||||
this.rgb = {
|
||||
r: r,
|
||||
g: g,
|
||||
b: b
|
||||
};
|
||||
|
||||
this.yuv = {
|
||||
y: y,
|
||||
u: u,
|
||||
v: v
|
||||
};
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Lighten or darken a color
|
||||
* @param multiplier Amount to lighten or darken (-1 to 1)
|
||||
*/
|
||||
Color.prototype.lighten = function(multiplier) {
|
||||
var cm = Math.min(1, Math.max(0, Math.abs(multiplier))) * (multiplier < 0 ? -1 : 1);
|
||||
var bm = (255 * cm) | 0;
|
||||
var cr = Math.min(255, Math.max(0, this.rgb.r + bm));
|
||||
var cg = Math.min(255, Math.max(0, this.rgb.g + bm));
|
||||
var cb = Math.min(255, Math.max(0, this.rgb.b + bm));
|
||||
var hex = Color.rgb2hex(cr, cg, cb);
|
||||
return new Color(hex);
|
||||
};
|
||||
|
||||
/**
|
||||
* Output color in hex format
|
||||
* @param addHash Add a hash character to the beginning of the output
|
||||
*/
|
||||
Color.prototype.toHex = function(addHash) {
|
||||
return (addHash ? '#' : '') + this.raw.toString(16);
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns whether or not current color is lighter than another color
|
||||
* @param color Color to compare against
|
||||
*/
|
||||
Color.prototype.lighterThan = function(color) {
|
||||
if (!(color instanceof Color)) {
|
||||
color = new Color(color);
|
||||
}
|
||||
|
||||
return this.yuv.y > color.yuv.y;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the result of mixing current color with another color
|
||||
* @param color Color to mix with
|
||||
* @param multiplier How much to mix with the other color
|
||||
*/
|
||||
/*
|
||||
Color.prototype.mix = function (color, multiplier) {
|
||||
if (!(color instanceof Color)) {
|
||||
color = new Color(color);
|
||||
}
|
||||
|
||||
var r = this.rgb.r;
|
||||
var g = this.rgb.g;
|
||||
var b = this.rgb.b;
|
||||
var a = this.alpha;
|
||||
|
||||
var m = typeof multiplier !== 'undefined' ? multiplier : 0.5;
|
||||
|
||||
//todo: write a lerp function
|
||||
r = r + m * (color.rgb.r - r);
|
||||
g = g + m * (color.rgb.g - g);
|
||||
b = b + m * (color.rgb.b - b);
|
||||
a = a + m * (color.alpha - a);
|
||||
|
||||
return new Color(Color.rgbToHex(r, g, b), {
|
||||
'alpha': a
|
||||
});
|
||||
};
|
||||
*/
|
||||
|
||||
/**
|
||||
* Returns the result of blending another color on top of current color with alpha
|
||||
* @param color Color to blend on top of current color, i.e. "Ca"
|
||||
*/
|
||||
//todo: see if .blendAlpha can be merged into .mix
|
||||
Color.prototype.blendAlpha = function(color) {
|
||||
if (!(color instanceof Color)) {
|
||||
color = new Color(color);
|
||||
}
|
||||
|
||||
var Ca = color;
|
||||
var Cb = this;
|
||||
|
||||
//todo: write alpha blending function
|
||||
var r = Ca.alpha * Ca.rgb.r + (1 - Ca.alpha) * Cb.rgb.r;
|
||||
var g = Ca.alpha * Ca.rgb.g + (1 - Ca.alpha) * Cb.rgb.g;
|
||||
var b = Ca.alpha * Ca.rgb.b + (1 - Ca.alpha) * Cb.rgb.b;
|
||||
|
||||
return new Color(Color.rgb2hex(r, g, b));
|
||||
};
|
||||
|
||||
module.exports = Color;
|
||||
4
vendor/assets/javascripts/holderjs/src/lib/constants.js
vendored
Normal file
4
vendor/assets/javascripts/holderjs/src/lib/constants.js
vendored
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
module.exports = {
|
||||
'version': '%version%',
|
||||
'svg_ns': 'http://www.w3.org/2000/svg'
|
||||
};
|
||||
62
vendor/assets/javascripts/holderjs/src/lib/dom.js
vendored
Normal file
62
vendor/assets/javascripts/holderjs/src/lib/dom.js
vendored
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
/**
|
||||
* Generic new DOM element function
|
||||
*
|
||||
* @param tag Tag to create
|
||||
* @param namespace Optional namespace value
|
||||
*/
|
||||
exports.newEl = function(tag, namespace) {
|
||||
if (!global.document) return;
|
||||
|
||||
if (namespace == null) {
|
||||
return global.document.createElement(tag);
|
||||
} else {
|
||||
return global.document.createElementNS(namespace, tag);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Generic setAttribute function
|
||||
*
|
||||
* @param el Reference to DOM element
|
||||
* @param attrs Object with attribute keys and values
|
||||
*/
|
||||
exports.setAttr = function (el, attrs) {
|
||||
for (var a in attrs) {
|
||||
el.setAttribute(a, attrs[a]);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a XML document
|
||||
* @private
|
||||
*/
|
||||
exports.createXML = function() {
|
||||
if (!global.DOMParser) return;
|
||||
return new DOMParser().parseFromString('<xml />', 'application/xml');
|
||||
};
|
||||
|
||||
/**
|
||||
* Converts a value into an array of DOM nodes
|
||||
*
|
||||
* @param val A string, a NodeList, a Node, or an HTMLCollection
|
||||
*/
|
||||
exports.getNodeArray = function(val) {
|
||||
var retval = null;
|
||||
if (typeof(val) == 'string') {
|
||||
retval = document.querySelectorAll(val);
|
||||
} else if (global.NodeList && val instanceof global.NodeList) {
|
||||
retval = val;
|
||||
} else if (global.Node && val instanceof global.Node) {
|
||||
retval = [val];
|
||||
} else if (global.HTMLCollection && val instanceof global.HTMLCollection) {
|
||||
retval = val;
|
||||
} else if (val instanceof Array) {
|
||||
retval = val;
|
||||
} else if (val === null) {
|
||||
retval = [];
|
||||
}
|
||||
|
||||
retval = Array.prototype.slice.call(retval);
|
||||
|
||||
return retval;
|
||||
};
|
||||
1198
vendor/assets/javascripts/holderjs/src/lib/index.js
vendored
Normal file
1198
vendor/assets/javascripts/holderjs/src/lib/index.js
vendored
Normal file
File diff suppressed because it is too large
Load diff
64
vendor/assets/javascripts/holderjs/src/lib/renderers/canvas.js
vendored
Normal file
64
vendor/assets/javascripts/holderjs/src/lib/renderers/canvas.js
vendored
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
var DOM = require('../dom');
|
||||
var utils = require('../utils');
|
||||
|
||||
module.exports = (function() {
|
||||
var canvas = DOM.newEl('canvas');
|
||||
var ctx = null;
|
||||
|
||||
return function(sceneGraph) {
|
||||
if (ctx == null) {
|
||||
ctx = canvas.getContext('2d');
|
||||
}
|
||||
|
||||
var dpr = utils.canvasRatio();
|
||||
var root = sceneGraph.root;
|
||||
canvas.width = dpr * root.properties.width;
|
||||
canvas.height = dpr * root.properties.height ;
|
||||
ctx.textBaseline = 'middle';
|
||||
|
||||
var bg = root.children.holderBg;
|
||||
var bgWidth = dpr * bg.width;
|
||||
var bgHeight = dpr * bg.height;
|
||||
//todo: parametrize outline width (e.g. in scene object)
|
||||
var outlineWidth = 2;
|
||||
var outlineOffsetWidth = outlineWidth / 2;
|
||||
|
||||
ctx.fillStyle = bg.properties.fill;
|
||||
ctx.fillRect(0, 0, bgWidth, bgHeight);
|
||||
|
||||
if (bg.properties.outline) {
|
||||
//todo: abstract this into a method
|
||||
ctx.strokeStyle = bg.properties.outline.fill;
|
||||
ctx.lineWidth = bg.properties.outline.width;
|
||||
ctx.moveTo(outlineOffsetWidth, outlineOffsetWidth);
|
||||
// TL, TR, BR, BL
|
||||
ctx.lineTo(bgWidth - outlineOffsetWidth, outlineOffsetWidth);
|
||||
ctx.lineTo(bgWidth - outlineOffsetWidth, bgHeight - outlineOffsetWidth);
|
||||
ctx.lineTo(outlineOffsetWidth, bgHeight - outlineOffsetWidth);
|
||||
ctx.lineTo(outlineOffsetWidth, outlineOffsetWidth);
|
||||
// Diagonals
|
||||
ctx.moveTo(0, outlineOffsetWidth);
|
||||
ctx.lineTo(bgWidth, bgHeight - outlineOffsetWidth);
|
||||
ctx.moveTo(0, bgHeight - outlineOffsetWidth);
|
||||
ctx.lineTo(bgWidth, outlineOffsetWidth);
|
||||
ctx.stroke();
|
||||
}
|
||||
|
||||
var textGroup = root.children.holderTextGroup;
|
||||
ctx.font = textGroup.properties.font.weight + ' ' + (dpr * textGroup.properties.font.size) + textGroup.properties.font.units + ' ' + textGroup.properties.font.family + ', monospace';
|
||||
ctx.fillStyle = textGroup.properties.fill;
|
||||
|
||||
for (var lineKey in textGroup.children) {
|
||||
var line = textGroup.children[lineKey];
|
||||
for (var wordKey in line.children) {
|
||||
var word = line.children[wordKey];
|
||||
var x = dpr * (textGroup.x + line.x + word.x);
|
||||
var y = dpr * (textGroup.y + line.y + word.y + (textGroup.properties.leading / 2));
|
||||
|
||||
ctx.fillText(word.properties.text, x, y);
|
||||
}
|
||||
}
|
||||
|
||||
return canvas.toDataURL('image/png');
|
||||
};
|
||||
})();
|
||||
122
vendor/assets/javascripts/holderjs/src/lib/renderers/svg-dom.js
vendored
Normal file
122
vendor/assets/javascripts/holderjs/src/lib/renderers/svg-dom.js
vendored
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
var SVG = require('../svg');
|
||||
var DOM = require('../dom');
|
||||
var utils = require('../utils');
|
||||
var constants = require('../constants');
|
||||
|
||||
var SVG_NS = constants.svg_ns;
|
||||
|
||||
var generatorComment = '\n' +
|
||||
'Created with Holder.js ' + constants.version + '.\n' +
|
||||
'Learn more at http://holderjs.com\n' +
|
||||
'(c) 2012-2015 Ivan Malopinsky - http://imsky.co\n';
|
||||
|
||||
module.exports = (function() {
|
||||
//Prevent IE <9 from initializing SVG renderer
|
||||
if (!global.XMLSerializer) return;
|
||||
var xml = DOM.createXML();
|
||||
var svg = SVG.initSVG(null, 0, 0);
|
||||
var bgEl = DOM.newEl('rect', SVG_NS);
|
||||
svg.appendChild(bgEl);
|
||||
|
||||
//todo: create a reusable pool for textNodes, resize if more words present
|
||||
|
||||
return function(sceneGraph, renderSettings) {
|
||||
var root = sceneGraph.root;
|
||||
|
||||
SVG.initSVG(svg, root.properties.width, root.properties.height);
|
||||
|
||||
var groups = svg.querySelectorAll('g');
|
||||
|
||||
for (var i = 0; i < groups.length; i++) {
|
||||
groups[i].parentNode.removeChild(groups[i]);
|
||||
}
|
||||
|
||||
var holderURL = renderSettings.holderSettings.flags.holderURL;
|
||||
var holderId = 'holder_' + (Number(new Date()) + 32768 + (0 | Math.random() * 32768)).toString(16);
|
||||
var sceneGroupEl = DOM.newEl('g', SVG_NS);
|
||||
var textGroup = root.children.holderTextGroup;
|
||||
var tgProps = textGroup.properties;
|
||||
var textGroupEl = DOM.newEl('g', SVG_NS);
|
||||
var tpdata = textGroup.textPositionData;
|
||||
var textCSSRule = '#' + holderId + ' text { ' +
|
||||
utils.cssProps({
|
||||
'fill': tgProps.fill,
|
||||
'font-weight': tgProps.font.weight,
|
||||
'font-family': tgProps.font.family + ', monospace',
|
||||
'font-size': tgProps.font.size + tgProps.font.units
|
||||
}) + ' } ';
|
||||
var commentNode = xml.createComment('\n' + 'Source URL: ' + holderURL + generatorComment);
|
||||
var holderCSS = xml.createCDATASection(textCSSRule);
|
||||
var styleEl = svg.querySelector('style');
|
||||
var bg = root.children.holderBg;
|
||||
|
||||
DOM.setAttr(sceneGroupEl, {
|
||||
id: holderId
|
||||
});
|
||||
|
||||
svg.insertBefore(commentNode, svg.firstChild);
|
||||
styleEl.appendChild(holderCSS);
|
||||
|
||||
sceneGroupEl.appendChild(bgEl);
|
||||
|
||||
//todo: abstract this into a cross-browser SVG outline method
|
||||
if (bg.properties.outline) {
|
||||
var outlineEl = DOM.newEl('path', SVG_NS);
|
||||
var outlineWidth = bg.properties.outline.width;
|
||||
var outlineOffsetWidth = outlineWidth / 2;
|
||||
DOM.setAttr(outlineEl, {
|
||||
'd': [
|
||||
'M', outlineOffsetWidth, outlineOffsetWidth,
|
||||
'H', bg.width - outlineOffsetWidth,
|
||||
'V', bg.height - outlineOffsetWidth,
|
||||
'H', outlineOffsetWidth,
|
||||
'V', 0,
|
||||
'M', 0, outlineOffsetWidth,
|
||||
'L', bg.width, bg.height - outlineOffsetWidth,
|
||||
'M', 0, bg.height - outlineOffsetWidth,
|
||||
'L', bg.width, outlineOffsetWidth
|
||||
].join(' '),
|
||||
'stroke-width': bg.properties.outline.width,
|
||||
'stroke': bg.properties.outline.fill,
|
||||
'fill': 'none'
|
||||
});
|
||||
sceneGroupEl.appendChild(outlineEl);
|
||||
}
|
||||
|
||||
sceneGroupEl.appendChild(textGroupEl);
|
||||
svg.appendChild(sceneGroupEl);
|
||||
|
||||
DOM.setAttr(bgEl, {
|
||||
'width': bg.width,
|
||||
'height': bg.height,
|
||||
'fill': bg.properties.fill
|
||||
});
|
||||
|
||||
textGroup.y += tpdata.boundingBox.height * 0.8;
|
||||
|
||||
for (var lineKey in textGroup.children) {
|
||||
var line = textGroup.children[lineKey];
|
||||
for (var wordKey in line.children) {
|
||||
var word = line.children[wordKey];
|
||||
var x = textGroup.x + line.x + word.x;
|
||||
var y = textGroup.y + line.y + word.y;
|
||||
|
||||
var textEl = DOM.newEl('text', SVG_NS);
|
||||
var textNode = document.createTextNode(null);
|
||||
|
||||
DOM.setAttr(textEl, {
|
||||
'x': x,
|
||||
'y': y
|
||||
});
|
||||
|
||||
textNode.nodeValue = word.properties.text;
|
||||
textEl.appendChild(textNode);
|
||||
textGroupEl.appendChild(textEl);
|
||||
}
|
||||
}
|
||||
|
||||
//todo: factor the background check up the chain, perhaps only return reference
|
||||
var svgString = SVG.svgStringToDataURI(SVG.serializeSVG(svg, renderSettings.engineSettings), renderSettings.mode === 'background');
|
||||
return svgString;
|
||||
};
|
||||
})();
|
||||
157
vendor/assets/javascripts/holderjs/src/lib/renderers/svg-text.js
vendored
Normal file
157
vendor/assets/javascripts/holderjs/src/lib/renderers/svg-text.js
vendored
Normal file
|
|
@ -0,0 +1,157 @@
|
|||
var shaven = require('shaven');
|
||||
|
||||
var SVG = require('../svg');
|
||||
var constants = require('../constants');
|
||||
var utils = require('../utils');
|
||||
|
||||
var SVG_NS = constants.svg_ns;
|
||||
|
||||
var templates = {
|
||||
'element': function (options) {
|
||||
var tag = options.tag;
|
||||
var content = options.content || '';
|
||||
delete options.tag;
|
||||
delete options.content;
|
||||
return [tag, content, options];
|
||||
}
|
||||
};
|
||||
|
||||
//todo: deprecate tag arg, infer tag from shape object
|
||||
function convertShape (shape, tag) {
|
||||
return templates.element({
|
||||
'tag': tag,
|
||||
'width': shape.width,
|
||||
'height': shape.height,
|
||||
'fill': shape.properties.fill
|
||||
});
|
||||
}
|
||||
|
||||
function textCss (properties) {
|
||||
return utils.cssProps({
|
||||
'fill': properties.fill,
|
||||
'font-weight': properties.font.weight,
|
||||
'font-family': properties.font.family + ', monospace',
|
||||
'font-size': properties.font.size + properties.font.units
|
||||
});
|
||||
}
|
||||
|
||||
function outlinePath (bgWidth, bgHeight, outlineWidth) {
|
||||
var outlineOffsetWidth = outlineWidth / 2;
|
||||
|
||||
return [
|
||||
'M', outlineOffsetWidth, outlineOffsetWidth,
|
||||
'H', bgWidth - outlineOffsetWidth,
|
||||
'V', bgHeight - outlineOffsetWidth,
|
||||
'H', outlineOffsetWidth,
|
||||
'V', 0,
|
||||
'M', 0, outlineOffsetWidth,
|
||||
'L', bgWidth, bgHeight - outlineOffsetWidth,
|
||||
'M', 0, bgHeight - outlineOffsetWidth,
|
||||
'L', bgWidth, outlineOffsetWidth
|
||||
].join(' ');
|
||||
}
|
||||
|
||||
module.exports = function (sceneGraph, renderSettings) {
|
||||
var engineSettings = renderSettings.engineSettings;
|
||||
var stylesheets = engineSettings.stylesheets;
|
||||
var stylesheetXml = stylesheets.map(function (stylesheet) {
|
||||
return '<?xml-stylesheet rel="stylesheet" href="' + stylesheet + '"?>';
|
||||
}).join('\n');
|
||||
|
||||
var holderId = 'holder_' + Number(new Date()).toString(16);
|
||||
|
||||
var root = sceneGraph.root;
|
||||
var textGroup = root.children.holderTextGroup;
|
||||
|
||||
var css = '#' + holderId + ' text { ' + textCss(textGroup.properties) + ' } ';
|
||||
|
||||
// push text down to be equally vertically aligned with canvas renderer
|
||||
textGroup.y += textGroup.textPositionData.boundingBox.height * 0.8;
|
||||
|
||||
var wordTags = [];
|
||||
|
||||
Object.keys(textGroup.children).forEach(function (lineKey) {
|
||||
var line = textGroup.children[lineKey];
|
||||
|
||||
Object.keys(line.children).forEach(function (wordKey) {
|
||||
var word = line.children[wordKey];
|
||||
var x = textGroup.x + line.x + word.x;
|
||||
var y = textGroup.y + line.y + word.y;
|
||||
var wordTag = templates.element({
|
||||
'tag': 'text',
|
||||
'content': word.properties.text,
|
||||
'x': x,
|
||||
'y': y
|
||||
});
|
||||
|
||||
wordTags.push(wordTag);
|
||||
});
|
||||
});
|
||||
|
||||
var text = templates.element({
|
||||
'tag': 'g',
|
||||
'content': wordTags
|
||||
});
|
||||
|
||||
var outline = null;
|
||||
|
||||
if (root.children.holderBg.properties.outline) {
|
||||
var outlineProperties = root.children.holderBg.properties.outline;
|
||||
outline = templates.element({
|
||||
'tag': 'path',
|
||||
'd': outlinePath(root.children.holderBg.width, root.children.holderBg.height, outlineProperties.width),
|
||||
'stroke-width': outlineProperties.width,
|
||||
'stroke': outlineProperties.fill,
|
||||
'fill': 'none'
|
||||
});
|
||||
}
|
||||
|
||||
var bg = convertShape(root.children.holderBg, 'rect');
|
||||
|
||||
var sceneContent = [];
|
||||
|
||||
sceneContent.push(bg);
|
||||
if (outlineProperties) {
|
||||
sceneContent.push(outline);
|
||||
}
|
||||
sceneContent.push(text);
|
||||
|
||||
var scene = templates.element({
|
||||
'tag': 'g',
|
||||
'id': holderId,
|
||||
'content': sceneContent
|
||||
});
|
||||
|
||||
var style = templates.element({
|
||||
'tag': 'style',
|
||||
//todo: figure out how to add CDATA directive
|
||||
'content': css,
|
||||
'type': 'text/css'
|
||||
});
|
||||
|
||||
var defs = templates.element({
|
||||
'tag': 'defs',
|
||||
'content': style
|
||||
});
|
||||
|
||||
var svg = templates.element({
|
||||
'tag': 'svg',
|
||||
'content': [defs, scene],
|
||||
'width': root.properties.width,
|
||||
'height': root.properties.height,
|
||||
'xmlns': SVG_NS,
|
||||
'viewBox': [0, 0, root.properties.width, root.properties.height].join(' '),
|
||||
'preserveAspectRatio': 'none'
|
||||
});
|
||||
|
||||
var output = shaven(svg);
|
||||
|
||||
if (/\&(x)?#[0-9A-Fa-f]/.test(output[0])) {
|
||||
output[0] = output[0].replace(/&#/gm, '&#');
|
||||
}
|
||||
|
||||
output = stylesheetXml + output[0];
|
||||
|
||||
var svgString = SVG.svgStringToDataURI(output, renderSettings.mode === 'background');
|
||||
return svgString;
|
||||
};
|
||||
105
vendor/assets/javascripts/holderjs/src/lib/scenegraph.js
vendored
Normal file
105
vendor/assets/javascripts/holderjs/src/lib/scenegraph.js
vendored
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
var SceneGraph = function(sceneProperties) {
|
||||
var nodeCount = 1;
|
||||
|
||||
//todo: move merge to helpers section
|
||||
function merge(parent, child) {
|
||||
for (var prop in child) {
|
||||
parent[prop] = child[prop];
|
||||
}
|
||||
return parent;
|
||||
}
|
||||
|
||||
var SceneNode = function(name) {
|
||||
nodeCount++;
|
||||
this.parent = null;
|
||||
this.children = {};
|
||||
this.id = nodeCount;
|
||||
this.name = 'n' + nodeCount;
|
||||
if (typeof name !== 'undefined') {
|
||||
this.name = name;
|
||||
}
|
||||
this.x = this.y = this.z = 0;
|
||||
this.width = this.height = 0;
|
||||
};
|
||||
|
||||
SceneNode.prototype.resize = function(width, height) {
|
||||
if (width != null) {
|
||||
this.width = width;
|
||||
}
|
||||
if (height != null) {
|
||||
this.height = height;
|
||||
}
|
||||
};
|
||||
|
||||
SceneNode.prototype.moveTo = function(x, y, z) {
|
||||
this.x = x != null ? x : this.x;
|
||||
this.y = y != null ? y : this.y;
|
||||
this.z = z != null ? z : this.z;
|
||||
};
|
||||
|
||||
SceneNode.prototype.add = function(child) {
|
||||
var name = child.name;
|
||||
if (typeof this.children[name] === 'undefined') {
|
||||
this.children[name] = child;
|
||||
child.parent = this;
|
||||
} else {
|
||||
throw 'SceneGraph: child already exists: ' + name;
|
||||
}
|
||||
};
|
||||
|
||||
var RootNode = function() {
|
||||
SceneNode.call(this, 'root');
|
||||
this.properties = sceneProperties;
|
||||
};
|
||||
|
||||
RootNode.prototype = new SceneNode();
|
||||
|
||||
var Shape = function(name, props) {
|
||||
SceneNode.call(this, name);
|
||||
this.properties = {
|
||||
'fill': '#000000'
|
||||
};
|
||||
if (typeof props !== 'undefined') {
|
||||
merge(this.properties, props);
|
||||
} else if (typeof name !== 'undefined' && typeof name !== 'string') {
|
||||
throw 'SceneGraph: invalid node name';
|
||||
}
|
||||
};
|
||||
|
||||
Shape.prototype = new SceneNode();
|
||||
|
||||
var Group = function() {
|
||||
Shape.apply(this, arguments);
|
||||
this.type = 'group';
|
||||
};
|
||||
|
||||
Group.prototype = new Shape();
|
||||
|
||||
var Rect = function() {
|
||||
Shape.apply(this, arguments);
|
||||
this.type = 'rect';
|
||||
};
|
||||
|
||||
Rect.prototype = new Shape();
|
||||
|
||||
var Text = function(text) {
|
||||
Shape.call(this);
|
||||
this.type = 'text';
|
||||
this.properties.text = text;
|
||||
};
|
||||
|
||||
Text.prototype = new Shape();
|
||||
|
||||
var root = new RootNode();
|
||||
|
||||
this.Shape = {
|
||||
'Rect': Rect,
|
||||
'Text': Text,
|
||||
'Group': Group
|
||||
};
|
||||
|
||||
this.root = root;
|
||||
return this;
|
||||
};
|
||||
|
||||
module.exports = SceneGraph;
|
||||
109
vendor/assets/javascripts/holderjs/src/lib/svg.js
vendored
Normal file
109
vendor/assets/javascripts/holderjs/src/lib/svg.js
vendored
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
var DOM = require('./dom');
|
||||
|
||||
var SVG_NS = 'http://www.w3.org/2000/svg';
|
||||
var NODE_TYPE_COMMENT = 8;
|
||||
|
||||
/**
|
||||
* Generic SVG element creation function
|
||||
*
|
||||
* @param svg SVG context, set to null if new
|
||||
* @param width Document width
|
||||
* @param height Document height
|
||||
*/
|
||||
exports.initSVG = function(svg, width, height) {
|
||||
var defs, style, initialize = false;
|
||||
|
||||
if (svg && svg.querySelector) {
|
||||
style = svg.querySelector('style');
|
||||
if (style === null) {
|
||||
initialize = true;
|
||||
}
|
||||
} else {
|
||||
svg = DOM.newEl('svg', SVG_NS);
|
||||
initialize = true;
|
||||
}
|
||||
|
||||
if (initialize) {
|
||||
defs = DOM.newEl('defs', SVG_NS);
|
||||
style = DOM.newEl('style', SVG_NS);
|
||||
DOM.setAttr(style, {
|
||||
'type': 'text/css'
|
||||
});
|
||||
defs.appendChild(style);
|
||||
svg.appendChild(defs);
|
||||
}
|
||||
|
||||
//IE throws an exception if this is set and Chrome requires it to be set
|
||||
if (svg.webkitMatchesSelector) {
|
||||
svg.setAttribute('xmlns', SVG_NS);
|
||||
}
|
||||
|
||||
//Remove comment nodes
|
||||
for (var i = 0; i < svg.childNodes.length; i++) {
|
||||
if (svg.childNodes[i].nodeType === NODE_TYPE_COMMENT) {
|
||||
svg.removeChild(svg.childNodes[i]);
|
||||
}
|
||||
}
|
||||
|
||||
//Remove CSS
|
||||
while (style.childNodes.length) {
|
||||
style.removeChild(style.childNodes[0]);
|
||||
}
|
||||
|
||||
DOM.setAttr(svg, {
|
||||
'width': width,
|
||||
'height': height,
|
||||
'viewBox': '0 0 ' + width + ' ' + height,
|
||||
'preserveAspectRatio': 'none'
|
||||
});
|
||||
|
||||
return svg;
|
||||
};
|
||||
|
||||
/**
|
||||
* Converts serialized SVG to a string suitable for data URI use
|
||||
* @param svgString Serialized SVG string
|
||||
* @param [base64] Use base64 encoding for data URI
|
||||
*/
|
||||
exports.svgStringToDataURI = function() {
|
||||
var rawPrefix = 'data:image/svg+xml;charset=UTF-8,';
|
||||
var base64Prefix = 'data:image/svg+xml;charset=UTF-8;base64,';
|
||||
|
||||
return function(svgString, base64) {
|
||||
if (base64) {
|
||||
return base64Prefix + btoa(global.unescape(encodeURIComponent(svgString)));
|
||||
} else {
|
||||
return rawPrefix + encodeURIComponent(svgString);
|
||||
}
|
||||
};
|
||||
}();
|
||||
|
||||
/**
|
||||
* Returns serialized SVG with XML processing instructions
|
||||
*
|
||||
* @param svg SVG context
|
||||
* @param stylesheets CSS stylesheets to include
|
||||
*/
|
||||
exports.serializeSVG = function(svg, engineSettings) {
|
||||
if (!global.XMLSerializer) return;
|
||||
var serializer = new XMLSerializer();
|
||||
var svgCSS = '';
|
||||
var stylesheets = engineSettings.stylesheets;
|
||||
|
||||
//External stylesheets: Processing Instruction method
|
||||
if (engineSettings.svgXMLStylesheet) {
|
||||
var xml = DOM.createXML();
|
||||
//Add <?xml-stylesheet ?> directives
|
||||
for (var i = stylesheets.length - 1; i >= 0; i--) {
|
||||
var csspi = xml.createProcessingInstruction('xml-stylesheet', 'href="' + stylesheets[i] + '" rel="stylesheet"');
|
||||
xml.insertBefore(csspi, xml.firstChild);
|
||||
}
|
||||
|
||||
xml.removeChild(xml.documentElement);
|
||||
svgCSS = serializer.serializeToString(xml);
|
||||
}
|
||||
|
||||
var svgText = serializer.serializeToString(svg);
|
||||
svgText = svgText.replace(/\&(\#[0-9]{2,}\;)/g, '&$1');
|
||||
return svgCSS + svgText;
|
||||
};
|
||||
173
vendor/assets/javascripts/holderjs/src/lib/utils.js
vendored
Normal file
173
vendor/assets/javascripts/holderjs/src/lib/utils.js
vendored
Normal file
|
|
@ -0,0 +1,173 @@
|
|||
/**
|
||||
* Shallow object clone and merge
|
||||
*
|
||||
* @param a Object A
|
||||
* @param b Object B
|
||||
* @returns {Object} New object with all of A's properties, and all of B's properties, overwriting A's properties
|
||||
*/
|
||||
exports.extend = function(a, b) {
|
||||
var c = {};
|
||||
for (var x in a) {
|
||||
if (a.hasOwnProperty(x)) {
|
||||
c[x] = a[x];
|
||||
}
|
||||
}
|
||||
if (b != null) {
|
||||
for (var y in b) {
|
||||
if (b.hasOwnProperty(y)) {
|
||||
c[y] = b[y];
|
||||
}
|
||||
}
|
||||
}
|
||||
return c;
|
||||
};
|
||||
|
||||
/**
|
||||
* Takes a k/v list of CSS properties and returns a rule
|
||||
*
|
||||
* @param props CSS properties object
|
||||
*/
|
||||
exports.cssProps = function(props) {
|
||||
var ret = [];
|
||||
for (var p in props) {
|
||||
if (props.hasOwnProperty(p)) {
|
||||
ret.push(p + ':' + props[p]);
|
||||
}
|
||||
}
|
||||
return ret.join(';');
|
||||
};
|
||||
|
||||
/**
|
||||
* Encodes HTML entities in a string
|
||||
*
|
||||
* @param str Input string
|
||||
*/
|
||||
exports.encodeHtmlEntity = function(str) {
|
||||
var buf = [];
|
||||
var charCode = 0;
|
||||
for (var i = str.length - 1; i >= 0; i--) {
|
||||
charCode = str.charCodeAt(i);
|
||||
if (charCode > 128) {
|
||||
buf.unshift(['&#', charCode, ';'].join(''));
|
||||
} else {
|
||||
buf.unshift(str[i]);
|
||||
}
|
||||
}
|
||||
return buf.join('');
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks if an image exists
|
||||
*
|
||||
* @param src URL of image
|
||||
* @param callback Callback to call once image status has been found
|
||||
*/
|
||||
exports.imageExists = function(src, callback) {
|
||||
var image = new Image();
|
||||
image.onerror = function() {
|
||||
callback.call(this, false);
|
||||
};
|
||||
image.onload = function() {
|
||||
callback.call(this, true);
|
||||
};
|
||||
image.src = src;
|
||||
};
|
||||
|
||||
/**
|
||||
* Decodes HTML entities in a string
|
||||
*
|
||||
* @param str Input string
|
||||
*/
|
||||
exports.decodeHtmlEntity = function(str) {
|
||||
return str.replace(/&#(\d+);/g, function(match, dec) {
|
||||
return String.fromCharCode(dec);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns an element's dimensions if it's visible, `false` otherwise.
|
||||
*
|
||||
* @param el DOM element
|
||||
*/
|
||||
exports.dimensionCheck = function(el) {
|
||||
var dimensions = {
|
||||
height: el.clientHeight,
|
||||
width: el.clientWidth
|
||||
};
|
||||
|
||||
if (dimensions.height && dimensions.width) {
|
||||
return dimensions;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if value is truthy or if it is "semantically truthy"
|
||||
* @param val
|
||||
*/
|
||||
exports.truthy = function(val) {
|
||||
if (typeof val === 'string') {
|
||||
return val === 'true' || val === 'yes' || val === '1' || val === 'on' || val === '✓';
|
||||
}
|
||||
return !!val;
|
||||
};
|
||||
|
||||
/**
|
||||
* Parses input into a well-formed CSS color
|
||||
* @param val
|
||||
*/
|
||||
exports.parseColor = function(val) {
|
||||
var hexre = /(^(?:#?)[0-9a-f]{6}$)|(^(?:#?)[0-9a-f]{3}$)/i;
|
||||
var rgbre = /^rgb\((\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\)$/;
|
||||
var rgbare = /^rgba\((\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(0\.\d{1,}|1)\)$/;
|
||||
|
||||
var match = val.match(hexre);
|
||||
var retval;
|
||||
|
||||
if (match !== null) {
|
||||
retval = match[1] || match[2];
|
||||
if (retval[0] !== '#') {
|
||||
return '#' + retval;
|
||||
} else {
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
|
||||
match = val.match(rgbre);
|
||||
|
||||
if (match !== null) {
|
||||
retval = 'rgb(' + match.slice(1).join(',') + ')';
|
||||
return retval;
|
||||
}
|
||||
|
||||
match = val.match(rgbare);
|
||||
|
||||
if (match !== null) {
|
||||
retval = 'rgba(' + match.slice(1).join(',') + ')';
|
||||
return retval;
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Provides the correct scaling ratio for canvas drawing operations on HiDPI screens (e.g. Retina displays)
|
||||
*/
|
||||
exports.canvasRatio = function () {
|
||||
var devicePixelRatio = 1;
|
||||
var backingStoreRatio = 1;
|
||||
|
||||
if (global.document) {
|
||||
var canvas = global.document.createElement('canvas');
|
||||
if (canvas.getContext) {
|
||||
var ctx = canvas.getContext('2d');
|
||||
devicePixelRatio = global.devicePixelRatio || 1;
|
||||
backingStoreRatio = ctx.webkitBackingStorePixelRatio || ctx.mozBackingStorePixelRatio || ctx.msBackingStorePixelRatio || ctx.oBackingStorePixelRatio || ctx.backingStorePixelRatio || 1;
|
||||
}
|
||||
}
|
||||
|
||||
return devicePixelRatio / backingStoreRatio;
|
||||
};
|
||||
155
vendor/assets/javascripts/holderjs/src/lib/vendor/ondomready.js
vendored
Normal file
155
vendor/assets/javascripts/holderjs/src/lib/vendor/ondomready.js
vendored
Normal file
|
|
@ -0,0 +1,155 @@
|
|||
/*!
|
||||
* onDomReady.js 1.4.0 (c) 2013 Tubal Martin - MIT license
|
||||
*
|
||||
* Specially modified to work with Holder.js
|
||||
*/
|
||||
|
||||
function _onDomReady(win) {
|
||||
//Lazy loading fix for Firefox < 3.6
|
||||
//http://webreflection.blogspot.com/2009/11/195-chars-to-help-lazy-loading.html
|
||||
if (document.readyState == null && document.addEventListener) {
|
||||
document.addEventListener("DOMContentLoaded", function DOMContentLoaded() {
|
||||
document.removeEventListener("DOMContentLoaded", DOMContentLoaded, false);
|
||||
document.readyState = "complete";
|
||||
}, false);
|
||||
document.readyState = "loading";
|
||||
}
|
||||
|
||||
var doc = win.document,
|
||||
docElem = doc.documentElement,
|
||||
|
||||
LOAD = "load",
|
||||
FALSE = false,
|
||||
ONLOAD = "on"+LOAD,
|
||||
COMPLETE = "complete",
|
||||
READYSTATE = "readyState",
|
||||
ATTACHEVENT = "attachEvent",
|
||||
DETACHEVENT = "detachEvent",
|
||||
ADDEVENTLISTENER = "addEventListener",
|
||||
DOMCONTENTLOADED = "DOMContentLoaded",
|
||||
ONREADYSTATECHANGE = "onreadystatechange",
|
||||
REMOVEEVENTLISTENER = "removeEventListener",
|
||||
|
||||
// W3C Event model
|
||||
w3c = ADDEVENTLISTENER in doc,
|
||||
_top = FALSE,
|
||||
|
||||
// isReady: Is the DOM ready to be used? Set to true once it occurs.
|
||||
isReady = FALSE,
|
||||
|
||||
// Callbacks pending execution until DOM is ready
|
||||
callbacks = [];
|
||||
|
||||
// Handle when the DOM is ready
|
||||
function ready( fn ) {
|
||||
if ( !isReady ) {
|
||||
|
||||
// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
|
||||
if ( !doc.body ) {
|
||||
return defer( ready );
|
||||
}
|
||||
|
||||
// Remember that the DOM is ready
|
||||
isReady = true;
|
||||
|
||||
// Execute all callbacks
|
||||
while ( fn = callbacks.shift() ) {
|
||||
defer( fn );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The ready event handler
|
||||
function completed( event ) {
|
||||
// readyState === "complete" is good enough for us to call the dom ready in oldIE
|
||||
if ( w3c || event.type === LOAD || doc[READYSTATE] === COMPLETE ) {
|
||||
detach();
|
||||
ready();
|
||||
}
|
||||
}
|
||||
|
||||
// Clean-up method for dom ready events
|
||||
function detach() {
|
||||
if ( w3c ) {
|
||||
doc[REMOVEEVENTLISTENER]( DOMCONTENTLOADED, completed, FALSE );
|
||||
win[REMOVEEVENTLISTENER]( LOAD, completed, FALSE );
|
||||
} else {
|
||||
doc[DETACHEVENT]( ONREADYSTATECHANGE, completed );
|
||||
win[DETACHEVENT]( ONLOAD, completed );
|
||||
}
|
||||
}
|
||||
|
||||
// Defers a function, scheduling it to run after the current call stack has cleared.
|
||||
function defer( fn, wait ) {
|
||||
// Allow 0 to be passed
|
||||
setTimeout( fn, +wait >= 0 ? wait : 1 );
|
||||
}
|
||||
|
||||
// Attach the listeners:
|
||||
|
||||
// Catch cases where onDomReady is called after the browser event has already occurred.
|
||||
// we once tried to use readyState "interactive" here, but it caused issues like the one
|
||||
// discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15
|
||||
if ( doc[READYSTATE] === COMPLETE ) {
|
||||
// Handle it asynchronously to allow scripts the opportunity to delay ready
|
||||
defer( ready );
|
||||
|
||||
// Standards-based browsers support DOMContentLoaded
|
||||
} else if ( w3c ) {
|
||||
// Use the handy event callback
|
||||
doc[ADDEVENTLISTENER]( DOMCONTENTLOADED, completed, FALSE );
|
||||
|
||||
// A fallback to window.onload, that will always work
|
||||
win[ADDEVENTLISTENER]( LOAD, completed, FALSE );
|
||||
|
||||
// If IE event model is used
|
||||
} else {
|
||||
// Ensure firing before onload, maybe late but safe also for iframes
|
||||
doc[ATTACHEVENT]( ONREADYSTATECHANGE, completed );
|
||||
|
||||
// A fallback to window.onload, that will always work
|
||||
win[ATTACHEVENT]( ONLOAD, completed );
|
||||
|
||||
// If IE and not a frame
|
||||
// continually check to see if the document is ready
|
||||
try {
|
||||
_top = win.frameElement == null && docElem;
|
||||
} catch(e) {}
|
||||
|
||||
if ( _top && _top.doScroll ) {
|
||||
(function doScrollCheck() {
|
||||
if ( !isReady ) {
|
||||
try {
|
||||
// Use the trick by Diego Perini
|
||||
// http://javascript.nwbox.com/IEContentLoaded/
|
||||
_top.doScroll("left");
|
||||
} catch(e) {
|
||||
return defer( doScrollCheck, 50 );
|
||||
}
|
||||
|
||||
// detach all dom ready events
|
||||
detach();
|
||||
|
||||
// and execute any waiting functions
|
||||
ready();
|
||||
}
|
||||
})();
|
||||
}
|
||||
}
|
||||
|
||||
function onDomReady( fn ) {
|
||||
// If DOM is ready, execute the function (async), otherwise wait
|
||||
isReady ? defer( fn ) : callbacks.push( fn );
|
||||
}
|
||||
|
||||
// Add version
|
||||
onDomReady.version = "1.4.0";
|
||||
// Add method to check if DOM is ready
|
||||
onDomReady.isReady = function(){
|
||||
return isReady;
|
||||
};
|
||||
|
||||
return onDomReady;
|
||||
}
|
||||
|
||||
module.exports = typeof window !== "undefined" && _onDomReady(window);
|
||||
234
vendor/assets/javascripts/holderjs/src/lib/vendor/polyfills.js
vendored
Normal file
234
vendor/assets/javascripts/holderjs/src/lib/vendor/polyfills.js
vendored
Normal file
|
|
@ -0,0 +1,234 @@
|
|||
(function (window) {
|
||||
if (!window.document) return;
|
||||
var document = window.document;
|
||||
|
||||
//https://github.com/inexorabletash/polyfill/blob/master/web.js
|
||||
if (!document.querySelectorAll) {
|
||||
document.querySelectorAll = function (selectors) {
|
||||
var style = document.createElement('style'), elements = [], element;
|
||||
document.documentElement.firstChild.appendChild(style);
|
||||
document._qsa = [];
|
||||
|
||||
style.styleSheet.cssText = selectors + '{x-qsa:expression(document._qsa && document._qsa.push(this))}';
|
||||
window.scrollBy(0, 0);
|
||||
style.parentNode.removeChild(style);
|
||||
|
||||
while (document._qsa.length) {
|
||||
element = document._qsa.shift();
|
||||
element.style.removeAttribute('x-qsa');
|
||||
elements.push(element);
|
||||
}
|
||||
document._qsa = null;
|
||||
return elements;
|
||||
};
|
||||
}
|
||||
|
||||
if (!document.querySelector) {
|
||||
document.querySelector = function (selectors) {
|
||||
var elements = document.querySelectorAll(selectors);
|
||||
return (elements.length) ? elements[0] : null;
|
||||
};
|
||||
}
|
||||
|
||||
if (!document.getElementsByClassName) {
|
||||
document.getElementsByClassName = function (classNames) {
|
||||
classNames = String(classNames).replace(/^|\s+/g, '.');
|
||||
return document.querySelectorAll(classNames);
|
||||
};
|
||||
}
|
||||
|
||||
//https://github.com/inexorabletash/polyfill
|
||||
// ES5 15.2.3.14 Object.keys ( O )
|
||||
// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/keys
|
||||
if (!Object.keys) {
|
||||
Object.keys = function (o) {
|
||||
if (o !== Object(o)) { throw TypeError('Object.keys called on non-object'); }
|
||||
var ret = [], p;
|
||||
for (p in o) {
|
||||
if (Object.prototype.hasOwnProperty.call(o, p)) {
|
||||
ret.push(p);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
};
|
||||
}
|
||||
|
||||
// ES5 15.4.4.18 Array.prototype.forEach ( callbackfn [ , thisArg ] )
|
||||
// From https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/forEach
|
||||
if (!Array.prototype.forEach) {
|
||||
Array.prototype.forEach = function (fun /*, thisp */) {
|
||||
if (this === void 0 || this === null) { throw TypeError(); }
|
||||
|
||||
var t = Object(this);
|
||||
var len = t.length >>> 0;
|
||||
if (typeof fun !== "function") { throw TypeError(); }
|
||||
|
||||
var thisp = arguments[1], i;
|
||||
for (i = 0; i < len; i++) {
|
||||
if (i in t) {
|
||||
fun.call(thisp, t[i], i, t);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
//https://github.com/inexorabletash/polyfill/blob/master/web.js
|
||||
(function (global) {
|
||||
var B64_ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
|
||||
global.atob = global.atob || function (input) {
|
||||
input = String(input);
|
||||
var position = 0,
|
||||
output = [],
|
||||
buffer = 0, bits = 0, n;
|
||||
|
||||
input = input.replace(/\s/g, '');
|
||||
if ((input.length % 4) === 0) { input = input.replace(/=+$/, ''); }
|
||||
if ((input.length % 4) === 1) { throw Error('InvalidCharacterError'); }
|
||||
if (/[^+/0-9A-Za-z]/.test(input)) { throw Error('InvalidCharacterError'); }
|
||||
|
||||
while (position < input.length) {
|
||||
n = B64_ALPHABET.indexOf(input.charAt(position));
|
||||
buffer = (buffer << 6) | n;
|
||||
bits += 6;
|
||||
|
||||
if (bits === 24) {
|
||||
output.push(String.fromCharCode((buffer >> 16) & 0xFF));
|
||||
output.push(String.fromCharCode((buffer >> 8) & 0xFF));
|
||||
output.push(String.fromCharCode(buffer & 0xFF));
|
||||
bits = 0;
|
||||
buffer = 0;
|
||||
}
|
||||
position += 1;
|
||||
}
|
||||
|
||||
if (bits === 12) {
|
||||
buffer = buffer >> 4;
|
||||
output.push(String.fromCharCode(buffer & 0xFF));
|
||||
} else if (bits === 18) {
|
||||
buffer = buffer >> 2;
|
||||
output.push(String.fromCharCode((buffer >> 8) & 0xFF));
|
||||
output.push(String.fromCharCode(buffer & 0xFF));
|
||||
}
|
||||
|
||||
return output.join('');
|
||||
};
|
||||
|
||||
global.btoa = global.btoa || function (input) {
|
||||
input = String(input);
|
||||
var position = 0,
|
||||
out = [],
|
||||
o1, o2, o3,
|
||||
e1, e2, e3, e4;
|
||||
|
||||
if (/[^\x00-\xFF]/.test(input)) { throw Error('InvalidCharacterError'); }
|
||||
|
||||
while (position < input.length) {
|
||||
o1 = input.charCodeAt(position++);
|
||||
o2 = input.charCodeAt(position++);
|
||||
o3 = input.charCodeAt(position++);
|
||||
|
||||
// 111111 112222 222233 333333
|
||||
e1 = o1 >> 2;
|
||||
e2 = ((o1 & 0x3) << 4) | (o2 >> 4);
|
||||
e3 = ((o2 & 0xf) << 2) | (o3 >> 6);
|
||||
e4 = o3 & 0x3f;
|
||||
|
||||
if (position === input.length + 2) {
|
||||
e3 = 64; e4 = 64;
|
||||
}
|
||||
else if (position === input.length + 1) {
|
||||
e4 = 64;
|
||||
}
|
||||
|
||||
out.push(B64_ALPHABET.charAt(e1),
|
||||
B64_ALPHABET.charAt(e2),
|
||||
B64_ALPHABET.charAt(e3),
|
||||
B64_ALPHABET.charAt(e4));
|
||||
}
|
||||
|
||||
return out.join('');
|
||||
};
|
||||
}(window));
|
||||
|
||||
//https://gist.github.com/jimeh/332357
|
||||
if (!Object.prototype.hasOwnProperty){
|
||||
/*jshint -W001, -W103 */
|
||||
Object.prototype.hasOwnProperty = function(prop) {
|
||||
var proto = this.__proto__ || this.constructor.prototype;
|
||||
return (prop in this) && (!(prop in proto) || proto[prop] !== this[prop]);
|
||||
};
|
||||
/*jshint +W001, +W103 */
|
||||
}
|
||||
|
||||
// @license http://opensource.org/licenses/MIT
|
||||
// copyright Paul Irish 2015
|
||||
|
||||
|
||||
// Date.now() is supported everywhere except IE8. For IE8 we use the Date.now polyfill
|
||||
// github.com/Financial-Times/polyfill-service/blob/master/polyfills/Date.now/polyfill.js
|
||||
// as Safari 6 doesn't have support for NavigationTiming, we use a Date.now() timestamp for relative values
|
||||
|
||||
// if you want values similar to what you'd get with real perf.now, place this towards the head of the page
|
||||
// but in reality, you're just getting the delta between now() calls, so it's not terribly important where it's placed
|
||||
|
||||
|
||||
(function(){
|
||||
|
||||
if ('performance' in window === false) {
|
||||
window.performance = {};
|
||||
}
|
||||
|
||||
Date.now = (Date.now || function () { // thanks IE8
|
||||
return new Date().getTime();
|
||||
});
|
||||
|
||||
if ('now' in window.performance === false){
|
||||
|
||||
var nowOffset = Date.now();
|
||||
|
||||
if (performance.timing && performance.timing.navigationStart){
|
||||
nowOffset = performance.timing.navigationStart;
|
||||
}
|
||||
|
||||
window.performance.now = function now(){
|
||||
return Date.now() - nowOffset;
|
||||
};
|
||||
}
|
||||
|
||||
})();
|
||||
|
||||
//requestAnimationFrame polyfill for older Firefox/Chrome versions
|
||||
if (!window.requestAnimationFrame) {
|
||||
if (window.webkitRequestAnimationFrame && window.webkitCancelAnimationFrame) {
|
||||
//https://github.com/Financial-Times/polyfill-service/blob/master/polyfills/requestAnimationFrame/polyfill-webkit.js
|
||||
(function (global) {
|
||||
global.requestAnimationFrame = function (callback) {
|
||||
return webkitRequestAnimationFrame(function () {
|
||||
callback(global.performance.now());
|
||||
});
|
||||
};
|
||||
|
||||
global.cancelAnimationFrame = global.webkitCancelAnimationFrame;
|
||||
}(window));
|
||||
} else if (window.mozRequestAnimationFrame && window.mozCancelAnimationFrame) {
|
||||
//https://github.com/Financial-Times/polyfill-service/blob/master/polyfills/requestAnimationFrame/polyfill-moz.js
|
||||
(function (global) {
|
||||
global.requestAnimationFrame = function (callback) {
|
||||
return mozRequestAnimationFrame(function () {
|
||||
callback(global.performance.now());
|
||||
});
|
||||
};
|
||||
|
||||
global.cancelAnimationFrame = global.mozCancelAnimationFrame;
|
||||
}(window));
|
||||
} else {
|
||||
(function (global) {
|
||||
global.requestAnimationFrame = function (callback) {
|
||||
return global.setTimeout(callback, 1000 / 60);
|
||||
};
|
||||
|
||||
global.cancelAnimationFrame = global.clearTimeout;
|
||||
})(window);
|
||||
}
|
||||
}
|
||||
})(this);
|
||||
102
vendor/assets/javascripts/holderjs/src/lib/vendor/querystring.js
vendored
Normal file
102
vendor/assets/javascripts/holderjs/src/lib/vendor/querystring.js
vendored
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
//Modified version of component/querystring
|
||||
//Changes: updated dependencies, dot notation parsing, JSHint fixes
|
||||
//Fork at https://github.com/imsky/querystring
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var encode = encodeURIComponent;
|
||||
var decode = decodeURIComponent;
|
||||
var trim = require('trim');
|
||||
var type = require('component-type');
|
||||
|
||||
var arrayRegex = /(\w+)\[(\d+)\]/;
|
||||
var objectRegex = /\w+\.\w+/;
|
||||
|
||||
/**
|
||||
* Parse the given query `str`.
|
||||
*
|
||||
* @param {String} str
|
||||
* @return {Object}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
exports.parse = function(str){
|
||||
if ('string' !== typeof str) return {};
|
||||
|
||||
str = trim(str);
|
||||
if ('' === str) return {};
|
||||
if ('?' === str.charAt(0)) str = str.slice(1);
|
||||
|
||||
var obj = {};
|
||||
var pairs = str.split('&');
|
||||
for (var i = 0; i < pairs.length; i++) {
|
||||
var parts = pairs[i].split('=');
|
||||
var key = decode(parts[0]);
|
||||
var m, ctx, prop;
|
||||
|
||||
if (m = arrayRegex.exec(key)) {
|
||||
obj[m[1]] = obj[m[1]] || [];
|
||||
obj[m[1]][m[2]] = decode(parts[1]);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (m = objectRegex.test(key)) {
|
||||
m = key.split('.');
|
||||
ctx = obj;
|
||||
|
||||
while (m.length) {
|
||||
prop = m.shift();
|
||||
|
||||
if (!prop.length) continue;
|
||||
|
||||
if (!ctx[prop]) {
|
||||
ctx[prop] = {};
|
||||
} else if (ctx[prop] && typeof ctx[prop] !== 'object') {
|
||||
break;
|
||||
}
|
||||
|
||||
if (!m.length) {
|
||||
ctx[prop] = decode(parts[1]);
|
||||
}
|
||||
|
||||
ctx = ctx[prop];
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
obj[parts[0]] = null == parts[1] ? '' : decode(parts[1]);
|
||||
}
|
||||
|
||||
return obj;
|
||||
};
|
||||
|
||||
/**
|
||||
* Stringify the given `obj`.
|
||||
*
|
||||
* @param {Object} obj
|
||||
* @return {String}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
exports.stringify = function(obj){
|
||||
if (!obj) return '';
|
||||
var pairs = [];
|
||||
|
||||
for (var key in obj) {
|
||||
var value = obj[key];
|
||||
|
||||
if ('array' == type(value)) {
|
||||
for (var i = 0; i < value.length; ++i) {
|
||||
pairs.push(encode(key + '[' + i + ']') + '=' + encode(value[i]));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
pairs.push(encode(key) + '=' + encode(obj[key]));
|
||||
}
|
||||
|
||||
return pairs.join('&');
|
||||
};
|
||||
12
vendor/assets/javascripts/holderjs/src/meteor/package.js
vendored
Normal file
12
vendor/assets/javascripts/holderjs/src/meteor/package.js
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
Package.describe({
|
||||
summary: '%summary%',
|
||||
version: '%version%',
|
||||
name: 'imsky:holder',
|
||||
git: 'https://github.com/imsky/holder',
|
||||
});
|
||||
|
||||
Package.onUse(function(api) {
|
||||
api.versionsFrom('0.9.0');
|
||||
api.export('Holder', 'client');
|
||||
api.addFiles('holder.js', 'client');
|
||||
});
|
||||
5
vendor/assets/javascripts/holderjs/src/meteor/shim.js
vendored
Normal file
5
vendor/assets/javascripts/holderjs/src/meteor/shim.js
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
(function(ctx, isMeteorPackage) {
|
||||
if (isMeteorPackage) {
|
||||
Holder = ctx.Holder;
|
||||
}
|
||||
})(this, typeof Meteor !== 'undefined' && typeof Package !== 'undefined');
|
||||
3050
vendor/assets/javascripts/holderjs/test/holder.js
vendored
Normal file
3050
vendor/assets/javascripts/holderjs/test/holder.js
vendored
Normal file
File diff suppressed because it is too large
Load diff
19
vendor/assets/javascripts/holderjs/test/index.js
vendored
Normal file
19
vendor/assets/javascripts/holderjs/test/index.js
vendored
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
var runner = require('./runner');
|
||||
var server = require('node-http-server');
|
||||
|
||||
server.deploy({
|
||||
'port': 8000,
|
||||
'root': __dirname
|
||||
});
|
||||
|
||||
runner({
|
||||
'browserName': 'chrome'
|
||||
}, function (err, retval) {
|
||||
console.log('Test result: ', retval);
|
||||
|
||||
if (!retval) {
|
||||
process.exitCode = -1;
|
||||
}
|
||||
|
||||
process.exit();
|
||||
});
|
||||
15
vendor/assets/javascripts/holderjs/test/phantom.js
vendored
Normal file
15
vendor/assets/javascripts/holderjs/test/phantom.js
vendored
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
var page = require('webpage').create();
|
||||
|
||||
page.onConsoleMessage = function (message) {
|
||||
console.log('Page: ', message);
|
||||
};
|
||||
|
||||
page.open('index.html', function (status) {
|
||||
console.log(status);
|
||||
|
||||
if (status === 'success') {
|
||||
page.render('phantom.png');
|
||||
}
|
||||
|
||||
phantom.exit();
|
||||
});
|
||||
3050
vendor/assets/javascripts/holderjs/test/renderperf/releases/holder-master/holder.js
vendored
Normal file
3050
vendor/assets/javascripts/holderjs/test/renderperf/releases/holder-master/holder.js
vendored
Normal file
File diff suppressed because it is too large
Load diff
37
vendor/assets/javascripts/holderjs/test/runner.js
vendored
Normal file
37
vendor/assets/javascripts/holderjs/test/runner.js
vendored
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
var client = require('webdriverio');
|
||||
|
||||
module.exports = function (options, cb) {
|
||||
var retval = true;
|
||||
|
||||
client.remote({
|
||||
'user': process.env.SAUCE_USERNAME,
|
||||
'key': process.env.SAUCE_ACCESS_KEY,
|
||||
'host': 'localhost',
|
||||
'port': 4445,
|
||||
'desiredCapabilities': {
|
||||
'browserName': options.browserName,
|
||||
'tunnel-identifier': process.env.TRAVIS_JOB_NUMBER,
|
||||
'name': 'Holder.js Test',
|
||||
'tags': [options.browserName]
|
||||
}
|
||||
})
|
||||
.init()
|
||||
.url('http://localhost:8000')
|
||||
.execute(function () {
|
||||
var expectImages = document.querySelectorAll('img').length - document.querySelectorAll('img[data-exclude]').length;
|
||||
var renderedImages = document.querySelectorAll('img[data-holder-rendered]').length;
|
||||
return {'expected': expectImages, 'rendered': renderedImages};
|
||||
}, function (err, ret) {
|
||||
var expected = ret.value.expected;
|
||||
var rendered = ret.value.rendered;
|
||||
console.log('Expected', expected);
|
||||
console.log('Rendered', rendered);
|
||||
if (expected !== rendered) {
|
||||
retval = false;
|
||||
}
|
||||
})
|
||||
.pause(15 * 1000)
|
||||
.end(function () {
|
||||
cb(null, retval);
|
||||
});
|
||||
};
|
||||
Loading…
Add table
Add a link
Reference in a new issue