datahub/docs/src/view.multiview.html
2015-03-06 15:32:03 -03:00

1049 lines
45 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html>
<head>
<title>view.multiview.js</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, target-densitydpi=160dpi, initial-scale=1.0; maximum-scale=1.0; user-scalable=0;">
<link rel="stylesheet" media="all" href="docco.css" />
</head>
<body>
<div id="container">
<div id="background"></div>
<ul id="jump_to">
<li>
<a class="large" href="javascript:void(0);">Jump To &hellip;</a>
<a class="small" href="javascript:void(0);">+</a>
<div id="jump_wrapper">
<div id="jump_page_wrapper">
<div id="jump_page">
<a class="source" href="backend.dataproxy.html">
backend.dataproxy.js
</a>
<a class="source" href="backend.memory.html">
backend.memory.js
</a>
<a class="source" href="ecma-fixes.html">
ecma-fixes.js
</a>
<a class="source" href="model.html">
model.js
</a>
<a class="source" href="view.flot.html">
view.flot.js
</a>
<a class="source" href="view.graph.html">
view.graph.js
</a>
<a class="source" href="view.grid.html">
view.grid.js
</a>
<a class="source" href="view.map.html">
view.map.js
</a>
<a class="source" href="view.multiview.html">
view.multiview.js
</a>
<a class="source" href="view.slickgrid.html">
view.slickgrid.js
</a>
<a class="source" href="view.timeline.html">
view.timeline.js
</a>
<a class="source" href="widget.facetviewer.html">
widget.facetviewer.js
</a>
<a class="source" href="widget.fields.html">
widget.fields.js
</a>
<a class="source" href="widget.filtereditor.html">
widget.filtereditor.js
</a>
<a class="source" href="widget.pager.html">
widget.pager.js
</a>
<a class="source" href="widget.queryeditor.html">
widget.queryeditor.js
</a>
<a class="source" href="widget.valuefilter.html">
widget.valuefilter.js
</a>
</div>
</div>
</li>
</ul>
<ul class="sections">
<li id="title">
<div class="annotation">
<h1>view.multiview.js</h1>
</div>
</li>
<li id="section-1">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-1">&#182;</a>
</div>
</div>
<div class="content"><div class='highlight'><pre><span class="hljs-comment">/*jshint multistr:true */</span></pre></div></div>
</li>
<li id="section-2">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-2">&#182;</a>
</div>
<p>Standard JS module setup</p>
</div>
<div class="content"><div class='highlight'><pre><span class="hljs-keyword">this</span>.recline = <span class="hljs-keyword">this</span>.recline || {};
<span class="hljs-keyword">this</span>.recline.View = <span class="hljs-keyword">this</span>.recline.View || {};
(<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">($, my)</span> </span>{
<span class="hljs-pi"> "use strict"</span>;</pre></div></div>
</li>
<li id="section-3">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-3">&#182;</a>
</div>
<h2 id="multiview">MultiView</h2>
<p>Manage multiple views together along with query editor etc. Usage:</p>
<pre>
var myExplorer = new recline.View.MultiView({
model: {{recline.Model.Dataset instance}}
el: {{an existing dom element}}
views: {{dataset views}}
state: {{state configuration -- see below}}
});
</pre>
<h3 id="parameters">Parameters</h3>
<p><strong>model</strong>: (required) recline.model.Dataset instance.</p>
<p><strong>el</strong>: (required) DOM element to bind to. NB: the element already
being in the DOM is important for rendering of some subviews (e.g.
Graph).</p>
<p><strong>views</strong>: (optional) the dataset views (Grid, Graph etc) for
MultiView to show. This is an array of view hashes. If not provided
initialize with (recline.View.)Grid, Graph, and Map views (with obvious id
and labels!).</p>
<pre>
var views = [
{
id: 'grid', // used for routing
label: 'Grid', // used for view switcher
view: new recline.View.Grid({
model: dataset
})
},
{
id: 'graph',
label: 'Graph',
view: new recline.View.Graph({
model: dataset
})
}
];
</pre>
<p><strong>sidebarViews</strong>: (optional) the sidebar views (Filters, Fields) for
MultiView to show. This is an array of view hashes. If not provided
initialize with (recline.View.)FilterEditor and Fields views (with obvious
id and labels!).</p>
<pre>
var sidebarViews = [
{
id: 'filterEditor', // used for routing
label: 'Filters', // used for view switcher
view: new recline.View.FilterEditor({
model: dataset
})
},
{
id: 'fieldsView',
label: 'Fields',
view: new recline.View.Fields({
model: dataset
})
}
];
</pre>
<p><strong>state</strong>: standard state config for this view. This state is slightly
special as it includes config of many of the subviews.</p>
<pre>
var state = {
query: {dataset query state - see dataset.queryState object}
'view-{id1}': {view-state for this view}
'view-{id2}': {view-state for }
...
// Explorer
currentView: id of current view (defaults to first view if not specified)
readOnly: (default: false) run in read-only mode
}
</pre>
<p>Note that at present we do <em>not</em> serialize information about the actual set
of views in use — e.g. those specified by the views argument — but instead
expect either that the default views are fine or that the client to have
initialized the MultiView with the relevant views themselves.</p>
</div>
<div class="content"><div class='highlight'><pre>my.MultiView = Backbone.View.extend({
template: <span class="hljs-string">' \
&lt;div class="recline-data-explorer"&gt; \
&lt;div class="alert-messages"&gt;&lt;/div&gt; \
\
&lt;div class="header clearfix"&gt; \
&lt;div class="navigation"&gt; \
&lt;div class="btn-group" data-toggle="buttons-radio"&gt; \
{{#views}} \
&lt;button href="#{{id}}" data-view="{{id}}" class="btn btn-default"&gt;{{label}}&lt;/button&gt; \
{{/views}} \
&lt;/div&gt; \
&lt;/div&gt; \
&lt;div class="recline-results-info"&gt; \
&lt;span class="doc-count"&gt;{{recordCount}}&lt;/span&gt; records\
&lt;/div&gt; \
&lt;div class="menu-right"&gt; \
&lt;div class="btn-group" data-toggle="buttons-checkbox"&gt; \
{{#sidebarViews}} \
&lt;button href="#" data-action="{{id}}" class="btn btn-default"&gt;{{label}}&lt;/button&gt; \
{{/sidebarViews}} \
&lt;/div&gt; \
&lt;/div&gt; \
&lt;div class="query-editor-here" style="display:inline;"&gt;&lt;/div&gt; \
&lt;/div&gt; \
&lt;div class="data-view-sidebar"&gt;&lt;/div&gt; \
&lt;div class="data-view-container"&gt;&lt;/div&gt; \
&lt;/div&gt; \
'</span>,
events: {
<span class="hljs-string">'click .menu-right button'</span>: <span class="hljs-string">'_onMenuClick'</span>,
<span class="hljs-string">'click .navigation button'</span>: <span class="hljs-string">'_onSwitchView'</span>
},
initialize: <span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">(options)</span> </span>{
<span class="hljs-keyword">var</span> self = <span class="hljs-keyword">this</span>;
<span class="hljs-keyword">this</span>._setupState(options.state);</pre></div></div>
</li>
<li id="section-4">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-4">&#182;</a>
</div>
<p>Hash of page views (i.e. those for whole page) keyed by page name</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (options.views) {
<span class="hljs-keyword">this</span>.pageViews = options.views;
} <span class="hljs-keyword">else</span> {
<span class="hljs-keyword">this</span>.pageViews = [{
id: <span class="hljs-string">'grid'</span>,
label: <span class="hljs-string">'Grid'</span>,
view: <span class="hljs-keyword">new</span> my.SlickGrid({
model: <span class="hljs-keyword">this</span>.model,
state: <span class="hljs-keyword">this</span>.state.get(<span class="hljs-string">'view-grid'</span>)
})
}, {
id: <span class="hljs-string">'graph'</span>,
label: <span class="hljs-string">'Graph'</span>,
view: <span class="hljs-keyword">new</span> my.Graph({
model: <span class="hljs-keyword">this</span>.model,
state: <span class="hljs-keyword">this</span>.state.get(<span class="hljs-string">'view-graph'</span>)
})
}, {
id: <span class="hljs-string">'map'</span>,
label: <span class="hljs-string">'Map'</span>,
view: <span class="hljs-keyword">new</span> my.Map({
model: <span class="hljs-keyword">this</span>.model,
state: <span class="hljs-keyword">this</span>.state.get(<span class="hljs-string">'view-map'</span>)
})
}, {
id: <span class="hljs-string">'timeline'</span>,
label: <span class="hljs-string">'Timeline'</span>,
view: <span class="hljs-keyword">new</span> my.Timeline({
model: <span class="hljs-keyword">this</span>.model,
state: <span class="hljs-keyword">this</span>.state.get(<span class="hljs-string">'view-timeline'</span>)
})
}];
}</pre></div></div>
</li>
<li id="section-5">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-5">&#182;</a>
</div>
<p>Hashes of sidebar elements</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span>(options.sidebarViews) {
<span class="hljs-keyword">this</span>.sidebarViews = options.sidebarViews;
} <span class="hljs-keyword">else</span> {
<span class="hljs-keyword">this</span>.sidebarViews = [{
id: <span class="hljs-string">'filterEditor'</span>,
label: <span class="hljs-string">'Filters'</span>,
view: <span class="hljs-keyword">new</span> my.FilterEditor({
model: <span class="hljs-keyword">this</span>.model
})
}, {
id: <span class="hljs-string">'fieldsView'</span>,
label: <span class="hljs-string">'Fields'</span>,
view: <span class="hljs-keyword">new</span> my.Fields({
model: <span class="hljs-keyword">this</span>.model
})
}];
}</pre></div></div>
</li>
<li id="section-6">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-6">&#182;</a>
</div>
<p>these must be called after pageViews are created</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">this</span>.render();
<span class="hljs-keyword">this</span>._bindStateChanges();
<span class="hljs-keyword">this</span>._bindFlashNotifications();</pre></div></div>
</li>
<li id="section-7">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-7">&#182;</a>
</div>
<p>now do updates based on state (need to come after render)</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (<span class="hljs-keyword">this</span>.state.get(<span class="hljs-string">'readOnly'</span>)) {
<span class="hljs-keyword">this</span>.setReadOnly();
}
<span class="hljs-keyword">if</span> (<span class="hljs-keyword">this</span>.state.get(<span class="hljs-string">'currentView'</span>)) {
<span class="hljs-keyword">this</span>.updateNav(<span class="hljs-keyword">this</span>.state.get(<span class="hljs-string">'currentView'</span>));
} <span class="hljs-keyword">else</span> {
<span class="hljs-keyword">this</span>.updateNav(<span class="hljs-keyword">this</span>.pageViews[<span class="hljs-number">0</span>].id);
}
<span class="hljs-keyword">this</span>._showHideSidebar();
<span class="hljs-keyword">this</span>.listenTo(<span class="hljs-keyword">this</span>.model, <span class="hljs-string">'query:start'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">()</span> </span>{
self.notify({loader: <span class="hljs-literal">true</span>, persist: <span class="hljs-literal">true</span>});
});
<span class="hljs-keyword">this</span>.listenTo(<span class="hljs-keyword">this</span>.model, <span class="hljs-string">'query:done'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">()</span> </span>{
self.clearNotifications();
self.$el.find(<span class="hljs-string">'.doc-count'</span>).text(self.model.recordCount || <span class="hljs-string">'Unknown'</span>);
});
<span class="hljs-keyword">this</span>.listenTo(<span class="hljs-keyword">this</span>.model, <span class="hljs-string">'query:fail'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">(error)</span> </span>{
self.clearNotifications();
<span class="hljs-keyword">var</span> msg = <span class="hljs-string">''</span>;
<span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span>(error) == <span class="hljs-string">'string'</span>) {
msg = error;
} <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span>(error) == <span class="hljs-string">'object'</span>) {
<span class="hljs-keyword">if</span> (error.title) {
msg = error.title + <span class="hljs-string">': '</span>;
}
<span class="hljs-keyword">if</span> (error.message) {
msg += error.message;
}
} <span class="hljs-keyword">else</span> {
msg = <span class="hljs-string">'There was an error querying the backend'</span>;
}
self.notify({message: msg, category: <span class="hljs-string">'error'</span>, persist: <span class="hljs-literal">true</span>});
});</pre></div></div>
</li>
<li id="section-8">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-8">&#182;</a>
</div>
<p>retrieve basic data like fields etc
note this.model and dataset returned are the same
TODO: set query state …?</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">this</span>.model.queryState.set(self.state.get(<span class="hljs-string">'query'</span>), {silent: <span class="hljs-literal">true</span>});
},
setReadOnly: <span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">()</span> </span>{
<span class="hljs-keyword">this</span>.$el.addClass(<span class="hljs-string">'recline-read-only'</span>);
},
render: <span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">()</span> </span>{
<span class="hljs-keyword">var</span> tmplData = <span class="hljs-keyword">this</span>.model.toTemplateJSON();
tmplData.views = <span class="hljs-keyword">this</span>.pageViews;
tmplData.sidebarViews = <span class="hljs-keyword">this</span>.sidebarViews;
<span class="hljs-keyword">var</span> template = Mustache.render(<span class="hljs-keyword">this</span>.template, tmplData);
<span class="hljs-keyword">this</span>.$el.html(template);</pre></div></div>
</li>
<li id="section-9">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-9">&#182;</a>
</div>
<p>now create and append other views</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> $dataViewContainer = <span class="hljs-keyword">this</span>.$el.find(<span class="hljs-string">'.data-view-container'</span>);
<span class="hljs-keyword">var</span> $dataSidebar = <span class="hljs-keyword">this</span>.$el.find(<span class="hljs-string">'.data-view-sidebar'</span>);</pre></div></div>
</li>
<li id="section-10">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-10">&#182;</a>
</div>
<p>the main views</p>
</div>
<div class="content"><div class='highlight'><pre> _.each(<span class="hljs-keyword">this</span>.pageViews, <span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">(view, pageName)</span> </span>{
view.view.render();
<span class="hljs-keyword">if</span> (view.view.redraw) {
view.view.redraw();
}
$dataViewContainer.append(view.view.el);
<span class="hljs-keyword">if</span> (view.view.elSidebar) {
$dataSidebar.append(view.view.elSidebar);
}
});
_.each(<span class="hljs-keyword">this</span>.sidebarViews, <span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">(view)</span> </span>{
<span class="hljs-keyword">this</span>[<span class="hljs-string">'$'</span>+view.id] = view.view.$el;
$dataSidebar.append(view.view.el);
}, <span class="hljs-keyword">this</span>);
<span class="hljs-keyword">this</span>.pager = <span class="hljs-keyword">new</span> recline.View.Pager({
model: <span class="hljs-keyword">this</span>.model
});
<span class="hljs-keyword">this</span>.$el.find(<span class="hljs-string">'.recline-results-info'</span>).after(<span class="hljs-keyword">this</span>.pager.el);
<span class="hljs-keyword">this</span>.queryEditor = <span class="hljs-keyword">new</span> recline.View.QueryEditor({
model: <span class="hljs-keyword">this</span>.model.queryState
});
<span class="hljs-keyword">this</span>.$el.find(<span class="hljs-string">'.query-editor-here'</span>).append(<span class="hljs-keyword">this</span>.queryEditor.el);
},
remove: <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-params">()</span> </span>{
_.each(<span class="hljs-keyword">this</span>.pageViews, <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-params">(view)</span> </span>{
view.view.remove();
});
_.each(<span class="hljs-keyword">this</span>.sidebarViews, <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-params">(view)</span> </span>{
view.view.remove();
});
<span class="hljs-keyword">this</span>.pager.remove();
<span class="hljs-keyword">this</span>.queryEditor.remove();
Backbone.View.prototype.remove.apply(<span class="hljs-keyword">this</span>, <span class="hljs-built_in">arguments</span>);
},</pre></div></div>
</li>
<li id="section-11">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-11">&#182;</a>
</div>
<p>hide the sidebar if empty</p>
</div>
<div class="content"><div class='highlight'><pre> _showHideSidebar: <span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">()</span> </span>{
<span class="hljs-keyword">var</span> $dataSidebar = <span class="hljs-keyword">this</span>.$el.find(<span class="hljs-string">'.data-view-sidebar'</span>);
<span class="hljs-keyword">var</span> visibleChildren = $dataSidebar.children().filter(<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">()</span> </span>{
<span class="hljs-keyword">return</span> $(<span class="hljs-keyword">this</span>).css(<span class="hljs-string">"display"</span>) != <span class="hljs-string">"none"</span>;
}).length;
<span class="hljs-keyword">if</span> (visibleChildren &gt; <span class="hljs-number">0</span>) {
$dataSidebar.show();
} <span class="hljs-keyword">else</span> {
$dataSidebar.hide();
}
},
updateNav: <span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">(pageName)</span> </span>{
<span class="hljs-keyword">this</span>.$el.find(<span class="hljs-string">'.navigation button'</span>).removeClass(<span class="hljs-string">'active'</span>);
<span class="hljs-keyword">var</span> $el = <span class="hljs-keyword">this</span>.$el.find(<span class="hljs-string">'.navigation button[data-view="'</span> + pageName + <span class="hljs-string">'"]'</span>);
$el.addClass(<span class="hljs-string">'active'</span>);</pre></div></div>
</li>
<li id="section-12">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-12">&#182;</a>
</div>
<p>add/remove sidebars and hide inactive views</p>
</div>
<div class="content"><div class='highlight'><pre> _.each(<span class="hljs-keyword">this</span>.pageViews, <span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">(view, idx)</span> </span>{
<span class="hljs-keyword">if</span> (view.id === pageName) {
view.view.$el.show();
<span class="hljs-keyword">if</span> (view.view.elSidebar) {
view.view.elSidebar.show();
}
} <span class="hljs-keyword">else</span> {
view.view.$el.hide();
<span class="hljs-keyword">if</span> (view.view.elSidebar) {
view.view.elSidebar.hide();
}
<span class="hljs-keyword">if</span> (view.view.hide) {
view.view.hide();
}
}
});
<span class="hljs-keyword">this</span>._showHideSidebar();</pre></div></div>
</li>
<li id="section-13">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-13">&#182;</a>
</div>
<p>call view.view.show after sidebar visibility has been determined so
that views can correctly calculate their maximum width</p>
</div>
<div class="content"><div class='highlight'><pre> _.each(<span class="hljs-keyword">this</span>.pageViews, <span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">(view, idx)</span> </span>{
<span class="hljs-keyword">if</span> (view.id === pageName) {
<span class="hljs-keyword">if</span> (view.view.show) {
view.view.show();
}
}
});
},
_onMenuClick: <span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">(e)</span> </span>{
e.preventDefault();
<span class="hljs-keyword">var</span> action = $(e.target).attr(<span class="hljs-string">'data-action'</span>);
<span class="hljs-keyword">this</span>[<span class="hljs-string">'$'</span>+action].toggle();
<span class="hljs-keyword">this</span>._showHideSidebar();
},
_onSwitchView: <span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">(e)</span> </span>{
e.preventDefault();
<span class="hljs-keyword">var</span> viewName = $(e.target).attr(<span class="hljs-string">'data-view'</span>);
<span class="hljs-keyword">this</span>.updateNav(viewName);
<span class="hljs-keyword">this</span>.state.set({currentView: viewName});
},</pre></div></div>
</li>
<li id="section-14">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-14">&#182;</a>
</div>
<p>create a state object for this view and do the job of</p>
<p>a) initializing it from both data passed in and other sources (e.g. hash url)</p>
<p>b) ensure the state object is updated in responese to changes in subviews, query etc.</p>
</div>
<div class="content"><div class='highlight'><pre> _setupState: <span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">(initialState)</span> </span>{
<span class="hljs-keyword">var</span> self = <span class="hljs-keyword">this</span>;</pre></div></div>
</li>
<li id="section-15">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-15">&#182;</a>
</div>
<p>get data from the query string / hash url plus some defaults</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> qs = my.parseHashQueryString();
<span class="hljs-keyword">var</span> query = qs.reclineQuery;
query = query ? <span class="hljs-built_in">JSON</span>.parse(query) : self.model.queryState.toJSON();</pre></div></div>
</li>
<li id="section-16">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-16">&#182;</a>
</div>
<p>backwards compatability (now named view-graph but was named graph)</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> graphState = qs[<span class="hljs-string">'view-graph'</span>] || qs.graph;
graphState = graphState ? <span class="hljs-built_in">JSON</span>.parse(graphState) : {};</pre></div></div>
</li>
<li id="section-17">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-17">&#182;</a>
</div>
<p>now get default data + hash url plus initial state and initial our state object with it</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> stateData = _.extend({
query: query,
<span class="hljs-string">'view-graph'</span>: graphState,
backend: <span class="hljs-keyword">this</span>.model.backend.__type__,
url: <span class="hljs-keyword">this</span>.model.get(<span class="hljs-string">'url'</span>),
dataset: <span class="hljs-keyword">this</span>.model.toJSON(),
currentView: <span class="hljs-literal">null</span>,
readOnly: <span class="hljs-literal">false</span>
},
initialState);
<span class="hljs-keyword">this</span>.state = <span class="hljs-keyword">new</span> recline.Model.ObjectState(stateData);
},
_bindStateChanges: <span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">()</span> </span>{
<span class="hljs-keyword">var</span> self = <span class="hljs-keyword">this</span>;</pre></div></div>
</li>
<li id="section-18">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-18">&#182;</a>
</div>
<p>finally ensure we update our state object when state of sub-object changes so that state is always up to date</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">this</span>.listenTo(<span class="hljs-keyword">this</span>.model.queryState, <span class="hljs-string">'change'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">()</span> </span>{
self.state.set({query: self.model.queryState.toJSON()});
});
_.each(<span class="hljs-keyword">this</span>.pageViews, <span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">(pageView)</span> </span>{
<span class="hljs-keyword">if</span> (pageView.view.state &amp;&amp; pageView.view.state.bind) {
<span class="hljs-keyword">var</span> update = {};
update[<span class="hljs-string">'view-'</span> + pageView.id] = pageView.view.state.toJSON();
self.state.set(update);
self.listenTo(pageView.view.state, <span class="hljs-string">'change'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">()</span> </span>{
<span class="hljs-keyword">var</span> update = {};
update[<span class="hljs-string">'view-'</span> + pageView.id] = pageView.view.state.toJSON();</pre></div></div>
</li>
<li id="section-19">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-19">&#182;</a>
</div>
<p>had problems where change not being triggered for e.g. grid view so lets do it explicitly</p>
</div>
<div class="content"><div class='highlight'><pre> self.state.set(update, {silent: <span class="hljs-literal">true</span>});
self.state.trigger(<span class="hljs-string">'change'</span>);
});
}
});
},
_bindFlashNotifications: <span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">()</span> </span>{
<span class="hljs-keyword">var</span> self = <span class="hljs-keyword">this</span>;
_.each(<span class="hljs-keyword">this</span>.pageViews, <span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">(pageView)</span> </span>{
self.listenTo(pageView.view, <span class="hljs-string">'recline:flash'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">(flash)</span> </span>{
self.notify(flash);
});
});
},</pre></div></div>
</li>
<li id="section-20">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-20">&#182;</a>
</div>
<h3 id="notify">notify</h3>
<p>Create a notification (a div.alert in div.alert-messsages) using provided
flash object. Flash attributes (all are optional):</p>
<ul>
<li>message: message to show.</li>
<li>category: warning (default), success, error</li>
<li>persist: if true alert is persistent, o/w hidden after 3s (default = false)</li>
<li>loader: if true show loading spinner</li>
</ul>
</div>
<div class="content"><div class='highlight'><pre> notify: <span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">(flash)</span> </span>{
<span class="hljs-keyword">var</span> tmplData = _.extend({
message: <span class="hljs-string">'Loading'</span>,
category: <span class="hljs-string">'warning'</span>,
loader: <span class="hljs-literal">false</span>
},
flash
);
<span class="hljs-keyword">var</span> _template;
<span class="hljs-keyword">if</span> (tmplData.loader) {
_template = <span class="hljs-string">' \
&lt;div class="alert alert-info alert-loader"&gt; \
{{message}} \
&lt;span class="notification-loader"&gt;&amp;nbsp;&lt;/span&gt; \
&lt;/div&gt;'</span>;
} <span class="hljs-keyword">else</span> {
_template = <span class="hljs-string">' \
&lt;div class="alert alert-{{category}} fade in" data-alert="alert"&gt;&lt;a class="close" data-dismiss="alert" href="#"&gt;×&lt;/a&gt; \
{{message}} \
&lt;/div&gt;'</span>;
}
<span class="hljs-keyword">var</span> _templated = $(Mustache.render(_template, tmplData));
_templated = $(_templated).appendTo($(<span class="hljs-string">'.recline-data-explorer .alert-messages'</span>));
<span class="hljs-keyword">if</span> (!flash.persist) {
setTimeout(<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">()</span> </span>{
$(_templated).fadeOut(<span class="hljs-number">1000</span>, <span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">()</span> </span>{
$(<span class="hljs-keyword">this</span>).remove();
});
}, <span class="hljs-number">1000</span>);
}
},</pre></div></div>
</li>
<li id="section-21">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-21">&#182;</a>
</div>
<h3 id="clearnotifications">clearNotifications</h3>
<p>Clear all existing notifications</p>
</div>
<div class="content"><div class='highlight'><pre> clearNotifications: <span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">()</span> </span>{
<span class="hljs-keyword">var</span> $notifications = $(<span class="hljs-string">'.recline-data-explorer .alert-messages .alert'</span>);
$notifications.fadeOut(<span class="hljs-number">1500</span>, <span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">()</span> </span>{
$(<span class="hljs-keyword">this</span>).remove();
});
}
});</pre></div></div>
</li>
<li id="section-22">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-22">&#182;</a>
</div>
<h3 id="multiview-restore">MultiView.restore</h3>
<p>Restore a MultiView instance from a serialized state including the associated dataset</p>
<p>This inverts the state serialization process in Multiview</p>
</div>
<div class="content"><div class='highlight'><pre>my.MultiView.restore = <span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">(state)</span> </span>{</pre></div></div>
</li>
<li id="section-23">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-23">&#182;</a>
</div>
<p>hack-y - restoring a memory dataset does not mean much … (but useful for testing!)</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> datasetInfo;
<span class="hljs-keyword">if</span> (state.backend === <span class="hljs-string">'memory'</span>) {
datasetInfo = {
backend: <span class="hljs-string">'memory'</span>,
records: [{stub: <span class="hljs-string">'this is a stub dataset because we do not restore memory datasets'</span>}]
};
} <span class="hljs-keyword">else</span> {
datasetInfo = _.extend({
url: state.url,
backend: state.backend
},
state.dataset
);
}
<span class="hljs-keyword">var</span> dataset = <span class="hljs-keyword">new</span> recline.Model.Dataset(datasetInfo);
<span class="hljs-keyword">var</span> explorer = <span class="hljs-keyword">new</span> my.MultiView({
model: dataset,
state: state
});
<span class="hljs-keyword">return</span> explorer;
};</pre></div></div>
</li>
<li id="section-24">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-24">&#182;</a>
</div>
<h2 id="miscellaneous-utilities">Miscellaneous Utilities</h2>
</div>
<div class="content"><div class='highlight'><pre><span class="hljs-keyword">var</span> urlPathRegex = <span class="hljs-regexp">/^([^?]+)(\?.*)?/</span>;</pre></div></div>
</li>
<li id="section-25">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-25">&#182;</a>
</div>
<p>Parse the Hash section of a URL into path and query string</p>
</div>
<div class="content"><div class='highlight'><pre>my.parseHashUrl = <span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">(hashUrl)</span> </span>{
<span class="hljs-keyword">var</span> parsed = urlPathRegex.exec(hashUrl);
<span class="hljs-keyword">if</span> (parsed === <span class="hljs-literal">null</span>) {
<span class="hljs-keyword">return</span> {};
} <span class="hljs-keyword">else</span> {
<span class="hljs-keyword">return</span> {
path: parsed[<span class="hljs-number">1</span>],
query: parsed[<span class="hljs-number">2</span>] || <span class="hljs-string">''</span>
};
}
};</pre></div></div>
</li>
<li id="section-26">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-26">&#182;</a>
</div>
<p>Parse a URL query string (?xyz=abc…) into a dictionary.</p>
</div>
<div class="content"><div class='highlight'><pre>my.parseQueryString = <span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">(q)</span> </span>{
<span class="hljs-keyword">if</span> (!q) {
<span class="hljs-keyword">return</span> {};
}
<span class="hljs-keyword">var</span> urlParams = {},
e, d = <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-params">(s)</span> </span>{
<span class="hljs-keyword">return</span> <span class="hljs-built_in">unescape</span>(s.replace(<span class="hljs-regexp">/\+/g</span>, <span class="hljs-string">" "</span>));
},
r = <span class="hljs-regexp">/([^&amp;=]+)=?([^&amp;]*)/g</span>;
<span class="hljs-keyword">if</span> (q &amp;&amp; q.length &amp;&amp; q[<span class="hljs-number">0</span>] === <span class="hljs-string">'?'</span>) {
q = q.slice(<span class="hljs-number">1</span>);
}
<span class="hljs-keyword">while</span> (e = r.exec(q)) {</pre></div></div>
</li>
<li id="section-27">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-27">&#182;</a>
</div>
<p>TODO: have values be array as query string allow repetition of keys</p>
</div>
<div class="content"><div class='highlight'><pre> urlParams[d(e[<span class="hljs-number">1</span>])] = d(e[<span class="hljs-number">2</span>]);
}
<span class="hljs-keyword">return</span> urlParams;
};</pre></div></div>
</li>
<li id="section-28">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-28">&#182;</a>
</div>
<p>Parse the query string out of the URL hash</p>
</div>
<div class="content"><div class='highlight'><pre>my.parseHashQueryString = <span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">()</span> </span>{
<span class="hljs-keyword">var</span> q = my.parseHashUrl(<span class="hljs-built_in">window</span>.location.hash).query;
<span class="hljs-keyword">return</span> my.parseQueryString(q);
};</pre></div></div>
</li>
<li id="section-29">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-29">&#182;</a>
</div>
<p>Compse a Query String</p>
</div>
<div class="content"><div class='highlight'><pre>my.composeQueryString = <span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">(queryParams)</span> </span>{
<span class="hljs-keyword">var</span> queryString = <span class="hljs-string">'?'</span>;
<span class="hljs-keyword">var</span> items = [];
$.each(queryParams, <span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">(key, value)</span> </span>{
<span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span>(value) === <span class="hljs-string">'object'</span>) {
value = <span class="hljs-built_in">JSON</span>.stringify(value);
}
items.push(key + <span class="hljs-string">'='</span> + <span class="hljs-built_in">encodeURIComponent</span>(value));
});
queryString += items.join(<span class="hljs-string">'&amp;'</span>);
<span class="hljs-keyword">return</span> queryString;
};
my.getNewHashForQueryString = <span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">(queryParams)</span> </span>{
<span class="hljs-keyword">var</span> queryPart = my.composeQueryString(queryParams);
<span class="hljs-keyword">if</span> (<span class="hljs-built_in">window</span>.location.hash) {</pre></div></div>
</li>
<li id="section-30">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-30">&#182;</a>
</div>
<p>slice(1) to remove # at start</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">return</span> <span class="hljs-built_in">window</span>.location.hash.split(<span class="hljs-string">'?'</span>)[<span class="hljs-number">0</span>].slice(<span class="hljs-number">1</span>) + queryPart;
} <span class="hljs-keyword">else</span> {
<span class="hljs-keyword">return</span> queryPart;
}
};
my.setHashQueryString = <span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">(queryParams)</span> </span>{
<span class="hljs-built_in">window</span>.location.hash = my.getNewHashForQueryString(queryParams);
};
})(jQuery, recline.View);</pre></div></div>
</li>
</ul>
</div>
</body>
</html>