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