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
multifeed
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" );
}
}
]]>