Changeset 2110

Show
Ignore:
Timestamp:
11/13/04 21:33:47 (4 years ago)
Author:
timothy
Message:

New direct DOM access calls to append messages, only kicks in when the user has Safari 1.3 installed.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • branches/overhaul/JVDirectChat.m

    r2103 r2110  
    100100- (void) addEventMessageToLogAndDisplay:(NSString *) message withName:(NSString *) name andAttributes:(NSDictionary *) attributes entityEncodeAttributes:(BOOL) encode; 
    101101- (void) addMessageToLogAndDisplay:(NSData *) message fromUser:(MVChatUser *) user asAction:(BOOL) action; 
     102- (int) locationOfMessage:(unsigned int) identifier; 
     103- (int) locationOfElementByIndex:(unsigned int) index; 
     104- (void) scrollToBottom; 
     105- (void) appendMessage:(NSString *) html subsequent:(BOOL) subsequent; 
    102106- (void) processQueue; 
    103107- (void) displayQueue; 
     
    829833 
    830834        [send reset:nil]; 
    831         [display stringByEvaluatingJavaScriptFromString:@"scrollToBottom();"]; 
     835        [self scrollToBottom]; 
    832836} 
    833837 
     
    12271231        [self writeToLog:root withDoc:doc initializing:NO continuation:NO]; 
    12281232 
    1229         NSMutableString *messageString = nil; 
     1233        NSString *messageString = nil; 
    12301234 
    12311235        @try { 
    1232                 messageString = [[[_chatStyle transformXMLDocument:doc withParameters:_styleParams] mutableCopy] autorelease]; 
     1236                messageString = [_chatStyle transformXMLDocument:doc withParameters:_styleParams]; 
    12331237        } @catch ( NSException *exception ) { 
    12341238                messageString = nil; 
     
    12381242        if( [messageString length] ) { 
    12391243                [[display window] disableFlushWindow]; // prevent any draw (white) flashing that might occur 
    1240  
    1241                 unsigned int messageCount = [[display stringByEvaluatingJavaScriptFromString:@"scrollBackMessageCount();"] intValue]; 
    1242                 unsigned int scrollbackLimit = [[NSUserDefaults standardUserDefaults] integerForKey:@"JVChatScrollbackLimit"]; 
    1243                 NSScroller *scroller = [[[[[display mainFrame] frameView] documentView] enclosingScrollView] verticalScroller]; 
    1244  
    1245                 if( ( messageCount + 1 ) > scrollbackLimit ) { 
    1246                         float loc = [[display stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"locationOfElementByIndex( %d );", ( ( messageCount + 1 ) - scrollbackLimit )]] floatValue]; 
    1247                         if( loc > 0. && [scroller isKindOfClass:[JVMarkedScroller class]] ) 
    1248                                 [(JVMarkedScroller *)scroller shiftMarksAndShadedAreasBy:( loc * -1. )]; 
    1249                 } 
    1250                  
    1251                 [messageString escapeCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"\\\"'"]]; 
    1252                 [messageString replaceOccurrencesOfString:@"\n" withString:@"\\n" options:NSLiteralSearch range:NSMakeRange( 0, [messageString length] )]; 
    1253                 [display stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"appendMessage( \"%@\" );", messageString]]; 
    1254  
     1244                [self appendMessage:messageString subsequent:NO]; 
    12551245                [[display window] enableFlushWindow]; 
    12561246        } 
     
    14631453        else xmlAddChild( xmlDocGetRootElement( _xmlLog ), xmlDocCopyNode( root, _xmlLog, 1 ) ); 
    14641454 
    1465         NSMutableString *transformedMessage = nil; 
     1455        NSString *transformedMessage = nil; 
    14661456        NSMutableDictionary *params = _styleParams; 
    14671457        if( parent ) { 
     
    14731463 
    14741464        @try { 
    1475                 transformedMessage = [[[_chatStyle transformXMLDocument:doc withParameters:params] mutableCopy] autorelease]; 
     1465                transformedMessage = [_chatStyle transformXMLDocument:doc withParameters:params]; 
    14761466        } @catch ( NSException *exception ) { 
    14771467                transformedMessage = nil; 
     
    14821472                [[display window] disableFlushWindow]; // prevent any draw (white) flashing that might occur 
    14831473 
    1484                 unsigned int messageCount = [[display stringByEvaluatingJavaScriptFromString:@"scrollBackMessageCount();"] intValue]; 
    1485                 unsigned int scrollbackLimit = [[NSUserDefaults standardUserDefaults] integerForKey:@"JVChatScrollbackLimit"]; 
    1486                 NSScroller *scroller = [[[[[display mainFrame] frameView] documentView] enclosingScrollView] verticalScroller]; 
    1487  
    1488                 if( ( messageCount + 1 ) > scrollbackLimit ) { 
    1489                         float loc = [[display stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"locationOfElementByIndex( %d );", ( ( messageCount + 1 ) - scrollbackLimit )]] floatValue]; 
    1490                         if( loc > 0. && [scroller isKindOfClass:[JVMarkedScroller class]] ) 
    1491                                 [(JVMarkedScroller *)scroller shiftMarksAndShadedAreasBy:( loc * -1. )]; 
    1492                 } 
    1493  
    14941474                BOOL subsequent = ( [transformedMessage rangeOfString:@"<?message type=\"subsequent\"?>"].location != NSNotFound ); 
    1495  
    1496                 [transformedMessage escapeCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"\\\"'"]]; 
    1497                 [transformedMessage replaceOccurrencesOfString:@"\n" withString:@"\\n" options:NSLiteralSearch range:NSMakeRange( 0, [transformedMessage length] )]; 
    1498                 [transformedMessage replaceOccurrencesOfString:@"  " withString:@"&nbsp; " options:NSLiteralSearch range:NSMakeRange( 0, [transformedMessage length] )]; 
    1499                 if( subsequent ) [display stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"scrollBackLimit = %d; appendConsecutiveMessage( \"%@\" );", scrollbackLimit, transformedMessage]]; 
    1500                 else [display stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"scrollBackLimit = %d; appendMessage( \"%@\" );", scrollbackLimit, transformedMessage]]; 
    1501  
    1502                 if( [_currentMessage isHighlighted] && [scroller isKindOfClass:[JVMarkedScroller class]] ) { 
    1503                         unsigned int loc = [[display stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"locationOfMessage( \"%d\" );", ( _messageId - 1 )]] intValue]; 
    1504                         if( loc ) [(JVMarkedScroller *)scroller addMarkAt:loc]; 
     1475                [self appendMessage:transformedMessage subsequent:subsequent]; 
     1476 
     1477                if( [_currentMessage isHighlighted] ) { 
     1478                        NSScroller *scroller = [[[[[display mainFrame] frameView] documentView] enclosingScrollView] verticalScroller]; 
     1479                        if( [scroller isKindOfClass:[JVMarkedScroller class]] ) { 
     1480                                unsigned int loc = [self locationOfMessage:( _messageId - 1 )]; 
     1481                                if( loc ) [(JVMarkedScroller *)scroller addMarkAt:loc]; 
     1482                        } 
    15051483                } 
    15061484 
     
    15211499 
    15221500        [_windowController reloadListItem:self andChildren:NO]; 
     1501} 
     1502 
     1503- (int) locationOfMessage:(unsigned int) identifier { 
     1504        if( [[display mainFrame] respondsToSelector:@selector( DOMDocument )] ) { 
     1505#ifdef _WEB_SCRIPT_OBJECT_H_ 
     1506                DOMElement *element = [[[display mainFrame] DOMDocument] getElementById:[NSString stringWithFormat:@"%d", identifier]]; 
     1507                return [[element valueForKey:@"offsetTop"] intValue]; 
     1508#endif 
     1509        } else { // old JavaScript method 
     1510                return [[display stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"locationOfMessage( \"%d\" );", identifier]] intValue]; 
     1511        } 
     1512} 
     1513 
     1514- (int) locationOfElementByIndex:(unsigned int) index { 
     1515        if( [[display mainFrame] respondsToSelector:@selector( DOMDocument )] ) { 
     1516#ifdef _WEB_SCRIPT_OBJECT_H_ 
     1517                DOMHTMLElement *body = [(DOMHTMLDocument *)[[display mainFrame] DOMDocument] body]; 
     1518                if( index < [[body children] length] ) return [[[[body children] item:index] valueForKey:@"offsetTop"] intValue]; 
     1519                else return 0; 
     1520#endif 
     1521        } else { // old JavaScript method 
     1522                return [[display stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"locationOfElementByIndex( %d );", index]] intValue]; 
     1523        } 
     1524} 
     1525 
     1526- (void) scrollToBottom { 
     1527        if( [[display mainFrame] respondsToSelector:@selector( DOMDocument )] ) { 
     1528#ifdef _WEB_SCRIPT_OBJECT_H_ 
     1529                DOMHTMLElement *body = [(DOMHTMLDocument *)[[display mainFrame] DOMDocument] body]; 
     1530                [body setValue:[body valueForKey:@"offsetHeight"] forKey:@"scrollTop"]; 
     1531#endif 
     1532        } else { 
     1533                [display stringByEvaluatingJavaScriptFromString:@"scrollToBottom();"]; 
     1534        } 
     1535} 
     1536 
     1537- (void) appendMessage:(NSString *) html subsequent:(BOOL) subsequent { 
     1538        unsigned int messageCount = 0; 
     1539        unsigned int scrollbackLimit = [[NSUserDefaults standardUserDefaults] integerForKey:@"JVChatScrollbackLimit"]; 
     1540        NSScroller *scroller = [[[[[display mainFrame] frameView] documentView] enclosingScrollView] verticalScroller]; 
     1541 
     1542        if( [[display mainFrame] respondsToSelector:@selector( DOMDocument )] ) { 
     1543#ifdef _WEB_SCRIPT_OBJECT_H_ 
     1544                messageCount = [[[(DOMHTMLDocument *)[[display mainFrame] DOMDocument] body] children] length]; 
     1545#endif 
     1546        } else messageCount = [[display stringByEvaluatingJavaScriptFromString:@"scrollBackMessageCount();"] intValue]; 
     1547 
     1548        if( ( messageCount + 1 ) > scrollbackLimit ) { 
     1549                int loc = [self locationOfElementByIndex:( ( messageCount + 1 ) - scrollbackLimit )]; 
     1550                if( loc > 0 && [scroller isKindOfClass:[JVMarkedScroller class]] ) 
     1551                        [(JVMarkedScroller *)scroller shiftMarksAndShadedAreasBy:( loc * -1 )]; 
     1552        } 
     1553 
     1554        if( [[display mainFrame] respondsToSelector:@selector( DOMDocument )] ) { 
     1555#ifdef _WEB_SCRIPT_OBJECT_H_ 
     1556                DOMHTMLElement *element = (DOMHTMLElement *)[[[display mainFrame] DOMDocument] createElement:@"span"]; 
     1557                DOMHTMLElement *replaceElement = (DOMHTMLElement *)[[[display mainFrame] DOMDocument] getElementById:@"consecutiveInsert"]; 
     1558                if( ! replaceElement ) subsequent = NO; 
     1559 
     1560                NSMutableString *transformedMessage = [html mutableCopy]; 
     1561                [transformedMessage replaceOccurrencesOfString:@"  " withString:@"&nbsp; " options:NSLiteralSearch range:NSMakeRange( 0, [transformedMessage length] )]; 
     1562                [transformedMessage replaceOccurrencesOfString:@"<?message type=\"subsequent\"?>" withString:@"" options:NSLiteralSearch range:NSMakeRange( 0, [transformedMessage length] )]; 
     1563 
     1564                // parses the message so we can get the DOM tree 
     1565                [element setInnerHTML:transformedMessage]; 
     1566 
     1567                [transformedMessage release]; 
     1568                transformedMessage = nil; 
     1569 
     1570                // check if we are near the bottom of the chat area, and if we should scroll down later 
     1571                NSNumber *scrollNeeded = [[[display mainFrame] DOMDocument] evaluateWebScript:@"( document.body.scrollTop >= ( document.body.offsetHeight - ( window.innerHeight * 1.1 ) ) )"]; 
     1572                DOMHTMLElement *body = [(DOMHTMLDocument *)[[display mainFrame] DOMDocument] body]; 
     1573 
     1574                unsigned int i = 0; 
     1575                if( ! subsequent ) { // append message normally 
     1576                        [[replaceElement parentNode] removeChild:replaceElement]; 
     1577                        while( [[element children] length] ) // append all children 
     1578                                [body appendChild:[element firstChild]]; 
     1579                } else if( [[element children] length] >= 1 ) { // append as a subsequent message 
     1580                        DOMNode *parent = [replaceElement parentNode]; 
     1581                        DOMNode *nextSib = [replaceElement nextSibling]; 
     1582                        [parent replaceChild:[element firstChild] :replaceElement]; // replaces the consecutiveInsert node 
     1583                        while( [[element children] length] ) { // append all remaining children (in reverse order) 
     1584                                if( nextSib ) [parent insertBefore:[element firstChild] :nextSib]; 
     1585                                else [parent appendChild:[element firstChild]]; 
     1586                        } 
     1587                } 
     1588 
     1589                // enforce the scrollback limit 
     1590                if( scrollbackLimit > 0 && [[body children] length] > scrollbackLimit ) 
     1591                        for( i = 0; [[body children] length] > scrollbackLimit && i < ( [[body children] length] - scrollbackLimit ); i++ ) 
     1592                                [body removeChild:[[body children] item:0]];             
     1593 
     1594                // scroll down if we need to 
     1595                if( [scrollNeeded boolValue] ) [self scrollToBottom]; 
     1596#endif 
     1597        } else { // old JavaScript method 
     1598                NSMutableString *transformedMessage = [html mutableCopy]; 
     1599                [transformedMessage escapeCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"\\\"'"]]; 
     1600                [transformedMessage replaceOccurrencesOfString:@"\n" withString:@"\\n" options:NSLiteralSearch range:NSMakeRange( 0, [transformedMessage length] )]; 
     1601                [transformedMessage replaceOccurrencesOfString:@"  " withString:@"&nbsp; " options:NSLiteralSearch range:NSMakeRange( 0, [transformedMessage length] )]; 
     1602                [transformedMessage replaceOccurrencesOfString:@"<?message type=\"subsequent\"?>" withString:@"" options:NSLiteralSearch range:NSMakeRange( 0, [transformedMessage length] )]; 
     1603                if( subsequent ) [display stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"scrollBackLimit = %d; appendConsecutiveMessage( \"%@\" );", scrollbackLimit, transformedMessage]]; 
     1604                else [display stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"scrollBackLimit = %d; appendMessage( \"%@\" );", scrollbackLimit, transformedMessage]]; 
     1605                [transformedMessage release]; 
     1606        } 
    15231607} 
    15241608 
     
    17551839                [self addEventMessageToDisplay:[NSString stringWithFormat:NSLocalizedString( @"You have set yourself away with \"%@\".", "self away status set message" ), msgString] withName:@"awaySet" andAttributes:[NSDictionary dictionaryWithObjectsAndKeys:messageString, @"away-message", nil]]; 
    17561840 
    1757                 unsigned int messageCount = [[display stringByEvaluatingJavaScriptFromString:@"scrollBackMessageCount();"] intValue]; 
    1758                 unsigned long loc = [[display stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"locationOfElementByIndex( %d );", ( messageCount - 1 )]] intValue]; 
     1841                unsigned int messageCount = 0; 
     1842                unsigned long loc = 0; 
     1843 
     1844                if( [[display mainFrame] respondsToSelector:@selector( DOMDocument )] ) { 
     1845#ifdef _WEB_SCRIPT_OBJECT_H_ 
     1846                        messageCount = [[[(DOMHTMLDocument *)[[display mainFrame] DOMDocument] body] children] length]; 
     1847                        loc = [self locationOfElementByIndex:( messageCount - 1 )]; 
     1848#endif 
     1849                } else { 
     1850                        messageCount = [[display stringByEvaluatingJavaScriptFromString:@"scrollBackMessageCount();"] intValue]; 
     1851                        loc = [[display stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"locationOfElementByIndex( %d );", ( messageCount - 1 )]] intValue]; 
     1852                } 
     1853 
    17591854                [(JVMarkedScroller *)[[[[[display mainFrame] frameView] documentView] enclosingScrollView] verticalScroller] startShadedAreaAt:loc]; 
    17601855        } else { 
    17611856                [self addEventMessageToDisplay:NSLocalizedString( @"You have returned from away.", "self away status removed message" ) withName:@"awayRemoved" andAttributes:nil]; 
    17621857 
    1763                 unsigned int messageCount = [[display stringByEvaluatingJavaScriptFromString:@"scrollBackMessageCount();"] intValue]; 
    1764                 unsigned long loc = [[display stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"locationOfElementByIndex( %d );", ( messageCount - 1 )]] intValue]; 
     1858                unsigned int messageCount = 0; 
     1859                unsigned long loc = 0; 
     1860 
     1861                if( [[display mainFrame] respondsToSelector:@selector( DOMDocument )] ) { 
     1862#ifdef _WEB_SCRIPT_OBJECT_H_ 
     1863                        messageCount = [[[(DOMHTMLDocument *)[[display mainFrame] DOMDocument] body] children] length]; 
     1864                        loc = [self locationOfElementByIndex:( messageCount - 1 )]; 
     1865#endif 
     1866                } else { 
     1867                        messageCount = [[display stringByEvaluatingJavaScriptFromString:@"scrollBackMessageCount();"] intValue]; 
     1868                        loc = [[display stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"locationOfElementByIndex( %d );", ( messageCount - 1 )]] intValue]; 
     1869                } 
     1870 
    17651871                [(JVMarkedScroller *)[[[[[display mainFrame] frameView] documentView] enclosingScrollView] verticalScroller] stopShadedAreaAt:loc]; 
    17661872        }