bplist00_WebMainResource_WebSubresources_WebSubframeArchives ^WebResourceURL_WebResourceTextEncodingName_WebResourceMIMEType_WebResourceData_WebResourceFrameName_6http://www.cnn.com/2009/US/09/11/us.sept.11/index.htmlUUTF-8Ytext/htmlO Obama on 9/11: 'No words can ease the ache of your hearts' - CNN.com Skip to main content
/US
Latest in news and entertainment. Join the chat.

Obama on 9/11: 'No words can ease the ache of your hearts'

  • Story Highlights
  • Obama: "Let us renew our resolve against those who perpetrated this violent act"
  • Family, friends of those killed in attacks read names in solemn roll calls
  • Services take place in New York, at the Pentagon and in Shanksville, Pennsylvania
updated 1 hour, 9 minutes ago
  • Next Article in U.S. »
Decrease font Decrease font
Enlarge font Enlarge font

NEW YORK (CNN) -- President Obama spoke at the Pentagon on Friday to those who lost loved ones on September 11, 2001, telling them no words would heal their pain yet calling for a renewed resolve against the ones who attacked the country eight years ago.

President Obama addresses family members and friends who lost loved ones on September 11, 2001.

President Obama addresses family members and friends who lost loved ones on September 11, 2001.

Click to view previous image
1 of 3
Click to view next image

Obama laid a wreath of white flowers at the Pentagon, where 184 people lost their lives when a hijacked jet smashed into the military icon outside the nation's capital.

"No words can ease the ache of your hearts," Obama told a crowd of relatives and friends standing under umbrellas in a steady rain. The plane, American Airlines Flight 77, struck the Pentagon's west wall.

Earlier in the day, the president and first lady Michelle Obama held a moment of silence outside the White House to mark the eighth anniversary of the al Qaeda attacks that killed 2,752 people.

At the Pentagon, Obama was introduced by Defense Secretary Robert Gates, who spoke of the "great pinnacle of sacrifice" shown that day.

"Eight Septembers have come and gone," Obama said. "Nearly 3,000 days have passed, almost one for each one who has been taken from us.

"We recall the beauty and meaning of their lives," he said. "No passage of time, no dark skies can dull the meaning of that moment.

"Let us renew our resolve against those who perpetrated this violent act," Obama said.

The nation paused at the moments when the planes crashed into the World Trade Center towers and the Pentagon -- symbols of America's financial and military might -- and at a field near Shanksville, Pennsylvania. Officials believe that plane's target was either the White House or the Capitol.

There was silence at the site of the former World Trade Center at 8:46 a.m., the time the first plane struck the North Tower, followed by another at 9:03 a.m. when a jet struck the South Tower.
iReport.com: 9/11 emotions surge back in sculpted tributes, memories on video

Family members and friends of those killed read their names in solemn roll calls at each site as bells tolled.

In London, England, U.S. Ambassador Louis Susman and his wife, Marjorie, laid a wreath at the September 11 Memorial Garden in Grosvenor Square.

At ground zero in New York, a woman whose husband worked on the 94th floor of one of the twin towers recalled that day.

"The pain can still be so sharp. ... I realize how much my life has changed," she said, mentioning that her children have now grown and she has grandchildren.

Her husband left many lessons, she said, including "the courage to be kind."

Just before the first moment of silence, New York City Mayor Michael Bloomberg praised the newly established September 11 National Day of Service and Remembrance, designated by Obama.

"Appropriately, the city of New York has taken up that call. From this day forward we will guard the memories of those who died by rekindling the spirit of service and help keep us strong," Bloomberg said.

At the Web site set up for that day, people were listing their charitable acts.

One man who spoke to the crowd at ground zero remembered his brother, a partner at a law firm near the twin towers and a longtime volunteer firefighter. He rushed "toward the inferno," to do what he could to help, the brother said.

"He was there when the tower collapsed."

Near Shanksville, people gathered at a field where the 40 passengers and crew of United Airlines Flight 93 died. The passengers and crew, aware of the fate of other hijacked planes, fought the men who had taken control of their aircraft, leading to its crash.

Former Secretary of State Colin Powell gave the keynote address at the 2,200-acre site, where a $58 million memorial is scheduled to open in 2011, on the 10th anniversary of the attacks.

More than 1 million people already have visited the field, Powell said.

No one could capture the terror the 40 people aboard Flight 93 must have endured, Powell said. They were strangers to each other who "represented the very best diversity that is America," he said.

"In place of fear, they found the courage of attack," he said. "They seized the moment, and they lost their lives in so doing. We are here to ... honor their spirits."

advertisement

Their sacrifice prevented thousands of families from suffering losses, he said.

"We will always rebuild," he said. "We will always go after those responsible."

All About Barack ObamaColin Powell

  • E-mail
  • Save
  • Print
Quick Job Search
keyword(s):
enter city:
Home  |  World  |  U.S.  |  Politics  |  Crime  |  Entertainment  |  Health  |  Tech  |  Travel  |  Living  |  Business  |  Sports  |  Time.com
© 2009 Cable News Network. Turner Broadcasting System, Inc. All Rights Reserved.
Pj#'+/37;?CGKOSW[_dgkosvz #'+/37;?CGKOSW[_eilpsw{_WebResourceResponse_4http://i.cdn.turner.com/cnn/.element/js/2.0/frame.jsO bplist00 X$versionT$topY$archiverX$objects_WebResourceResponse_NSKeyedArchiver &,-345MNOPQRSTUVWXYZ[\]^_cdU$null  !"#$%V$classR$3R$8S$10S$11R$5R$6R$4R$7R$2R$9R$0R$1 '()$+WNS.base[NS.relative_4http://i.cdn.turner.com/cnn/.element/js/2.0/frame.js./01X$classesZ$classname12UNSURLXNSObject#AZgNt 6789CWNS.keysZNS.objects:;<=>?@AB DEFGHIJKL]Cache-ControlWExpires]Accept-Ranges\Content-TypeVServer^Content-LengthTDateZConnection]Last-Modified\max-age=3600_Fri, 11 Sep 2009 17:30:44 GMTUbytes_application/x-javascriptVApacheS623_Fri, 11 Sep 2009 17:24:55 GMTZkeep-alive_Thu, 11 Jun 2009 12:31:10 GMT./`aab2_NSMutableDictionary\NSDictionaryo./effg2_NSHTTPURLResponse]NSURLResponse)27:PRd  CHQ\_enwy$2?_e "h0_application/x-javascriptOofunction CNN_extractHost(url) { var returnArry = /^(?:[^:\/?#]+):\/\/([^\/?#]+)(?::\d+)?(?:[^?#]*)\//i.exec(url); if(returnArry && typeof returnArry === "object") { return returnArry[1]; } else { return ""; } } function CNN_bustFrame(){ var blacklist = ['digg.com']; if (top.location!=window.location) { var topURL = CNN_extractHost(document.referrer); if (topURL) { for (var i=0; i < blacklist.length; i++) { if (topURL.indexOf( blacklist[i] ) != -1) { top.location.replace(window.location); return; } } } } } CNN_bustFrame(); _7http://i.cdn.turner.com/cnn/.element/js/2.0/ad_head0.jsO$bplist00 X$versionT$topY$archiverX$objects_WebResourceResponse_NSKeyedArchiver &,-345MNOPQRSTUVWXYZ[\]^_cdU$null  !"#$%V$classR$3R$8S$10S$11R$5R$6R$4R$7R$2R$9R$0R$1 '()$+WNS.base[NS.relative_7http://i.cdn.turner.com/cnn/.element/js/2.0/ad_head0.js./01X$classesZ$classname12UNSURLXNSObject#AZgd 6789CWNS.keysZNS.objects:;<=>?@AB DEFGHIJKL]Cache-ControlWExpires]Accept-Ranges\Content-TypeVServer^Content-LengthTDateZConnection]Last-Modified\max-age=3600_Fri, 11 Sep 2009 17:50:18 GMTUbytes_application/x-javascriptVApacheT4759_Fri, 11 Sep 2009 17:24:55 GMTZkeep-alive_Mon, 27 Apr 2009 18:11:07 GMT./`aab2_NSMutableDictionary\NSDictionary./effg2_NSHTTPURLResponse]NSURLResponse)27:PRd  FKT_bhqz|'5Bbh &h4Ofunction CNN_getCookies() { var hash = new Array; if ( document.cookie ) { var cookies = document.cookie.split( '; ' ); for ( var i = 0; i < cookies.length; i++ ) { var namevaluePairs = cookies[i].split( '=' ); hash[namevaluePairs[0]] = unescape( namevaluePairs[1] ) || null; } } return hash; } function CNN_parseCookieData( cookieDataString ) { var cookieValues = new Object(); var separatePairs = cookieDataString.split( '&' ); for ( var i = 0; i < separatePairs.length; i++ ) { var separateValues = separatePairs[i].split( ':' ); cookieValues[separateValues[0]] = separateValues[1] || null; } return cookieValues; } // default values var adHeadOffset = 0; var adHeadClass = "us.low"; var allCookies = CNN_getCookies(); var adHeadCookie = allCookies[ "Target" ] || null; var isClassAndOffsetValid = false; var alreadySwappedTargetImage = false; var alreadySwappedCookieCrumb = false; if ( adHeadCookie ) { // got milk? var adHeadHash = CNN_parseCookieData( adHeadCookie ); //alert("o=" + adHeadHash[ "o" ] + "\nclass=" + adHeadHash[ "class"]); if ( adHeadHash[ "o" ] && adHeadHash[ "class" ] ) { var validClassesAndOffsets = [ 'us.low', 0, 'us.high', 1, 'intl', 2, 'intl', 3, 'us.edu', 0, 'us.gov', 0, 'us.mil', 0, 'us.org', 0 ]; for ( var i = 0; i < validClassesAndOffsets.length; i+=2 ) { if ( validClassesAndOffsets[i] == adHeadHash[ "class" ] && validClassesAndOffsets[i+1] == adHeadHash[ "o" ] ) { isClassAndOffsetValid = true; break; } } } if ( isClassAndOffsetValid ) { adHeadOffset = adHeadHash[ "o" ]; adHeadClass = adHeadHash[ "class" ]; } } function getCookieCrumb( imageRef ) { var cnnCookie = allCookies[ "CNNid" ]; if ( cnnCookie && cnnCookie.charAt( 0 ) === 'G' ) { // it's all good, you already got a cookie } else if ( !alreadySwappedCookieCrumb ) { imageRef.src = "http://cnn.dyn.cnn.com/cookie.crumb"; alreadySwappedCookieCrumb = true; } } document.adoffset = adHeadOffset; //alert( "GLOBAL\nalreadySwappedTargetImage=" + alreadySwappedTargetImage + "\nisClassAndOffsetValid=" + isClassAndOffsetValid ); function getAdHeadCookie( imageRef ) { //alert( "isClassAndOffsetValid=" + isClassAndOffsetValid + "\nadHeadOffset=" + adHeadOffset + "\nadHeadClass=" + adHeadClass); var newSrc = "http://cnn.dyn.cnn.com/1.gif?" + new Date().getTime(); if ( !alreadySwappedTargetImage && !isClassAndOffsetValid && (typeof WM_browserAcceptsCookies != "undefined") && WM_browserAcceptsCookies() ) { //alert( "getAdHeadCookie\nalreadySwappedTargetImage=" + alreadySwappedTargetImage + "\nisClassAndOffsetValid=" + isClassAndOffsetValid ); imageRef.src = newSrc; alreadySwappedTargetImage = true; } } var alreadySwappedDETargetImage = false; var cnnDEadDEonCookie = false; var cnnU_Country = ''; var cnnAdDE_UVal = 'R00'; function WM_readCookie( name ) { if ( document.cookie == '' ) { // there's no cookie, so go no further return false; } else { // there is a cookie var firstChar, lastChar; var theBigCookie = document.cookie; firstChar = theBigCookie.indexOf(name); // find the start of 'name' var NN2Hack = firstChar + name.length; if ( (firstChar != -1) && (theBigCookie.charAt(NN2Hack) == '=') ) { // if you found the cookie firstChar += name.length + 1; // skip 'name' and '=' lastChar = theBigCookie.indexOf(';', firstChar); // Find the end of the value string (i.e. the next ';'). if (lastChar == -1) lastChar = theBigCookie.length; return unescape( theBigCookie.substring(firstChar, lastChar) ); } else { // If there was no cookie of that name, return false. return false; } } } // WM_readCookie function getDEAdHeadCookie( imageRef ) { //if (typeof(WM_readCookie) != "undefined") { cnnDEadDEonCookie = allCookies['adDEon']; //} var newSrc = "http://gdyn.cnn.com/1.1/1.gif?" + new Date().getTime(); if ( !alreadySwappedDETargetImage && !cnnDEadDEonCookie) { imageRef.src = newSrc; alreadySwappedDETargetImage = true; } else if((alreadySwappedDETargetImage || WM_readCookie('adDEmas')) && !cnnUserEd_Pref) { if(WM_readCookie('adDEmas')) { cnnU_Country = WM_readCookie('adDEmas').split('&')[0]; } if(cnnU_Country && (cnnU_Country != cnnAdDE_UVal) && (cnnU_Country != '-')) { CNN_setCookie('SelectedEdition', 'edition', 854400, '/', '.cnn.com'); if(cnnOn_Dom_Flag) { document.getElementById('cnnsetPref_Form').edition[1].checked = true; } else { document.getElementById('cnnsetPref_Form').edition[0].checked = true; } } else { CNN_setCookie('SelectedEdition', 'www', 854400, '/', '.cnn.com'); if(cnnOn_Dom_Flag) { document.getElementById('cnnsetPref_Form').edition[0].checked = true; } else { document.getElementById('cnnsetPref_Form').edition[1].checked = true; } } } } _8http://i.cdn.turner.com/cnn/cnn_adspaces/cnn_adspaces.jsO&bplist00 X$versionT$topY$archiverX$objects_WebResourceResponse_NSKeyedArchiver &,-345MNOPQRSTUVWXYZ[\]^_cdU$null  !"#$%V$classR$3R$8S$10S$11R$5R$6R$4R$7R$2R$9R$0R$1 '()$+WNS.base[NS.relative_8http://i.cdn.turner.com/cnn/cnn_adspaces/cnn_adspaces.js./01X$classesZ$classname12UNSURLXNSObject#AZgqrG 6789CWNS.keysZNS.objects:;<=>?@AB DEFGHIJKL]Cache-ControlWExpires]Accept-Ranges\Content-TypeVServer^Content-LengthTDateZConnection]Last-Modified\max-age=3600_Fri, 11 Sep 2009 17:38:42 GMTUbytes_application/x-javascriptVApacheU15719_Fri, 11 Sep 2009 17:24:55 GMTZkeep-alive_Thu, 25 Jun 2009 14:25:21 GMT./`aab2_NSMutableDictionary\NSDictionary=g./effg2_NSHTTPURLResponse]NSURLResponse)27:PRd  GLU`cir{} (6Cci (h6O=gvar cnnad_tileID = cnnad_getID(); var cnnad_enabled = true; var cnnad_adIframes = new Array(); var cnnad_adVault = new Array(); var cnnad_adCache = new Array(); var cnnad_interstitialPID = null; var cnnad_interstitialPlaying = false; // flag for geo targetting image var alreadySwappedDETargetImage = false; var cnnDEadDEonCookie = false; // document domain security issues var cnnDocDomain = cnnad_getTld(location.hostname); if(cnnDocDomain) {document.domain = cnnDocDomain;} //ADM send functionality //pagemodes - 1(all tags) - DM_cat(), DM_addToLoc(), DM_tag(); //pagemodes - 2(health) - DM_tag(); //pagemodes - 3(none); var cnnad_pageMode = 1; var cnnad_calledURLs = new Array(); //associative array var cnnad_successfulSend = 0; var cnnad_resultArray = new Array(); function cnnad_sendADMData() { var cnnad_ADMSizes = new Array(); var finalExpression = ""; cnnad_ADMSizes = ["728x90","300x250","336x280","160x600"]; for(as=0;as \n '; if(cnnad_pageMode == 1){ finalExpression += ' A09801.DM_cat("'; var site = cnnad_getParamValue(calledURL, "site=","&"); var rollup = cnnad_getParamValue(calledURL, "_rollup=","&"); var section = cnnad_getParamValue(calledURL, "_section=","&"); var subsection = cnnad_getParamValue(calledURL, "_subsection=","&"); finalExpression += site; if((site!="") && ((rollup!="") || (section!="") || (subsection!=""))){ finalExpression += " > "; } finalExpression += rollup; if((rollup!="") && ((section!="") || (subsection!=""))){ finalExpression += " > "; } finalExpression += section; if((section!="") && (subsection!="")){ finalExpression += " > "; } finalExpression += subsection; finalExpression += '"); \n '; finalExpression += ' A09801.DM_addEncToLoc(); \n '; } finalExpression += ' A09801.DM_tag(); \n '; finalExpression += ' \n '; document.write(finalExpression); } cnnad_successfulSend = 1; break; } } } //DYNAMIC TYLEID var cnnad_adTileIDGroup = new Array(); var cnnad_newTileIDIteration = 0; function cnnad_newTileIDGroup(newGroupArray) { var newTileID = (cnnad_tileID * 1 + (++cnnad_newTileIDIteration)); for (var i = 0; i < newGroupArray.length; i++) { cnnad_adTileIDGroup[cnnad_adTileIDGroup.length] = {tileID:newTileID, adName:newGroupArray[i]}; } } function cnnad_getDynamicTileID(adURL) { var returnId = cnnad_tileID; if(cnnad_adTileIDGroup.length > 0){ var ad_position = cnnad_getParamValue(adURL, '_position=', "&"); for (var i = 0; i < cnnad_adTileIDGroup.length; i++) { var adName = cnnad_adTileIDGroup[i].adName; if(ad_position == adName){ returnId = cnnad_adTileIDGroup[i].tileID; break; } } } return returnId; } //END DYNAMIC TYLEID function cnnad_getParamValue(paramString, parameter, endCharacter){ if(paramString.match(parameter)){ var startOfString = paramString.indexOf(parameter)+parameter.length; var endOfString = paramString.indexOf(endCharacter,startOfString); var parameterValue = paramString.substring(startOfString,endOfString); return parameterValue; } else{ return ""; } } // end ADM send functionality function cnnad_debug (m) { if (typeof(console) != 'undefined' && typeof(console.debug) != 'undefined') { console.debug(m); } } function cnnad_error (m) { if (typeof(console) != 'undefined' && typeof(console.error) != 'undefined') { console.error(m); } } function cnnad_reverseString (input) { // convert everything to a string input = "" + input; var output = ''; if (input.length) { var i; for (i = input.length; i > 0; i--) { output += input.charAt(i-1); } } return(output); } function cnnad_getID() { return (cnnad_reverseString(new Date().getTime())); } function cnnad_renderAd(cnnad_url) { if(cnnad_enabled == true) { document.write("'); }, load: function() { if((typeof Prototype=='undefined') || (typeof Element == 'undefined') || (typeof Element.Methods=='undefined') || parseFloat(Prototype.Version.split(".")[0] + "." + Prototype.Version.split(".")[1]) < 1.5) throw("script.aculo.us requires the Prototype JavaScript framework >= 1.5.0"); $A(document.getElementsByTagName("script")).findAll( function(s) { return (s.src && s.src.match(/scriptaculous\.js(\?.*)?$/)) }).each( function(s) { var path = s.src.replace(/scriptaculous\.js(\?.*)?$/,''); var includes = s.src.match(/\?.*load=([a-z,]*)/); (includes ? includes[1] : 'builder,effects,dragdrop,controls,slider').split(',').each( function(include) { Scriptaculous.require(path+include+'.js') }); }); } } Scriptaculous.load();012_>http://i.cdn.turner.com/cnn/.element/js/2.0/scripts/effects.jsO,bplist00 X$versionT$topY$archiverX$objects_WebResourceResponse_NSKeyedArchiver &,-345MNOPQRSTUVWXYZ[\]^_cdU$null  !"#$%V$classR$3R$8S$10S$11R$5R$6R$4R$7R$2R$9R$0R$1 '()$+WNS.base[NS.relative_>http://i.cdn.turner.com/cnn/.element/js/2.0/scripts/effects.js./01X$classesZ$classname12UNSURLXNSObject#AZeh< 6789CWNS.keysZNS.objects:;<=>?@AB DEFGHIJKL]Cache-ControlWExpires]Accept-Ranges\Content-TypeVServer^Content-LengthTDateZConnection]Last-Modified\max-age=3600_Fri, 11 Sep 2009 18:08:25 GMTUbytes_application/x-javascriptVApacheU37872_Fri, 11 Sep 2009 17:24:53 GMTZkeep-alive_Fri, 04 Jan 2008 00:40:43 GMT./`aab2_NSMutableDictionary\NSDictionary./effg2_NSHTTPURLResponse]NSURLResponse)27:PRd  MR[fiox#.<Iio.h0) window.scrollBy(0,0); return element; } Element.getOpacity = function(element){ return $(element).getStyle('opacity'); } Element.setOpacity = function(element, value){ return $(element).setStyle({opacity:value}); } Element.getInlineOpacity = function(element){ return $(element).style.opacity || ''; } Element.forceRerendering = function(element) { try { element = $(element); var n = document.createTextNode(' '); element.appendChild(n); element.removeChild(n); } catch(e) { } }; /*--------------------------------------------------------------------------*/ Array.prototype.call = function() { var args = arguments; this.each(function(f){ f.apply(this, args) }); } /*--------------------------------------------------------------------------*/ var Effect = { _elementDoesNotExistError: { name: 'ElementDoesNotExistError', message: 'The specified DOM element does not exist, but is required for this effect to operate' }, tagifyText: function(element) { if(typeof Builder == 'undefined') throw("Effect.tagifyText requires including script.aculo.us' builder.js library"); var tagifyStyle = 'position:relative'; if(/MSIE/.test(navigator.userAgent) && !window.opera) tagifyStyle += ';zoom:1'; element = $(element); $A(element.childNodes).each( function(child) { if(child.nodeType==3) { child.nodeValue.toArray().each( function(character) { element.insertBefore( Builder.node('span',{style: tagifyStyle}, character == ' ' ? String.fromCharCode(160) : character), child); }); Element.remove(child); } }); }, multiple: function(element, effect) { var elements; if(((typeof element == 'object') || (typeof element == 'function')) && (element.length)) elements = element; else elements = $(element).childNodes; var options = Object.extend({ speed: 0.1, delay: 0.0 }, arguments[2] || {}); var masterDelay = options.delay; $A(elements).each( function(element, index) { new effect(element, Object.extend(options, { delay: index * options.speed + masterDelay })); }); }, PAIRS: { 'slide': ['SlideDown','SlideUp'], 'blind': ['BlindDown','BlindUp'], 'appear': ['Appear','Fade'] }, toggle: function(element, effect) { element = $(element); effect = (effect || 'appear').toLowerCase(); var options = Object.extend({ queue: { position:'end', scope:(element.id || 'global'), limit: 1 } }, arguments[2] || {}); Effect[element.visible() ? Effect.PAIRS[effect][1] : Effect.PAIRS[effect][0]](element, options); } }; var Effect2 = Effect; // deprecated /* ------------- transitions ------------- */ Effect.Transitions = { linear: Prototype.K, sinoidal: function(pos) { return (-Math.cos(pos*Math.PI)/2) + 0.5; }, reverse: function(pos) { return 1-pos; }, flicker: function(pos) { return ((-Math.cos(pos*Math.PI)/4) + 0.75) + Math.random()/4; }, wobble: function(pos) { return (-Math.cos(pos*Math.PI*(9*pos))/2) + 0.5; }, pulse: function(pos, pulses) { pulses = pulses || 5; return ( Math.round((pos % (1/pulses)) * pulses) == 0 ? ((pos * pulses * 2) - Math.floor(pos * pulses * 2)) : 1 - ((pos * pulses * 2) - Math.floor(pos * pulses * 2)) ); }, none: function(pos) { return 0; }, full: function(pos) { return 1; } }; /* ------------- core effects ------------- */ Effect.ScopedQueue = Class.create(); Object.extend(Object.extend(Effect.ScopedQueue.prototype, Enumerable), { initialize: function() { this.effects = []; this.interval = null; }, _each: function(iterator) { this.effects._each(iterator); }, add: function(effect) { var timestamp = new Date().getTime(); var position = (typeof effect.options.queue == 'string') ? effect.options.queue : effect.options.queue.position; switch(position) { case 'front': // move unstarted effects after this effect this.effects.findAll(function(e){ return e.state=='idle' }).each( function(e) { e.startOn += effect.finishOn; e.finishOn += effect.finishOn; }); break; case 'with-last': timestamp = this.effects.pluck('startOn').max() || timestamp; break; case 'end': // start effect after last queued effect has finished timestamp = this.effects.pluck('finishOn').max() || timestamp; break; } effect.startOn += timestamp; effect.finishOn += timestamp; if(!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit)) this.effects.push(effect); if(!this.interval) this.interval = setInterval(this.loop.bind(this), 15); }, remove: function(effect) { this.effects = this.effects.reject(function(e) { return e==effect }); if(this.effects.length == 0) { clearInterval(this.interval); this.interval = null; } }, loop: function() { var timePos = new Date().getTime(); for(var i=0, len=this.effects.length;i= this.startOn) { if(timePos >= this.finishOn) { this.render(1.0); this.cancel(); this.event('beforeFinish'); if(this.finish) this.finish(); this.event('afterFinish'); return; } var pos = (timePos - this.startOn) / (this.finishOn - this.startOn); var frame = Math.round(pos * this.options.fps * this.options.duration); if(frame > this.currentFrame) { this.render(pos); this.currentFrame = frame; } } }, render: function(pos) { if(this.state == 'idle') { this.state = 'running'; this.event('beforeSetup'); if(this.setup) this.setup(); this.event('afterSetup'); } if(this.state == 'running') { if(this.options.transition) pos = this.options.transition(pos); pos *= (this.options.to-this.options.from); pos += this.options.from; this.position = pos; this.event('beforeUpdate'); if(this.update) this.update(pos); this.event('afterUpdate'); } }, cancel: function() { if(!this.options.sync) Effect.Queues.get(typeof this.options.queue == 'string' ? 'global' : this.options.queue.scope).remove(this); this.state = 'finished'; }, event: function(eventName) { if(this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this); if(this.options[eventName]) this.options[eventName](this); }, inspect: function() { var data = $H(); for(property in this) if(typeof this[property] != 'function') data[property] = this[property]; return '#'; } } Effect.Parallel = Class.create(); Object.extend(Object.extend(Effect.Parallel.prototype, Effect.Base.prototype), { initialize: function(effects) { this.effects = effects || []; this.start(arguments[1]); }, update: function(position) { this.effects.invoke('render', position); }, finish: function(position) { this.effects.each( function(effect) { effect.render(1.0); effect.cancel(); effect.event('beforeFinish'); if(effect.finish) effect.finish(position); effect.event('afterFinish'); }); } }); Effect.Event = Class.create(); Object.extend(Object.extend(Effect.Event.prototype, Effect.Base.prototype), { initialize: function() { var options = Object.extend({ duration: 0 }, arguments[0] || {}); this.start(options); }, update: Prototype.emptyFunction }); Effect.Opacity = Class.create(); Object.extend(Object.extend(Effect.Opacity.prototype, Effect.Base.prototype), { initialize: function(element) { this.element = $(element); if(!this.element) throw(Effect._elementDoesNotExistError); // make this work on IE on elements without 'layout' if(/MSIE/.test(navigator.userAgent) && !window.opera && (!this.element.currentStyle.hasLayout)) this.element.setStyle({zoom: 1}); var options = Object.extend({ from: this.element.getOpacity() || 0.0, to: 1.0 }, arguments[1] || {}); this.start(options); }, update: function(position) { this.element.setOpacity(position); } }); Effect.Move = Class.create(); Object.extend(Object.extend(Effect.Move.prototype, Effect.Base.prototype), { initialize: function(element) { this.element = $(element); if(!this.element) throw(Effect._elementDoesNotExistError); var options = Object.extend({ x: 0, y: 0, mode: 'relative' }, arguments[1] || {}); this.start(options); }, setup: function() { // Bug in Opera: Opera returns the "real" position of a static element or // relative element that does not have top/left explicitly set. // ==> Always set top and left for position relative elements in your stylesheets // (to 0 if you do not need them) this.element.makePositioned(); this.originalLeft = parseFloat(this.element.getStyle('left') || '0'); this.originalTop = parseFloat(this.element.getStyle('top') || '0'); if(this.options.mode == 'absolute') { // absolute movement, so we need to calc deltaX and deltaY this.options.x = this.options.x - this.originalLeft; this.options.y = this.options.y - this.originalTop; } }, update: function(position) { this.element.setStyle({ left: Math.round(this.options.x * position + this.originalLeft) + 'px', top: Math.round(this.options.y * position + this.originalTop) + 'px' }); } }); // for backwards compatibility Effect.MoveBy = function(element, toTop, toLeft) { return new Effect.Move(element, Object.extend({ x: toLeft, y: toTop }, arguments[3] || {})); }; Effect.Scale = Class.create(); Object.extend(Object.extend(Effect.Scale.prototype, Effect.Base.prototype), { initialize: function(element, percent) { this.element = $(element); if(!this.element) throw(Effect._elementDoesNotExistError); var options = Object.extend({ scaleX: true, scaleY: true, scaleContent: true, scaleFromCenter: false, scaleMode: 'box', // 'box' or 'contents' or {} with provided values scaleFrom: 100.0, scaleTo: percent }, arguments[2] || {}); this.start(options); }, setup: function() { this.restoreAfterFinish = this.options.restoreAfterFinish || false; this.elementPositioning = this.element.getStyle('position'); this.originalStyle = {}; ['top','left','width','height','fontSize'].each( function(k) { this.originalStyle[k] = this.element.style[k]; }.bind(this)); this.originalTop = this.element.offsetTop; this.originalLeft = this.element.offsetLeft; var fontSize = this.element.getStyle('font-size') || '100%'; ['em','px','%','pt'].each( function(fontSizeType) { if(fontSize.indexOf(fontSizeType)>0) { this.fontSize = parseFloat(fontSize); this.fontSizeType = fontSizeType; } }.bind(this)); this.factor = (this.options.scaleTo - this.options.scaleFrom)/100; this.dims = null; if(this.options.scaleMode=='box') this.dims = [this.element.offsetHeight, this.element.offsetWidth]; if(/^content/.test(this.options.scaleMode)) this.dims = [this.element.scrollHeight, this.element.scrollWidth]; if(!this.dims) this.dims = [this.options.scaleMode.originalHeight, this.options.scaleMode.originalWidth]; }, update: function(position) { var currentScale = (this.options.scaleFrom/100.0) + (this.factor * position); if(this.options.scaleContent && this.fontSize) this.element.setStyle({fontSize: this.fontSize * currentScale + this.fontSizeType }); this.setDimensions(this.dims[0] * currentScale, this.dims[1] * currentScale); }, finish: function(position) { if(this.restoreAfterFinish) this.element.setStyle(this.originalStyle); }, setDimensions: function(height, width) { var d = {}; if(this.options.scaleX) d.width = Math.round(width) + 'px'; if(this.options.scaleY) d.height = Math.round(height) + 'px'; if(this.options.scaleFromCenter) { var topd = (height - this.dims[0])/2; var leftd = (width - this.dims[1])/2; if(this.elementPositioning == 'absolute') { if(this.options.scaleY) d.top = this.originalTop-topd + 'px'; if(this.options.scaleX) d.left = this.originalLeft-leftd + 'px'; } else { if(this.options.scaleY) d.top = -topd + 'px'; if(this.options.scaleX) d.left = -leftd + 'px'; } } this.element.setStyle(d); } }); Effect.Highlight = Class.create(); Object.extend(Object.extend(Effect.Highlight.prototype, Effect.Base.prototype), { initialize: function(element) { this.element = $(element); if(!this.element) throw(Effect._elementDoesNotExistError); var options = Object.extend({ startcolor: '#ffff99' }, arguments[1] || {}); this.start(options); }, setup: function() { // Prevent executing on elements not in the layout flow if(this.element.getStyle('display')=='none') { this.cancel(); return; } // Disable background image during the effect this.oldStyle = {}; if (!this.options.keepBackgroundImage) { this.oldStyle.backgroundImage = this.element.getStyle('background-image'); this.element.setStyle({backgroundImage: 'none'}); } if(!this.options.endcolor) this.options.endcolor = this.element.getStyle('background-color').parseColor('#ffffff'); if(!this.options.restorecolor) this.options.restorecolor = this.element.getStyle('background-color'); // init color calculations this._base = $R(0,2).map(function(i){ return parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16) }.bind(this)); this._delta = $R(0,2).map(function(i){ return parseInt(this.options.endcolor.slice(i*2+1,i*2+3),16)-this._base[i] }.bind(this)); }, update: function(position) { this.element.setStyle({backgroundColor: $R(0,2).inject('#',function(m,v,i){ return m+(Math.round(this._base[i]+(this._delta[i]*position)).toColorPart()); }.bind(this)) }); }, finish: function() { this.element.setStyle(Object.extend(this.oldStyle, { backgroundColor: this.options.restorecolor })); } }); Effect.ScrollTo = Class.create(); Object.extend(Object.extend(Effect.ScrollTo.prototype, Effect.Base.prototype), { initialize: function(element) { this.element = $(element); this.start(arguments[1] || {}); }, setup: function() { Position.prepare(); var offsets = Position.cumulativeOffset(this.element); if(this.options.offset) offsets[1] += this.options.offset; var max = window.innerHeight ? window.height - window.innerHeight : document.body.scrollHeight - (document.documentElement.clientHeight ? document.documentElement.clientHeight : document.body.clientHeight); this.scrollStart = Position.deltaY; this.delta = (offsets[1] > max ? max : offsets[1]) - this.scrollStart; }, update: function(position) { Position.prepare(); window.scrollTo(Position.deltaX, this.scrollStart + (position*this.delta)); } }); /* ------------- combination effects ------------- */ Effect.Fade = function(element) { element = $(element); var oldOpacity = element.getInlineOpacity(); var options = Object.extend({ from: element.getOpacity() || 1.0, to: 0.0, afterFinishInternal: function(effect) { if(effect.options.to!=0) return; effect.element.hide().setStyle({opacity: oldOpacity}); }}, arguments[1] || {}); return new Effect.Opacity(element,options); } Effect.Appear = function(element) { element = $(element); var options = Object.extend({ from: (element.getStyle('display') == 'none' ? 0.0 : element.getOpacity() || 0.0), to: 1.0, // force Safari to render floated elements properly afterFinishInternal: function(effect) { effect.element.forceRerendering(); }, beforeSetup: function(effect) { effect.element.setOpacity(effect.options.from).show(); }}, arguments[1] || {}); return new Effect.Opacity(element,options); } Effect.Puff = function(element) { element = $(element); var oldStyle = { opacity: element.getInlineOpacity(), position: element.getStyle('position'), top: element.style.top, left: element.style.left, width: element.style.width, height: element.style.height }; return new Effect.Parallel( [ new Effect.Scale(element, 200, { sync: true, scaleFromCenter: true, scaleContent: true, restoreAfterFinish: true }), new Effect.Opacity(element, { sync: true, to: 0.0 } ) ], Object.extend({ duration: 1.0, beforeSetupInternal: function(effect) { Position.absolutize(effect.effects[0].element) }, afterFinishInternal: function(effect) { effect.effects[0].element.hide().setStyle(oldStyle); } }, arguments[1] || {}) ); } Effect.BlindUp = function(element) { element = $(element); element.makeClipping(); return new Effect.Scale(element, 0, Object.extend({ scaleContent: false, scaleX: false, restoreAfterFinish: true, afterFinishInternal: function(effect) { effect.element.hide().undoClipping(); } }, arguments[1] || {}) ); } Effect.BlindDown = function(element) { element = $(element); var elementDimensions = element.getDimensions(); return new Effect.Scale(element, 100, Object.extend({ scaleContent: false, scaleX: false, scaleFrom: 0, scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, restoreAfterFinish: true, afterSetup: function(effect) { effect.element.makeClipping().setStyle({height: '0px'}).show(); }, afterFinishInternal: function(effect) { effect.element.undoClipping(); } }, arguments[1] || {})); } Effect.SwitchOff = function(element) { element = $(element); var oldOpacity = element.getInlineOpacity(); return new Effect.Appear(element, Object.extend({ duration: 0.4, from: 0, transition: Effect.Transitions.flicker, afterFinishInternal: function(effect) { new Effect.Scale(effect.element, 1, { duration: 0.3, scaleFromCenter: true, scaleX: false, scaleContent: false, restoreAfterFinish: true, beforeSetup: function(effect) { effect.element.makePositioned().makeClipping(); }, afterFinishInternal: function(effect) { effect.element.hide().undoClipping().undoPositioned().setStyle({opacity: oldOpacity}); } }) } }, arguments[1] || {})); } Effect.DropOut = function(element) { element = $(element); var oldStyle = { top: element.getStyle('top'), left: element.getStyle('left'), opacity: element.getInlineOpacity() }; return new Effect.Parallel( [ new Effect.Move(element, {x: 0, y: 100, sync: true }), new Effect.Opacity(element, { sync: true, to: 0.0 }) ], Object.extend( { duration: 0.5, beforeSetup: function(effect) { effect.effects[0].element.makePositioned(); }, afterFinishInternal: function(effect) { effect.effects[0].element.hide().undoPositioned().setStyle(oldStyle); } }, arguments[1] || {})); } Effect.Shake = function(element) { element = $(element); var oldStyle = { top: element.getStyle('top'), left: element.getStyle('left') }; return new Effect.Move(element, { x: 20, y: 0, duration: 0.05, afterFinishInternal: function(effect) { new Effect.Move(effect.element, { x: -40, y: 0, duration: 0.1, afterFinishInternal: function(effect) { new Effect.Move(effect.element, { x: 40, y: 0, duration: 0.1, afterFinishInternal: function(effect) { new Effect.Move(effect.element, { x: -40, y: 0, duration: 0.1, afterFinishInternal: function(effect) { new Effect.Move(effect.element, { x: 40, y: 0, duration: 0.1, afterFinishInternal: function(effect) { new Effect.Move(effect.element, { x: -20, y: 0, duration: 0.05, afterFinishInternal: function(effect) { effect.element.undoPositioned().setStyle(oldStyle); }}) }}) }}) }}) }}) }}); } Effect.SlideDown = function(element) { element = $(element).cleanWhitespace(); // SlideDown need to have the content of the element wrapped in a container element with fixed height! var oldInnerBottom = element.down().getStyle('bottom'); var elementDimensions = element.getDimensions(); return new Effect.Scale(element, 100, Object.extend({ scaleContent: false, scaleX: false, scaleFrom: window.opera ? 0 : 1, scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, restoreAfterFinish: true, afterSetup: function(effect) { effect.element.makePositioned(); effect.element.down().makePositioned(); if(window.opera) effect.element.setStyle({top: ''}); effect.element.makeClipping().setStyle({height: '0px'}).show(); }, afterUpdateInternal: function(effect) { effect.element.down().setStyle({bottom: (effect.dims[0] - effect.element.clientHeight) + 'px' }); }, afterFinishInternal: function(effect) { effect.element.undoClipping().undoPositioned(); effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom}); } }, arguments[1] || {}) ); } Effect.SlideUp = function(element) { element = $(element).cleanWhitespace(); var oldInnerBottom = element.down().getStyle('bottom'); return new Effect.Scale(element, window.opera ? 0 : 1, Object.extend({ scaleContent: false, scaleX: false, scaleMode: 'box', scaleFrom: 100, restoreAfterFinish: true, beforeStartInternal: function(effect) { effect.element.makePositioned(); effect.element.down().makePositioned(); if(window.opera) effect.element.setStyle({top: ''}); effect.element.makeClipping().show(); }, afterUpdateInternal: function(effect) { effect.element.down().setStyle({bottom: (effect.dims[0] - effect.element.clientHeight) + 'px' }); }, afterFinishInternal: function(effect) { effect.element.hide().undoClipping().undoPositioned().setStyle({bottom: oldInnerBottom}); effect.element.down().undoPositioned(); } }, arguments[1] || {}) ); } // Bug in opera makes the TD containing this element expand for a instance after finish Effect.Squish = function(element) { return new Effect.Scale(element, window.opera ? 1 : 0, { restoreAfterFinish: true, beforeSetup: function(effect) { effect.element.makeClipping(); }, afterFinishInternal: function(effect) { effect.element.hide().undoClipping(); } }); } Effect.Grow = function(element) { element = $(element); var options = Object.extend({ direction: 'center', moveTransition: Effect.Transitions.sinoidal, scaleTransition: Effect.Transitions.sinoidal, opacityTransition: Effect.Transitions.full }, arguments[1] || {}); var oldStyle = { top: element.style.top, left: element.style.left, height: element.style.height, width: element.style.width, opacity: element.getInlineOpacity() }; var dims = element.getDimensions(); var initialMoveX, initialMoveY; var moveX, moveY; switch (options.direction) { case 'top-left': initialMoveX = initialMoveY = moveX = moveY = 0; break; case 'top-right': initialMoveX = dims.width; initialMoveY = moveY = 0; moveX = -dims.width; break; case 'bottom-left': initialMoveX = moveX = 0; initialMoveY = dims.height; moveY = -dims.height; break; case 'bottom-right': initialMoveX = dims.width; initialMoveY = dims.height; moveX = -dims.width; moveY = -dims.height; break; case 'center': initialMoveX = dims.width / 2; initialMoveY = dims.height / 2; moveX = -dims.width / 2; moveY = -dims.height / 2; break; } return new Effect.Move(element, { x: initialMoveX, y: initialMoveY, duration: 0.01, beforeSetup: function(effect) { effect.element.hide().makeClipping().makePositioned(); }, afterFinishInternal: function(effect) { new Effect.Parallel( [ new Effect.Opacity(effect.element, { sync: true, to: 1.0, from: 0.0, transition: options.opacityTransition }), new Effect.Move(effect.element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }), new Effect.Scale(effect.element, 100, { scaleMode: { originalHeight: dims.height, originalWidth: dims.width }, sync: true, scaleFrom: window.opera ? 1 : 0, transition: options.scaleTransition, restoreAfterFinish: true}) ], Object.extend({ beforeSetup: function(effect) { effect.effects[0].element.setStyle({height: '0px'}).show(); }, afterFinishInternal: function(effect) { effect.effects[0].element.undoClipping().undoPositioned().setStyle(oldStyle); } }, options) ) } }); } Effect.Shrink = function(element) { element = $(element); var options = Object.extend({ direction: 'center', moveTransition: Effect.Transitions.sinoidal, scaleTransition: Effect.Transitions.sinoidal, opacityTransition: Effect.Transitions.none }, arguments[1] || {}); var oldStyle = { top: element.style.top, left: element.style.left, height: element.style.height, width: element.style.width, opacity: element.getInlineOpacity() }; var dims = element.getDimensions(); var moveX, moveY; switch (options.direction) { case 'top-left': moveX = moveY = 0; break; case 'top-right': moveX = dims.width; moveY = 0; break; case 'bottom-left': moveX = 0; moveY = dims.height; break; case 'bottom-right': moveX = dims.width; moveY = dims.height; break; case 'center': moveX = dims.width / 2; moveY = dims.height / 2; break; } return new Effect.Parallel( [ new Effect.Opacity(element, { sync: true, to: 0.0, from: 1.0, transition: options.opacityTransition }), new Effect.Scale(element, window.opera ? 1 : 0, { sync: true, transition: options.scaleTransition, restoreAfterFinish: true}), new Effect.Move(element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }) ], Object.extend({ beforeStartInternal: function(effect) { effect.effects[0].element.makePositioned().makeClipping(); }, afterFinishInternal: function(effect) { effect.effects[0].element.hide().undoClipping().undoPositioned().setStyle(oldStyle); } }, options) ); } Effect.Pulsate = function(element) { element = $(element); var options = arguments[1] || {}; var oldOpacity = element.getInlineOpacity(); var transition = options.transition || Effect.Transitions.sinoidal; var reverser = function(pos){ return transition(1-Effect.Transitions.pulse(pos, options.pulses)) }; reverser.bind(transition); return new Effect.Opacity(element, Object.extend(Object.extend({ duration: 2.0, from: 0, afterFinishInternal: function(effect) { effect.element.setStyle({opacity: oldOpacity}); } }, options), {transition: reverser})); } Effect.Fold = function(element) { element = $(element); var oldStyle = { top: element.style.top, left: element.style.left, width: element.style.width, height: element.style.height }; element.makeClipping(); return new Effect.Scale(element, 5, Object.extend({ scaleContent: false, scaleX: false, afterFinishInternal: function(effect) { new Effect.Scale(element, 1, { scaleContent: false, scaleY: false, afterFinishInternal: function(effect) { effect.element.hide().undoClipping().setStyle(oldStyle); } }); }}, arguments[1] || {})); }; Effect.Morph = Class.create(); Object.extend(Object.extend(Effect.Morph.prototype, Effect.Base.prototype), { initialize: function(element) { this.element = $(element); if(!this.element) throw(Effect._elementDoesNotExistError); var options = Object.extend({ style: {} }, arguments[1] || {}); if (typeof options.style == 'string') { if(options.style.indexOf(':') == -1) { var cssText = '', selector = '.' + options.style; $A(document.styleSheets).reverse().each(function(styleSheet) { if (styleSheet.cssRules) cssRules = styleSheet.cssRules; else if (styleSheet.rules) cssRules = styleSheet.rules; $A(cssRules).reverse().each(function(rule) { if (selector == rule.selectorText) { cssText = rule.style.cssText; throw $break; } }); if (cssText) throw $break; }); this.style = cssText.parseStyle(); options.afterFinishInternal = function(effect){ effect.element.addClassName(effect.options.style); effect.transforms.each(function(transform) { if(transform.style != 'opacity') effect.element.style[transform.style.camelize()] = ''; }); } } else this.style = options.style.parseStyle(); } else this.style = $H(options.style) this.start(options); }, setup: function(){ function parseColor(color){ if(!color || ['rgba(0, 0, 0, 0)','transparent'].include(color)) color = '#ffffff'; color = color.parseColor(); return $R(0,2).map(function(i){ return parseInt( color.slice(i*2+1,i*2+3), 16 ) }); } this.transforms = this.style.map(function(pair){ var property = pair[0].underscore().dasherize(), value = pair[1], unit = null; if(value.parseColor('#zzzzzz') != '#zzzzzz') { value = value.parseColor(); unit = 'color'; } else if(property == 'opacity') { value = parseFloat(value); if(/MSIE/.test(navigator.userAgent) && !window.opera && (!this.element.currentStyle.hasLayout)) this.element.setStyle({zoom: 1}); } else if(Element.CSS_LENGTH.test(value)) var components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/), value = parseFloat(components[1]), unit = (components.length == 3) ? components[2] : null; var originalValue = this.element.getStyle(property); return $H({ style: property, originalValue: unit=='color' ? parseColor(originalValue) : parseFloat(originalValue || 0), targetValue: unit=='color' ? parseColor(value) : value, unit: unit }); }.bind(this)).reject(function(transform){ return ( (transform.originalValue == transform.targetValue) || ( transform.unit != 'color' && (isNaN(transform.originalValue) || isNaN(transform.targetValue)) ) ) }); }, update: function(position) { var style = $H(), value = null; this.transforms.each(function(transform){ value = transform.unit=='color' ? $R(0,2).inject('#',function(m,v,i){ return m+(Math.round(transform.originalValue[i]+ (transform.targetValue[i] - transform.originalValue[i])*position)).toColorPart() }) : transform.originalValue + Math.round( ((transform.targetValue - transform.originalValue) * position) * 1000)/1000 + transform.unit; style[transform.style] = value; }); this.element.setStyle(style); } }); Effect.Transform = Class.create(); Object.extend(Effect.Transform.prototype, { initialize: function(tracks){ this.tracks = []; this.options = arguments[1] || {}; this.addTracks(tracks); }, addTracks: function(tracks){ tracks.each(function(track){ var data = $H(track).values().first(); this.tracks.push($H({ ids: $H(track).keys().first(), effect: Effect.Morph, options: { style: data } })); }.bind(this)); return this; }, play: function(){ return new Effect.Parallel( this.tracks.map(function(track){ var elements = [$(track.ids) || $$(track.ids)].flatten(); return elements.map(function(e){ return new track.effect(e, Object.extend({ sync:true }, track.options)) }); }).flatten(), this.options ); } }); Element.CSS_PROPERTIES = $w( 'backgroundColor backgroundPosition borderBottomColor borderBottomStyle ' + 'borderBottomWidth borderLeftColor borderLeftStyle borderLeftWidth ' + 'borderRightColor borderRightStyle borderRightWidth borderSpacing ' + 'borderTopColor borderTopStyle borderTopWidth bottom clip color ' + 'fontSize fontWeight height left letterSpacing lineHeight ' + 'marginBottom marginLeft marginRight marginTop markerOffset maxHeight '+ 'maxWidth minHeight minWidth opacity outlineColor outlineOffset ' + 'outlineWidth paddingBottom paddingLeft paddingRight paddingTop ' + 'right textIndent top width wordSpacing zIndex'); Element.CSS_LENGTH = /^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/; String.prototype.parseStyle = function(){ var element = Element.extend(document.createElement('div')); element.innerHTML = '
'; var style = element.down().style, styleRules = $H(); Element.CSS_PROPERTIES.each(function(property){ if(style[property]) styleRules[property] = style[property]; }); if(/MSIE/.test(navigator.userAgent) && !window.opera && this.indexOf('opacity') > -1) { styleRules.opacity = this.match(/opacity:\s*((?:0|1)?(?:\.\d*)?)/)[1]; } return styleRules; }; Element.morph = function(element, style) { new Effect.Morph(element, Object.extend({ style: style }, arguments[2] || {})); return element; }; ['setOpacity','getOpacity','getInlineOpacity','forceRerendering','setContentZoom', 'collectTextNodes','collectTextNodesIgnoreClass','morph'].each( function(f) { Element.Methods[f] = Element[f]; } ); Element.Methods.visualEffect = function(element, effect, options) { s = effect.gsub(/_/, '-').camelize(); effect_class = s.charAt(0).toUpperCase() + s.substring(1); new Effect[effect_class](element, options); return $(element); }; Element.addMethods();456_3http://i.cdn.turner.com/cnn/.element/js/2.0/main.jsO$bplist00 X$versionT$topY$archiverX$objects_WebResourceResponse_NSKeyedArchiver &,-345MNOPQRSTUVWXYZ[\]^_cdU$null  !"#$%V$classR$3R$8S$10S$11R$5R$6R$4R$7R$2R$9R$0R$1 '()$+WNS.base[NS.relative_3http://i.cdn.turner.com/cnn/.element/js/2.0/main.js./01X$classesZ$classname12UNSURLXNSObject#AZg 6789CWNS.keysZNS.objects:;<=>?@AB DEFGHIJKL]Cache-ControlWExpires]Accept-Ranges\Content-TypeVServer^Content-LengthTDateZConnection]Last-Modified\max-age=3600_Fri, 11 Sep 2009 17:50:06 GMTUbytes_application/x-javascriptVApacheV106209_Fri, 11 Sep 2009 17:24:55 GMTZkeep-alive_Mon, 04 May 2009 17:33:04 GMT./`aab2_NSMutableDictionary\NSDictionary./effg2_NSHTTPURLResponse]NSURLResponse)27:PRd  BGP[^dmvx#1>^d &h4Ovar cnnLockToggle = false; function CNN_getCookies() { var hash = new Array; if ( document.cookie ) { var cookies = document.cookie.split( '; ' ); for ( var i = 0; i < cookies.length; i++ ) { var namevaluePairs = cookies[i].split( '=' ); hash[namevaluePairs[0]] = unescape( namevaluePairs[1] ) || null; } } return hash; } function CNN_parseCookieData( cookieDataString ) { var cookieValues = new Object(); var separatePairs = cookieDataString.split( '&' ); for ( var i = 0; i < separatePairs.length; i++ ) { var separateValues = separatePairs[i].split( ':' ); cookieValues[separateValues[0]] = separateValues[1] || null; } return cookieValues; } function CNN_setCookie( name, value, hours, path, domain, secure ) { var numHours = 0; if ( hours) { if ( (typeof(hours) == 'string') && Date.parse(hours) ) { // already a Date string numHours = hours; } else if ( typeof(hours) == 'number' ) { // calculate Date from number of hours numHours = ( new Date((new Date()).getTime() + hours*3600000) ).toGMTString(); } } document.cookie = name + '=' + escape(value) + ((numHours)?(';expires=' + numHours):'') + ((path)?';path=' + path:'') + ((domain)?';domain=' + domain:'') + ((secure && (secure == true))?'; secure':''); // Set the cookie, adding any parameters that were specified. } function CNN_killCookie( name, path, domain ) { var allCookies = CNN_getCookies(); var theValue = allCookies[ name ] || null; // We need the value to kill the cookie if ( theValue ) { document.cookie = name + '=' + theValue + '; expires=Fri, 13-Apr-1970 00:00:00 GMT' + ((path)?';path=' + path:'') + ((domain)?';domain=' + domain:''); // set an already-expired cookie } } var allCookies = CNN_getCookies(); var cnnDomainArray = location.hostname.split( '.' ); var cnnCurrDomain = ( cnnDomainArray.length > 1 ) ? '.' + cnnDomainArray[cnnDomainArray.length-2] + '.' + cnnDomainArray[cnnDomainArray.length-1] : ''; var pagetypeTS=""; function cnnRenderTimeStamp(date,timeString) { var cnnIsIntl = (location.hostname.indexOf('edition.') > -1) ? true : false; cnnStoryPublishTime = (date) ? new Date(date) : cnnStoryPublishTime; var days = new Array('Sun','Mon','Tue','Wed','Thur','Fri','Sat'); var months = new Array('January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'); var cnnTimeStampDiff = cnnCurrTime.getTime() - cnnStoryPublishTime.getTime(); var daysDifference = Math.floor(cnnTimeStampDiff/1000/60/60/24); cnnTimeStampDiff -= daysDifference*1000*60*60*24 var hoursDifference = Math.floor(cnnTimeStampDiff/1000/60/60); cnnTimeStampDiff -= hoursDifference*1000*60*60 var minutesDifference = Math.floor(cnnTimeStampDiff/1000/60); cnnTimeStampDiff -= minutesDifference*1000*60 var cnnDays = (daysDifference > 1) ? "days" : "day"; var cnnHours = (hoursDifference > 1) ? "hours" : "hour"; var cnnMinutes = (minutesDifference > 1) ? "minutes" : "minute"; var cnnHPMinutes = "min"; var cnnCMSTimeString = ''; var cnnBlankString = ""; if (timeString) { cnnCMSTimeString = (cnnIsIntl) ? timeString[0] : timeString[1]; } else { //for legacy support cnnCMSTimeString = "updated " + (!cnnIsIntl ? days[cnnStoryPublishTime.getUTCDay()] : '') + " " + months[cnnStoryPublishTime.getUTCMonth()] + " " + cnnStoryPublishTime.getUTCDate() + ", " + cnnStoryPublishTime.getUTCFullYear(); } if (hoursDifference > 4 && daysDifference >= 0 || daysDifference >= 1) { switch(pagetypeTS) { case "homepage": //t2 formatted return cnnBlankString; break; case "mosaic": return "
" + cnnCMSTimeString + "<\/div>"; break; case "section": default: if (pagetypeTS == 'section' && cnnIsIntl) { return "
" + cnnCMSTimeString + "<\/div>"; } else { return "
updated " + (!cnnIsIntl ? days[cnnStoryPublishTime.getUTCDay()] : '') + " " + months[cnnStoryPublishTime.getUTCMonth()] + " " + cnnStoryPublishTime.getUTCDate() + ", " + cnnStoryPublishTime.getUTCFullYear() + "<\/div>"; } } } else if( hoursDifference <= 4 && hoursDifference >= 1) { switch(pagetypeTS) { case "homepage": //t2 formatted return cnnBlankString; break; case "mosaic": default: if (minutesDifference > 0) { return "
updated " + hoursDifference + " "+cnnHours+", " + minutesDifference + " "+cnnMinutes+" ago<\/div>"; } else { return "
updated " + hoursDifference + " "+cnnHours+" ago<\/div>"; } } } else { switch(pagetypeTS) { case "homepage": //t2 formatted if(hoursDifference < 1 && minutesDifference > 0){ return '' + minutesDifference + " min<\/span>"; } else { return "1 min<\/span>"; } break; case "mosaic": default: if(hoursDifference < 1 && minutesDifference > 0){ return "updated " + minutesDifference + " "+cnnMinutes+" ago"; } else { return "updated 1 minute ago"; } } } } function cnnRenderBackStoryTimeStamp(date,timeString) { cnnStoryPublishTime = new Date(date); var days = new Array('Sun','Mon','Tue','Wed','Thur','Fri','Sat'); var months = new Array('January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'); var cnnTimeStampDiff = cnnCurrTime.getTime() - cnnStoryPublishTime.getTime(); var daysDifference = Math.floor(cnnTimeStampDiff/1000/60/60/24); cnnTimeStampDiff -= daysDifference*1000*60*60*24 var hoursDifference = Math.floor(cnnTimeStampDiff/1000/60/60); cnnTimeStampDiff -= hoursDifference*1000*60*60 var minutesDifference = Math.floor(cnnTimeStampDiff/1000/60); cnnTimeStampDiff -= minutesDifference*1000*60 var cnnDays = (daysDifference > 1) ? "days" : "day"; var cnnHours = (hoursDifference > 1) ? "hours" : "hour"; var cnnMinutes = (minutesDifference > 1) ? "minutes" : "minute"; var cnnCMSTimeString = ''; if (timeString) { cnnCMSTimeString = timeString; } if (hoursDifference > 4 && daysDifference >= 0 || daysDifference >= 1) { return "" + cnnCMSTimeString + "<\/span>"; } else if( hoursDifference <= 4 && hoursDifference >= 1) { if (minutesDifference > 0) { return "updated " + hoursDifference + " "+cnnHours+", " + minutesDifference + " "+cnnMinutes+" ago<\/span>"; } else { return "updated " + hoursDifference + " "+cnnHours+" ago<\/span>"; } } else { if(hoursDifference < 1 && minutesDifference > 0){ return "updated " + minutesDifference + " "+cnnMinutes+" ago"; } else { return "updated 1 minute ago"; } } } function cnnRenderT1TimeStamp(date,useLongFormat) { cnnStoryPublishTime = (date) ? new Date(date) : cnnStoryPublishTime; var cnnTimeStampString; var nullString=""; var cnnTimeStampDiff = cnnCurrTime.getTime() - cnnStoryPublishTime.getTime(); var daysDifference = Math.floor(cnnTimeStampDiff/1000/60/60/24); cnnTimeStampDiff -= daysDifference*1000*60*60*24 var hoursDifference = Math.floor(cnnTimeStampDiff/1000/60/60); cnnTimeStampDiff -= hoursDifference*1000*60*60 var minutesDifference = Math.floor(cnnTimeStampDiff/1000/60); cnnTimeStampDiff -= minutesDifference*1000*60 var secondsDifference = Math.floor(cnnTimeStampDiff/1000); var cnnDays = (daysDifference > 1) ? "days" : "day"; var cnnHours = (hoursDifference > 1) ? "hours" : "hour"; var cnnMinutes = (minutesDifference > 1) ? "minutes" : "minute"; var cnnSeconds = (secondsDifference > 1) ? "seconds" : "second"; var cnnHPMinutes = (minutesDifference > 1) ? "minutes" : "minute"; var cnnHPSeconds = (secondsDifference > 1) ? "secs" : "sec"; if (pagetypeTS=='homepage') { cnnTimeStampString = 'updated '; if(hoursDifference < 1 && minutesDifference > 0){ cnnTimeStampString += minutesDifference + " "+(useLongFormat?cnnMinutes:cnnHPMinutes)+" ago"; } else if(hoursDifference < 1 && minutesDifference < 1) { cnnTimeStampString += secondsDifference + " "+(useLongFormat?cnnSeconds:cnnHPSeconds)+" ago"; } else if(hoursDifference >= 1) { return nullString; } return ''+cnnTimeStampString+''; } } function CNN_submitUserComment(form) { var cnnSubmitForm = true; if(typeof(cnnThread) != "undefined") { $(form).threadName.value = cnnThread; } if(typeof(cnnForum) != "undefined") { $(form).forumName.value = cnnForum; } var errorDivs = $('cnnROCSubFrm').getElementsByClassName('cnnError'); for (var i = 0; i»<\/span>'); } if (allFormEls[i].name == "location") { new Insertion.Before('cnnUserResponseLocation',' »<\/span>'); } if (allFormEls[i].name == "body") { new Insertion.Before('cnnUserResponseComment',' »<\/span>'); } cnnSubmitForm = false; } } if (cnnSubmitForm) { new Effect.Opacity('cnnROCFrm', { duration:1.0, from:1.0, to:0, beforeStart:function() { document.cnnROCSubFrm.submit(); }, afterFinish: function(obj) { Form.reset(form); $('cnnROCFrmComplete').innerHTML = "Thank you for contributing. Comments are moderated by CNN and will not appear on this story until after they have been reviewed and deemed appropriate for posting. Unfortunately, due to the volume of comments we receive, not all comments can be posted.

Post another comment<\/a>"; new Effect.Opacity('cnnROCFrmComplete', { duration:1.0, from:0, to:1.0, beforeUpdate:function(obj) { $('cnnROCFrm').hide(); obj.element.show(); } } ); } } ); } } function CNN_toggleSubmissionForm(show,hide) { new Effect.Opacity(hide, { duration:1.0, from:1.0, to:0, afterFinish: function(obj) { new Effect.Opacity(show, { duration:1.0, from:0, to:1.0, beforeUpdate:function(obj) { $(hide).hide(); obj.element.show(); } } ); } } ) } function cnnShowExtendedComments(el) { var block = document.getElementsByClassName('cnnExtended',el.parentNode.parentNode); if (block && block.length > 0) { cnnToggleUGC(block[0],el); el.style.display = "none"; } } function cnnHideExtendedComments(el) { var block = el.parentNode.parentNode; var blockLinks = block.parentNode.getElementsByTagName('a'); if (block) { cnnToggleUGC(block,el); for (var i=0; i < blockLinks.length; i++) { blockLinks[i].style.display = "inline"; } } } function cnnShowMore(el) { var block = document.getElementsByClassName('cnnExtended',el.parentNode.parentNode); var initialGraph = el.parentNode.getElementsByTagName('p'); if (block && block.length > 0) { el.parentNode.hide(); block[0].show(); } } function cnnShowLess(el) { var block = el.parentNode.parentNode; var blockLinks = block.parentNode.getElementsByTagName('p'); block.hide(); blockLinks[0].show(); } function cnnToggleUGC(el,lnk) { if (cnnLockToggle) { return; } cnnLockToggle = true; var cnnToggleClass = (lnk.parentNode.className.indexOf('Closed') > -1) ? true : false; Effect.toggle(el,'blind', { beforeStart:function(obj) { try { lnk.blur(); } catch(e) {}; if (cnnToggleClass) { switch(lnk.parentNode.className) { case 'cnnOpinionClosed': lnk.parentNode.className = 'cnnOpinion'; break; case 'cnnIReportClosed': lnk.parentNode.className = 'cnnIReport'; break; case 'cnnBlogsClosed': lnk.parentNode.className = 'cnnBlogs'; Sphere.Widget.search(); break; default: } } }, afterFinish:function(obj) { if (!cnnToggleClass) { switch(lnk.parentNode.className) { case 'cnnOpinion': lnk.parentNode.className = 'cnnOpinionClosed'; break; case 'cnnIReport': lnk.parentNode.className = 'cnnIReportClosed'; break; case 'cnnBlogs': lnk.parentNode.className = 'cnnBlogsClosed'; break; default: } } cnnLockToggle = false; } } ); } function cnnToggleNestedContent(el,lnk,num,desc) { if (cnnLockToggle) { return; } cnnLockToggle = true; var cnnLnkTxt = "Last 3 comments only"; Effect.toggle(el,'blind', { duration:0.5, afterFinish: function() { if(!desc) { if (lnk.innerHTML == cnnLnkTxt) { lnk.innerHTML = "See all " + num + " comments"; } else { lnk.innerHTML = cnnLnkTxt; } } cnnLockToggle = false; }, beforeStart: function() { if(desc) { $(lnk).style.display = "none"; } } } ); } function CNN_displayBlogContent(widgetLoading,widgetContent) { if (!$(widgetLoading) || !$(widgetContent)) { return; } Effect.BlindUp(widgetLoading, { afterFinish:function(obj) { $(obj.element.id).remove(); } } ); Effect.BlindDown(widgetContent); } var cnnHasOpenPopup = 0; // this is for opening pop-up windows function CNN_openPopup( url, name, widgets, openerUrl ) { var host = location.hostname; if (window == top) { window.top.name = "opener"; } var popupWin = window.open( url, name, widgets ); if(popupWin) {cnnHasOpenPopup = 1;} if ( popupWin && popupWin.opener ) { if ( openerUrl ) { popupWin.opener.location = openerUrl; } } if ( popupWin) { popupWin.focus(); } } function cnnImgSwap( strId, intSwap ) { // assumes 2 images: image.gif and image_over.gif var imgObj = (typeof(strId) == "object") ? strId.getElementsByTagName('img')[0] : document.getElementById( strId ); var strTemp = imgObj.src; var intStrLength = strTemp.length; var intChop, strEnd; if ( intSwap ) { if (strTemp.indexOf('_over.gif') == -1) { intChop = intStrLength - 4; strEnd = '_over.gif'; } } else { if (strTemp.indexOf('_over.gif') > -1) { intChop = intStrLength - 9; strEnd = '.gif'; } } if (typeof(intChop) != "undefined") { strTemp = strTemp.substring( 0, intChop ); } if (typeof(strEnd) != "undefined") { imgObj.src = strTemp + strEnd; } } /* Flash Detect and Render ======================= The CNN_FlashObject takes a few required arguments... name ......... the id/name of the object/embed src .......... the URL of the swf width ........ (i think this should be required) height ....... (i think this should be required) ...and some optional arguments... parameters ... this is a "hash" of keys and values { menu: "true", play: "false", loop: "false" } (or set this to null or an empty string to skip) flashVars .... this is a hash or a string { cs_url: "/football/nfl/scoreboards/today/" } - or - "cs_url=/football/nfl/scoreboards/today/" Sample Usage: if ( new CNN_FlashDetect().detectVersion( 6 ) ) { var cnn_Scoreboard = new CNN_FlashObject( "cnnScoreboard", "/.element/img/2.0/swf/nfl_scoreboard.swf", 420, 85, null, "cs_url=/football/nfl/scoreboards/today/" ); cnn_Scoreboard.writeHtml(); } else { document.write( 'alternate html' ); } Of course, if you plan to have Flash in lots of places on a page, it might make more sense to make a global variable for the detection. You could go as far as creating a session-based cookie... */ var VBS_Result = false; function CNN_FlashDetect() { } CNN_FlashDetect.prototype.maxVersionToDetect = 10; CNN_FlashDetect.prototype.minVersionToDetect = 3; CNN_FlashDetect.prototype.hasPlugin = ( navigator.mimeTypes && navigator.mimeTypes.length && navigator.mimeTypes["application/x-shockwave-flash"] && navigator.mimeTypes["application/x-shockwave-flash"].enabledPlugin ); CNN_FlashDetect.prototype.hasActiveX = window.ActiveXObject; CNN_FlashDetect.prototype.hasWinIE = ( navigator.userAgent && ( navigator.userAgent.indexOf( "MSIE" ) != -1 ) && navigator.appVersion && ( navigator.appVersion.indexOf( "Win" ) != -1 ) ); CNN_FlashDetect.prototype.getVersion = function () { var versionNum = 0; var i = 0; if ( this.hasActiveX ) { var activeXObject = false; for ( i = this.maxVersionToDetect; i >= this.minVersionToDetect && !activeXObject; versionNum = ( activeXObject ? i : versionNum ), i-- ) { try { activeXObject = new ActiveXObject( "ShockwaveFlash.ShockwaveFlash." + i ); } catch( e ) { // do nothing } } } else if ( this.hasWinIE ) { VBS_Result = false; for ( i = this.maxVersionToDetect; i >= this.minVersionToDetect && !VBS_Result; versionNum = ( VBS_Result ? i : versionNum ), i-- ) { execScript( 'on error resume next: VBS_Result = IsObject( CreateObject( "ShockwaveFlash.ShockwaveFlash.' + i + '" ) )', 'VBScript' ); } } else if ( this.hasPlugin ) { if ( navigator.plugins && navigator.plugins.length && navigator.plugins["Shockwave Flash"] ) { var words = navigator.plugins["Shockwave Flash"].description.split( " " ); for ( i = 0; i < words.length; ++i ) { var wordAsNum = parseInt( words[i], 10 ); if ( isNaN( wordAsNum ) ) { continue; } else { versionNum = wordAsNum; break; // assume first number we get is version number } } } } return ( versionNum ); } CNN_FlashDetect.prototype.detectVersion = function ( num ) { var isVersionSupported = false; if ( ! isNaN( num ) ) { isVersionSupported = ( parseInt( this.getVersion(), 10 ) >= parseInt( num, 10 ) ); } return ( isVersionSupported ); } function CNN_FlashObject( p_name, p_src, p_width, p_height, p_parameters, p_flashVars ) { this.m_name = p_name; this.m_src = p_src; this.m_width = p_width; this.m_height = p_height; this.m_flashVars = p_flashVars; // constructor if ( p_parameters ) { this.setParams( p_parameters ); } } // Declare member properties CNN_FlashObject.prototype.m_name = ''; CNN_FlashObject.prototype.m_src = ''; CNN_FlashObject.prototype.m_width = ''; CNN_FlashObject.prototype.m_height = ''; CNN_FlashObject.prototype.m_flashVars = ''; CNN_FlashObject.prototype.m_params = { menu: "false", quality: "high", allowScriptAccess: "always", wmode: "transparent" }; CNN_FlashObject.prototype.setParam = function ( p_name, p_value ) { this.m_params[ p_name ] = p_value; } CNN_FlashObject.prototype.setParams = function ( p_paramHash ) { if ( typeof p_paramHash == "object" ) { for ( var param in p_paramHash ) { if ( p_paramHash[param] ) { this.setParam( param, p_paramHash[param] ); } } } } CNN_FlashObject.prototype.getParam = function ( p_name ) { return ( this.m_params[ p_name ] ); } CNN_FlashObject.prototype.getParams = function () { return ( this.m_params ); } CNN_FlashObject.prototype.getFlashVarsString = function () { var flashVarsString = ''; if ( typeof this.m_flashVars == "string" ) { flashVarsString = this.m_flashVars; } else if ( typeof this.m_flashVars == "object" ) { for ( var flashVar in this.m_flashVars ) { if ( flashVarsString != '' ) { flashVarsString += "&"; } flashVarsString += flashVar + "=" + escape( this.m_flashVars[flashVar] ); } } return ( flashVarsString ); } CNN_FlashObject.prototype.getAttributeString = function ( p_attr, p_value ) { return ( p_value ? ' ' + p_attr + '="' + p_value + '"' : '' ); } CNN_FlashObject.prototype.getParamTag = function ( p_name, p_value ) { return ( p_value ? '' : '' ); } CNN_FlashObject.prototype.getHtml = function () { var htmlString = ''; var eachParam = ''; var flashUrl = 'http://www.macromedia.com/go/getflashplayer'; // open object htmlString += 'Last '+cnnInitialDisplay+' comments only<\/a> | Next '+commentsWindow+' comments »'; loadingComments = false; return "
"+hideableComments+"
"+document.getElementById("cnnOpinionSubContainer").innerHTML+CNN_comment+"
"; } //builds a single comment element function CNN_generateACommentDiv(clObject){ var CNN_comment = ''; CNN_comment += '
'; CNN_comment += '
<\/div>'; CNN_comment += '
'; CNN_comment += '
'; CNN_comment += ''+clObject['jf:author']+'<\/span>
'; CNN_comment += cnnRenderTimeStamp(clObject['pubDate']); CNN_comment += ' <\/div>'; CNN_comment += '

'; CNN_comment += clObject['description'].truncate(300,' ...more<\/a>'); CNN_comment += ' <\/p>'; CNN_comment += '