mercury-rails 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (153) hide show
  1. data/LICENSE +20 -0
  2. data/README.rdoc +152 -0
  3. data/VERSION +1 -0
  4. data/app/assets/images/mercury/button.png +0 -0
  5. data/app/assets/images/mercury/clippy.png +0 -0
  6. data/app/assets/images/mercury/default-snippet.png +0 -0
  7. data/app/assets/images/mercury/loading-dark.gif +0 -0
  8. data/app/assets/images/mercury/loading-light.gif +0 -0
  9. data/app/assets/images/mercury/search-icon.png +0 -0
  10. data/app/assets/images/mercury/toolbar/editable/buttons.png +0 -0
  11. data/app/assets/images/mercury/toolbar/markupable/buttons.png +0 -0
  12. data/app/assets/images/mercury/toolbar/primary/_expander.png +0 -0
  13. data/app/assets/images/mercury/toolbar/primary/_pressed.png +0 -0
  14. data/app/assets/images/mercury/toolbar/primary/historypanel.png +0 -0
  15. data/app/assets/images/mercury/toolbar/primary/insertcharacter.png +0 -0
  16. data/app/assets/images/mercury/toolbar/primary/insertlink.png +0 -0
  17. data/app/assets/images/mercury/toolbar/primary/insertmedia.png +0 -0
  18. data/app/assets/images/mercury/toolbar/primary/inserttable.png +0 -0
  19. data/app/assets/images/mercury/toolbar/primary/inspectorpanel.png +0 -0
  20. data/app/assets/images/mercury/toolbar/primary/notespanel.png +0 -0
  21. data/app/assets/images/mercury/toolbar/primary/objectspanel.png +0 -0
  22. data/app/assets/images/mercury/toolbar/primary/preview.png +0 -0
  23. data/app/assets/images/mercury/toolbar/primary/redo.png +0 -0
  24. data/app/assets/images/mercury/toolbar/primary/save.png +0 -0
  25. data/app/assets/images/mercury/toolbar/primary/todospanel.png +0 -0
  26. data/app/assets/images/mercury/toolbar/primary/undo.png +0 -0
  27. data/app/assets/images/mercury/toolbar/snippetable/buttons.png +0 -0
  28. data/app/assets/javascripts/mercury.js +30 -0
  29. data/app/assets/javascripts/mercury/dialog.js.coffee +75 -0
  30. data/app/assets/javascripts/mercury/dialogs/backcolor.js.coffee +6 -0
  31. data/app/assets/javascripts/mercury/dialogs/forecolor.js.coffee +6 -0
  32. data/app/assets/javascripts/mercury/dialogs/formatblock.js.coffee +4 -0
  33. data/app/assets/javascripts/mercury/dialogs/objectspanel.js.coffee +10 -0
  34. data/app/assets/javascripts/mercury/dialogs/style.js.coffee +4 -0
  35. data/app/assets/javascripts/mercury/history_buffer.js.coffee +30 -0
  36. data/app/assets/javascripts/mercury/mercury.js.coffee +293 -0
  37. data/app/assets/javascripts/mercury/modal.js.coffee +177 -0
  38. data/app/assets/javascripts/mercury/modals/htmleditor.js.coffee +10 -0
  39. data/app/assets/javascripts/mercury/modals/insertcharacter.js.coffee +4 -0
  40. data/app/assets/javascripts/mercury/modals/insertlink.js.coffee +92 -0
  41. data/app/assets/javascripts/mercury/modals/insertmedia.js.coffee +72 -0
  42. data/app/assets/javascripts/mercury/modals/insertsnippet.js.coffee +11 -0
  43. data/app/assets/javascripts/mercury/modals/inserttable.js.coffee +56 -0
  44. data/app/assets/javascripts/mercury/native_extensions.js.coffee +47 -0
  45. data/app/assets/javascripts/mercury/page_editor.js.coffee +139 -0
  46. data/app/assets/javascripts/mercury/palette.js.coffee +29 -0
  47. data/app/assets/javascripts/mercury/panel.js.coffee +97 -0
  48. data/app/assets/javascripts/mercury/region.js.coffee +103 -0
  49. data/app/assets/javascripts/mercury/regions/editable.js.coffee +546 -0
  50. data/app/assets/javascripts/mercury/regions/markupable.js.coffee +380 -0
  51. data/app/assets/javascripts/mercury/regions/snippetable.js.coffee +127 -0
  52. data/app/assets/javascripts/mercury/select.js.coffee +40 -0
  53. data/app/assets/javascripts/mercury/snippet.js.coffee +92 -0
  54. data/app/assets/javascripts/mercury/snippet_toolbar.js.coffee +69 -0
  55. data/app/assets/javascripts/mercury/statusbar.js.coffee +25 -0
  56. data/app/assets/javascripts/mercury/table_editor.js.coffee +266 -0
  57. data/app/assets/javascripts/mercury/toolbar.button.js.coffee +152 -0
  58. data/app/assets/javascripts/mercury/toolbar.button_group.js.coffee +42 -0
  59. data/app/assets/javascripts/mercury/toolbar.expander.js.coffee +56 -0
  60. data/app/assets/javascripts/mercury/toolbar.js.coffee +72 -0
  61. data/app/assets/javascripts/mercury/tooltip.js.coffee +67 -0
  62. data/app/assets/javascripts/mercury/uploader.js.coffee +213 -0
  63. data/app/assets/javascripts/mercury/websocket.js.coffee +34 -0
  64. data/app/assets/stylesheets/mercury.css +31 -0
  65. data/app/assets/stylesheets/mercury/dialog.scss +178 -0
  66. data/app/assets/stylesheets/mercury/mercury.scss +119 -0
  67. data/app/assets/stylesheets/mercury/modal.scss +192 -0
  68. data/app/assets/stylesheets/mercury/statusbar.scss +23 -0
  69. data/app/assets/stylesheets/mercury/toolbar.scss +417 -0
  70. data/app/assets/stylesheets/mercury/tooltip.scss +26 -0
  71. data/app/assets/stylesheets/mercury/uploader.scss +109 -0
  72. data/app/controllers/images_controller.rb +19 -0
  73. data/app/controllers/mercury_controller.rb +20 -0
  74. data/app/models/image.rb +14 -0
  75. data/app/views/layouts/mercury.html.haml +12 -0
  76. data/app/views/mercury/modals/character.html.haml +252 -0
  77. data/app/views/mercury/modals/htmleditor.html.haml +8 -0
  78. data/app/views/mercury/modals/link.html.haml +31 -0
  79. data/app/views/mercury/modals/media.html.haml +33 -0
  80. data/app/views/mercury/modals/sanitizer.html.haml +4 -0
  81. data/app/views/mercury/modals/table.html.haml +49 -0
  82. data/app/views/mercury/palettes/backcolor.html.haml +79 -0
  83. data/app/views/mercury/palettes/forecolor.html.haml +79 -0
  84. data/app/views/mercury/panels/history.html.haml +0 -0
  85. data/app/views/mercury/panels/notes.html.haml +0 -0
  86. data/app/views/mercury/panels/snippets.html.haml +10 -0
  87. data/app/views/mercury/selects/formatblock.html.haml +10 -0
  88. data/app/views/mercury/selects/style.html.haml +4 -0
  89. data/app/views/mercury/snippets/example.html.haml +2 -0
  90. data/app/views/mercury/snippets/example_options.html.haml +16 -0
  91. data/config/engine.rb +6 -0
  92. data/config/routes.rb +15 -0
  93. data/db/migrate/20110526035601_create_images.rb +11 -0
  94. data/features/editing/basic.feature +11 -0
  95. data/features/step_definitions/debug_steps.rb +14 -0
  96. data/features/step_definitions/web_steps.rb +211 -0
  97. data/features/support/env.rb +46 -0
  98. data/features/support/paths.rb +35 -0
  99. data/features/support/selectors.rb +42 -0
  100. data/lib/mercury-rails.rb +4 -0
  101. data/log/.gitkeep +0 -0
  102. data/mercury-rails.gemspec +230 -0
  103. data/spec/javascripts/mercury/dialog_spec.js.coffee +258 -0
  104. data/spec/javascripts/mercury/history_buffer_spec.js.coffee +79 -0
  105. data/spec/javascripts/mercury/mercury_spec.js.coffee +52 -0
  106. data/spec/javascripts/mercury/native_extensions_spec.js.coffee +66 -0
  107. data/spec/javascripts/mercury/page_editor_spec.js.coffee +435 -0
  108. data/spec/javascripts/mercury/palette_spec.js.coffee +51 -0
  109. data/spec/javascripts/mercury/panel_spec.js.coffee +147 -0
  110. data/spec/javascripts/mercury/region_spec.js.coffee +261 -0
  111. data/spec/javascripts/mercury/regions/_editable_.js.coffee +0 -0
  112. data/spec/javascripts/mercury/regions/_markupable_.js.coffee +0 -0
  113. data/spec/javascripts/mercury/regions/snippetable_spec.js.coffee +368 -0
  114. data/spec/javascripts/mercury/select_spec.js.coffee +51 -0
  115. data/spec/javascripts/mercury/snippet_spec.js.coffee +246 -0
  116. data/spec/javascripts/mercury/snippet_toolbar_spec.js.coffee +186 -0
  117. data/spec/javascripts/mercury/statusbar_spec.js.coffee +78 -0
  118. data/spec/javascripts/mercury/table_editor_spec.js.coffee +192 -0
  119. data/spec/javascripts/mercury/toolbar.button_group_spec.js.coffee +92 -0
  120. data/spec/javascripts/mercury/toolbar.button_spec.js.coffee +341 -0
  121. data/spec/javascripts/mercury/toolbar.expander_spec.js.coffee +120 -0
  122. data/spec/javascripts/mercury/toolbar_spec.js.coffee +152 -0
  123. data/spec/javascripts/mercury/tooltip_spec.js.coffee +188 -0
  124. data/spec/javascripts/mercury/uploader_spec.js.coffee +512 -0
  125. data/spec/javascripts/responses/blank.html +1 -0
  126. data/spec/javascripts/spec_helper.js +513 -0
  127. data/spec/javascripts/templates/mercury/dialog.html +2 -0
  128. data/spec/javascripts/templates/mercury/page_editor.html +24 -0
  129. data/spec/javascripts/templates/mercury/palette.html +16 -0
  130. data/spec/javascripts/templates/mercury/panel.html +16 -0
  131. data/spec/javascripts/templates/mercury/region.html +2 -0
  132. data/spec/javascripts/templates/mercury/regions/snippetable.html +4 -0
  133. data/spec/javascripts/templates/mercury/select.html +16 -0
  134. data/spec/javascripts/templates/mercury/snippet.html +1 -0
  135. data/spec/javascripts/templates/mercury/snippet_toolbar.html +16 -0
  136. data/spec/javascripts/templates/mercury/statusbar.html +7 -0
  137. data/spec/javascripts/templates/mercury/table_editor.html +65 -0
  138. data/spec/javascripts/templates/mercury/toolbar.button.html +64 -0
  139. data/spec/javascripts/templates/mercury/toolbar.button_group.html +9 -0
  140. data/spec/javascripts/templates/mercury/toolbar.expander.html +18 -0
  141. data/spec/javascripts/templates/mercury/toolbar.html +10 -0
  142. data/spec/javascripts/templates/mercury/tooltip.html +12 -0
  143. data/spec/javascripts/templates/mercury/uploader.html +11 -0
  144. data/vendor/assets/javascripts/jquery-1.6.js +8865 -0
  145. data/vendor/assets/javascripts/jquery-ui-1.8.13.custom.min.js +249 -0
  146. data/vendor/assets/javascripts/jquery-ui-1.8.13.sortable.custom.js +1078 -0
  147. data/vendor/assets/javascripts/jquery.easing.js +173 -0
  148. data/vendor/assets/javascripts/jquery.json2.js +178 -0
  149. data/vendor/assets/javascripts/jquery.serialize_object.js +16 -0
  150. data/vendor/assets/javascripts/jquery.ujs.js +289 -0
  151. data/vendor/assets/javascripts/liquidmetal.js +88 -0
  152. data/vendor/assets/javascripts/showdown.js +1362 -0
  153. metadata +364 -0
@@ -0,0 +1,92 @@
1
+ require '/assets/mercury/mercury.js'
2
+
3
+ describe "Mercury.Toolbar.ButtonGroup", ->
4
+
5
+ template 'mercury/toolbar.button_group.html'
6
+
7
+ beforeEach ->
8
+ Mercury.Toolbar.ButtonGroup.contexts.foo = -> false
9
+ @region = {
10
+ element: $('<div class="mercury-region">')
11
+ currentElement: -> $('<div>')
12
+ }
13
+
14
+ afterEach ->
15
+ @buttonGroup = null
16
+ delete(@buttonGroup)
17
+ $(document).unbind('mercury:region:update')
18
+
19
+ describe "constructor", ->
20
+
21
+ beforeEach ->
22
+ @buildSpy = spyOn(Mercury.Toolbar.ButtonGroup.prototype, 'build').andCallThrough()
23
+ @bindEventsSpy = spyOn(Mercury.Toolbar.ButtonGroup.prototype, 'bindEvents').andCallThrough()
24
+ @buttonGroup = new Mercury.Toolbar.ButtonGroup('foo', {_context: true})
25
+
26
+ it "returns an element", ->
27
+ html = $('<div>').html(@buttonGroup).html()
28
+ expect(html).toEqual('<div class="mercury-button-group mercury-foo-group disabled"></div>')
29
+
30
+ it "calls build", ->
31
+ expect(@buildSpy.callCount).toEqual(1)
32
+
33
+ it "calls bindEvents", ->
34
+ expect(@bindEventsSpy.callCount).toEqual(1)
35
+
36
+
37
+ describe "observed events", ->
38
+
39
+ describe "custom event: region:update", ->
40
+
41
+ it "sets disabled/enabled state based on it's context", ->
42
+ @buttonGroup = new Mercury.Toolbar.ButtonGroup('foo', {_context: true})
43
+ contextSpy = spyOn(Mercury.Toolbar.ButtonGroup.contexts, 'foo').andCallFake(-> true)
44
+
45
+ expect(@buttonGroup.hasClass('disabled')).toEqual(true)
46
+
47
+ Mercury.trigger('region:update', {region: @region})
48
+ expect(contextSpy.callCount).toEqual(1)
49
+ expect(@buttonGroup.hasClass('disabled')).toEqual(false)
50
+
51
+ describe "custom event: region:focused", ->
52
+
53
+ beforeEach ->
54
+ @region = {
55
+ type: 'editable'
56
+ element: $('<div class="mercury-region">')
57
+ }
58
+
59
+ it "disables if the region type isn't supported", ->
60
+ @buttonGroup = new Mercury.Toolbar.ButtonGroup('foo', {_regions: ['foo']})
61
+ @buttonGroup.removeClass('disabled')
62
+ Mercury.trigger('region:focused', {region: @region})
63
+ expect(@buttonGroup.hasClass('disabled')).toEqual(true)
64
+
65
+ it "enables if the region type is supported", ->
66
+ @buttonGroup = new Mercury.Toolbar.ButtonGroup('foo', {_regions: ['editable']})
67
+ @buttonGroup.addClass('disabled')
68
+ Mercury.trigger('region:focused', {region: @region})
69
+ expect(@buttonGroup.hasClass('disabled')).toEqual(false)
70
+
71
+ describe "custom event: region:blurred", ->
72
+
73
+ it "disables if it's a button group for specific region types", ->
74
+ @buttonGroup = new Mercury.Toolbar.ButtonGroup('foo', {_regions: ['editable']})
75
+ @buttonGroup.removeClass('disabled')
76
+ Mercury.trigger('region:blurred', {region: @region})
77
+
78
+
79
+
80
+ describe "Mercury.Toolbar.ButtonGroup.contexts", ->
81
+
82
+ template 'mercury/toolbar.button_group.html'
83
+
84
+ beforeEach ->
85
+ @contexts = Mercury.Toolbar.ButtonGroup.contexts
86
+ @region = $('#context_container')
87
+
88
+ describe "table", ->
89
+
90
+ it "looks up for a table tag", ->
91
+ expect(@contexts.table($('#context_td'), @region)).toEqual(true)
92
+ expect(@contexts.table($('#context_em'), @region)).toEqual(false)
@@ -0,0 +1,341 @@
1
+ require '/assets/mercury/mercury.js'
2
+
3
+ describe "Mercury.Toolbar.Button", ->
4
+
5
+ template 'mercury/toolbar.button.html'
6
+
7
+ beforeEach ->
8
+ Mercury.displayRect = {0, 0, 500, 200}
9
+ Mercury.Toolbar.Button.contexts.foo = -> true
10
+ @region = {
11
+ type: 'editable'
12
+ element: $('<div class="mercury-region">')
13
+ currentElement: -> $('<div>')
14
+ }
15
+
16
+ afterEach ->
17
+ @button = null
18
+ delete(@button)
19
+ $(document).unbind('mercury:region:update')
20
+ $(document).unbind('mercury:button')
21
+
22
+ describe "constructor", ->
23
+
24
+ it "expects name and title values", ->
25
+ @button = new Mercury.Toolbar.Button('foo', 'title')
26
+ html = $('<div>').html(@button).html()
27
+ expect(html).toContain('title="title"')
28
+ expect(html).toContain('class="mercury-button mercury-foo-button"')
29
+ expect(html).toContain('<em>title</em>')
30
+
31
+ it "accepts summary, types and options", ->
32
+ @button = new Mercury.Toolbar.Button('foo', 'title', 'summary', {palette: '/nothing'}, {appendDialogsTo: $('#test')})
33
+ html = $('<div>').html(@button).html()
34
+ expect(html).toContain('title="summary"')
35
+ expect(html).toContain('class="mercury-button mercury-foo-button mercury-button-palette"')
36
+ expect(html).toContain('<em>title</em>')
37
+
38
+ it "calls build", ->
39
+ spy = spyOn(Mercury.Toolbar.Button.prototype, 'build').andCallFake(=>)
40
+ spyOn(Mercury.Toolbar.Button.prototype, 'bindEvents').andCallFake(=>)
41
+ @button = new Mercury.Toolbar.Button('foo', 'title')
42
+ expect(spy.callCount).toEqual(1)
43
+
44
+ it "calls bindEvents", ->
45
+ spyOn(Mercury.Toolbar.Button.prototype, 'build').andCallFake(=>)
46
+ spy = spyOn(Mercury.Toolbar.Button.prototype, 'bindEvents').andCallFake(=>)
47
+ @button = new Mercury.Toolbar.Button('foo', 'title')
48
+ expect(spy.callCount).toEqual(1)
49
+
50
+
51
+ describe "#build for various button types", ->
52
+
53
+ it "attaches an element meant for the expander in button data", ->
54
+ @button = new Mercury.Toolbar.Button('foo', 'title')
55
+ expect(@button.data('expander')).toEqual('<div class="mercury-expander-button" data-button="foo"><em></em><span>title</span></div>')
56
+
57
+ it "builds toggle buttons, that when clicked toggle their state", ->
58
+ @button = new Mercury.Toolbar.Button('foo', 'title', 'summary', {toggle: true})
59
+
60
+ jasmine.simulate.click(@button.get(0))
61
+ expect(@button.hasClass('pressed')).toEqual(true)
62
+
63
+ jasmine.simulate.click(@button.get(0))
64
+ expect(@button.hasClass('pressed')).toEqual(false)
65
+
66
+ it "builds mode buttons, that when clicked fire a mode event", ->
67
+ @button = new Mercury.Toolbar.Button('foo', 'title', 'summary', {mode: true})
68
+ spy = spyOn(Mercury, 'trigger').andCallFake(=>)
69
+
70
+ jasmine.simulate.click(@button.get(0))
71
+ expect(spy.callCount).toEqual(2)
72
+ expect(spy.argsForCall[0]).toEqual(['mode', {mode: 'foo'}])
73
+
74
+ it "builds buttons that understand context", ->
75
+ @button = new Mercury.Toolbar.Button('foo', 'title', 'summary', {context: true})
76
+
77
+ expect(@button.hasClass('active')).toEqual(false)
78
+ Mercury.trigger('region:update', {region: @region})
79
+ expect(@button.hasClass('active')).toEqual(true)
80
+
81
+ it "builds panel buttons (and assigns toggle)", ->
82
+ @button = new Mercury.Toolbar.Button('foo', 'title', 'summary', {panel: '/evergreen/responses/blank.html'}, {appendDialogsTo: $('#test')})
83
+ expect($('#test .mercury-panel').length).toEqual(1)
84
+
85
+ jasmine.simulate.click(@button.get(0))
86
+ expect(@button.hasClass('pressed')).toEqual(true)
87
+
88
+ jasmine.simulate.click(@button.get(0))
89
+ expect(@button.hasClass('pressed')).toEqual(false)
90
+
91
+ it "builds palette buttons", ->
92
+ @button = new Mercury.Toolbar.Button('foo', 'title', 'summary', {palette: '/evergreen/responses/blank.html'}, {appendDialogsTo: $('#test')})
93
+ expect($('#test .mercury-palette').length).toEqual(1)
94
+
95
+ it "builds select buttons", ->
96
+ @button = new Mercury.Toolbar.Button('foo', 'title', 'summary', {select: '/evergreen/responses/blank.html'}, {appendDialogsTo: $('#test')})
97
+ expect($('#test .mercury-select').length).toEqual(1)
98
+
99
+ it "builds modal buttons", ->
100
+ @button = new Mercury.Toolbar.Button('foo', 'title', 'summary', {modal: '/evergreen/responses/blank.html'}, {appendDialogsTo: $('#test')})
101
+ # nothing unique about this in building -- the modal is built/fired on click
102
+
103
+ it "throws an error when an unknown type is encountered", ->
104
+ expect(=>
105
+ @button = new Mercury.Toolbar.Button('foo', 'title', 'summary', {foo: '/evergreen/responses/blank.html'})
106
+ ).toThrow('Unknown button type foo used for the foo button.')
107
+
108
+
109
+ describe "observed events", ->
110
+
111
+ describe "custom event: button", ->
112
+
113
+ it "calls click on the button itself", ->
114
+ @button = new Mercury.Toolbar.Button('foo', 'title', 'summary', {context: true})
115
+ spy = spyOn(@button, 'click').andCallFake(=>)
116
+
117
+ Mercury.trigger('button', {action: 'foo'})
118
+ expect(spy.callCount).toEqual(1)
119
+
120
+ describe "custom event: region:update", ->
121
+
122
+ it "calls contexts if one is available and set", ->
123
+ contextSpy = spyOn(Mercury.Toolbar.Button.contexts, 'foo').andCallFake(-> true)
124
+ @button = new Mercury.Toolbar.Button('foo', 'title', 'summary', {context: true})
125
+
126
+ expect(@button.hasClass('active')).toEqual(false)
127
+
128
+ Mercury.trigger('region:update', {region: @region})
129
+ expect(contextSpy.callCount).toEqual(1)
130
+ expect(@button.hasClass('active')).toEqual(true)
131
+
132
+ describe "custom event: region:focused", ->
133
+
134
+ it "disables if the region type isn't supported", ->
135
+ @button = new Mercury.Toolbar.Button('foo', 'title', 'summary', {context: true, regions: ['foo']})
136
+ @button.removeClass('disabled')
137
+ Mercury.trigger('region:focused', {region: @region})
138
+ expect(@button.hasClass('disabled')).toEqual(true)
139
+
140
+ it "enables if the region type is supported", ->
141
+ @button = new Mercury.Toolbar.Button('foo', 'title', 'summary', {context: true, regions: ['editable']})
142
+ @button.addClass('disabled')
143
+ Mercury.trigger('region:focused', {region: @region})
144
+ expect(@button.hasClass('disabled')).toEqual(false)
145
+
146
+ describe "custom event: region:blurred", ->
147
+
148
+ it "disables if it's a button for specific region types", ->
149
+ @button = new Mercury.Toolbar.Button('foo', 'title', 'summary', {context: true, regions: ['editable']})
150
+ @button.addClass('disabled')
151
+ Mercury.trigger('region:blurred', {region: @region})
152
+ expect(@button.hasClass('disabled')).toEqual(true)
153
+
154
+ describe "mousedown", ->
155
+
156
+ it "sets the active state", ->
157
+ @button = new Mercury.Toolbar.Button('foo', 'title')
158
+
159
+ expect(@button.hasClass('active')).toEqual(false)
160
+ jasmine.simulate.mousedown(@button.get(0))
161
+ expect(@button.hasClass('active')).toEqual(true)
162
+
163
+ describe "mouseup", ->
164
+
165
+ it "removes the active state", ->
166
+ @button = new Mercury.Toolbar.Button('foo', 'title')
167
+ @button.addClass('active')
168
+
169
+ jasmine.simulate.mouseup(@button.get(0))
170
+ expect(@button.hasClass('active')).toEqual(false)
171
+
172
+ describe "click for various button types", ->
173
+
174
+ it "does nothing if the button is disabled", ->
175
+ spy = spyOn(Mercury.Toolbar.Button.prototype, 'togglePressed').andCallThrough()
176
+ @button = new Mercury.Toolbar.Button('foo', 'title', 'summary', {toggle: true})
177
+
178
+ jasmine.simulate.click(@button.get(0))
179
+ expect(spy.callCount).toEqual(1)
180
+
181
+ @button.addClass('disabled')
182
+ jasmine.simulate.click(@button.get(0))
183
+ expect(spy.callCount).toEqual(1)
184
+
185
+ it "triggers an action event", ->
186
+ @button = new Mercury.Toolbar.Button('foo', 'title', 'summary')
187
+ spy = spyOn(Mercury, 'trigger').andCallFake(=>)
188
+
189
+ jasmine.simulate.click(@button.get(0))
190
+ expect(spy.argsForCall[0]).toEqual(['action', {action: 'foo'}])
191
+
192
+ it "triggers a focus:frame event", ->
193
+ spy = spyOn(Mercury, 'trigger').andCallFake(=>)
194
+ @button = new Mercury.Toolbar.Button('foo', 'title', 'summary')
195
+
196
+ jasmine.simulate.click(@button.get(0))
197
+ expect(spy.argsForCall[1]).toEqual(['focus:frame'])
198
+
199
+ it "toggles toggle button pressed state", ->
200
+ @button = new Mercury.Toolbar.Button('foo', 'title', 'summary', {toggle: true})
201
+
202
+ jasmine.simulate.click(@button.get(0))
203
+ expect(@button.hasClass('pressed')).toEqual(true)
204
+
205
+ jasmine.simulate.click(@button.get(0))
206
+ expect(@button.hasClass('pressed')).toEqual(false)
207
+
208
+ it "triggers a mode event", ->
209
+ spy = spyOn(Mercury, 'trigger').andCallFake(=>)
210
+ @button = new Mercury.Toolbar.Button('foo', 'title', 'summary', {mode: true})
211
+
212
+ jasmine.simulate.click(@button.get(0))
213
+ expect(spy.argsForCall[0]).toEqual(['mode', {mode: 'foo'}])
214
+
215
+ it "opens a modal window", ->
216
+ spy = spyOn(Mercury, 'modal').andCallFake(=>)
217
+ @button = new Mercury.Toolbar.Button('foo', 'title', 'summary', {modal: '/evergreen/responses/blank.html'})
218
+
219
+ jasmine.simulate.click(@button.get(0))
220
+ expect(spy.argsForCall[0]).toEqual(['/evergreen/responses/blank.html', {title: 'summary', handler: 'foo'}])
221
+
222
+ it "shows and hides palettes", ->
223
+ spy = spyOn(Mercury.Palette.prototype, 'toggle').andCallFake(=>)
224
+ @button = new Mercury.Toolbar.Button('foo', 'title', 'summary', {palette: '/evergreen/responses/blank.html'})
225
+
226
+ jasmine.simulate.click(@button.get(0))
227
+ expect(spy.callCount).toEqual(1)
228
+
229
+ jasmine.simulate.click(@button.get(0))
230
+ expect(spy.callCount).toEqual(2)
231
+
232
+ it "shows and hides selects", ->
233
+ spy = spyOn(Mercury.Select.prototype, 'toggle').andCallFake(=>)
234
+ @button = new Mercury.Toolbar.Button('foo', 'title', 'summary', {select: '/evergreen/responses/blank.html'})
235
+
236
+ jasmine.simulate.click(@button.get(0))
237
+ expect(spy.callCount).toEqual(1)
238
+
239
+ jasmine.simulate.click(@button.get(0))
240
+ expect(spy.callCount).toEqual(2)
241
+
242
+ it "shows and hides panels, and toggles the button pressed state", ->
243
+ spy = spyOn(Mercury.Panel.prototype, 'toggle').andCallFake(=>)
244
+ @button = new Mercury.Toolbar.Button('foo', 'title', 'summary', {panel: '/evergreen/responses/blank.html'})
245
+
246
+ jasmine.simulate.click(@button.get(0))
247
+ expect(spy.callCount).toEqual(1)
248
+
249
+ jasmine.simulate.click(@button.get(0))
250
+ expect(spy.callCount).toEqual(2)
251
+
252
+
253
+ describe "Mercury.Toolbar.Button.contexts", ->
254
+
255
+ template 'mercury/toolbar.button.html'
256
+
257
+ beforeEach ->
258
+ @contexts = Mercury.Toolbar.Button.contexts
259
+ @region = $('#context_container')
260
+ @element = $('#context_button')
261
+
262
+ it "handles background color", ->
263
+ @contexts.backcolor.call(@, $('#context_backcolor'), @region)
264
+ expect(@element.css('background-color')).toEqual('rgb(255, 0, 0)')
265
+
266
+ @contexts.backcolor.call(@, $('#context_none'), @region)
267
+ if $.browser.mozilla
268
+ expect(@element.css('background-color')).toEqual('transparent')
269
+ else
270
+ expect(@element.css('background-color')).toEqual('rgba(0, 0, 0, 0)')
271
+
272
+ it "handles foreground color", ->
273
+ @contexts.forecolor.call(@, $('#context_forecolor'), @region)
274
+ expect(@element.css('background-color')).toEqual('rgb(0, 255, 0)')
275
+
276
+ @contexts.forecolor.call(@, $('#context_none'), @region)
277
+ expect(@element.css('background-color')).toEqual('rgb(0, 0, 0)')
278
+
279
+ it "knows when something is bold", ->
280
+ expect(@contexts.bold.call(@, $('#context_bold1 span'), @region)).toEqual(true)
281
+ expect(@contexts.bold.call(@, $('#context_bold2 span'), @region)).toEqual(true)
282
+ expect(@contexts.bold.call(@, $('#context_bold3 span'), @region)).toEqual(true)
283
+ expect(@contexts.bold.call(@, $('#context_bold4 span'), @region)).toEqual(true)
284
+ expect(@contexts.bold.call(@, $('#context_bold5 span'), @region)).toEqual(false)
285
+ expect(@contexts.bold.call(@, $('#context_bold6 span'), @region)).toEqual(true)
286
+ expect(@contexts.bold.call(@, $('#context_none'), @region)).toEqual(false)
287
+
288
+ it "knows when something is italic", ->
289
+ expect(@contexts.italic.call(@, $('#context_italic1 span'), @region)).toEqual(true)
290
+ expect(@contexts.italic.call(@, $('#context_italic2 span'), @region)).toEqual(true)
291
+ expect(@contexts.italic.call(@, $('#context_none'), @region)).toEqual(false)
292
+
293
+ it "knows when something is overlined", ->
294
+ expect(@contexts.overline.call(@, $('#context_overline'), @region)).toEqual(true)
295
+ expect(@contexts.overline.call(@, $('#context_none'), @region)).toEqual(false)
296
+
297
+ it "knows when something is striked through", ->
298
+ expect(@contexts.strikethrough.call(@, $('#context_strikethrough1 span'), @region)).toEqual(true)
299
+ expect(@contexts.strikethrough.call(@, $('#context_strikethrough2'), @region)).toEqual(true)
300
+ expect(@contexts.strikethrough.call(@, $('#context_none'), @region)).toEqual(false)
301
+
302
+ it "knows when something is underlined", ->
303
+ expect(@contexts.underline.call(@, $('#context_underline1 span'), @region)).toEqual(true)
304
+ expect(@contexts.underline.call(@, $('#context_underline2'), @region)).toEqual(true)
305
+ expect(@contexts.underline.call(@, $('#context_none'), @region)).toEqual(false)
306
+
307
+ it "knows when something is subscript", ->
308
+ expect(@contexts.subscript.call(@, $('#context_subscript span'), @region)).toEqual(true)
309
+ expect(@contexts.subscript.call(@, $('#context_none'), @region)).toEqual(false)
310
+
311
+ it "knows when something is superscript", ->
312
+ expect(@contexts.superscript.call(@, $('#context_superscript span'), @region)).toEqual(true)
313
+ expect(@contexts.superscript.call(@, $('#context_none'), @region)).toEqual(false)
314
+
315
+ it "knows when something is justified left", ->
316
+ expect(@contexts.justifyleft.call(@, $('#context_justifyleft span'), @region)).toEqual(true)
317
+ expect(@contexts.justifyleft.call(@, $('#context_none'), @region)).toEqual(false)
318
+
319
+ it "knows when something is justified center", ->
320
+ expect(@contexts.justifycenter.call(@, $('#context_justifycenter span'), @region)).toEqual(true)
321
+ expect(@contexts.justifycenter.call(@, $('#context_none'), @region)).toEqual(false)
322
+
323
+ it "knows when something is justified right", ->
324
+ expect(@contexts.justifyright.call(@, $('#context_justifyright span'), @region)).toEqual(true)
325
+ expect(@contexts.justifyright.call(@, $('#context_none'), @region)).toEqual(false)
326
+
327
+ it "knows when something is justified fully", ->
328
+ expect(@contexts.justifyfull.call(@, $('#context_justifyfull span'), @region)).toEqual(true)
329
+ expect(@contexts.justifyfull.call(@, $('#context_none'), @region)).toEqual(false)
330
+
331
+ it "knows when something is inside an ordered list", ->
332
+ expect(@contexts.insertorderedlist.call(@, $('#context_orderedlist span'), @region)).toEqual(true)
333
+ expect(@contexts.insertorderedlist.call(@, $('#context_none'), @region)).toEqual(false)
334
+
335
+ it "knows when something is inside an unordered list", ->
336
+ expect(@contexts.insertunorderedlist.call(@, $('#context_unorderedlist span'), @region)).toEqual(true)
337
+ expect(@contexts.insertunorderedlist.call(@, $('#context_none'), @region)).toEqual(false)
338
+
339
+ # todo: fix in jquery
340
+ # it "understands nested text-decoration styles", ->
341
+ # expect(@contexts.underline.call(@, $('#context_decoration'), @region)).toEqual(true)
@@ -0,0 +1,120 @@
1
+ require '/assets/mercury/mercury.js'
2
+
3
+ describe "Mercury.Toolbar.Expander", ->
4
+
5
+ template 'mercury/toolbar.expander.html'
6
+
7
+ beforeEach ->
8
+ @container = $('#expander_container')
9
+
10
+ afterEach ->
11
+ @expander = null
12
+ delete(@expander)
13
+ $(document).unbind('mercury:resize')
14
+
15
+ describe "constructor", ->
16
+
17
+ beforeEach ->
18
+ @expander = new Mercury.Toolbar.Expander('foo', {appendTo: '#test', for: @container})
19
+
20
+ it "expects a name, and options", ->
21
+ html = $('<div>').html(@expander).html()
22
+ expect(html).toContain('class="mercury-palette mercury-expander mercury-foo-expander"')
23
+ expect(html).toMatch(/style="display:\s?none/)
24
+ expect($('#test .mercury-toolbar-expander').length).toEqual(1)
25
+
26
+
27
+ describe "#build", ->
28
+
29
+ beforeEach ->
30
+ @resizeSpy = spyOn(Mercury.Toolbar.Expander.prototype, 'windowResize').andCallFake(=>)
31
+ @expander = new Mercury.Toolbar.Expander('foo', {appendTo: '#test', for: @container})
32
+
33
+ it "sets the whitespace of the container to normal", ->
34
+ expect(@container.css('whiteSpace')).toEqual('normal')
35
+
36
+ it "builds an element", ->
37
+ html = $('<div>').html(@expander).html()
38
+ expect(html).toContain('class="mercury-palette mercury-expander mercury-foo-expander"')
39
+ expect(html).toMatch(/style="display:\s?none/)
40
+
41
+ it "builds a trigger button", ->
42
+ expect($('#test .mercury-toolbar-expander').length).toEqual(1)
43
+
44
+ it "calls windowResize", ->
45
+ expect(@resizeSpy.callCount).toEqual(1)
46
+
47
+
48
+ describe "observed events", ->
49
+
50
+ beforeEach ->
51
+ $('.mercury-button').data('expander', '<div data-button="test">expander</div>')
52
+ @expander = new Mercury.Toolbar.Expander('foo', {appendTo: '#test', for: @container})
53
+
54
+ describe "custom event: hide:dialogs", ->
55
+
56
+ it "hides", ->
57
+ @expander.css({display: 'block'})
58
+ Mercury.trigger('hide:dialogs')
59
+ expect(@expander.css('display')).toEqual('none')
60
+
61
+ it "doesn't hide if it's the same dialog", ->
62
+ # there's no way to test this since we don't expose the instance -- just the element
63
+ #@expander.css({display: 'block'})
64
+ #Mercury.trigger('hide:dialogs', !instance!)
65
+ #expect(@expander.css('display')).toEqual('block')
66
+
67
+ describe "custom event: resize", ->
68
+
69
+ it "calls windowResize", ->
70
+ spy = spyOn(Mercury.Toolbar.Expander.prototype, 'windowResize').andCallFake(=>)
71
+ Mercury.trigger('resize')
72
+ expect(spy.callCount).toEqual(1)
73
+
74
+ describe "click (on trigger)", ->
75
+
76
+ it "pulls buttons into the palette", ->
77
+ jasmine.simulate.click($('.mercury-toolbar-expander').get(0))
78
+ expect(@expander.html()).toEqual('<div data-button="test">expander</div>')
79
+
80
+ describe "click", ->
81
+
82
+ it "calls click on the real button", ->
83
+ button = $('#button2')
84
+ spy = spyOn(button, 'click').andCallFake(=>)
85
+ @container.find = -> button
86
+ @expander.appendTo('#test')
87
+
88
+ jasmine.simulate.click($('.mercury-toolbar-expander').get(0))
89
+ jasmine.simulate.click($('[data-button=test]').get(0))
90
+ expect(spy.callCount).toEqual(1)
91
+
92
+ describe "#windowResize", ->
93
+
94
+ it "hides", ->
95
+ @expander = new Mercury.Toolbar.Expander('foo', {appendTo: '#test', for: @container})
96
+ @expander.css({display: 'block'})
97
+
98
+ Mercury.trigger('resize')
99
+ expect(@expander.css('display')).toEqual('none')
100
+
101
+ it "shows the trigger if the container is wider than the window", ->
102
+ @expander = new Mercury.Toolbar.Expander('foo', {appendTo: '#test', for: @container})
103
+ Mercury.trigger('resize')
104
+ expect($('.mercury-toolbar-expander').css('display')).toEqual('block')
105
+
106
+ it "hides the trigger if the container is narrower than the window", ->
107
+ @container.css({width: '1px'})
108
+ @expander = new Mercury.Toolbar.Expander('foo', {appendTo: '#test', for: @container})
109
+ Mercury.trigger('resize')
110
+ expect($('.mercury-toolbar-expander').css('display')).toEqual('none')
111
+
112
+
113
+ describe "#position", ->
114
+
115
+ it "positions the element", ->
116
+ @expander = new Mercury.Toolbar.Expander('foo', {appendTo: '#test', for: @container})
117
+ @expander.appendTo('#positioned_container')
118
+ jasmine.simulate.click($('.mercury-toolbar-expander').get(0))
119
+
120
+ expect(@expander.offset()).toEqual({top: 42, left: 42})