http://www.dcubed.ca/twupdate.js
Its syntax is simply "<<twupdate>>", and it assumes that the empty.html
document on tiddlywiki.com is the place to grab the latest and
greatest.
My vision would be that this is part of the core so that users,
especially ones that are not ultra-TW savvy, don't have to fuss with
the usual update process...just a single click on the SidebarOptions
with this new macro and they are updated.
Please note that this is version 0.1! I have tested it out on my copies
of IE 6 and Firefox 1.5.0.1, Windows only. So please use it carefully
and let me know of any issues you might find. I am using as much core
code as possible, so it *should* just work on all TW platforms. But
then again, I am not sure about XMLHttpRequest support on Safari.
-- tomo
I have posted the source for a macro I cobbled together to update
TiddlyWiki documents with a single click. You can grab it from:
http://www.dcubed.ca/twupdate.js
1. Be smarter about doing any work if the version you are running
is current.
2. Support an optional URL param that would point at another
source document, for those of us that play with beta releases of TW.
-- tomo
There's a few other things that need to be done before it goes in the
core, I think:
- The XMLHttpRequest stuff needs to be abstracted off out of the
twupdate code so that other parts of the core or plugins can easily
reuse it. I'm imagining something like Yahoo's UI library code, which
is broad enough to smooth over browser incompatibilities
- The SaveChanges code should be refactored to merge it with the the update code
Cheers
Jeremy
--
Jeremy Ruston
mailto:jer...@osmosoft.com
http://www.tiddlywiki.com
Jeremy,
Do you mean we need "libraries" that could be shared by different
plugins or extensions and could be "included" as needed ?
I think TiddlyWiki should have his own kind of mechanism to factorize
and keep more reliable extension writing.
-- BidiX
TiddlyWiki.bidix.info
I just mean in the same way that the TW core groups together useful
utility functions in areas like Date.*, String.*, RGB.*. So I'm
imagining a very simple generic Ajax.* class that is embedded in the
core to smooth out the cross browser differences. To do that properly
it needs to be a bit more extensive than Tomo's current code, which
really only encapsulates the creation of the XmlHttpRequest object.
> I think TiddlyWiki should have his own kind of mechanism to factorize
> and keep more reliable extension writing.
I'm not sure I understand; are you wondering about a plugin format for
shared library code?
Cheers
Jeremy
I'm not sure I understand; are you wondering about a plugin format for
shared library code?
I've tried to use config.lib.XXX array to put some generic code between my different plugins and an config.lib.include function to joint those "micro-plugin" into extensions http://tiddlywiki.bidix.info/BidiXLab.html. It's "a work in progress" but I wanted to share the idea. Thoughts ?
Do you want me to offer up a prototype for that? Or, are you
envisioning a whole bunch of true Ajax functionality beyond simple
background requests?
-- tomo
Udo
I think we should be looking at these external toolkits. Dojo is
another worthwhile one (http://www.dojotoolkit.org/). I wouldn't be
surprised if we end up rolling our own, though, because the TW
situation is pretty unique (there's certainly a bunch of stuff in
those toolkits that would be of little or no value in TW).
> What about using an existing Ajax implementation, e.g. the one provided
> by the prototype framework (http://prototype.conio.net/)?
I think we should be looking at these external toolkits.
There are a few other considerations. For instance, leaks in IE:
http://www.volkanozcelik.com/cre8/blog/2006/02/simple-leak-free-defensive.html
We also need to think about things like error handling and cache control:
http://ajaxpatterns.org/XMLHttpRequest_Call
This is also relevant:
http://ajaxian.com/archives/reusing-xmlhttprequest-without-abort
All those intricacies are why I think it's worth looking at some of
the work others have already done on this in Prototype and Dojo.
> Do you want me to offer up a prototype for that? Or, are you
> envisioning a whole bunch of true Ajax functionality beyond simple
> background requests?
Background requests are the basics I'd want to look at, and yes, I'd
welcome code submissions like this for 2.1.
So I guess that begs the question, implicit in my "how much stuff"
question: what use cases to we want this to cover? Clearly, GETting
updates as responseText from a remote site are one. What other
functionality do we, really, want to load TW up with?
-- tomo
If you mean XMLHttpRequest-related functionality, I guess I'd want to
look at authentication (even if just basic), cache handling, error
handling, https, timeout handling, POSTs, and perhaps safe handling of
JSON payloads. At the back of my mind is the idea that we should
implement enough that a WebDAV layer could be placed over the top of
it.
Note that I'm not suggesting putting such a WebDAV layer in the core
would be a good idea, just that it's a good reference use case...
Cheers
Jeremy.
Libraries are meant to be reused, but often they require more of a
commitment than is warranted unless you are at the beginning of a
project. A better mantra is "objects are meant to be reused", and if
there is an Ajax object out there that can be lifted up and dropped
into TW then I am all for it. Practically speaking, I am finding more
and more that the only useful approach is "ideas can be reused" --
cut/paste/rejig to make it work for you.
-- tomo
I think one of the obstacles to flexible plugin management is that the
only way for the core code to read the metadata for a plugin is to
actually execute the plugin. For instance, one might quite reasonably
want to add:
versions.extensions.FormTiddlerPlugin.requiresCore = {major: 2, minor:
0, revision: 0};
Where the idea is that the plugin will be automatically disabled if
the core isn't a sufficiently recent version. But, of course, the
plugin has already been executed in order to establish what version of
the core it needs.
I'd like to propose a really simple solution: machine readable plugin
metadata. The implementation I propose is that the first table in the
tiddler is interpreted as a table of name value pairs (with an
optional type). For instance:
|!Field |!Description |!Type |
|Title |FormTiddlerPlugin |String |
|Publisher |Abego Software |String |
|PublisherUrl |http://tiddlywiki.abego-software.de |String |
So, the idea is that the core code would scan the tiddler before
execution and glean the
list of name/value pairs. The metadata would be used to determine
whether to execute the plugin, and made available via some form of
control panel.
The de facto standard for existing tiddlers is pretty similar to this.
Cheers
Jeremy.
For TiddlyWiki 3.0 I could imagine going to Prototype, say, but I
think it would be a fairly fundamental architectural change.
Cheers
Jeremy
But in looking at them, the issue with Dojo and Prototype is that they are pretty large libraries.
Even that file still has a bunch of stuff that's not going to be used
- for instance Ajax.Updater and Ajax.PeriodicalUpdater support a very
RubyOnRails pattern of interaction, and wouldn't be useful in a single
file TiddlyWiki.
I think we'll end up using code inspired by these libraries. For
instance, that ajax.js file includes a reference to a bug I've not
heard of:
http://dev.rubyonrails.org/browser/spinoffs/prototype/src/ajax.js#L124
That kind of stuff is like golddust in terms of preemptive bug fixing...
--
Jules
www.knightnet.org.uk
http://knighjm.googlepages.com/knightnet-default-tw.html
Cheers,
FYI, both ZiddlyWiki and Plugin: jsMath use the tiny ajax library
written by Tim Morgan:
http://timmorgan.org/wiki/Mini
--
Cheers,
Bob McElrath [Univ. of California at Davis, Department of Physics]
"It is almost universally felt that when we call a country
democratic we are praising it; consequently, the defenders of every
kind of regime claim that it is a democracy, and fear that they
might have to stop using the word if it were tied down to any one
meaning." -- George Orwell
The regex could pick out the extension, eval it into an extension
*object*, and then do the right thing from there.
-- tomo
I'm afraid that's only true if the syntax of the versions.extension
assignment were to be heavily restricted; otherwise your assertion
would be equivalent to saying that you thought you could create a
regexp that will parse general JavaScript.
Even with the restrictions, why bother? It's an awful lot easier to
parse the table format, and you end up with human readable values.
> The regex could pick out the extension, eval it into an extension
> *object*, and then do the right thing from there.
No, no, no! The point is to avoid eval()ing anything until we've read
the metadata and had a chance to act on it.
Cheers
Jeremy
And I don't think that it is unreasonable to restrict the syntax of
version.extensions. That is also already a de facto "standard", in the
same way you suggest that the table header is de facto standardized.
But hey, you lead, we follow.
I'd like to propose a really simple solution: machine readable plugin metadata. The implementation I propose is that the first table in the tiddler is interpreted as a table of name value pairs (with an optional type)
Dojo is a disaster or, shall we say, very promising but unripe,
undocumented and unfinished.
AJAX's inherit complexity is in the letter A - asynchrnonous. I know
the arguments for this but have not often seen arguments against it.
The "AJAX" library I wrote is technically an SJAX library (synchronous)
and it's simple, bug free and makes coding a pleasure. No more call
back functions just write procedural code.
See the function ajax.js linked from here:
http://ajaxwiki.blogsome.com/2006/03/13/first-release/
I think one of the obstacles to flexible plugin management is that the
only way for the core code to read the metadata for a plugin is to
actually execute the plugin.
I'd like to propose a really simple solution: machine readable plugin
metadata. The implementation I propose is that the first table in the
tiddler is interpreted as a table of name value pairs (with an
optional type). For instance:
|!Field |!Description |!Type |
|Title |FormTiddlerPlugin |String |
|Publisher |Abego Software |String |
|PublisherUrl |http://tiddlywiki.abego-software.de |String |
Oh my goodness, I may be able to come back into the 2.0 fold. :-) I've
been using an older version of Tiddlywiki because I had figured out
the 7 or 8 specific fixes needed for prototype to be added to a
tiddlywiki. I've not tried the ajax part (which put prototype on the
map) but it's been easy to use script.aculo.us effects and
autocompleting. I love the hightlight effect. At one point I replace
all the Tiddlywiki animation with script.aculo.us ones. But I started
to feel like I was a kid learning desktop publishing and making a
document with 15 fonts.
http://unchart.com/current/pw/tiddly1.2.38.js
has my changes. Search for 'prototype fix' and I think you'll see most of them.
Jonathan
But if the motivation is just to use Script.aculo.us effects, it would
be pretty simple to translate them into the TW animation engine;
there's none of them particularly complicated.
Cheers
Jeremy.
> I should think that the point is to avoid eval()ing the *plugin* unless
> the requirements are met...there is nothing wrong with eval(), per se,
> even if the snippet is pulled out from the plugin code. It is just a
> nice clean way to get the metadata we are after, IMNSHO.
I'm thinking about security. The reason why we want to be able to do
these checks before executing a plugin is to be able to do what we can
to verify that the code is safe. Partly it's a matter of compatibility
with new versions, but I'm also concerned with doing what we can about
malicious code. If you start with the assumption that a plugin isn't
"trusted" until these checks have been done, then executing any of
it's content is potentially dangerous.
> And I don't think that it is unreasonable to restrict the syntax of
> version.extensions.
But if you restrict the syntax to make it essentially a static
assignment then there's no advantage over the table syntax except that
it's less human readable.
I've said that we should add extensible tiddler metadata in 2.1. The
motivation for ETM is to enable people to easily add new general
tiddler properties, like "creator" or plugin specific ones like
"summary".
There are two implementations I can see for ETM. The first is to store
the data outside the content of the tiddler, in additional attributes
or sub-elements in the tiddler store (just as is done with the current
metadata). The second appraoch is to embed the data inside the
tiddler, as with this proposal, and similar to Udo's PartTiddler.
In the case of plugin metadata, I particularly like the embedded
approach because it keeps the entire plugin as a single stream of text
that can be copied and pasted in one go; hence the proposal above.
Wasteful as it may seem, my current thinking is that we should proceed
with both approaches because they both have a distinct role. For
clarity, let's call the embedded metadata the tiddler 'properties' and
the separate metadata just plain tiddler metadata.
So, all tiddlers would have metadata: at least created, modified,
modifier, title, tags and potentially further custom items. Some
tiddlers would also have properties by virtue of having a specially
formatted table of name-value pairs.
One further attraction of the property table approach is that it works
with non-JavaScript tiddlers like stylesheets and templates.
Cheers
Jeremy
I'm afraid that it is a professional (IT consultant) bad habit to spout
off without having time (or the inclination!) to think things out a bit
more.
I can understand your concerns about eval & it doesn't really matter to
us as "users" as long as everything works.
The advantage of using valid JavaScript to define the meta data is, of
course, that it makes version checking much easier from within the
plugin but I guess that, as long as there is a built-in function to
parse the standard table format, this is not really a problem. It
doesn't make sense, though to have to maintain both a table and the
versions stuff. I suggest that there be a new built in function that
reads the "table" and returns a suitable JavaScript array that can be
directly assigned to the versions object. Of course, you will still
need to fairly heavily restrict the format of the "standard" table.
I've said that we should add extensible tiddler metadata in 2.1. The
motivation for ETM is to enable people to easily add new general
tiddler properties, like "creator" or plugin specific ones like
"summary".
There are two implementations I can see for ETM. The first is to store
the data outside the content of the tiddler, in additional attributes
or sub-elements in the tiddler store (just as is done with the current
metadata). The second appraoch is to embed the data inside the
tiddler, as with this proposal, and similar to Udo's PartTiddler.
http://www.dcubed.ca/twupdate.js
In this version, I have abstracted the HTTP stuff into an AjaxHelper
class that, for the moment, does not do a ton of stuff beyond
encapsulating the browser-specific variances of using the
XMLHttpRequest object and making it a little simpler to setup and
handle a request. As far as the <<twupdate>> macro is concerned, it is
pretty much unchanged except for using this new class.
The AjaxHelper is *not* from a standard library, but is inspired by a
lot of personal experience and some good ideas from some of the class
libraries people have pointed me to. Since the code is trivially small,
I am totally fine with this.
Note that by default, the helper works asynchronously, but you can
force it to be synchronous. However, to make coding simpler, regardless
of which method you use a callback function is always required. The
format of the callback is:
callback(response, status, statusText, responseHeaders)
Depending on how you call the helper, the response will either be plain
text, or an XML document object. The responseHeaders are an associative
array of name/value pairs returned by the server. In order to push up
appropriate error handling into the caller, the status should always be
checked in your callback to ensure that a 200 is received before
munching away on the response.
Note also that the helper currently only supports three "methods": two
GETs, one for plain text and one for XML documents, and the "HEAD". Of
course, supporting POST would be a useful addition in the future.
Enjoy!
-- tomo
When we get something similar for updating plugins we will be in
heaven!!
Hey Tom,
I get to:
"Merging with existing document..."
and that's it - no more progress. Here are the steps I took...
I altered the URL to http://simonbaird.com/mptw/empty_mptw.html
(because that's what I use) and clicked on the update link. When it
reached the above message I could see it was going to take a while so
I went off for a coffee. Still like it when I returned.
Changed URL back to tiddlywiki.com and clicked on update again - same
response. Still like it now, as I type.
XPsp2, FF1502...
russ
For the sake of the science, I see this in the js console :
Error: getLocalPath is not defined
Source File: e:/tw.html
Line: 396
Interestingly, I see the message "File successfully loaded"
Makes me wonder what "loaded" means this context - loaded where?
Thanks Simon
russ
-- tomo
-- tomo
Sorry Tomo - can't confirm that. I made a typo as in
www.tidlywiki.com (missing a 'd') and saw the very obscure:
"The original file 'empty.html' does not appear to be a valid TiddlyWiki"
I don't think that's coming from you, though. Wins the award for
"Most obscure 404 message Ever" methinks!
BTW tom, that same typo (missing 'd') appears in one of your messages too ;)
russ
www.tidlywiki.com exists, I see...