1 // FUN FACT: This depends on global_search.js for sprintf
3 $(document).ready(function() {
4 $(".widget-place").bind('click', function() {
5 $("#page_settings").hide();
7 $('#show_global_widget_refresh').click(function (ev) {
9 // maybe someone clicked the input?
10 if (ev.target != this)
13 if ($('#widget_global_slider').is('div')) {
14 $('#widget_global_slider').remove();
16 var content = '<div id="widget_global_slider"><div style="height:10px;background-color: #ffffff;"></div>';
17 content += '<br /><input style="border:0px; display: inline; padding: 0px; margin-bottom: 7px" size="3" type="text" name="global_widget_refresh" id="global_widget_refresh" value="' + global_refresh + '" />';
19 $("#show_global_widget_refresh").append(content);
20 $("#widget_global_slider div").slider({
21 value: global_refresh,
25 slide: function(event, ui) {
26 $("#global_widget_refresh").val(ui.value);
27 global_refresh = ui.value;
28 update_save_interval();
35 // create array prototype to sole the lack of in_array() in javascript
36 Array.prototype.has = function(value) {
38 for (var i = 0, loopCnt = this.length; i < loopCnt; i++) {
39 if (this[i] === value) {
46 function init_easywidgets(){
47 window.easywidgets_obj = $.fn.EasyWidgets({
52 editText : '<img src="' + _site_domain + 'application/views/icons/12x12/box-config.png" alt="Settings" />',
53 closeText : '<img src="' + _site_domain + 'application/views/icons/12x12/box-close.png" alt="Close widget" />',
54 collapseText : '<img src="' + _site_domain + 'application/views/icons/12x12/box-mimimize.png" alt="Collapse" />',
55 cancelEditText : '<img src="' + _site_domain + 'application/views/icons/12x12/box-config.png" alt="Cancel" />',
56 extendText : '<img src="' + _site_domain + 'application/views/icons/12x12/box-maximize.png" alt="Extend" />'
62 widgetClose : 'slide',
63 widgetExtend : 'slide',
64 widgetCollapse : 'slide',
65 widgetOpenEdit : 'slide',
66 widgetCloseEdit : 'slide',
67 widgetCancelEdit : 'slide'
70 onChangePositions : function(str){
71 // triggered by drag & drop
72 save_widget_order(str);
74 onClose: function(link, widget) {
75 // triggered by X on the widget's own window panel
76 save_widget_state('hide', widget.data('name'), widget.data('instance_id'));
77 var menu_siblings = $('.widget-selector').filter('[data-name=' + widget.data('name') + ']');
78 var this_entry = menu_siblings.filter('[data-instance_id=' + widget.data('instance_id') + ']');
79 if (menu_siblings.length > 1)
82 this_entry.removeClass('selected').addClass('unselected').attr('data-instance_id', '');
84 delete loaded_widgets[widget.data('name')+'-'+widget.data('instance_id')];
86 onHide: function(widget) {
87 // trigged by unchecking box in the widget menu
88 save_widget_state('hide', widget.data('name'), widget.data('instance_id'));
89 var menu_siblings = $('.widget-selector').filter('[data-name=' + widget.data('name') + ']');
90 var this_entry = menu_siblings.filter('[data-instance_id=' + widget.data('instance_id') + ']');
91 if (menu_siblings.length > 1)
94 this_entry.removeClass('selected').addClass('unselected').attr('data-instance_id', '');
96 delete loaded_widgets[widget.data('name')+'-'+widget.data('instance_id')];
99 // triggered by checking box in the widget menu
100 new widget(w.data('name'), w.data('instance_id'));
106 // Global variable to keep track of when user decides to reload the interface.
107 // This is needed since we want to prevent the spawning of additional ajax calls.
108 var _is_refreshing = false;
110 var _global_save = 0; // timeout handler variable
111 var global_refresh = 60; // keeps track of the refresh rate set by slider
114 * Keep track of the timeout for when to save
115 * the global refresh rate for widgets.
116 * Is reset to 5 sec between all changes
118 function update_save_interval()
121 clearTimeout(_global_save);
123 _global_save = setTimeout("set_widget_refresh()", 5000);
127 * Save new refresh rate for all widgets to database
128 * and display notification if successful or not
130 function set_widget_refresh()
132 _is_refreshing = true;
134 var url = _site_domain + _index_page + "/widget/set_widget_refresh/";
135 var page_name = _current_uri;
136 var value = global_refresh;
137 var data = {page: escape(page_name), value: value, type: 'refresh_interval'};
143 success: function(data) {
144 if (data.success == true) {
145 $.jGrowl(sprintf(_widget_refresh_msg, value), { header: _success_header });
146 $('#widget_global_slider').remove();
147 $('.widget-editbox [name=refresh_interval]').each(function() {
148 $(this).attr('value', value);
150 window.location.reload();
152 $.jGrowl(_widget_refresh_error, { header: _error_header });
155 error: function(obj, msg){$.jGrowl(_widget_global_refresh_error, { header: _error_header });}
160 * Save widget order to database
162 function save_widget_order(order_str)
165 _site_domain + _index_page + "/widget/save_widgets_order/",
168 page: escape(_current_uri),
169 widget_str: order_str
176 function control_widgets(item) {
178 if (it.hasClass('selected')) {
179 $.fn.HideEasyWidget('widget-' + it.data('name') + '-' + it.data('instance_id'), window.easywidgets_obj);
180 it.removeClass('selected').addClass('unselected').data('instance_id', '');
183 copy_widget_instance(it.data('name'), it.data('instance_id'), function(new_widget) {
184 if (!it.data('instance_id')) {
185 it.data('instance_id', new_widget.data('instance_id')).attr('data-instance_id', new_widget.data('instance_id'));
188 it.removeClass('unselected').addClass('selected');
192 function copy_widget_instance(name, instance_id, cb) {
194 url: _site_domain + _index_page + '/widget/copy_widget_instance',
197 data: {page: _current_uri, widget: name, 'instance_id': instance_id},
198 success: function(data) {
200 var this_widget = $('#widget-' + name + '-' + instance_id);
201 if (this_widget.length) {
202 this_widget.after(data);
203 new_widget = this_widget.next('.widget');
206 var container = $('#widget-placeholder');
207 container.append(data);
208 new_widget = container.find('.widget:last');
216 function save_widget_state(what, widget_name, instance_id)
219 _site_domain + _index_page + "/widget/save_widget_state/",
222 page: escape(_current_uri),
225 instance_id: instance_id
232 var loaded_widgets = {};
237 function widget(name, instance_id)
240 this.ajax_url = _site_domain + _index_page + '/widget/';
242 this._refresh_interval = 0;
243 this.save_interval = 0;
244 this.current_uri = _current_uri;
245 this.content_area = 'widget-content';
246 this.is_updating = false;
249 var widget_ok = this.init_widget(name, instance_id);
250 if (widget_ok == false) {
251 // here we should probably notify user that
252 // the widget isn't found
254 $.jGrowl(sprintf(_widget_notfound_error, name), { header: _error_header });
259 // only enable refresh and interval editing
260 // if we have a content_area and there's a sider div
261 if (this.content_area && $("#" + this.widget_id + " .refresh_slider").length) {
262 this.set_refresh_interval(true);
265 this.init_title_edit();
266 if (widget.widgets[name])
267 for (var i in widget.widgets[name])
268 widget.widgets[name][i].call(this);
270 widget.loadimg = new Image(16,16);
271 widget.loadimg.src = _site_domain + 'application/media/images/loading_small.gif';
274 * Initialize some internal values.
276 widget.prototype.init_widget = function(name, instance_id) {
278 this.set_id(name, instance_id);
280 // check that widget isn't already loaded
281 if (loaded_widgets[this.id]) {
285 if (!$('#' + this.widget_id).text())
287 this.current_interval = $('#' + this.widget_id + ' .refresh_interval').val();
288 this.title = $('#' + this.id + '_title').text();
289 if (this.current_uri == 'external_widget/show_widget') {
290 $('.widget-menu .widget-collapselink').hide();
291 $('.widget-menu .widget-closelink').hide();
292 $('#' + this.id + '_title').removeClass(this.id + '_editable');
295 $('#' + this.widget_id + '.duplicatable .widget-menu').prepend('<a class="widget-copylink" title="Copy this widget" href="#"><img alt="Copy" src="' + _site_domain + 'application/views/icons/12x12/copy.png"/></a>');
296 $('#' + this.widget_id + ' .widget-copylink').click(function(ev) {
298 copy_widget_instance(self.name, self.instance_id, function (new_widget) {
299 $('.widget-selector').filter(':last').after('<li id="li-'+new_widget.data('name')+'-'+new_widget.data('instance_id')+'" data-name="'+new_widget.data('name')+'" data-instance_id="'+new_widget.data('instance_id')+'" class="selected widget-selector" onclick="control_widgets(this)">'+new_widget.find('#'+new_widget.data('name')+'-'+new_widget.data('instance_id')+'_title').text()+'</li>');
302 loaded_widgets[this.id] = 1;
307 widget.prototype.set_current_uri = function(uri) {
308 this.current_uri = uri;
311 widget.prototype.set_id = function(name, instance_id) {
314 this.id = name + '-' + instance_id;
316 this.instance_id = instance_id;
317 this.widget_id = 'widget-' + this.id;
321 * Fetch current widget state through AJAX call
323 widget.prototype.update_display = function() {
326 if (this.content_area != false && $('#' + this.widget_id).is(':visible')) {
327 if (this.is_updating || _is_refreshing) {
329 * Prevent multiple instances of the same widget
330 * from trying to fetch data at the same time as this
331 * will possibly hog the system. Also prevent new
332 * ajax calls when user has decided to reload the page
336 this.is_updating = true;
338 // add a loading img to indicate update progress
339 $("#" + this.widget_id + ' .widget-header').append('<img src="' + widget.loadimg.src + '" class="widget_loadimg" />');
340 $("#" + this.widget_id + ' .widget-header .widget_loadimg').css('opacity', 0.4).css('padding-left', '15px').css('width', '12px').css('height', '12px');
343 widget_name: this.name,
344 instance_id: this.instance_id,
345 page: this.current_uri
348 url: this.ajax_url + "widget/" + this.name + "/index/?" + jQuery.param(params),
350 success: function(data) {
351 $("#" + self.widget_id + ' .' + self.content_area).html(data);
352 self.is_updating = false;
355 $("#" + self.widget_id + ' .widget-header .widget_loadimg').remove();
362 * Save widget settings to db
364 widget.prototype.save_settings = function(data) {
367 this.ajax_url + "save_widget_setting/",
371 complete: function() {
372 $.jGrowl(sprintf(_widget_settings_msg, self.name), { header: _success_header });
379 * Save custom widget setting
381 widget.prototype.save_custom_val = function(newval, fieldname, cb) {
384 this.ajax_url + "save_dynamic_widget_setting/",
387 page: this.current_uri,
389 fieldname: fieldname,
391 instance_id: this.instance_id
393 complete: function(data) {
394 if (typeof cb == 'function') {
397 $.jGrowl(sprintf(_widget_settings_msg, self.name), { header: _success_header });
405 widget.register_widget_load = function(widget_name, cb) {
406 if (!widget.widgets[widget_name])
407 widget.widgets[widget_name] = [cb];
409 for (var i =0; i < widget.widgets[widget_name].length; i++) {
410 if (widget.widgets[widget_name][i].toString() == cb.toString())
413 widget.widgets[widget_name].push(cb);
418 * Set the refresh interval to use for widget
419 * and also pass this value on to be saved to db
421 widget.prototype.set_refresh_interval = function(is_init){
423 if (this._refresh_interval) {
424 clearInterval(this._refresh_interval);
427 if (this.current_interval>0) {
428 var interval = (this.current_interval * 1000);
429 //this._refresh_interval = setInterval("update_display()", interval);
430 this._refresh_interval = setInterval(function() {self.update_display();}, interval);
434 // update widget settings
435 var data = {page: this.current_uri, refresh_interval: this.current_interval, widget: this.name, instance_id: this.instance_id};
436 this.save_settings(data);
441 * Since the slider is possible to move rather fast,
442 * we add a delay (timeout) to this before we do anything with it.
443 * The timeout is cleared when a new value is selected and only saved
444 * until there is no activity (new value) for 5 seconds
446 widget.prototype.control_save_interval = function() {
448 if (this.save_interval) {
449 clearTimeout(this.save_interval);
451 this.save_interval = setTimeout(function() {self.set_refresh_interval();}, 5000);
454 widget.prototype.init_slider = function() {
456 $("#" + this.widget_id + " .refresh_slider").slider({
457 value: this.current_interval,
461 slide: function(event, ui) {
462 $("#" + self.widget_id + " .refresh_interval").val(ui.value);
463 self.current_interval = ui.value;
464 self.control_save_interval();
467 $("#" + this.widget_id + " .refresh_interval").val($("#" + this.widget_id + " .refresh_slider").slider("value")).change(function() {
468 $("#" + self.widget_id + " .refresh_slider").slider("value", $(this).val());
469 self.current_interval = $(this).val();
470 self.control_save_interval();
475 widget.prototype.init_title_edit = function() {
477 $("." + this.id + "_editable").editable(function(value, settings) {
478 var data = {page: self.current_uri, widget:self.name, instance_id:self.instance_id, widget_title:value};
479 value = $.trim(value);
480 // don't save an empty title
482 self.save_settings(data);
490 style : 'margin-top: -4px',
496 placeholder:'Double-click to edit'