/[drupal]/contributions/modules/exhibit/exhibit.js
ViewVC logotype

Contents of /contributions/modules/exhibit/exhibit.js

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.2 - (show annotations) (download) (as text)
Thu Jul 24 13:16:13 2008 UTC (16 months ago) by arto
Branch: MAIN
CVS Tags: DRUPAL-6--1-0-BETA1, DRUPAL-6--1-0-ALPHA2, HEAD
Changes since 1.1: +30 -27 lines
File MIME type: text/javascript
Imported latest 6.x version (1c2672d) from the GitHub development repository.

Changelog:
- Added error handling for the facet generator for cases when feed URLs return an error status (by jhuckabee).
- Added link parsing to correctly handle query arguments for feed links (by jhuckabee).
- Added basic usage instructions to README for various definitions and the facet generator (by jhuckabee).
- Added co-maintainers to README.
1 // $Id$
2
3 /**
4 * Enable auto facet generation based on fields in selected feeds in Exhibit node creation
5 */
6 Drupal.behaviors.exhibit = function(context) {
7
8 Drupal.exhibit.buildForm();
9 // Loads all feeds, attaches change handler to feed checkboxes,
10 // and initializes
11 Drupal.exhibit.loadFeeds(function(){
12 $('input.exhibit-feed-checkbox:not(.exhibit-feed-checkbox-processed)', context).addClass('exhibit-feed-checkbox-processed').each(function () {
13 $(this).bind('change', function(){
14 Drupal.exhibit.selectFeed(this);
15 });
16
17 if (this.checked) {
18 Drupal.exhibit.selectFeed(this);
19 }
20 });
21
22 // Bind insert button click event
23 $('input#edit-insert-facet').bind('click', function(){
24 Drupal.exhibit.insertFacet();
25 return false;
26 });
27
28 $('#edit-exhibit-facet-generator-form-wrapper-field-name').bind('change', function(){
29 Drupal.exhibit.filterFacetTypeByField();
30 return false;
31 });
32
33 $('#edit-exhibit-facet-generator-form-wrapper-facet-type').bind('change', function(){
34 Drupal.exhibit.facetTypeChange();
35 return false;
36 });
37
38 });
39
40 };
41
42 /**
43 * Facet form generator
44 */
45 Drupal.exhibit = function() {
46
47 var facets = {
48 list: {
49 title:'List',
50 exhibitClass: 'List',
51 types: ['text','number','date','boolean','url','item'],
52 options: {
53 height: {
54 title: 'Height',
55 help: "Height of the facet's body, e.g., \"20em\", \"200px\""
56 },
57 sortMode: {
58 title: 'Sort Mode',
59 help: "How to sort the choices in the facet",
60 choices: ['value', 'count']
61 },
62 sortDirection: {
63 title: 'Sort Direction',
64 help: "Whether to reverse the sort direction",
65 choices: ['forward', 'reverse']
66 },
67 showMissing: {
68 title: 'Show Missiong',
69 help: "Whether to provide a selection for items missing the facet -- this will suppress the '(missing this field)' text",
70 choices: ['true', 'false']
71 },
72 selection: {
73 title: 'Selection',
74 help: "Semicolon-separated list of default selections"
75 },
76 fixedOrder: {
77 title: 'Fixed Order',
78 help: "Semicolon-separated list of values specifying a fixed order for sorting the choices in the facet, e.g., \"Mo;Tu;We;Th;Fr\" for weekdays"
79 },
80 scroll: {
81 title: 'Scroll',
82 help: "If true, facet values are in a scrollable window of fixed size. If false, all facet values are shown in as much space as needed, without a scroll bar.",
83 choices: ['true', 'false']
84 },
85 colorCoder: {
86 title: 'Color Coder',
87 help: "Whcih color coder to use"
88 },
89 collapsible: {
90 title: 'Collapsible',
91 help: "Whether the facet is collapsible or not.",
92 choices: ['false', 'true'],
93 dependency: 'collapsed'
94 },
95 collapsed: {
96 title: 'Collapsed',
97 help: "Whether the facet is defaulted to a collapsed state.",
98 choices: ['false', 'true']
99 }
100 }
101 },
102 cloud: {
103 title: 'Cloud',
104 exhibitClass: 'Cloud',
105 types: ['text','number','date','boolean','url','item'],
106 options: {
107 selectMissing: {
108 title: 'Select Missiong',
109 help: "Whether to provide a selection for items missing the facet -- this will suppress the '(missing this field)' text",
110 choices: ['true', 'false']
111 },
112 selection: {
113 title: 'Selection',
114 help: "Semicolon-separated list of default selections"
115 }
116 }
117 },
118 datePicker: {
119 title: 'Date Picker',
120 exhibitClass: 'DatePicker',
121 types: ['date'],
122 options: {
123 timerLimit: {
124 title: 'Timer Limit',
125 help: "If set, this is the number of miliseconds that will pass between the first date selection and the auto selection of the second date. Timer limit will not apply if selection dragging is enabled."
126 },
127 dragSelection: {
128 title: 'Enable Selection Dragging',
129 help: "If true, users will select a date range by clicking and dragging on the dates they want to pick.",
130 choices: ['false', 'true']
131 }
132 }
133 },
134 hierarchical: {
135 title: 'Hierarchical',
136 exhibitClass: 'Hierarchical',
137 types: ['text','number','date','boolean','url','item'],
138 options: {}
139 },
140 numericRange: {
141 title: 'Numeric Range',
142 exhibitClass: 'NumericRange',
143 types: ['number'],
144 options: {
145 height: {
146 title: 'Height',
147 help: "Height of the facet's body, e.g., \"20em\", \"200px\""
148 },
149 collapsible: {
150 title: 'Collapsible',
151 help: "Whether the facet is collapsible or not.",
152 choices: ['false', 'true'],
153 dependency: 'collapsed'
154 },
155 collapsed: {
156 title: 'Collapsed',
157 help: "Whether the facet is defaulted to a collapsed state.",
158 choices: ['false', 'true']
159 }
160 }
161 },
162 slider: {
163 title: 'Slider',
164 exhibitClass: 'Slider',
165 types: ['number'],
166 options: {
167 scroll: {
168 title: 'Scroll',
169 help: "If true, facet values are in a scrollable window of fixed size. If false, all facet values are shown in as much space as needed, without a scroll bar.",
170 choices: ['true', 'false']
171 },
172 height: {
173 title: 'Height',
174 help: "Height of the facet's body, e.g., \"20em\", \"200px\""
175 },
176 precision: {
177 title: 'Precision',
178 help: "Precision of the slider expressed as a whole or floating point number"
179 },
180 historgram: {
181 title: 'Histogram',
182 help: "Whether or not to show the histogram",
183 choices: ['true', 'false']
184 }
185 }
186 },
187 textSearch: {
188 title: 'Text Search',
189 exhibitClass: 'TextSearch',
190 types: ['text','number','date','boolean','url','item'],
191 options: {
192 queryParamName: {
193 title: 'Query Param Name',
194 help: "Which query param from the URL to auto filter by. E.g. http://example.com?srch=something would automatically set the text search filter to 'something' and filter the results when the page is loaded."
195 },
196 requiresEnter: {
197 title: 'Requires Enter',
198 help: "Whether the facet requires the user to hit the 'enter' key before filtering.",
199 choices: ['false', 'true']
200 }
201 }
202 }
203 };
204
205 var feeds = {};
206
207 var fieldWrapper = function(label, input, fieldId, helpText){
208 return ['<div class="form-item">',
209 '<label for="', fieldId, '">', label, '</label>',
210 input,
211 (helpText === undefined ? '' : '<div class="description">' + helpText + '</div>'),
212 '</div>'].join('');
213 };
214
215 // Build list of facet type options
216 var facetTypeOptions = function() {
217 var options = [],
218 selFieldName = $('#edit-exhibit-facet-generator-form-wrapper-field-name').val(),
219 selField;
220
221 // If a field name is selected, filter the facets by type
222 if ($('#edit-exhibit-facet-generator-form-wrapper-field-name') && selFieldName) {
223 selField = getField(selFieldName);
224 for (facet in facets) {
225 if ($.inArray(selField.valueType, facets[facet].types) >= 0) {
226 options.push('<option value="' + facet + '">' + facets[facet].title + '</option>');
227 }
228 }
229 }
230 else { // No field selected, return them all. Used in initialization
231 for (facet in facets) {
232 options.push('<option value="' + facet + '">' + facets[facet].title + '</option>');
233 }
234 }
235 return options.join('');
236 };
237
238 // Build array of unique fields based on selected feeds
239 var getUniqueFields = function() {
240 var fields = [];
241
242 // Gather selected feed ids
243 selectedIds = $.map($('input.exhibit-feed-checkbox:checked'), function(item) {
244 var parts = item.id.split('-');
245 return parts[parts.length-1];
246 });
247
248
249 // Build list of unique field names from the selected feeds
250 $.each(selectedIds, function(selIdx, feed_id){
251 $.each(feeds[feed_id].fields, function(feedsIdx, field){
252 if($.inArray(field.name, fields) < 0) {
253 fields.push(field.name);
254 }
255 });
256 });
257
258 return fields;
259 };
260
261 var getField = function(fieldName) {
262 var selField;
263
264 $.each(feeds, function(feedIdx, feed){
265 $.each(feed.fields, function(fieldIdx, field){
266 if (field.name === fieldName) {
267 selField = field;
268 }
269 });
270 });
271
272 return selField;
273 };
274
275 return {
276
277 // Build the default facet generation form
278 buildForm: function() {
279 $('div#facet-generator-form').html([fieldWrapper('Select Field: <span class="form-required" title="This field is required.">*</span>',
280 '<select name="exhibit[facet-generator-form-wrapper][field-name]" class="form-select required" id="edit-exhibit-facet-generator-form-wrapper-field-name" ></select>',
281 'edit-exhibit-facet-generator-form-wrapper-field-name'),
282 fieldWrapper('Label: ',
283 '<input type="text" maxlength="128" name="exhibit[facet-generator-form-wrapper][facet-label]" id="edit-exhibit-facet-generator-form-wrapper-facet-label" size="60" value="" class="form-text" />',
284 'edit-exhibit-facet-generator-form-wrapper-facet-label'),
285 fieldWrapper('Facet Type: <span class="form-required" title="This field is required.">*</span>',
286 ['<select name="exhibit[facet-generator-form-wrapper][facet-type]" class="form-select" id="edit-exhibit-facet-generator-form-wrapper-facet-type" >',
287 '<option></option>', facetTypeOptions() ,'</select>'].join(''),
288 'edit-exhibit-facet-generator-form-wrapper-facet-type'),
289 '<div id="facet-options"></div>',
290 '<input type="submit" name="insertFacet" id="edit-insert-facet" value="Generate Facet HTML" class="form-submit" />'].join('\n'));
291 },
292
293 // Build a facets options form
294 buildFacetOptionsForm: function(facet) {
295 var selFacet = facets[facet],
296 formHtml = [];
297
298 if (!facet || !selFacet) {
299 return '';
300 }
301
302 for (option in selFacet.options) {
303 // select field
304 if (selFacet.options[option].choices &&
305 selFacet.options[option].choices.length) {
306 formHtml.push(fieldWrapper((selFacet.options[option].title ? selFacet.options[option].title : option) + ': ',
307 ['<select name="exhibit[facet-generator-form-wrapper][', facet, '][', option, ']" ',
308 'class="form-select" id="edit-exhibit-facet-generator-form-wrapper-', facet, '-', option, '" >',
309 $.map(selFacet.options[option].choices, function(choice){
310 return '<option value="' + choice + '">' + choice + '</option>';
311 }).join(''),
312 '</select>'].join(''),
313 'edit-exhibit-facet-generator-form-wrapper-' + facet + '-' + option,
314 selFacet.options[option].help));
315 }
316 else { // text field
317 formHtml.push(fieldWrapper((selFacet.options[option].title ? selFacet.options[option].title : option) + ': ',
318 '<input type="text" maxlength="128" name="exhibit[facet-generator-form-wrapper][' + facet + '][' + option + ']" id="edit-exhibit-facet-generator-form-wrapper-' + facet + '-' + option + '" size="60" value="" class="form-text" />',
319 'edit-exhibit-facet-generator-form-wrapper-' + facet + '-' + option,
320 selFacet.options[option].help));
321 }
322 }
323
324 return formHtml.join('');
325
326 },
327
328 // Load all feeds
329 loadFeeds: function(callback) {
330 for (var feed_id in Drupal.settings.exhibit) {
331 feeds[feed_id] = {loaded: false, url: Drupal.settings.exhibit[feed_id], fields: []};
332 }
333
334 for (feed_id in feeds){
335 this.loadFeed(feeds[feed_id], callback);
336 }
337 },
338
339 // Load an individual feed
340 loadFeed: function(feed, callback) {
341 var fieldType,
342 that = this;
343
344 $.ajax({
345 type: "GET",
346 url: '/' + feed.url,
347 dataType: "json",
348 success: function(data) {
349 if (data.items && data.items[0]) { // Make sure the feed contains items
350 $.each(data.items, function(item){ // Loop through each item
351 $.each(data.items[item], function(i) { // Loop through each field in the item
352 if ($.inArray(i, $.map(feed.fields, function(f){ return f.name;})) < 0) { // Make sure the field doesn't already exist
353 if (data.properties &&
354 data.properties[i] &&
355 data.properties[i]['valueType']) { // Check if item has a defined value type
356 fieldType = data.properties[i]['valueType']; // Use specified value type
357 }
358 else {
359 fieldType = 'item'; // Use default 'item' value type
360 }
361 feed.fields.push({name: i, valueType: fieldType}); // Add the field to the fields array
362 }
363 });
364 });
365 }
366 },
367 complete: function() {
368 feed.loaded = true;
369
370 if (typeof callback === 'function' &&
371 that.allFeedsLoaded()) {
372 callback();
373 }
374 }
375 });
376
377 },
378
379 // Check if all feeds have been loaded
380 allFeedsLoaded: function() {
381 var loaded = true;
382 $.each(feeds, function(feed_id){
383 if (!feeds[feed_id].loaded) {
384 loaded = false;
385 }
386 });
387 return loaded;
388 },
389
390 // Handle feed selection
391 selectFeed: function(element) {
392 var selectedIds = [],
393 options,
394 optionsHtml = ['<option></option>'];
395
396 // Hide facet generator form if no checkboxes are selected
397 if (!$('input.exhibit-feed-checkbox:checked').size()){
398 $('#exhibit-facet-builder').hide();
399 return;
400 }
401
402 // Get fields
403 options = getUniqueFields();
404
405 // Show the facet generator form if we have fields
406 if (options.length > 0){
407
408 // Create the options list for each field and
409 // update the field select box
410 $.each(options, function(i, option){
411 optionsHtml.push('<option value="' + option + '">' + option + '</option>');
412 });
413 $('#edit-exhibit-facet-generator-form-wrapper-field-name').html(optionsHtml.join(''));
414
415
416 $('#exhibit-facet-builder').show();
417 }
418 else { // No fields for selected feeds, hide the form
419 $('#exhibit-facet-builder').hide();
420 }
421 },
422
423 // Handles the facet type selection.
424 // Displays the facet's options form
425 facetTypeChange: function() {
426 $('#facet-options').html(this.buildFacetOptionsForm($('#edit-exhibit-facet-generator-form-wrapper-facet-type').val()));
427 },
428
429 buildFacet: function() {
430 if(!$('#edit-exhibit-facet-generator-form-wrapper-facet-type').val() ||
431 !$('#edit-exhibit-facet-generator-form-wrapper-field-name').val()) {
432 return '';
433 }
434
435 var facetType = $('#edit-exhibit-facet-generator-form-wrapper-facet-type').val(),
436 facet = facets[facetType],
437 facetOptionValue;
438
439 if (!facet) {
440 return '';
441 }
442
443 var facetHtml = ['<div class="facet" ex:role="facet"',
444 ' ex:expression=".', $('#edit-exhibit-facet-generator-form-wrapper-field-name').val(), '"'];
445
446 if (facetType !== 'list'){
447 facetHtml.push(' ex:facetClass="' + facet.exhibitClass + '"');
448 }
449
450 if ($('#edit-exhibit-facet-generator-form-wrapper-facet-label').val()){
451 facetHtml.push(' ex:facetLabel="' + $('#edit-exhibit-facet-generator-form-wrapper-facet-label').val() + '"');
452 }
453
454 for (option in facet.options) {
455 facetOptionValue = $('#edit-exhibit-facet-generator-form-wrapper-' + facetType + '-' + option).val();
456
457 if (facetOptionValue) {
458 if (facet.options[option].choices &&
459 facet.options[option].choices.length &&
460 facet.options[option].choices.length > 0) {
461 if (facetOptionValue !== facet.options[option].choices[0]) {
462 facetHtml.push(' ex:' + option + '="' + facetOptionValue + '"');
463 }
464 }
465 else {
466 facetHtml.push(' ex:' + option + '="' + facetOptionValue + '"');
467 }
468 }
469 }
470
471 facetHtml.push('></div>');
472 return facetHtml.join('');
473 },
474
475 // Inserts the HTML for a facet based on the given options
476 insertFacet: function() {
477 var currentVal = '',
478 val = [];
479 currentVal = $('#edit-exhibit-facet-definition').val();
480 if (currentVal != '') {
481 val.push($.trim(currentVal));
482 }
483 val.push(this.buildFacet());
484 $('#edit-exhibit-facet-definition').val(val.join('\n'));
485 },
486
487 filterFacetTypeByField: function() {
488 $('#edit-exhibit-facet-generator-form-wrapper-facet-type').html('<option></option>' + facetTypeOptions());
489 return false;
490 }
491
492 };
493
494 }();

  ViewVC Help
Powered by ViewVC 1.1.2