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#include "WECalendarField.h" 23#include <NGObjWeb/WEClientCapabilities.h> 24#include "common.h" 25 26static Class StrClass = Nil; 27 28@implementation WECalendarField 29 30+ (void)initialize { 31 StrClass = [NSString class]; 32} 33 34static NSString *retStrForInt(int i) { 35 // TODO: find out good statics 36 return [[StrClass alloc] initWithFormat:@"%i", i]; 37} 38static NSString *retStr02ForInt(int i) { 39 switch (i) { // TODO: find out a good count ... 40 case 0: return @"00"; 41 case 1: return @"01"; 42 case 2: return @"02"; 43 case 3: return @"03"; 44 case 4: return @"04"; 45 case 5: return @"05"; 46 case 6: return @"06"; 47 case 7: return @"07"; 48 case 8: return @"08"; 49 case 9: return @"09"; 50 default: 51 // TODO: add log ... 52 return [[StrClass alloc] initWithFormat:@"%02i", i]; 53 } 54} 55 56- (id)initWithName:(NSString *)_name 57 associations:(NSDictionary *)_config 58 template:(WOElement *)_subs 59{ 60 if ((self = [super initWithName:_name associations: _config template:_subs])) { 61 self->name = OWGetProperty(_config, @"name"); 62 self->date = OWGetProperty(_config, @"date"); 63 64 // time field associations 65 self->hour = OWGetProperty(_config, @"hour"); 66 self->minute = OWGetProperty(_config, @"minute"); 67 self->second = OWGetProperty(_config, @"second"); 68 self->useTextField = OWGetProperty(_config, @"useTextField"); 69 self->hourInterval = OWGetProperty(_config, @"hourInterval"); 70 self->minuteInterval = OWGetProperty(_config, @"minuteInterval"); 71 self->secondInterval = OWGetProperty(_config, @"secondInterval"); 72 73 // date field associations 74 self->year = OWGetProperty(_config, @"year"); 75 self->month = OWGetProperty(_config, @"month"); 76 self->day = OWGetProperty(_config, @"day"); 77 self->format = OWGetProperty(_config, @"format"); 78 79 self->template = [_subs retain]; 80 } 81 return self; 82} 83 84- (void)dealloc { 85 [self->name release]; 86 [self->date release]; 87 88 /* time field associations */ 89 [self->hour release]; 90 [self->minute release]; 91 [self->second release]; 92 [self->useTextField release]; 93 [self->hourInterval release]; 94 [self->minuteInterval release]; 95 [self->secondInterval release]; 96 97 /* date field associations */ 98 [self->year release]; 99 [self->month release]; 100 [self->day release]; 101 [self->format release]; 102 103 [self->template release]; 104 [super dealloc]; 105} 106 107- (void)takeValuesFromRequest:(WORequest *)_rq inContext:(WOContext *)_ctx { 108 [self _takeValuesFromTimeFieldRequest:_rq inContext:_ctx]; 109 [self _takeValuesFromDateFieldRequest:_rq inContext:_ctx]; 110} 111 112- (id)invokeActionForRequest:(WORequest *)_rq inContext:(WOContext *)_ctx { 113 id result = nil; 114 115 result = [self _invokeActionForTimeFieldRequest:_rq inContext:_ctx]; 116 if (result == nil) 117 result = [self _invokeActionForDateFieldRequest:_rq inContext:_ctx]; 118 119 return result; 120} 121 122- (void)appendToResponse:(WOResponse *)_response inContext:(WOContext *)_ctx { 123 if ([_ctx isRenderingDisabled]) { 124 [self->template appendToResponse:_response inContext:_ctx]; 125 return; 126 } 127 128 [_response appendContentString: 129 @"<table border='0' cellpadding='0' cellspacing='0'>" 130 @"<tr>" 131 @"<td align='left' valign='bottom'>"]; 132 [self _appendTimeFieldToResponse:_response inContext:_ctx]; 133 134 [_response appendContentString: 135 @"</td>" 136 @"<td align='left' valign='bottom'>"]; 137 138 [self _appendDateFieldToResponse:_response inContext:_ctx]; 139 140 [_response appendContentString: 141 @"</td>" 142 @"</tr>" 143 @"</table>"]; 144} 145 146@end /* WECalendarField */ 147 148@implementation WECalendarField(WETimeFieldImplementation) 149 150/* Private Methodes */ 151 152- (NSString *)_divIDAndScriptInContext:(WOContext *)_ctx 153 response:(WOResponse *)_response 154{ 155 int divCount; 156 157 divCount = [[_ctx valueForKey: @"WETimeFieldScript"] intValue]; 158 if (divCount == 0) { 159 [_response appendContentString: 160 @"<style type=\"text/css\">\n" 161 @"A.DDLlink { width: 23px; font: normal 10pt Arial; color: " 162 @"#6F1537; text-decoration: none; } \n" 163 @"A.DDLlink:hover { color: red; background: #FAE8B8; } \n" 164 @"</style>"]; 165 [_response appendContentString: 166 @"<script language=\"JavaScript\">\n" 167 @"var DDLlayerCount = 1000;\n" 168 @"function DDLopen(layerObj,el) {\n" 169 @" if (layerObj.style.visibility == 'hidden') {\n" 170 @" layerObj.style.visibility = 'visible';\n" 171 @" layerObj.style.zIndex = DDLlayerCount;\n" 172 @" formObj = DDLformField(el);\n" 173 @" formObj.contentEditable = false;\n" 174 @" DDLlayerCount++;\n" 175 @" " 176 @" } else { layerObj.style.visibility = 'hidden'; }\n" 177 @"}\n\n" 178 @"function DDLreturn(layerObj,el,value) {\n" 179 @" formObj = DDLformField(el);\n" 180 @" formObj.value = value;\n" 181 @" formObj.contentEditable = true;\n" 182 @" layerObj.style.visibility = 'hidden';\n" 183 @"}\n" 184 @"function DDLformField(el) {\n" 185 @" for (i = 0; i < document.forms.length; i++)\n" 186 @" for (j = 0; j < document.forms[i].elements.length; j++)\n" 187 @" if (document.forms[i].elements[j].name == el)\n" 188 @" return document.forms[i].elements[j];\n" 189 @"}\n" 190 @"</script>"]; 191 } 192 [_ctx takeValue:[NSNumber numberWithInt:(divCount+1)] 193 forKey:@"WETimeFieldScript"]; 194 195 return [StrClass stringWithFormat:@"dropDownDiv%i", divCount]; 196} 197 198- (void)_appendSelectToResponse:(WOResponse *)_response 199 inContext:(WOContext *)_ctx 200 elementIDComponent:(NSString *)_elementIDComponent 201 count:(int)_count 202 selectedIndex:(int)_idx 203 interval:(int)_interval 204{ 205 WEClientCapabilities *ccaps; 206 NSString *tmp; 207 int i; 208 BOOL isMSIE; 209 NSString *divID; 210 NSString *img; 211 NSString *elementId; 212 213 ccaps = [[_ctx request] clientCapabilities]; 214 isMSIE = [ccaps isInternetExplorer]; 215 elementId = [self elementIdWithSuffix:_elementIDComponent ctx:_ctx]; 216 217 divID = [self _divIDAndScriptInContext:_ctx response:_response]; 218 219 img = WEUriOfResource(@"downstairs.gif", _ctx); 220 221 if (isMSIE && img) { 222 NSString *s; 223 224 [_response appendContentString:@"<input readonly=\"readonly\" name=\""]; 225 [_response appendContentString:elementId]; 226 [_response appendContentString:@"\" value=\""]; 227 228 s = retStr02ForInt(_idx); 229 [_response appendContentHTMLAttributeValue:s]; 230 [s release]; 231 232 [_response appendContentString: 233 @"\" type=\"text\" size=\"2\" maxlength=\"2\""]; 234#if 0 235 [_response appendContentString:@" style=\"background-color: #FFDAAA;\""]; 236#endif 237 [_response appendContentString:@" /><img border=\"0\" src=\""]; 238 [_response appendContentString:img]; 239 [_response appendContentString:@"\" onClick=\""]; 240 [_response appendContentString:@"javascript:DDLopen("]; 241 [_response appendContentString:divID]; 242 [_response appendContentString:@",'"]; 243 [_response appendContentString:elementId]; 244 [_response appendContentString:@"')\" /><br />"]; 245 [_response appendContentString:@"<div id=\""]; 246 [_response appendContentString:divID]; 247 [_response appendContentString: 248 @"\" style=\"position: absolute; overflow: auto; height: 150; width: 47;" 249 @" background: #FFDAAA; border: 1 solid; " 250 @"visibility: hidden; padding: 0 0 0 2;\">"]; 251 } 252 else { 253 [_response appendContentString:@"<select name=\""]; 254 [_response appendContentString:elementId]; 255 [_response appendContentString:@"\">"]; 256 } 257 258 for (i = 0; i <= _count; i += _interval) { 259 tmp = retStr02ForInt(i); 260 if (isMSIE && img) { 261 NSString *s; 262 263 s = [[StrClass alloc] initWithFormat: 264 @"<a class=\"DDLlink\" href=\"javascript:DDLreturn(%@,'%@','%@')\">%@" 265 @"</a><br />", 266 divID, elementId, tmp, tmp]; 267 [_response appendContentString:s]; 268 [s release]; 269 } 270 else { 271 [_response appendContentString:@"<option value=\""]; 272 [_response appendContentString:tmp]; 273 [_response appendContentString:@"\""]; 274 [_response appendContentString: 275 (i == _idx) ? @" selected=\"selected\"" : @""]; 276 [_response appendContentString:@">"]; 277 [_response appendContentString:tmp]; 278 [_response appendContentString:@"</option>"]; 279 } 280 [tmp release]; tmp = nil; 281 } 282 283 if (isMSIE && img) 284 [_response appendContentString:@"</div>"]; 285 else 286 [_response appendContentString:@"</select>"]; 287} 288 289/* handle request */ 290 291- (void)_takeValuesFromTimeFieldRequest:(WORequest *)_request 292 inContext:(WOContext *)_ctx 293{ 294 WOComponent *comp; 295 id formValue; 296 BOOL tuseTField; 297 NSString *elementId; 298 NSArray *ta; 299 int idx; 300 301 comp = [_ctx component]; 302 tuseTField = self->useTextField 303 ? [[self->useTextField valueInComponent: comp] boolValue] 304 : NO; 305 306 if (tuseTField) { 307 // TextField value 308 elementId = [self elementIdWithSuffix:@"" ctx:_ctx]; 309 if ((formValue = [_request formValueForKey:elementId])) { 310 int intValue, cnt; 311 312 ta = [formValue componentsSeparatedByString:@":"]; 313 cnt = [ta count]; 314 315 idx = 0; 316 if ([self isHourSettable]) { 317 intValue = (idx < cnt) ? [[ta objectAtIndex:idx] intValue] : 0; 318 [self setHour:intValue inComponent:comp]; 319 idx++; 320 } 321 if ([self isMinuteSettable]) { 322 intValue = (idx < cnt) ? [[ta objectAtIndex:idx] intValue] : 0; 323 [self setMinute:intValue inComponent:comp]; 324 idx++; 325 } 326 if ([self isSecondSettable]) { 327 intValue = (idx < cnt) ? [[ta objectAtIndex:idx] intValue] : 0; 328 [self setSecond:intValue inComponent:comp]; 329 } 330 } 331 } 332 else { 333 elementId = [self elementIdWithSuffix:@"hour" ctx:_ctx]; 334 if ((formValue = [_request formValueForKey:elementId])) { 335 if ([self isHourSettable]) 336 [self setHour:[formValue intValue] inComponent:comp]; 337 } 338 339 elementId = [self elementIdWithSuffix:@"minute" ctx:_ctx]; 340 if ((formValue = [_request formValueForKey:elementId])) { 341 if ([self isMinuteSettable]) 342 [self setMinute:[formValue intValue] inComponent:comp]; 343 } 344 345 elementId = [self elementIdWithSuffix:@"second" ctx:_ctx]; 346 if ((formValue = [_request formValueForKey:elementId])) { 347 if ([self isSecondSettable]) 348 [self setSecond:[formValue intValue] inComponent:comp]; 349 } 350 } 351 352 /* template */ 353 [_ctx appendElementIDComponent:@"timeField"]; 354 [self->template takeValuesFromRequest:_request inContext:_ctx]; 355 [_ctx deleteLastElementIDComponent]; 356} 357 358- (id)_invokeActionForTimeFieldRequest:(WORequest *)_rq 359 inContext:(WOContext *)_ctx 360{ 361 return [self->template invokeActionForRequest:_rq inContext:_ctx]; 362} 363 364/* generate response */ 365 366- (void)_appendTimeFieldToResponse:(WOResponse *)_r inContext:(WOContext *)_cx{ 367 WOComponent *comp; 368 BOOL tuseTField; 369 int hourInt; // hourInterval 370 int minuteInt; // minuteInterval 371 int secondInt; // secondInterval 372 NSMutableArray *ta; 373 374 comp = [_cx component]; 375 376 hourInt = self->hourInterval 377 ? [self->hourInterval intValueInComponent:comp] : 1; 378 379 minuteInt = self->minuteInterval 380 ? [self->minuteInterval intValueInComponent:comp] : 1; 381 382 secondInt = self->secondInterval 383 ? [self->secondInterval intValueInComponent:comp] : 1; 384 385 tuseTField = self->useTextField 386 ? [self->useTextField boolValueInComponent:comp] 387 : NO; 388 389 // template 390 [_cx appendElementIDComponent:@"timeField"]; 391 [self->template appendToResponse:_r inContext:_cx]; 392 [_cx deleteLastElementIDComponent]; 393 394 // all values in one textField 395 if (tuseTField) { 396 int h, m, s; 397 NSString *tmp, *fmt; 398 // build string of values and @":" 399 400 h = [self hourInComponent:comp]; 401 m = [self minuteInComponent:comp]; 402 s = [self secondInComponent:comp]; 403 404 ta = [[NSMutableArray alloc] initWithCapacity: 3]; 405 fmt = @"%02i"; 406 407 if ([self hasHourInComponent:comp]) { 408 tmp = retStr02ForInt(h); 409 [ta addObject:tmp]; 410 [tmp release]; 411 } 412 if ([self hasMinuteInComponent:comp]) { 413 tmp = [[StrClass alloc] initWithFormat:fmt, m]; 414 [ta addObject:tmp]; 415 [tmp release]; 416 } 417 if ([self hasSecondInComponent:comp]) { 418 tmp = [[StrClass alloc] initWithFormat:fmt, s]; 419 [ta addObject:tmp]; 420 [tmp release]; 421 } 422 423 tmp = [ta componentsJoinedByString:@":"]; 424 [ta release]; ta = nil; 425 426 /* append to response */ 427 if ([tmp isNotEmpty]) { 428 [_r appendContentString:@"<input type=\"text\" name=\""]; 429 [_r appendContentString:[self elementIdWithSuffix:@"" ctx:_cx]]; 430 [_r appendContentString:@"\" value=\""]; 431 [_r appendContentString:tmp]; 432 [_r appendContentString:@"\""]; 433 434 tmp = retStrForInt([tmp length]); 435 [_r appendContentString:@" size=\""]; 436 [_r appendContentString:tmp]; 437 [_r appendContentString:@"\" maxlength=\""]; 438 [_r appendContentString:tmp]; 439 [_r appendContentString:@"\""]; 440 [tmp release]; 441 442 [_r appendContentString:@" />"]; 443 } 444 } 445 else { 446 // hour select field 447 [_r appendContentString: 448 @"<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tr>"]; 449 450 if ([self hasHourInComponent:comp]) { 451 [_r appendContentString:@"<td valign=\"bottom\">"]; 452 [self _appendSelectToResponse:_r inContext:_cx 453 elementIDComponent:@"hour" 454 count:23 selectedIndex:[self hourInComponent:comp] 455 interval:hourInt]; 456 [_r appendContentString:@"</td>"]; 457 } 458 459 // minute select field 460 if ([self hasMinuteInComponent:comp]) { 461 [_r appendContentString:@"<td valign=\"bottom\">"]; 462 [self _appendSelectToResponse:_r inContext:_cx 463 elementIDComponent:@"minute" 464 count:59 selectedIndex:[self minuteInComponent:comp] 465 interval:minuteInt]; 466 [_r appendContentString:@"</td>"]; 467 } 468 469 // second select field 470 if ([self hasSecondInComponent:comp]) { 471 [_r appendContentString:@"<td valign=\"bottom\">"]; 472 [self _appendSelectToResponse:_r inContext:_cx 473 elementIDComponent:@"second" 474 count:59 selectedIndex:[self secondInComponent:comp] 475 interval:secondInt]; 476 [_r appendContentString:@"</td>"]; 477 } 478 [_r appendContentString:@"</tr></table>"]; 479 480 } /* end of (!tuseTField) */ 481} 482 483@end /* WECalendarField(WETimeFieldImplementation */ 484 485@implementation WECalendarField(WEDateFieldImplementation) 486 487- (void)_takeValuesFromDateFieldRequest:(WORequest *)_request 488 inContext:(WOContext *)_ctx 489{ 490 NSString *tformat; 491 NSCalendarDate *tdate; 492 int tyear; 493 int tmonth; 494 int tday; 495 WOComponent *comp; 496 NSString *elementId; 497 498 comp = [_ctx component]; 499 500 tformat = [self->format stringValueInComponent: comp]; 501 if (tformat == nil) tformat = @"%Y-%m-%d"; 502 elementId = [self elementIdWithSuffix:@"" ctx:_ctx]; 503 504 if ([self isKindOfClass:[WECalendarField class]]) { 505 id t = tformat; 506 507 t = [[t componentsSeparatedByString:@"%H"] componentsJoinedByString:@""]; 508 t = [[t componentsSeparatedByString:@"%M"] componentsJoinedByString:@""]; 509 t = [[t componentsSeparatedByString:@"%S"] componentsJoinedByString:@""]; 510 511 tformat = t; 512 } 513 514 tdate = [NSCalendarDate dateWithString: 515 [_request formValueForKey:elementId] 516 calendarFormat: tformat]; 517 if (tdate == nil) { 518 NSLog(@"WARNING: WEDateField: field value and format do not match!"); 519 } 520 else { 521 tyear = [tdate yearOfCommonEra]; 522 tmonth = [tdate monthOfYear]; 523 tday = [tdate dayOfMonth]; 524 525 526 if ([self isYearSettable]) [self setYear:tyear inComponent:comp]; 527 if ([self isMonthSettable]) [self setMonth:tmonth inComponent:comp]; 528 if ([self isDaySettable]) [self setDay:tday inComponent:comp]; 529 } 530 531 [_ctx appendElementIDComponent:@"dateField"]; 532 [self->template takeValuesFromRequest:_request inContext:_ctx]; 533 [_ctx deleteLastElementIDComponent]; 534} 535 536- (id)_invokeActionForDateFieldRequest:(WORequest *)_request 537 inContext:(WOContext *)_ctx 538{ 539 return [self->template invokeActionForRequest:_request inContext:_ctx]; 540} 541 542- (void)_appendDateFieldToResponse:(WOResponse *)_response 543 inContext:(WOContext *)_ctx 544{ 545 WEClientCapabilities *ccaps; 546 int tyear; 547 int tmonth; 548 int tday; 549 NSString *tformat; 550 NSString *tmp; 551 WOComponent *comp; 552 NSCalendarDate *tdate; 553 NSString *calendarDivID; 554 int calendarID; 555 BOOL isMSIE; 556 NSString *value; 557 558 ccaps = [[_ctx request] clientCapabilities]; 559 comp = [_ctx component]; 560 tdate = [NSCalendarDate calendarDate]; 561 isMSIE = [ccaps isInternetExplorer]; 562 563 if (![_ctx valueForKey:@"WEDateFieldScriptDone"]) 564 [WEDateFieldScript appendWEDateFieldScriptToResponse: _response 565 inContext: _ctx 566 headBackground: HEAD_BACKGROUND_COLOR 567 headColor: HEAD_COLOR 568 headNavColor: HEAD_NAVIGATION_COLOR 569 labels: nil 570 useImages: NO]; 571 572 // associations 573 tyear = ([self hasYearInComponent:comp]) 574 ? [self yearInComponent:comp] 575 : [tdate yearOfCommonEra]; 576 tmonth = ([self hasMonthInComponent:comp]) 577 ? [self monthInComponent:comp] 578 : [tdate monthOfYear]; 579 tday = ([self hasDayInComponent:comp]) 580 ? [self dayInComponent:comp] 581 : [tdate dayOfMonth]; 582 tformat = self->format 583 ? [self->format stringValueInComponent: comp] 584 : (NSString *)@"%Y-%m-%d"; 585 586 if ([self isKindOfClass:[WECalendarField class]]) { 587 id t = tformat; 588 589 t = [[t componentsSeparatedByString:@"%H"] componentsJoinedByString:@""]; 590 t = [[t componentsSeparatedByString:@"%M"] componentsJoinedByString:@""]; 591 t = [[t componentsSeparatedByString:@"%S"] componentsJoinedByString:@""]; 592 593 tformat = t; 594 } 595 596 // input field value 597 tdate = [NSCalendarDate dateWithYear: tyear 598 month: tmonth 599 day: tday 600 hour: 0 minute: 0 second: 0 601 timeZone: [tdate timeZone]]; 602 603 value = [tdate descriptionWithCalendarFormat: tformat]; 604 605 // div id for javascript calendar 606 calendarID = ([_ctx valueForKey: @"WEDateField_DivID"]) 607 ? [[_ctx valueForKey: @"WEDateField_DivID"] intValue] 608 : 0; 609 calendarDivID = [StrClass stringWithFormat:@"calendarDiv%d", calendarID]; 610 calendarID++; 611 [_ctx takeValue:[NSNumber numberWithInt: calendarID] 612 forKey:@"WEDateField_DivID"]; 613 614 // template 615 [_ctx appendElementIDComponent:@"dateField"]; 616 [self->template appendToResponse:_response inContext:_ctx]; 617 [_ctx deleteLastElementIDComponent]; 618 619 [_response appendContentString: 620 @"<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\">"]; 621 [_response appendContentString: 622 @"<td valign=\"top\" align=\"left\">"]; 623 624 // input field 625 [_response appendContentString:@"<input type=\"text\" name=\""]; 626 [_response appendContentString:[self elementIdWithSuffix:@"" ctx:_ctx]]; 627 [_response appendContentString:@"\" value=\""]; 628 [_response appendContentString:value]; 629 [_response appendContentString:@"\" size=\""]; 630 [_response appendContentString: 631 [[NSNumber numberWithInt: [value length]] stringValue]]; 632 [_response appendContentString:@"\" maxlength=\""]; 633 [_response appendContentString: 634 [[NSNumber numberWithInt: [value length]] stringValue]]; 635 [_response appendContentString:@"\" />"]; 636 637 /* link to calendar panel */ 638 [_response appendContentString: @" <a href=\"javascript:doNothing()\" "]; 639 [_response appendContentString: @"onClick=\""]; 640 tmp = @"javascript:%@toggleCalendar('%@',%@%@,'%@')"; 641 tmp = [[StrClass alloc] initWithFormat: tmp, 642 (isMSIE) ? @"" : @"actPos;", // layer position 643 [self elementIdWithSuffix:@"" ctx:_ctx], // form element 644 (isMSIE) ? @"" : @"document.", calendarDivID, // calendar DIV 645 tformat]; // dateFormat 646 [_response appendContentString: tmp]; 647 [tmp release]; 648 [_response appendContentString: @"\">"]; 649 650 // calendar image 651 tmp = WEUriOfResource(@"icon_popupcalendar.gif", _ctx); 652 653 if (tmp) { 654 tmp = [[StrClass alloc] initWithFormat: 655 @"<img border=\"0\" src=\"%@\" />", tmp]; 656 } 657 else 658 tmp = @"x"; 659 660 [_response appendContentString:tmp]; 661 [tmp release]; 662 663 [_response appendContentString: @"</a><br />"]; 664 665 /* calendar panel */ 666 [_response appendContentString: @"<div id=\""]; 667 [_response appendContentString: calendarDivID]; 668 [_response appendContentString: @"\" style=\"position: absolute; "]; 669 [_response appendContentString: @"visibility: "]; 670 [_response appendContentString: (isMSIE) ? @"hidden" : @"hide"]; 671 [_response appendContentString: @";\"></div>"]; 672 673 [_response appendContentString: @"</td></tr></table>"]; 674} 675 676@end /* WECalendarField(WEDateFieldImplementation) */ 677 678@implementation WEDateFieldScript 679 680- (id)initWithName:(NSString *)_name 681 associations:(NSDictionary *)_config 682 template: (WOElement *)_subs 683{ 684 if ((self = [super initWithName:_name associations: _config template:_subs])) 685 { 686 self->headBackground = OWGetProperty(_config, @"headBackground"); 687 self->headColor = OWGetProperty(_config, @"headColor"); 688 self->headNavColor = OWGetProperty(_config, @"headNavColor"); 689 self->labels = OWGetProperty(_config, @"labels"); 690 self->useImages = OWGetProperty(_config, @"useImages"); 691 } 692 return self; 693} 694 695- (void)dealloc { 696 [self->useImages release]; 697 [self->headBackground release]; 698 [self->headColor release]; 699 [self->headNavColor release]; 700 [self->labels release]; 701 [super dealloc]; 702} 703 704 705+ (void)appendWEDateFieldScriptToResponse: (WOResponse *)_response 706 inContext: (WOContext *)_ctx 707 headBackground: (NSString *)_hBack 708 headColor: (NSString *)_hCol 709 headNavColor: (NSString *)_hNav 710 labels: (id)_labels 711 useImages: (BOOL)_useImg 712{ 713 NSString *tmp; 714 NSString *tmon; 715 NSString *tweek; 716 NSString *timg; 717 718 // images... 719 NSString *firstI; 720 NSString *prevI; 721 NSString *todayI; 722 NSString *nextI; 723 NSString *lastI; 724 NSString *closeI; 725 726 // colors 727 if (_hBack == nil) _hBack = HEAD_BACKGROUND_COLOR; 728 if (_hCol == nil) _hCol = HEAD_COLOR; 729 if (_hNav == nil) _hNav = HEAD_NAVIGATION_COLOR; 730 731 // months and weekdays 732 if (_labels == nil) { 733 NSLog(@"WARNING: WEDateFieldScript: undefined variable 'labels'"); 734 tmon = @"var externMonths = false; \n"; 735 tweek = @"var externWeekdays = false; \n"; 736 } 737 else { 738 tmon = @"var externMonths = new Array(" 739 @"\"%@\",\"%@\",\"%@\",\"%@\",\"%@\",\"%@\"," 740 @"\"%@\",\"%@\",\"%@\",\"%@\",\"%@\",\"%@\"); \n"; 741 tmon = [[StrClass alloc] initWithFormat: tmon, 742 [_labels valueForKey: @"January"], 743 [_labels valueForKey: @"February"], 744 [_labels valueForKey: @"March"], 745 [_labels valueForKey: @"April"], 746 [_labels valueForKey: @"May"], 747 [_labels valueForKey: @"June"], 748 [_labels valueForKey: @"July"], 749 [_labels valueForKey: @"August"], 750 [_labels valueForKey: @"September"], 751 [_labels valueForKey: @"October"], 752 [_labels valueForKey: @"November"], 753 [_labels valueForKey: @"December"] 754 ]; 755 tweek = @"var externWeekdays = new Array(" 756 @"\"%@\",\"%@\",\"%@\",\"%@\",\"%@\",\"%@\",\"%@\"); \n"; 757 tweek = [[StrClass alloc] initWithFormat: tweek, 758 [_labels valueForKey: @"SundayAbbrev"], 759 [_labels valueForKey: @"MondayAbbrev"], 760 [_labels valueForKey: @"TuesdayAbbrev"], 761 [_labels valueForKey: @"WednesdayAbbrev"], 762 [_labels valueForKey: @"ThursdayAbbrev"], 763 [_labels valueForKey: @"FridayAbbrev"], 764 [_labels valueForKey: @"SaturdayAbbrev"] 765 ]; 766 } 767 768 if (![_ctx valueForKey: @"WEDateFieldScriptDone"]) { 769 tmp = @"<style type='text/css'>\n" 770 @"TD.heading { text-decoration: none; color: black; " 771 @"font: bold 8pt arial, helvetica; } \n " 772 @"A.focusDay { color: blue; text-decoration: none; " 773 @"font: 8pt arial, helvetica; } \n" 774 @"A.focusDay:hover { color:darkred; text-decoration: none; " 775 @"font: 8pt arial, helvetica; } \n" 776 @"A.weekday { color: blue; text-decoration: none; " 777 @"font: 8pt arial, helvetica; } \n" 778 @"A.weekday:hover { color: darkred; font: 8pt arial, helvetica; } \n" 779 @"A.navMonYear " 780 @"{ color: %@; text-decoration: none; font: 8pt Arial; }\n" 781 @"TD.topCal " 782 @"{ font: 10pt Arial; color: %@; background-color: %@; } \n" 783 @"</style>\n"; 784 tmp = [StrClass stringWithFormat: tmp, _hNav, _hCol, _hBack]; 785 [_response appendContentString: tmp]; 786 787 [_response appendContentString: 788 @"<script language=\"JavaScript\">\n"]; 789 [_response appendContentString: @"var dateFormat = \"%Y-%m-%d\"; \n"]; 790 [_response appendContentString: tmon]; 791 [_response appendContentString: tweek]; 792 793 // navigation images 794 // doppelt haelt wirklich besser 795 firstI = WEUriOfResource(@"first.gif", _ctx); 796 prevI = WEUriOfResource(@"previous.gif", _ctx); 797 todayI = WEUriOfResource(@"non_sorted.gif", _ctx); 798 nextI = WEUriOfResource(@"next.gif", _ctx); 799 lastI = WEUriOfResource(@"last.gif", _ctx); 800 closeI = WEUriOfResource(@"icon_unread.gif", _ctx); 801 802 if (_useImg) { 803 NSString *s; 804 805 timg = @"var %@=new Image(); %@.src='%@';\n" 806 @"var %@=\"<img border='0' name='%@' src='%@' />\";\n"; 807 s = [[StrClass alloc] initWithFormat: timg, 808 @"dateFieldFirst", @"dateFieldFirst", firstI, 809 @"dateFieldFirstSRC", @"dateFieldFirstImg", firstI]; 810 [_response appendContentString:s]; 811 [s release]; 812 s = [[StrClass alloc] initWithFormat: timg, 813 @"dateFieldPrevious", @"dateFieldPrevious", prevI, 814 @"dateFieldPreviousSRC", @"dateFieldPreviousImg", prevI]; 815 [_response appendContentString:s]; 816 [s release]; 817 s = [[StrClass alloc] initWithFormat: timg, 818 @"dateFieldToday", @"dateFieldToday", todayI, 819 @"dateFieldTodaySRC", @"dateFieldTodayImg", todayI]; 820 [_response appendContentString:s]; 821 [s release]; 822 s = [[StrClass alloc] initWithFormat: timg, 823 @"dateFieldNext", @"dateFieldNext", nextI, 824 @"dateFieldNextSRC", @"dateFieldNextImg", nextI]; 825 [_response appendContentString:s]; 826 [s release]; 827 s = [[StrClass alloc] initWithFormat: timg, 828 @"dateFieldLast", @"dateFieldLast", lastI, 829 @"dateFieldLastSRC", @"dateFieldLastImg", lastI]; 830 [_response appendContentString:s]; 831 [s release]; 832 s = [[StrClass alloc] initWithFormat: timg, 833 @"dateFieldClose", @"dateFieldClose", closeI, 834 @"dateFieldCloseSRC", @"dateFieldCloseImg", closeI]; 835 [_response appendContentString:s]; 836 [s release]; 837 [_response appendContentString:@"var usesNavImages = true;\n"]; 838 } 839 else { 840 [_response appendContentString:@"var dateFieldCloseSRC=\"X\";\n"]; 841 [_response appendContentString:@"var dateFieldFirstSRC=\"<<\";\n"]; 842 [_response appendContentString:@"var dateFieldPreviousSRC=\"<\";\n"]; 843 [_response appendContentString:@"var dateFieldTodaySRC=\"O\";\n"]; 844 [_response appendContentString:@"var dateFieldNextSRC=\">\";\n"]; 845 [_response appendContentString:@"var dateFieldLastSRC=\">>\";\n"]; 846 [_response appendContentString:@"var usesNavImages = false;\n"]; 847 } 848 849 tmp = 850#include "calendar.jsm" 851 ; 852 [_response appendContentString: tmp]; 853 [_response appendContentString: @"\n</script>"]; 854 855 [_ctx takeValue: [NSNumber numberWithBool: YES] 856 forKey: @"WEDateFieldScriptDone"]; 857 } 858 859 [tmon release]; 860 [tweek release]; 861} 862 863- (void)appendToResponse: (WOResponse *)_response 864 inContext: (WOContext *)_ctx 865{ 866 WOComponent *comp; 867 868 if ([_ctx isRenderingDisabled]) return; 869 870 comp = [_ctx component]; 871 872 [[self class] appendWEDateFieldScriptToResponse: _response inContext:_ctx 873 headBackground: [self->headBackground stringValueInComponent:comp] 874 headColor: [self->headColor stringValueInComponent:comp] 875 headNavColor: [self->headNavColor stringValueInComponent:comp] 876 labels: [self->labels valueInComponent:comp] 877 useImages: [[self->useImages valueInComponent: comp] boolValue]]; 878} 879 880@end /* WEDateFieldScript */ 881 882@implementation WECalendarField(Accessors) 883 884- (NSString *)elementIdWithSuffix:(NSString *)_suffix ctx:(WOContext *)_ctx { 885 NSString *prefix = nil; 886 887 if ((prefix = [self->name stringValueInComponent:[_ctx component]]) == nil) 888 prefix = [_ctx elementID]; 889 890 if ([_suffix isNotEmpty]) 891 prefix = [prefix stringByAppendingString:@"_"]; 892 893 return [prefix stringByAppendingString:_suffix]; 894} 895 896- (void)setSecond:(int)_second inComponent:(WOComponent *)_comp { 897 if (self->date) { 898 NSCalendarDate *d = [self->date valueInComponent:_comp]; 899 900 901 d = [NSCalendarDate dateWithYear:[d yearOfCommonEra] 902 month:[d monthOfYear] 903 day:[d dayOfMonth] 904 hour:[d hourOfDay] 905 minute:[d minuteOfHour] 906 second:_second 907 timeZone:[d timeZone]]; 908 909 [self->date setValue:d inComponent:_comp]; 910 } 911 else { 912 [self->second setIntValue:_second inComponent:_comp]; 913 } 914} 915- (int)secondInComponent:(WOComponent *)_comp { 916 return (self->date != nil) 917 ? [[self->date valueInComponent:_comp] secondOfMinute] 918 : [self->second intValueInComponent:_comp]; 919} 920 921- (void)setMinute:(int)_minute inComponent:(WOComponent *)_comp { 922 if (self->date) { 923 NSCalendarDate *d; 924 925 d = [self->date valueInComponent:_comp]; 926 d = [NSCalendarDate dateWithYear:[d yearOfCommonEra] 927 month:[d monthOfYear] 928 day:[d dayOfMonth] 929 hour:[d hourOfDay] 930 minute:_minute 931 second:[d secondOfMinute] 932 timeZone:[d timeZone]]; 933 934 [self->date setValue:d inComponent:_comp]; 935 } 936 else { 937 [self->minute setIntValue:_minute inComponent:_comp]; 938 } 939} 940- (int)minuteInComponent:(WOComponent *)_comp { 941 return (self->date != nil) 942 ? [[self->date valueInComponent:_comp] minuteOfHour] 943 : [self->minute intValueInComponent:_comp]; 944} 945 946- (void)setHour:(int)_hour inComponent:(WOComponent *)_comp { 947 if (self->date) { 948 NSCalendarDate *d = [self->date valueInComponent:_comp]; 949 950 951 d = [NSCalendarDate dateWithYear:[d yearOfCommonEra] 952 month:[d monthOfYear] 953 day:[d dayOfMonth] 954 hour:_hour 955 minute:[d minuteOfHour] 956 second:[d secondOfMinute] 957 timeZone:[d timeZone]]; 958 959 [self->date setValue:d inComponent:_comp]; 960 } 961 else { 962 [self->hour setIntValue:_hour inComponent:_comp]; 963 } 964} 965- (int)hourInComponent:(WOComponent *)_comp { 966 return (self->date != nil) 967 ? [[self->date valueInComponent:_comp] hourOfDay] 968 : [self->hour intValueInComponent:_comp]; 969} 970 971- (void)setDay:(int)_day inComponent:(WOComponent *)_comp { 972 if (self->date) { 973 NSCalendarDate *d = [self->date valueInComponent:_comp]; 974 975 d = [NSCalendarDate dateWithYear:[d yearOfCommonEra] 976 month:[d monthOfYear] 977 day:_day 978 hour:[d hourOfDay] 979 minute:[d minuteOfHour] 980 second:[d secondOfMinute] 981 timeZone:[d timeZone]]; 982 983 [self->date setValue:d inComponent:_comp]; 984 } 985 else { 986 [self->day setIntValue:_day inComponent:_comp]; 987 } 988} 989- (int)dayInComponent:(WOComponent *)_comp { 990 return (self->date != nil) 991 ? [[self->date valueInComponent:_comp] dayOfMonth] 992 : [self->day intValueInComponent:_comp]; 993} 994 995- (void)setMonth:(int)_month inComponent:(WOComponent *)_comp { 996 if (self->date) { 997 NSCalendarDate *d = [self->date valueInComponent:_comp]; 998 999 d = [NSCalendarDate dateWithYear:[d yearOfCommonEra] 1000 month:_month 1001 day:[d dayOfMonth] 1002 hour:[d hourOfDay] 1003 minute:[d minuteOfHour] 1004 second:[d secondOfMinute] 1005 timeZone:[d timeZone]]; 1006 1007 [self->date setValue:d inComponent:_comp]; 1008 } 1009 else { 1010 [self->month setIntValue:_month inComponent:_comp]; 1011 } 1012} 1013- (int)monthInComponent:(WOComponent *)_comp { 1014 return (self->date != nil) 1015 ? [[self->date valueInComponent:_comp] monthOfYear] 1016 : [self->month intValueInComponent:_comp]; 1017} 1018 1019- (void)setYear:(int)_year inComponent:(WOComponent *)_comp { 1020 if (self->date) { 1021 NSCalendarDate *d = [self->date valueInComponent:_comp]; 1022 1023 d = [NSCalendarDate dateWithYear:_year 1024 month:[d monthOfYear] 1025 day:[d dayOfMonth] 1026 hour:[d hourOfDay] 1027 minute:[d minuteOfHour] 1028 second:[d secondOfMinute] 1029 timeZone:[d timeZone]]; 1030 1031 [self->date setValue:d inComponent:_comp]; 1032 } 1033 else { 1034 [self->year setIntValue:_year inComponent:_comp]; 1035 } 1036} 1037- (int)yearInComponent:(WOComponent *)_comp { 1038 return (self->date != nil) 1039 ? [[self->date valueInComponent:_comp] yearOfCommonEra] 1040 : [self->year intValueInComponent:_comp]; 1041} 1042 1043- (BOOL)isSecondSettable { 1044 return (self->date != nil) 1045 ? [self->date isValueSettable] : [self->second isValueSettable]; 1046} 1047 1048- (BOOL)isMinuteSettable { 1049 return (self->date != nil) 1050 ? [self->date isValueSettable] : [self->minute isValueSettable]; 1051} 1052 1053- (BOOL)isHourSettable { 1054 return (self->date != nil) 1055 ? [self->date isValueSettable] : [self->hour isValueSettable]; 1056} 1057 1058- (BOOL)isDaySettable { 1059 return (self->date != nil) 1060 ? [self->date isValueSettable] : [self->day isValueSettable]; 1061} 1062 1063- (BOOL)isMonthSettable { 1064 return (self->date != nil) 1065 ? [self->date isValueSettable] : [self->month isValueSettable]; 1066} 1067 1068- (BOOL)isYearSettable { 1069 return (self->date != nil) 1070 ? [self->date isValueSettable] : [self->year isValueSettable]; 1071} 1072 1073- (BOOL)_chkDateFormatKey:(NSString *)_s inComponent:(WOComponent *)_comp { 1074 NSString *fmt; 1075 1076 if (self->format == nil) 1077 return YES; 1078 1079 fmt = [self->format stringValueInComponent:_comp]; 1080 return ([fmt rangeOfString:_s].length > 0) ? YES : NO; 1081} 1082 1083- (BOOL)hasSecondInComponent:(WOComponent *)_comp { 1084 return (self->date) 1085 ? [self _chkDateFormatKey:@"S" inComponent:_comp] 1086 : (self->second != nil ? YES : NO); 1087} 1088 1089- (BOOL)hasMinuteInComponent:(WOComponent *)_comp { 1090 return (self->date) 1091 ? [self _chkDateFormatKey:@"M" inComponent:_comp] 1092 : (self->minute != nil ? YES : NO); 1093} 1094 1095- (BOOL)hasHourInComponent:(WOComponent *)_comp { 1096 return (self->date) 1097 ? [self _chkDateFormatKey:@"H" inComponent:_comp] 1098 : (self->hour != nil ? YES : NO); 1099} 1100 1101- (BOOL)hasDayInComponent:(WOComponent *)_comp { 1102 return (self->date) 1103 ? [self _chkDateFormatKey:@"d" inComponent:_comp] 1104 : (self->day != nil ? YES : NO); 1105} 1106 1107- (BOOL)hasMonthInComponent:(WOComponent *)_comp { 1108 return (self->date) 1109 ? [self _chkDateFormatKey:@"m" inComponent:_comp] 1110 : (self->month != nil ? YES : NO); 1111} 1112 1113- (BOOL)hasYearInComponent:(WOComponent *)_comp { 1114 return (self->date) 1115 ? [self _chkDateFormatKey:@"Y" inComponent:_comp] 1116 : (self->year != nil ? YES : NO); 1117} 1118 1119@end /* WECalendarField */ 1120