diff --git a/components/ionSpinner/ionSpinner.html b/components/ionSpinner/ionSpinner.html
index 5cab289..d18a5e6 100644
--- a/components/ionSpinner/ionSpinner.html
+++ b/components/ionSpinner/ionSpinner.html
@@ -1,6 +1,3 @@
-
-
-
-
+
\ No newline at end of file
diff --git a/components/ionSpinner/ionSpinner.js b/components/ionSpinner/ionSpinner.js
index e26e5b1..05d2d29 100644
--- a/components/ionSpinner/ionSpinner.js
+++ b/components/ionSpinner/ionSpinner.js
@@ -1,437 +1,449 @@
-//$element.addClass('spinner spinner-' + spinnerName);
+
Template.ionSpinner.helpers({
- classes: function() {
- classes = [];
- if (this.class) {
- var customClasses = this.class.split(' ');
- _(customClasses).each(function(customClass) {
- classes.push(customClass);
- });
- }
-
- return classes.join(' ');
- },
-
- icon: function() {
- return this.icon;
+ classes: function() {
+ classes = [];
+ if (this.class) {
+ var customClasses = this.class.split(' ');
+ _(customClasses).each(function(customClass) {
+ classes.push(customClass);
+ });
}
+ return classes.join(' ');
+ },
+
+ icon: function() {
+ iconName = "spinner-" + (this.icon || 'ios');
+
+ return iconName;
+ }
});
+// the relevant code for getting the spinner element and assigning the
+// spinner names is in the init function at the bottom of this file.
+// Almost all of the rest of the code is from the ionic version.
Template.ionSpinner.rendered = function() {
- var TRANSLATE32 = 'translate(32,32)';
- var STROKE_OPACITY = 'stroke-opacity';
- var ROUND = 'round';
- var INDEFINITE = 'indefinite';
- var DURATION = '750ms';
- var NONE = 'none';
- var SHORTCUTS = {
- a: 'animate',
- an: 'attributeName',
- at: 'animateTransform',
- c: 'circle',
- da: 'stroke-dasharray',
- os: 'stroke-dashoffset',
- f: 'fill',
- lc: 'stroke-linecap',
- rc: 'repeatCount',
- sw: 'stroke-width',
- t: 'transform',
- v: 'values'
- };
- var SPIN_ANIMATION = {
- v: '0,32,32;360,32,32',
- an: 'transform',
- type: 'rotate',
- rc: INDEFINITE,
- dur: DURATION
- };
+ var TRANSLATE32 = 'translate(32,32)';
+ var STROKE_OPACITY = 'stroke-opacity';
+ var ROUND = 'round';
+ var INDEFINITE = 'indefinite';
+ var DURATION = '750ms';
+ var NONE = 'none';
+ var SHORTCUTS = {
+ a: 'animate',
+ an: 'attributeName',
+ at: 'animateTransform',
+ c: 'circle',
+ da: 'stroke-dasharray',
+ os: 'stroke-dashoffset',
+ f: 'fill',
+ lc: 'stroke-linecap',
+ rc: 'repeatCount',
+ sw: 'stroke-width',
+ t: 'transform',
+ v: 'values'
+ };
- function createSvgElement(tagName, data, parent, spinnerName) {
- var ele = document.createElement(SHORTCUTS[tagName] || tagName);
- var k, x, y;
- for (k in data) {
+ var SPIN_ANIMATION = {
+ v: '0,32,32;360,32,32',
+ an: 'transform',
+ type: 'rotate',
+ rc: INDEFINITE,
+ dur: DURATION
+ };
- if (Array.isArray(data[k])) {
- for (x = 0; x < data[k].length; x++) {
- if (data[k][x].fn) {
- for (y = 0; y < data[k][x].t; y++) {
- createSvgElement(k, data[k][x].fn(y, spinnerName), ele, spinnerName);
- }
- } else {
- createSvgElement(k, data[k][x], ele, spinnerName);
- }
- }
+ //get icon name and element from blaze template
- } else {
- setSvgAttribute(ele, k, data[k]);
+ var iconElement = this.firstNode;
+ this.data = this.data || {};
+ iconName = this.data.icon || 'ios';
+
+
+ function createSvgElement(tagName, data, parent, spinnerName) {
+ var ele = document.createElement(SHORTCUTS[tagName] || tagName);
+ var k, x, y;
+ for (k in data) {
+
+ if (Array.isArray(data[k])) {
+ for (x = 0; x < data[k].length; x++) {
+ if (data[k][x].fn) {
+ for (y = 0; y < data[k][x].t; y++) {
+ createSvgElement(k, data[k][x].fn(y, spinnerName), ele, spinnerName);
}
+ } else {
+ createSvgElement(k, data[k][x], ele, spinnerName);
+ }
}
- parent.appendChild(ele);
+ } else {
+ setSvgAttribute(ele, k, data[k]);
+ }
}
- function setSvgAttribute(ele, k, v) {
- ele.setAttribute(SHORTCUTS[k] || k, v);
- }
+ parent.appendChild(ele);
+ }
- function animationValues(strValues, i) {
- var values = strValues.split(';');
- var back = values.slice(i);
- var front = values.slice(0, values.length - back.length);
- values = back.concat(front).reverse();
- return values.join(';') + ';' + values[0];
- }
+ function setSvgAttribute(ele, k, v) {
+ ele.setAttribute(SHORTCUTS[k] || k, v);
+ }
- var IOS_SPINNER = {
+ function animationValues(strValues, i) {
+ var values = strValues.split(';');
+ var back = values.slice(i);
+ var front = values.slice(0, values.length - back.length);
+ values = back.concat(front).reverse();
+ return values.join(';') + ';' + values[0];
+ }
+
+ var IOS_SPINNER = {
+ sw: 4,
+ lc: ROUND,
+ line: [{
+ fn: function(i, spinnerName) {
+ return {
+ y1: spinnerName == 'ios' ? 17 : 12,
+ y2: spinnerName == 'ios' ? 29 : 20,
+ t: TRANSLATE32 + ' rotate(' + (30 * i + (i < 6 ? 180 : -180)) + ')',
+ a: [{
+ fn: function() {
+ return {
+ an: STROKE_OPACITY,
+ dur: DURATION,
+ v: animationValues('0;.1;.15;.25;.35;.45;.55;.65;.7;.85;1', i),
+ rc: INDEFINITE
+ };
+ },
+ t: 1
+ }]
+ };
+ },
+ t: 12
+ }]
+ };
+
+ var spinners = {
+
+ android: {
+ c: [{
+ sw: 6,
+ da: 128,
+ os: 82,
+ r: 26,
+ cx: 32,
+ cy: 32,
+ f: NONE
+ }]
+ },
+
+ ios: IOS_SPINNER,
+
+ 'ios-small': IOS_SPINNER,
+
+ bubbles: {
+ sw: 0,
+ c: [{
+ fn: function(i) {
+ return {
+ cx: 24 * Math.cos(2 * Math.PI * i / 8),
+ cy: 24 * Math.sin(2 * Math.PI * i / 8),
+ t: TRANSLATE32,
+ a: [{
+ fn: function() {
+ return {
+ an: 'r',
+ dur: DURATION,
+ v: animationValues('1;2;3;4;5;6;7;8', i),
+ rc: INDEFINITE
+ };
+ },
+ t: 1
+ }]
+ };
+ },
+ t: 8
+ }]
+ },
+
+ circles: {
+
+ c: [{
+ fn: function(i) {
+ return {
+ r: 5,
+ cx: 24 * Math.cos(2 * Math.PI * i / 8),
+ cy: 24 * Math.sin(2 * Math.PI * i / 8),
+ t: TRANSLATE32,
+ sw: 0,
+ a: [{
+ fn: function() {
+ return {
+ an: 'fill-opacity',
+ dur: DURATION,
+ v: animationValues('.3;.3;.3;.4;.7;.85;.9;1', i),
+ rc: INDEFINITE
+ };
+ },
+ t: 1
+ }]
+ };
+ },
+ t: 8
+ }]
+ },
+
+ crescent: {
+ c: [{
+ sw: 4,
+ da: 128,
+ os: 82,
+ r: 26,
+ cx: 32,
+ cy: 32,
+ f: NONE,
+ at: [SPIN_ANIMATION]
+ }]
+ },
+
+ dots: {
+
+ c: [{
+ fn: function(i) {
+ return {
+ cx: 16 + (16 * i),
+ cy: 32,
+ sw: 0,
+ a: [{
+ fn: function() {
+ return {
+ an: 'fill-opacity',
+ dur: DURATION,
+ v: animationValues('.5;.6;.8;1;.8;.6;.5', i),
+ rc: INDEFINITE
+ };
+ },
+ t: 1
+ }, {
+ fn: function() {
+ return {
+ an: 'r',
+ dur: DURATION,
+ v: animationValues('4;5;6;5;4;3;3', i),
+ rc: INDEFINITE
+ };
+ },
+ t: 1
+ }]
+ };
+ },
+ t: 3
+ }]
+ },
+
+ lines: {
+ sw: 7,
+ lc: ROUND,
+ line: [{
+ fn: function(i) {
+ return {
+ x1: 10 + (i * 14),
+ x2: 10 + (i * 14),
+ a: [{
+ fn: function() {
+ return {
+ an: 'y1',
+ dur: DURATION,
+ v: animationValues('16;18;28;18;16', i),
+ rc: INDEFINITE
+ };
+ },
+ t: 1
+ }, {
+ fn: function() {
+ return {
+ an: 'y2',
+ dur: DURATION,
+ v: animationValues('48;44;36;46;48', i),
+ rc: INDEFINITE
+ };
+ },
+ t: 1
+ }, {
+ fn: function() {
+ return {
+ an: STROKE_OPACITY,
+ dur: DURATION,
+ v: animationValues('1;.8;.5;.4;1', i),
+ rc: INDEFINITE
+ };
+ },
+ t: 1
+ }]
+ };
+ },
+ t: 4
+ }]
+ },
+
+ ripple: {
+ f: NONE,
+ 'fill-rule': 'evenodd',
+ sw: 3,
+ circle: [{
+ fn: function(i) {
+ return {
+ cx: 32,
+ cy: 32,
+ a: [{
+ fn: function() {
+ return {
+ an: 'r',
+ begin: (i * -1) + 's',
+ dur: '2s',
+ v: '0;24',
+ keyTimes: '0;1',
+ keySplines: '0.1,0.2,0.3,1',
+ calcMode: 'spline',
+ rc: INDEFINITE
+ };
+ },
+ t: 1
+ }, {
+ fn: function() {
+ return {
+ an: STROKE_OPACITY,
+ begin: (i * -1) + 's',
+ dur: '2s',
+ v: '.2;1;.2;0',
+ rc: INDEFINITE
+ };
+ },
+ t: 1
+ }]
+ };
+ },
+ t: 2
+ }]
+ },
+
+ spiral: {
+ defs: [{
+ linearGradient: [{
+ id: 'sGD',
+ gradientUnits: 'userSpaceOnUse',
+ x1: 55,
+ y1: 46,
+ x2: 2,
+ y2: 46,
+ stop: [{
+ offset: 0.1,
+ class: 'stop1'
+ }, {
+ offset: 1,
+ class: 'stop2'
+ }]
+ }]
+ }],
+ g: [{
sw: 4,
lc: ROUND,
- line: [{
- fn: function(i, spinnerName) {
- return {
- y1: spinnerName == 'ios' ? 17 : 12,
- y2: spinnerName == 'ios' ? 29 : 20,
- t: TRANSLATE32 + ' rotate(' + (30 * i + (i < 6 ? 180 : -180)) + ')',
- a: [{
- fn: function() {
- return {
- an: STROKE_OPACITY,
- dur: DURATION,
- v: animationValues('0;.1;.15;.25;.35;.45;.55;.65;.7;.85;1', i),
- rc: INDEFINITE
- };
- },
- t: 1
- }]
- };
- },
- t: 12
- }]
- };
-
- var spinners = {
-
- android: {
- c: [{
- sw: 6,
- da: 128,
- os: 82,
- r: 26,
- cx: 32,
- cy: 32,
- f: NONE
- }]
- },
-
- ios: IOS_SPINNER,
-
- 'ios-small': IOS_SPINNER,
-
- bubbles: {
- sw: 0,
- c: [{
- fn: function(i) {
- return {
- cx: 24 * Math.cos(2 * Math.PI * i / 8),
- cy: 24 * Math.sin(2 * Math.PI * i / 8),
- t: TRANSLATE32,
- a: [{
- fn: function() {
- return {
- an: 'r',
- dur: DURATION,
- v: animationValues('1;2;3;4;5;6;7;8', i),
- rc: INDEFINITE
- };
- },
- t: 1
- }]
- };
- },
- t: 8
- }]
- },
-
- circles: {
-
- c: [{
- fn: function(i) {
- return {
- r: 5,
- cx: 24 * Math.cos(2 * Math.PI * i / 8),
- cy: 24 * Math.sin(2 * Math.PI * i / 8),
- t: TRANSLATE32,
- sw: 0,
- a: [{
- fn: function() {
- return {
- an: 'fill-opacity',
- dur: DURATION,
- v: animationValues('.3;.3;.3;.4;.7;.85;.9;1', i),
- rc: INDEFINITE
- };
- },
- t: 1
- }]
- };
- },
- t: 8
- }]
- },
-
- crescent: {
- c: [{
- sw: 4,
- da: 128,
- os: 82,
- r: 26,
- cx: 32,
- cy: 32,
- f: NONE,
- at: [SPIN_ANIMATION]
- }]
- },
-
- dots: {
-
- c: [{
- fn: function(i) {
- return {
- cx: 16 + (16 * i),
- cy: 32,
- sw: 0,
- a: [{
- fn: function() {
- return {
- an: 'fill-opacity',
- dur: DURATION,
- v: animationValues('.5;.6;.8;1;.8;.6;.5', i),
- rc: INDEFINITE
- };
- },
- t: 1
- }, {
- fn: function() {
- return {
- an: 'r',
- dur: DURATION,
- v: animationValues('4;5;6;5;4;3;3', i),
- rc: INDEFINITE
- };
- },
- t: 1
- }]
- };
- },
- t: 3
- }]
- },
-
- lines: {
- sw: 7,
- lc: ROUND,
- line: [{
- fn: function(i) {
- return {
- x1: 10 + (i * 14),
- x2: 10 + (i * 14),
- a: [{
- fn: function() {
- return {
- an: 'y1',
- dur: DURATION,
- v: animationValues('16;18;28;18;16', i),
- rc: INDEFINITE
- };
- },
- t: 1
- }, {
- fn: function() {
- return {
- an: 'y2',
- dur: DURATION,
- v: animationValues('48;44;36;46;48', i),
- rc: INDEFINITE
- };
- },
- t: 1
- }, {
- fn: function() {
- return {
- an: STROKE_OPACITY,
- dur: DURATION,
- v: animationValues('1;.8;.5;.4;1', i),
- rc: INDEFINITE
- };
- },
- t: 1
- }]
- };
- },
- t: 4
- }]
- },
-
- ripple: {
- f: NONE,
- 'fill-rule': 'evenodd',
- sw: 3,
- circle: [{
- fn: function(i) {
- return {
- cx: 32,
- cy: 32,
- a: [{
- fn: function() {
- return {
- an: 'r',
- begin: (i * -1) + 's',
- dur: '2s',
- v: '0;24',
- keyTimes: '0;1',
- keySplines: '0.1,0.2,0.3,1',
- calcMode: 'spline',
- rc: INDEFINITE
- };
- },
- t: 1
- }, {
- fn: function() {
- return {
- an: STROKE_OPACITY,
- begin: (i * -1) + 's',
- dur: '2s',
- v: '.2;1;.2;0',
- rc: INDEFINITE
- };
- },
- t: 1
- }]
- };
- },
- t: 2
- }]
- },
-
- spiral: {
- defs: [{
- linearGradient: [{
- id: 'sGD',
- gradientUnits: 'userSpaceOnUse',
- x1: 55,
- y1: 46,
- x2: 2,
- y2: 46,
- stop: [{
- offset: 0.1,
- class: 'stop1'
- }, {
- offset: 1,
- class: 'stop2'
- }]
- }]
- }],
- g: [{
- sw: 4,
- lc: ROUND,
- f: NONE,
- path: [{
- stroke: 'url(#sGD)',
- d: 'M4,32 c0,15,12,28,28,28c8,0,16-4,21-9'
- }, {
- d: 'M60,32 C60,16,47.464,4,32,4S4,16,4,32'
- }],
- at: [SPIN_ANIMATION]
- }]
- }
-
- };
-
- var animations = {
-
- android: function(ele) {
- var rIndex = 0;
- var rotateCircle = 0;
- var startTime;
- var svgEle = ele.querySelector('g');
- var circleEle = ele.querySelector('circle');
-
- function run() {
- var v = easeInOutCubic(Date.now() - startTime, 650);
- var scaleX = 1;
- var translateX = 0;
- var dasharray = (188 - (58 * v));
- var dashoffset = (182 - (182 * v));
-
- if (rIndex % 2) {
- scaleX = -1;
- translateX = -64;
- dasharray = (128 - (-58 * v));
- dashoffset = (182 * v);
- }
-
- var rotateLine = [0, -101, -90, -11, -180, 79, -270, -191][rIndex];
-
- setSvgAttribute(circleEle, 'da', Math.max(Math.min(dasharray, 188), 128));
- setSvgAttribute(circleEle, 'os', Math.max(Math.min(dashoffset, 182), 0));
- setSvgAttribute(circleEle, 't', 'scale(' + scaleX + ',1) translate(' + translateX + ',0) rotate(' + rotateLine + ',32,32)');
-
- rotateCircle += 4.1;
- if (rotateCircle > 359) rotateCircle = 0;
- setSvgAttribute(svgEle, 't', 'rotate(' + rotateCircle + ',32,32)');
-
- if (v >= 1) {
- rIndex++;
- if (rIndex > 7) rIndex = 0;
- startTime = Date.now();
- }
-
- ionic.requestAnimationFrame(run);
- }
-
- return function() {
- startTime = Date.now();
- run();
- };
-
- }
-
- };
-
- function easeInOutCubic(t, c) {
- t /= c / 2;
- if (t < 1) return 1 / 2 * t * t * t;
- t -= 2;
- return 1 / 2 * (t * t * t + 2);
+ f: NONE,
+ path: [{
+ stroke: 'url(#sGD)',
+ d: 'M4,32 c0,15,12,28,28,28c8,0,16-4,21-9'
+ }, {
+ d: 'M60,32 C60,16,47.464,4,32,4S4,16,4,32'
+ }],
+ at: [SPIN_ANIMATION]
+ }]
}
- init();
+ };
- function init() {
- var spinnerName = $('.spinner').attr('id');
- var $element = $('.spinner');
- var container = $('.spinner')[0];
- createSvgElement('svg', {
- viewBox: '0 0 64 64',
- g: [spinners[spinnerName]]
- }, container, spinnerName);
+ var animations = {
- // Specifically for animations to work,
- // Android 4.3 and below requires the element to be
- // added as an html string, rather than dynmically
- // building up the svg element and appending it.
- $element.html(container.innerHTML);
+ android: function(ele) {
+ var rIndex = 0;
+ var rotateCircle = 0;
+ var startTime;
+ var svgEle = ele.querySelector('g');
+ var circleEle = ele.querySelector('circle');
- start(spinnerName);
+ function run() {
+ var v = easeInOutCubic(Date.now() - startTime, 650);
+ var scaleX = 1;
+ var translateX = 0;
+ var dasharray = (188 - (58 * v));
+ var dashoffset = (182 - (182 * v));
- // return spinnerName;
- };
+ if (rIndex % 2) {
+ scaleX = -1;
+ translateX = -64;
+ dasharray = (128 - (-58 * v));
+ dashoffset = (182 * v);
+ }
- function start(spinnerName) {
- animations[spinnerName] && animations[spinnerName]($element[0])();
- };
+ var rotateLine = [0, -101, -90, -11, -180, 79, -270, -191][rIndex];
+
+ setSvgAttribute(circleEle, 'da', Math.max(Math.min(dasharray, 188), 128));
+ setSvgAttribute(circleEle, 'os', Math.max(Math.min(dashoffset, 182), 0));
+ setSvgAttribute(circleEle, 't', 'scale(' + scaleX + ',1) translate(' + translateX + ',0) rotate(' + rotateLine + ',32,32)');
+
+ rotateCircle += 4.1;
+ if (rotateCircle > 359) rotateCircle = 0;
+ setSvgAttribute(svgEle, 't', 'rotate(' + rotateCircle + ',32,32)');
+
+ if (v >= 1) {
+ rIndex++;
+ if (rIndex > 7) rIndex = 0;
+ startTime = Date.now();
+ }
+
+ ionic.requestAnimationFrame(run);
+ }
+
+ return function() {
+ startTime = Date.now();
+ run();
+ };
+
+ }
+
+ };
+
+ function easeInOutCubic(t, c) {
+ t /= c / 2;
+ if (t < 1) return 1 / 2 * t * t * t;
+ t -= 2;
+ return 1 / 2 * (t * t * t + 2);
+ }
+
+ init();
+
+ function init() {
+
+ var spinnerName = iconName;
+ var $element = $(iconElement);
+ var container = iconElement;
+ createSvgElement('svg', {
+ viewBox: '0 0 64 64',
+ g: [spinners[spinnerName]]
+ }, container, spinnerName);
+
+ // Specifically for animations to work,
+ // Android 4.3 and below requires the element to be
+ // added as an html string, rather than dynmically
+ // building up the svg element and appending it.
+ $element.html(container.innerHTML);
+
+ start(spinnerName);
+
+ };
+
+ function start(spinnerName) {
+ animations[spinnerName] && animations[spinnerName]($element[0])();
+ };
}