1/*** 2 * Contains basic SlickGrid editors. 3 * @module Editors 4 * @namespace Slick 5 */ 6 7(function ($) { 8 // register namespace 9 $.extend(true, window, { 10 "Slick": { 11 "Editors": { 12 "Text": TextEditor, 13 "Integer": IntegerEditor, 14 "Date": DateEditor, 15 "YesNoSelect": YesNoSelectEditor, 16 "Checkbox": CheckboxEditor, 17 "PercentComplete": PercentCompleteEditor, 18 "LongText": LongTextEditor 19 } 20 } 21 }); 22 23 function TextEditor(args) { 24 var $input; 25 var defaultValue; 26 var scope = this; 27 28 this.init = function () { 29 $input = $("<INPUT type=text class='editor-text' />") 30 .appendTo(args.container) 31 .bind("keydown.nav", function (e) { 32 if (e.keyCode === $.ui.keyCode.LEFT || e.keyCode === $.ui.keyCode.RIGHT) { 33 e.stopImmediatePropagation(); 34 } 35 }) 36 .focus() 37 .select(); 38 }; 39 40 this.destroy = function () { 41 $input.remove(); 42 }; 43 44 this.focus = function () { 45 $input.focus(); 46 }; 47 48 this.getValue = function () { 49 return $input.val(); 50 }; 51 52 this.setValue = function (val) { 53 $input.val(val); 54 }; 55 56 this.loadValue = function (item) { 57 defaultValue = item[args.column.field] || ""; 58 $input.val(defaultValue); 59 $input[0].defaultValue = defaultValue; 60 $input.select(); 61 }; 62 63 this.serializeValue = function () { 64 return $input.val(); 65 }; 66 67 this.applyValue = function (item, state) { 68 item[args.column.field] = state; 69 }; 70 71 this.isValueChanged = function () { 72 return (!($input.val() == "" && defaultValue == null)) && ($input.val() != defaultValue); 73 }; 74 75 this.validate = function () { 76 if (args.column.validator) { 77 var validationResults = args.column.validator($input.val()); 78 if (!validationResults.valid) { 79 return validationResults; 80 } 81 } 82 83 return { 84 valid: true, 85 msg: null 86 }; 87 }; 88 89 this.init(); 90 } 91 92 function IntegerEditor(args) { 93 var $input; 94 var defaultValue; 95 var scope = this; 96 97 this.init = function () { 98 $input = $("<INPUT type=text class='editor-text' />"); 99 100 $input.bind("keydown.nav", function (e) { 101 if (e.keyCode === $.ui.keyCode.LEFT || e.keyCode === $.ui.keyCode.RIGHT) { 102 e.stopImmediatePropagation(); 103 } 104 }); 105 106 $input.appendTo(args.container); 107 $input.focus().select(); 108 }; 109 110 this.destroy = function () { 111 $input.remove(); 112 }; 113 114 this.focus = function () { 115 $input.focus(); 116 }; 117 118 this.loadValue = function (item) { 119 defaultValue = item[args.column.field]; 120 $input.val(defaultValue); 121 $input[0].defaultValue = defaultValue; 122 $input.select(); 123 }; 124 125 this.serializeValue = function () { 126 return parseInt($input.val(), 10) || 0; 127 }; 128 129 this.applyValue = function (item, state) { 130 item[args.column.field] = state; 131 }; 132 133 this.isValueChanged = function () { 134 return (!($input.val() == "" && defaultValue == null)) && ($input.val() != defaultValue); 135 }; 136 137 this.validate = function () { 138 if (isNaN($input.val())) { 139 return { 140 valid: false, 141 msg: "Please enter a valid integer" 142 }; 143 } 144 145 return { 146 valid: true, 147 msg: null 148 }; 149 }; 150 151 this.init(); 152 } 153 154 function DateEditor(args) { 155 var $input; 156 var defaultValue; 157 var scope = this; 158 var calendarOpen = false; 159 160 this.init = function () { 161 $input = $("<INPUT type=text class='editor-text' />"); 162 $input.appendTo(args.container); 163 $input.focus().select(); 164 $input.datepicker({ 165 showOn: "button", 166 buttonImageOnly: true, 167 buttonImage: "../images/calendar.gif", 168 beforeShow: function () { 169 calendarOpen = true 170 }, 171 onClose: function () { 172 calendarOpen = false 173 } 174 }); 175 $input.width($input.width() - 18); 176 }; 177 178 this.destroy = function () { 179 $.datepicker.dpDiv.stop(true, true); 180 $input.datepicker("hide"); 181 $input.datepicker("destroy"); 182 $input.remove(); 183 }; 184 185 this.show = function () { 186 if (calendarOpen) { 187 $.datepicker.dpDiv.stop(true, true).show(); 188 } 189 }; 190 191 this.hide = function () { 192 if (calendarOpen) { 193 $.datepicker.dpDiv.stop(true, true).hide(); 194 } 195 }; 196 197 this.position = function (position) { 198 if (!calendarOpen) { 199 return; 200 } 201 $.datepicker.dpDiv 202 .css("top", position.top + 30) 203 .css("left", position.left); 204 }; 205 206 this.focus = function () { 207 $input.focus(); 208 }; 209 210 this.loadValue = function (item) { 211 defaultValue = item[args.column.field]; 212 $input.val(defaultValue); 213 $input[0].defaultValue = defaultValue; 214 $input.select(); 215 }; 216 217 this.serializeValue = function () { 218 return $input.val(); 219 }; 220 221 this.applyValue = function (item, state) { 222 item[args.column.field] = state; 223 }; 224 225 this.isValueChanged = function () { 226 return (!($input.val() == "" && defaultValue == null)) && ($input.val() != defaultValue); 227 }; 228 229 this.validate = function () { 230 return { 231 valid: true, 232 msg: null 233 }; 234 }; 235 236 this.init(); 237 } 238 239 function YesNoSelectEditor(args) { 240 var $select; 241 var defaultValue; 242 var scope = this; 243 244 this.init = function () { 245 $select = $("<SELECT tabIndex='0' class='editor-yesno'><OPTION value='yes'>Yes</OPTION><OPTION value='no'>No</OPTION></SELECT>"); 246 $select.appendTo(args.container); 247 $select.focus(); 248 }; 249 250 this.destroy = function () { 251 $select.remove(); 252 }; 253 254 this.focus = function () { 255 $select.focus(); 256 }; 257 258 this.loadValue = function (item) { 259 $select.val((defaultValue = item[args.column.field]) ? "yes" : "no"); 260 $select.select(); 261 }; 262 263 this.serializeValue = function () { 264 return ($select.val() == "yes"); 265 }; 266 267 this.applyValue = function (item, state) { 268 item[args.column.field] = state; 269 }; 270 271 this.isValueChanged = function () { 272 return ($select.val() != defaultValue); 273 }; 274 275 this.validate = function () { 276 return { 277 valid: true, 278 msg: null 279 }; 280 }; 281 282 this.init(); 283 } 284 285 function CheckboxEditor(args) { 286 var $select; 287 var defaultValue; 288 var scope = this; 289 290 this.init = function () { 291 $select = $("<INPUT type=checkbox value='true' class='editor-checkbox' hideFocus>"); 292 $select.appendTo(args.container); 293 $select.focus(); 294 }; 295 296 this.destroy = function () { 297 $select.remove(); 298 }; 299 300 this.focus = function () { 301 $select.focus(); 302 }; 303 304 this.loadValue = function (item) { 305 defaultValue = !!item[args.column.field]; 306 if (defaultValue) { 307 $select.prop('checked', true); 308 } else { 309 $select.prop('checked', false); 310 } 311 }; 312 313 this.serializeValue = function () { 314 return $select.prop('checked'); 315 }; 316 317 this.applyValue = function (item, state) { 318 item[args.column.field] = state; 319 }; 320 321 this.isValueChanged = function () { 322 return (this.serializeValue() !== defaultValue); 323 }; 324 325 this.validate = function () { 326 return { 327 valid: true, 328 msg: null 329 }; 330 }; 331 332 this.init(); 333 } 334 335 function PercentCompleteEditor(args) { 336 var $input, $picker; 337 var defaultValue; 338 var scope = this; 339 340 this.init = function () { 341 $input = $("<INPUT type=text class='editor-percentcomplete' />"); 342 $input.width($(args.container).innerWidth() - 25); 343 $input.appendTo(args.container); 344 345 $picker = $("<div class='editor-percentcomplete-picker' />").appendTo(args.container); 346 $picker.append("<div class='editor-percentcomplete-helper'><div class='editor-percentcomplete-wrapper'><div class='editor-percentcomplete-slider' /><div class='editor-percentcomplete-buttons' /></div></div>"); 347 348 $picker.find(".editor-percentcomplete-buttons").append("<button val=0>Not started</button><br/><button val=50>In Progress</button><br/><button val=100>Complete</button>"); 349 350 $input.focus().select(); 351 352 $picker.find(".editor-percentcomplete-slider").slider({ 353 orientation: "vertical", 354 range: "min", 355 value: defaultValue, 356 slide: function (event, ui) { 357 $input.val(ui.value) 358 } 359 }); 360 361 $picker.find(".editor-percentcomplete-buttons button").bind("click", function (e) { 362 $input.val($(this).attr("val")); 363 $picker.find(".editor-percentcomplete-slider").slider("value", $(this).attr("val")); 364 }) 365 }; 366 367 this.destroy = function () { 368 $input.remove(); 369 $picker.remove(); 370 }; 371 372 this.focus = function () { 373 $input.focus(); 374 }; 375 376 this.loadValue = function (item) { 377 $input.val(defaultValue = item[args.column.field]); 378 $input.select(); 379 }; 380 381 this.serializeValue = function () { 382 return parseInt($input.val(), 10) || 0; 383 }; 384 385 this.applyValue = function (item, state) { 386 item[args.column.field] = state; 387 }; 388 389 this.isValueChanged = function () { 390 return (!($input.val() == "" && defaultValue == null)) && ((parseInt($input.val(), 10) || 0) != defaultValue); 391 }; 392 393 this.validate = function () { 394 if (isNaN(parseInt($input.val(), 10))) { 395 return { 396 valid: false, 397 msg: "Please enter a valid positive number" 398 }; 399 } 400 401 return { 402 valid: true, 403 msg: null 404 }; 405 }; 406 407 this.init(); 408 } 409 410 /* 411 * An example of a "detached" editor. 412 * The UI is added onto document BODY and .position(), .show() and .hide() are implemented. 413 * KeyDown events are also handled to provide handling for Tab, Shift-Tab, Esc and Ctrl-Enter. 414 */ 415 function LongTextEditor(args) { 416 var $input, $wrapper; 417 var defaultValue; 418 var scope = this; 419 420 this.init = function () { 421 var $container = $("body"); 422 423 $wrapper = $("<DIV style='z-index:10000;position:absolute;background:white;padding:5px;border:3px solid gray; -moz-border-radius:10px; border-radius:10px;'/>") 424 .appendTo($container); 425 426 $input = $("<TEXTAREA hidefocus rows=5 style='backround:white;width:250px;height:80px;border:0;outline:0'>") 427 .appendTo($wrapper); 428 429 $("<DIV style='text-align:right'><BUTTON>Save</BUTTON><BUTTON>Cancel</BUTTON></DIV>") 430 .appendTo($wrapper); 431 432 $wrapper.find("button:first").bind("click", this.save); 433 $wrapper.find("button:last").bind("click", this.cancel); 434 $input.bind("keydown", this.handleKeyDown); 435 436 scope.position(args.position); 437 $input.focus().select(); 438 }; 439 440 this.handleKeyDown = function (e) { 441 if (e.which == $.ui.keyCode.ENTER && e.ctrlKey) { 442 scope.save(); 443 } else if (e.which == $.ui.keyCode.ESCAPE) { 444 e.preventDefault(); 445 scope.cancel(); 446 } else if (e.which == $.ui.keyCode.TAB && e.shiftKey) { 447 e.preventDefault(); 448 args.grid.navigatePrev(); 449 } else if (e.which == $.ui.keyCode.TAB) { 450 e.preventDefault(); 451 args.grid.navigateNext(); 452 } 453 }; 454 455 this.save = function () { 456 args.commitChanges(); 457 }; 458 459 this.cancel = function () { 460 $input.val(defaultValue); 461 args.cancelChanges(); 462 }; 463 464 this.hide = function () { 465 $wrapper.hide(); 466 }; 467 468 this.show = function () { 469 $wrapper.show(); 470 }; 471 472 this.position = function (position) { 473 $wrapper 474 .css("top", position.top - 5) 475 .css("left", position.left - 5) 476 }; 477 478 this.destroy = function () { 479 $wrapper.remove(); 480 }; 481 482 this.focus = function () { 483 $input.focus(); 484 }; 485 486 this.loadValue = function (item) { 487 $input.val(defaultValue = item[args.column.field]); 488 $input.select(); 489 }; 490 491 this.serializeValue = function () { 492 return $input.val(); 493 }; 494 495 this.applyValue = function (item, state) { 496 item[args.column.field] = state; 497 }; 498 499 this.isValueChanged = function () { 500 return (!($input.val() == "" && defaultValue == null)) && ($input.val() != defaultValue); 501 }; 502 503 this.validate = function () { 504 return { 505 valid: true, 506 msg: null 507 }; 508 }; 509 510 this.init(); 511 } 512})(jQuery);
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.