ad2e5fdeaa81fd120ff37b83bea7a4be8b275fb9
[myslice.git] / plugins / resources_selected / resources_selected.js
1 /**
2  * MySlice ResourcesSelected plugin
3  * Version: 0.1.0
4  * URL: http://www.myslice.info
5  * Description: display of selected resources
6  * Requires: 
7  * Author: The MySlice Team
8  * Copyright: Copyright 2012 UPMC Sorbonne Universités
9  * License: GPLv3
10  */
11
12 /*
13  * It's a best practice to pass jQuery to an IIFE (Immediately Invoked Function
14  * Expression) that maps it to the dollar sign so it can't be overwritten by
15  * another library in the scope of its execution.
16  */
17 (function( $ ){
18
19     // Routing calls
20     jQuery.fn.ResourcesSelected = function( method ) {
21         if ( methods[method] ) {
22             return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 ));
23         } else if ( typeof method === 'object' || ! method ) {
24             return methods.init.apply( this, arguments );
25         } else {
26             jQuery.error( 'Method ' +  method + ' does not exist on jQuery.ResourcesSelected' );
27         }    
28
29     };
30
31     /***************************************************************************
32      * Public methods
33      ***************************************************************************/
34
35     var methods = {
36
37         /**
38          * @brief Plugin initialization
39          * @param options : an associative array of setting values
40          * @return : a jQuery collection of objects on which the plugin is
41          *     applied, which allows to maintain chainability of calls
42          */
43         init : function( options ) {
44
45             return this.each(function(){
46
47                 var $this = $(this);
48
49                 /* An object that will hold private variables and methods */
50                 var s = new ResourcesSelected(options);
51                 $(this).data('ResourcesSelected', s);
52                 var RESULTS_RESOURCES = '/results/' + options.resource_query_uuid + '/changed';
53                 var UPDATE_RESOURCES  = '/update-set/' + options.resource_query_uuid;
54                                  
55                 $.subscribe(RESULTS_RESOURCES, function(e, resources) { s.set_resources(resources);    });
56                 $.subscribe(UPDATE_RESOURCES,  function(e, resources, change) { s.update_resources(resources, change); });
57                 
58             }); // this.each
59         }, // init
60
61         /**
62          * @brief Plugin destruction
63          * @return : a jQuery collection of objects on which the plugin is
64          *     applied, which allows to maintain chainability of calls
65          */
66         destroy : function( ) {
67
68             return this.each(function(){
69                 var $this = jQuery(this), data = $this.data('ResourcesSelected');
70                 jQuery(window).unbind('ResourcesSelected');
71                 data.ResourcesSelected.remove();
72                 $this.removeData('ResourcesSelected');
73             })
74
75         }, // destroy
76
77     }; // var methods
78
79     /***************************************************************************
80      * ResourcesSelected object
81      ***************************************************************************/
82
83     function ResourcesSelected(options)
84     {
85         /* member variables */
86
87         this.options = options;
88
89         /* The resources that are in the slice */
90         this.current_resources = null;
91
92         /* The resources that are in the slice before any edit */
93         this.initial_resources = null;
94
95         var rs = this;
96
97         /* constructor */
98             // ioi: resources table id
99         var TABLE_NAME = '#table-' + options.plugin_uuid;
100         this.table = $(TABLE_NAME).dataTable({
101             //sPaginationType: 'full_numbers',  // Use pagination
102             sPaginationType: 'bootstrap',
103             //bJQueryUI: true,
104             //bRetrieve: true,
105             sScrollX: '100%',                 // Horizontal scrolling 
106             bSortClasses: false,              // Disable style for the sorted column
107             aaSorting: [[ 1, "asc" ]],        // Default sorting on URN
108             fnDrawCallback: function() {      // Reassociate close click every time the table is redrawn
109                 /* Prevent to loop on click while redrawing table  */
110                 jQuery('.ResourceSelectedClose').unbind('click');
111                 /* Handle clicks on close span */
112                 /* Reassociate close click every time the table is redrawn */
113                 $('.ResourceSelectedClose').bind('click',{instance: rs}, close_click);
114             }
115          });
116
117         /* methods */
118
119         this.set_resources = function(resources)
120         {
121             console.log("set_resources");
122             /* Some sanity checks on the API results */
123             if(resources.length==0){
124                 this.table.html(errorDisplay("No Result"));   
125                 return;
126             }
127
128             if (typeof(resources[0].error) != 'undefined') {
129                 this.table.html(errorDisplay(resources[0].error));
130                 return;
131             }
132
133             /* Update the table with resources in the slice */
134             //var slivers = $.grep(resources, function(i) {return typeof(i['sliver']) != 'undefined';})
135             var slivers = resources;
136             var sliver_urns = Array();
137             // ioi : refubrished
138                 $.each(resources, function(i, x) { sliver_urns.push({urn:x.urn, timeslot:"0"}); }); // ioi
139
140             this.initial_resources = sliver_urns; // We make a copy of the object // ioi
141                 // ioi
142             
143             if (this.current_resources == null) {
144                 this.current_resources = sliver_urns;
145
146                 /* We simply add to the ResourceSelected table */
147                 var newlines=Array();
148                 $.each(sliver_urns, function(index, elt) {
149                     newlines.push(Array('attached', elt.urn, elt.timeslot, "<span class='ui-icon ui-icon-close ResourceSelectedClose' id='"+elt.urn+"'/>")); // ioi: added last element
150                 });
151                 this.table.dataTable().fnAddData(newlines);
152             } else {
153                 alert('Slice updated. Refresh not yet implemented!');
154             }
155         }
156
157         this.update_resources = function(resources, change) {
158             console.log("update_resources");
159             var my_oTable = this.table.dataTable();
160             var prev_resources = this.current_resources; 
161             /*      \ this.initial_resources
162              *           \
163              * this.          \
164              * current_resources  \    YES    |   NO
165              * --------------------+----------+---------
166              *       YES           | attached | added
167              *       NO            | removed  |   /
168              */
169
170             /*
171              * The first time the query is advertised, don't do anything.  The
172              * component will learn nodes in the slice through the manifest
173              * received through the other subscription 
174              */
175              if (!change)
176                 return;
177              // ioi: Refubrished
178              var initial = this.initial_resources;
179              //var r_removed  = []; //
180              /*-----------------------------------------------------------------------
181                 TODO: remove this dirty hack !!!
182              */
183              resources = jQuery.map(resources, function(x){
184                 if(!('timeslot' in x)){x.timeslot=0;}
185                 return x;
186              });
187              /*
188                 TODO: handle generic keys instead of specific stuff
189                       ex: urn
190                           urn-lease
191              */
192              var initial_urn = $.map(initial, function(x){return x.urn;});
193              var resources_urn = $.map(resources, function(x){return x.urn;});
194              var r_removed = $.grep(initial, function (x) { return $.inArray(x.urn, resources_urn) == -1 });
195              var r_attached = $.grep(initial, function (x) { return $.inArray(x.urn, resources_urn) > -1 });
196              var r_added = $.grep(resources, function (x) { return $.inArray(x.urn, initial_urn) == -1 });
197              exists = false; // ioi
198              /*-----------------------------------------------------------------------*/
199
200              my_oTable.fnClearTable();
201              /*
202                 TODO: factorization of this code !!!
203              */
204              $.each(r_added, function(i, r) { 
205                 //var type = (typeof initial == 'undefined' || r.node != initial.node) ? 'add' : 'attached';
206                 var type = 'add';  
207                 // Create the resource objects
208                 // ioi: refubrished
209                 var urn = r.urn;
210                 time = r.timeslot;
211                               
212                 var SPAN = "<span class='ui-icon ui-icon-close ResourceSelectedClose' id='"+urn+"'/>";
213                 var slot = "<span id='resource_"+urn+"'>" + time + "</span>"; //ioi
214                 // ioi
215                 var newline=Array();
216                 newline.push(type, urn, slot, SPAN); // ioi
217                 var line = my_oTable.fnAddData(newline);
218                 var nTr = my_oTable.fnSettings().aoData[ line[0] ].nTr;
219                 nTr.className = type;
220              });
221              $.each(r_attached, function(i, r) {  
222                 //var type = (typeof initial == 'undefined' || r.node != initial.node) ? 'add' : 'attached';
223                 var type = 'attached';
224                 // Create the resource objects
225                 // ioi: refubrished
226                 var node = r.urn;
227                 time = r.timeslot;
228
229                 var SPAN = "<span class='ui-icon ui-icon-close ResourceSelectedClose' id='"+node+"'/>";
230                 var slot = "<span id='resource_"+node+"'>" + time + "</span>"; //ioi
231                 // ioi
232                 var newline=Array();
233                 newline.push(type, node, slot, SPAN); // ioi
234                 var line = my_oTable.fnAddData(newline);
235                 var nTr = my_oTable.fnSettings().aoData[ line[0] ].nTr;
236                 nTr.className = type;
237              });
238              $.each(r_removed, function(i, r) { 
239                 // The list contains objects
240                 // ioi: refubrished
241                 var node = r.urn;
242                 var time = r.timeslot;
243                     
244                 var SPAN = "<span class='ui-icon ui-icon-close ResourceSelectedClose' id='"+node+"'/>";
245                 var slot = "<span id='resource_"+node+"'>" + time + "</span>";
246                 // ioi
247                 var newline=Array();
248                 newline.push('remove', node, slot, SPAN); // ioi
249                 var line = my_oTable.fnAddData(newline);
250                 var nTr = my_oTable.fnSettings().aoData[ line[0] ].nTr;
251                 nTr.className = 'remove';
252              });
253
254              this.current_resources = $.merge(r_attached,r_added);
255
256              /* Allow the user to update the slice */
257              //jQuery('#updateslice-' + data.ResourceSelected.plugin_uuid).prop('disabled', false);
258
259         } // update_resources
260
261     } // ResourcesSelected
262
263
264     /***************************************************************************
265      * Private methods
266      ***************************************************************************/
267
268     /* Callbacks */    
269     function close_click(event){
270         //jQuery.publish('selected', 'add/'+key_value);
271         // this.parentNode is <td> this.parentNode.parentNode is <tr> 
272         // this.parentNode.parentNode.firstChild is the first cell <td> of this line <tr>
273         // this.parentNode.parentNode.firstChild.firstChild is the text in that cell
274         //var firstCellVal=this.parentNode.parentNode.firstChild.firstChild.data;
275         var remove_urn = this.id; 
276         var current_resources = event.data.instance.current_resources;
277         var list_resources = $.grep(current_resources, function(x) {return x.urn != remove_urn});
278         //jQuery.publish('selected', 'cancel/'+this.id+'/'+get_value(firstCellVal));
279         $.publish('/update-set/' + event.data.instance.options.resource_query_uuid, [list_resources, true]);
280     }
281
282 })(jQuery);