Chrysostomos for scheduler
[unfold.git] / plugins / scheduler2 / static / js / scheduler2.js
1 /*\r
2 #\r
3 # Copyright (c) 2013 NITLab, University of Thessaly, CERTH, Greece\r
4 #\r
5 # Permission is hereby granted, free of charge, to any person obtaining a copy\r
6 # of this software and associated documentation files (the "Software"), to deal\r
7 # in the Software without restriction, including without limitation the rights\r
8 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r
9 # copies of the Software, and to permit persons to whom the Software is\r
10 # furnished to do so, subject to the following conditions:\r
11 #\r
12 # The above copyright notice and this permission notice shall be included in\r
13 # all copies or substantial portions of the Software.\r
14 #\r
15 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
16 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
17 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE\r
18 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
19 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
20 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r
21 # THE SOFTWARE.\r
22 #\r
23 #\r
24 # This is a MySlice plugin for the NITOS Scheduler\r
25 # Nitos Scheduler v1\r
26 #\r
27 */\r
28 \r
29 /* some params */\r
30 var scheduler2;\r
31 var scheduler2Instance;\r
32 //is ctrl keyboard button pressed\r
33 var schedulerCtrlPressed = false;\r
34 //table Id\r
35 var schedulerTblId = "scheduler-reservation-table";\r
36 var schedulerTblFirstColWidth = 150;\r
37 //Some Data\r
38 var schedulerSlotsPerHour = 6;\r
39 var schedulerMaxRows = 12;\r
40 var SchedulerData = [];\r
41 var SchedulerSlots = [];\r
42 var SchedulerDateSelected = new Date();\r
43 var SchedulerDataViewData = [];\r
44 var SchedulerSlotsViewData = [];\r
45 var SchedulerTotalCells;\r
46 var SchedulerTotalVisibleCells;\r
47 //Help Variables\r
48 var _schedulerCurrentCellPosition = 0;\r
49 var _leasesDone = false;\r
50 var _resourcesDone = false;\r
51 //Enable Debug\r
52 var schedulerDebug = true;\r
53 //tmp to delete\r
54 var tmpSchedulerLeases = [];\r
55 \r
56 (function($) {\r
57         scheduler2 = Plugin.extend({\r
58 \r
59             /** XXX to check\r
60          * @brief Plugin constructor\r
61          * @param options : an associative array of setting values\r
62          * @param element : \r
63          * @return : a jQuery collection of objects on which the plugin is\r
64          *     applied, which allows to maintain chainability of calls\r
65          */\r
66             init: function(options, element) {\r
67                 this.classname = "scheduler2";\r
68                 // Call the parent constructor, see FAQ when forgotten\r
69                 this._super(options, element);\r
70                 scheduler2Instance = this;\r
71                 // We need to remember the active filter for datatables filtering\r
72                 this.filters = Array();\r
73 \r
74 \r
75                 SchedulerSlots = schedulerGetSlots(60 / schedulerSlotsPerHour);\r
76                 //selection from table \r
77                 $(window).keydown(function(evt) {\r
78                     if (evt.which == 17) { // ctrl\r
79                         schedulerCtrlPressed = true;\r
80                     }\r
81                 }).keyup(function(evt) {\r
82                     if (evt.which == 17) { // ctrl\r
83                         schedulerCtrlPressed = false;\r
84                     }\r
85                 });\r
86                 $("#" + schedulerTblId).on('mousedown', 'td', rangeMouseDown).on('mouseup', 'td', rangeMouseUp).on('mousemove', 'td', rangeMouseMove);\r
87 \r
88                 // Explain this will allow query events to be handled\r
89                 // What happens when we don't define some events ?\r
90                 // Some can be less efficient\r
91 \r
92                 if (schedulerDebug) console.time("Listening_to_queries");\r
93                 /* Listening to queries */\r
94 \r
95                 this.listen_query(options.query_uuid);\r
96                 //this.listen_query(options.query_all_uuid, 'all');\r
97                 this.listen_query(options.query_all_resources_uuid, 'all_resources');\r
98                 this.listen_query(options.query_lease_uuid, 'lease');\r
99                 this.listen_query(options.query_all_leases_uuid, 'all_leases');\r
100                 if (schedulerDebug) console.timeEnd("Listening_to_queries");\r
101 \r
102             },\r
103 \r
104             /* Handlers */\r
105 \r
106             /* all_ev QUERY HANDLERS Start */\r
107             on_all_ev_clear_records: function(data) {\r
108                 //alert('all_ev clear_records');\r
109             },\r
110             on_all_ev_query_in_progress: function(data) {\r
111                 // alert('all_ev query_in_progress');\r
112             },\r
113             on_all_ev_new_record: function(data) {\r
114                 //alert('all_ev new_record');\r
115             },\r
116             on_all_ev_query_done: function(data) {\r
117                 //alert('all_ev query_done');\r
118             },\r
119             //another plugin has modified something, that requires you to update your display. \r
120             on_all_ev_field_state_changed: function(data) {\r
121                 //alert('all_ev query_done');\r
122             },\r
123             /* all_ev QUERY HANDLERS End */\r
124             /* all_resources QUERY HANDLERS Start */\r
125             on_all_resources_clear_records: function(data) {\r
126                 //data is empty on load\r
127             },\r
128             on_all_resources_query_in_progress: function(data) {\r
129                 //data is empty on load\r
130             },\r
131             on_all_resources_new_record: function(data) {\r
132                 //alert(data.toSource());\r
133                 if (data.exclusive == true) {\r
134                     var tmpGran = schedulerDebug && data.granularity == null ? 1800 : data.granularity;\r
135                     SchedulerData.push({\r
136                         id: data.urn,\r
137                         index: SchedulerData.length,\r
138                         name: data.hrn,\r
139                         granularity: tmpGran,\r
140                         leases: schedulerGetLeases(60 / schedulerSlotsPerHour, tmpGran),\r
141                         type: data.type,\r
142                         org_resource: data\r
143                     });\r
144                     /*if (schedulerDebug && SchedulerData[SchedulerData.length - 1].org_resource.network_hrn == 'omf') {\r
145                         SchedulerData[SchedulerData.length - 1].granularity = 1800;\r
146                     }*/\r
147                 }\r
148                 //alert(data.toSource());\r
149 \r
150             },\r
151             on_all_resources_query_done: function(data) {\r
152                 _resourcesDone = true;\r
153                 this._initScheduler();\r
154             },\r
155             //another plugin has modified something, that requires you to update your display. \r
156             on_all_resources_field_state_changed: function(data) {\r
157                 //alert('all_resources query_done');\r
158             },\r
159             /* all_resources QUERY HANDLERS End */\r
160             /* lease QUERY HANDLERS Start */\r
161             on_lease_clear_records: function(data) { console.log('clear_records'); },\r
162             on_lease_query_in_progress: function(data) { console.log('lease_query_in_progress'); },\r
163             on_all_leases_new_record: function(data) {\r
164                 if (data.resource.indexOf("nitos") > -1) {\r
165                     tmpSchedulerLeases.push({\r
166                         id: schedulerGetSlotId(data.start_time, data.duration, data.granularity),\r
167                         end_id: schedulerGetSlotId(data.end_time, data.duration, data.granularity),\r
168                         slice: data.slice,\r
169                         status: 'reserved',\r
170                         resource: data.resource,\r
171                         network: data.network,\r
172                         start_time: new Date(data.start_time * 1000),\r
173                         start_time_unixtimestamp: data.start_time,\r
174                         end_time: new Date(data.end_time * 1000),\r
175                         end_time_unixtimestamp: data.end_time,\r
176                         lease_type: data.lease_type,\r
177                         granularity: data.granularity,\r
178                         duration: data.duration\r
179                     });\r
180                 }\r
181                 //console.log(data.toSource()); console.log('lease_new_record');\r
182             },\r
183             on_all_leases_query_done: function(data) {\r
184                 _leasesDone = true;\r
185                 this._initScheduler();\r
186                 // console.log('lease_query_done');\r
187             },\r
188             //another plugin has modified something, that requires you to update your display. \r
189             on_lease_field_state_changed: function(data) { console.log('lease_field_state_changed'); },\r
190             /* lease QUERY HANDLERS End */\r
191 \r
192 \r
193             // no prefix\r
194             on_filter_added: function(filter) {\r
195                 this.filters.push(filter);\r
196                 this._SetFiletredResources(this.filters);\r
197                 //angular and UI\r
198                 var tmpScope = angular.element(document.getElementById('SchedulerCtrl')).scope();\r
199                 if (SchedulerDataViewData.length == 0) {\r
200                     $("#plugin-scheduler").hide();\r
201                     $("#plugin-scheduler-empty").show();\r
202                     tmpScope.clearStuff();\r
203                 } else {\r
204                     $("#plugin-scheduler-empty").hide();\r
205                     $("#plugin-scheduler").show();\r
206                     tmpScope.initSchedulerResources(schedulerMaxRows < SchedulerDataViewData.length ? schedulerMaxRows : SchedulerDataViewData.length);\r
207                 }\r
208             },\r
209 \r
210             on_filter_removed: function(filter) {\r
211                 // Remove corresponding filters\r
212                 this.filters = $.grep(this.filters, function(x) {\r
213                     return x == filter;\r
214                 });\r
215                 this._SetFiletredResources(this.filters);\r
216                 //angular and UI\r
217                 var tmpScope = angular.element(document.getElementById('SchedulerCtrl')).scope();\r
218                 if (SchedulerDataViewData.length == 0) {\r
219                     $("#plugin-scheduler").hide();\r
220                     $("#plugin-scheduler-empty").show();\r
221                     tmpScope.clearStuff();\r
222                 } else {\r
223                     $("#plugin-scheduler-empty").hide();\r
224                     $("#plugin-scheduler").show();\r
225                     tmpScope.initSchedulerResources(schedulerMaxRows < SchedulerDataViewData.length ? schedulerMaxRows : SchedulerDataViewData.length);\r
226                 }\r
227             },\r
228 \r
229             on_filter_clear: function() {\r
230                 this.filters = [];\r
231                 this._SetFiletredResources(this.filters);\r
232                 //angular and UI\r
233                 var tmpScope = angular.element(document.getElementById('SchedulerCtrl')).scope();\r
234                 if (SchedulerDataViewData.length == 0) {\r
235                     $("#plugin-scheduler").hide();\r
236                     $("#plugin-scheduler-empty").show();\r
237                     tmpScope.clearStuff();\r
238                 } else {\r
239                     $("#plugin-scheduler-empty").hide();\r
240                     $("#plugin-scheduler").show();\r
241                     tmpScope.initSchedulerResources(schedulerMaxRows < SchedulerDataViewData.length ? schedulerMaxRows : SchedulerDataViewData.length);\r
242                 }\r
243             },\r
244 \r
245             on_all_leases_filter_added: function(filter) {\r
246                 console.log("Filter on Leases added !");\r
247             },\r
248 \r
249             // ... be sure to list all events here\r
250 \r
251             /* RECORD HANDLERS */\r
252             on_all_new_record: function(record) {\r
253                 //alert('on_all_new_record');\r
254             },\r
255 \r
256             debug: function(logTxt) {\r
257                 if (typeof window.console != 'undefined') {\r
258                     console.debug(logTxt);\r
259                 }\r
260             },\r
261 \r
262             /* INTERNAL FUNCTIONS */\r
263             _initScheduler: function() {\r
264                 if (_resourcesDone && _leasesDone) {\r
265                     SchedulerDataViewData = SchedulerData;\r
266                     /* GUI setup and event binding */\r
267                     this._FixLeases();\r
268                     this._initUI();\r
269                 }\r
270             },\r
271 \r
272             _initUI: function() {\r
273                 //alert(1);\r
274                 if (schedulerDebug) console.time("_initUI");\r
275                 //init DatePicker Start\r
276                 $("#DateToRes").datepicker({\r
277                     dateFormat: "yy-mm-dd",\r
278                     minDate: 0,\r
279                     numberOfMonths: 3\r
280                 }).change(function() {\r
281                     //Scheduler2.loadWithDate();\r
282                     SchedulerDateSelected = $("#DateToRes").datepicker("getDate");\r
283                     if (SchedulerDateSelected != null && SchedulerDateSelected != '') {\r
284                         for (var i = 0; i < SchedulerData.length; i++) {\r
285                             SchedulerData[i].leases = schedulerGetLeases(60 / schedulerSlotsPerHour, SchedulerData[i].granularity);\r
286                         }\r
287                         scheduler2Instance._FixLeases();\r
288                         $('#tblSlider').slider('value', 0);\r
289                         var tmpScope = angular.element(document.getElementById('SchedulerCtrl')).scope();\r
290                         tmpScope.initSchedulerResources(schedulerMaxRows < SchedulerDataViewData.length ? schedulerMaxRows : SchedulerDataViewData.length);\r
291 \r
292                         //console.log(SchedulerDateSelected);\r
293                         //console.log(SchedulerDateSelected.getTime()/1000);\r
294                         var tomorrow = new Date(SchedulerDateSelected);\r
295                         tomorrow.setDate(SchedulerDateSelected.getDate()+1);\r
296                         //console.log(tomorrow);\r
297                         //console.log(tomorrow.getTime()/1000);\r
298                         \r
299                         // Remove previous date interval\r
300                         manifold.raise_event(scheduler2Instance.options.query_all_leases_uuid, FILTER_REMOVED, ['start_time', '>']);\r
301                         manifold.raise_event(scheduler2Instance.options.query_all_leases_uuid, FILTER_REMOVED, ['start_time', '<']);\r
302 \r
303                         // Add new date interval\r
304                         manifold.raise_event(scheduler2Instance.options.query_all_leases_uuid, FILTER_ADDED, ['start_time', '>', SchedulerDateSelected.getTime()/1000]);\r
305                         manifold.raise_event(scheduler2Instance.options.query_all_leases_uuid, FILTER_ADDED, ['start_time', '<', tomorrow.getTime()/1000]);\r
306                     } else {\r
307                         alert("Please select a date, so the scheduler can reserve leases.");\r
308                     }\r
309                 }).datepicker('setDate', SchedulerDateSelected);\r
310                 /*.click(function () {\r
311                 $("#ui-datepicker-div").css("z-index", 5);\r
312             })*/\r
313                 //End init DatePicker\r
314 \r
315                 //init Table\r
316                 this._FixTable();\r
317                 //End init Table\r
318 \r
319                 //init Slider\r
320                 $('#tblSlider').slider({\r
321                     min: 0,\r
322                     max: SchedulerTotalCells - SchedulerTotalVisibleCells,\r
323                     value: 0,\r
324                     slide: function(event, ui) {\r
325                         //$("#amount").val("$" + ui.values[0] + " - $" + ui.values[1]);\r
326                         //console.log(ui.value);\r
327                         var angScope = angular.element(document.getElementById('SchedulerCtrl')).scope();\r
328                         if (_schedulerCurrentCellPosition > ui.value) {\r
329                             angScope.moveBackSlot(ui.value, ui.value + SchedulerTotalVisibleCells);\r
330                         } else if (_schedulerCurrentCellPosition < ui.value) {\r
331                             angScope.moveFrontSlot(ui.value, ui.value + SchedulerTotalVisibleCells);\r
332                         }\r
333                         _schedulerCurrentCellPosition = ui.value;\r
334                     }\r
335                 });\r
336                 //End init Slider\r
337 \r
338 \r
339                 //btn Submit leases\r
340                 $('#btnSchedulerSubmit').click(function () {\r
341                     console.log("click btnSchedulerSubmit");\r
342                     var leasesForCommit = new Array();\r
343                     var tmpDateTime = SchedulerDateSelected;\r
344                     console.log(SchedulerData);\r
345                     for (var i = 0; i < SchedulerData.length; i++)\r
346                     {\r
347                         var tpmR = SchedulerData[i];\r
348                         //for capturing start and end of the lease\r
349                         var newLeaseStarted = false;\r
350                         for (var j = 0; j < tpmR.leases.length; j++) {\r
351                             var tpmL = tpmR.leases[j];\r
352                             if (newLeaseStarted == false && tpmL.status == 'selected') {\r
353                                 //get date of the slot\r
354                                 tmpDateTime = schedulerGetDateTimeFromSlotId(tpmL.id, tmpDateTime);\r
355                                 var unixStartTime = tmpDateTime.getTime() / 1000;\r
356                                 //add lease object\r
357                                 leasesForCommit.push({\r
358                                     resource: tpmR.id,\r
359                                     //granularity: tpmR.granularity,\r
360                                     //lease_type: null,\r
361                                     //slice: null,\r
362                                     start_time: unixStartTime,\r
363                                     end_time: null,\r
364                                     //duration: null\r
365                                 });\r
366                                 console.log(tpmR.id);\r
367                                 newLeaseStarted = true;\r
368                             } else if (newLeaseStarted == true && tpmL.status != 'selected') {\r
369                                 //get date of the slot\r
370                                 tmpDateTime = schedulerGetDateTimeFromSlotId(tpmL.id, tmpDateTime);\r
371                                 var unixEndTime = tmpDateTime.getTime() / 1000;\r
372                                 //upate end_time\r
373                                 var tmpCL = leasesForCommit[leasesForCommit.length - 1];\r
374                                 tmpCL.end_time = unixEndTime;\r
375                                 //tmpCL.duration = schedulerFindDuration(tmpCL.start_time, tmpCL.end_time, tmpCL.granularity);\r
376                                 newLeaseStarted = false;\r
377                             }\r
378                         }\r
379                     }\r
380                     console.log(leasesForCommit);\r
381                     for (var i = 0; i < leasesForCommit.length; i++) {\r
382                         manifold.raise_event(scheduler2Instance.options.query_lease_uuid, SET_ADD, leasesForCommit[i]);\r
383                     }\r
384                 });\r
385                 //\r
386 \r
387 \r
388                 //End btn Submit leases\r
389 \r
390                 //other stuff\r
391                 $("#plugin-scheduler-loader").hide();\r
392                 $("#plugin-scheduler").show();\r
393                 //fixOddEvenClasses();\r
394                 //$("#" + schedulerTblId + " td:not([class])").addClass("free");\r
395                 if (schedulerDebug) console.timeEnd("_initUI");\r
396             },\r
397 \r
398         _FixLeases  : function () {\r
399             for (var i = 0; i < tmpSchedulerLeases.length; i++) {\r
400                 var tmpLea = tmpSchedulerLeases[i];\r
401                 if ((schedulerCompareOnDay(tmpLea.start_time, SchedulerDateSelected) == 0) ||\r
402                                 (tmpLea.start_time <= SchedulerDateSelected && SchedulerDateSelected <= tmpLea.end_time) || \r
403                                 (schedulerCompareOnDay(tmpLea.end_time, SchedulerDateSelected) == 0)) {\r
404                     var tmpRes = schedulerFindResourceById(SchedulerData, tmpLea.resource);\r
405                     if (tmpRes != null) {\r
406                         //Replace Lease with current lease from the manifold\r
407                         var orgLease = tmpRes.leases[tmpLea.id];\r
408                         tmpLea['groupid'] = orgLease.groupid;\r
409                         tmpLea['groupIndex'] = orgLease.groupIndex;\r
410                         if (orgLease.groupIndex != 0) {\r
411                             if (!window.console) {\r
412                                 console.warn('there is an error with the leases of the resource :' + tmpRes.name + '\n The lease start in the middle of the granularity!' + '\n The Scheduler plugin might not work!');\r
413                             }\r
414                         }\r
415                         tmpRes.leases[tmpLea.id] = tmpLea;\r
416                         this._ExtractLeaseSlots(tmpRes, tmpRes.leases[tmpLea.id]);\r
417                     }\r
418                 }\r
419             }\r
420         },\r
421 \r
422         _ExtractLeaseSlots: function (tmpRes, lease) {\r
423             var tmpStartDate = lease.start_time;\r
424             var tmpEndDate = lease.end_time;\r
425             var startLoop; var toLoop;\r
426             if (schedulerCompareOnDay(lease.start_time,lease.end_time) == 0) {\r
427                 //in the same date\r
428                 startLoop = lease.id;\r
429                 toLoop = lease.end_id;\r
430             } else if (lease.start_time < SchedulerDateSelected && SchedulerDateSelected < lease.end_time) {\r
431                 //one hole day (more than 3days)\r
432                 startLoop = 0;\r
433                 toLoop = tmpRes.leases.length;\r
434             } else if (schedulerCompareOnDay(lease.start_time, SchedulerDateSelected) == 0) {\r
435                 //the same day and extends\r
436                 startLoop = lease.id;\r
437                 toLoop = tmpRes.leases.length;\r
438             } else if (schedulerCompareOnDay(lease.end_time, SchedulerDateSelected) == 0) {\r
439                 //extends to the last say\r
440                 startLoop = 0;\r
441                 toLoop = lease.end_id;\r
442             }\r
443             //var minutGran = tmpRes.granularity * 60;\r
444             for (var li = lease.id; li < toLoop; li++) {\r
445                 tmpRes.leases[li].status = 'reserved';\r
446             }\r
447             \r
448             //reserved\r
449             //tmpRes.leases[tmpLea.id\r
450         },\r
451 \r
452         _FixTable: function () {\r
453             var colWidth = 50;\r
454             SchedulerTotalCells = SchedulerSlots.length;\r
455             $('#' + schedulerTblId + ' thead tr th:eq(0)').css("width", schedulerTblFirstColWidth); //.css("display", "block");\r
456             //this get width might need fix depending on the template \r
457             var tblwidth = $('#scheduler-tab').parent().outerWidth();\r
458             SchedulerTotalVisibleCells = parseInt((tblwidth - schedulerTblFirstColWidth) / colWidth);\r
459 \r
460             //if (SchedulerData.length == 0) {\r
461             //    //puth some test data\r
462             //    SchedulerData.push({ name: 'xyz+aaa', leases: schedulerGetLeases(60 / schedulerSlotsPerHour), urn: 'xyz+aaa', type: 'node' });\r
463             //    SchedulerData.push({ name: 'xyz+bbb', leases: schedulerGetLeases(60 / schedulerSlotsPerHour), urn: 'xyz+bbb', type: 'node' });\r
464             //    SchedulerData.push({ name: 'xyz+ccc', leases: schedulerGetLeases(60 / schedulerSlotsPerHour), urn: 'xyz+ccc', type: 'node' });\r
465             //    SchedulerData.push({ name: 'nitos1', leases: schedulerGetLeases(60 / schedulerSlotsPerHour), urn: 'nitos1', type: 'node' });\r
466             //}\r
467             var tmpScope = angular.element(document.getElementById('SchedulerCtrl')).scope();\r
468             tmpScope.initSchedulerResources(schedulerMaxRows < SchedulerDataViewData.length ? schedulerMaxRows : SchedulerDataViewData.length);\r
469 \r
470         },\r
471 \r
472         _SetFiletredResources : function (filters) {\r
473             if (filters.length > 0) {\r
474                 SchedulerDataViewData = new Array();\r
475                 var tmpAddIt = true;\r
476                 for (var i = 0; i < SchedulerData.length; i++) {\r
477                     loopfilters:\r
478                     for (var f = 0; f < filters.length; f++) {\r
479                         tmpAddIt = this._FilterResource(SchedulerData[i], filters[f]);\r
480                         if (tmpAddIt == false) break loopfilters;\r
481                     }\r
482                     if (tmpAddIt) {\r
483                         SchedulerDataViewData.push(SchedulerData[i]);\r
484                     }\r
485                 }\r
486             } else {\r
487                 SchedulerDataViewData = SchedulerData;\r
488             }\r
489         },\r
490 \r
491         _FilterResource: function (resource, filter) {\r
492             var key = filter[0];\r
493             var op = filter[1];\r
494             var value = filter[2];\r
495             var colValue = resource.org_resource[key];\r
496             var ret = true;\r
497             if (schedulerDebug &&  colValue == 'omf') colValue = 'nitos';\r
498 \r
499             if (op == '=' || op == '==') {\r
500                 if (colValue != value || colValue == null || colValue == "" || colValue == "n/a")\r
501                     ret = false;\r
502             } else if (op == 'included') {\r
503                 $.each(value, function (i, x) {\r
504                     if (x == colValue) {\r
505                         ret = true;\r
506                         return false;\r
507                     } else {\r
508                         ret = false;\r
509                     }\r
510                 });\r
511             } else if (op == '!=') {\r
512                 if (colValue == value || colValue == null || colValue == "" || colValue == "n/a")\r
513                     ret = false;\r
514             }\r
515 \r
516             return ret;\r
517         },\r
518 \r
519         _SetPeriodInPage: function (start, end) {\r
520         }\r
521     });\r
522 \r
523     //Sched2 = new Scheduler2();\r
524 \r
525     /* Plugin registration */\r
526     $.plugin('Scheduler2', scheduler2);\r
527 \r
528     // TODO Here use cases for instanciating plugins in different ways like in the pastie.\r
529 \r
530 \r
531 })(jQuery);\r
532 \r
533 \r
534 \r