Klipfolio Inc. Copyright © 2002-2009 Klipfolio Inc. support@klipfolio.com http://www.klipfolio.com/ Klip Template: Multi-Feed 3.0.1 Multi_Feed_Klip 2009.01.16 This template can be used to create a single Klip that consolidates multiple RSS/RDF/Atom feeds together. multiple rss rdf feed viewer xml syndicate channel custom reader http://www.klipfolio.com/ http://www.serence.com/support/samples/images/multiFeed_icon.gif http://www.serence.com/support/samples/images/multiFeed_banner.gif http://www.serence.com/support/samples/multiFeed.klip 120 -- -- true Loading data ... No headlines to display. = 0; --i) { if (Items[i].getData ("source") == source) { Items.remove (i, true); } } } // // Called when a ListControl was clicked. // // Because we are refreshing the Klip in between user events, it's possible for the // user to quickly click multiple items in the list control before we get an event // from KlipFolio that the list control was updated. // // So, we keep a shadow value for each list control item called .previous_state // // We use the property .offset to find the index of this entry // function lcSource_onStateChange( index ) { _t( "Item: " + this[index] ); _t( "Offset: " + this.offset ); _t( "State: " + this.getState(index) ); var name = multiFeeds[index + this.offset][NAME]; var state = this.getState(index); _t( "You clicked on: " + name ); UpdatePrefs(); // update the state of all visible items in the list. Use the Item's name, // which is stored in .extra, as a hash lookup for Prefs.getPref() for (var i = 0; i < Items.length; ++i) { Items[i].hidden = Prefs.getPref( Items[i].extra ) == "true" ? false : true; } // // Request a refresh to update any feeds the user has changed to // now show. // // Comment out these two lines to have the user click the Refresh button in the Klip setup // userClickedListControl = true; Klip.requestRefresh(); } function UpdatePrefs() { // // Store the state of the prefs for all listControls. // for (var lc_index = 0; lc_index < lcSource.length; lc_index++) { for (var i = 0; i < lcSource[lc_index].length; i++ ) { var prefs_name = lcSource[ lc_index ].name + "|" + lcSource[lc_index][i]; Prefs.setPref( prefs_name, lcSource[lc_index].getState( i ) ); } } } // // Mark all items in Items[] that have been marked as coming from // the feed of the given name // function items_mark( name ) { for (var i=0; i= 5897) { setItemActions(); } // Clear global state userClickedListControl = false; // Clear global state return result; } // // Refresh only the items for the given URL. // function getData( url, name ) { _t( "Refreshing : " + url ); req = Engines.HTTP.newRequest (url); if ( !req.send() ) { _t( "Unable to send url" ); return false; } var data = req.response.data; if( !data.length ) { // Check if we got a "304 Not Modified message" in the headers // // true -- data has not changed since we last checked it // false -- no data for another reason, return false var re_304 = new RegExp( "304 Not Modified" ); var check = re_304.exec( req.response.headers ) != null; if ( check ) { _t( "304 NOT MODIFIED returned -- no refresh needed" ); } return( check ); } // At this point we have data, so let's refresh this source and purge // any items that are not updated // items_mark( name ); // Mark all items for this source Engines.KlipFood.process (req.response); items_purge( name ); // Delete all items not updated _t( " done" ); // Update the show of sources // var count = 0; for (var i = 0; i < Items.length; i++) { if (!Items[i].tagged) { Items[i].extra = name; Items[i].tagged = true; count++; } } _t(" Updated #: " + count ); return true; } // // The myCreate function modifies the properties of each new item that is created. // function myCreate (new_item) { _t( "myCreate()" ); if (multiFeeds.length) { var source = Klip.processEntities (Engines.KlipFood.getScratch ("Channel Title")); new_item.setData ("sourcerow", source); if (multiFeeds.length > 1) { new_item.setData ("source", source); new_item.setData ("icon", multiFeeds[g_current_feed][ICON]); } new_item.setData ("banner", Klip.processEntities (Engines.KlipFood.getScratch ("Channel Image"))); // note that the replace on tags is to fix feedster's naive highlighting of search terms var data = Klip.processEntities (new_item.getData ("description")).replace (/(|<\/strong>)/g, ""); var index; var m; // // Retrieve an image from the news item and display it in the note // var imgdata = data; var done = false; while (!done && ((index = imgdata.indexOf ("')) != -1) {} if (index2 != -1) { img = m.substring (0, index2); } } } img = Klip.convertToText (img); if (img.length) { if (!imageBlacklisted (img)) { new_item.setData ("storyimage", img); done = true; } } } //while data = Klip.convertToText (data); new_item.setData ("description", data); // // Fix for livejournal entries without titles // var test_data = new_item.getData ("matchtitle"); if (test_data.length) { new_item.setData ("visibletitle", test_data) } else { var first_line_re = new RegExp (".........*?[.:?\r\n]"); if (m = first_line_re.exec (data)) { data = m[0]; if (data[data.length-1] == '\r' || data[data.length-1] == '\n') { data = data.substring (0, data.length); } } data = data.substring (0, 80); if (data.length == 80) { if ((index = data.lastIndexOf (' ')) > 25) { data = data.substring (0, index); } data += "..."; } new_item.setData ("visibletitle", data) } } return true; } function myUpdate (existing_item, properties) { // Update using the new properties _t( "myUpdate()" ); myCreate(properties); return true; } function imageBlacklisted (url) { if (url.indexOf ("r.feedster.net") != -1) { return true; } return false; } // ---------------- Useful Trace Code ------------------- function show_state() { _t( "show_state()" ); dumpItems(); dumpItemsDeleted(); show_all_prefs(); queryListControl(); } function dumpItems() { if( Items.length == 0 ) { trace( "There are no items in the Items[] array\r\n" ); return; } for( i = 0; i < Items.length; i++ ) { trace( "Items[" + i + "]: \r\n" ); queryItem( Items[i] ); } } function dumpItemsDeleted() { if( Items.Deleted.length == 0 ) { trace( "There are no items in the Items.Deleted[] array\r\n" ); return; } for( i = 0; i < Items.Deleted.length; i++ ) { trace( "Items.Deleted[" + i + "]: \r\n" ); queryItem( Items.Deleted[i] ); } } function queryItem( item ) { trace( "----\r\n" ); trace( " item.text = \"" + item.text + "\" (string)\r\n" ); trace( " item.url = \"" + item.url + "\" (string)\r\n" ); trace( " item.note = \"" + item.note + "\" (string)\r\n" ); trace( " item.extra = \"" + item.extra + "\" (string)\r\n" ); trace( " item.hidden = " + item.hidden + " (boolean)\r\n" ); trace( " item.visited = " + item.visited + " (boolean)\r\n" ); trace( " item.canpurge = " + item.canpurge + " (boolean)\r\n" ); trace( " item.alerting = " + item.alerting + " (boolean)\r\n" ); trace( " item.creation = " + item.creation + " (double)\r\n" ); trace( " item.pubdate = " + item.pubdate + " (double)\r\n" ); trace( " item.lastmodified = " + item.lastmodified + " (double)\r\n" ); trace(" -- \r\n" ); trace( " item.tagged = " + item.tagged + " (text)\r\n" ); trace( "\r\n" ); } function queryListControl() { for (var lc_index = 0; lc_index < lcSource.length; lc_index++) { var index = lcSource[lc_index].offset + i; for (var i = 0; i < lcSource[lc_index].length; i++ ) { _t( "lcSource: " + lcSource[lc_index].getState( i ) + " multiFeeds: " + multiFeeds[i + lcSource[lc_index].offset].updated + " - name: " + multiFeeds[i + lcSource[lc_index].offset][NAME] ); } } } function show_all_prefs() { var i; trace( "------------------------\r\n" ); for (i = 0; i < Prefs.length; i++) { trace("Prefs["+i+"]: '"+Prefs[i].name+"' == '"+Prefs[i].value+"'\r\n"); } trace( "------------------------\r\n" ); } // // Trace code // var gTrace = false; // Turn on trace code function _t( s ) { if ( gTrace ) { trace( Prefs.title + ": " + s + "\r\n" ); } } ]]>