]> err.no Git - sope/blob - sope-appserver/WOExtensions/JSImageFlyover.m
updated framework version
[sope] / sope-appserver / WOExtensions / JSImageFlyover.m
1 /*
2   Copyright (C) 2000-2005 SKYRIX Software AG
3
4   This file is part of SOPE.
5
6   SOPE 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   SOPE 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 SOPE; 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
22 #import <NGObjWeb/WODynamicElement.h>
23
24 @interface JSImageFlyover : WODynamicElement
25 {
26   WOAssociation *action;
27   WOAssociation *javaScriptFunction;
28   WOAssociation *pageName;
29   WOAssociation *selectedImage;
30   WOAssociation *unselectedImage;
31   WOAssociation *framework;
32   WOAssociation *targetWindow;
33
34   // Skyrix add-ons
35   WOAssociation *directActionName;
36   WOAssociation *actionClass;
37   BOOL          sidInUrl;
38   WOAssociation *queryDictionary;
39   NSDictionary  *queryParameters;
40   
41   WOElement     *template;
42 }
43
44 @end
45
46 #import <NGObjWeb/NGObjWeb.h>
47 #include "common.h"
48
49 @implementation JSImageFlyover
50
51 + (int)version {
52   return [super version] + 0 /* v2 */;
53 }
54 + (void)initialize {
55   NSAssert2([super version] == 2,
56             @"invalid superclass (%@) version %i !",
57             NSStringFromClass([self superclass]), [super version]);
58 }
59
60 - (NSDictionary *)extractQueryParameters: (NSDictionary *)_set {
61   NSMutableDictionary *paras = nil;
62   NSMutableArray      *paraKeys = nil;
63   NSEnumerator        *keys;
64   NSString            *key;
65
66   // locate query parameters
67   keys = [_set keyEnumerator];
68   while ((key = [keys nextObject])) {
69     if ([key hasPrefix:@"?"]) {
70       WOAssociation *value;
71
72       if ([key isEqualToString:@"?wosid"])
73         continue;
74
75       value = [_set objectForKey:key];
76           
77       if (paraKeys == nil)
78         paraKeys = [NSMutableArray arrayWithCapacity:8];
79       if (paras == nil)
80         paras = [NSMutableDictionary dictionaryWithCapacity:8];
81           
82       [paraKeys addObject:key];
83       [paras setObject:value forKey:[key substringFromIndex:1]];
84     }
85   }
86
87   // remove query parameters
88   if (paraKeys) {
89     unsigned cnt, count;
90     for (cnt = 0, count = [paraKeys count]; cnt < count; cnt++) {
91       [(NSMutableDictionary *)_set removeObjectForKey:
92                                      [paraKeys objectAtIndex:cnt]];
93     }
94   }
95
96   // assign parameters
97   return [paras copy];
98 }
99
100 - (id)initWithName:(NSString *)_name
101   associations:(NSDictionary *)_config
102   template:(WOElement *)_subs
103 {
104   if ((self = [super initWithName:_name associations:_config template:_subs])){
105     int           funcCount;
106     WOAssociation *sidInUrlAssoc;
107     
108     self->action             = WOExtGetProperty(_config, @"action");
109     self->javaScriptFunction = WOExtGetProperty(_config, @"javaScriptFunction");
110     self->pageName           = WOExtGetProperty(_config, @"pageName");
111     self->selectedImage      = WOExtGetProperty(_config, @"selectedImage");
112     self->unselectedImage    = WOExtGetProperty(_config, @"unselectedImage");
113     self->framework          = WOExtGetProperty(_config, @"framework");
114     self->targetWindow       = WOExtGetProperty(_config, @"targetWindow");
115
116     self->directActionName   = WOExtGetProperty(_config, @"directActionName");
117     self->actionClass        = WOExtGetProperty(_config, @"actionClass");
118     self->queryDictionary    = WOExtGetProperty(_config, @"queryDictionary");
119     self->queryParameters    = [self extractQueryParameters:_config];
120     
121     funcCount = 0;
122     if (self->action) funcCount++;
123     if (self->pageName) funcCount++;
124     if (self->javaScriptFunction) funcCount++;
125     if (self->directActionName) funcCount++;
126
127     if (funcCount > 1)
128       NSLog(@"WARNING: JSImageFlyover: choose only one of "
129             @"action | pageName | javaScriptFunction | directActionName");
130     if (funcCount < 1)
131       NSLog(@"WARNING: JSImageFlyover: no function declared - choose one of"
132             @"action | pageName | javaScriptFunction | directActionName");
133     if (!self->selectedImage)
134       NSLog(@"WARNING: JSImageFlyover: no value for 'selectedImage'");
135     if (!self->unselectedImage)
136       NSLog(@"WARNING: JSImageFlyover: no value for 'unselectedImage'");
137
138     /* for directActionName */
139     sidInUrlAssoc = WOExtGetProperty(_config, @"?wosid");
140     self->sidInUrl = (sidInUrlAssoc)
141       ? [sidInUrlAssoc boolValueInComponent:nil]
142       : YES;
143     
144
145     self->template = [_subs retain];
146   }
147   return self;
148 }
149
150 - (void)dealloc {
151   [self->action             release];
152   [self->javaScriptFunction release];
153   [self->pageName           release];
154   [self->selectedImage      release];
155   [self->unselectedImage    release];
156   [self->framework          release];
157   [self->targetWindow       release];
158   [self->template           release];
159
160   [self->directActionName release];
161   [self->actionClass      release];
162   [self->queryDictionary  release];
163   [self->queryParameters  release];
164   
165   [super dealloc];
166 }
167
168 /* handle requests */
169
170 - (void)takeValuesFromRequest:(WORequest *)_rq inContext:(WOContext *)_ctx {
171   [self->template takeValuesFromRequest:_rq inContext:_ctx];
172 }
173
174 - (id)invokeActionForRequest:(WORequest *)_rq inContext:(WOContext *)_ctx {
175   id          result;
176   NSString    *name;
177
178   if (self->pageName) {
179     name = [self->pageName stringValueInComponent: [_ctx component]];
180     result = [[_ctx application] pageWithName:name inContext:_ctx];
181   }
182   else if (self->action) {
183     result = [self->action valueInComponent:[_ctx component]];
184   }
185   else {
186     result = [self->template invokeActionForRequest:_rq inContext:_ctx];
187   }
188   return result;
189 }
190
191 /* generate response */
192
193 - (NSString *)imageByFilename:(NSString *)_name
194   inContext:(WOContext *)_ctx
195   framework:(NSString *)_framework
196 {
197   WOResourceManager *rm;
198   NSString          *tmp;
199   NSArray           *languages;
200
201   rm        = [[_ctx application] resourceManager];
202   languages = [_ctx resourceLookupLanguages];
203   tmp       = [rm urlForResourceNamed:_name
204                   inFramework:_framework
205                   languages:languages
206                   request:[_ctx request]];
207   return tmp;
208 }
209     
210
211 - (void)appendDirectActionURLToResponse:(WOResponse *)_response
212   inContext:(WOContext *)_ctx
213 {
214   WOComponent *comp;
215   NSString            *daName;
216   NSString            *daClass;
217   NSMutableDictionary *qd;
218   WOSession           *sn;
219   NSDictionary        *tdict;
220   NSString *s;
221   
222   comp    = [_ctx component];
223   daName  = [self->directActionName stringValueInComponent:comp];
224   daClass = [self->actionClass stringValueInComponent:comp];
225       
226   if (daClass) {
227     if (daName) {
228       if (![daClass isEqualToString:@"DirectAction"])
229         daName = [NSString stringWithFormat:@"%@/%@", daClass, daName];
230     }
231     else
232       daName = daClass;
233   }
234       
235   qd = [NSMutableDictionary dictionaryWithCapacity:16];
236
237   if (self->queryDictionary) {
238     if ((tdict = [self->queryDictionary valueInComponent:comp]))
239       [qd addEntriesFromDictionary:tdict];
240   }
241
242   if (self->queryParameters) {
243     NSEnumerator *keys;
244     NSString     *key;
245
246     keys = [self->queryParameters keyEnumerator];
247     while ((key = [keys nextObject])) {
248       id assoc, value;
249       assoc = [self->queryParameters objectForKey:key];
250       value = [assoc stringValueInComponent:comp];
251       [qd setObject:(value ? value : @"") forKey:key];
252     }
253   }
254       
255   if ((self->sidInUrl) && ([_ctx hasSession])) {
256     sn = [_ctx session];
257     [qd setObject:[sn sessionID] forKey:WORequestValueSessionID];
258     if (![sn isDistributionEnabled]) {
259       [qd setObject:[[WOApplication application] number]
260           forKey:WORequestValueInstance];
261     }
262   }
263       
264   s = [_ctx directActionURLForActionNamed:daName queryDictionary:qd];
265   [_response appendContentString:s];
266 }
267
268 - (void)appendToResponse:(WOResponse *)_response
269   inContext:(WOContext *)_ctx
270 {
271   WOComponent *comp;
272   NSString    *tmp;
273   NSString    *tunselected, *tselected, *tframework;
274   NSString    *elID;
275   NSArray     *ta;
276   NSString    *s;
277   
278   comp = [_ctx component];
279   tunselected = [self->unselectedImage stringValueInComponent:comp];
280   tselected   = [self->selectedImage   stringValueInComponent:comp];
281   tframework  = (self->framework)
282     ? [self->framework stringValueInComponent:comp]
283     : [comp frameworkName];
284
285   tunselected = [self imageByFilename: tunselected inContext:_ctx
286                       framework: tframework];
287   tselected   = [self imageByFilename: tselected inContext:_ctx
288                       framework: tframework];
289   
290   elID = [_ctx elementID];
291   /* javascript didn't work with #.#.#.# -> replacing to #x#x#x# */
292   ta = [[NSArray alloc] initWithArray:[elID componentsSeparatedByString:@"."]];
293   elID = [ta componentsJoinedByString:@"x"];
294   [ta release];
295   
296   /* template */
297   [self->template appendToResponse:_response inContext:_ctx];
298
299   /* script */
300   [_response appendContentString:@"<script type=\"text/javascript\">\n<!--\n"];
301
302   if (![_ctx valueForKey:@"JSImageFlyoverScriptDone"]) {
303     tmp = @"var JSImageFlyoverImages = new Array();\n"
304           @"function JSImageFlyover(imgName,imgKind) {\n"
305           @"  document.images[imgName].src = "
306           @"JSImageFlyoverImages[imgName][imgKind].src;\n"
307           @"}\n";
308     [_response appendContentString:tmp];
309     [_ctx takeValue:[NSNumber numberWithBool:YES]
310           forKey:@"JSImageFlyoverScriptDone"];
311   }
312
313   tmp = @"JSImageFlyoverImages['%@'] = new Array; \n"
314         @"JSImageFlyoverImages['%@'][0] = new Image; "
315         @"JSImageFlyoverImages['%@'][0].src = '%@'; \n"
316         @"JSImageFlyoverImages['%@'][1] = new Image; "
317         @"JSImageFlyoverImages['%@'][1].src = '%@'; \n";
318   
319   s = [[NSString alloc] initWithFormat:tmp,
320                           elID, elID, elID, tunselected,
321                           elID, elID, tselected];
322   [_response appendContentString:s];
323   [s release];
324   
325   [_response appendContentString:@"\n//-->\n</script>"];
326   
327   /* link containing onMouseOver, onMouseOut and HREF */
328   [_response appendContentString:@"<a onmouseover=\"JSImageFlyover('"];
329   [_response appendContentString:elID];
330   [_response appendContentString:@"',1)\""];
331   [_response appendContentString:@" onmouseout=\"JSImageFlyover('"];
332   [_response appendContentString:elID];
333   [_response appendContentString:@"',0)\""];
334   [_response appendContentString:@" href=\""];
335   
336   if (self->javaScriptFunction) {
337     [_response appendContentString:@"javascript:"];
338     [_response appendContentHTMLAttributeValue:
339                  [self->javaScriptFunction stringValueInComponent:comp]];
340   }
341   else if (self->directActionName)
342     [self appendDirectActionURLToResponse:_response inContext:_ctx];
343   else /* component action */
344     [_response appendContentString:[_ctx componentActionURL]];
345   
346   [_response appendContentString:@"\" "];
347
348   if (self->targetWindow) {
349     [_response appendContentString:@" target=\""];
350     [_response appendContentHTMLAttributeValue:
351                  [self->targetWindow stringValueInComponent: comp]];
352     [_response appendContentString:@"\" "];
353   }
354   [_response appendContentString:@" >"];
355
356   /* the image itself */
357   
358   [_response appendContentString:@"<img border='0' src=\""];
359   [_response appendContentString:tunselected];
360   [_response appendContentString:@"\" name=\""];
361   [_response appendContentString:elID];
362   [_response appendContentString:@"\" "];
363   [self appendExtraAttributesToResponse:_response inContext:_ctx];
364   
365   [_response appendContentString:
366                (_ctx->wcFlags.xmlStyleEmptyElements ? @" />" : @">")];
367
368   /* close link */
369   [_response appendContentString:@"</a>"];
370 }
371
372 @end /* JSImageFlyover */