aslakjo-aslakjo-comatose 2.0.5.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (93) hide show
  1. data/CHANGELOG +195 -0
  2. data/INSTALL +20 -0
  3. data/LICENSE +20 -0
  4. data/MANIFEST +91 -0
  5. data/README.markdown +159 -0
  6. data/Rakefile +176 -0
  7. data/SPECS +61 -0
  8. data/about.yml +7 -0
  9. data/bin/comatose +112 -0
  10. data/comatose.gemspec +113 -0
  11. data/generators/comatose_migration/USAGE +15 -0
  12. data/generators/comatose_migration/comatose_migration_generator.rb +74 -0
  13. data/generators/comatose_migration/templates/migration.rb +35 -0
  14. data/generators/comatose_migration/templates/v4_upgrade.rb +15 -0
  15. data/generators/comatose_migration/templates/v6_upgrade.rb +23 -0
  16. data/generators/comatose_migration/templates/v7_upgrade.rb +22 -0
  17. data/init.rb +2 -0
  18. data/install.rb +18 -0
  19. data/lib/acts_as_versioned.rb +543 -0
  20. data/lib/comatose.rb +33 -0
  21. data/lib/comatose/comatose_drop.rb +79 -0
  22. data/lib/comatose/configuration.rb +69 -0
  23. data/lib/comatose/page_wrapper.rb +119 -0
  24. data/lib/comatose/processing_context.rb +69 -0
  25. data/lib/comatose/tasks/admin.rb +60 -0
  26. data/lib/comatose/tasks/data.rb +82 -0
  27. data/lib/comatose/tasks/setup.rb +52 -0
  28. data/lib/comatose/version.rb +4 -0
  29. data/lib/comatose_admin_controller.rb +395 -0
  30. data/lib/comatose_admin_helper.rb +37 -0
  31. data/lib/comatose_controller.rb +138 -0
  32. data/lib/comatose_helper.rb +3 -0
  33. data/lib/comatose_page.rb +141 -0
  34. data/lib/liquid.rb +52 -0
  35. data/lib/liquid/block.rb +96 -0
  36. data/lib/liquid/context.rb +190 -0
  37. data/lib/liquid/document.rb +17 -0
  38. data/lib/liquid/drop.rb +48 -0
  39. data/lib/liquid/errors.rb +7 -0
  40. data/lib/liquid/extensions.rb +53 -0
  41. data/lib/liquid/file_system.rb +62 -0
  42. data/lib/liquid/htmltags.rb +64 -0
  43. data/lib/liquid/standardfilters.rb +111 -0
  44. data/lib/liquid/standardtags.rb +399 -0
  45. data/lib/liquid/strainer.rb +42 -0
  46. data/lib/liquid/tag.rb +25 -0
  47. data/lib/liquid/template.rb +88 -0
  48. data/lib/liquid/variable.rb +39 -0
  49. data/lib/redcloth.rb +1129 -0
  50. data/lib/support/class_options.rb +36 -0
  51. data/lib/support/inline_rendering.rb +48 -0
  52. data/lib/support/route_mapper.rb +50 -0
  53. data/lib/text_filters.rb +140 -0
  54. data/lib/text_filters/markdown.rb +14 -0
  55. data/lib/text_filters/markdown_smartypants.rb +15 -0
  56. data/lib/text_filters/none.rb +8 -0
  57. data/lib/text_filters/rdoc.rb +13 -0
  58. data/lib/text_filters/simple.rb +8 -0
  59. data/lib/text_filters/textile.rb +15 -0
  60. data/rails/init.rb +3 -0
  61. data/resources/layouts/comatose_admin_template.html.erb +28 -0
  62. data/resources/public/images/collapsed.gif +0 -0
  63. data/resources/public/images/expanded.gif +0 -0
  64. data/resources/public/images/no-children.gif +0 -0
  65. data/resources/public/images/page.gif +0 -0
  66. data/resources/public/images/spinner.gif +0 -0
  67. data/resources/public/images/title-hover-bg.gif +0 -0
  68. data/resources/public/javascripts/comatose_admin.js +401 -0
  69. data/resources/public/stylesheets/comatose_admin.css +404 -0
  70. data/tasks/comatose.rake +9 -0
  71. data/test/behaviors.rb +106 -0
  72. data/test/fixtures/comatose_pages.yml +96 -0
  73. data/test/functional/comatose_admin_controller_test.rb +114 -0
  74. data/test/functional/comatose_controller_test.rb +44 -0
  75. data/test/javascripts/test.html +26 -0
  76. data/test/javascripts/test_runner.js +307 -0
  77. data/test/test_helper.rb +55 -0
  78. data/test/unit/class_options_test.rb +52 -0
  79. data/test/unit/comatose_page_test.rb +136 -0
  80. data/test/unit/processing_context_test.rb +108 -0
  81. data/test/unit/text_filters_test.rb +52 -0
  82. data/views/comatose_admin/_form.html.erb +96 -0
  83. data/views/comatose_admin/_page_list_item.html.erb +60 -0
  84. data/views/comatose_admin/delete.html.erb +18 -0
  85. data/views/comatose_admin/edit.html.erb +5 -0
  86. data/views/comatose_admin/index.html.erb +29 -0
  87. data/views/comatose_admin/new.html.erb +5 -0
  88. data/views/comatose_admin/reorder.html.erb +30 -0
  89. data/views/comatose_admin/versions.html.erb +40 -0
  90. data/views/layouts/comatose_admin.html.erb +837 -0
  91. data/views/layouts/comatose_admin_customize.html.erb +28 -0
  92. data/views/layouts/comatose_content.html.erb +17 -0
  93. metadata +148 -0
@@ -0,0 +1,60 @@
1
+ <%# Params:
2
+ # - page (Page Node)
3
+ # - level (integer indicating current tree depth)
4
+ # Called From:
5
+ # - index
6
+ # Description:
7
+ # This partial is used recursively. Render it with the root node, and it will recurse
8
+ # down all of the child nodes to build a list with proper indentation to indicate
9
+ # tree depth.
10
+ %>
11
+
12
+ <%
13
+ # Create the page-level links...
14
+ links = []
15
+ links << link_to(pluralize(page.versions.length, 'revision', 'revisions'), :action=>'versions', :id=>page) if !page.nil? and !page.versions.nil? and page.versions.length > 0
16
+ links << link_to('add child page', {:action=>'new', :parent=>page}, :title=>"Add a child to '#{page.title}'", :class=>'add-page')
17
+ links << link_to_function('reorder children', "ComatoseList.toggle_reorder('page_list_#{page.id}',this,#{page.id})", :title=>"Reorder children of '#{page.title}'", :class=>'reorder-children', :href=>url_for(:action=>'reorder', :id=>page)) if !page.children.empty? and page.children.length > 1
18
+ links << link_to('delete', {:action=>'delete', :id=>page}, :confirm=>'This will delete this page, and any children. Are you sure?', :title=>"Delete page '#{page.title}' and all it's children", :class=>'delete-page', :method=>'post', :onmouseover=>"ComatoseList.item_hover('page_#{page.id}', 'over', true)", :onmouseout=>"ComatoseList.item_hover('page_#{page.id}', 'out', true)") unless @root_pages.include? page
19
+ # Level check, one, two, three...
20
+ collapse_children = (level >= Comatose.config.default_tree_level)
21
+ %>
22
+
23
+ <li id="page_<%= page.id %>">
24
+ <table cellpadding="0" cellspacing="0">
25
+ <tr>
26
+ <td rowspan="2" valign="center">
27
+ <% if !page.children.empty? %>
28
+ <%= image_tag( ((collapse_children) ? 'comatose/collapsed.gif' : 'comatose/expanded.gif'), :title=>'Expand/Collapse', :onclick=>"ComatoseList.toggle_tree_nodes(this,#{page.id});", :class=>'tree-controller', :size=>'12x12', :id=>"page_controller_#{page.id}" ) %>
29
+ <% else %>
30
+ <%= image_tag 'comatose/no-children.gif', :size=>'12x12', :class=>'tree-controller' %>
31
+ <% end %>
32
+ </td>
33
+ <td rowspan="2" valign="center">
34
+ <%= image_tag 'comatose/page.gif', :size=>'25x31', :align=>"absmiddle" %>
35
+ <span class="handle">DRAG</span>
36
+ </td>
37
+ <td>
38
+ <%= link_to page.title, {:action=>'edit', :id=>page}, :title=>"Path:#{page.full_path}", :class=>'page' %>
39
+ </td>
40
+ </tr>
41
+ <tr>
42
+ <td class="commands">
43
+ Updated <span title="Created on <%= page.created_on %>"><%= time_ago_in_words page.updated_on, true %> ago</span><%= " by #{page.author}" unless page.author.nil? or page.author.empty? %>,
44
+ <%= links.join(', ') %>.
45
+ </td>
46
+ </tr>
47
+ </table>
48
+
49
+ <ul id="page_list_<%= page.id %>" old="lvl-<%= page.id %>" class="page-list <%= 'collapsed' if collapse_children %>" >
50
+ <% for child in page.children %>
51
+ <%= render :partial=>'page_list_item', :locals=>{ :page=>child, :level=>level+1 } %>
52
+ <% end %>
53
+ </ul>
54
+
55
+ <%= sortable_element( "page_list_#{page.id}",
56
+ :complete => visual_effect(:highlight, "page_list_#{page.id}"),
57
+ :handle=>'handle',
58
+ :update=>'flash-content',
59
+ :url => { :action => "reorder", :id=>page } ) if !page.children.empty? and page.children.length > 1 %>
60
+ </li>
@@ -0,0 +1,18 @@
1
+ <h1>
2
+ Page Delete Confirmation
3
+ </h1>
4
+
5
+ <blockquote>
6
+ <p>Are you sure you want to delete the page titled "<b><%= @page.title %></b>"?</p>
7
+ <% unless @page.children.empty? %>
8
+ <p>It has <b><%= @page.children.length %></b> child pages that will also be deleted...</p>
9
+ <% end %>
10
+ </blockquote>
11
+
12
+ <%= start_form_tag %>
13
+ <div id="button-group">
14
+ <%= submit_tag "Yes, Delete The Page" %>
15
+ or
16
+ <%= link_to "Cancel", :action=>'index' %>
17
+ </div>
18
+ <%= end_form_tag %>
@@ -0,0 +1,5 @@
1
+ <h1>
2
+ Edit Page
3
+ </h1>
4
+
5
+ <%= render :partial=>'form', :locals=>{:mode=>:edit} %>
@@ -0,0 +1,29 @@
1
+ <div class="action">
2
+ <%= link_to 'Clear Page Cache', :controller=>controller.controller_name, :action=>'expire_page_cache' %>
3
+ <% if Comatose.config.allow_import_export %>
4
+ <%= link_to 'Import', '#', :id => 'import_link2', :onclick => "$('import_form').setStyle({display: 'inline'}); return false;" %>
5
+ <%= link_to 'Export', :controller=>controller.controller_name, :action=>'export' %>
6
+ <div id="import_form" style="display: none;">
7
+ <% form_tag(url_for(:action => 'import'), :multipart => true) do %>
8
+ <%= file_field_tag 'import_file' %>
9
+ <%= submit_tag 'Upload and Import' %>
10
+ <a href="#" onclick="$('import_form').hide(); return false;">Cancel</a>
11
+ <% end %>
12
+ </div>
13
+ <% end %>
14
+ </div>
15
+
16
+ <h1>
17
+ Page List
18
+ <%= image_tag 'comatose/spinner.gif', :id=>'spinner', :align=>'absmiddle', :style=>'display:none;' %>
19
+ </h1>
20
+
21
+ <ul class="page-list root">
22
+ <% @root_pages.each do |page| %>
23
+ <%= render :partial=>'page_list_item', :locals=>{ :page=>page, :level=>1 } %>
24
+ <% end %>
25
+ </ul>
26
+
27
+ <div id="status"></div>
28
+
29
+ <%= javascript_tag "ComatoseList.init()" %>
@@ -0,0 +1,5 @@
1
+ <h1>
2
+ New Page
3
+ </h1>
4
+
5
+ <%= render :partial=>'form', :locals=>{:mode=>:new} %>
@@ -0,0 +1,30 @@
1
+ <h1>Reorder Pages</h1>
2
+
3
+ <h3>"<%= @page.title %>" child pages:</h3>
4
+
5
+ <ul class="page-list">
6
+ <% @page.children.each do |page| %>
7
+ <li>
8
+ <table cellpadding="0" cellspacing="0">
9
+ <tr>
10
+ <td rowspan="2" valign="center">
11
+ <%= image_tag 'comatose/page.gif', :size=>'25x31', :align=>"absmiddle" %>
12
+ </td>
13
+ <td>
14
+ <a class="page"><%= page.title %></a>
15
+ </td>
16
+ </tr>
17
+ <tr>
18
+ <td class="commands">
19
+ <%= link_to "Move Up", :action=>'reorder', :cmd=>'up', :page=>page.id %>,
20
+ <%= link_to "Move Down", :action=>'reorder', :cmd=>'down', :page=>page.id %>
21
+ </td>
22
+ </tr>
23
+ </table>
24
+ </li>
25
+ <% end %>
26
+ </ul>
27
+
28
+ <div id="button-group">
29
+ <%= link_to "Finished", :action=>'index' %>
30
+ </div>
@@ -0,0 +1,40 @@
1
+ <h1>Page Revisions</h1>
2
+ <form>
3
+ <div class="revisions older-content">
4
+ <div class="header">
5
+ <div class="header-actions">
6
+ <% form_tag :action => 'versions', :id => @page, :html => { :method => :get } do %>
7
+ View Version: <%= select_tag "version", options_from_collection_for_select(@page.versions, 'version', 'version', @version_num), {'onchange'=>'this.form.submit();'} %>
8
+ <%= submit_tag 'Go', {'id'=>'go-btn'} %>
9
+ <% end %>
10
+ </div>
11
+ Version <%= @version_num %>
12
+ </div>
13
+ <div class="meta">
14
+ <label class="title"><span>Title:</span><%= @version.title %></label>
15
+ <label><span>Slug:</span> <%= @version.slug %></label>
16
+ <label><span>Keywords:</span> <%= @version.keywords %></label>
17
+ </div>
18
+ <%= @version.body.split("\n").join('<br/>') unless @version.body.nil? %>
19
+ <div id="button-group" class="footer">
20
+ <% form_tag :action=>'set_version', :id => @page, :version => @version_num do %>
21
+ <%= submit_tag "Set As Current Version" %>
22
+ or
23
+ <%= link_to "Cancel", :action=>'index' %>
24
+ <% end %>
25
+ </div>
26
+ </div>
27
+
28
+ <div class="revisions current-content">
29
+ <div class="header">
30
+ Current Version
31
+ </div>
32
+ <div class="meta">
33
+ <label class="title"><span>Title:</span><%= @page.title %></label>
34
+ <label><span>Slug:</span> <%= @page.slug %></label>
35
+ <label><span>Keywords:</span> <%= @page.keywords %></label>
36
+ </div>
37
+ <%= @page.body.split("\n").join('<br/>') unless @page.body.nil? %>
38
+ </div>
39
+
40
+ <div style="clear:both">&nbsp;</div>
@@ -0,0 +1,837 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3
+ <html class="noscript" xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
4
+ <head>
5
+ <meta http-equiv="Content-Type" content="text/html; charset=<%= Comatose.config.content_type %>"/>
6
+ <title>Comatose Admin</title>
7
+ <style>
8
+ BODY {
9
+ background: #DDD;
10
+ margin: 0px 100px;
11
+ padding: 0px;
12
+ font-family: "Lucida Grande", Tahoma, Verdana, Arial, Sans-Serif;
13
+ font-size: 12px;
14
+ min-width: 450px;
15
+ }
16
+ /* General Layout and Header Area */
17
+ #page-container {
18
+ margin: 0px;
19
+ padding: 0px;
20
+ }
21
+ #header {
22
+ background: #0053C2;
23
+ padding: 5px;
24
+ border-bottom: 4px solid #00398B;
25
+ }
26
+ #header A {
27
+ text-decoration: none;
28
+ color: white;
29
+ }
30
+ #header A:hover {
31
+ color: white;
32
+ }
33
+ #header h1 {
34
+ margin: 0px;
35
+ padding: 0px;
36
+ padding-left: 10px;
37
+ }
38
+ #header h5 {
39
+ margin: 0px;
40
+ padding: 0px;
41
+ padding-left: 15px;
42
+ color: silver;
43
+ }
44
+ #header #flash {
45
+ float: right;
46
+ color: #4BA8FF;
47
+ font-weight: bold;
48
+ margin-right: 5px;
49
+ }
50
+ /* Content Area */
51
+ #content {
52
+ padding: 15px;
53
+ background: white;
54
+ border-left: 1px solid silver;
55
+ border-right: 1px solid silver;
56
+ }
57
+ #content h1 {
58
+ margin: 0px;
59
+ padding: 0px;
60
+ font-size: 135%;
61
+ color: gray;
62
+ }
63
+ #content .action {
64
+ float: right;
65
+ color: gray;
66
+ }
67
+ #content .action A {
68
+ font-weight: bold;
69
+ text-decoration: none;
70
+ color: navy;
71
+ border-bottom: 1px solid blue;
72
+ margin-left: 15px;
73
+ }
74
+ #content .action A:hover {
75
+ color: red;
76
+ border-bottom: 1px solid red;
77
+ }
78
+ #content .page-header {
79
+ color: gray;
80
+ }
81
+ #import_form {
82
+ position: fixed;
83
+ right: 75px;
84
+ border: 3px solid gray !important;
85
+ -webkit-border-radius: 10px;
86
+ -moz-border-radius: 10px;
87
+ background: #FFF;
88
+ padding: 15px;
89
+ }
90
+ #import_form FORM {
91
+ display: inline;
92
+ margin: 0px;
93
+ padding: 0px;
94
+ }
95
+ #import_form A {
96
+ color: maroon !important;
97
+ border-bottom: 1px solid gray !important;
98
+ }
99
+ #import_form A:hover {
100
+ color: red !important;
101
+ border-bottom: 1px solid red !important;
102
+ }
103
+
104
+ /* Page Listing */
105
+ #content .tree-controller {
106
+ border: 0px;
107
+ cursor: pointer;
108
+ }
109
+ #content .page-list.root {
110
+ clear: both;
111
+ list-style: none;
112
+ margin: 0px;
113
+ padding: 0px;
114
+ margin-top: 10px;
115
+ }
116
+ #content .page-list.collapsed {
117
+ display: none;
118
+ }
119
+ #content .page-list {
120
+ background: white;
121
+ clear: both;
122
+ list-style: none;
123
+ border-left: 0px dotted silver;
124
+ margin: 0px;
125
+ padding: 0px;
126
+ padding-left: 15px;
127
+ margin-top: 2px;
128
+ }
129
+ #content .page-list LI {
130
+ clear: both;
131
+ padding: 0px;
132
+ margin: 5px 0px;
133
+ padding-top: 2px;
134
+ padding-right: 0px;
135
+ padding-left: 2px;
136
+ }
137
+ #content .page-list .commands {
138
+ font-size: 90%;
139
+ padding-left: 5px;
140
+ color: silver;
141
+ }
142
+ #content .page-list .commands A {
143
+ color: gray;
144
+ }
145
+ #content .page-list .commands A.add-page:hover {
146
+ color: blue;
147
+ }
148
+ #content .page-list .commands A.reorder-children:hover {
149
+ color: black;
150
+ }
151
+ #content .page-list .commands A.delete-page:hover {
152
+ color: white;
153
+ }
154
+ #content .page-list .commands A.reordering {
155
+ background: navy;
156
+ color: white;
157
+ }
158
+ #content .page-list .commands A.reordering:hover {
159
+ color: white;
160
+ }
161
+ #content .page-list A.page {
162
+ text-decoration: none;
163
+ color: black;
164
+ margin-left: 3px;
165
+ font-size: 150%;
166
+ display: block;
167
+ }
168
+ #content .page-list A.page:hover {
169
+ /*color: blue;*/
170
+ background: white url(../images/comatose/title-hover-bg.gif) top left repeat-y;
171
+ }
172
+ #content .handle, #content .do-reorder UL LI .handle {
173
+ display: none;
174
+ }
175
+
176
+ #content .page-list .hover {
177
+ background: #F1F0DB;
178
+ }
179
+ #content .page-list .hover-delete {
180
+ background: red;
181
+ color: #FF8E90;
182
+ }
183
+ #content .page-list .hover-delete A,
184
+ #content .page-list .hover-delete .commands A {
185
+ color: #FF8E90;
186
+ }
187
+ #content .page-list .hover-delete A.page {
188
+ color: white;
189
+ border-bottom: 0px;
190
+ }
191
+ #content .page-list .hover-delete UL LI A.page {
192
+ color: red;
193
+ border-bottom: 0px;
194
+ }
195
+
196
+ #content .do-reorder LI .handle {
197
+ display: inline;
198
+ background: gray;
199
+ color: white;
200
+ padding: 1px 3px;
201
+ cursor: move;
202
+ }
203
+
204
+ #content .page-list .do-reorder .commands A {
205
+ display: none;
206
+ }
207
+
208
+ /* Page Form */
209
+ #content .page-form {
210
+ margin-top: 10px;
211
+ }
212
+ #content .page-form LABEL {
213
+ font-weight: bold;
214
+ color: #555;
215
+ }
216
+ #content .page-form .meta-info LABEL {
217
+ color: #999 !important;
218
+ }
219
+ #content .page-form .label {
220
+ padding-top: 5px;
221
+ width: 75px;
222
+ text-align: right;
223
+ padding-right: 10px;
224
+ }
225
+ #content .page-form .label.body {
226
+ vertical-align: top;
227
+ padding-top: 10px;
228
+ }
229
+ #content .page-form .field {
230
+ padding-top: 5px;
231
+ }
232
+ #content .page-form .field-help {
233
+ color: gray;
234
+ }
235
+ #content .page-form #page_title {
236
+ font-size: 125%;
237
+ font-weight: bold;
238
+ }
239
+ #content .page-form #page_slug {
240
+ color: gray;
241
+ }
242
+ #content .page-form #page_body {
243
+ font-family: monospace;
244
+ font-size: 110%;
245
+ }
246
+ #content #button-group {
247
+ padding: 10px;
248
+ text-align: right;
249
+ background-color: #EAEAEA;
250
+ margin-top: 10px;
251
+ }
252
+ #content #button-group .last-update {
253
+ float: left;
254
+ color: gray;
255
+ padding-top: 4px;
256
+ font-weight: bold;
257
+ }
258
+ #content #button-group .last-update LABEL {
259
+ font-weight: normal;
260
+ }
261
+ #content #button-group .last-update A {
262
+ color: gray;
263
+ }
264
+ #content #button-group A {
265
+ color: maroon;
266
+ }
267
+ #content #button-group A:hover {
268
+ color: red;
269
+ }
270
+ #content #preview-area {
271
+ margin-top: 10px;
272
+ }
273
+ #content #preview-area FIELDSET {
274
+ border: 1px solid silver;
275
+ }
276
+ #content #preview-area LEGEND {
277
+ font-size: 125%;
278
+ }
279
+ #content #preview-area .preview-body {
280
+ padding: 10px;
281
+ }
282
+ #content #preview-area .preview-note {
283
+ background: #FFFFD9;
284
+ padding: 15px;
285
+ }
286
+ #content #preview-area .commands {
287
+ text-align: right;
288
+ color: gray;
289
+ }
290
+ #content #preview-area .commands A{
291
+ color: gray;
292
+ }
293
+ #content #preview-area .commands A:hover{
294
+ color: black;
295
+ }
296
+ #content .revisions {
297
+ padding: 10px;
298
+ width: 49%;
299
+ }
300
+ #content .current-content {
301
+ }
302
+ #content .older-content {
303
+ background: #E9E9E9;
304
+ float: right;
305
+ }
306
+
307
+ #content .revisions label {
308
+ display: block;
309
+ color: #000;
310
+ }
311
+ #content .revisions label span {
312
+ color: #999;
313
+ font-weight: normal !important;
314
+ }
315
+ #content .revisions .title {
316
+ font-weight: bold;
317
+ margin-top: 5px;
318
+ }
319
+ #content .revisions .header {
320
+ font-size: 110%;
321
+ vertical-align: middle;
322
+ font-weight: bold;
323
+ }
324
+ #content .revisions .header-actions {
325
+ float: right;
326
+ font-size: 90%;
327
+ font-weight: normal;
328
+ color: #999;
329
+ }
330
+ #content .revisions .meta {
331
+ margin-bottom: 15px;
332
+ }
333
+ #content .revisions .footer {
334
+ margin-top: 25px !important;
335
+ text-align: center !important;
336
+ }
337
+ #content #go-btn {
338
+ display: none;
339
+ }
340
+ /* Errors */
341
+ #errorExplanation {
342
+ border: 1px solid red;
343
+ background: #FFEAEB;
344
+ padding: 10px;
345
+ margin-top: 10px;
346
+ }
347
+ #errorExplanation h2 {
348
+ margin: 0px;
349
+ padding: 0px;
350
+ color: maroon;
351
+ }
352
+ #errorExplanation p {
353
+ margin: 0px;
354
+ padding: 0px;
355
+ padding-top: 5px;
356
+ padding-left: 15px;
357
+ }
358
+ #errorExplanation ul {
359
+ margin: 0px;
360
+ padding: 0px;
361
+ padding-left: 35px;
362
+ }
363
+ #errorExplanation li {
364
+ margin: 0px;
365
+ padding: 0px;
366
+ padding-top: 5px;
367
+ }
368
+ /* Footer Area*/
369
+ #footer {
370
+ border-top: 4px solid #AAA;
371
+ text-align: center;
372
+ font-size: 90%;
373
+ color: #AAA;
374
+ padding-top: 5px;
375
+ padding-bottom: 5px;
376
+ }
377
+ #footer A {
378
+ color: #AAA;
379
+ text-decoration: none;
380
+ font-weight: bold;
381
+ }
382
+ #footer A:hover {
383
+ color: #333;
384
+ text-decoration: underline;
385
+ }
386
+
387
+ /* Modifiers */
388
+
389
+ /* When JavaScript is Turned Off... We need to adjust some things... */
390
+ .noscript #more-options,
391
+ .noscript #preview-area,
392
+ .noscript #preview-btn,
393
+ .noscript .tree-controller {
394
+ display: none;
395
+ }
396
+ .noscript .page-list.collapsed {
397
+ display: block !important;
398
+ }
399
+ .noscript .delete-page:hover {
400
+ color: red !important;
401
+ }
402
+ .noscript #content .page-form #page_title,
403
+ .noscript #content .page-form #page_slug,
404
+ .noscript #content .page-form #page_parent,
405
+ .noscript #content .page-form #page_keywords,
406
+ .noscript #content .page-form #page_body {
407
+ width: 100% !important;
408
+ }
409
+ .noscript #content .revisions #go-btn {
410
+ display: inline;
411
+ }
412
+
413
+ </style>
414
+ <%= javascript_include_tag :defaults %>
415
+ <script>
416
+ // CSS Browser Selector v0.2.3b (M@: added noscript support)
417
+ // Documentation: http://rafael.adm.br/css_browser_selector
418
+ // License: http://creativecommons.org/licenses/by/2.5/
419
+ // Author: Rafael Lima (http://rafael.adm.br)
420
+ // Contributors: http://rafael.adm.br/css_browser_selector#contributors
421
+ var css_browser_selector = function() {
422
+ var
423
+ ua = navigator.userAgent.toLowerCase(),
424
+ is = function(t){ return ua.indexOf(t) != -1; },
425
+ h = document.getElementsByTagName('html')[0],
426
+ b = (!(/opera|webtv/i.test(ua)) && /msie (\d)/.test(ua)) ? ((is('mac') ? 'ieMac ' : '') + 'ie ie' + RegExp.$1)
427
+ : is('gecko/') ? 'gecko' : is('opera') ? 'opera' : is('konqueror') ? 'konqueror' : is('applewebkit/') ? 'webkit safari' : is('mozilla/') ? 'gecko' : '',
428
+ os = (is('x11') || is('linux')) ? ' linux' : is('mac') ? ' mac' : is('win') ? ' win' : '';
429
+ var c = b+os+' js';
430
+ h.className = h.className.replace('noscript', '') + h.className?' '+c:c;
431
+ }();
432
+
433
+ // List View Functions
434
+ var ComatoseList = {
435
+ save_node_state: true,
436
+ state_store: 'cookie', // Only 'cookie' for now
437
+ state_key: 'ComatoseTreeState',
438
+
439
+ init: function() {
440
+ var items = ComatoseList._read_state();
441
+ items.each(function(node){
442
+ ComatoseList.expand_node(node.replace('page_controller_', ''))
443
+ });
444
+ },
445
+
446
+ toggle_tree_nodes : function(img, id) {
447
+ if(/expanded/.test(img.src)) {
448
+ $('page_list_'+ id).addClassName('collapsed');
449
+ img.src = img.src.replace(/expanded/, 'collapsed')
450
+ if(ComatoseList.save_node_state) {
451
+ var items = ComatoseList._read_state();
452
+ items = items.select(function(id){ return id != img.id; })
453
+ ComatoseList._write_state(items);
454
+ }
455
+ } else {
456
+ $('page_list_'+ id).removeClassName('collapsed');
457
+ img.src = img.src.replace(/collapsed/, 'expanded')
458
+ if(ComatoseList.save_node_state) {
459
+ var items = ComatoseList._read_state();
460
+ items.push(img.id);
461
+ ComatoseList._write_state(items);
462
+ }
463
+ }
464
+ },
465
+
466
+ expand_node: function(id) {
467
+ $('page_list_'+ id).removeClassName('collapsed');
468
+ $('page_controller_'+ id).src = $('page_controller_'+ id).src.replace(/collapsed/, 'expanded')
469
+ },
470
+
471
+ collapse_node: function(id) {
472
+ $('page_list_'+ id).addClassName('collapsed');
473
+ $('page_controller_'+ id).src = $('page_controller_'+ id).src.replace(/expanded/, 'collapsed')
474
+ },
475
+
476
+ item_hover : function(node, state, is_delete) {
477
+ if( state == 'over') {
478
+ $(node).addClassName( (is_delete) ? 'hover-delete' : 'hover' );
479
+ } else {
480
+ $(node).removeClassName( (is_delete) ? 'hover-delete' : 'hover' );
481
+ }
482
+ },
483
+
484
+ toggle_reorder: function(node, anc, id) {
485
+ if( $(node).hasClassName('do-reorder') ) {
486
+ $(node).removeClassName( 'do-reorder' );
487
+ $(anc).removeClassName('reordering');
488
+ $(anc).innerHTML = "reorder children";
489
+ } else {
490
+ $(node).addClassName( 'do-reorder' );
491
+ $(anc).addClassName('reordering');
492
+ $(anc).innerHTML = "finished reordering";
493
+ // Make sure the children are visible...
494
+ ComatoseList.expand_node(id);
495
+ }
496
+ },
497
+
498
+ _write_state: function(items) {
499
+ var cookie = {}; var options = {}; var expiration = new Date();
500
+ cookie[ ComatoseList.state_key ] = items.join(',');
501
+ expiration.setDate(expiration.getDate()+30)
502
+ options['expires'] = expiration;
503
+ Cookie.write( cookie, options );
504
+ },
505
+
506
+ _read_state: function() {
507
+ var state = Cookie.read( ComatoseList.state_key );
508
+ return (state != "" && state != null) ? state.split(',') : [];
509
+ }
510
+ }
511
+
512
+ // Edit Form Functions
513
+ var ComatoseEditForm = {
514
+
515
+ default_data: {},
516
+ last_preview: {},
517
+ last_title_slug: '',
518
+ mode : null,
519
+ liquid_horiz: true,
520
+ width_offset: 325,
521
+
522
+ // Initialize the page...
523
+ init : function(mode) {
524
+ this.mode = mode;
525
+ this.default_data = Form.serialize(document.forms[0]);
526
+ if(mode == 'new') {
527
+ this.last_title_slug = $('page_title').value.toSlug();
528
+ Event.observe('page_title', 'blur', ComatoseEditForm.title_updated_aggressive);
529
+ } else {
530
+ Event.observe('page_title', 'blur', ComatoseEditForm.title_updated);
531
+ }
532
+ $('page_title').focus();
533
+ Hide.these(
534
+ 'preview-area',
535
+ 'slug_row',
536
+ 'parent_row',
537
+ 'keywords_row',
538
+ 'filter_row',
539
+ 'created_row'
540
+ );
541
+ $('page_title').select();
542
+ // Create the horizontal liquidity of the fields
543
+ if(this.liquid_horiz) {
544
+ xOffset = this.width_offset;
545
+ new Layout.LiquidHoriz((xOffset + 50), 'page_title');
546
+ new Layout.LiquidHoriz(xOffset, 'page_slug','page_keywords','page_parent','page_body');
547
+ }
548
+ },
549
+ // For use when updating an existing page...
550
+ title_updated : function() {
551
+ slug = $('page_slug');
552
+ if(slug.value == "") {
553
+ title = $('page_title');
554
+ slug.value = title.value.toSlug();
555
+ }
556
+ },
557
+ // For use when creating a new page...
558
+ title_updated_aggressive : function() {
559
+ slug = $('page_slug');
560
+ title = $('page_title');
561
+ if(slug.value == "" || slug.value == this.last_title ) {
562
+ slug.value = title.value.toSlug();
563
+ }
564
+ this.last_title = slug.value;
565
+ },
566
+ // Todo: Make the meta fields remember their visibility?
567
+ toggle_extra_fields : function(anchor) {
568
+ if(anchor.innerHTML == "More...") {
569
+ Show.these(
570
+ 'slug_row',
571
+ 'keywords_row',
572
+ 'parent_row',
573
+ 'filter_row',
574
+ 'created_row'
575
+ );
576
+ anchor.innerHTML = 'Less...';
577
+ } else {
578
+ Hide.these(
579
+ 'slug_row',
580
+ 'keywords_row',
581
+ 'parent_row',
582
+ 'filter_row',
583
+ 'created_row'
584
+ );
585
+ anchor.innerHTML = 'More...';
586
+ }
587
+ },
588
+ // Uses server to create preview of content...
589
+ preview_content : function(preview_url) {
590
+ $('preview-area').show();
591
+ var params = Form.serialize(document.forms[0]);
592
+ if( params != this.last_preview ) {
593
+ $('preview-panel').innerHTML = "<span style='color:blue;'>Loading Preview...</span>";
594
+ new Ajax.Updater(
595
+ 'preview-panel',
596
+ preview_url,
597
+ { parameters: params }
598
+ );
599
+ }
600
+ this.last_preview = params;
601
+ },
602
+ cancel : function(url) {
603
+ var current_data = Form.serialize(document.forms[0]);
604
+ var data_changed = (this.default_data != current_data)
605
+ if(data_changed) {
606
+ if( confirm('Changes detected. You will lose all the updates you have made if you proceed...') ) {
607
+ location.href = url;
608
+ }
609
+ } else {
610
+ location.href = url;
611
+ }
612
+
613
+ }
614
+ }
615
+
616
+ var Hide = {
617
+ these : function() {
618
+ for (var i = 0; i < arguments.length; i++) {
619
+ try {
620
+ $(arguments[i]).hide();
621
+ } catch (e) {}
622
+ }
623
+ }
624
+ }
625
+
626
+ var Show = {
627
+ these : function() {
628
+ for (var i = 0; i < arguments.length; i++) {
629
+ try {
630
+ $(arguments[i]).show();
631
+ } catch (e) {}
632
+ }
633
+ }
634
+ }
635
+
636
+ // Layout namespace
637
+ var Layout = {};
638
+
639
+ // This class allows dom objects to stretch with the browser
640
+ // (for when a good, cross-browser, CSS approach can't be found)
641
+ Layout.LiquidBase = Class.create();
642
+ // Base class for all Liquid* layouts...
643
+ Object.extend(Layout.LiquidBase.prototype, {
644
+ enabled: true,
645
+ elems: [],
646
+ offset: null,
647
+ // Constructor is (offset, **array_of_elements)
648
+ initialize: function() {
649
+ args = $A(arguments)
650
+ this.offset = args.shift();
651
+ this.elems = args.select( function(elem){ return ($(elem) != null) } );
652
+ if( this.elems.length > 0 ) {
653
+ this.on_resize(); // Initial size
654
+ Event.observe(window, 'resize', this.on_resize.bind(this) );
655
+ Event.observe(window, 'load', this.on_resize.bind(this) );
656
+ }
657
+ },
658
+ resize_in: function(timeout) {
659
+ setTimeout( this.on_resize.bind(this), timeout );
660
+ },
661
+ on_resize: function() {
662
+ // Need to override!
663
+ alert('Override on_resize, please!');
664
+ }
665
+ });
666
+
667
+
668
+ // Liquid vertical layout
669
+ Layout.LiquidVert = Class.create();
670
+ Object.extend(Layout.LiquidVert.prototype, Object.extend(Layout.LiquidBase.prototype, {
671
+ on_resize: function() {
672
+ if( this.offset != null && this.enabled ) {
673
+ var new_height = ((window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight) - this.offset) +"px";
674
+ this.elems.each(function(e){ $(e).style.height = new_height; })
675
+ }
676
+ }
677
+ }) );
678
+
679
+
680
+ // Liquid horizontal layout
681
+ Layout.LiquidHoriz = Class.create();
682
+ Object.extend(Layout.LiquidHoriz.prototype, Object.extend(Layout.LiquidBase.prototype, {
683
+ on_resize: function() {
684
+ if( this.offset != null && this.enabled ) {
685
+ var new_width = ((window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth) - this.offset) +"px";
686
+ this.elems.each( function(e){ $(e).style.width = new_width; })
687
+ }
688
+ }
689
+ }) );
690
+
691
+ // String Extensions... Yes, these are from Radiant! ;-)
692
+ Object.extend(String.prototype, {
693
+ upcase: function() {
694
+ return this.toUpperCase();
695
+ },
696
+ downcase: function() {
697
+ return this.toLowerCase();
698
+ },
699
+ strip: function() {
700
+ return this.replace(/^\s+/, '').replace(/\s+$/, '');
701
+ },
702
+ toInteger: function() {
703
+ return parseInt(this);
704
+ },
705
+ toSlug: function() {
706
+ // M@: Modified from Radiant's version, removes multple --'s next to each other
707
+ // This is the same RegExp as the one on the page model...
708
+ return this.strip().downcase().replace(/[^-a-z0-9~\s\.:;+=_]/g, '').replace(/[\s\.:;=_+]+/g, '-').replace(/[\-]{2,}/g, '-');
709
+ }
710
+ });
711
+
712
+ // Run a spinner when an AJAX request in running...
713
+ var ComatoseAJAXSpinner = {
714
+ busy : function () {
715
+ if($('spinner') && Ajax.activeRequestCount > 0) {
716
+ Effect.Appear('spinner',{duration:0.5,queue:'end'});
717
+ }
718
+ },
719
+
720
+ notBusy: function() {
721
+ if($('spinner') && Ajax.activeRequestCount == 0) {
722
+ Effect.Fade('spinner',{duration:0.5,queue:'end'});
723
+ }
724
+ }
725
+ }
726
+ // Register it with Prototype...
727
+ Ajax.Responders.register({
728
+ onCreate: ComatoseAJAXSpinner.busy,
729
+ onComplete: ComatoseAJAXSpinner.notBusy
730
+ });
731
+
732
+
733
+ if(!window.Cookie)
734
+ (function (){
735
+ // From Mephisto!
736
+ window.Cookie = {
737
+ version: '0.7',
738
+ cookies: {},
739
+ _each: function(iterator) {
740
+ $H(this.cookies).each(iterator);
741
+ },
742
+
743
+ getAll: function() {
744
+ this.cookies = {};
745
+ $A(document.cookie.split('; ')).each(function(cookie) {
746
+ var seperator = cookie.indexOf('=');
747
+ this.cookies[cookie.substring(0, seperator)] =
748
+ unescape(cookie.substring(seperator + 1, cookie.length));
749
+ }.bind(this));
750
+ return this.cookies;
751
+ },
752
+
753
+ read: function() {
754
+ var cookies = $A(arguments), results = [];
755
+ this.getAll();
756
+ cookies.each(function(name) {
757
+ if (this.cookies[name]) results.push(this.cookies[name]);
758
+ else results.push(null);
759
+ }.bind(this));
760
+ return results.length > 1 ? results : results[0];
761
+ },
762
+
763
+ write: function(cookies, options) {
764
+ if (cookies.constructor == Object && cookies.name) cookies = [cookies];
765
+ if (cookies.constructor == Array) {
766
+ $A(cookies).each(function(cookie) {
767
+ this._write(cookie.name, cookie.value, cookie.expires,
768
+ cookie.path, cookie.domain);
769
+ }.bind(this));
770
+ } else {
771
+ options = options || {expires: false, path: '', domain: ''};
772
+ for (name in cookies){
773
+ this._write(name, cookies[name],
774
+ options.expires, options.path, options.domain);
775
+ }
776
+ }
777
+ },
778
+
779
+ _write: function(name, value, expires, path, domain) {
780
+ if (name.indexOf('=') != -1) return;
781
+ var cookieString = name + '=' + escape(value);
782
+ if (expires) cookieString += '; expires=' + expires.toGMTString();
783
+ if (path) cookieString += '; path=' + path;
784
+ if (domain) cookieString += '; domain=' + domain;
785
+ document.cookie = cookieString;
786
+ },
787
+
788
+ erase: function(cookies) {
789
+ var cookiesToErase = {};
790
+ $A(arguments).each(function(cookie) {
791
+ cookiesToErase[cookie] = '';
792
+ });
793
+
794
+ this.write(cookiesToErase, {expires: (new Date((new Date()).getTime() - 1e11))});
795
+ this.getAll();
796
+ },
797
+
798
+ eraseAll: function() {
799
+ this.erase.apply(this, $H(this.getAll()).keys());
800
+ }
801
+ };
802
+
803
+ Object.extend(Cookie, {
804
+ get: Cookie.read,
805
+ set: Cookie.write,
806
+
807
+ add: Cookie.read,
808
+ remove: Cookie.erase,
809
+ removeAll: Cookie.eraseAll,
810
+
811
+ wipe: Cookie.erase,
812
+ wipeAll: Cookie.eraseAll,
813
+ destroy: Cookie.erase,
814
+ destroyAll: Cookie.eraseAll
815
+ });
816
+ })();
817
+
818
+ </script>
819
+ </head>
820
+ <body>
821
+ <div id="page-container">
822
+ <div id="header">
823
+ <h1><%= link_to Comatose.config.admin_title, :controller=>controller.controller_name, :action=>'index' %></h1>
824
+ <div id="flash">
825
+ <span id="flash-content"><%= flash[:notice] %></span>
826
+ </div>
827
+ <h5><%= Comatose.config.admin_sub_title %></h5>
828
+ </div>
829
+ <div id="content">
830
+ <%= yield %>
831
+ </div>
832
+ <div id="footer">
833
+ Powered by <a href="http://comatose.rubyforge.org" target="_new_window">Comatose <%= Comatose::VERSION_STRING %></a>, created by <a href="http://www.mattmccray.com" target="_new_window">M@ McCray</a>.
834
+ </div>
835
+ </div>
836
+ </body>
837
+ </html>