On Thu, Jun 25, 2009 at 9:44 PM, Asiri Rathnayake <
asiri.rathnayake(a)gmail.com> wrote:
> Hi,
>
> On Thu, Jun 25, 2009 at 11:53 PM, Niels Mayer <nielsmayer(a)gmail.com>
> wrote:
>
> > Another interesting advanced JS data-visualization toolkit that would be
> > useful to integrate in Xwiki.
> >
> > http://vis.stanford.edu/protovis/
> > http://www.technologyreview.com/computing/22927/?nlid=2130
> > http://flare.prefuse.org/launch/apps/job_voyager
>
> Protovis sounds cool, but the way xwiki macros work will make it difficult
> (or messy) to implement a macro that will have to depend on a JS library.
> What we can do is this:
>
> * Implement the wiki-macro bridge:
> http://jira.xwiki.org/jira/browse/XWIKI-3213 (Basically this will allow
> you
> to convert any wiki content into your personal macro) - I'll finish this in
> a week or so.
>
> * We use a JSX (?) to get protovis support.
>
> * Neils can implement a js charting wiki-macro using protovis ;)
>
> I want to ask other developers, Is this possible? (I have a confusion about
> macros + js working together)
I have Macros/JS working together all the time, using JSX. I'm certain it's
possible, given the kinds of integration I've been able to do in
Exhibit&Xwiki, e.g. http://nielsmayer.com/xwiki/bin/view/Exhibit/NPRpods3
...
Here's a simple example, which are tests for my Xwiki integration of
http://www.longtailvideo.com/players/jw-flv-player/ which is the media
player used in the NPRpods3 application above:
http://nielsmayer.com/xwiki/bin/view/Macros/JWPlayer?viewer=codehttp://nielsmayer.com/xwiki/bin/view/Macros/JWPlayerJSPL_Test
(xwiki integration of
http://home5.inet.tele.dk/nyboe/flash/mediaplayer4/JW_API_xmpl_5-2-4-0.html
with an improvement, the JWplayer example doesn't work on Linux/Firefox,
mine does!)
http://nielsmayer.com/xwiki/bin/view/Macros/JWPlayerJSPL_Test?viewer=code
(wiki-code for above)
http://nielsmayer.com/xwiki/bin/jsx/Macros/JWPlayerJSPL_Test
(the javascript playlist from XWiki.JavaScriptExtension[0])
##
## Load and initialize LoadJS: defines injectJS(url) required by JWPlayer
##
#includeMacros("Macros.LoadJS")##
#loadjs_xwiki_init()##
##
## Load and initialize JWPlayer after LoadJS.
##
#includeMacros("Macros.JWPlayer")##
#jwplayer_xwiki_init()##
##
## Load JavaScript playlist from object XWiki.JavaScriptExtension[0] into
## js variable jwplayer_jspl, used below in parameter to
jwplayer_embed_generic()
## function(jwpl){jwpl.sendEvent(’LOAD’, jwplayer_jspl);}. This function
called
## by jwplayer’s playerReady() calback when player has been instantiated,
and
## causes the javascript-based playlist to get loaded.
##
$xwiki.jsx.use("$doc.fullName")##
...
#set( $jw_name = "$doc.name" )##
#set( $jw_player = "jwplayer_embed_generic(’$jw_name’, ’mpl’,
’&autostart=false&playlist=right&playlistsize=250&shuffle=false&repeat=always’,
function(jwpl){jwpl.sendEvent(’LOAD’, jwplayer_jspl);}, ’100%’, ’385px’);"
)##
#jwplayer_create("$jw_name", "$jw_player")##
http://nielsmayer.com/xwiki/bin/view/Macros/JWPlayerPL_Test is another test
using playlists.
This also calls JS jwplayer_embed_generic(), but with an external file,
passed as URL/string, instead of creating the playlist in lambda-function as
above. (
http://nielsmayer.com/xwiki/bin/view/Macros/JWPlayerPL_Test?viewer=code ):
#set( $jw_player = "jwplayer_embed_generic(’$jw_name’, ’mpl’,
’&autostart=false&playlist=right&playlistsize=250&shuffle=false&repeat=always’,
’/xwiki/bin/view/Macros/JWPlayer_PlayList?xpage=plain’, ’100%’, ’385px’);"
)##
JS functions jwplayer_embed(), jwplayer_embed_generic() and macros
#jwplayer_xwiki_init(), #jwplayer_create() are from
http://nielsmayer.com/xwiki/bin/view/Macros/JWPlayer?viewer=code
---
Going in "the other direction", here's an example of using velocity to
compute results returned by Javascript:
http://svn.xwiki.org/svnroot/xwiki/curriki/branches/curriki-1.8/web/src/mai…
#set( $total_attachments_size = 0 ) ## javascript:getAttachmentsSize()
#set( $total_attachments_names = [] ) ## javascript:getAttachmentsNames()
#foreach ($attach in $doc.attachmentList) ## {
#set( $ok = $total_attachments_names.add("'${attach.filename}'") )
## append attachment filename to ArrayList
#set( $total_attachments_size = ${total_attachments_size} +
${attach.getFilesize()} ) ## compute total size of atttachments
#end ## } -- foreach
...
function getAttachmentsNames() { return (${total_attachments_names}); }
function getAttachmentsSize() { return (${total_attachments_size}); }
...
lpattachments is called from an iframe. The parent document accesses the
iframe'd document's javascript functions like this: (
http://svn.xwiki.org/svnroot/xwiki/curriki/branches/curriki-1.8/wiki/src/ma…
)
//
// get size of files in attachments iframe
//
function getAttachmentsSize() {
return (window.frames['attachment_iframe'].getAttachmentsSize());
}
//
// retrieve ArrayList of filenames contained in attachment
//
function getAttachmentsNames() {
return (window.frames['attachment_iframe'].getAttachmentsNames());
}
-- Niels
http://nielsmayer.com
Hi Marius
>>> Collections.EMPTY_MAP is used to fill a "missing" parameter when a
>>> method is overloaded. Use the signature that specifies the parameter:
>>>
>>> public SyndEntrySourceApi getSyndEntryArticleSource()
>>> public SyndEntrySourceApi getSyndEntryArticleSource(Map params)
>>
>
>> I noticed that but the problem is that later these maps are used to
>
>Used where? In your code or in the feed plug-in code? I doubt it's in
>the feed plug-in code because the semantic I choose was: if you don't
>specify any parameters then you don't have any parameters and thus
>there's no need to change the map. If you want to specify parameters
>then you have to provide at least an empty (mutable) map.
>
>Can you give me a code snipped that shows the failure?
Calling getBlogFeed(String,int,int):
public SyndFeed getBlogFeed(String query, int count, int start)
{
return getBlogFeed(query, count, start, Collections.EMPTY_MAP);
}
Call THIS:
public SyndFeed getBlogFeed(String query, int count, int start, Map metadata)
{
if (query == null) {
XWikiRequest request = getXWikiContext().getRequest();
String category = request.getParameter("category");
if (category == null || category.equals("")) {
query =
", BaseObject as obj where obj.name=doc.fullName and obj.className='XWiki.ArticleClass' and obj.name<>'XWiki.ArticleClassTemplate' order by doc.creationDate desc";
} else {
query =
", BaseObject as obj, DBStringListProperty as prop join prop.list list where obj.name=doc.fullName and obj.className='XWiki.ArticleClass' and obj.name<>'XWiki.ArticleClassTemplate' and obj.id=prop.id.id and prop.id.name='category' and list = '"
+ category + "' order by doc.creationDate desc";
}
}
SyndFeed blogFeed = getArticleFeed(query, count, start, fillBlogFeedMetadata(metadata));
if (blogFeed != null) {
blogFeed.setImage(getDefaultFeedImage());
}
return blogFeed;
}
which calls THIS:
private Map fillWebFeedMetadata(Map metadata)
{
fillDefaultFeedMetadata(metadata);
// these strings should be taken from a resource bundle
String title = "Feed for document changes";
String description = title;
if (!keyHasValue(metadata, "title", "")) {
metadata.put("title", title);
}
if (!keyHasValue(metadata, "description", "")) {
metadata.put("description", description);
}
return metadata;
}
which calls THIS where it fails because the MAP is immutable:
private Map fillDefaultFeedMetadata(Map metadata)
{
XWiki xwiki = getXWikiContext().getWiki();
XWikiDocument doc = getXWikiContext().getDoc();
if (metadata.get("author") == null) {
metadata.put("author", xwiki.getUserName(doc.getAuthor(), null, false, getXWikiContext()));
}
if (!keyHasValue(metadata, "copyright", "")) {
metadata.put("copyright", xwiki.getWebCopyright(getXWikiContext()));
}
if (!keyHasValue(metadata, "encoding", "")) {
metadata.put("encoding", xwiki.getEncoding());
}
if (!keyHasValue(metadata, "url", "")) {
metadata.put("url", "http://" + getXWikiContext().getRequest().getServerName());
}
if (!keyHasValue(metadata, "language", "")) {
metadata.put("language", doc.getDefaultLanguage());
}
return metadata;
}
>> The FeedPlugin has two problems. A default query is not working
>> because it looks for XWiki.ArticleClass which I changed but also it
>> uses the XWiki.ArticleClass to define the properties to read out the
>> values and that fails with a NPE:
Here is where XWiki.ArticleClass is used:
public SyndFeed getBlogFeed(String query, int count, int start, Map metadata)
{
if (query == null) {
XWikiRequest request = getXWikiContext().getRequest();
String category = request.getParameter("category");
if (category == null || category.equals("")) {
query =
", BaseObject as obj where obj.name=doc.fullName and obj.className='XWiki.ArticleClass' and obj.name<>'XWiki.ArticleClassTemplate' order by doc.creationDate desc";
} else {
query =
", BaseObject as obj, DBStringListProperty as prop join prop.list list where obj.name=doc.fullName and obj.className='XWiki.ArticleClass' and obj.name<>'XWiki.ArticleClassTemplate' and obj.id=prop.id.id and prop.id.name='category' and list = '"
+ category + "' order by doc.creationDate desc";
}
}
SyndFeed blogFeed = getArticleFeed(query, count, start, fillBlogFeedMetadata(metadata));
if (blogFeed != null) {
blogFeed.setImage(getDefaultFeedImage());
}
return blogFeed;
}
>> I had to change the Source
>> Parameters in order to make it work. I will have a closer look at the
>> Feed Plugin and provide a patch when I could make it work.
>
>Again, can you provide a code snipped that shows the issue?
>
>SyndEntryDocumentSource is a generic feed entry source that knows
>nothing about XWiki.ArticleClass. It can generate a feed entry by
>collecting values from different properties of different objects
>attached to the source document. You can even specify velocity
>expressions to fill feed entry fields.
>
>Feed plug-in provides some helper methods for generating a feed from
>XWiki.ArticleClass objects. Forget about it. For the new blog you have
>to use the generic API and specify the mapping between feed entry fields
>and Blog.BlogPostClass properties. Take a closer look at my example
>http://tinyurl.com/cps7oa . As you can see I map:
>
>* ContentLength field -> a constant, 10
>* title field -> document title
>* description field -> the content property of the first
>XWiki.ArticleClass object attached to the source document
>* publishedDate -> the date property of the XWiki.ArticleClass object
>with index 0 among all the XWiki.ArticleClass objects attached to the
>source document
>* updatedDate -> a velocity expression, $doc.date.time
>* categories -> a list: $doc.space, $doc.name, $doc.isNew()
>
>So what stops you from mapping feed entry fields to Blog.BlogPostClass
>properties ?
If we have methods that provide default values shouldn't it then work. The SyndEntryDocumentSource uses the XWiki.ArticleClass as the default mapping for the properties and it fails silently if the properties cannot be found.
Shouldn't we then provide a default mapping for getBlogFeed() methods that don't have one?
I will use the code snipped you mentioned above and see if I can make it work with 2.0m2 when it comes out.
Thanks - Andy
Hi
I just attached the 7th draft of the Blog 2.0 Wiki Syntax upgrade to this JIRA report:
http://jira.xwiki.org/jira/browse/XABLOG-50
This one includes the upgrades of the Panels to the 2.0 syntax. The only thing remaining are the RSS feeds and these cannot be upgraded now because the XHTML renderer does add the macro content as comment to the top of the output AHEAD of the <?xml> which is not allowed by the XML specification. So far I could not find a way to suppress that. I tried to create a XML renderer macro but got nowhere with it.
My own Blog: http://madplanet.com/xwiki/bin/view/Blog/ uses the latest (7th) draft of the blog upgrade.
Cheers
Andreas Schaefer
CEO of Madplanet.com Inc.
EMail: andreas.schaefer(a)madplanet.com
schaefera(a)me.com
Twitter: andy_mpc
AIM: schaefera(a)me.com
Hi,
Right now we have a macro description in the macro descriptor but
we're missing the macro name (ie a human understandable name to be
used when displaying the list of macros in the wysiwyg editor for
example).
So I'm proposing we:
* rename getMacroNames* methods in MacroManager/MacroCategoryManagers
to getMacroIds
* add a getName() in MacroDesciptor
Here's my +1
Thanks
-Vincent
On Tue, Aug 4, 2009 at 9:29 AM, Asiri Rathnayake <asiri.rathnayake(a)gmail.com
> wrote:
>
> The wiki macro bridge has been released with 2.0M2. ...
>
> If you come across any problems while you are at it, we can improve wiki
> macro bridge :)
>
Thanks for reminding me about the Xwiki macro bridge. Looks great and is a
big improvement over how things were done previously. Your message was
timely as helped me answer one of my big questions about having groovy or
clojure macros available on virtual-wiki setup:
http://platform.xwiki.org/xwiki/bin/view/DevGuide/WikiMacroTutorial
- Wiki macro authors need to have programming rights
- Wiki macros can only be defined inside the main wiki, though they can
be used throughout a farm
I wrote my first macro-bridge macro (see attachment Main.TestMacroBridge.xar
) in groovy in preparation for my experiments with scripting in Clojure. The
hardest thing was finding out that the name of "context" had changed to
"xcontext" for groovy and other JSR-223 languages, whereas velocity (and
WikiMacroTutorial) uses "context". This has been discussed on the lists (
http://markmail.org/message/o2trzrnv5xts6x6v ), and the WikiMacroTutorial
needs updating to reflect the final status & naming-conventions.
My macro is quite simple. but does a lot, taken from here:
http://www.ibm.com/developerworks/java/library/j-pg05199/index.html
Usage: {{weather_by_zip zip=92625 /}}
Code:
...............................
Objects of type XWiki.WikiMacroClass WikiMacroClass 0: weather_by_zip
{{script language=groovy}}
def rss = new XmlSlurper().parseText(("
http://weather.yahooapis.com/forecastrss?p=" +
xcontext.macro.params.zip).toURL().text) println rss.channel.title println
"Sunrise: ${rss.channel.astronomy.@sunrise}" println "Sunset:
${rss.channel.astronomy.@sunset}" println "Currently:" println "\t" +
rss.channel.item.condition.@date println "\t" +
rss.channel.item.condition.@temp println "\t" +
rss.channel.item.condition.@text {{/script}}
Objects of type XWiki.WikiMacroParameterClass WikiMacroParameterClass 0: zip
...............................
May be you can put it to test by trying to implement your chart macro ;)
It would be more useful to offer all-new
Exhibit<http://www.simile-widgets.org/exhibit/> functionality
with tighter integration into the Xwiki back-end, e.g.
having document/space and other Xwiki "model" information abstractly
available to an Exhibit-based "view/controller" to provide a "faceted views"
presentation of Xwiki documents and contents. FYI, My existing Exhibit
integration with Xwiki demo:
http://nielsmayer.com/xwiki/bin/view/Exhibit/Presidents4 (source:
http://nielsmayer.com/xwiki/bin/download/Exhibit/Presidents4/Presidents4Pkg…)
My main commitment right now is an experiment to see if I can get
JSR223-supported Clojure scripting in Xwiki.
This message didn't give me much hope of success right now (
http://groups.google.com/group/clojure/msg/ad811b69d448e3db ) but I'll give
Clojure on Xwiki a try anyways, and revisit later if it's just a matter of
getting more solid JSR223 support for Clojure as development progresses.
Niels
http://nielsmayer.com
Hi Devs,
as described in http://jira.xwiki.org/jira/bro
wse/XE-472<http://jira.xwiki.org/jira/browse/XE-472> ,
I've rewritten the Sandbox space in syntax 2.0. Since operations in table
(Sum, multiplication etc...) are not yet supported in XWiki 2.0 syntax, I
suggest we remove the Sandbox.TableTraining page for the time being instead
of keeping a XWiki 1.0 syntax page in the Sandbox since it doesn't bring
much value and cannot be converted satisfactorily as of today. I can't
remember any recent email about operations in tables on this list (at least
not in the past 2 years), thus I think removing it won't cause too many
problems. I'll rewrite it later if / when the new syntax supports such
operations once again.
Here's my +1 for removing the Sandbox.TableTraining page.
Thanks for your feedback,
Guillaume
--
Guillaume Lerouge
Product Manager - XWiki
Skype: wikibc
Twitter: glerouge
http://guillaumelerouge.com/
Hi,
I'd like to propose the following API changes to the Rendering module:
1) Modify PrintRendererFactory
a) There's now one factory component per Renderer type with the
following interface:
public interface PrintRendererFactory
{
/**
* @return the Syntax supported by the Renderer type
* @since 2.0M3
*/
Syntax getSyntax();
/**
* @param printer the printer to use to output renderer data
* @return a new Renderer instance (stateful)
* @since 2.0M3
*/
PrintRenderer createRenderer(WikiPrinter printer);
}
b) The getAvailableSynatxes() doesn't exist anymore. It's been moved
to SyntaxFactory, see below.
2) Modify SyntaxFactory
a) Remove getAvailableSyntaxes() since there are different types of
syntaxes: Parser syntaxes, Renderer syntaxes and even amongst Parser/
Renderer there will be different types of them: streaming, block. Thus
the new strategy is for client code to directly ask for syntaxes by
looking up the objects against the CM. getAvailableSyntaxes() has been
deprecated.
3) Introduce BlockRenderer
@ComponentRole
public interface BlockRenderer
{
/**
* @param block the block to render in the target syntax
* @param printer the object where to output the result of the
rendering
*/
void render(Block block, WikiPrinter printer);
/**
* @param blocks the list of blocks to render in the target syntax
* @param printer the object where to output the result of the
rendering
* @todo remove this API once we introduce the notion of
BlockCollection
*/
void render(Collection<Block> blocks, WikiPrinter printer);
}
Goals:
a) Have 2 types of Renderers (as we'll have 2 types of Parsers in the
future): Stream and Block
b) reduce code duplication since using the BlockRenderer will simplify
the client code
4) Introduce Converter
@ComponentRole
public interface Converter
{
void convert(Reader source, Syntax sourceSyntax, Syntax
targetSyntax, WikiPrinter printer)
throws ConversionException;
}
Goal: Simplify client code when the need is pure conversion.
5) Move Renderer's implementation classes (components now) in the
internal package
They're now components and thus we can move them in the internal
package.
Here's my +1 to all
Thanks
-Vincent