Skip to content

Commit 11adddd

Browse files
committed
Reactify cssarrowplease
1 parent e9d0b48 commit 11adddd

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+16952
-5487
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
node_modules
2-
public-min
2+
build
33
*.log
44
.DS_Store

Gruntfile.js

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
module.exports = function(grunt) {
2+
grunt.initConfig({
3+
pkg: grunt.file.readJSON('package.json'),
4+
5+
// =watch
6+
watch: {
7+
react: {
8+
files: ['app/**/*.js'],
9+
tasks: ['react'],
10+
options: { interrupt: true}
11+
},
12+
browserify: {
13+
files: ['build/**/*.js'],
14+
tasks: ['browserify'],
15+
options: { interrupt: true}
16+
}
17+
},
18+
19+
react: {
20+
files: {
21+
expand: true,
22+
cwd: './app',
23+
src: ['**/*.js'],
24+
dest: './build',
25+
ext: '.js'
26+
}
27+
},
28+
29+
browserify: {
30+
all: {
31+
src: 'build/main.js',
32+
dest: 'public/js/cssarrowplease.js'
33+
}
34+
}
35+
});
36+
37+
grunt.registerTask('build', ['react', 'browserify']);
38+
grunt.registerTask('default', 'build');
39+
40+
grunt.loadNpmTasks('grunt-contrib-watch');
41+
grunt.loadNpmTasks('grunt-browserify');
42+
grunt.loadNpmTasks('grunt-react');
43+
};

Makefile

Lines changed: 0 additions & 12 deletions
This file was deleted.

app/app.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/** @jsx React.DOM */
2+
3+
var Page = require('./components/page');
4+
5+
var App = function (props) {
6+
this.container = props.container;
7+
};
8+
9+
App.prototype = {
10+
run: function () {
11+
React.renderComponent(
12+
<Page/>,
13+
this.container
14+
);
15+
}
16+
};
17+
18+
module.exports = App;

app/arrow_generator.js

Lines changed: 252 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,252 @@
1+
/**
2+
@class Arrow
3+
@constructor
4+
**/
5+
var Arrow = function () {
6+
this._createAttrs();
7+
};
8+
9+
Arrow.prototype = {
10+
/**
11+
returns the opposite of the position
12+
so 'top' becomes 'bottom' and 'left' becomes 'right'
13+
@method invertedPosition
14+
@returns {String}
15+
**/
16+
invertedPosition: function () {
17+
var pos = this.get('position');
18+
19+
if ( pos === 'top' ) return 'bottom';
20+
else if ( pos === 'bottom') return 'top';
21+
else if ( pos === 'left' ) return 'right';
22+
else if ( pos === 'right' ) return 'left';
23+
},
24+
25+
/**
26+
returns an rgb color from an hex color
27+
28+
@method hexToRGB
29+
@returns {Array}
30+
**/
31+
hexToRGB: function (h) {
32+
if ( typeof h !== 'string' || !h.match(/^#([0-9A-F]{3}$)|([0-9A-F]{6}$)/i) ) return [0, 0, 0];
33+
else if ( h.match(/^(#[0-9a-f]{3})$/i) ) h = '#' + h[1] + h[1] + h[2] + h[2] + h[3] + h[3];
34+
var rgb = [],
35+
i = 1;
36+
37+
for(; i < 6; i+=2) {
38+
rgb.push(parseInt(h.substring(i, i + 2), 16));
39+
}
40+
return rgb;
41+
},
42+
43+
/**
44+
generates the base css
45+
46+
@method _baseCSS
47+
@returns {String} css
48+
@protected
49+
**/
50+
_baseCSS: function () {
51+
var pos = this.get('position'),
52+
iPos = this.invertedPosition(),
53+
color = this.get('color'),
54+
borderSize = this.get('borderSize'),
55+
borderColor = this.get('borderColor'),
56+
hasBorder = borderSize > 0,
57+
css = '.with-arrow {\n';
58+
59+
css += '\tposition: relative;\n';
60+
css += '\tbackground: ' + color + ';\n';
61+
62+
if (hasBorder) css += '\tborder: ' + borderSize + 'px solid ' + borderColor + ';\n';
63+
64+
css += '}\n';
65+
css += '.with-arrow:after';
66+
67+
if (hasBorder) css += ', .with-arrow:before {\n';
68+
else css += ' {\n';
69+
70+
css += '\t' + iPos +': 100%;\n';
71+
72+
if (pos === 'top' || pos === 'bottom') {
73+
css += '\tleft: 50%;\n';
74+
}
75+
else {
76+
css += '\ttop: 50%;\n';
77+
}
78+
79+
css += '\tborder: solid transparent;\n';
80+
css += '\tcontent: " ";\n';
81+
css += '\theight: 0;\n';
82+
css += '\twidth: 0;\n';
83+
css += '\tposition: absolute;\n';
84+
css += '\tpointer-events: none;\n';
85+
86+
if(hasBorder) css += '}\n';
87+
88+
return css;
89+
},
90+
91+
/**
92+
@method _arrowCSS
93+
@description generates arrow css
94+
@param {String} color the color of the arrow
95+
@param {Integer} size the size of the arrow
96+
@param {String} layer :after or :before (defaults to :after)
97+
@returns {String} css
98+
@protected
99+
**/
100+
_arrowCSS: function (color, size, layer) {
101+
var pos = this.get('position'),
102+
iPos = this.invertedPosition(),
103+
rgbColor = this.hexToRGB(color),
104+
borderSize = this.get('borderSize'),
105+
css = "";
106+
107+
layer = layer || 'after';
108+
109+
if(borderSize > 0) css += '.with-arrow:' + layer + ' {\n';
110+
111+
css += '\tborder-color: rgba(' + rgbColor.join(', ') + ', 0);\n';
112+
css += '\tborder-' + iPos + '-color: ' + color + ';\n';
113+
css += '\tborder-width: ' + size + 'px;\n';
114+
115+
if (pos === 'top' || pos === 'bottom') {
116+
css += '\tmargin-left: -' + size + 'px;\n';
117+
}
118+
else {
119+
css += '\tmargin-top: -' + size + 'px;\n';
120+
}
121+
122+
css += '}';
123+
124+
return css;
125+
},
126+
127+
/**
128+
@method _baseArrowCSS
129+
@description generates the base arrow
130+
@returns {String} css
131+
@protected
132+
**/
133+
_baseArrowCSS: function () {
134+
return this._arrowCSS(
135+
this.get('color'),
136+
this.get('size'),
137+
'after'
138+
);
139+
},
140+
141+
/**
142+
@method _arrowBorderCSS
143+
@description generates the border arrow
144+
@returns {String} css
145+
@protected
146+
**/
147+
_arrowBorderCSS: function () {
148+
var css = '',
149+
borderSize = this.get('borderSize');
150+
151+
if (borderSize > 0) {
152+
css = this._arrowCSS(
153+
this.get('borderColor'),
154+
this.get('size') + Math.round(borderSize * 1.41421356), // cos(PI/4) * 2
155+
'before'
156+
);
157+
}
158+
159+
return css;
160+
},
161+
162+
/**
163+
@method toCSS
164+
@description returns a CSS representation of the arrow
165+
@returns {String} css
166+
**/
167+
toCSS: function () {
168+
169+
var css = [
170+
this._baseCSS(),
171+
this._baseArrowCSS(),
172+
this._arrowBorderCSS()
173+
];
174+
175+
return css.join(css[2] ? '\n':'');
176+
},
177+
178+
/**
179+
@method _createAttrs
180+
@description creates attributes from the ATTR constant
181+
@protected
182+
**/
183+
_createAttrs: function () {
184+
var ATTRS = Arrow.ATTRS,
185+
attributes = {};
186+
187+
for (var attr in ATTRS) {
188+
if (ATTRS.hasOwnProperty(attr)) {
189+
attributes[attr] = ATTRS[attr];
190+
}
191+
};
192+
193+
this._attributes = attributes;
194+
},
195+
196+
/**
197+
@method getAttrs
198+
@description returns all the attributes
199+
@returns {Object} all the model attributes
200+
**/
201+
getAttrs: function () {
202+
return this._attributes;
203+
},
204+
205+
/**
206+
@method get
207+
@description returns the provided attribute
208+
@param {String} attr the attribute to return
209+
@returns {?} the attribute
210+
**/
211+
get: function (attr) {
212+
return this._attributes[attr];
213+
},
214+
215+
/**
216+
@method set
217+
@description updates the provided attribute
218+
@param {String} attr the attribute to update
219+
@param {?} val the value to update with
220+
**/
221+
set: function (attr, val) {
222+
if (!(attr in this._attributes)) return;
223+
224+
this._attributes[attr] = val;
225+
},
226+
227+
setAttrs: function (attrs) {
228+
for (var attr in attrs) {
229+
if (attrs.hasOwnProperty(attr)) {
230+
this.set(attr, attrs[attr]);
231+
}
232+
}
233+
}
234+
235+
};
236+
237+
Arrow.ATTRS = {
238+
position: 'top',
239+
size: 16,
240+
color: '#88b7d5',
241+
borderSize: 3,
242+
borderColor:'#c2e1f5'
243+
};
244+
245+
// TODO: refactor!!
246+
var arrowGenerator = function (config) {
247+
var arrow = new Arrow();
248+
arrow.setAttrs(config);
249+
return arrow.toCSS();
250+
};
251+
252+
module.exports = arrowGenerator;

app/components/arrow_box.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/** @jsx React.DOM */
2+
3+
var ArrowBox = React.createClass({
4+
render: function () {
5+
return (
6+
<div className='with-arrow'>
7+
Generate tooltips with a<br />
8+
CSS triangle in any direction.<br />
9+
Configure below
10+
</div>
11+
);
12+
}
13+
});
14+
15+
module.exports = ArrowBox;

app/components/config.js

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/** @jsx React.DOM */
2+
3+
var ConfigLabels = require('./config_labels'),
4+
ConfigForm = require('./config_form'),
5+
GeneratedCode = require('./generated_code'),
6+
arrowGenerator = require('../arrow_generator');
7+
8+
var Config = React.createClass({
9+
10+
/**
11+
@method getInitialState
12+
@return {Object}
13+
**/
14+
getInitialState: function () {
15+
return {
16+
generatedCode: arrowGenerator(this.props.config)
17+
};
18+
},
19+
20+
/**
21+
@method render
22+
@return {ReactComponent}
23+
**/
24+
render: function() {
25+
return (
26+
<div className='content'>
27+
<ConfigLabels />
28+
<ConfigForm onConfigChange={this.handleConfigChange} config={this.props.config}/>
29+
<GeneratedCode code={this.state.generatedCode}/>
30+
</div>
31+
);
32+
},
33+
34+
/**
35+
@method handleConfigChange
36+
@param {Object} config
37+
**/
38+
handleConfigChange: function (config) {
39+
this.setState({ generatedCode: arrowGenerator(config) });
40+
}
41+
});
42+
43+
module.exports = Config;

0 commit comments

Comments
 (0)