From 1d54fa161c2ad60269f9129d9bedc2bc54a3501b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Peter=20M=C3=BCller?=
Date: Wed, 13 Jun 2012 12:07:10 +0200
Subject: [PATCH 01/28] Reduced colors in fork.png to 128
---
public/img/fork.png | Bin 9267 -> 3981 bytes
1 file changed, 0 insertions(+), 0 deletions(-)
diff --git a/public/img/fork.png b/public/img/fork.png
index 7dc1afca60b9d40dcd402703f5b29717583150d7..aba9b3965d73d2ca1ba1a57940ffa78be4b8f9f3 100644
GIT binary patch
literal 3981
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
A%K!iX
literal 9267
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
V)~XPt9$f$c002ovPDHLkV1fgJi?9Fy
From 97d866d380c59f35e3d24106cb5613dafa458da0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Peter=20M=C3=BCller?=
Date: Wed, 13 Jun 2012 12:07:56 +0200
Subject: [PATCH 02/28] Upgraded to assetgraph-builder 0.2.37 to gain better IE
support for embedded css backgrounds
---
package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/package.json b/package.json
index a298c3a..b02dfe2 100644
--- a/package.json
+++ b/package.json
@@ -23,7 +23,7 @@
"connect": "~2.0.3"
},
"devDependencies": {
- "assetgraph-builder": "latest"
+ "assetgraph-builder": ">=0.2.37"
},
"engines": {
"node": ">=0.6"
From 682ac820cdb7051bbf1da0597056519de9b7c628 Mon Sep 17 00:00:00 2001
From: Yannick Croissant
Date: Tue, 21 Aug 2012 00:53:19 +0200
Subject: [PATCH 03/28] Fix a graphical bug in Firefox
---
public/js/lib/models/arrow.js | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/public/js/lib/models/arrow.js b/public/js/lib/models/arrow.js
index 7488d0b..88eb512 100644
--- a/public/js/lib/models/arrow.js
+++ b/public/js/lib/models/arrow.js
@@ -36,6 +36,22 @@ if (!('CSSArrowPlease' in window)) window.CSSArrowPlease = {};
else if ( pos === 'right' ) return 'left';
},
+ /**
+ @method hexToRGB
+ @description
+ returns an rgb color from an hex color
+ @returns {Array}
+ **/
+ hexToRGB: function (h) {
+ var rgb = [],
+ i = 1;
+
+ for(; i < 6; i+=2) {
+ rgb.push(parseInt(h.substring(i, i + 2), 16));
+ }
+ return rgb;
+ },
+
/**
@method _baseCSS
@description generates the base css
@@ -87,12 +103,14 @@ if (!('CSSArrowPlease' in window)) window.CSSArrowPlease = {};
_arrowCSS: function (color, size, layer) {
var pos = this.get('position'),
iPos = this.invertedPosition(),
+ rgbColor = this.hexToRGB(color),
css = ".arrow_box:";
layer = layer || 'after';
css += layer + ' {\n';
+ css += '\tborder-color: rgba(' + rgbColor.join(', ') + ', 0);\n';
css += '\tborder-' + iPos + '-color: ' + color + ';\n';
css += '\tborder-width: ' + size + 'px;\n';
From 518399e6983082c62a30ee0407e4afaa4c9170bb Mon Sep 17 00:00:00 2001
From: Yannick Croissant
Date: Tue, 21 Aug 2012 11:53:39 +0200
Subject: [PATCH 04/28] add 3 char hex color support in hexToRGB function add
input checking in hexToRGB function
---
public/js/lib/models/arrow.js | 2 ++
1 file changed, 2 insertions(+)
diff --git a/public/js/lib/models/arrow.js b/public/js/lib/models/arrow.js
index 88eb512..262db02 100644
--- a/public/js/lib/models/arrow.js
+++ b/public/js/lib/models/arrow.js
@@ -43,6 +43,8 @@ if (!('CSSArrowPlease' in window)) window.CSSArrowPlease = {};
@returns {Array}
**/
hexToRGB: function (h) {
+ if ( typeof h !== 'string' || !h.match(/^#([0-9A-F]{3}$)|([0-9A-F]{6}$)/i) ) return [0, 0, 0];
+ else if ( h.match(/^(#[0-9a-f]{3})$/i) ) h = '#' + h[1] + h[1] + h[2] + h[2] + h[3] + h[3];
var rgb = [],
i = 1;
From 142f7a1235bda9208c57649c57aa4c276af032d5 Mon Sep 17 00:00:00 2001
From: Yannick Croissant
Date: Tue, 21 Aug 2012 11:53:49 +0200
Subject: [PATCH 05/28] add tests for hexToRGB function and _arrowCSS border
color
---
public/js/spec/models/arrow_spec.js | 29 +++++++++++++++++++++++++++--
1 file changed, 27 insertions(+), 2 deletions(-)
diff --git a/public/js/spec/models/arrow_spec.js b/public/js/spec/models/arrow_spec.js
index 6e98ff5..eaa73f7 100644
--- a/public/js/spec/models/arrow_spec.js
+++ b/public/js/spec/models/arrow_spec.js
@@ -96,6 +96,30 @@ describe("CSSArrowPlease.Arrow", function () {
});
+ describe('convert hex color to rgb color', function () {
+
+ it('converts "#888"', function () {
+ expect( arrow.hexToRGB('#888') ).toEqual([136 , 136 , 136]);
+ });
+
+ it('converts "#88B7D5"', function () {
+ expect( arrow.hexToRGB('#88B7D5') ).toEqual([136, 183, 213]);
+ });
+
+ it('converts "#C2E1F5"', function () {
+ expect( arrow.hexToRGB('#C2E1F5') ).toEqual([194, 225, 245]);
+ });
+
+ it('returns [0, 0, 0] if there is no input color', function () {
+ expect( arrow.hexToRGB() ).toEqual([0, 0, 0]);
+ });
+
+ it('returns [0, 0, 0] if the input color is invalid', function () {
+ expect( arrow.hexToRGB('invalid') ).toEqual([0, 0, 0]);
+ });
+
+ });
+
describe('toCSS', function () {
describe('baseCSS', function () {
@@ -177,8 +201,9 @@ describe("CSSArrowPlease.Arrow", function () {
});
it('it has the correct color', function () {
- var expected = 'border-bottom-color: #888';
- expect( arrow._arrowCSS('#888', 20) ).toMatch( expected );
+ var css = arrow._arrowCSS('#888', 20);
+ expect( css ).toMatch( 'border-bottom-color: #888' );
+ expect( css ).toMatch( 'border-color: rgba\\(136, 136, 136, 0\\)' );
});
describe('position top', function () {
From 097d2f14c0a833ca3ea898ec644b4edda1340d1c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Simon=20H=C3=B8jberg?=
Date: Sat, 25 Aug 2012 13:14:02 -0400
Subject: [PATCH 06/28] deployed
---
package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/package.json b/package.json
index b02dfe2..101c85f 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "cssarrowplease",
- "version": "0.2.2-10",
+ "version": "0.2.2-13",
"author": {
"name": "Simon Højberg",
"email": "r.hackr@gmail.com"
From 3f7a9662b85e3f30c0cc29826720dea1b3f1686e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Simon=20H=C3=B8jberg?=
Date: Wed, 28 Nov 2012 23:04:11 -0500
Subject: [PATCH 07/28] dont fade fork
---
public/css/app.css | 13 +------------
1 file changed, 1 insertion(+), 12 deletions(-)
diff --git a/public/css/app.css b/public/css/app.css
index c4d0947..5cdc1eb 100644
--- a/public/css/app.css
+++ b/public/css/app.css
@@ -58,15 +58,4 @@ input[type='radio'] { border: 0; }
/* fork_me */
-.fork_me { position: absolute; top: 0; right: 0; display: block; width: 149px; height: 149px; background: url(../img/fork.png);
- opacity: 0.7;
- -webkit-transition: all 0.2s ease-in;
- -moz-transition: all 0.2s ease-in;
- transition: all 0.2s ease-in;
-}
-.fork_me:hover {
- opacity: 1;
- -webkit-transform: scale(1.03);
- -moz-transform: scale(1.03);
- transform: scale(1.03);
-}
+.fork_me { position: absolute; top: 0; right: 0; display: block; width: 149px; height: 149px; background: url(../img/fork.png); }
From a96cb6a8da84e97d945fc275c83c908e01d927ea Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Simon=20H=C3=B8jberg?=
Date: Wed, 28 Nov 2012 23:05:17 -0500
Subject: [PATCH 08/28] deploy
---
package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/package.json b/package.json
index 101c85f..17be371 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "cssarrowplease",
- "version": "0.2.2-13",
+ "version": "0.2.2-15",
"author": {
"name": "Simon Højberg",
"email": "r.hackr@gmail.com"
From eb80717ed44cf3c4f140d933bc013c081945d733 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Simon=20H=C3=B8jberg?=
Date: Sun, 23 Dec 2012 22:07:51 -0500
Subject: [PATCH 09/28] Use filter dropshadow
---
public/css/app.css | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/public/css/app.css b/public/css/app.css
index 5cdc1eb..d33bd83 100644
--- a/public/css/app.css
+++ b/public/css/app.css
@@ -32,7 +32,11 @@ input[type='radio'] { border: 0; }
/* =MODULES
====================================================== */
/* preview */
-.arrow_box { padding: 40px; width: 280px; height: 100px; border-radius: 6px; box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3); }
+.arrow_box { padding: 40px; width: 280px; height: 100px; border-radius: 6px;
+ -webkit-filter: drop-shadow(0 1px 4px rgba(0, 0, 0, 0.3));
+ -moz-filter: drop-shadow(0 1px 4px rgba(0, 0, 0, 0.3));
+ filter: drop-shadow(0 1px 4px rgba(0, 0, 0, 0.3));
+}
/* logo */
.logo { color: #ddf8c6; text-align: center; font-size: 54px; line-height: 54px; font-weight: bold; text-transform: uppercase; text-shadow: 0 1px 2px rgba(0, 0, 0, 0.4); }
From 620da6f4bb4abb833656b320fbbbb215c367f183 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Simon=20H=C3=B8jberg?=
Date: Sun, 23 Dec 2012 22:09:07 -0500
Subject: [PATCH 10/28] firefox fallback
---
public/css/app.css | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/public/css/app.css b/public/css/app.css
index d33bd83..ea7a844 100644
--- a/public/css/app.css
+++ b/public/css/app.css
@@ -33,8 +33,9 @@ input[type='radio'] { border: 0; }
====================================================== */
/* preview */
.arrow_box { padding: 40px; width: 280px; height: 100px; border-radius: 6px;
+ -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3);
+
-webkit-filter: drop-shadow(0 1px 4px rgba(0, 0, 0, 0.3));
- -moz-filter: drop-shadow(0 1px 4px rgba(0, 0, 0, 0.3));
filter: drop-shadow(0 1px 4px rgba(0, 0, 0, 0.3));
}
From 10d9098e0392330bfe04ff453b49fc3f6a2550fc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Simon=20H=C3=B8jberg?=
Date: Sun, 23 Dec 2012 22:11:44 -0500
Subject: [PATCH 11/28] deploy
---
package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/package.json b/package.json
index 17be371..c458abe 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "cssarrowplease",
- "version": "0.2.2-15",
+ "version": "0.2.2-16",
"author": {
"name": "Simon Højberg",
"email": "r.hackr@gmail.com"
From 0e9d69181b25c48638226132b1a28f762ab0530e Mon Sep 17 00:00:00 2001
From: yukulele
Date: Tue, 21 May 2013 11:44:14 +0200
Subject: [PATCH 12/28] add svg drop-shadow filter
-moz-box-shadow dont seam to works anymore
---
public/css/app.css | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/public/css/app.css b/public/css/app.css
index ea7a844..9959457 100644
--- a/public/css/app.css
+++ b/public/css/app.css
@@ -33,10 +33,12 @@ input[type='radio'] { border: 0; }
====================================================== */
/* preview */
.arrow_box { padding: 40px; width: 280px; height: 100px; border-radius: 6px;
- -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3);
+ /*-moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3);*/
+ filter: url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%3E%3Cfilter%20id%3D%27drop-shadow%27%3E%3CfeGaussianBlur%20in%3D%27SourceAlpha%27%20stdDeviation%3D%274%27%2F%3E%3CfeOffset%20dx%3D%270%27%20dy%3D%271%27%20result%3D%27offsetblur%27%2F%3E%3CfeFlood%20flood-color%3D%27rgba(0,0,0,0.3)%27%2F%3E%3CfeComposite%20in2%3D%27offsetblur%27%20operator%3D%27in%27%2F%3E%3CfeMerge%3E%3CfeMergeNode%2F%3E%3CfeMergeNode%20in%3D%27SourceGraphic%27%2F%3E%3C%2FfeMerge%3E%3C%2Ffilter%3E%3C%2Fsvg%3E#drop-shadow");
-webkit-filter: drop-shadow(0 1px 4px rgba(0, 0, 0, 0.3));
filter: drop-shadow(0 1px 4px rgba(0, 0, 0, 0.3));
+
}
/* logo */
From 13c90a66b6b4c608c66d769babe4c5c9ff8673c8 Mon Sep 17 00:00:00 2001
From: bra1n
Date: Fri, 1 Nov 2013 18:35:45 +0100
Subject: [PATCH 13/28] moved redundant absolute positioning to common styles
adjusted unittests to reflect changes
---
public/js/lib/models/arrow.js | 14 +++++++++++---
public/js/spec/models/arrow_spec.js | 29 +++++++++++++++++------------
2 files changed, 28 insertions(+), 15 deletions(-)
diff --git a/public/js/lib/models/arrow.js b/public/js/lib/models/arrow.js
index 262db02..e2f3350 100644
--- a/public/js/lib/models/arrow.js
+++ b/public/js/lib/models/arrow.js
@@ -61,7 +61,8 @@ if (!('CSSArrowPlease' in window)) window.CSSArrowPlease = {};
@protected
**/
_baseCSS: function () {
- var iPos = this.invertedPosition(),
+ var pos = this.get('position'),
+ iPos = this.invertedPosition(),
color = this.get('color'),
borderWidth = this.get('borderWidth'),
borderColor = this.get('borderColor'),
@@ -81,6 +82,13 @@ if (!('CSSArrowPlease' in window)) window.CSSArrowPlease = {};
css += '\t' + iPos +': 100%;\n';
+ if (pos === 'top' || pos === 'bottom') {
+ css += '\tleft: 50%;\n';
+ }
+ else {
+ css += '\ttop: 50%;\n';
+ }
+
css += '\tborder: solid transparent;\n';
css += '\tcontent: " ";\n';
css += '\theight: 0;\n';
@@ -117,10 +125,10 @@ if (!('CSSArrowPlease' in window)) window.CSSArrowPlease = {};
css += '\tborder-width: ' + size + 'px;\n';
if (pos === 'top' || pos === 'bottom') {
- css += '\tleft: 50%;\n\tmargin-left: -' + size + 'px;\n';
+ css += '\tmargin-left: -' + size + 'px;\n';
}
else {
- css += '\ttop: 50%;\n\tmargin-top: -' + size + 'px;\n';
+ css += '\tmargin-top: -' + size + 'px;\n';
}
css += '}';
diff --git a/public/js/spec/models/arrow_spec.js b/public/js/spec/models/arrow_spec.js
index eaa73f7..ff3a7a8 100644
--- a/public/js/spec/models/arrow_spec.js
+++ b/public/js/spec/models/arrow_spec.js
@@ -134,6 +134,7 @@ describe("CSSArrowPlease.Arrow", function () {
expected;
expected = '\tbottom: 100%;\n';
+ expected = '\tleft: 50%;\n';
expected += '\tborder: solid transparent;\n';
expected += '\tcontent: " ";\n';
expected += '\theight: 0;\n';
@@ -210,9 +211,10 @@ describe("CSSArrowPlease.Arrow", function () {
beforeEach(function () { arrow.set('position', 'top'); });
it('is centered', function () {
- var css = arrow._arrowCSS('red', 20);
- expect( css ).toMatch( 'left: 50%' );
- expect( css ).toMatch( 'margin-left: -20px' );
+ var arrowcss = arrow._arrowCSS('red', 20),
+ basecss = arrow._baseCSS();
+ expect( basecss ).toMatch( 'left: 50%' );
+ expect( arrowcss ).toMatch( 'margin-left: -20px' );
});
});
@@ -220,9 +222,10 @@ describe("CSSArrowPlease.Arrow", function () {
beforeEach(function () { arrow.set('position', 'bottom'); });
it('is centered', function () {
- var css = arrow._arrowCSS('red', 20);
- expect( css ).toMatch( 'left: 50%' );
- expect( css ).toMatch( 'margin-left: -20px' );
+ var arrowcss = arrow._arrowCSS('red', 20),
+ basecss = arrow._baseCSS();
+ expect( basecss ).toMatch( 'left: 50%' );
+ expect( arrowcss ).toMatch( 'margin-left: -20px' );
});
});
@@ -230,9 +233,10 @@ describe("CSSArrowPlease.Arrow", function () {
beforeEach(function () { arrow.set('position', 'right'); });
it('is centered', function () {
- var css = arrow._arrowCSS('red', 20);
- expect( css ).toMatch( 'top: 50%' );
- expect( css ).toMatch( 'margin-top: -20px' );
+ var arrowcss = arrow._arrowCSS('red', 20),
+ basecss = arrow._baseCSS();
+ expect( basecss ).toMatch( 'top: 50%' );
+ expect( arrowcss ).toMatch( 'margin-top: -20px' );
});
});
@@ -240,9 +244,10 @@ describe("CSSArrowPlease.Arrow", function () {
beforeEach(function () { arrow.set('position', 'left'); });
it('is centered', function () {
- var css = arrow._arrowCSS('red', 20);
- expect( css ).toMatch( 'top: 50%' );
- expect( css ).toMatch( 'margin-top: -20px' );
+ var arrowcss = arrow._arrowCSS('red', 20),
+ basecss = arrow._baseCSS();
+ expect( basecss ).toMatch( 'top: 50%' );
+ expect( arrowcss ).toMatch( 'margin-top: -20px' );
});
});
From 246dbad2e2c109da30d50cdefe27559f935bfd7e Mon Sep 17 00:00:00 2001
From: bra1n
Date: Fri, 1 Nov 2013 18:59:39 +0100
Subject: [PATCH 14/28] better handling of zero border width case
---
public/js/lib/models/arrow.js | 15 ++++++++-------
1 file changed, 8 insertions(+), 7 deletions(-)
diff --git a/public/js/lib/models/arrow.js b/public/js/lib/models/arrow.js
index e2f3350..aced0c3 100644
--- a/public/js/lib/models/arrow.js
+++ b/public/js/lib/models/arrow.js
@@ -96,7 +96,7 @@ if (!('CSSArrowPlease' in window)) window.CSSArrowPlease = {};
css += '\tposition: absolute;\n';
css += '\tpointer-events: none;\n';
- css += '}\n';
+ if(hasBorder) css += '}\n';
return css;
},
@@ -111,14 +111,15 @@ if (!('CSSArrowPlease' in window)) window.CSSArrowPlease = {};
@protected
**/
_arrowCSS: function (color, size, layer) {
- var pos = this.get('position'),
- iPos = this.invertedPosition(),
- rgbColor = this.hexToRGB(color),
- css = ".arrow_box:";
+ var pos = this.get('position'),
+ iPos = this.invertedPosition(),
+ rgbColor = this.hexToRGB(color),
+ borderWidth = this.get('borderWidth'),
+ css = "";
layer = layer || 'after';
- css += layer + ' {\n';
+ if(borderWidth > 0) css += '.arrow_box:' + layer + ' {\n';
css += '\tborder-color: rgba(' + rgbColor.join(', ') + ', 0);\n';
css += '\tborder-' + iPos + '-color: ' + color + ';\n';
@@ -184,7 +185,7 @@ if (!('CSSArrowPlease' in window)) window.CSSArrowPlease = {};
this._arrowBorderCSS()
];
- return css.join('\n');
+ return css.join(css[2] ? '\n':'');
},
/**
From 313058366fe7dd5d26816aca7e579cce9acdd826 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Simon=20H=C3=B8jberg?=
Date: Wed, 13 Nov 2013 16:24:04 -0500
Subject: [PATCH 15/28] remove arrow box drop shadow
---
public/css/app.css | 9 +--------
1 file changed, 1 insertion(+), 8 deletions(-)
diff --git a/public/css/app.css b/public/css/app.css
index 9959457..c137a21 100644
--- a/public/css/app.css
+++ b/public/css/app.css
@@ -32,14 +32,7 @@ input[type='radio'] { border: 0; }
/* =MODULES
====================================================== */
/* preview */
-.arrow_box { padding: 40px; width: 280px; height: 100px; border-radius: 6px;
- /*-moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3);*/
-
- filter: url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%3E%3Cfilter%20id%3D%27drop-shadow%27%3E%3CfeGaussianBlur%20in%3D%27SourceAlpha%27%20stdDeviation%3D%274%27%2F%3E%3CfeOffset%20dx%3D%270%27%20dy%3D%271%27%20result%3D%27offsetblur%27%2F%3E%3CfeFlood%20flood-color%3D%27rgba(0,0,0,0.3)%27%2F%3E%3CfeComposite%20in2%3D%27offsetblur%27%20operator%3D%27in%27%2F%3E%3CfeMerge%3E%3CfeMergeNode%2F%3E%3CfeMergeNode%20in%3D%27SourceGraphic%27%2F%3E%3C%2FfeMerge%3E%3C%2Ffilter%3E%3C%2Fsvg%3E#drop-shadow");
- -webkit-filter: drop-shadow(0 1px 4px rgba(0, 0, 0, 0.3));
- filter: drop-shadow(0 1px 4px rgba(0, 0, 0, 0.3));
-
-}
+.arrow_box { padding: 40px; width: 280px; height: 100px; border-radius: 6px; }
/* logo */
.logo { color: #ddf8c6; text-align: center; font-size: 54px; line-height: 54px; font-weight: bold; text-transform: uppercase; text-shadow: 0 1px 2px rgba(0, 0, 0, 0.4); }
From e9d0b487c4fac8fc45a0efa8b1c99573e08f34ff Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Simon=20H=C3=B8jberg?=
Date: Wed, 13 Nov 2013 16:26:23 -0500
Subject: [PATCH 16/28] deploy
---
package.json | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/package.json b/package.json
index c458abe..a47cfab 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "cssarrowplease",
- "version": "0.2.2-16",
+ "version": "0.2.2-18",
"author": {
"name": "Simon Højberg",
"email": "r.hackr@gmail.com"
@@ -41,4 +41,4 @@
"cssarrowplease.com",
"www.cssarrowplease.com"
]
-}
\ No newline at end of file
+}
From 598fc92c2ddea3eafe8338d7e1ae96c9ba8580ec Mon Sep 17 00:00:00 2001
From: Stefan Hasenstab
Date: Tue, 8 Jul 2014 15:56:33 +0200
Subject: [PATCH 17/28] sanitize hex colors by prefixing missing # if necessary
---
public/js/lib/models/arrow.js | 18 +++++++++++++++++-
1 file changed, 17 insertions(+), 1 deletion(-)
diff --git a/public/js/lib/models/arrow.js b/public/js/lib/models/arrow.js
index aced0c3..4ba0d95 100644
--- a/public/js/lib/models/arrow.js
+++ b/public/js/lib/models/arrow.js
@@ -69,10 +69,15 @@ if (!('CSSArrowPlease' in window)) window.CSSArrowPlease = {};
hasBorder = borderWidth > 0,
css = '.arrow_box {\n';
+ color = this._sanitizeHexColors(color);
+
css += '\tposition: relative;\n';
css += '\tbackground: ' + color + ';\n';
- if (hasBorder) css += '\tborder: ' + borderWidth + 'px solid ' + borderColor + ';\n';
+ if (hasBorder) {
+ borderColor = this._sanitizeHexColors(borderColor);
+ css += '\tborder: ' + borderWidth + 'px solid ' + borderColor + ';\n';
+ }
css += '}\n';
css += '.arrow_box:after';
@@ -111,6 +116,7 @@ if (!('CSSArrowPlease' in window)) window.CSSArrowPlease = {};
@protected
**/
_arrowCSS: function (color, size, layer) {
+ color = this._sanitizeHexColors(color);
var pos = this.get('position'),
iPos = this.invertedPosition(),
rgbColor = this.hexToRGB(color),
@@ -204,6 +210,16 @@ if (!('CSSArrowPlease' in window)) window.CSSArrowPlease = {};
this._attributes = attributes;
},
+ /**
+ @method _sanitizeHexColors
+ @description prefix hexcolors with # if necessary
+ @returns {String} h
+ @protected
+ **/
+ _sanitizeHexColors: function(h) {
+ return (h.charAt(0)==='#')?h:'#' + h;
+ },
+
/**
@method getAttrs
@description returns all the attributes
From a77d696e923b44040675498fbbb542fe3a73e974 Mon Sep 17 00:00:00 2001
From: Stefan Hasenstab
Date: Mon, 14 Jul 2014 10:16:11 +0200
Subject: [PATCH 18/28] changed code indention to 2 spaces
---
public/js/lib/models/arrow.js | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/public/js/lib/models/arrow.js b/public/js/lib/models/arrow.js
index 4ba0d95..a23af2c 100644
--- a/public/js/lib/models/arrow.js
+++ b/public/js/lib/models/arrow.js
@@ -75,8 +75,8 @@ if (!('CSSArrowPlease' in window)) window.CSSArrowPlease = {};
css += '\tbackground: ' + color + ';\n';
if (hasBorder) {
- borderColor = this._sanitizeHexColors(borderColor);
- css += '\tborder: ' + borderWidth + 'px solid ' + borderColor + ';\n';
+ borderColor = this._sanitizeHexColors(borderColor);
+ css += '\tborder: ' + borderWidth + 'px solid ' + borderColor + ';\n';
}
css += '}\n';
@@ -217,7 +217,7 @@ if (!('CSSArrowPlease' in window)) window.CSSArrowPlease = {};
@protected
**/
_sanitizeHexColors: function(h) {
- return (h.charAt(0)==='#')?h:'#' + h;
+ return (h.charAt(0)==='#')?h:'#' + h;
},
/**
From 486917ec0b11955f77ade992393816cfe3920303 Mon Sep 17 00:00:00 2001
From: Ryan McDermott
Date: Fri, 18 Jul 2014 17:56:25 -0500
Subject: [PATCH 19/28] Add SEO meta description
---
public/index.html | 1 +
1 file changed, 1 insertion(+)
diff --git a/public/index.html b/public/index.html
index 413f523..4159f24 100644
--- a/public/index.html
+++ b/public/index.html
@@ -3,6 +3,7 @@
cssarrowplease
+
From 636e45e02c2db2f4626c61cc9dd0752592aa52ee Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Simon=20H=C3=B8jberg?=
Date: Sat, 2 Aug 2014 10:26:10 -0700
Subject: [PATCH 20/28] simplify deploymeny and serving
---
.gitignore | 1 -
bin/server | 18 ------------------
package.json | 6 +-----
public/index.html | 2 +-
server.js | 10 ++++++++++
5 files changed, 12 insertions(+), 25 deletions(-)
delete mode 100644 bin/server
create mode 100644 server.js
diff --git a/.gitignore b/.gitignore
index b5b56cf..ac1e8f7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,3 @@
node_modules
-public-min
*.log
.DS_Store
diff --git a/bin/server b/bin/server
deleted file mode 100644
index f1ef1b5..0000000
--- a/bin/server
+++ /dev/null
@@ -1,18 +0,0 @@
-#!/usr/bin/env node
-
-var connect = require('connect'),
- http = require('http'),
- port = process.env.PORT || 3000,
- static;
-
-if (process.argv.indexOf('--development') !== -1) {
- console.log('CSS Arrow Please in development on http://localhost:' + port);
- static = connect.static('public');
-}
-else {
- static = connect.static('public-min', {
- maxAge: 365 * 24 * 60 * 60 * 1000
- });
-}
-
-http.createServer( connect().use( static ) ).listen( port );
diff --git a/package.json b/package.json
index a47cfab..ebe8566 100644
--- a/package.json
+++ b/package.json
@@ -6,7 +6,6 @@
"email": "r.hackr@gmail.com"
},
"description": "Generate the CSS for a tooltip arrow",
- "main": "",
"repository": {
"type": "git",
"url": "git://github.com/hojberg/cssarrowplease.git"
@@ -17,14 +16,11 @@
],
"homepage": "http://cssarrowplease.com/",
"scripts": {
- "start": "node ./bin/server"
+ "start": "node ./server.js"
},
"dependencies": {
"connect": "~2.0.3"
},
- "devDependencies": {
- "assetgraph-builder": ">=0.2.37"
- },
"engines": {
"node": ">=0.6"
},
diff --git a/public/index.html b/public/index.html
index 4159f24..fa3c54c 100644
--- a/public/index.html
+++ b/public/index.html
@@ -56,7 +56,7 @@ Arrow configuration
-
+
Fork me on Github
diff --git a/server.js b/server.js
new file mode 100644
index 0000000..b0e74db
--- /dev/null
+++ b/server.js
@@ -0,0 +1,10 @@
+#!/usr/bin/env node
+
+var connect = require('connect');
+var http = require('http');
+var port = process.env.PORT || 3000;
+var static = connect.static('public');
+
+console.log('CSSArrowPlease on http://localhost:' + port);
+
+http.createServer( connect().use( static ) ).listen( port );
From 1805c42055f89a4d8fd99632bb7fdd996a3ff6cc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Simon=20H=C3=B8jberg?=
Date: Sat, 2 Aug 2014 10:29:31 -0700
Subject: [PATCH 21/28] deploy version 0.2.2-19
---
package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/package.json b/package.json
index ebe8566..822f80d 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "cssarrowplease",
- "version": "0.2.2-18",
+ "version": "0.2.2-19",
"author": {
"name": "Simon Højberg",
"email": "r.hackr@gmail.com"
From 02dadb5c9abc64e3864686c2635b15df5b5e6c5a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Simon=20H=C3=B8jberg?=
Date: Sat, 2 Aug 2014 11:50:24 -0700
Subject: [PATCH 22/28] add proper testing setup and browserify
---
app/main.js | 49 +
app/models/arrow.js | 291 +
app/views/arrow_configuration_view.js | 108 +
app/views/arrow_css_view.js | 44 +
app/views/arrow_preview_view.js | 39 +
package.json | 15 +-
public/css/app.css | 2 -
public/index.html | 48 +-
public/js/cssarrowplease.js | 9734 +++++++++++++++++
public/js/lib/app.js | 52 -
public/js/lib/models/arrow.js | 297 -
.../js/lib/views/arrow_configuration_view.js | 115 -
public/js/lib/views/arrow_css_view.js | 54 -
public/js/lib/views/arrow_preview_view.js | 47 -
public/js/spec/app_spec.js | 3 -
.../js/spec/views/arrow_preview_view_spec.js | 32 -
public/js/spec_runner.html | 60 -
public/js/vendor/jasmine/jasmine-html.js | 676 --
public/js/vendor/jasmine/jasmine.css | 81 -
public/js/vendor/jasmine/jasmine.js | 2528 -----
.../vendor/jquery.clippy/jquery.clippy.min.js | 1 -
server.js | 2 -
.../arrow_configuration_view_test.js | 40 +-
.../arrow_css_view_test.js | 32 +-
test/arrow_preview_view_test.js | 43 +
.../arrow_spec.js => test/arrow_test.js | 130 +-
test/test_helper.js | 5 +
27 files changed, 10450 insertions(+), 4078 deletions(-)
create mode 100644 app/main.js
create mode 100644 app/models/arrow.js
create mode 100644 app/views/arrow_configuration_view.js
create mode 100644 app/views/arrow_css_view.js
create mode 100644 app/views/arrow_preview_view.js
create mode 100644 public/js/cssarrowplease.js
delete mode 100644 public/js/lib/app.js
delete mode 100644 public/js/lib/models/arrow.js
delete mode 100644 public/js/lib/views/arrow_configuration_view.js
delete mode 100644 public/js/lib/views/arrow_css_view.js
delete mode 100644 public/js/lib/views/arrow_preview_view.js
delete mode 100644 public/js/spec/app_spec.js
delete mode 100644 public/js/spec/views/arrow_preview_view_spec.js
delete mode 100644 public/js/spec_runner.html
delete mode 100644 public/js/vendor/jasmine/jasmine-html.js
delete mode 100644 public/js/vendor/jasmine/jasmine.css
delete mode 100644 public/js/vendor/jasmine/jasmine.js
delete mode 100755 public/js/vendor/jquery.clippy/jquery.clippy.min.js
rename public/js/spec/views/arrow_configuration_view_spec.js => test/arrow_configuration_view_test.js (70%)
rename public/js/spec/views/arrow_css_view_spec.js => test/arrow_css_view_test.js (52%)
create mode 100644 test/arrow_preview_view_test.js
rename public/js/spec/models/arrow_spec.js => test/arrow_test.js (65%)
create mode 100644 test/test_helper.js
diff --git a/app/main.js b/app/main.js
new file mode 100644
index 0000000..54ceca7
--- /dev/null
+++ b/app/main.js
@@ -0,0 +1,49 @@
+var $ = require('jquery');
+var Arrow = require('./models/arrow');
+var ArrowConfigurationView = require('./views/arrow_configuration_view');
+var ArrowPreviewView = require('./views/arrow_preview_view');
+var ArrowCSSView = require('./views/arrow_css_view');
+
+/**
+@class App
+@constructor
+@description
+ Main application object.
+ Acts as view dispatcher
+**/
+var App = function () {
+ this.init.apply(this, arguments);
+};
+
+App.prototype = {
+
+ init: function () {
+ this.model = new Arrow();
+ this._initViews();
+ },
+
+ /**
+ @method _initViews
+ @description initializes views
+ @protected
+ **/
+ _initViews: function () {
+ var model = this.model;
+
+ this.views = [
+ new ArrowConfigurationView({ model: model, container: $('.configuration') }),
+ new ArrowPreviewView({ model: model, container: $('').appendTo('body') }),
+ new ArrowCSSView({ model: model, container: $('.css_result') }),
+ ];
+ },
+
+ render: function () {
+ $.each(this.views, function (i, view) {
+ view.render();
+ });
+ }
+
+};
+
+new App().render();
+
diff --git a/app/models/arrow.js b/app/models/arrow.js
new file mode 100644
index 0000000..fafde4d
--- /dev/null
+++ b/app/models/arrow.js
@@ -0,0 +1,291 @@
+var $ = require('jquery');
+
+/**
+@class Arrow
+@constructor
+**/
+var Arrow = function () {
+ this.init.apply(this, arguments);
+};
+
+Arrow.prototype = {
+
+ init: function () {
+ // jquerify 'this'
+ this._$self = $(this);
+
+ this._createAttrs();
+ },
+
+ /**
+ @method invertedPosition
+ @description
+ returns the opposite of the position
+ so 'top' becomes 'bottom' and 'left' becomes 'right'
+ @returns {String}
+ **/
+ invertedPosition: function () {
+ var pos = this.get('position');
+
+ if ( pos === 'top' ) return 'bottom';
+ else if ( pos === 'bottom') return 'top';
+ else if ( pos === 'left' ) return 'right';
+ else if ( pos === 'right' ) return 'left';
+ },
+
+ /**
+ @method hexToRGB
+ @description
+ returns an rgb color from an hex color
+ @returns {Array}
+ **/
+ hexToRGB: function (h) {
+ if ( typeof h !== 'string' || !h.match(/^#([0-9A-F]{3}$)|([0-9A-F]{6}$)/i) ) return [0, 0, 0];
+ else if ( h.match(/^(#[0-9a-f]{3})$/i) ) h = '#' + h[1] + h[1] + h[2] + h[2] + h[3] + h[3];
+ var rgb = [],
+ i = 1;
+
+ for(; i < 6; i+=2) {
+ rgb.push(parseInt(h.substring(i, i + 2), 16));
+ }
+ return rgb;
+ },
+
+ /**
+ @method _baseCSS
+ @description generates the base css
+ @returns {String} css
+ @protected
+ **/
+ _baseCSS: function () {
+ var pos = this.get('position'),
+ iPos = this.invertedPosition(),
+ color = this.get('color'),
+ borderWidth = this.get('borderWidth'),
+ borderColor = this.get('borderColor'),
+ hasBorder = borderWidth > 0,
+ css = '.arrow_box {\n';
+
+ color = this._sanitizeHexColors(color);
+
+ css += '\tposition: relative;\n';
+ css += '\tbackground: ' + color + ';\n';
+
+ if (hasBorder) {
+ borderColor = this._sanitizeHexColors(borderColor);
+ css += '\tborder: ' + borderWidth + 'px solid ' + borderColor + ';\n';
+ }
+
+ css += '}\n';
+ css += '.arrow_box:after';
+
+ if (hasBorder) css += ', .arrow_box:before {\n';
+ else css += ' {\n';
+
+ css += '\t' + iPos +': 100%;\n';
+
+ if (pos === 'top' || pos === 'bottom') {
+ css += '\tleft: 50%;\n';
+ }
+ else {
+ css += '\ttop: 50%;\n';
+ }
+
+ css += '\tborder: solid transparent;\n';
+ css += '\tcontent: " ";\n';
+ css += '\theight: 0;\n';
+ css += '\twidth: 0;\n';
+ css += '\tposition: absolute;\n';
+ css += '\tpointer-events: none;\n';
+
+ if (hasBorder) css += '}\n';
+
+ return css;
+ },
+
+ /**
+ @method _arrowCSS
+ @description generates arrow css
+ @param {String} color the color of the arrow
+ @param {Integer} size the size of the arrow
+ @param {String} layer :after or :before (defaults to :after)
+ @returns {String} css
+ @protected
+ **/
+ _arrowCSS: function (color, size, layer) {
+ color = this._sanitizeHexColors(color);
+ var pos = this.get('position'),
+ iPos = this.invertedPosition(),
+ rgbColor = this.hexToRGB(color),
+ borderWidth = this.get('borderWidth'),
+ css = "";
+
+ layer = layer || 'after';
+
+ if(borderWidth > 0) css += '.arrow_box:' + layer + ' {\n';
+
+ css += '\tborder-color: rgba(' + rgbColor.join(', ') + ', 0);\n';
+ css += '\tborder-' + iPos + '-color: ' + color + ';\n';
+ css += '\tborder-width: ' + size + 'px;\n';
+
+ if (pos === 'top' || pos === 'bottom') {
+ css += '\tmargin-left: -' + size + 'px;\n';
+ }
+ else {
+ css += '\tmargin-top: -' + size + 'px;\n';
+ }
+
+ css += '}';
+
+ return css;
+ },
+
+ /**
+ @method _baseArrowCSS
+ @description generates the base arrow
+ @returns {String} css
+ @protected
+ **/
+ _baseArrowCSS: function () {
+ return this._arrowCSS(
+ this.get('color'),
+ this.get('size'),
+ 'after'
+ );
+ },
+
+ /**
+ @method _arrowBorderCSS
+ @description generates the border arrow
+ @returns {String} css
+ @protected
+ **/
+ _arrowBorderCSS: function () {
+ var css = '',
+ borderWidth = this.get('borderWidth');
+
+ if (borderWidth > 0) {
+ css = this._arrowCSS(
+ this.get('borderColor'),
+ this.get('size') + Math.round(borderWidth * 1.41421356), // cos(PI/4) * 2
+ 'before'
+ );
+ }
+
+ return css;
+ },
+
+ /**
+ @method toCSS
+ @description returns a CSS representation of the arrow
+ @returns {String} css
+ **/
+ toCSS: function () {
+
+ var css = [
+ this._baseCSS(),
+ this._baseArrowCSS(),
+ this._arrowBorderCSS()
+ ];
+
+ return css.join(css[2] ? '\n':'');
+ },
+
+ /**
+ @method _createAttrs
+ @description creates attributes from the ATTR constant
+ @protected
+ **/
+ _createAttrs: function () {
+ var ATTRS = Arrow.ATTRS,
+ attributes = {};
+
+ $.each(ATTRS, function (attr, value) {
+ attributes[attr] = value;
+ });
+
+ this._attributes = attributes;
+ },
+
+ /**
+ @method _sanitizeHexColors
+ @description prefix hexcolors with # if necessary
+ @returns {String} h
+ @protected
+ **/
+ _sanitizeHexColors: function(h) {
+ return (h.charAt(0)==='#')?h:'#' + h;
+ },
+
+ /**
+ @method getAttrs
+ @description returns all the attributes
+ @returns {Object} all the model attributes
+ **/
+ getAttrs: function () {
+ return this._attributes;
+ },
+
+ /**
+ @method get
+ @description returns the provided attribute
+ @param {String} attr the attribute to return
+ @returns {?} the attribute
+ **/
+ get: function (attr) {
+ return this._attributes[attr];
+ },
+
+ /**
+ @method set
+ @description updates the provided attribute
+ @param {String} attr the attribute to update
+ @param {?} val the value to update with
+ **/
+ set: function (attr, val) {
+ if (!(attr in this._attributes)) return;
+
+ this._attributes[attr] = val;
+ this.fire('change');
+ },
+
+ /**
+ @method on
+ @description adds event listeners
+ @note uses jQuery custom events under the hood
+ @param {String} evType the event type
+ @param {Function} callback the event handler
+ @param {Object} context the 'this' for the callback
+ **/
+ on: function (evType, callback, context) {
+ var $self = this._$self;
+
+ $self.on(
+ evType,
+ $.proxy(callback, context || this)
+ );
+ },
+
+ /**
+ @method fire
+ @description trigger event
+ @note uses jQuery custom events under the hood
+ @param {String} evType the event type
+ **/
+ fire: function (evType) {
+ var $self = this._$self;
+
+ $self.trigger(evType);
+ }
+
+};
+
+Arrow.ATTRS = {
+ position: 'top',
+ size: 30,
+ color: '#88b7d5',
+ borderWidth: 4,
+ borderColor: '#c2e1f5'
+};
+
+module.exports = Arrow;
diff --git a/app/views/arrow_configuration_view.js b/app/views/arrow_configuration_view.js
new file mode 100644
index 0000000..93595c6
--- /dev/null
+++ b/app/views/arrow_configuration_view.js
@@ -0,0 +1,108 @@
+var $ = require('jquery');
+
+/**
+@class ArrowConfigurationView
+@constructor
+**/
+var ArrowConfigurationView = function () {
+ this.init.apply(this, arguments);
+};
+
+ArrowConfigurationView.prototype = {
+
+ init: function (options) {
+ this.container = options.container;
+ this.model = options.model;
+
+ this._attachEvents();
+ },
+
+ /**
+ @method render
+ @chainable
+ **/
+ render: function () {
+ this._setDefaults();
+ return this;
+ },
+
+ /**
+ @method _setDetaults
+ @description update the view with the model defaults
+ **/
+ _setDefaults: function () {
+ var container = this.container,
+ model = this.model;
+
+ container.find('.position').val([ model.get('position') ]);
+ container.find('.size').val( model.get('size') );
+ container.find('.base_color').val( model.get('color') );
+ container.find('.border_width').val( model.get('borderWidth') );
+ container.find('.border_color').val( model.get('borderColor') );
+ },
+
+ /**
+ @method _attachEvents
+ @description attaches dom events
+ @protected
+ **/
+ _attachEvents: function () {
+ var _updateModelProxy = this._updateModel.bind(this),
+ _updateInputProxy = this._updateInput.bind(this),
+ container = this.container,
+ selectors = [ { classname: '.position', keyboard_interactive: false },
+ { classname: '.size', keyboard_interactive: true },
+ { classname: '.base_color', keyboard_interactive: false },
+ { classname: '.border_width', keyboard_interactive: true },
+ { classname: '.border_color', keyboard_interactive: false }
+ ];
+
+ selectors.forEach(function (selector, i) {
+ container.delegate(selector.classname, 'change', _updateModelProxy);
+ if (selector.keyboard_interactive) {
+ container.delegate(selector.classname, 'keydown', _updateInputProxy);
+ }
+ });
+ },
+
+ _updateModel: function (ev) {
+ var target = $(ev.currentTarget),
+ val = target.val(),
+ attr;
+
+
+ if (target.hasClass('border_width')) {
+ attr = 'borderWidth';
+ }
+ else if (target.hasClass('border_color')) {
+ attr = 'borderColor';
+ }
+ else if (target.hasClass('base_color')) {
+ attr = 'color';
+ }
+ else {
+ attr = target.attr('class');
+ }
+
+ if (attr === 'borderWidth' || attr === 'size') val = parseInt(val, 10);
+ this.model.set(attr, val);
+ },
+
+ _updateInput: function (ev) {
+ if (ev.keyCode != 38 && ev.keyCode != 40) return;
+
+ var target = $(ev.currentTarget),
+ val = parseInt(target.val()),
+ increment = ev.keyCode == 38 ? 1 : -1,
+ multiply = ev.shiftKey ? 10 : 1,
+ newVal = val + increment * multiply;
+
+ if (newVal < 0) newVal = 0;
+
+ target.val(newVal);
+ this._updateModel(ev);
+ }
+
+};
+
+module.exports = ArrowConfigurationView;
diff --git a/app/views/arrow_css_view.js b/app/views/arrow_css_view.js
new file mode 100644
index 0000000..efe89ce
--- /dev/null
+++ b/app/views/arrow_css_view.js
@@ -0,0 +1,44 @@
+/**
+@class ArrowCSSView
+@constructor
+**/
+var ArrowCSSView = function () {
+ this.init.apply(this, arguments);
+};
+
+ArrowCSSView.prototype = {
+
+ init: function (options) {
+ this.container = options.container;
+ this._codeNode = this.container.find('.code');
+ this._copyNode = this.container.find('.copy_code');
+
+ this.model = options.model;
+ this.model.on('change', this._handleChange, this);
+ },
+
+ /**
+ @method _handleChange
+ @description handles changes to the model
+ @chainable
+ **/
+ _handleChange: function () {
+ this.render();
+ },
+
+ /**
+ @method render
+ @description renders the model's css
+ @chainable
+ **/
+ render: function () {
+ var css = this.model.toCSS();
+
+ this._codeNode.text( css );
+
+ return this;
+ }
+
+};
+
+module.exports = ArrowCSSView;
diff --git a/app/views/arrow_preview_view.js b/app/views/arrow_preview_view.js
new file mode 100644
index 0000000..61d7941
--- /dev/null
+++ b/app/views/arrow_preview_view.js
@@ -0,0 +1,39 @@
+/**
+@class ArrowPreviewView
+@constructor
+**/
+var ArrowPreviewView = function () {
+ this.init.apply(this, arguments);
+};
+
+ArrowPreviewView.prototype = {
+
+ init: function (options) {
+ this.container = options.container;
+ this.model = options.model;
+
+ this.model.on('change', this._handleChange, this);
+ },
+
+ /**
+ @method _handleChange
+ @description handles changes to the model
+ @chainable
+ **/
+ _handleChange: function () {
+ this.render();
+ },
+
+ /**
+ @method render
+ @description renders the css to style the preview
+ @chainable
+ **/
+ render: function () {
+ this.container.text( this.model.toCSS() );
+ return this;
+ }
+
+};
+
+module.exports = ArrowPreviewView;
diff --git a/package.json b/package.json
index 822f80d..258cd66 100644
--- a/package.json
+++ b/package.json
@@ -16,13 +16,22 @@
],
"homepage": "http://cssarrowplease.com/",
"scripts": {
- "start": "node ./server.js"
+ "start": "node ./server.js",
+ "build": "./node_modules/browserify/bin/cmd.js -e app/main.js -o public/js/cssarrowplease.js",
+ "test": "mocha --require=test/test_helper.js"
},
"dependencies": {
- "connect": "~2.0.3"
+ "connect": "~2.0.3",
+ "browserify": "latest",
+ "jquery": "latest",
+ "jsdom": "latest",
+ "mocha": "latest",
+ "chai": "latest",
+ "sinon": "latest",
+ "sinon-chai": "latest"
},
"engines": {
- "node": ">=0.6"
+ "node": ">=0.10"
},
"licenses": [
{
diff --git a/public/css/app.css b/public/css/app.css
index c137a21..fbf43dc 100644
--- a/public/css/app.css
+++ b/public/css/app.css
@@ -54,8 +54,6 @@ input[type='radio'] { border: 0; }
/* css_result */
.css_result { position: relative; float: right; width: 402px; }
.css_result .code { white-space: pre; padding: 10px; display: block; width: 380px; font-size: 12px; font-family: 'Courier new'; font-weight: bold; background: #8c9196; background: rgba(0, 0, 0, 0.15); border-radius: 4px; color: #fff; text-shadow: 0 1px 1px rgba(0, 0, 0, 0.3); border: 1px solid #696d72; border-color: rgba(0, 0, 0, 0.2); box-shadow: 0 1px 1px 0 rgba(255, 255, 255, 0.3), inset 0 1px 5px rgba(0, 0, 0, 0.1); }
-.css_result .copy_code { position: absolute; bottom: 5px; right: 10px; width: 14px; height: 22px; background: url(../img/clippy.png) no-repeat 0 4px; }
-
/* fork_me */
.fork_me { position: absolute; top: 0; right: 0; display: block; width: 149px; height: 149px; background: url(../img/fork.png); }
diff --git a/public/index.html b/public/index.html
index fa3c54c..c336ad7 100644
--- a/public/index.html
+++ b/public/index.html
@@ -73,50 +73,30 @@ Arrow configuration
-
-
-
-
-
-
-
-
+