1/*** 2 * Contains core SlickGrid classes. 3 * @module Core 4 * @namespace Slick 5 */ 6 7(function($) { 8 // register namespace 9 $.extend(true, window, { 10 "Slick": { 11 "Event": Event, 12 "EventData": EventData, 13 "Range": Range, 14 "NonDataRow": NonDataItem, 15 "Group": Group, 16 "GroupTotals": GroupTotals, 17 "EditorLock": EditorLock, 18 19 /*** 20 * A global singleton editor lock. 21 * @class GlobalEditorLock 22 * @static 23 * @constructor 24 */ 25 "GlobalEditorLock": new EditorLock() 26 } 27 }); 28 29 /*** 30 * An event object for passing data to event handlers and letting them control propagation. 31 * <p>This is pretty much identical to how W3C and jQuery implement events.</p> 32 * @class EventData 33 * @constructor 34 */ 35 function EventData() { 36 var isPropagationStopped = false; 37 var isImmediatePropagationStopped = false; 38 39 /*** 40 * Stops event from propagating up the DOM tree. 41 * @method stopPropagation 42 */ 43 this.stopPropagation = function() { 44 isPropagationStopped = true; 45 }; 46 47 /*** 48 * Returns whether stopPropagation was called on this event object. 49 * @method isPropagationStopped 50 * @return {Boolean} 51 */ 52 this.isPropagationStopped = function() { 53 return isPropagationStopped; 54 }; 55 56 /*** 57 * Prevents the rest of the handlers from being executed. 58 * @method stopImmediatePropagation 59 */ 60 this.stopImmediatePropagation = function() { 61 isImmediatePropagationStopped = true; 62 }; 63 64 /*** 65 * Returns whether stopImmediatePropagation was called on this event object.\ 66 * @method isImmediatePropagationStopped 67 * @return {Boolean} 68 */ 69 this.isImmediatePropagationStopped = function() { 70 return isImmediatePropagationStopped; 71 } 72 } 73 74 /*** 75 * A simple publisher-subscriber implementation. 76 * @class Event 77 * @constructor 78 */ 79 function Event() { 80 var handlers = []; 81 82 /*** 83 * Adds an event handler to be called when the event is fired. 84 * <p>Event handler will receive two arguments - an <code>EventData</code> and the <code>data</code> 85 * object the event was fired with.<p> 86 * @method subscribe 87 * @param fn {Function} Event handler. 88 */ 89 this.subscribe = function(fn) { 90 handlers.push(fn); 91 }; 92 93 /*** 94 * Removes an event handler added with <code>subscribe(fn)</code>. 95 * @method unsubscribe 96 * @param fn {Function} Event handler to be removed. 97 */ 98 this.unsubscribe = function(fn) { 99 for (var i = handlers.length - 1; i >= 0; i--) { 100 if (handlers[i] === fn) { 101 handlers.splice(i, 1); 102 } 103 } 104 }; 105 106 /*** 107 * Fires an event notifying all subscribers. 108 * @method notify 109 * @param args {Object} Additional data object to be passed to all handlers. 110 * @param e {EventData} 111 * Optional. 112 * An <code>EventData</code> object to be passed to all handlers. 113 * For DOM events, an existing W3C/jQuery event object can be passed in. 114 * @param scope {Object} 115 * Optional. 116 * The scope ("this") within which the handler will be executed. 117 * If not specified, the scope will be set to the <code>Event</code> instance. 118 */ 119 this.notify = function(args, e, scope) { 120 e = e || new EventData(); 121 scope = scope || this; 122 123 var returnValue; 124 for (var i = 0; i < handlers.length && !(e.isPropagationStopped() || e.isImmediatePropagationStopped()); i++) { 125 returnValue = handlers[i].call(scope, e, args); 126 } 127 128 return returnValue; 129 }; 130 } 131 132 /*** 133 * A structure containing a range of cells. 134 * @class Range 135 * @constructor 136 * @param fromRow {Integer} Starting row. 137 * @param fromCell {Integer} Starting cell. 138 * @param toRow {Integer} Optional. Ending row. Defaults to <code>fromRow</code>. 139 * @param toCell {Integer} Optional. Ending cell. Defaults to <code>fromCell</code>. 140 */ 141 function Range(fromRow, fromCell, toRow, toCell) { 142 if (toRow === undefined && toCell === undefined) { 143 toRow = fromRow; 144 toCell = fromCell; 145 } 146 147 /*** 148 * @property fromRow 149 * @type {Integer} 150 */ 151 this.fromRow = Math.min(fromRow, toRow); 152 153 /*** 154 * @property fromCell 155 * @type {Integer} 156 */ 157 this.fromCell = Math.min(fromCell, toCell); 158 159 /*** 160 * @property toRow 161 * @type {Integer} 162 */ 163 this.toRow = Math.max(fromRow, toRow); 164 165 /*** 166 * @property toCell 167 * @type {Integer} 168 */ 169 this.toCell = Math.max(fromCell, toCell); 170 171 /*** 172 * Returns whether a range represents a single row. 173 * @method isSingleRow 174 * @return {Boolean} 175 */ 176 this.isSingleRow = function() { 177 return this.fromRow == this.toRow; 178 }; 179 180 /*** 181 * Returns whether a range represents a single cell. 182 * @method isSingleCell 183 * @return {Boolean} 184 */ 185 this.isSingleCell = function() { 186 return this.fromRow == this.toRow && this.fromCell == this.toCell; 187 }; 188 189 /*** 190 * Returns whether a range contains a given cell. 191 * @method contains 192 * @param row {Integer} 193 * @param cell {Integer} 194 * @return {Boolean} 195 */ 196 this.contains = function(row, cell) { 197 return row >= this.fromRow && row <= this.toRow && 198 cell >= this.fromCell && cell <= this.toCell; 199 }; 200 201 /*** 202 * Returns a readable representation of a range. 203 * @method toString 204 * @return {String} 205 */ 206 this.toString = function() { 207 if (this.isSingleCell()) { 208 return "(" + this.fromRow + ":" + this.fromCell + ")"; 209 } 210 else { 211 return "(" + this.fromRow + ":" + this.fromCell + " - " + this.toRow + ":" + this.toCell + ")"; 212 } 213 } 214 } 215 216 217 /*** 218 * A base class that all special / non-data rows (like Group and GroupTotals) derive from. 219 * @class NonDataItem 220 * @constructor 221 */ 222 function NonDataItem() { 223 this.__nonDataRow = true; 224 } 225 226 227 /*** 228 * Information about a group of rows. 229 * @class Group 230 * @extends Slick.NonDataItem 231 * @constructor 232 */ 233 function Group() { 234 this.__group = true; 235 this.__updated = false;
236 237 /*** 238 * Number of rows in the group. 239 * @property count 240 * @type {Integer} 241 */ 242 this.count = 0; 243 244 /*** 245 * Grouping value. 246 * @property value 247 * @type {Object} 248 */ 249 this.value = null; 250 251 /*** 252 * Formatted display value of the group. 253 * @property title 254 * @type {String} 255 */ 256 this.title = null; 257 258 /*** 259 * Whether a group is collapsed. 260 * @property collapsed 261 * @type {Boolean} 262 */ 263 this.collapsed = false; 264 265 /*** 266 * GroupTotals, if any. 267 * @property totals 268 * @type {GroupTotals} 269 */ 270 this.totals = null; 271 } 272 273 Group.prototype = new NonDataItem(); 274 275 /*** 276 * Compares two Group instances. 277 * @method equals 278 * @return {Boolean} 279 * @param group {Group} Group instance to compare to. 280 */ 281 Group.prototype.equals = function(group) { 282 return this.value === group.value && 283 this.count === group.count && 284 this.collapsed === group.collapsed; 285 }; 286 287 /*** 288 * Information about group totals. 289 * An instance of GroupTotals will be created for each totals row and passed to the aggregators 290 * so that they can store arbitrary data in it. That data can later be accessed by group totals 291 * formatters during the display. 292 * @class GroupTotals 293 * @extends Slick.NonDataItem 294 * @constructor 295 */ 296 function GroupTotals() { 297 this.__groupTotals = true; 298 299 /*** 300 * Parent Group. 301 * @param group 302 * @type {Group} 303 */ 304 this.group = null; 305 } 306 307 GroupTotals.prototype = new NonDataItem(); 308 309 /*** 310 * A locking helper to track the active edit controller and ensure that only a single controller 311 * can be active at a time. This prevents a whole class of state and validation synchronization 312 * issues. An edit controller (such as SlickGrid) can query if an active edit is in progress 313 * and attempt a commit or cancel before proceeding. 314 * @class EditorLock 315 * @constructor 316 */ 317 function EditorLock() { 318 var activeEditController = null; 319 320 /*** 321 * Returns true if a specified edit controller is active (has the edit lock). 322 * If the parameter is not specified, returns true if any edit controller is active. 323 * @method isActive 324 * @param editController {EditController} 325 * @return {Boolean} 326 */ 327 this.isActive = function(editController) { 328 return (editController ? activeEditController === editController : activeEditController !== null); 329 }; 330 331 /*** 332 * Sets the specified edit controller as the active edit controller (acquire edit lock). 333 * If another edit controller is already active, and exception will be thrown. 334 * @method activate 335 * @param editController {EditController} edit controller acquiring the lock 336 */ 337 this.activate = function(editController) { 338 if (editController === activeEditController) { // already activated? 339 return; 340 } 341 if (activeEditController !== null) { 342 throw "SlickGrid.EditorLock.activate: an editController is still active, can't activate another editController"; 343 } 344 if (!editController.commitCurrentEdit) { 345 throw "SlickGrid.EditorLock.activate: editController must implement .commitCurrentEdit()"; 346 } 347 if (!editController.cancelCurrentEdit) { 348 throw "SlickGrid.EditorLock.activate: editController must implement .cancelCurrentEdit()"; 349 } 350 activeEditController = editController; 351 }; 352 353 /*** 354 * Unsets the specified edit controller as the active edit controller (release edit lock). 355 * If the specified edit controller is not the active one, an exception will be thrown. 356 * @method deactivate 357 * @param editController {EditController} edit controller releasing the lock 358 */ 359 this.deactivate = function(editController) { 360 if (activeEditController !== editController) { 361 throw "SlickGrid.EditorLock.deactivate: specified editController is not the currently active one"; 362 } 363 activeEditController = null; 364 }; 365 366 /*** 367 * Attempts to commit the current edit by calling "commitCurrentEdit" method on the active edit 368 * controller and returns whether the commit attempt was successful (commit may fail due to validation 369 * errors, etc.). Edit controller's "commitCurrentEdit" must return true if the commit has succeeded 370 * and false otherwise. If no edit controller is active, returns true. 371 * @method commitCurrentEdit 372 * @return {Boolean} 373 */ 374 this.commitCurrentEdit = function() { 375 return (activeEditController ? activeEditController.commitCurrentEdit() : true); 376 }; 377 378 /*** 379 * Attempts to cancel the current edit by calling "cancelCurrentEdit" method on the active edit 380 * controller and returns whether the edit was successfully cancelled. If no edit controller is 381 * active, returns true. 382 * @method cancelCurrentEdit 383 * @return {Boolean} 384 */ 385 this.cancelCurrentEdit = function cancelCurrentEdit() { 386 return (activeEditController ? activeEditController.cancelCurrentEdit() : true); 387 }; 388 } 389})(jQuery); 390 391
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.