2 Copyright (C) 2000-2004 SKYRIX Software AG
4 This file is part of OpenGroupware.org.
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
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.
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
23 #include "WETabView.h"
25 #include "WEClientCapabilities.h"
26 #import <NGObjWeb/NGObjWeb.h>
27 #import <NGExtensions/NGExtensions.h>
28 #import <EOControl/EOControl.h>
31 // # define DEBUG_TAKEVALUES 1
36 NSString *WETabView_HEAD = @"WETabView_head";
37 NSString *WETabView_BODY = @"WETabView_body";
38 NSString *WETabView_KEYS = @"WETabView_keys";
39 NSString *WETabView_SCRIPT = @"WETabView_script";
40 NSString *WETabView_ACTIVEKEY = @"WETabView_activekey";
41 NSString *WETabView_COLLECT = @"~tv~";
43 @implementation WETabView
45 static NSNumber *YesNumber;
49 YesNumber = [[NSNumber numberWithBool:YES] retain];
53 return [super version] + 0;
56 - (id)initWithName:(NSString *)_name
57 associations:(NSDictionary *)_config
58 template:(WOElement *)_t
60 if ((self = [super initWithName:_name associations:_config template:_t])) {
61 self->selection = WOExtGetProperty(_config, @"selection");
63 self->bgColor = WOExtGetProperty(_config, @"bgColor");
64 self->nonSelectedBgColor = WOExtGetProperty(_config, @"nonSelectedBgColor");
65 self->leftCornerIcon = WOExtGetProperty(_config, @"leftCornerIcon");
66 self->rightCornerIcon = WOExtGetProperty(_config, @"rightCornerIcon");
68 self->tabIcon = WOExtGetProperty(_config, @"tabIcon");
69 self->leftTabIcon = WOExtGetProperty(_config, @"leftTabIcon");
70 self->selectedTabIcon = WOExtGetProperty(_config, @"selectedTabIcon");
72 self->asBackground = WOExtGetProperty(_config, @"asBackground");
73 self->width = WOExtGetProperty(_config, @"width");
74 self->height = WOExtGetProperty(_config, @"height");
75 self->activeBgColor = WOExtGetProperty(_config, @"activeBgColor");
76 self->inactiveBgColor = WOExtGetProperty(_config, @"inactiveBgColor");
78 self->fontColor = WOExtGetProperty(_config, @"fontColor");
79 self->fontSize = WOExtGetProperty(_config, @"fontSize");
80 self->fontFace = WOExtGetProperty(_config, @"fontFace");
82 self->template = [_t retain];
88 RELEASE(self->selection);
90 RELEASE(self->bgColor);
91 RELEASE(self->nonSelectedBgColor);
92 RELEASE(self->leftCornerIcon);
93 RELEASE(self->rightCornerIcon);
95 RELEASE(self->leftTabIcon);
96 RELEASE(self->selectedTabIcon);
97 RELEASE(self->tabIcon);
100 RELEASE(self->height);
102 RELEASE(self->activeBgColor);
103 RELEASE(self->inactiveBgColor);
105 RELEASE(self->fontColor);
106 RELEASE(self->fontSize);
107 RELEASE(self->fontFace);
109 RELEASE(self->template);
115 - (id)saveNestedStateInContext:(WOContext *)_ctx {
118 - (void)restoreNestedState:(id)_state inContext:(WOContext *)_ctx {
119 if (_state == nil) return;
122 - (NSArray *)collectKeysInContext:(WOContext *)_ctx {
123 /* collect mode, collects all keys */
124 [_ctx setObject:WETabView_COLLECT forKey:WETabView_HEAD];
126 [self->template appendToResponse:nil inContext:_ctx];
128 [_ctx removeObjectForKey:WETabView_HEAD];
129 return [_ctx objectForKey:WETabView_KEYS];
134 - (void)takeValuesFromRequest:(WORequest *)_req inContext:(WOContext *)_ctx {
136 NSString *activeTabKey;
138 activeTabKey = [self->selection stringValueInComponent:[_ctx component]];
140 nestedState = [self saveNestedStateInContext:_ctx];
141 [_ctx appendElementIDComponent:@"b"];
142 [_ctx appendElementIDComponent:activeTabKey];
144 [_ctx setObject:activeTabKey forKey:WETabView_BODY];
147 [[_ctx component] debugWithFormat:@"WETabView: body takes values, eid='%@'",
151 [self->template takeValuesFromRequest:_req inContext:_ctx];
153 [_ctx removeObjectForKey:WETabView_BODY];
154 [_ctx deleteLastElementIDComponent]; // activeKey
155 [_ctx deleteLastElementIDComponent]; /* 'b' */
156 [self restoreNestedState:nestedState inContext:_ctx];
159 - (id)invokeActionForRequest:(WORequest *)_req inContext:(WOContext *)_ctx {
164 if ((key = [_ctx currentElementID]) == nil)
168 nestedState = [self saveNestedStateInContext:_ctx];
170 if ([key isEqualToString:@"h"]) {
174 [_ctx consumeElementID];
175 [_ctx appendElementIDComponent:@"h"];
177 if ((urlKey = [_ctx currentElementID]) == nil) {
179 debugWithFormat:@"missing active head tab key !"];
182 //NSLog(@"clicked: %@", urlKey);
183 [_ctx consumeElementID];
184 [_ctx appendElementIDComponent:urlKey];
188 [_ctx setObject:self->selection forKey:WETabView_HEAD];
189 result = [self->template invokeActionForRequest:_req inContext:_ctx];
190 [_ctx removeObjectForKey:WETabView_HEAD];
194 [_ctx deleteLastElementIDComponent]; // active key
196 [_ctx deleteLastElementIDComponent]; // 'h'
198 else if ([key isEqualToString:@"b"]) {
200 NSString *activeTabKey, *urlKey;
202 [_ctx consumeElementID];
203 [_ctx appendElementIDComponent:@"b"];
205 if ((urlKey = [_ctx currentElementID]) == nil) {
207 debugWithFormat:@"missing active body tab key !"];
210 //NSLog(@"clicked: %@", urlKey);
211 [_ctx consumeElementID];
212 [_ctx appendElementIDComponent:urlKey];
215 activeTabKey = [self->selection stringValueInComponent:[_ctx component]];
216 [_ctx setObject:activeTabKey forKey:WETabView_BODY];
218 result = [self->template invokeActionForRequest:_req inContext:_ctx];
220 [_ctx removeObjectForKey:WETabView_BODY];
223 [_ctx deleteLastElementIDComponent]; // active key
224 [_ctx deleteLastElementIDComponent]; // 'b'
228 debugWithFormat:@"unknown tab container key '%@'", key];
231 [self restoreNestedState:nestedState inContext:_ctx];
235 - (NSString *)_tabViewCountInContext:(WOContext *)_ctx {
237 count = [[_ctx valueForKey:@"WETabViewScriptDone"] intValue];
238 return [NSString stringWithFormat:@"%d",count];
241 - (NSString *)scriptHref:(WETabItemInfo *)_info
242 inContext:(WOContext *)_ctx
244 keys:(NSArray *)_keys
246 NSMutableString *result = [NSMutableString string];
253 activeKey = [self->selection stringValueInComponent:[_ctx component]];
254 [result appendString:@"JavaScript:showTab("];
255 [result appendString:_info->key];
256 [result appendString:@"Tab);"];
258 [result appendString:@"swapCorners("];
260 ? @"tabCorner%@,tabCornerLeft%@);"
261 : @"tabCornerLeft%@,tabCorner%@);";
262 elID = [self _tabViewCountInContext:_ctx];
263 [result appendString:[NSString stringWithFormat:tstring,elID,elID]];
265 for (i=0, cnt = [_keys count]; i < cnt; i++) {
266 tmp = [_keys objectAtIndex:i];
268 if ((tmp->isScript || [tmp->key isEqualToString:activeKey])
269 && ![tmp->key isEqualToString:_info->key]) {
270 [result appendString:@"hideTab("];
271 [result appendString:tmp->key];
272 [result appendString:@"Tab);"];
278 - (void)appendLink:(WETabItemInfo *)_info
279 toResponse:(WOResponse *)_response
280 inContext:(WOContext *)_ctx
281 isActive:(BOOL)_isActive isLeft:(BOOL)_isLeft
282 doScript:(BOOL)_doScript keys:(NSArray *)_keys
286 NSString *headUri = nil;
287 NSString *imgUri = nil;
288 NSString *label = nil;
289 NSString *bgcolor = nil;
292 NSString *scriptHref = nil;
295 doImages = ![[[_ctx request] clientCapabilities] isTextModeBrowser];
297 comp = [_ctx component];
298 headUri = _info->uri;
300 if (_info->asBackground == 0)
301 doBgIcon = [self->asBackground boolValueInComponent:comp];
303 doBgIcon = (_info->asBackground == 1) ? YES : NO;
305 if ((label = _info->label) == nil)
310 NSString *imgName = nil;
313 imgName = _info->selIcon; // selectedTabIcon
315 imgName = [self->selectedTabIcon stringValueInComponent:comp];
318 imgName = _info->leftIcon; // leftTabIcon
320 imgName = [self->leftTabIcon stringValueInComponent:comp];
323 imgName = _info->tabIcon; // tabIcon
325 imgName = [self->tabIcon stringValueInComponent:comp];
328 if (imgName == nil) {
329 imgName = _info->icon;
332 imgUri = WEUriOfResource(imgName, _ctx);
334 if ([imgUri length] < 1)
339 bgcolor = (_info->activeBg)
341 : [self->activeBgColor stringValueInComponent:comp];
344 bgcolor = (_info->inactiveBg)
346 : [self->inactiveBgColor stringValueInComponent:comp];
351 : [self->width stringValueInComponent:comp];
354 : [self->height stringValueInComponent:comp];
356 [_response appendContentString:@"<td align='center' valign='middle'"];
359 [_response appendContentString:@" width='"];
360 [_response appendContentHTMLAttributeValue:w];
361 [_response appendContentCharacter:'\''];
364 [_response appendContentString:@" height='"];
365 [_response appendContentHTMLAttributeValue:h];
366 [_response appendContentCharacter:'\''];
369 [_response appendContentString:@" bgcolor='"];
370 [_response appendContentHTMLAttributeValue:bgcolor];
371 [_response appendContentCharacter:'\''];
373 if (doBgIcon && doImages) {
374 WEClientCapabilities *ccaps;
376 ccaps = [[_ctx request] clientCapabilities];
378 [_response appendContentString:@" background='"];
379 [_response appendContentHTMLAttributeValue:imgUri];
380 [_response appendContentCharacter:'\''];
382 // click on td background
383 if ([ccaps isInternetExplorer] && [ccaps isJavaScriptBrowser]) {
384 [_response appendContentString:@" onclick=\"window.location.href='"];
385 [_response appendContentHTMLAttributeValue:headUri];
386 [_response appendContentString:@"'\""];
390 [_response appendContentCharacter:'>'];
392 if (!doImages) [_response appendContentString:@"["];
394 [_response appendContentString:@"<a style=\"text-decoration:none;\" href=\""];
396 if (_doScript && doImages && (_info->isScript || _isActive)) {
398 [self scriptHref:_info inContext:_ctx isLeft:_isLeft keys:_keys];
399 [_response appendContentHTMLAttributeValue:scriptHref];
402 [_response appendContentHTMLAttributeValue:headUri];
405 [_response appendContentString:@"\" "];
406 [_response appendContentString:
407 [NSString stringWithFormat:@"name='%@TabLink'", _info->key]];
408 [_response appendContentString:@">"];
410 if (!doImages && _isActive)
411 [_response appendContentString:@"<b>"];
413 if (doImages && !doBgIcon) {
414 [_response appendContentString:@"<img border='0' src='"];
415 [_response appendContentString:imgUri];
416 [_response appendContentString:@"' name='"];
417 [_response appendContentString:_info->key];
418 [_response appendContentString:@"TabImg' alt='"];
419 [_response appendContentHTMLAttributeValue:label];
420 [_response appendContentString:@"' title='"];
421 [_response appendContentHTMLAttributeValue:label];
422 [_response appendContentString:@"'"];
423 [_response appendContentString:@" />"];
426 NSString *fc = [self->fontColor stringValueInComponent:comp];
427 NSString *fs = [self->fontSize stringValueInComponent:comp];
428 NSString *ff = [self->fontFace stringValueInComponent:comp];
431 hasFont = (fc || fs || ff) ? YES : NO;
433 if ([label length] < 1)
435 [_response appendContentString:@"<nobr>"];
436 if (hasFont) WEAppendFont(_response, fc, ff, fs); // <font>
438 if (_isActive) [_response appendContentString:@"<b>"];
439 [_response appendContentHTMLString:label];
440 if (_isActive) [_response appendContentString:@"</b>"];
442 if (hasFont) [_response appendContentString:@"</font>"]; // </font>
443 [_response appendContentString:@"</nobr>"];
446 if (!doImages && _isActive)
447 [_response appendContentString:@"</b>"];
449 [_response appendContentString:@"</a>"];
450 if (!doImages) [_response appendContentString:@"]"];
453 [_response appendContentString:@"</td>"];
455 if (_doScript && doImages && (_info->isScript || _isActive)) {
457 NSString *s; // selected tab icon
458 NSString *u; // unselected tab icon
462 s = _info->selIcon; // selectedTabIcon
463 u = (_isLeft) ? _info->leftIcon : _info->tabIcon;
465 s = WEUriOfResource(s, _ctx);
466 u = WEUriOfResource(u, _ctx);
468 s = ([s length] < 1) ? imgUri : s;
469 u = ([u length] < 1) ? imgUri : u;
472 out = [NSString alloc];
473 out = [out initWithFormat:
474 @"<script language=\"JavaScript\">\n"
476 @"var %@Tab = new Array();\n"
477 @"%@Tab[\"link\"] = %@TabLink;\n"
478 @"%@Tab[\"href1\"] = \"%@\";\n"
479 @"%@Tab[\"href2\"] = \"%@\";\n"
480 @"%@Tab[\"Img\"] = window.document.%@TabImg;\n"
481 @"%@Tab[\"Ar\"] = new Array();\n"
482 @"%@Tab[\"Ar\"][0] = new Image();\n"
483 @"%@Tab[\"Ar\"][0].src = \"%@\";\n"
484 @"%@Tab[\"Ar\"][1] = new Image();\n"
485 @"%@Tab[\"Ar\"][1].src = \"%@\";\n"
487 k, k, k, k, scriptHref, k, headUri,
492 [_response appendContentString:out];
495 # define _appendStr_(_str_) [_response appendContentString:_str_]
496 _appendStr_(@"<script language=\"JavaScript\">\n<!--\nvar ");
497 _appendStr_(k); _appendStr_(@"Tab = new Array();\n");
499 _appendStr_(k); _appendStr_(@"Tab[\"link\"] = ");
500 _appendStr_(k); _appendStr_(@"TabLink;\n"); // linkName
502 _appendStr_(k); _appendStr_(@"Tab[\"href1\"] = \"");
503 _appendStr_(scriptHref); _appendStr_(@"\";\n"); // scriptHref
505 _appendStr_(k); _appendStr_(@"Tab[\"href2\"] = \"");
506 _appendStr_(_info->uri); _appendStr_(@"\";\n"); // actionHref
508 _appendStr_(k); _appendStr_(@"Tab[\"Img\"] = window.document.");
509 _appendStr_(k); _appendStr_(@"TabImg;\n");
510 _appendStr_(k); _appendStr_(@"Tab[\"Ar\"] = new Array();\n");
511 _appendStr_(k); _appendStr_(@"Tab[\"Ar\"][0] = new Image();\n");
512 _appendStr_(k); _appendStr_(@"Tab[\"Ar\"][0].src = \"");
513 _appendStr_(u); _appendStr_(@"\";\n"); // unselected img
514 _appendStr_(k); _appendStr_(@"Tab[\"Ar\"][1] = new Image();\n");
515 _appendStr_(k); _appendStr_(@"Tab[\"Ar\"][1].src = \"");
516 _appendStr_(s); _appendStr_(@"\";\n"); // selected img
517 _appendStr_(@"//-->\n</script>");
523 - (void)appendSubmitButton:(WETabItemInfo *)_info
524 toResponse:(WOResponse *)_response
525 inContext:(WOContext *)_ctx
526 isActive:(BOOL)_isActive isLeft:(BOOL)_left
527 doScript:(BOOL)_doScript keys:(NSArray *)_keys
529 [self appendLink:_info
532 isActive:_isActive isLeft:_left
533 doScript:_doScript keys:_keys];
536 - (void)_appendTabViewJSScriptToResponse:(WOResponse *)_response
537 inContext:(WOContext *)_ctx
539 [_response appendContentString:
540 @"<script language=\"JavaScript\">\n<!--\n\n"
541 @"function showTab(obj) {\n"
543 @" if (obj==null) { alert('missing tab obj ..'); return; }\n"
544 @" if (obj['Div']==null) {"
545 @" alert('missing div key in ' + obj); return; }\n"
546 @" if (obj['Div'].style==null) {"
547 @" alert('missing style key in div ' + obj['Div']);return; }\n"
549 @" obj['Div'].style.display = \"\";\n"
550 @" obj['Img'].src = obj[\"Ar\"][1].src;\n"
551 @" obj['link'].href = obj[\"href2\"];\n"
553 @"function hideTab(obj) {\n"
555 @" if (obj==null) { alert('missing tab obj ..'); return; }\n"
556 @" if (obj['Div']==null) {"
557 @" alert('missing div key in ' + obj); return; }\n"
558 @" if (obj['Div'].style==null) {"
559 @" alert('missing style key in div ' + obj['Div']);return; }\n"
561 @" obj['Div'].style.display = \"none\";\n"
562 @" obj['Img'].src = obj[\"Ar\"][0].src;\n"
563 @" obj['link'].href = obj[\"href1\"];\n"
565 @"function swapCorners(obj1,obj2) {\n"
566 @" if (obj1==null) { alert('missing corner 1'); return; }\n"
567 @" if (obj2==null) { alert('missing corner 2'); return; }\n"
568 @" obj1.style.display = \"none\";\n"
569 @" obj2.style.display = \"\";\n"
571 @"//-->\n</script>"];
574 - (void)_appendHeaderRowToResponse:(WOResponse *)_response
575 inContext:(WOContext *)_ctx
576 keys:(NSArray *)keys activeKey:(NSString *)activeKey
577 doScript:(BOOL)doScript
582 doForm = NO; /* generate form controls ? */
584 [_response appendContentString:@"<tr><td colspan='2'>"];
585 [_response appendContentString:
586 @"<table border='0' cellpadding='0' cellspacing='0'><tr>"];
588 for (i = 0, count = [keys count]; i < count; i++) {
593 info = [keys objectAtIndex:i];
595 isActive = [key isEqualToString:activeKey];
597 [_ctx appendElementIDComponent:key];
600 /* tab is inside of a FORM, so produce submit buttons */
601 [self appendSubmitButton:info
605 isLeft:(i == 0) ? YES : NO
610 /* tab is not in a FORM, generate hyperlinks for tab */
611 [self appendLink:info
615 isLeft:(i == 0) ? YES : NO
620 [_ctx deleteLastElementIDComponent];
622 // [_response appendContentString:@"<td></td>"];
623 [_response appendContentString:@"</tr></table>"];
624 [_response appendContentString:@"</td></tr>"];
627 - (void)_appendHeaderFootRowToResponse:(WOResponse *)_response
628 inContext:(WOContext *)_ctx
629 bgcolor:(NSString *)bgcolor
630 doScript:(BOOL)doScript
631 isLeftActive:(BOOL)isLeftActive
633 [_response appendContentString:@" <tr"];
635 [_response appendContentString:@" bgcolor=\""];
636 [_response appendContentHTMLAttributeValue:bgcolor];
637 [_response appendContentString:@"\""];
639 [_response appendContentString:@">\n"];
642 [_response appendContentString:@" <td align=\"left\" width=\"10\">"];
645 [_response appendContentString:@"<div id=\"tabCorner"];
646 [_response appendContentString:[self _tabViewCountInContext:_ctx]];
647 [_response appendContentString:@"\" "];
648 [_response appendContentString:@"style=\"display: "];
649 [_response appendContentString:(isLeftActive) ? @"" : @"none"];
650 [_response appendContentString:@";\">"];
651 [_response appendContentString:@" "];
652 [_response appendContentString:@"</div>"];
654 else if (isLeftActive)
655 [_response appendContentString:@" "];
658 [_response appendContentString:@"<div id=\"tabCornerLeft"];
659 [_response appendContentString:[self _tabViewCountInContext:_ctx]];
660 [_response appendContentString:@"\" "];
661 [_response appendContentString:@"style=\"display: "];
662 [_response appendContentString:(!isLeftActive) ? @"visible" : @"none"];
663 [_response appendContentString:@";\">"];
666 if (!isLeftActive || doScript) {
669 uri = [self->leftCornerIcon stringValueInComponent:[_ctx component]];
670 if ((uri = WEUriOfResource(uri, _ctx))) {
671 [_response appendContentString:@"<img border=\"0\" alt=\"\" src=\""];
672 [_response appendContentString:uri];
673 [_response appendContentString:@"\">"];
676 [_response appendContentString:@" "];
679 [_response appendContentString:@"</div>"];
681 [_response appendContentString:@"</td>\n"];
684 [_response appendContentString:@" <td align=\"right\">"];
688 uri = [self->rightCornerIcon stringValueInComponent:[_ctx component]];
689 if ((uri = WEUriOfResource(uri, _ctx))) {
690 [_response appendContentString:@"<img border=\"0\" alt=\"\" src=\""];
691 [_response appendContentString:uri];
692 [_response appendContentString:@"\" />"];
695 [_response appendContentString:@" "];
697 [_response appendContentString:@"</td>\n"];
699 [_response appendContentString:@" </tr>\n"];
702 - (void)_appendBodyRowToResponse:(WOResponse *)_response
703 inContext:(WOContext *)_ctx
704 bgcolor:(NSString *)bgcolor
705 activeKey:(NSString *)activeKey
707 WEClientCapabilities *ccaps;
710 ccaps = [[_ctx request] clientCapabilities];
712 /* put additional padding table into content ??? */
713 indentContent = [ccaps isFastTableBrowser] && ![ccaps isTextModeBrowser];
715 [_response appendContentString:@"<tr><td colspan='2'"];
718 [_response appendContentString:@" bgcolor=\""];
719 [_response appendContentHTMLAttributeValue:bgcolor];
720 [_response appendContentString:@"\""];
722 [_response appendContentString:@">"];
725 /* start padding table */
726 [_response appendContentString:
727 @"<table border='0' width='100%'"
728 @" cellpadding='10' cellspacing='0'>"];
729 [_response appendContentString:@"<tr><td>"];
732 [_ctx appendElementIDComponent:@"b"];
733 [_ctx appendElementIDComponent:activeKey];
735 /* generate currently active body */
737 [_ctx setObject:activeKey forKey:WETabView_BODY];
738 [self->template appendToResponse:_response inContext:_ctx];
739 [_ctx removeObjectForKey:WETabView_BODY];
742 [_ctx deleteLastElementIDComponent]; // activeKey
743 [_ctx deleteLastElementIDComponent]; // 'b'
746 /* close padding table */
747 [_response appendContentString:@"</td></tr></table>"];
749 [_response appendContentString:@"</td></tr>"];
752 - (BOOL)isLeftActiveInKeys:(NSArray *)keys activeKey:(NSString *)activeKey{
758 for (i = 0, count = [keys count]; i < count; i++) {
761 info = [keys objectAtIndex:i];
763 if ((i == 0) && [info->key isEqualToString:activeKey])
770 - (void)appendToResponse:(WOResponse *)_response inContext:(WOContext *)_ctx {
778 int tabViewCount; /* used for image id's and writing script once */
780 doScript = NO; /* perform tab-clicks on browser (use javascript) */
781 tabViewCount = [[_ctx valueForKey:@"WETabViewScriptDone"] intValue];
782 cmp = [_ctx component];
784 /* check for browser */
786 WEClientCapabilities *ccaps;
787 //BOOL isJavaScriptBrowser;
789 ccaps = [[_ctx request] clientCapabilities];
790 doScript = [ccaps isInternetExplorer] && [ccaps isJavaScriptBrowser];
791 if ([_ctx hasSession]) {
795 doScript = (doScript &&
796 [[sn valueForKey:@"isJavaScriptEnabled"] boolValue]);
800 /* disable javascript */
805 nestedState = [self saveNestedStateInContext:_ctx];
809 activeKey = [self->selection stringValueInComponent:cmp];
811 bgcolor = [self->bgColor stringValueInComponent:cmp];
812 bgcolor = [bgcolor stringValue];
814 [_ctx appendElementIDComponent:@"h"];
816 /* collect & process keys (= available tabs) */
818 keys = [self collectKeysInContext:_ctx];
820 if (![[keys valueForKey:@"key"] containsObject:activeKey])
821 /* selection is not available in keys */
824 if ((activeKey == nil) && ([keys count] > 0)) {
825 /* no or invalid selection, use first key */
826 activeKey = [[keys objectAtIndex:0] key];
827 if ([self->selection isValueSettable])
828 [self->selection setValue:activeKey inComponent:[_ctx component]];
832 doScript = [[keys valueForKey:@"isScript"] containsObject:YesNumber];
833 [_ctx setObject:[NSNumber numberWithBool:doScript]
834 forKey:WETabView_SCRIPT];
837 /* start appending */
839 if ((doScript) && (tabViewCount == 0))
840 [self _appendTabViewJSScriptToResponse:_response inContext:_ctx];
842 /* count up for unique tabCorner/tabCornerLeft images */
843 [_ctx takeValue:[NSNumber numberWithInt:(tabViewCount + 1)]
844 forKey:@"WETabViewScriptDone"];
846 [_response appendContentString:
847 @"<table border='0' width='100%'"
848 @" cellpadding='0' cellspacing='0'>"];
850 /* find out whether left is active */
852 isLeftActive = [self isLeftActiveInKeys:keys activeKey:activeKey];
854 /* generate header row */
856 [self _appendHeaderRowToResponse:_response inContext:_ctx
857 keys:keys activeKey:activeKey
860 [_ctx deleteLastElementIDComponent]; // 'h' for head
861 [_ctx removeObjectForKey:WETabView_HEAD];
863 /* header foot row */
865 [self _appendHeaderFootRowToResponse:_response inContext:_ctx
868 isLeftActive:isLeftActive];
872 [self _appendBodyRowToResponse:_response inContext:_ctx
874 activeKey:activeKey];
878 [_response appendContentString:@"</table>"];
879 [_ctx removeObjectForKey:WETabView_ACTIVEKEY];
880 [_ctx removeObjectForKey:WETabView_KEYS];
881 [self restoreNestedState:nestedState inContext:_ctx];