Languages

Lecteur de RSS en AS3

Une problématique archi-connue, et pourtant peut être peu traitée ?

On m'a demandé récemment de créer un lecteur de flux RSS en flash . Après une rapide recherche sur le web , je suis tombé sur ce très intéressant article de Mike Chambers , qui proposait une solution en "flex" utilisant des classes fournies par Adobe. J'ai utilisé ces classes pour le lecteur RSS au dessus.

L'avantage de ces classes adobe est qu'elles sont très fournies et permettent de parser trois sortes de flux différents (atom, rss1 et rss2 ) . Pour faire fonctionner ce reader en AS3 , par contre , il faut modifier quelques paramètres notamment dans les classes distribuées par Adobe . J'ai remis sous forme de classe AS3 le code fournit par Mike chambers dans son site. Créez votre fla 'RSSReader' dans un répertoire . Associez y la classe RssReader . Placez la classe RssReader.as qui est téléchargeable dans cet article. Je me suis contenté d'afficher le résultat du parsing des balises dans un textfield , aussi ne vous attendez pas à quelque chose de graphique ! Une fois que vous avez récupéré la classe et que vous l'avez placé à la racine de votre site , vous devez rajouter les différentes classes d'adobe à mettre dans le sous-répertoire com/ ou se trouve votre fla

  1. téléchargez les classes xmlsyndication ici
  2. téléchargez les classes corelib ici

De ces packages, vous n'avez besoin que de ce qui se trouve dans le répertoire src/com/adobe que vous copierez dans les sous-répertoire correspondant de votre fla : com/adobe . Il faut respecter cette nomenclature, qui veut que les packages qu'on utilise sont référencés dans un sous répertoire com , cela permet de mieux organiser le code et la programmation). Une fois que vos librairies sont copiées, vous pourrez commencer à compiler pour "voir ou ça coince" :

1172: La définition mx.formatters:DateBase est introuvable.Rendez vous dans la classe DateUtils du package com/adobe/utils et remplacez import mx.formatters.DateBase; par import com.adobe.utils.DateBase ;

Ensuite vous aurez

1120: Accès à la propriété non définie DateBase. A nouveau, une référence à MX dans les classes, cette fois çi dans DateUtil.as .. Remplacez donc : import mx.formatters.DateBase; par import com.adobe.utils.DateBase ;

Recompile, et on tombe sur

1120: Accès à la propriété non définie DateBase. Normal, en y regardant de près on se rend compte que la classe DateBase.as n'est pas présnete dans le package utils d'adobe. Pour contourner le problème, Martin Legris (lisez son blog utile ,ici ) a créer une classe basique Datebase qu'il propose au téléchargement sur son site . Téléchargez là et placez là dans com/adobe/utils/ .

1172: La définition mx.utils:StringUtil est introuvable. Mince ! Encore un MX ! Remplacez import mx.utils.StringUtil; par import com.adobe.utils.StringUtil ; dans le fichier Channel20.as  . Voila , cette fois çi c'est bon, les erreurs que vous rencontrer éventuellement ne sont plus dû aux références dans les packages ou a des problèmes de classe ..

luca mezzalira propose les librairies modifiés (c'est à dire corrigées comme je l'ai fait manuellement) ici : http://lucamezzalira.com/2009/02/07/parsing-rss-10-20-and-atom-feeds-with-actionscript-3-and-flash-cs4/ , mais je  n'ai pas essayé ces librairies modifiées.

Maintenant concernant mon code, j'ai instancié pour chaque item du RSS un objet "RssLine" qui est rajouté à mon objet RssReader .

Voici le code de la classe RssLine documenté au maximum :

package  {
	
	// liste des packages importés 
	// on importe les objets movieclip car la classe RssLine en descends 
	import flash.display.MovieClip;
	// la classe textfield sert à créer le champ texte de la ligne.
	import flash.text.TextField ;
	// TextFieldAutoSize permet de fixer la taille en largeur du TextField par rapport au contenu de la ligne.
	import flash.text.TextFieldAutoSize;
	// textformat permet de modifier l'affichage du texte (police, etc..)
	import flash.text.TextFormat ;	
	// URL Request est nécessaire à créer un "objet" URL géré par Flash 
	import flash.net.URLRequest;	
	// navigateToUrl est nécessaire au lancement d'un lien via le navigateur
	import flash.net.navigateToURL;
	// les évenements de souris aussi doivent être importés.
	import flash.events.MouseEvent;	
	// classes servant au déplacement (effet tween)
	import fl.transitions.*;
	import fl.transitions.easing.*;
	import fl.transitions.Tween;


	
	
	public class RssLine extends MovieClip{
		
		// Constants:

		// Public Properties: 
		// Private Properties:
		private var _urllink:String ;
		private var _headline:String ;	
		private var _textfield:TextField ;	
		private var _rsslineformat:TextFormat;
		private var _container:MovieClip;	
		private var _mask:MovieClip;			
		private var _myTween:Tween;
		
			
	
		// Initialization:
		public function RssLine(headline:String,urllink:String) {
			buttonMode = true;
			mouseChildren = false 
			_container = new MovieClip() ;
			addChild(_container);

			_mask = new MovieClip();
			_mask.graphics.lineStyle();

			_mask.graphics.beginFill(0xff0000);
 			_mask.graphics.drawRect(0,0,300,20);			
			_mask.graphics.endFill();					
 			
  			

			
			addChild(_mask);

			_rsslineformat = new TextFormat();
			_rsslineformat.bullet = true ;
			
			_rsslineformat.font = 'Arial' ;
			_rsslineformat.size = 12;
			_textfield = new TextField() ;
			_textfield.selectable = false ;
			//_textfield.width = 500 ;
			_container.addChild(_textfield) ;
			_textfield.text = headline ; 
			_textfield.setTextFormat(_rsslineformat);
			_textfield.autoSize = "left"; 
			_headline = headline ;
			_urllink = urllink ;  
			

			_textfield.mask = _mask ;
			
			// events handling
			addEventListener(MouseEvent.CLICK, buttGotoArticle);
			addEventListener(MouseEvent.ROLL_OVER, buttArtOver);
			addEventListener(MouseEvent.ROLL_OUT, buttArtOut);
			
		}
	
		// Public Methods:

		
		// Protected Methods:
		private function buttGotoArticle(e:MouseEvent){
				var requ = new URLRequest(_urllink);
				navigateToURL(requ ,"_blank");	
		}				
		private function buttArtOver(e:MouseEvent){
			_rsslineformat.underline = true;
			_textfield.setTextFormat(_rsslineformat);
			var diff:int = _mask.width - _textfield.width ;
			var speed:Number ;
			if(diff<0){
				// plus ou moins rapide selon la taille du text 
				if(diff>-10){ // si moins de 10pixels, pas d'animation, deplacement simple
					_container.x = _container.x + diff ;
				}else{
					_myTween = new Tween(_container, "x", None.easeIn, 0, (_mask.width- _textfield.width),3, true);
				}
 				
			}
			

		}				
		private function buttArtOut(e:MouseEvent){
			if(_myTween){
				_myTween.stop();
			}
			_rsslineformat.underline = false;
			_textfield.setTextFormat(_rsslineformat);
			_container.x = 0 ;
		
		}						
		
		
	}
	
}

Le code du RssReader est quasiment celui que fournit Mike Chambers, notamment dans la logique du téléchargement du XML, qui est faite de façon synchrone , c'est à dire avant de lancer l'affichage (un truc de base pour tout nouveau sur AS3, mais essentiel lorsqu'on vient télécharger de l'extérieur un fichier, que ce soit une image ou autre chose.

 

package {
	
	import com.adobe.utils.XMLUtil;
	import com.adobe.xml.syndication.rss.Item20;
	import com.adobe.xml.syndication.rss.RSS20;
	import RssLine ;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.events.IOErrorEvent;
	import flash.events.SecurityErrorEvent;
	import flash.net.URLLoader;
	import flash.net.URLRequest;
	import flash.net.URLRequestMethod;
	import flash.net.navigateToURL;	
	import flash.display.MovieClip;
	import preloader ;		
	import logoFT ;
	// for button more
	import flash.text.TextField ;
	import flash.text.TextFieldAutoSize;
	import flash.text.TextFormat ;		
	
	public class RssReader extends MovieClip{

		// Constants:
		//url of rss 2.0 feed
		
		private static const RSS_URL:String="http://www.euronews.net/rss/fr/home/home.xml";	
		
		// Public Properties:
		// Private Properties:
		private var loader:URLLoader;
  	    // preloader
		private var _preloader:preloader ;
        //  position  de la première ligne
		private var linePosY:int = 58 ;
		// hauteur entre 2 lignes
		private var _ligneHeight:int = 20  ; 
		// Initialization:
		public function RssReader() {
			loader = new URLLoader();

			// add the logo
			var logo = new logoFT();
			addChild(logo) ;
			logo.x = 0;
			logo.y = 0 ;
			logo.scaleX = logo.scaleY = 0.4 ;
			
			logo.buttonMode = true ;
			logo.addEventListener(MouseEvent.CLICK, buttGotoSite);
			
			// add the more button
			var moretext:TextField = new TextField();
			var moreTf = new TextFormat('Arial',12,'0x71a2c3',null,null,null,"http://www.euronews.net/","_self",null,null,null,null,null);
			moretext.text = "More" ;
			moretext.setTextFormat(moreTf);
			addChild(moretext) ;
			moretext.x = 270 ;
			moretext.y = 30;
			

			_preloader =new preloader();
			addChild(_preloader); 
			_preloader.x = 155;
			_preloader.y = 128;
			//var logoFT = new logoFT();
			//trace(logoFT);
			//request pointing to feed
			var request:URLRequest=new URLRequest(RSS_URL);
			request.method=URLRequestMethod.GET;

			//listen for when the data loads
			loader.addEventListener(Event.COMPLETE, onDataLoad);

			//listen for error events
			loader.addEventListener(IOErrorEvent.IO_ERROR, onIOError);
			loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onSecurityError);

			//load the feed data
			loader.load(request);


		}

		// Public Methods:
		// Protected Methods:
		//called once the data has loaded from the feed
		private function onDataLoad(e:Event):void { 
			_preloader.visible = false ;
			//get the raw string data from the feed
			var rawRSS:String=URLLoader(e.target).data;
			//parse it as RSS
			parseRSS(rawRSS);

		}
		// go to FT site
		private function buttGotoSite(e:MouseEvent):void { 
					var requ = new URLRequest("http://www.sensue.com/");
                   navigateToURL( requ,"_self");	
		}
		

		//parses RSS 2.0 feed and prints out the feed titles into
		//the text area
		private function parseRSS(data:String):void {

			//XMLSyndicationLibrary does not validate that the data contains valid
			//XML, so you need to validate that the data is valid XML.
			//We use the XMLUtil.isValidXML API from the corelib library.
			if (! XMLUtil.isValidXML(data)) {
				//writeOutput("Feed does not contain valid XML.");
				writeOutput('Sorry, data is currently unavailable' , '' );
				return;
			}

			//create RSS20 instance
			var rss:RSS20 = new RSS20();

			//parse the raw rss data
			rss.parse(data);

			//get all of the items within the feed
			var items:Array=rss.items;

			//loop through each item in the feed
			for each (var item:Item20 in items) {
				//print out the title of each item
				writeOutput(item.title,item.link);

			}
			
		}

		private function writeOutput(dataTitre:String,dataUrl:String):void {
				var rssline:RssLine = new RssLine(dataTitre,dataUrl);
				rssline.y = linePosY ; 
				addChild(rssline) ;
				linePosY+= _ligneHeight ; 
				
		}

		private function onIOError(e:IOErrorEvent):void {
			writeOutput('Sorry, data is currently unavailable'+e.text+')' , '' );
			_preloader.visible = false ;
		}

		private function onSecurityError(e:SecurityErrorEvent):void {
			//writeOutput("SecurityError : " + e.text);
			writeOutput('Sorry, data is currently unavailable ('+e.text+')'  , '' );
			_preloader.visible = false ;
		}


	}

}
AttachmentSize
RssReader.as4.35 KB
RssLine.as3.38 KB
»

Comments

Est-ce normal qu'il n'y ait

Est-ce normal qu'il n'y ait pas le mois d'aout dans la classe DateBase ???

bien vu !

On va transmettre à l'auteur , martin legris, que sa classe est incomplète ..Sinon, tu peux la corriger , vu le contenu de la classe ça devrait pas être un gros problème !!

/**
* ...
* @author Martin Legris
* @version 0.1
* CORRECTED by zitezoon
*/

package com.adobe.utils
{

public class DateBase
{
public static var monthNamesShort:Array = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul","Aug", "Sep", "Oct", "Nov", "Dec"];
public static var monthNamesLong:Array = ["January", "February", "March", "April", "May", "June", "July", "September", "October", "November", "December"];
public static var dayNamesShort:Array = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
public static var dayNamesLong:Array = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
}
}