phrasing 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. data/.gitignore +2 -0
  2. data/Gemfile +10 -0
  3. data/Gemfile.lock +142 -0
  4. data/MIT-LICENSE +20 -0
  5. data/README.md +93 -0
  6. data/Rakefile +35 -0
  7. data/app/assets/fonts/icomoon.dev.svg +38 -0
  8. data/app/assets/fonts/icomoon.eot +0 -0
  9. data/app/assets/fonts/icomoon.svg +38 -0
  10. data/app/assets/fonts/icomoon.ttf +0 -0
  11. data/app/assets/fonts/icomoon.woff +0 -0
  12. data/app/assets/images/phrasing_information_icon.png +0 -0
  13. data/app/assets/javascripts/editor.js +318 -0
  14. data/app/assets/javascripts/head.js +423 -0
  15. data/app/assets/javascripts/phrasing.js.erb +148 -0
  16. data/app/assets/javascripts/spin.js +355 -0
  17. data/app/assets/stylesheets/phrasing.css.scss +240 -0
  18. data/app/assets/stylesheets/phrasing_edit_mode_bubble.css.scss +117 -0
  19. data/app/assets/stylesheets/phrasing_engine.css +470 -0
  20. data/app/assets/stylesheets/phrasing_fonts.css.scss +60 -0
  21. data/app/controllers/phrasing_phrases_controller.rb +126 -0
  22. data/app/helpers/inline_helper.rb +47 -0
  23. data/app/models/phrasing_phrase.rb +97 -0
  24. data/app/views/layouts/phrasing.html.haml +12 -0
  25. data/app/views/phrasing/_initializer.html.haml +25 -0
  26. data/app/views/phrasing/_menu.html.haml +8 -0
  27. data/app/views/phrasing/_messages.html.haml +4 -0
  28. data/app/views/phrasing/_production_warning.html.haml +4 -0
  29. data/app/views/phrasing_phrases/edit.html.haml +7 -0
  30. data/app/views/phrasing_phrases/help.html.haml +17 -0
  31. data/app/views/phrasing_phrases/import_export.html.haml +18 -0
  32. data/app/views/phrasing_phrases/index.html.haml +17 -0
  33. data/config/routes.rb +12 -0
  34. data/db/migrate/20120313191745_create_phrasing_phrases.rb +11 -0
  35. data/lib/phrasing.rb +72 -0
  36. data/lib/phrasing/ambiguous_phrases_error.rb +3 -0
  37. data/lib/phrasing/implementation.rb +19 -0
  38. data/lib/phrasing/phrasable_error_handler.rb +9 -0
  39. data/lib/phrasing/simple.rb +3 -0
  40. data/lib/phrasing/version.rb +3 -0
  41. data/lib/tasks/phrasing_tasks.rake +57 -0
  42. data/phrasing.gemspec +21 -0
  43. metadata +135 -0
@@ -0,0 +1,355 @@
1
+ //fgnass.github.com/spin.js#v1.3.2
2
+
3
+ /**
4
+ * Copyright (c) 2011-2013 Felix Gnass
5
+ * Licensed under the MIT license
6
+ */
7
+ (function(root, factory) {
8
+
9
+ /* CommonJS */
10
+ if (typeof exports == 'object') module.exports = factory()
11
+
12
+ /* AMD module */
13
+ else if (typeof define == 'function' && define.amd) define(factory)
14
+
15
+ /* Browser global */
16
+ else root.Spinner = factory()
17
+ }
18
+ (this, function() {
19
+ "use strict";
20
+
21
+ var prefixes = ['webkit', 'Moz', 'ms', 'O'] /* Vendor prefixes */
22
+ , animations = {} /* Animation rules keyed by their name */
23
+ , useCssAnimations /* Whether to use CSS animations or setTimeout */
24
+
25
+ /**
26
+ * Utility function to create elements. If no tag name is given,
27
+ * a DIV is created. Optionally properties can be passed.
28
+ */
29
+ function createEl(tag, prop) {
30
+ var el = document.createElement(tag || 'div')
31
+ , n
32
+
33
+ for(n in prop) el[n] = prop[n]
34
+ return el
35
+ }
36
+
37
+ /**
38
+ * Appends children and returns the parent.
39
+ */
40
+ function ins(parent /* child1, child2, ...*/) {
41
+ for (var i=1, n=arguments.length; i<n; i++)
42
+ parent.appendChild(arguments[i])
43
+
44
+ return parent
45
+ }
46
+
47
+ /**
48
+ * Insert a new stylesheet to hold the @keyframe or VML rules.
49
+ */
50
+ var sheet = (function() {
51
+ var el = createEl('style', {type : 'text/css'})
52
+ ins(document.getElementsByTagName('head')[0], el)
53
+ return el.sheet || el.styleSheet
54
+ }())
55
+
56
+ /**
57
+ * Creates an opacity keyframe animation rule and returns its name.
58
+ * Since most mobile Webkits have timing issues with animation-delay,
59
+ * we create separate rules for each line/segment.
60
+ */
61
+ function addAnimation(alpha, trail, i, lines) {
62
+ var name = ['opacity', trail, ~~(alpha*100), i, lines].join('-')
63
+ , start = 0.01 + i/lines * 100
64
+ , z = Math.max(1 - (1-alpha) / trail * (100-start), alpha)
65
+ , prefix = useCssAnimations.substring(0, useCssAnimations.indexOf('Animation')).toLowerCase()
66
+ , pre = prefix && '-' + prefix + '-' || ''
67
+
68
+ if (!animations[name]) {
69
+ sheet.insertRule(
70
+ '@' + pre + 'keyframes ' + name + '{' +
71
+ '0%{opacity:' + z + '}' +
72
+ start + '%{opacity:' + alpha + '}' +
73
+ (start+0.01) + '%{opacity:1}' +
74
+ (start+trail) % 100 + '%{opacity:' + alpha + '}' +
75
+ '100%{opacity:' + z + '}' +
76
+ '}', sheet.cssRules.length)
77
+
78
+ animations[name] = 1
79
+ }
80
+
81
+ return name
82
+ }
83
+
84
+ /**
85
+ * Tries various vendor prefixes and returns the first supported property.
86
+ */
87
+ function vendor(el, prop) {
88
+ var s = el.style
89
+ , pp
90
+ , i
91
+
92
+ prop = prop.charAt(0).toUpperCase() + prop.slice(1)
93
+ for(i=0; i<prefixes.length; i++) {
94
+ pp = prefixes[i]+prop
95
+ if(s[pp] !== undefined) return pp
96
+ }
97
+ if(s[prop] !== undefined) return prop
98
+ }
99
+
100
+ /**
101
+ * Sets multiple style properties at once.
102
+ */
103
+ function css(el, prop) {
104
+ for (var n in prop)
105
+ el.style[vendor(el, n)||n] = prop[n]
106
+
107
+ return el
108
+ }
109
+
110
+ /**
111
+ * Fills in default values.
112
+ */
113
+ function merge(obj) {
114
+ for (var i=1; i < arguments.length; i++) {
115
+ var def = arguments[i]
116
+ for (var n in def)
117
+ if (obj[n] === undefined) obj[n] = def[n]
118
+ }
119
+ return obj
120
+ }
121
+
122
+ /**
123
+ * Returns the absolute page-offset of the given element.
124
+ */
125
+ function pos(el) {
126
+ var o = { x:el.offsetLeft, y:el.offsetTop }
127
+ while((el = el.offsetParent))
128
+ o.x+=el.offsetLeft, o.y+=el.offsetTop
129
+
130
+ return o
131
+ }
132
+
133
+ /**
134
+ * Returns the line color from the given string or array.
135
+ */
136
+ function getColor(color, idx) {
137
+ return typeof color == 'string' ? color : color[idx % color.length]
138
+ }
139
+
140
+ // Built-in defaults
141
+
142
+ var defaults = {
143
+ lines: 12, // The number of lines to draw
144
+ length: 7, // The length of each line
145
+ width: 5, // The line thickness
146
+ radius: 10, // The radius of the inner circle
147
+ rotate: 0, // Rotation offset
148
+ corners: 1, // Roundness (0..1)
149
+ color: '#000', // #rgb or #rrggbb
150
+ direction: 1, // 1: clockwise, -1: counterclockwise
151
+ speed: 1, // Rounds per second
152
+ trail: 100, // Afterglow percentage
153
+ opacity: 1/4, // Opacity of the lines
154
+ fps: 20, // Frames per second when using setTimeout()
155
+ zIndex: 2e9, // Use a high z-index by default
156
+ className: 'spinner', // CSS class to assign to the element
157
+ top: 'auto', // center vertically
158
+ left: 'auto', // center horizontally
159
+ position: 'relative' // element position
160
+ }
161
+
162
+ /** The constructor */
163
+ function Spinner(o) {
164
+ if (typeof this == 'undefined') return new Spinner(o)
165
+ this.opts = merge(o || {}, Spinner.defaults, defaults)
166
+ }
167
+
168
+ // Global defaults that override the built-ins:
169
+ Spinner.defaults = {}
170
+
171
+ merge(Spinner.prototype, {
172
+
173
+ /**
174
+ * Adds the spinner to the given target element. If this instance is already
175
+ * spinning, it is automatically removed from its previous target b calling
176
+ * stop() internally.
177
+ */
178
+ spin: function(target) {
179
+ this.stop()
180
+
181
+ var self = this
182
+ , o = self.opts
183
+ , el = self.el = css(createEl(0, {className: o.className}), {position: o.position, width: 0, zIndex: o.zIndex})
184
+ , mid = o.radius+o.length+o.width
185
+ , ep // element position
186
+ , tp // target position
187
+
188
+ if (target) {
189
+ target.insertBefore(el, target.firstChild||null)
190
+ tp = pos(target)
191
+ ep = pos(el)
192
+ css(el, {
193
+ left: (o.left == 'auto' ? tp.x-ep.x + (target.offsetWidth >> 1) : parseInt(o.left, 10) + mid) + 'px',
194
+ top: (o.top == 'auto' ? tp.y-ep.y + (target.offsetHeight >> 1) : parseInt(o.top, 10) + mid) + 'px'
195
+ })
196
+ }
197
+
198
+ el.setAttribute('role', 'progressbar')
199
+ self.lines(el, self.opts)
200
+
201
+ if (!useCssAnimations) {
202
+ // No CSS animation support, use setTimeout() instead
203
+ var i = 0
204
+ , start = (o.lines - 1) * (1 - o.direction) / 2
205
+ , alpha
206
+ , fps = o.fps
207
+ , f = fps/o.speed
208
+ , ostep = (1-o.opacity) / (f*o.trail / 100)
209
+ , astep = f/o.lines
210
+
211
+ ;(function anim() {
212
+ i++;
213
+ for (var j = 0; j < o.lines; j++) {
214
+ alpha = Math.max(1 - (i + (o.lines - j) * astep) % f * ostep, o.opacity)
215
+
216
+ self.opacity(el, j * o.direction + start, alpha, o)
217
+ }
218
+ self.timeout = self.el && setTimeout(anim, ~~(1000/fps))
219
+ })()
220
+ }
221
+ return self
222
+ },
223
+
224
+ /**
225
+ * Stops and removes the Spinner.
226
+ */
227
+ stop: function() {
228
+ var el = this.el
229
+ if (el) {
230
+ clearTimeout(this.timeout)
231
+ if (el.parentNode) el.parentNode.removeChild(el)
232
+ this.el = undefined
233
+ }
234
+ return this
235
+ },
236
+
237
+ /**
238
+ * Internal method that draws the individual lines. Will be overwritten
239
+ * in VML fallback mode below.
240
+ */
241
+ lines: function(el, o) {
242
+ var i = 0
243
+ , start = (o.lines - 1) * (1 - o.direction) / 2
244
+ , seg
245
+
246
+ function fill(color, shadow) {
247
+ return css(createEl(), {
248
+ position: 'absolute',
249
+ width: (o.length+o.width) + 'px',
250
+ height: o.width + 'px',
251
+ background: color,
252
+ boxShadow: shadow,
253
+ transformOrigin: 'left',
254
+ transform: 'rotate(' + ~~(360/o.lines*i+o.rotate) + 'deg) translate(' + o.radius+'px' +',0)',
255
+ borderRadius: (o.corners * o.width>>1) + 'px'
256
+ })
257
+ }
258
+
259
+ for (; i < o.lines; i++) {
260
+ seg = css(createEl(), {
261
+ position: 'absolute',
262
+ top: 1+~(o.width/2) + 'px',
263
+ transform: o.hwaccel ? 'translate3d(0,0,0)' : '',
264
+ opacity: o.opacity,
265
+ animation: useCssAnimations && addAnimation(o.opacity, o.trail, start + i * o.direction, o.lines) + ' ' + 1/o.speed + 's linear infinite'
266
+ })
267
+
268
+ if (o.shadow) ins(seg, css(fill('#000', '0 0 4px ' + '#000'), {top: 2+'px'}))
269
+ ins(el, ins(seg, fill(getColor(o.color, i), '0 0 1px rgba(0,0,0,.1)')))
270
+ }
271
+ return el
272
+ },
273
+
274
+ /**
275
+ * Internal method that adjusts the opacity of a single line.
276
+ * Will be overwritten in VML fallback mode below.
277
+ */
278
+ opacity: function(el, i, val) {
279
+ if (i < el.childNodes.length) el.childNodes[i].style.opacity = val
280
+ }
281
+
282
+ })
283
+
284
+
285
+ function initVML() {
286
+
287
+ /* Utility function to create a VML tag */
288
+ function vml(tag, attr) {
289
+ return createEl('<' + tag + ' xmlns="urn:schemas-microsoft.com:vml" class="spin-vml">', attr)
290
+ }
291
+
292
+ // No CSS transforms but VML support, add a CSS rule for VML elements:
293
+ sheet.addRule('.spin-vml', 'behavior:url(#default#VML)')
294
+
295
+ Spinner.prototype.lines = function(el, o) {
296
+ var r = o.length+o.width
297
+ , s = 2*r
298
+
299
+ function grp() {
300
+ return css(
301
+ vml('group', {
302
+ coordsize: s + ' ' + s,
303
+ coordorigin: -r + ' ' + -r
304
+ }),
305
+ { width: s, height: s }
306
+ )
307
+ }
308
+
309
+ var margin = -(o.width+o.length)*2 + 'px'
310
+ , g = css(grp(), {position: 'absolute', top: margin, left: margin})
311
+ , i
312
+
313
+ function seg(i, dx, filter) {
314
+ ins(g,
315
+ ins(css(grp(), {rotation: 360 / o.lines * i + 'deg', left: ~~dx}),
316
+ ins(css(vml('roundrect', {arcsize: o.corners}), {
317
+ width: r,
318
+ height: o.width,
319
+ left: o.radius,
320
+ top: -o.width>>1,
321
+ filter: filter
322
+ }),
323
+ vml('fill', {color: getColor(o.color, i), opacity: o.opacity}),
324
+ vml('stroke', {opacity: 0}) // transparent stroke to fix color bleeding upon opacity change
325
+ )
326
+ )
327
+ )
328
+ }
329
+
330
+ if (o.shadow)
331
+ for (i = 1; i <= o.lines; i++)
332
+ seg(i, -2, 'progid:DXImageTransform.Microsoft.Blur(pixelradius=2,makeshadow=1,shadowopacity=.3)')
333
+
334
+ for (i = 1; i <= o.lines; i++) seg(i)
335
+ return ins(el, g)
336
+ }
337
+
338
+ Spinner.prototype.opacity = function(el, i, val, o) {
339
+ var c = el.firstChild
340
+ o = o.shadow && o.lines || 0
341
+ if (c && i+o < c.childNodes.length) {
342
+ c = c.childNodes[i+o]; c = c && c.firstChild; c = c && c.firstChild
343
+ if (c) c.opacity = val
344
+ }
345
+ }
346
+ }
347
+
348
+ var probe = css(createEl('group'), {behavior: 'url(#default#VML)'})
349
+
350
+ if (!vendor(probe, 'transform') && probe.adj) initVML()
351
+ else useCssAnimations = vendor(probe, 'animation')
352
+
353
+ return Spinner
354
+
355
+ }));
@@ -0,0 +1,240 @@
1
+ //= require phrasing_fonts
2
+ //= require phrasing_edit_mode_bubble
3
+ /*********************************************
4
+ * BASE STYLES
5
+ *********************************************/
6
+
7
+ /*html {
8
+ overflow: hidden;
9
+ }*/
10
+
11
+ .phrasable_on{
12
+ border-bottom: 1px dashed black;
13
+
14
+ &:focus{
15
+ outline: none;
16
+ }
17
+
18
+ &:hover{
19
+ background-color: #fffadc;
20
+ cursor: pointer;
21
+ }
22
+
23
+ &.inverse{
24
+ border-bottom: 1px dashed white;
25
+
26
+ &:hover{
27
+ background-color: #333333;
28
+ }
29
+ }
30
+
31
+ }
32
+
33
+ /*blockquote {
34
+ border-left: 4px solid deepskyblue;
35
+ margin-left: -19px;
36
+ padding-left: 15px;
37
+ margin-right: 0px;
38
+ }*/
39
+
40
+ span.no-overflow {
41
+ overflow: hidden;
42
+ display: block;
43
+ height: 100%;
44
+ width: 100%;
45
+ }
46
+
47
+ /* Used by the ui bubble to stop wrapping */
48
+ .lengthen {
49
+ display: block;
50
+ width: 300px;
51
+ height: 100%;
52
+ }
53
+
54
+ .useicons {
55
+ -webkit-font-smoothing: antialiased;
56
+ font-size: 20px !important;
57
+ font-family: 'icomoon' !important;
58
+ }
59
+
60
+ /*.ui {
61
+ position: fixed;
62
+ padding: 20px;
63
+ width: 65px;
64
+ bottom: 0px;
65
+ left: 0px;
66
+ top: 0px;
67
+ }
68
+
69
+ .ui:hover button {
70
+ opacity: 0.4;
71
+ }
72
+
73
+ .ui button:hover {
74
+ opacity: 1;
75
+ }*/
76
+
77
+ .text-options button {
78
+
79
+ -webkit-transition: opacity 400ms;
80
+ -moz-transition: opacity 400ms;
81
+ -ms-transition: opacity 400ms;
82
+ -o-transition: opacity 400ms;
83
+ transition: opacity 400ms;
84
+
85
+ font-family: inherit;
86
+ background: none;
87
+ cursor: pointer;
88
+ font-size: 25px;
89
+ color: inherit;
90
+ opacity: 0.1;
91
+ padding: 0px;
92
+ height: 32px;
93
+ width: 25px;
94
+ border: 0px;
95
+ }
96
+
97
+ /*.quote {
98
+ line-height: 60px !important;
99
+ font-size: 49px !important;
100
+ }*/
101
+
102
+ /*********************************************
103
+ * UI BUBBLE
104
+ *********************************************/
105
+
106
+ .text-options {
107
+
108
+ -webkit-transition: opacity 250ms, margin 250ms;
109
+ -moz-transition: opacity 250ms, margin 250ms;
110
+ -ms-transition: opacity 250ms, margin 250ms;
111
+ -o-transition: opacity 250ms, margin 250ms;
112
+ transition: opacity 250ms, margin 250ms;
113
+
114
+ position: absolute;
115
+ left: -999px;
116
+ top: -999px;
117
+ color: #fff;
118
+ height: 0px;
119
+ width: 0px;
120
+ z-index: 5;
121
+ margin-top: 5px;
122
+ opacity: 0;
123
+
124
+ &.fade {
125
+ opacity: 0;
126
+ margin-top: -5px;
127
+ }
128
+
129
+ &.active {
130
+ opacity: 1;
131
+ margin-top: 0px;
132
+ }
133
+ }
134
+
135
+
136
+ .text-options .options {
137
+ background-color: rgba(0,0,0,0.9);
138
+ position: absolute;
139
+ border-radius: 5px;
140
+ margin-left: -48px;
141
+ margin-top: -46px;
142
+ z-index: 1000;
143
+ padding: 5px 4px 5px 5px;
144
+ width: 96px;
145
+ height: 40px;
146
+
147
+ -moz-box-sizing: border-box;
148
+ box-sizing: border-box;
149
+
150
+ -webkit-transition: all 300ms ease-in-out;
151
+ -moz-transition: all 300ms ease-in-out;
152
+ -ms-transition: all 300ms ease-in-out;
153
+ -o-transition: all 300ms ease-in-out;
154
+ transition: all 300ms ease-in-out;
155
+
156
+
157
+ &.url-mode {
158
+ width: 275px;
159
+ margin-left: -137px;
160
+
161
+ .bold, .options.url-mode .italic, .options.url-mode .quote {
162
+ width: 0px;
163
+ overflow: hidden;
164
+ margin-right: 0px;
165
+ opacity: 0;
166
+ }
167
+
168
+ input{
169
+ border-left: 2px solid transparent;
170
+ padding-right: 5px;
171
+ padding-left: 5px;
172
+ width: 236px;
173
+ }
174
+ }
175
+
176
+ .italic {
177
+ font-style: italic;
178
+ }
179
+
180
+ button {
181
+ -webkit-transition: all 250ms ease-in-out;
182
+ -moz-transition: all 250ms ease-in-out;
183
+ -ms-transition: all 250ms ease-in-out;
184
+ -o-transition: all 250ms ease-in-out;
185
+ transition: all 250ms ease-in-out;
186
+
187
+ float: left;
188
+ width: 28px;
189
+ opacity: 0.7;
190
+ height: 30px;
191
+ border-radius: 3px;
192
+ margin-right: 1px;
193
+ font-family: 'Lora', serif;
194
+
195
+ &.active {
196
+ background-color: rgba(255,255,255,0.4);
197
+ opacity: 1;
198
+ }
199
+
200
+ &:hover {
201
+ opacity: 0.95;
202
+ }
203
+ }
204
+
205
+ input {
206
+ -webkit-transition: all 300ms ease-in-out;
207
+ -moz-transition: all 300ms ease-in-out;
208
+ -ms-transition: all 300ms ease-in-out;
209
+ -o-transition: all 300ms ease-in-out;
210
+ transition: all 300ms ease-in-out;
211
+
212
+ border-radius: 3px;
213
+ overflow: hidden;
214
+ outline: 0px;
215
+ height: 30px;
216
+ padding: 0px;
217
+ margin: 0px;
218
+ border: 0px;
219
+ float: left;
220
+ width: 0px;
221
+ }
222
+
223
+ &:before {
224
+ content: "";
225
+ border-top: 5px solid rgba(0,0,0,0.9);
226
+ border-bottom: 5px solid transparent;
227
+ border-right: 5px solid transparent;
228
+ border-left: 5px solid transparent;
229
+ position: absolute;
230
+ margin-left: -5px;
231
+ bottom: -15px;
232
+ height: 5px;
233
+ width: 0px;
234
+ left: 50%;
235
+ }
236
+ }
237
+
238
+ .url {
239
+ -webkit-font-smoothing: antialiased;
240
+ }