修訂 | 133 (tree) |
---|---|
時間 | 2008-11-02 20:24:19 |
作者 | junkikuchi |
updated.
@@ -40,6 +40,24 @@ | ||
40 | 40 | :row => {'name' => 'widget-json'}, |
41 | 41 | :relation => {'model' => 'admin_widget:view.widget'}, |
42 | 42 | }, |
43 | + { | |
44 | + :name => 'widget', | |
45 | + :class => 'View', | |
46 | + :row => {'name' => 'widget'}, | |
47 | + :relation => {'model' => 'admin_widget:widget'}, | |
48 | + }, | |
49 | + { | |
50 | + :name => 'widget.property-json', | |
51 | + :class => 'View', | |
52 | + :row => {'name' => 'widget-property-json'}, | |
53 | + :relation => {'model' => 'admin_widget:widget.property-json'}, | |
54 | + }, | |
55 | + { | |
56 | + :name => 'widget.css-json', | |
57 | + :class => 'View', | |
58 | + :row => {'name' => 'widget-css-json'}, | |
59 | + :relation => {'model' => 'admin_widget:widget.css-json'}, | |
60 | + }, | |
43 | 61 | ], |
44 | 62 | |
45 | 63 | 'admin_widget' => [ |
@@ -47,6 +65,7 @@ | ||
47 | 65 | :name => 'html', |
48 | 66 | :class => 'Widget::HTML', |
49 | 67 | :relation => {'view' => 'admin_view:admin'}, |
68 | + :property => {:html_attr_class => 'yui-skin-sam'} | |
50 | 69 | }, |
51 | 70 | { |
52 | 71 | :name => 'html.google_ajax_loader', |
@@ -151,5 +170,22 @@ | ||
151 | 170 | :class => 'Widget::Widget::JSON', |
152 | 171 | :relation => {'view' => 'admin_view:view.widget.json'}, |
153 | 172 | }, |
173 | + | |
174 | + { | |
175 | + :name => 'widget', | |
176 | + :class => 'Widget::Widget', | |
177 | + :relation => {'view' => 'admin_view:widget'}, | |
178 | + :property => {:model => 'admin_widget'}, | |
179 | + }, | |
180 | + { | |
181 | + :name => 'widget.property-json', | |
182 | + :class => 'Widget::Widget::Property::JSON', | |
183 | + :relation => {'view' => 'admin_view:widget.property-json'}, | |
184 | + }, | |
185 | + { | |
186 | + :name => 'widget.css-json', | |
187 | + :class => 'Widget::Widget::CSS::JSON', | |
188 | + :relation => {'view' => 'admin_view:widget.css-json'}, | |
189 | + }, | |
154 | 190 | ], |
155 | 191 | } |
@@ -37,12 +37,14 @@ | ||
37 | 37 | if name == 'admin' |
38 | 38 | service = models['admin_service'] |
39 | 39 | view = models['admin_view'] |
40 | + widget = models['admin_widget'] | |
40 | 41 | else |
41 | 42 | service = models['user_service'] |
42 | 43 | view = models['user_view'] |
44 | + widget = models['user_widget'] | |
43 | 45 | end |
44 | 46 | |
45 | - service.dispatch(name, view, models, params, request, response) | |
47 | + service.dispatch(name, view, widget, models, params, request, response) | |
46 | 48 | end |
47 | 49 | |
48 | 50 | def server(name) |
@@ -8,6 +8,12 @@ | ||
8 | 8 | }, |
9 | 9 | widget: { |
10 | 10 | url: '/admin/widget-json/' |
11 | + }, | |
12 | + property: { | |
13 | + url: '/admin/widget-property-json/' | |
14 | + }, | |
15 | + css: { | |
16 | + url: '/admin/widget-css-json/' | |
11 | 17 | } |
12 | 18 | } |
13 | 19 | } |
@@ -15,7 +21,15 @@ | ||
15 | 21 | google.load('jquery', '1.2'); |
16 | 22 | google.setOnLoadCallback(function() { |
17 | 23 | (new YAHOO.util.YUILoader({ |
18 | - require: ['layout', 'resize', 'treeview', 'tabview'], | |
24 | + require: [ | |
25 | + 'layout', | |
26 | + 'resize', | |
27 | + 'treeview', | |
28 | + 'datatable', | |
29 | + 'datasource', | |
30 | + 'json', | |
31 | + 'connection' | |
32 | + ], | |
19 | 33 | onSuccess: function() { |
20 | 34 | var Dom = YAHOO.util.Dom; |
21 | 35 | var Event = YAHOO.util.Event; |
@@ -68,7 +82,8 @@ | ||
68 | 82 | body: 'right', |
69 | 83 | width: 200, |
70 | 84 | resize: true, |
71 | - scroll: true | |
85 | + scroll: true, | |
86 | + gutter: '0 0 0 5px' | |
72 | 87 | }, |
73 | 88 | bottom: { |
74 | 89 | position: 'bottom', |
@@ -80,7 +95,8 @@ | ||
80 | 95 | body: 'left', |
81 | 96 | width: 200, |
82 | 97 | resize: true, |
83 | - scroll: true | |
98 | + scroll: true, | |
99 | + gutter: '0 5px 0 0' | |
84 | 100 | }, |
85 | 101 | center: { |
86 | 102 | position: 'center', |
@@ -116,7 +132,6 @@ | ||
116 | 132 | this.app = app; |
117 | 133 | this.config = config; |
118 | 134 | |
119 | - /* View Tree */ | |
120 | 135 | $('#left').append('<h2>View</h2>'); |
121 | 136 | $('#left').append('<div id="view"><div id="view-tree"></div></div>'); |
122 | 137 | this.view_tree = new App.View.ViewTree( |
@@ -125,7 +140,7 @@ | ||
125 | 140 | config.view.url |
126 | 141 | ); |
127 | 142 | |
128 | - // to make view tree resizable | |
143 | + /* | |
129 | 144 | new YAHOO.util.Resize( |
130 | 145 | 'view', |
131 | 146 | { |
@@ -136,8 +151,8 @@ | ||
136 | 151 | ); |
137 | 152 | $('#view').css('overflow', 'auto'); |
138 | 153 | $('#view .yui-resize-handle-b').css('background-color', '#c3d9ff'); |
154 | + */ | |
139 | 155 | |
140 | - /* Widget Tree */ | |
141 | 156 | $('#left').append('<h2>Widget</h2>'); |
142 | 157 | $('#left').append('<div id="widget-tree"></div>'); |
143 | 158 | this.widget_tree = new App.View.WidgetTree( |
@@ -146,13 +161,21 @@ | ||
146 | 161 | config.widget.url |
147 | 162 | ); |
148 | 163 | |
149 | - /* Property Table */ | |
150 | 164 | $('#right').append('<h2>Property</h2>'); |
151 | 165 | $('#right').append('<div id="property"></div>'); |
166 | + this.property = new App.View.Property( | |
167 | + this, | |
168 | + 'property', | |
169 | + config.property.url | |
170 | + ); | |
152 | 171 | |
153 | - /* Style Table */ | |
154 | - $('#right').append('<h2>Style</h2>'); | |
155 | - $('#right').append('<div id="style"></div>'); | |
172 | + $('#right').append('<h2>CSS</h2>'); | |
173 | + $('#right').append('<div id="css"></div>'); | |
174 | + this.css = new App.View.CSS( | |
175 | + this, | |
176 | + 'css', | |
177 | + config.css.url | |
178 | + ); | |
156 | 179 | }, |
157 | 180 | |
158 | 181 | render: function() { |
@@ -165,7 +188,8 @@ | ||
165 | 188 | }, |
166 | 189 | |
167 | 190 | on_click_widget: function(id) { |
168 | - alert(id); | |
191 | + this.property.update(id); | |
192 | + this.css.update(id); | |
169 | 193 | } |
170 | 194 | } |
171 | 195 |
@@ -246,4 +270,133 @@ | ||
246 | 270 | |
247 | 271 | render: function() {} |
248 | 272 | } |
273 | + | |
274 | + /* | |
275 | + * App.View.Property | |
276 | + */ | |
277 | + App.View.Property = function() { | |
278 | + this.init.apply(this, arguments); | |
279 | + } | |
280 | + | |
281 | + App.View.Property.prototype = { | |
282 | + init: function(client, tag_id, url) { | |
283 | + this.client = client; | |
284 | + this.tag_id = tag_id; | |
285 | + this.url = url; | |
286 | + }, | |
287 | + | |
288 | + update: function(widget_id) { | |
289 | + src = new YAHOO.util.XHRDataSource(this.url + widget_id); | |
290 | + src.responseType = YAHOO.util.DataSource.TYPE_JSON; | |
291 | + src.responseSchema = { | |
292 | + resultsList: 'results', | |
293 | + fields: ['name', 'value'] | |
294 | + } | |
295 | + | |
296 | + YAHOO.widget.DataTable._bStylesheetFallback = !!YAHOO.env.ua.ie; | |
297 | + table = new YAHOO.widget.DataTable( | |
298 | + this.tag_id, | |
299 | + [ | |
300 | + { | |
301 | + key: 'name' | |
302 | + }, | |
303 | + { | |
304 | + key: 'value', | |
305 | + editor: new YAHOO.widget.TextboxCellEditor({disableBtns: true}) | |
306 | + } | |
307 | + ], | |
308 | + src | |
309 | + ); | |
310 | + table.subscribe('cellMouseoverEvent', function(args) { | |
311 | + var cell = args.target; | |
312 | + if(YAHOO.util.Dom.hasClass(cell, 'yui-dt-editable')) { | |
313 | + this.highlightCell(cell); | |
314 | + } | |
315 | + }); | |
316 | + table.subscribe('cellMouseoutEvent', table.onEventUnhighlightCell); | |
317 | + table.subscribe('cellClickEvent', table.onEventShowCellEditor); | |
318 | + }, | |
319 | + | |
320 | + render: function() {} | |
321 | + } | |
322 | + | |
323 | + /* | |
324 | + * App.View.CSS | |
325 | + */ | |
326 | + App.View.CSS = function() { | |
327 | + this.init.apply(this, arguments); | |
328 | + } | |
329 | + | |
330 | + App.View.CSS.prototype = { | |
331 | + init: function(client, tag_id, url) { | |
332 | + this.client = client; | |
333 | + this.tag_id = tag_id; | |
334 | + this.url = url; | |
335 | + }, | |
336 | + | |
337 | + update: function(widget_id) { | |
338 | + var url = this.url + widget_id; | |
339 | + | |
340 | + src = new YAHOO.util.XHRDataSource(url); | |
341 | + src.responseType = YAHOO.util.DataSource.TYPE_JSON; | |
342 | + src.responseSchema = { | |
343 | + resultsList: 'results', | |
344 | + fields: ['id', 'name', 'value'] | |
345 | + } | |
346 | + | |
347 | + YAHOO.widget.DataTable._bStylesheetFallback = !!YAHOO.env.ua.ie; | |
348 | + table = new YAHOO.widget.DataTable( | |
349 | + this.tag_id, | |
350 | + [ | |
351 | + { | |
352 | + key: 'id' | |
353 | + }, | |
354 | + { | |
355 | + key: 'name' | |
356 | + }, | |
357 | + { | |
358 | + key: 'value', | |
359 | + editor: new YAHOO.widget.TextboxCellEditor({ | |
360 | + asyncSubmitter: function(callback, new_value) { | |
361 | + var old_value = this.value; | |
362 | + var id = this.getRecord().getData().id | |
363 | + | |
364 | + YAHOO.util.Connect.asyncRequest( | |
365 | + 'post', | |
366 | + url, | |
367 | + { | |
368 | + success: function(o) { | |
369 | + var r = YAHOO.lang.JSON.parse(o.responseText); | |
370 | + if(o.status == 200) { | |
371 | + callback(true, new_value); | |
372 | + } else { | |
373 | + callback(); | |
374 | + } | |
375 | + }, | |
376 | + failure: function(o) { | |
377 | + alert(o.statusText); | |
378 | + callback(); | |
379 | + }, | |
380 | + scope: this | |
381 | + }, | |
382 | + escape(id) + '=' + escape(new_value) | |
383 | + ); | |
384 | + } | |
385 | + }) | |
386 | + } | |
387 | + ], | |
388 | + src | |
389 | + ); | |
390 | + table.subscribe('cellMouseoverEvent', function(args) { | |
391 | + var cell = args.target; | |
392 | + if(YAHOO.util.Dom.hasClass(cell, 'yui-dt-editable')) { | |
393 | + this.highlightCell(cell); | |
394 | + } | |
395 | + }); | |
396 | + table.subscribe('cellMouseoutEvent', table.onEventUnhighlightCell); | |
397 | + table.subscribe('cellClickEvent', table.onEventShowCellEditor); | |
398 | + }, | |
399 | + | |
400 | + render: function() {} | |
401 | + } | |
249 | 402 | })(); |
@@ -51,12 +51,12 @@ | ||
51 | 51 | build_uri(view, nil, query) |
52 | 52 | end |
53 | 53 | |
54 | - def dispatch(models, view, params, request, response) | |
54 | + def dispatch(models, view, widget, params, request, response) | |
55 | 55 | @models = models |
56 | 56 | @request = request |
57 | 57 | @response = response |
58 | 58 | @view = view.fetch_by_name(params.shift) || default_view |
59 | - @view.render(self, params) | |
59 | + @view.render(self, widget, params) | |
60 | 60 | rescue Service::Error => err |
61 | 61 | err.exec(self) |
62 | 62 | end |
@@ -1,198 +0,0 @@ | ||
1 | -# | |
2 | -# Copyright (C) 2008 Jun Kikuchi <kikuchi@bonnou.com> | |
3 | -# | |
4 | - | |
5 | -Tenarai::ClassLoader.load_class('Widget::Widget') | |
6 | - | |
7 | -class Widget | |
8 | - class Widget | |
9 | - class CSS < ::Widget | |
10 | - extend Tenarai::ClassLoader | |
11 | - | |
12 | - css | |
13 | - | |
14 | - CSS = Tenarai::Container.new | |
15 | - CSS << Tenarai::Container::Value.new( | |
16 | - 'font', | |
17 | - [ | |
18 | - 'font-family', | |
19 | - 'font-weight', | |
20 | - 'font-size', | |
21 | - 'font-style', | |
22 | - 'font-variant', | |
23 | - ] | |
24 | - ) | |
25 | - CSS << Tenarai::Container::Value.new( | |
26 | - 'text', | |
27 | - [ | |
28 | - 'color', | |
29 | - 'text-indent', | |
30 | - 'text-align', | |
31 | - 'line-height', | |
32 | - 'vertical-align', | |
33 | - 'word-spacing', | |
34 | - 'letter-spacing', | |
35 | - 'text-transform', | |
36 | - 'text-decoration', | |
37 | - 'white-space', | |
38 | - ] | |
39 | - ) | |
40 | - CSS << Tenarai::Container::Value.new( | |
41 | - 'background', | |
42 | - [ | |
43 | - 'background-color', | |
44 | - 'background-image', | |
45 | - 'background-repeat', | |
46 | - 'background-position', | |
47 | - 'background-attachment', | |
48 | - ] | |
49 | - ) | |
50 | - CSS << Tenarai::Container::Value.new( | |
51 | - 'margin', | |
52 | - [ | |
53 | - 'margin', | |
54 | - 'margin-top', | |
55 | - 'margin-right', | |
56 | - 'margin-bottom', | |
57 | - 'margin-left', | |
58 | - ] | |
59 | - ) | |
60 | - CSS << Tenarai::Container::Value.new( | |
61 | - 'border', | |
62 | - [ | |
63 | - 'border', | |
64 | - 'border-top', | |
65 | - 'border-right', | |
66 | - 'border-bottom', | |
67 | - 'border-left', | |
68 | - ] | |
69 | - ) | |
70 | - CSS << Tenarai::Container::Value.new( | |
71 | - 'padding', | |
72 | - [ | |
73 | - 'padding', | |
74 | - 'padding-top', | |
75 | - 'padding-right', | |
76 | - 'padding-bottom', | |
77 | - 'padding-left', | |
78 | - ] | |
79 | - ) | |
80 | - CSS << Tenarai::Container::Value.new( | |
81 | - 'size', | |
82 | - [ | |
83 | - 'width', | |
84 | - 'height', | |
85 | - 'min-width', | |
86 | - 'min-height', | |
87 | - 'max-width', | |
88 | - 'max-height', | |
89 | - ] | |
90 | - ) | |
91 | - CSS << Tenarai::Container::Value.new( | |
92 | - 'layout', | |
93 | - [ | |
94 | - 'float', | |
95 | - 'clear', | |
96 | - 'position', | |
97 | - 'top', | |
98 | - 'right', | |
99 | - 'bottom', | |
100 | - 'left', | |
101 | - 'overflow', | |
102 | - 'clip', | |
103 | - 'visibility', | |
104 | - 'z-index', | |
105 | - 'display', | |
106 | - ] | |
107 | - ) | |
108 | - CSS << Tenarai::Container::Value.new( | |
109 | - 'list', | |
110 | - [ | |
111 | - 'list-style-type', | |
112 | - ] | |
113 | - ) | |
114 | - CSS << Tenarai::Container::Value.new( | |
115 | - 'ui', | |
116 | - [ | |
117 | - 'cursor', | |
118 | - ] | |
119 | - ) | |
120 | - | |
121 | - def render_css_form(xml, widget) | |
122 | - widget.class.meta[:css].each do |val| | |
123 | - xml.tag('h3').text( | |
124 | - if val.name.to_s.empty? then 'CSS' else val.name end | |
125 | - ) | |
126 | - self.class::CSS.each do |css| | |
127 | - xml.tag( | |
128 | - 'form', | |
129 | - 'method' => 'post', | |
130 | - 'action' => uri(@builder.view, resource.content.id) do |query| | |
131 | - query[form_id('update')] = nil | |
132 | - end | |
133 | - ) do |form| | |
134 | - form.tag('h4').text(css.name) | |
135 | - form.tag('dl') do |dl| | |
136 | - css.value.each do |selector| | |
137 | - _form_id = [val.name, css.name, selector].join("_") | |
138 | - _id = form_id(_form_id) | |
139 | - value = if widget.css.key?(_form_id) then | |
140 | - widget.css[_form_id].value | |
141 | - else | |
142 | - '' | |
143 | - end | |
144 | - dl.tag('dt').tag('label', 'for' => _id).text(selector) | |
145 | - dl.tag('dd').tag( | |
146 | - 'input', | |
147 | - 'type' => 'text', | |
148 | - 'id' => _id, | |
149 | - 'name' => _id, | |
150 | - 'value' => value | |
151 | - ) | |
152 | - end | |
153 | - dl.tag('dt').tag('br') | |
154 | - dl.tag('dd').tag( | |
155 | - 'input', | |
156 | - 'type' => 'submit', | |
157 | - 'value' => 'update' | |
158 | - ) | |
159 | - end | |
160 | - end | |
161 | - end | |
162 | - end | |
163 | - end | |
164 | - private :render_css_form | |
165 | - | |
166 | - def render_html(head, body) | |
167 | - body.tag('div', html_attr) do |div| | |
168 | - render_css_form(div, resource.content) | |
169 | - div.text('') if div.empty? | |
170 | - end | |
171 | - end | |
172 | - | |
173 | - def post(query=Tenarai::CGI::Query.new) | |
174 | - css = resource.content.css | |
175 | - query.inject({}) do |ret, (key, val)| | |
176 | - s, g, a = key.split('_') | |
177 | - ret[s] ||= {} | |
178 | - ret[s][g] ||= {} | |
179 | - ret[s][g][a] = [key, val] | |
180 | - ret | |
181 | - end.each do |skey, sval| | |
182 | - sval.each do |gkey, gval| | |
183 | - self.class::CSS[gkey].value.each do |s| | |
184 | - key, val = gval[s] | |
185 | - if val.empty? | |
186 | - css.delete(key) | |
187 | - else | |
188 | - css[key] = val | |
189 | - end | |
190 | - end | |
191 | - end | |
192 | - end | |
193 | - | |
194 | - resource.content.save | |
195 | - end | |
196 | - end | |
197 | - end | |
198 | -end |
@@ -1,67 +0,0 @@ | ||
1 | -# | |
2 | -# Copyright (C) 2008 Jun Kikuchi <kikuchi@bonnou.com> | |
3 | -# | |
4 | - | |
5 | -Tenarai::ClassLoader.load_class('Widget::Widget') | |
6 | - | |
7 | -class Widget | |
8 | - class Widget | |
9 | - class Property < ::Widget | |
10 | - extend Tenarai::ClassLoader | |
11 | - | |
12 | - css | |
13 | - | |
14 | - def render_property_form(xml, widget) | |
15 | - xml.tag('h3').text('Property') | |
16 | - xml.tag( | |
17 | - 'form', | |
18 | - 'method' => 'post', | |
19 | - 'action' => uri( | |
20 | - @builder.view, | |
21 | - resource.content.id | |
22 | - ) do |query| | |
23 | - query[form_id('update')] = nil | |
24 | - end | |
25 | - ) do |form| | |
26 | - form.tag('dl') do |dl| | |
27 | - widget.property.each do |key, val| | |
28 | - _id = form_id(key) | |
29 | - dl.tag('dt').tag('label', 'for' => _id).text(key) | |
30 | - dl.tag('dd').tag( | |
31 | - 'input', | |
32 | - 'type' => 'text', | |
33 | - 'id' => _id, | |
34 | - 'name' => _id, | |
35 | - 'value' => val | |
36 | - ) | |
37 | - end | |
38 | - dl.tag('dt').tag('br') | |
39 | - dl.tag('dd').tag( | |
40 | - 'input', | |
41 | - 'type' => 'submit', | |
42 | - 'value' => 'update' | |
43 | - ) | |
44 | - end | |
45 | - end | |
46 | - end | |
47 | - private :render_property_form | |
48 | - | |
49 | - def render_html(head, body) | |
50 | - body.tag('div', html_attr) do |div| | |
51 | - render_property_form(div, resource.content) | |
52 | - end | |
53 | - end | |
54 | - | |
55 | - def post(query=Tenarai::CGI::Query.new) | |
56 | - query.each do |key, val| | |
57 | - resource.content.property[key.to_sym] = if val.empty? | |
58 | - nil | |
59 | - else | |
60 | - val | |
61 | - end | |
62 | - end | |
63 | - resource.content.save | |
64 | - end | |
65 | - end | |
66 | - end | |
67 | -end |
@@ -0,0 +1,69 @@ | ||
1 | +# | |
2 | +# Copyright (C) 2008 Jun Kikuchi <kikuchi@bonnou.com> | |
3 | +# | |
4 | + | |
5 | +Tenarai::ClassLoader.load_class('Widget::Widget') | |
6 | + | |
7 | +class Widget | |
8 | + class Widget | |
9 | + class Property | |
10 | + class Form < ::Widget | |
11 | + extend Tenarai::ClassLoader | |
12 | + | |
13 | + css | |
14 | + | |
15 | + def render_property_form(xml, widget) | |
16 | + xml.tag('h3').text('Property') | |
17 | + xml.tag( | |
18 | + 'form', | |
19 | + 'method' => 'post', | |
20 | + 'action' => uri( | |
21 | + @builder.view, | |
22 | + resource.content.id | |
23 | + ) do |query| | |
24 | + query[form_id('update')] = nil | |
25 | + end | |
26 | + ) do |form| | |
27 | + form.tag('dl') do |dl| | |
28 | + widget.property.each do |key, val| | |
29 | + _id = form_id(key) | |
30 | + dl.tag('dt').tag('label', 'for' => _id).text(key) | |
31 | + dl.tag('dd').tag( | |
32 | + 'input', | |
33 | + 'type' => 'text', | |
34 | + 'id' => _id, | |
35 | + 'name' => _id, | |
36 | + 'value' => val | |
37 | + ) | |
38 | + end | |
39 | + dl.tag('dt').tag('br') | |
40 | + dl.tag('dd').tag( | |
41 | + 'input', | |
42 | + 'type' => 'submit', | |
43 | + 'value' => 'update' | |
44 | + ) | |
45 | + end | |
46 | + end | |
47 | + end | |
48 | + private :render_property_form | |
49 | + | |
50 | + def render_html(head, body) | |
51 | + body.tag('div', html_attr) do |div| | |
52 | + render_property_form(div, resource.content) | |
53 | + end | |
54 | + end | |
55 | + | |
56 | + def post(query=Tenarai::CGI::Query.new) | |
57 | + query.each do |key, val| | |
58 | + resource.content.property[key.to_sym] = if val.empty? | |
59 | + nil | |
60 | + else | |
61 | + val | |
62 | + end | |
63 | + end | |
64 | + resource.content.save | |
65 | + end | |
66 | + end | |
67 | + end | |
68 | + end | |
69 | +end |
@@ -0,0 +1,36 @@ | ||
1 | +# | |
2 | +# Copyright (C) 2008 Jun Kikuchi <kikuchi@bonnou.com> | |
3 | +# | |
4 | + | |
5 | +Tenarai::ClassLoader.load_class('Widget::Widget') | |
6 | + | |
7 | +require 'simple-json' | |
8 | + | |
9 | +class Widget | |
10 | + class Widget | |
11 | + class Property | |
12 | + class JSON < ::Widget | |
13 | + extend Tenarai::ClassLoader | |
14 | + | |
15 | + model 'Widget::Widget' | |
16 | + | |
17 | + def render | |
18 | + properties = [] | |
19 | + | |
20 | + model.content.property.sort do |(ak, av), (bk, bv)| | |
21 | + ak.to_s <=> bk.to_s | |
22 | + end.each do |key, val| | |
23 | + properties << { | |
24 | + 'name' => key, | |
25 | + 'value' => val | |
26 | + } | |
27 | + end | |
28 | + | |
29 | + @service.response.body << JsonBuilder.new.build({ | |
30 | + 'results' => properties | |
31 | + }) | |
32 | + end | |
33 | + end | |
34 | + end | |
35 | + end | |
36 | +end |
@@ -0,0 +1,94 @@ | ||
1 | +# | |
2 | +# Copyright (C) 2008 Jun Kikuchi <kikuchi@bonnou.com> | |
3 | +# | |
4 | + | |
5 | +Tenarai::ClassLoader.load_class('Widget::Widget') | |
6 | + | |
7 | +class Widget | |
8 | + class Widget | |
9 | + class CSS | |
10 | + class Form < ::Widget | |
11 | + extend Tenarai::ClassLoader | |
12 | + | |
13 | + css | |
14 | + | |
15 | + | |
16 | + def render_css_form(xml, widget) | |
17 | + widget.class.meta[:css].each do |val| | |
18 | + xml.tag('h3').text( | |
19 | + if val.name.to_s.empty? then 'CSS' else val.name end | |
20 | + ) | |
21 | + self.class::CSS.each do |css| | |
22 | + xml.tag( | |
23 | + 'form', | |
24 | + 'method' => 'post', | |
25 | + 'action' => uri(@builder.view, resource.content.id) do |query| | |
26 | + query[form_id('update')] = nil | |
27 | + end | |
28 | + ) do |form| | |
29 | + form.tag('h4').text(css.name) | |
30 | + form.tag('dl') do |dl| | |
31 | + css.value.each do |selector| | |
32 | + _form_id = [val.name, css.name, selector].join("_") | |
33 | + _id = form_id(_form_id) | |
34 | + value = if widget.css.key?(_form_id) then | |
35 | + widget.css[_form_id].value | |
36 | + else | |
37 | + '' | |
38 | + end | |
39 | + dl.tag('dt').tag('label', 'for' => _id).text(selector) | |
40 | + dl.tag('dd').tag( | |
41 | + 'input', | |
42 | + 'type' => 'text', | |
43 | + 'id' => _id, | |
44 | + 'name' => _id, | |
45 | + 'value' => value | |
46 | + ) | |
47 | + end | |
48 | + dl.tag('dt').tag('br') | |
49 | + dl.tag('dd').tag( | |
50 | + 'input', | |
51 | + 'type' => 'submit', | |
52 | + 'value' => 'update' | |
53 | + ) | |
54 | + end | |
55 | + end | |
56 | + end | |
57 | + end | |
58 | + end | |
59 | + private :render_css_form | |
60 | + | |
61 | + def render_html(head, body) | |
62 | + body.tag('div', html_attr) do |div| | |
63 | + render_css_form(div, resource.content) | |
64 | + div.text('') if div.empty? | |
65 | + end | |
66 | + end | |
67 | + | |
68 | + def post(query=Tenarai::CGI::Query.new) | |
69 | + css = resource.content.css | |
70 | + query.inject({}) do |ret, (key, val)| | |
71 | + s, g, a = key.split('_') | |
72 | + ret[s] ||= {} | |
73 | + ret[s][g] ||= {} | |
74 | + ret[s][g][a] = [key, val] | |
75 | + ret | |
76 | + end.each do |skey, sval| | |
77 | + sval.each do |gkey, gval| | |
78 | + self.class::CSS[gkey].value.each do |s| | |
79 | + key, val = gval[s] | |
80 | + if val.empty? | |
81 | + css.delete(key) | |
82 | + else | |
83 | + css[key] = val | |
84 | + end | |
85 | + end | |
86 | + end | |
87 | + end | |
88 | + | |
89 | + resource.content.save | |
90 | + end | |
91 | + end | |
92 | + end | |
93 | + end | |
94 | +end |
@@ -0,0 +1,79 @@ | ||
1 | +# | |
2 | +# Copyright (C) 2008 Jun Kikuchi <kikuchi@bonnou.com> | |
3 | +# | |
4 | + | |
5 | +Tenarai::ClassLoader.load_class('Widget::Widget::CSS') | |
6 | + | |
7 | +require 'simple-json' | |
8 | + | |
9 | +class Widget | |
10 | + class Widget | |
11 | + class CSS | |
12 | + class JSON < ::Widget | |
13 | + extend Tenarai::ClassLoader | |
14 | + | |
15 | + model 'Widget::Widget' | |
16 | + | |
17 | + def render | |
18 | + properties = [] | |
19 | + | |
20 | + model.content.class.meta[:css].each do |val| | |
21 | + Widget::Widget::CSS::CSS.each do |css| | |
22 | + css.value.each do |selector| | |
23 | + _form_id = [val.name, css.name, selector].join("_") | |
24 | + _id = form_id(_form_id) | |
25 | + | |
26 | + value = if model.content.css.key?(_form_id) then | |
27 | + model.content.css[_form_id].value | |
28 | + else | |
29 | + '' | |
30 | + end | |
31 | + | |
32 | + name = if val.name.to_s.empty? | |
33 | + '' | |
34 | + else | |
35 | + val.name + ' ' | |
36 | + end + selector | |
37 | + | |
38 | + properties << { | |
39 | + 'id' => _id, | |
40 | + 'name' => name, | |
41 | + 'value' => value | |
42 | + } | |
43 | + end | |
44 | + end | |
45 | + end | |
46 | + | |
47 | + @service.response['content-type'] = 'text/javascript+json; charset=utf-8' | |
48 | + @service.response.body << JsonBuilder.new.build({ | |
49 | + 'results' => properties | |
50 | + }) | |
51 | + end | |
52 | + | |
53 | + def post(query) | |
54 | + css = model.content.css | |
55 | + query.inject({}) do |ret, (key, val)| | |
56 | + s, g, a = key.split('_') | |
57 | + ret[s] ||= {} | |
58 | + ret[s][g] ||= {} | |
59 | + ret[s][g][a] = [key, val] | |
60 | + ret | |
61 | + end.each do |skey, sval| | |
62 | + sval.each do |gkey, gval| | |
63 | + Widget::Widget::CSS::CSS[gkey].value.each do |s| | |
64 | + key, val = gval[s] | |
65 | + if val.to_s.empty? | |
66 | + css.delete(key) | |
67 | + else | |
68 | + css[key] = val | |
69 | + end | |
70 | + end | |
71 | + end | |
72 | + end | |
73 | + | |
74 | + model.content.save | |
75 | + end | |
76 | + end | |
77 | + end | |
78 | + end | |
79 | +end |
@@ -11,11 +11,11 @@ | ||
11 | 11 | end |
12 | 12 | end |
13 | 13 | |
14 | - def dispatch(name, view, models, params, request, response) | |
14 | + def dispatch(name, view, widget, models, params, request, response) | |
15 | 15 | response.code = 404 |
16 | 16 | query('WHERE name = ?', name) do |service| |
17 | 17 | response.code = 200 |
18 | - service.dispatch(models, view, params, request, response) | |
18 | + service.dispatch(models, view, widget, params, request, response) | |
19 | 19 | end |
20 | 20 | end |
21 | 21 | end |
@@ -8,7 +8,7 @@ | ||
8 | 8 | class Builder |
9 | 9 | extend Tenarai::ClassLoader |
10 | 10 | |
11 | - def parse_query(service) | |
11 | + def parse_query(service, widget) | |
12 | 12 | ws, rs, qs = {}, {}, Tenarai::CGI::Query.new |
13 | 13 | |
14 | 14 | if service.request.method == 'post' |
@@ -19,12 +19,12 @@ | ||
19 | 19 | end.each do |key, val| |
20 | 20 | case key |
21 | 21 | when /id(\d+):(.+)/ |
22 | - if w = service.model['widget'].fetch($1) | |
22 | + if w = widget.fetch($1) | |
23 | 23 | ws[w] ||= Tenarai::CGI::Query.new |
24 | 24 | ws[w][$2] = val |
25 | 25 | end |
26 | 26 | when /id(\d+)/ |
27 | - if w = service.model['widget'].fetch($1) | |
27 | + if w = widget.fetch($1) | |
28 | 28 | rs[w] = val.split(',').map do |val| Tenarai::CGI.decode(val) end |
29 | 29 | end |
30 | 30 | else |
@@ -36,11 +36,9 @@ | ||
36 | 36 | end |
37 | 37 | private :parse_query |
38 | 38 | |
39 | - def build_widget(view, service, param) | |
40 | - ws, rs, qs = parse_query(service) | |
39 | + def build_widget(view, widget, service, param) | |
40 | + ws, rs, qs = parse_query(service, widget) | |
41 | 41 | |
42 | - @preview = true if qs.key?('preview') | |
43 | - | |
44 | 42 | widget = {} |
45 | 43 | view.widget.each do |val| |
46 | 44 | unless val.parent.nil? |
@@ -66,17 +64,13 @@ | ||
66 | 64 | |
67 | 65 | attr_reader :view |
68 | 66 | |
69 | - def initialize(view, service, param) | |
67 | + def initialize(view, widget, service, param) | |
70 | 68 | @view = view |
69 | + @widget = widget | |
71 | 70 | @service = service |
72 | 71 | @param = param |
73 | - @preview = false | |
74 | 72 | end |
75 | 73 | |
76 | - def preview? | |
77 | - @preview | |
78 | - end | |
79 | - | |
80 | 74 | def each(widget, &block) |
81 | 75 | unless empty?(widget) |
82 | 76 | @widget[widget.id].each(&block) |
@@ -92,7 +86,7 @@ | ||
92 | 86 | end |
93 | 87 | |
94 | 88 | def render |
95 | - @widget = build_widget(@view, @service, @param) | |
89 | + @widget = build_widget(@view, @widget, @service, @param) | |
96 | 90 | @widget[nil].render unless @widget[nil].nil? |
97 | 91 | end |
98 | 92 | end |
@@ -86,8 +86,8 @@ | ||
86 | 86 | self |
87 | 87 | end |
88 | 88 | |
89 | - def render(service, params=[]) | |
90 | - Tenarai::ClassLoader['View::Builder'].new(self, service, params).render | |
89 | + def render(service, widget, params=[]) | |
90 | + Tenarai::ClassLoader['View::Builder'].new(self, widget, service, params).render | |
91 | 91 | end |
92 | 92 | |
93 | 93 | alias :_model :model |