exhibit 3.0 scripted demo : "nobelists" and "senate in HTML5" doesn't work???

160 views
Skip to first unread message

asmi

unread,
Apr 25, 2012, 5:31:47 AM4/25/12
to simile-...@googlegroups.com
Hi all,

Did anyone realize that the demo: http://databench.zepheira.com/demos/nobelists/nobelists.html and wiki howto provided here: http://www.simile-widgets.org/wiki/NobelistsHTML,  doesnt work somehow?? it doesnt respond to the filters / navigators at all!


I tried them in latest chrome 18 and firefox both! is it just me or ?

thanks,
asmi

ma...@coactus.com

unread,
Apr 25, 2012, 10:02:49 PM4/25/12
to simile-...@googlegroups.com
Hi again,
The Nobelists exhibit worked fine for me in both Chrome 18 and Firefox
11 on Ubuntu 64, but I did run into some strange problems with the map
and tile views in the Senate exhibit on Firefox though.

Hopefully Ryan can have a look when he returns next week.

Mark.

Sima Kan

unread,
May 11, 2012, 8:40:53 AM5/11/12
to simile-...@googlegroups.com
Hi!

I cannot view the Map or Tile views for the Senate example on the Mac either. I'm using Safari 5.0.4

Any idea why?

Thanks!
sima

Ryan Lee

unread,
May 11, 2012, 3:08:50 PM5/11/12
to simile-...@googlegroups.com
Hi all,

We've traced this down to a problem with the current extension loading
mechanism. In an attempt to keep things from shifting too much between
Exhibit 2 and Exhibit 3, I tried to allow for the form:

<script src="exhibit-api.js">
<script src="extensions/map-extension.js">

But, with the varied ways released browsers now handle the script tag,
this introduces a potential network delay in loading everything in the
right order; sometimes the map code gets loaded after Exhibit's started
to initialize itself, which is too late.

You probably weren't expecting design proposals to your question, but it
seems an opportune time to share what I've been kicking around the past
couple of days, each with its own strengths and weaknesses.

* Use LABjs

In this scenario, the only script src tag will be to load the LABjs
library, then use its loading framework inline to bring everything
related to Exhibit, including extensions, in in an orderly fashion. The
major drawback here is that it forces users who don't necessarily care
at all about code to pay attention to the actual scripting. For those
who do pay attention, it makes things a bit easier to incorporate
extra-Exhibit material into the loading process.

A related scenario would be to mask LABjs entirely with an
Exhibit-specific mechanism, but this only really adds a layer that might
allow an easier departure from LABjs if needed in the future.

* Use async / defer

HTML 5 introduces attributes to the script tag that allow the page
author to give hints to the browser about whether some scripts can load
without dependency on one another and whether some need to be run in the
order they appear in. But support is not universal across browsers.

* Abuse link rel

Instead of listing extensions (or other scripts) as actual script tags,
just point to them with

<link rel="exhibit-extension" href="...">

and let Exhibit pick out and load extensions itself during its loading
process. Other than the fact that I've never seen anybody use <link> in
this way, this might be the simplest and least obtrusive solution I
could think of. It does tend to make it even harder for those who don't
control the <head> of a document to get Exhibit in.

* Cram in more parameters

Instead of listing each extension separately, they could also be set as
additional parameters to the core of Exhibit

<script src="exhibit-api.js?extension=extensions/map-extension.js">

which (aside from taking some steps backwards into Exhibit's history) is
not as dubious as the prior proposal but makes that one line difficult
to read and assemble and additionally makes it difficult for the
extensions themselves to extract any of their own parameters; it would
probably require an ad hoc solution for adding extension-only parameters.



If you have any other ideas or feedback on the above, I'd love to hear
from you (or get a pull request from you on GitHub ;).

As for the Tile view issue, it had to do with paging and localization;
that's been fixed in trunk [1]. Perhaps we can make a new release
candidate in the near future bundling some of these fixes together.

1.
https://github.com/zepheira/exhibit3/commit/0814c0b3695bb96e79272c2b00de8b3c17d1f784

David Karger

unread,
Jun 5, 2012, 5:31:11 PM6/5/12
to simile-...@googlegroups.com
Ryan, of the scenarios you propose, I'd advocate the principle that the
user should never need to write js just to load extensions. I don't
know enough about labjs to be sure but I think this rules out direct use
of labjs, and possibly the exhibt-specific version. On the other hand,
if there were a way to use labjs "invisibly", embedding its invocations
inside the exhibit api and extensinos, it would be great.

An option you didn't mention would be to incorporate a "just in time"
approach to the extensions. As you say, exhibit runs into problems when
if it starts running before all extensions have loaded. But more
specifically, the problem only occurs when it tries to use the
functionality offered by the extension. Canonical examples include
trying to generate a view provided by an extension that hasn't loaded
yet, or to import data using an importer that hasn't loaded yet. What
if exhibit were designed such that, if it got into that situation, it
simply registered a callback to be invoked when the necessary
functionality was available? e.g., view rendering could be gated by a
"require" method that wouldn't run its argument until a corresponding
"provide" method was called. I think this is the kind of functionality
offered by labjs, right? So as long as extension authors followed the
right design pattern, invoking labjs at the right moment, we'd be ok.

Of course, you'd want to handle the case of the necessary element
*never* being provided---but I think the page's load event, which tells
you all scripts are loaded, could be used to trigger a "timeout" that
would signal an error if some necessary functionality were still missing
at that point.

I agree with you that it's premature to rely on "async" loading, and
that inline-extensions would be come a parameter management nightmare.

An alternative to abusing link tags is abusing script tags. One could
add an attribute <script ex:role="extension" src=...>; exhibit could
find such tags and use them to detect scripts it should wait for (using
onload events) before running. On the other hand, for fastest response
it would be better to use the just in time approach discussed before,
since that would allow exhibit to quickly render its initial view even
if other views in the viewpanel require specific extensions.

David Karger

unread,
Jul 3, 2012, 3:11:13 PM7/3/12
to simile-...@googlegroups.com, Ryan Lee
Here's one other option, as demonstrated by the aloha editor, leveraging
their usage of requirejs:

<script type="text/javascript" src="Aloha/lib/aloha.js"
data-aloha-plugins="common/format,
common/table,
common/list,
common/link,
common/highlighteditables,
common/block,
common/undo,
common/contenthandler,
common/paste,
common/commands,
common/abbr,
extra/browser,
extra/linkbrowser"></script>

Ryan Lee

unread,
Jul 5, 2012, 6:01:45 PM7/5/12
to simile-...@googlegroups.com
RequireJS is quite popular. We've considered looking into it at
Zepheira for Exhibit 3.0, but it's a big and somewhat experimental
change and not one we have slated for the immediate future. If you're
interested in pursuing it and submitting a pull request, I'd be happy to
look it over.

Ryan Lee

unread,
Jul 5, 2012, 6:02:15 PM7/5/12
to simile-...@googlegroups.com
As a follow on, I've already pushed an experiment using the <link>
method I discussed. We're currently considering other libraries to help
manage dependencies, too (cf., RequireJS).

On 2012-06-05 14:31 , David Karger wrote:
> Ryan, of the scenarios you propose, I'd advocate the principle that the
> user should never need to write js just to load extensions. I don't
> know enough about labjs to be sure but I think this rules out direct use
> of labjs, and possibly the exhibt-specific version. On the other hand,
> if there were a way to use labjs "invisibly", embedding its invocations
> inside the exhibit api and extensinos, it would be great.

LABjs has been in use within the Exhibit 3 codebase since it was
started. The problem with merely embedding it in Exhibit and then
allowing the specifying of extensions outside of that scheme is [see all
of previous message].

> An option you didn't mention would be to incorporate a "just in time"
> approach to the extensions. As you say, exhibit runs into problems when
> if it starts running before all extensions have loaded. But more
> specifically, the problem only occurs when it tries to use the
> functionality offered by the extension. Canonical examples include
> trying to generate a view provided by an extension that hasn't loaded
> yet, or to import data using an importer that hasn't loaded yet. What
> if exhibit were designed such that, if it got into that situation, it
> simply registered a callback to be invoked when the necessary
> functionality was available? e.g., view rendering could be gated by a
> "require" method that wouldn't run its argument until a corresponding

> "provide" method was called. I think this is the kind of functionality
> offered by labjs, right? So as long as extension authors followed the
> right design pattern, invoking labjs at the right moment, we'd be ok.

No, not at all. LABjs documentation is brief and readily available, I
suggest you read it before making suggestions on how it might be applied.

Making a UI seem responsive even if it isn't all there is a great way to
design things, but what was under discussion was load ordering - not
load transport delays. Comparing loading Exhibit, loading extensions,
loading data, and parsing data, network costs of loading extensions is
highly unlikely to be the reason the UI is blocked. It may interfere
due to indeterminate ordering; it is far less likely that it interferes
due to transport matters.

Still, if you want to redesign all of Exhibit along those lines, I'm
happy to look over a pull request. Making Exhibit initialization as
asynchronous as possible is a worthwhile goal.

> Of course, you'd want to handle the case of the necessary element
> *never* being provided---but I think the page's load event, which tells
> you all scripts are loaded, could be used to trigger a "timeout" that
> would signal an error if some necessary functionality were still missing
> at that point.

This isn't related to the general topic, but as it pertains to Exhibit,
"the page's load event" does not tell you all the scripts are loaded.
Exhibit's capacity to load additional scripts means the page load event
(which specific one you're referring to is unclear) is definitely not a
reliable indicator of completion. Exhibit itself (now reliably) fires
its own scripts loaded event.

> I agree with you that it's premature to rely on "async" loading, and
> that inline-extensions would be come a parameter management nightmare.
>
> An alternative to abusing link tags is abusing script tags. One could
> add an attribute <script ex:role="extension" src=...>; exhibit could
> find such tags and use them to detect scripts it should wait for (using
> onload events) before running. On the other hand, for fastest response
> it would be better to use the just in time approach discussed before,
> since that would allow exhibit to quickly render its initial view even
> if other views in the viewpanel require specific extensions.

Using script tags just comes back to the original problem that brought
us here, of browsers handling how they load scripts differently. If you
want Exhibit to get to the tags before the browsers themselves do, you
go back to the bad days of working with each browser's DOM ready event
and DOM manipulation inconsistencies to find them.

David Karger

unread,
Jul 5, 2012, 6:05:41 PM7/5/12
to simile-...@googlegroups.com, Ryan Lee
My suggestion wasn't to switch to requirejs, but just this approach of
listing the desired extensions as attributes in the script tag so that
exhibit could take explicit control of loading them instead of leaving
it to the browser. I'm not sure if it's a *good* idea but it seemed
different so worth pointing out.

David Karger

unread,
Jul 5, 2012, 6:29:07 PM7/5/12
to simile-...@googlegroups.com, Ryan Lee
Most of what you responded to was pure brainstorming that I don't feel
strongly about. My one serious concern is about the non-developer's
experience. Anything forcing them to use requirejs or labjs code
explicitly is bad. The experiment with the <link> method isn't that bad
but is still unfamiliar.

On the other hand, I'm happy to require any extension developer to
follow a specific contract. For example, if we forbid the extensions
from relying on any dependencies at load time, and instead require all
dependent behavior to occur in an init method, then we don't have to
worry about script load order if exhibit takes care of invoking the inits.

e.g., refining the old exhibit_onload approach, we can require every
extension script to begin with:

if (typeof(Exhibit) == 'undefined') Exhibit = {};
if (typeof(Exhibit.onload) == 'undefined') Exhibit.onload = [];

and end with:

if (Exhibit.loaded == true) {
init();
}
else {
Exhibit.onload.push(init)
}

Then exhibit core can take care of loading anything in the
Exhibit.onload queue once it is ready to do so.
I recognize that this is much more limited than what you can achieve
with labjs etc., but I see that simplicity as part of its appeal.

David Karger

unread,
Jul 5, 2012, 8:47:49 PM7/5/12
to simile-...@googlegroups.com, Ryan Lee
Here's another question/issue. The current e3 approach of associating
everything with events does a nice job of keeping everything
independent, but what if that's not what we want? For example, there's
a "registerStaticComponents" event that gets triggered when it is time
for static components to be registered. But since we then leave it up to
the individual static components to register themselves, there's no way
for my library to say "I want to run after all the static components are
registered" (which I think is what I want to do).

An alternative would be to define a set of clear "stages" in exhibit,
such as loading, initialization, configuration, and user interaction,
allow a given module to indicate that a certain function should run
during a certain stage, and then declare that stage over after all
functions allocated to it have finished. This does yoke components
together more closely, but perhaps that is a good thing?

On 7/5/2012 6:02 PM, Ryan Lee wrote:

Ryan Lee

unread,
Jul 6, 2012, 3:41:49 AM7/6/12
to simile-...@googlegroups.com
Given RequireJS is a widespread ecosystem, I'm not sure why you would
want to take on the pattern, but only in-house, foregoing all of the
other possibly useful code out there available to you. At any rate, I
*am* suggesting it as a valid development path with potential for uptake
for someone to pursue if I don't get to it first.

In case you're not clear on RequireJS use, you don't have to specify
dependencies in the HTML. You can list requirements in code. This is
where the experimenting comes in, but it seems possible that we might
adopt RequireJS without needing to amend any of the instructions for
including Exhibit in a page.

Ryan Lee

unread,
Jul 6, 2012, 3:51:46 AM7/6/12
to simile-...@googlegroups.com
On 2012-07-05 17:47 , David Karger wrote:
> Here's another question/issue. The current e3 approach of associating
> everything with events does a nice job of keeping everything
> independent, but what if that's not what we want? For example, there's
> a "registerStaticComponents" event that gets triggered when it is time
> for static components to be registered. But since we then leave it up to
> the individual static components to register themselves, there's no way
> for my library to say "I want to run after all the static components are
> registered" (which I think is what I want to do).

I would say there's an event missing, something like
registerStaticComponentsFinished. If that's something you need or if
there's some other piece of the events picture that seems incomplete,
I'm happy to look into it.

> An alternative would be to define a set of clear "stages" in exhibit,
> such as loading, initialization, configuration, and user interaction,
> allow a given module to indicate that a certain function should run
> during a certain stage, and then declare that stage over after all
> functions allocated to it have finished. This does yoke components
> together more closely, but perhaps that is a good thing?

If you think this is a good thing, I'm also happy to look over a pull
request. I've already made what I consider a good choice for making
Exhibit accessible to other code - one of the worst parts of Exhibit 2
was trying to hook into its behavior without simply overwriting every
available function, which is fragile and ended up being the way it had
to be - but if you've got something you think is better, write it up so
we can make a comparison.

Ryan Lee

unread,
Jul 6, 2012, 4:00:03 AM7/6/12
to simile-...@googlegroups.com
On 2012-07-05 15:29 , David Karger wrote:
> Most of what you responded to was pure brainstorming that I don't feel
> strongly about. My one serious concern is about the non-developer's
> experience. Anything forcing them to use requirejs or labjs code
> explicitly is bad.

I never suggested that it was good. I pointed it out to note it had
fatal drawbacks.

> The experiment with the <link> method isn't that bad
> but is still unfamiliar.

I am also pointing out to you why your suggestions are not feasible; I
get that they're a bit fluffy - you have yet to follow up these
discussions with code - but you are airing them in public as if they are
worth consideration. I understand this is part of your process, but
some of your brainstorms, light as you hold to them, have been tending
to neglect very pertinent details that make it difficult to take them
seriously enough to respond.

> On the other hand, I'm happy to require any extension developer to
> follow a specific contract. For example, if we forbid the extensions
> from relying on any dependencies at load time, and instead require all
> dependent behavior to occur in an init method, then we don't have to
> worry about script load order if exhibit takes care of invoking the inits.

Case in point. You have to take script load order into account if you
have dependencies.

> e.g., refining the old exhibit_onload approach, we can require every
> extension script to begin with:
>
> if (typeof(Exhibit) == 'undefined') Exhibit = {};
> if (typeof(Exhibit.onload) == 'undefined') Exhibit.onload = [];
>
> and end with:
>
> if (Exhibit.loaded == true) {
> init();
> }
> else {
> Exhibit.onload.push(init)
> }

It would make sense to run this only after the DOM has loaded, no? Do
you intend for this contract to require redefining cross-browser
compatible DOM load event management in each extension, given you can't
expect anything like jQuery to have loaded?

Extensions may have their own dependencies within dependencies (e.g.,
maps requires loading its own details which strongly depends on the map
provider scripts being loaded, especially if you're showing a map
immediately). How do you propose to manage loading those
sub-dependencies in the right order? Or load them in a cross browser
fashion - especially when browsers have different ideas about what order
scripts are going to be loaded in? This seems like it's just pushing
the problem down another level. Is that more code each extension would
also have to paste in and include? What happens if the contract changes?

> Then exhibit core can take care of loading anything in the
> Exhibit.onload queue once it is ready to do so.
> I recognize that this is much more limited than what you can achieve
> with labjs etc., but I see that simplicity as part of its appeal.

It is not at all simple. It sounds unsustainably onerous to me.

David Karger

unread,
Jul 6, 2012, 10:02:54 AM7/6/12
to simile-...@googlegroups.com, Ryan Lee

On 7/6/2012 3:51 AM, Ryan Lee wrote:
> On 2012-07-05 17:47 , David Karger wrote:
>> Here's another question/issue. The current e3 approach of associating
>> everything with events does a nice job of keeping everything
>> independent, but what if that's not what we want? For example, there's
>> a "registerStaticComponents" event that gets triggered when it is time
>> for static components to be registered. But since we then leave it up to
>> the individual static components to register themselves, there's no way
>> for my library to say "I want to run after all the static components are
>> registered" (which I think is what I want to do).
> I would say there's an event missing, something like
> registerStaticComponentsFinished. If that's something you need or if
> there's some other piece of the events picture that seems incomplete,
> I'm happy to look into it.
1. I'm not sure the name registerStaticComponentsFinished captures the
semantics of "the entire exhibit codebase is now initialized, and we are
now ready to do anything with exhibit that does on rely on information
specific to this page". Whether you stick with events or implement
specific stages, I think it would help to define some higher level event
names. In particular if a new initialization stage with new event names
is added in the future, it would be nice not to have to modify too much
code to listen for a different event. You've already got an implied
set of higher-level events in the headings of the scripted event api.

2. Since static components are currently registered based on their
listening for a "registerStaticComponents.exhibit" event, and you have
no way of knowing who is listening, how are you going to know that
registrations are complete in order to trigger the proposed new event?
Since we impose no contract on the listeners, it's possible that some of
them are asynchronous and are not finished when
trigger("registerStaticComponents.exhibit") returns. I suggested phases
as a way to require that every component provide both an "I am starting
registration" and "I am finished registration" indicator.


>
>> An alternative would be to define a set of clear "stages" in exhibit,
>> such as loading, initialization, configuration, and user interaction,
>> allow a given module to indicate that a certain function should run
>> during a certain stage, and then declare that stage over after all
>> functions allocated to it have finished. This does yoke components
>> together more closely, but perhaps that is a good thing?
> If you think this is a good thing, I'm also happy to look over a pull
> request. I've already made what I consider a good choice for making
> Exhibit accessible to other code - one of the worst parts of Exhibit 2
> was trying to hook into its behavior without simply overwriting every
> available function, which is fragile and ended up being the way it had
> to be - but if you've got something you think is better, write it up so
> we can make a comparison.
This proposed design change would obviously require a lot of code
changes. So I figured it would be worth deciding whether it would be a
good idea *before* making all the changes. Pull request are a great way
to propose small code changes but not such a great way to propose
high-level design changes.

Ryan Lee

unread,
Jul 9, 2012, 5:41:19 PM7/9/12
to simile-...@googlegroups.com
On 2012-07-06 07:02 , David Karger wrote:
>
> On 7/6/2012 3:51 AM, Ryan Lee wrote:
>> On 2012-07-05 17:47 , David Karger wrote:
>>> Here's another question/issue. The current e3 approach of associating
>>> everything with events does a nice job of keeping everything
>>> independent, but what if that's not what we want? For example, there's
>>> a "registerStaticComponents" event that gets triggered when it is time
>>> for static components to be registered. But since we then leave it up to
>>> the individual static components to register themselves, there's no way
>>> for my library to say "I want to run after all the static components are
>>> registered" (which I think is what I want to do).
>> I would say there's an event missing, something like
>> registerStaticComponentsFinished. If that's something you need or if
>> there's some other piece of the events picture that seems incomplete,
>> I'm happy to look into it.
> 1. I'm not sure the name registerStaticComponentsFinished captures the
> semantics of "the entire exhibit codebase is now initialized, and we are
> now ready to do anything with exhibit that does on rely on information
> specific to this page". Whether you stick with events or implement
> specific stages, I think it would help to define some higher level event
> names. In particular if a new initialization stage with new event names
> is added in the future, it would be nice not to have to modify too much
> code to listen for a different event. You've already got an implied
> set of higher-level events in the headings of the scripted event api.

So come up with some abstract names you think are worthwhile and point
out where they seem to fit best. Your phrasing makes it sound like this
is entirely on me; if you've got something you want to accomplish, I'm
probably not going to be able to guess how to get there correctly.

> 2. Since static components are currently registered based on their
> listening for a "registerStaticComponents.exhibit" event, and you have
> no way of knowing who is listening, how are you going to know that
> registrations are complete in order to trigger the proposed new event?
> Since we impose no contract on the listeners, it's possible that some of
> them are asynchronous and are not finished when
> trigger("registerStaticComponents.exhibit") returns. I suggested phases
> as a way to require that every component provide both an "I am starting
> registration" and "I am finished registration" indicator.

Static component registration is, for Exhibit's initializing purposes,
effectively instant. The code is both loaded and evaluated by the time
the signal goes out, and registration is simply informing Exhibit that
those static classes exist. In your paradigm, it would be calling start
immediately followed by end. Exhibit has no need to do anything with
the static components after they've registered, which is why there's no
signal for it and no design around that occurrence.

I did consider the exact drawback you're hammering on, and given what I
just described, it seemed reasonable to let it be. If you have some
specific case for me to look at that illustrates that it could be
better, by all means, let's see if some events are better made to be
blocking and synchronous instead of reinventing everything.

>>> An alternative would be to define a set of clear "stages" in exhibit,
>>> such as loading, initialization, configuration, and user interaction,
>>> allow a given module to indicate that a certain function should run
>>> during a certain stage, and then declare that stage over after all
>>> functions allocated to it have finished. This does yoke components
>>> together more closely, but perhaps that is a good thing?
>> If you think this is a good thing, I'm also happy to look over a pull
>> request. I've already made what I consider a good choice for making
>> Exhibit accessible to other code - one of the worst parts of Exhibit 2
>> was trying to hook into its behavior without simply overwriting every
>> available function, which is fragile and ended up being the way it had
>> to be - but if you've got something you think is better, write it up so
>> we can make a comparison.
> This proposed design change would obviously require a lot of code
> changes. So I figured it would be worth deciding whether it would be a
> good idea *before* making all the changes. Pull request are a great way
> to propose small code changes but not such a great way to propose
> high-level design changes.

There is certainly a risk involved in investing effort into a branch
that doesn't ultimately get adopted.

Let me be more clear: the time for these design discussions was a rather
long time ago. If you want to revisit them, that's your experiment to
undertake. Convince me with code your ideas are worth following or
settle down and help improve what's already there. It seems to me that
it's quite possible it doesn't need to be thrown away wholesale for an
entirely new branch.
Reply all
Reply to author
Forward
0 new messages