* \brief We use js function closure to be able to pass the query (array)
* to the callback function used when data is received
*/
- success_closure: function(query, publish_uuid, callback /*domid*/) {
+ success_closure: function(query, publish_uuid, callback) {
return function(data, textStatus) {
- manifold.asynchroneous_success(data, query, publish_uuid, callback /*domid*/);
+ manifold.asynchroneous_success(data, query, publish_uuid, callback);
}
},
// manifold.raise_record_event(sq.query_uuid, IN_PROGRESS);
//});
- $.post(manifold.proxy_url, {'json': query_json} , manifold.success_closure(query, null, callback /*domid*/));
+ $.post(manifold.proxy_url, {'json': query_json} , manifold.success_closure(query, null, callback));
},
- // Executes all async. queries
- // input queries are specified as a list of {'query_uuid': <query_uuid>, 'id': <possibly null>}
- asynchroneous_exec : function (query_publish_dom_tuples) {
-// start spinners - be robust if the spin stuff was not loaded for any reason
-// turned off because each plugin is responsible for doing that through on_query_in_progress
-// try {
-// var subjects=$(".need-spin");
-// if (manifold.asynchroneous_debug) {
-// messages.debug("Turning on spin with " + subjects.length + " matches for .need-spin");
-// $.map (subjects, function (subject) { messages.debug("need-spin: "+ subject.id);});
-// }
-// subjects.spin(manifold.spin_presets);
-// } catch (err) { messages.debug("Cannot turn on spins " + err); }
+ // Executes all async. queries - intended for the javascript header to initialize queries
+ // input queries are specified as a list of {'query_uuid': <query_uuid> }
+ // each plugin is responsible for managing its spinner through on_query_in_progress
+ asynchroneous_exec : function (query_exec_tuples) {
// Loop through input array, and use publish_uuid to publish back results
- $.each(query_publish_dom_tuples, function(index, tuple) {
+ $.each(query_exec_tuples, function(index, tuple) {
var query=manifold.find_query(tuple.query_uuid);
var query_json=JSON.stringify (query);
var publish_uuid=tuple.publish_uuid;
// not quite sure what happens if we send a string directly, as POST data is named..
// this gets reconstructed on the proxy side with ManifoldQuery.fill_from_POST
$.post(manifold.proxy_url, {'json':query_json},
- manifold.success_closure(query, publish_uuid, tuple.callback /*domid*/));
+ manifold.success_closure(query, publish_uuid, tuple.callback));
})
},
* \brief Forward a query to the manifold backend
* \param query (dict) the query to be executed asynchronously
* \param callback (function) the function to be called when the query terminates
- * Deprecated:
- * \param domid (string) the domid to be notified about the results (null for using the pub/sub system
*/
- forward: function(query, callback /*domid*/) {
+ forward: function(query, callback) {
var query_json = JSON.stringify(query);
$.post(manifold.proxy_url, {'json': query_json} ,
- manifold.success_closure(query, query.query_uuid, callback/*domid*/));
+ manifold.success_closure(query, query.query_uuid, callback));
},
/*!
}
},
- // if set domid allows the result to be directed to just one plugin
+ // if set callback is provided it is called
// most of the time publish_uuid will be query.query_uuid
// however in some cases we wish to publish the result under a different uuid
// e.g. an updater wants to publish its result as if from the original (get) query
- asynchroneous_success : function (data, query, publish_uuid, callback /*domid*/) {
+ asynchroneous_success : function (data, query, publish_uuid, callback) {
// xxx should have a nicer declaration of that enum in sync with the python code somehow
var start = new Date();
if (manifold.asynchroneous_debug)
messages.debug(">>>>>>>>>> asynchroneous_success query.object=" + query.object);
- /* If a callback has been specified, we redirect results to it */
- if (!!callback) {
- callback(data);
- if (manifold.asynchroneous_debug) {
- duration=new Date()-start;
- messages.debug ("<<<<<<<<<< asynchroneous_success " + query.object + " -- callback ended " + duration + " ms");
- }
- return;
- }
-
if (data.code == 2) { // ERROR
// We need to make sense of error codes here
alert("Your session has expired, please log in again");
if (publish_uuid)
$.publish("/results/" + publish_uuid + "/failed", [data.code, data.description] );
-/* DEMO - Debug Messages desactivated
- $("#notifications").notify("create", "sticky", {
- title: 'Warning',
- text: data.description
- },{
- expires: false,
- speed: 1000
- });
-*/
}
+
+ // If a callback has been specified, we redirect results to it
+ if (!!callback) {
+ callback(data);
+ if (manifold.asynchroneous_debug) {
+ duration=new Date()-start;
+ messages.debug ("<<<<<<<<<< asynchroneous_success " + query.object + " -- callback ended " + duration + " ms");
+ }
+ return;
+ }
+
if (manifold.asynchroneous_debug)
messages.debug ("========== asynchroneous_success " + query.object + " -- before process_query_records");
raise_event_handler: function(type, query_uuid, event_type, value) {
if ((type != 'query') && (type != 'record'))
throw 'Incorrect type for manifold.raise_event()';
+ // xxx we observe quite a lot of incoming calls with an undefined query_uuid
+ // this should be fixed upstream
+ if (query_uuid === undefined) {
+ messages.warning("undefined query in raise_event_handler");
+ return;
+ }
+ // notify the change to objects that either listen to this channel specifically,
+ // or to the wildcard channel
var channels = [ manifold.get_channel(type, query_uuid), manifold.get_channel(type, '*') ];
$.each(channels, function(i, channel) {
def json_settings_list (self):
return [ 'plugin_uuid', 'levels' ]
- # and we don't need a spin wheel
- def start_with_spin (self):
- return False
}
def json_settings_list (self): return ['plugin_uuid','query_uuid']
-
- # because we have a link to a query it looks like we need a spin, let's make this right
- def start_with_spin (self): return False
def json_settings_list (self):
return ['plugin_uuid', 'domid', 'query_uuid']
- def export_json_settings (self):
- return True
def json_settings_list (self):
return []
- def export_json_settings(self):
- return True
result={'query_uuid':a}
if b: result['domid']=b
return result
- env['query_publish_dom_tuples'] = [ query_publish_dom_tuple (a,b) for (a,b) in self._queue ]
+ env['query_exec_tuples'] = [ query_publish_dom_tuple (a,b) for (a,b) in self._queue ]
javascript = render_to_string ("page-queries.js",env)
self.add_js_chunks (javascript)
# self.reset_queue()
self.expose_js_manifold_config()
-# DEPRECATED # # needs to be called explicitly and only when metadata is actually required
-# DEPRECATED # # in particular user needs to be logged
-# DEPRECATED # def get_metadata (self):
-# DEPRECATED # # look in session's cache - we don't want to retrieve this for every request
-# DEPRECATED # session=self.request.session
-# DEPRECATED # if 'manifold' not in session:
-# DEPRECATED # print "Page.expose_js_metadata: no 'manifold' in session... - cannot retrieve metadata - skipping"
-# DEPRECATED # return
-# DEPRECATED # manifold=session['manifold']
-# DEPRECATED # # if cached, use it
-# DEPRECATED # if 'metadata' in manifold and isinstance(manifold['metadata'],MetaData):
-# DEPRECATED # if debug: print "Page.get_metadata: return cached value"
-# DEPRECATED # return manifold['metadata']
-# DEPRECATED # # otherwise retrieve it
-# DEPRECATED # manifold_api_session_auth = session['manifold']['auth']
-# DEPRECATED # print "get_metadata(), manifold_api_session_auth =", session['manifold']['auth']
-# DEPRECATED # metadata=MetaData (manifold_api_session_auth)
-# DEPRECATED # metadata.fetch()
-# DEPRECATED # # store it for next time
-# DEPRECATED # manifold['metadata']=metadata
-# DEPRECATED # if debug: print "Page.get_metadata: return new value"
-# DEPRECATED # return metadata
-
# needs to be called explicitly and only when metadata is actually required
# in particular user needs to be logged
def get_metadata (self):
return metadata
def expose_js_metadata (self):
- # export in this js global...
- self.add_js_chunks("var MANIFOLD_METADATA =" + self.get_metadata().to_json() + ";")
+ # expose global MANIFOLD_METADATA as a js variable
+ # xxx this is fetched synchroneously..
+ self.add_js_init_chunks("var MANIFOLD_METADATA =" + self.get_metadata().to_json() + ";")
def expose_js_manifold_config (self):
config=Config()
- self.add_js_chunks(config.manifold_js_export())
+ self.add_js_init_chunks(config.manifold_js_export())
#################### requirements/prelude management
# just forward to self.prelude - see decorator above
@to_prelude
def add_css_files (self):pass
@to_prelude
+ def add_js_init_chunks (self):pass
+ @to_prelude
def add_js_chunks (self):pass
@to_prelude
def add_css_chunks (self):pass
def export_json_settings (self):
return 'query_uuid' in self.json_settings_list()
- # by default we create a timer if there's a query attached, redefine to change this behaviour
- def start_with_spin (self):
- return self.export_json_settings()
-
# returns the html code for that plugin
# in essence, wraps the results of self.render_content ()
def render (self, request):
# shove this into plugin.html
env = {}
env ['plugin_content']= plugin_content
- # need_spin is used in plugin.html
- self.need_spin=self.start_with_spin()
env.update(self.__dict__)
# translate high-level 'toggled' into 4 different booleans
self.need_toggle = False
env ['settings_json' ] = self.settings_json()
# compute plugin-specific initialization
js_init = render_to_string ( 'plugin-init.js', env )
- self.add_js_chunks (js_init)
+ # make sure this happens first in js
+ self.add_js_init_chunks (js_init)
# interpret the result of requirements ()
self.handle_requirements (request)
@to_prelude
def add_css_files (self):pass
@to_prelude
+ def add_js_init_chunks (self):pass
+ @to_prelude
def add_js_chunks (self):pass
@to_prelude
def add_css_chunks (self):pass
#
# whether we export the json settings to js
# def export_json_settings (self)
- #
- # whether we show an initial spinner
- # def start_with_spin (self)
from django.template.loader import render_to_string
-debug=True
+debug=False
+# the need for js_init_chunks is because we need to have the plugins initialized
+# before the queries fly
+# and when writing a view it is not very easy to remember in which order
+# all the js initialization will end up, so we use these 2 categories
+# as a simple way to enforce this dependency
+# far from perfect but good enough for now
class Prelude:
- """A class for collecting dependencies on js/css files or fragments"""
+ """A class for collecting dependencies on js/css stuff
+ files are expected from your 'static' area, typically 'css/foo.css' or 'js/foo.js'
+ fragments (chunks) is for raw code
+ you can specify a string or a list of strings
+ js_init_chunks get collated with js_chunks but come first
+ """
- keys=[ 'js_files','css_files','js_chunks', 'css_chunks' ]
- def __init__ (self, js_files=None, css_files=None, js_chunks=None, css_chunks=None):
+ keys=[ 'js_files', 'css_files', 'js_init_chunks', 'js_chunks', 'css_chunks' ]
+ def __init__ (self, js_files=None, css_files=None, js_init_chunks=None, js_chunks=None, css_chunks=None):
# it's tempting to use sets but sets are not ordered..
self.js_files = Prelude._normalize(js_files)
self.css_files = Prelude._normalize(css_files)
+ self.js_init_chunks = Prelude._normalize(js_init_chunks)
self.js_chunks = Prelude._normalize(js_chunks)
self.css_chunks= Prelude._normalize(css_chunks)
def add_css_files (self, x):
for i in Prelude._normalize (x):
if i not in self.css_files: self.css_files.append(i)
+ def add_js_init_chunks (self, x):
+ self.js_init_chunks += Prelude._normalize (x)
def add_js_chunks (self, x):
self.js_chunks += Prelude._normalize (x)
def add_css_chunks (self, x):
def inspect_string (self,msg):
result = 'Prelude.inspect %s (%s) with '%(msg,self)
- result += ",".join( [ "%s->%s"%(k,len(getattr(self,k))) for k in ['js_files','js_chunks','css_files','css_chunks'] ] )
+ result += ",".join( [ "%s->%s"%(k,len(getattr(self,k))) for k in Prelude.keys ] )
return result
def inspect (self,msg):
print self.inspect_string(msg)
env={}
env['js_urls'] = [ Prelude.full_url (js_file) for js_file in self.js_files ]
env['css_urls'] = [ Prelude.full_url (css_file) for css_file in self.css_files ]
- env['js_chunks']= self.js_chunks
+ env['all_js_chunks']= self.js_init_chunks + self.js_chunks
env['css_chunks']=self.css_chunks
if debug:
- print "prelude has %d js_files, %d css files, %d js chunks and %d css_chunks"%\
- (len(self.js_files),len(self.css_files),len(self.js_chunks),len(self.css_chunks),)
+ print "prelude has %d js_files, %d css files, (%d+%d) js chunks and %d css_chunks"%\
+ (len(self.js_files),len(self.css_files),len(self.js_init_chunks),len(self.js_chunks),len(self.css_chunks),)
# render this with prelude.html and put the result in header_prelude
header_prelude = render_to_string ('prelude.html',env)
return { 'header_prelude' : header_prelude }
{% for json in queries_json %}manifold.insert_query({{ json|safe }});
{% endfor %}
$(document).ready(function () {
-var query_publish_dom_tuples = new Array();
-{% for d in query_publish_dom_tuples %}try {query_publish_dom_tuples.push({'query_uuid':"{{ d.query_uuid }}"{%if d.domid %},'domid':"{{ d.domid }}"{% endif %}}) }
-catch(err){messages.debug ("Could not expose query {{ d.query_uuid }}")}
+var query_exec_tuples = [];
+{% for tuple in query_exec_tuples %} query_exec_tuples.push({'query_uuid':"{{ tuple.query_uuid }}"});
{% endfor %}
-manifold.asynchroneous_exec(query_publish_dom_tuples);
+manifold.asynchroneous_exec(query_exec_tuples);
})
{% if visible %}
-<div id='complete-{{ domid }}' class='{% if need_toggle %}plugin-toggle{% endif %}{% if need_spin %} need-spin{% endif %}{% if persistent_toggle %} persistent-toggle{% endif %}{% if outline_complete %} plugin-outline-complete{% endif %}'>
+<div id='complete-{{ domid }}' class='{% if need_toggle %}plugin-toggle{% endif %}{% if persistent_toggle %} persistent-toggle{% endif %}{% if outline_complete %} plugin-outline-complete{% endif %}'>
{% if togglable %}
<h4 id='show-{{ domid }}' class='plugin-show'{% if not display_show_button %} style='display:none;'{% endif %}>
<span class="glyphicon glyphicon-chevron-right"></span>
{% endfor %}
{% for css_url in css_urls %} <link rel='stylesheet' type='text/css' href='{{ css_url|safe }}' />
{% endfor %}
-<script type="text/javascript"> {% for js_chunk in js_chunks %} {{ js_chunk|safe }} {% endfor %} </script>
+<script type="text/javascript"> {% for js_chunk in all_js_chunks %} {{ js_chunk|safe }} {% endfor %} </script>
<style type="text/css"> {% for css_chunk in css_chunks %} {{ css_chunk|safe }} {% endfor %} </style>