]> err.no Git - sope/blob - sope-appserver/WEExtensions/WEDropContainer.m
fix for SoProductResourceManager.m
[sope] / sope-appserver / WEExtensions / WEDropContainer.m
1 /*
2   Copyright (C) 2000-2003 SKYRIX Software AG
3
4   This file is part of OGo
5
6   OGo is free software; you can redistribute it and/or modify it under
7   the terms of the GNU Lesser General Public License as published by the
8   Free Software Foundation; either version 2, or (at your option) any
9   later version.
10
11   OGo is distributed in the hope that it will be useful, but WITHOUT ANY
12   WARRANTY; without even the implied warranty of MERCHANTABILITY or
13   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
14   License for more details.
15
16   You should have received a copy of the GNU Lesser General Public
17   License along with OGo; see the file COPYING.  If not, write to the
18   Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
19   02111-1307, USA.
20 */
21 // $Id$
22
23 #import <NGObjWeb/WODynamicElement.h>
24
25 /*
26   usage:
27
28      DropContainer: WEDropContainer {
29        elementName   = "tr";
30        isAttached    = YES;
31        tags          = ( * );
32        action        = dropAction;
33        droppedObject = droppedObject;
34        
35        swapColor     = YES;
36        activeColor   = "lightblue";
37        bgColor       = bgColor;
38      }
39      
40   renders this:
41
42     <$area BGCOLOR=white 
43         onDragEnter="fnCancelDefault()"
44         onDragOver="fnCancelDefault()"
45         onDrop="fnGetInfo()">
46        $content
47     </$area>
48 */
49
50 @interface WEDropContainer : WODynamicElement
51 {
52   NSDictionary  *dExtraAttrs;
53   WOAssociation *tags;
54   WOAssociation *elementName;
55   WOAssociation *isAttached;  /* bool */
56   WOAssociation *effect;
57   WOAssociation *swapColor; /* swap bgcolor if drag object is over container */
58   WOAssociation *action;
59   WOAssociation *droppedObject;
60   
61   WOElement     *template;
62 }
63 @end
64
65 @interface WEDropScript : WODynamicElement
66 + (void)appendDropScriptToResponse:(WOResponse *)_response
67   inContext:(WOContext *)_ctx;
68 @end
69
70 #include "WEClientCapabilities.h"
71 #import <NGObjWeb/NGObjWeb.h>
72 #import <NGExtensions/NGExtensions.h>
73 #include "common.h"
74
75 @implementation WEDropContainer
76
77 + (int)version {
78   return 0 + [super version];
79 }
80
81 - (id)initWithName:(NSString *)_name
82   associations:(NSDictionary *)_config
83   template:(WOElement *)_subs
84 {
85   if ((self = [super initWithName:_name associations:_config template:_subs])) {
86     self->tags            = WOExtGetProperty(_config, @"tags");
87     self->elementName     = WOExtGetProperty(_config, @"elementName");
88     self->effect          = WOExtGetProperty(_config, @"effect");
89     self->action          = WOExtGetProperty(_config, @"action");
90     self->droppedObject   = WOExtGetProperty(_config, @"droppedObject");
91     self->swapColor       = WOExtGetProperty(_config, @"swapColor");
92     self->isAttached      = WOExtGetProperty(_config, @"isAttached");
93     
94     self->template = RETAIN(_subs);
95   }
96   return self;
97 }
98
99 - (void)dealloc {
100   RELEASE(self->dExtraAttrs);
101   
102   RELEASE(self->swapColor);
103   RELEASE(self->droppedObject);
104   RELEASE(self->action);
105   RELEASE(self->template);
106   RELEASE(self->effect);
107   RELEASE(self->tags);
108   RELEASE(self->elementName);
109   RELEASE(self->isAttached);
110   
111   [super dealloc];
112 }
113
114 - (void)setExtraAttributes:(NSDictionary *)_extras {
115   ASSIGNCOPY(self->dExtraAttrs, _extras);
116 }
117
118 - (void)appendExtraAttributesToResponse:(WOResponse *)_response
119   inContext:(WOContext *)_ctx
120 {
121   if (self->dExtraAttrs) {
122     WOComponent  *sComponent;
123     NSEnumerator *keys;
124     NSString     *key;
125     
126     sComponent = [_ctx component];
127
128     keys = [self->dExtraAttrs keyEnumerator];
129     
130     while ((key = [keys nextObject])) {
131       id value;
132       
133       value = [self->dExtraAttrs objectForKey:key];
134       
135       if (value == nil)
136         continue;
137       
138       //key   = [key lowercaseString];
139       value = [value stringValueInComponent:sComponent];
140
141       [_response appendContentCharacter:' '];
142       [_response appendContentString:key];
143       [_response appendContentString:@"=\""];
144       [_response appendContentHTMLAttributeValue:value];
145       [_response appendContentCharacter:'"'];
146     }
147   }
148 }
149
150 /* responder */
151
152 - (void)takeValuesFromRequest:(WORequest *)_request
153   inContext:(WOContext *)_ctx
154 {
155   [_ctx appendElementIDComponent:@"p"];
156   [self->template takeValuesFromRequest:_request inContext:_ctx];
157   [_ctx deleteLastElementIDComponent];
158 }
159
160 - (id)invokeActionForRequest:(WORequest *)_request
161   inContext:(WOContext *)_ctx
162 {
163   NSString *op;
164   id result;
165   
166   op = [[_ctx currentElementID] stringValue];
167 #if 0
168     NSLog(@"check DROP ACTION %@ ..", op);
169 #endif
170   
171   if ([op isEqualToString:@"p"]) {
172     /* an action inside of the component */
173     [_ctx consumeElementID]; // consume id
174     [_ctx appendElementIDComponent:@"p"];
175     result = [self->template invokeActionForRequest:_request inContext:_ctx];
176     [_ctx deleteLastElementIDComponent];
177   }
178   else if ([op isEqualToString:@"drop"]) {
179     /* an action of *this* component */
180     [_ctx consumeElementID]; // consume id
181     [_ctx appendElementIDComponent:@"drop"];
182
183 #if 0
184     NSLog(@"WILL RUN DROP ACTION ..");
185 #endif
186     
187     if ([self->droppedObject isValueSettable]) {
188       [self->droppedObject setValue:
189                              [_ctx valueForKey:@"WEDragContainer_DropObject"]
190                            inComponent:[_ctx component]];
191     }
192     
193     result = [self->action valueInComponent:[_ctx component]];
194     
195     [_ctx deleteLastElementIDComponent];
196   }
197   else {
198     NSLog(@"invalid element-id: did not expect '%@' id", op);
199     result = nil;
200   }
201   return result;
202 }
203
204 - (void)appendExtraAttributesAsJavaScriptToResponse:(WOResponse *)_response
205   inContext:(WOContext *)_ctx
206 {
207   if (self->dExtraAttrs) {
208     WOComponent     *sComponent = [_ctx component];
209     NSEnumerator    *keyEnum;
210     NSString        *key;
211
212     [_response appendContentString:
213                @"\n"
214                @"<script language=\"JavaScript\">\n"
215                @"<!--\n"];
216
217     keyEnum = [self->dExtraAttrs keyEnumerator];
218     while ((key = [keyEnum nextObject])) {
219       id value;
220       
221       value = [self->dExtraAttrs objectForKey:key];
222       
223       if (value == nil)
224         continue;
225
226       if ([[key lowercaseString] isEqualToString:@"width"])
227         key = @"width";
228       else if ([[key lowercaseString] isEqualToString:@"height"])
229         key = @"height";
230       else if ([[key lowercaseString] isEqualToString:@"bgcolor"])
231         key = @"bgColor";
232       else if ([[key lowercaseString] isEqualToString:@"activecolor"])
233         key = @"activeColor";
234       else if ([[key lowercaseString] isEqualToString:@"align"])
235         key = @"align";
236       else if ([[key lowercaseString] isEqualToString:@"valign"])
237         key = @"vAlign";
238       else if ([[key lowercaseString] isEqualToString:@"colspan"])
239         key = @"colSpan";
240       else if ([[key lowercaseString] isEqualToString:@"rowspan"])
241         key = @"rowSpan";
242       else if ([[key lowercaseString] isEqualToString:@"nowrap"])
243         key = @"noWrap";
244       
245       value = [value stringValueInComponent:sComponent];
246       [_response appendContentString:
247                  [NSString stringWithFormat:@"tmp.%@ = \"%@\";\n", key, value]];
248     }
249     [_response appendContentString:
250                @"// -->\n"
251                @"</script>\n"];
252   }
253 }
254
255 - (void)appendToResponse:(WOResponse *)_response
256   inContext:(WOContext *)_ctx
257 {
258   NSString *htmlEl;
259   NSString *ttag;
260   NSString *teffect;
261   NSString *containerID = nil;
262   BOOL     doDnD, doSwap, doAttach;
263   
264   doDnD = [[[_ctx request] clientCapabilities] doesSupportDHTMLDragAndDrop];
265
266   //doDnD = YES;
267   
268   ttag = [[self->tags valueInComponent:[_ctx component]]
269                       componentsJoinedByString:@","];
270   
271   teffect = [self->effect stringValueInComponent:[_ctx component]];
272   if (teffect == nil) teffect = @"move";
273   
274   [WEDropScript appendDropScriptToResponse:_response inContext:_ctx];
275   
276   [_ctx appendElementIDComponent:@"drop"];
277   
278   htmlEl   = [self->elementName stringValueInComponent:[_ctx component]];
279   doAttach = ([self->isAttached boolValueInComponent:[_ctx component]] &&
280              (self->elementName != nil));
281   
282   if (htmlEl == nil || doAttach) htmlEl = @"span";
283   
284   if ((self->elementName != nil) || doDnD) {
285     int containerIDc;
286     
287     [_response appendContentString: @"<"];
288     [_response appendContentString:htmlEl];
289
290     if (doDnD) {
291       /* gen unique container id */
292       
293       if ((containerID = [_ctx valueForKey:@"WEDropContainerSequence"])) {
294         containerID = AUTORELEASE([containerID copy]);
295         containerIDc = [containerID intValue];
296       }
297       else {
298         containerID  = @"0";
299         containerIDc = 0;
300       }
301       
302       [_response appendContentString:@" id=\"skydrop"];
303       if (doAttach) [_response appendContentString:@"dummy"];
304       [_response appendContentString:containerID];
305       [_response appendContentString:@"\""];
306       
307       containerIDc++;
308     
309       [_ctx takeValue:[NSString stringWithFormat:@"%i", containerIDc]
310             forKey:@"WEDropContainerSequence"];
311     }
312   }
313   
314   if (doDnD) {
315     NSString *swapOnAction  = @"";
316     NSString *swapOffAction = @"";
317     NSString *cancelAction;
318     NSString *infoAction;
319       
320
321     doSwap = self->swapColor
322       ? [self->swapColor boolValueInComponent:[_ctx component]]
323       : YES;
324
325     cancelAction = [NSString stringWithFormat:@"fnCancelDefault('%@','%@');",
326                              ttag, teffect];
327     if (doSwap) {
328       swapOnAction  = [NSString stringWithFormat:
329                                 @"dropFieldSwapColor(skydrop%@,true);",
330                                 containerID];
331       swapOffAction = [NSString stringWithFormat:
332                                 @"dropFieldSwapColor(skydrop%@,false);",
333                                 containerID];
334     }
335     
336     infoAction = [NSString stringWithFormat:@"fnGetInfo(this, '%@');",
337                            [_ctx componentActionURL]];
338
339     if (doAttach) {
340       NSString *tagName = nil;
341
342       // doAttach==YES -> self->elementName != nil
343       tagName = [self->elementName stringValueInComponent:[_ctx component]];
344       tagName = [tagName uppercaseString];
345       
346       [_response appendContentCharacter:'>'];
347       
348       [_response appendContentString:[NSString stringWithFormat:
349            @"\n"
350            @"<script language=\"JavaScript\">\n"
351            @"<!--\n"
352            @"  function onDragEnterFunc%@() {\n    %@\n     %@\n}\n"
353            @"  function onDragOverFunc%@()  {\n    %@\n     %@\n}\n"
354            @"  function onDragLeaveFunc%@() {\n %@\n     }\n"
355            @"  function onDropFunc%@()      {\n %@\n     }\n"
356            @"\n"
357            @"  tmp = document.getElementById(\"%@\");\n"
358            @"  i = 5;\n"
359            @"  while ((tmp.tagName != \"%@\") && (i >= 0)) {\n"
360            @"    tmp = tmp.parentNode;\n"
361            @"    i--;\n"
362            @"  }\n"
363            @"  tmp.ondragover    = onDragOverFunc%@;\n"
364            @"  tmp.ondragleave   = onDragLeaveFunc%@;\n"
365            @"  tmp.ondrop        = onDropFunc%@;\n"
366            @"  tmp.ondragenter   = onDragEnterFunc%@;\n"
367            @"  tmp.id            = \"%@\";\n"
368            @"// -->\n"
369            @"</script>\n",
370            containerID, cancelAction, swapOnAction,
371            containerID, cancelAction, swapOnAction,
372            containerID, swapOffAction,
373            containerID, infoAction,
374            [@"skydropdummy" stringByAppendingString:containerID],
375            tagName,
376            containerID,
377            containerID,
378            containerID,
379            containerID,
380            [@"skydrop" stringByAppendingString:containerID]]];
381
382       // remove bgColors of TR's sub TD:
383       if ([tagName isEqualToString:@"TR"]) {
384         [_response appendContentString:
385            @"\n"
386            @"<script language=\"JavaScript\">\n"
387            @"<!--\n"
388            @"list = tmp.getElementsByTagName(\"TD\");\n"
389            @"cnt  = list.length;\n"
390            @"for (i=0; i<cnt; i++) {\n"
391            @"  list[i].removeAttribute(\"bgColor\");\n"
392            @"}\n"
393            @"// -->\n"
394            @"</script>\n"];
395       }
396
397       /* append extra attributes by script */
398       [self appendExtraAttributesAsJavaScriptToResponse:_response
399                                               inContext:_ctx];
400     }
401     else {
402       [_response appendContentString:@" onDragEnter=\""];
403       [_response appendContentString:cancelAction];
404       [_response appendContentString:swapOnAction];
405
406       [_response appendContentString:@"\" onDragOver=\""];
407       [_response appendContentString:cancelAction];
408       [_response appendContentString:swapOnAction];
409
410       [_response appendContentString:@"\" onDragLeave=\""];
411       [_response appendContentString:swapOffAction];
412      
413       [_response appendContentString:@"\" onDrop=\""];
414       [_response appendContentString:infoAction];
415       [_response appendContentCharacter:'"'];
416       
417       [self appendExtraAttributesToResponse:_response inContext:_ctx];
418       [_response appendContentCharacter:'>'];
419     }
420   }
421   else if (self->elementName != nil) {
422     [self appendExtraAttributesToResponse:_response inContext:_ctx];
423     [_response appendContentCharacter:'>'];
424   }
425   
426   [_ctx deleteLastElementIDComponent];
427   
428   /* add template */
429   [_ctx appendElementIDComponent:@"p"];
430   [self->template appendToResponse:_response inContext:_ctx];
431   [_ctx deleteLastElementIDComponent];
432   
433   /* close container */
434   if ((self->elementName != nil) || doDnD) {
435     [_response appendContentString:@"</"];
436     [_response appendContentString:htmlEl];
437     [_response appendContentCharacter:'>'];
438   }
439 }
440
441 // --- accessors ---
442
443 - (WOElement *)template {
444   return self->template;
445 }
446
447 @end /* WEDropContainer */
448
449 @implementation WEDropScript
450
451 + (void)appendDropScriptToResponse:(WOResponse *)_response
452   inContext:(WOContext *)_ctx
453 {
454   BOOL doDnD;
455   
456   doDnD = [[[_ctx request] clientCapabilities] doesSupportDHTMLDragAndDrop];
457   
458   if (![[_ctx valueForKey:@"WEDropContainerScriptDone"] boolValue] && doDnD) {
459     NSString *dropScript;
460     
461     dropScript =
462 #include "WEDropScript.jsm"
463       ;
464     
465     [_response appendContentString:dropScript];
466     
467     [_ctx takeValue:[NSNumber numberWithBool:YES]
468           forKey:@"WEDropContainerScriptDone"];
469   }
470 }
471
472 - (void)appendToResponse:(WOResponse *)_response
473   inContext:(WOContext *)_ctx
474 {
475   [[self class] appendDropScriptToResponse:_response inContext:_ctx];
476 }
477
478 @end /* WEDropScript */