\n\t\t`\n\t};\n\n} )\n( jQuery );//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiNTU4My5qcyIsIm1hcHBpbmdzIjoiO0FBQUE7O0FBRUE7QUFDQSx5QkFBeUI7QUFDekI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEdBQUc7O0FBRUg7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBLE1BQU07QUFDTixzQkFBc0IsVUFBVTtBQUNoQztBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLE1BQU07O0FBRU47QUFDQTtBQUNBO0FBQ0E7QUFDQSxNQUFNO0FBQ047QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsTUFBTTtBQUNOO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLE1BQU07QUFDTjtBQUNBOztBQUVBOztBQUVBOztBQUVBLGdDQUFnQzs7QUFFaEM7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsTUFBTTs7QUFFTixJQUFJOztBQUVKLElBQUk7O0FBRUo7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxFQUFFO0FBQ0YsRUFBRSxNQUFNIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vLy4vaW50ZXJmYWNlL2h0bWw1L2dsb2JhbC93aWRnZXRzL3BhZ2luZy9QYWdpbmcyLmpzPzM3MTciXSwic291cmNlc0NvbnRlbnQiOlsiKCBmdW5jdGlvbiggJCApIHtcblxuXHQkLmZuLlBhZ2luZzIgPSBmdW5jdGlvbiggb3B0aW9ucyApIHtcblx0XHR2YXIgb3B0cyA9ICQuZXh0ZW5kKCB7fSwgJC5mbi5QYWdpbmcyLmRlZmF1bHRzLCBvcHRpb25zICk7XG5cdFx0dmFyICR0aGlzID0gdGhpcztcblx0XHR2YXIgcGFnZXJfZGF0YTtcblx0XHR2YXIgc3RhcnQ7XG5cdFx0dmFyIGxhc3Q7XG5cdFx0dmFyIG5leHQ7XG5cdFx0dmFyIGVuZDtcblx0XHR2YXIgcGFnaW5nX3NlbGVjdG9yO1xuXHRcdHZhciBsZWZ0X2J1dHRvbnNfZGl2O1xuXHRcdHZhciByaWdodF9idXR0b25zX2RpdjtcblxuXHRcdHZhciBsZWZ0X2J1dHRvbnNfZW5hYmxlO1xuXHRcdHZhciByaWdodF9idXR0b25zX2VuYWJsZTtcblxuXHRcdHRoaXMuZ2V0UGFnZXJEYXRhID0gZnVuY3Rpb24oKSB7XG5cdFx0XHRyZXR1cm4gcGFnZXJfZGF0YTtcblx0XHR9LFxuXG5cdFx0XHR0aGlzLnNldFBhZ2VyRGF0YSA9IGZ1bmN0aW9uKCB2YWx1ZSApIHtcblxuXHRcdFx0XHRwYWdlcl9kYXRhID0gdmFsdWU7XG5cblx0XHRcdFx0aWYgKCAhcGFnZXJfZGF0YSApIHtcblx0XHRcdFx0XHQkKCB0aGlzLmNzcyggJ2Rpc3BsYXknLCAnbm9uZScgKSApO1xuXHRcdFx0XHRcdHJldHVybjtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHQkKCB0aGlzLmNzcyggJ2Rpc3BsYXknLCAnYmxvY2snICkgKTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdCQoIHBhZ2luZ19zZWxlY3RvciApLmVtcHR5KCk7XG5cblx0XHRcdFx0dmFyIGxlbiA9IHBhZ2VyX2RhdGEubGFzdF9wYWdlX251bWJlcjtcblxuXHRcdFx0XHRpZiAoIGxlbiA9PT0gLTEgKSB7XG5cdFx0XHRcdFx0JCggcGFnaW5nX3NlbGVjdG9yICkuYXBwZW5kKCAnPG9wdGlvbiB2YWx1ZT1cIicgKyAxICsgJ1wiPicgKyAxICsgJzwvb3B0aW9uPicgKTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRmb3IgKCB2YXIgaSA9IDE7IGkgPD0gbGVuOyBpKysgKSB7XG5cdFx0XHRcdFx0XHQkKCBwYWdpbmdfc2VsZWN0b3IgKS5hcHBlbmQoICc8b3B0aW9uIHZhbHVlPVwiJyArIGkgKyAnXCI+JyArIGkgKyAnPC9vcHRpb24+JyApO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXG5cdFx0XHRcdCQoICQoIHBhZ2luZ19zZWxlY3RvciApLmZpbmQoICdvcHRpb24nICkgKS5maWx0ZXIoIGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdHZhciBjdXJyZW50X3ZhbHVlID0gcGFyc2VJbnQoICQoIHRoaXMgKS5hdHRyKCAndmFsdWUnICkgKTtcblxuXHRcdFx0XHRcdHJldHVybiBjdXJyZW50X3ZhbHVlID09PSBwYWdlcl9kYXRhLmN1cnJlbnRfcGFnZTtcblx0XHRcdFx0fSApLnByb3AoICdzZWxlY3RlZCcsIHRydWUgKS5wcm9wKCAnc2VsZWN0ZWQnLCB0cnVlICk7XG5cblx0XHRcdFx0aWYgKCBwYWdlcl9kYXRhLmlzX2xhc3RfcGFnZSA9PT0gdHJ1ZSApIHtcblx0XHRcdFx0XHRyaWdodF9idXR0b25zX2Rpdi5hZGRDbGFzcyggJ2Rpc2FibGVkJyApO1xuXHRcdFx0XHRcdHJpZ2h0X2J1dHRvbnNfZGl2LmFkZENsYXNzKCAnZGlzYWJsZWQtaW1hZ2UnICk7XG5cdFx0XHRcdFx0cmlnaHRfYnV0dG9uc19lbmFibGUgPSBmYWxzZTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRyaWdodF9idXR0b25zX2Rpdi5yZW1vdmVDbGFzcyggJ2Rpc2FibGVkJyApO1xuXHRcdFx0XHRcdHJpZ2h0X2J1dHRvbnNfZGl2LnJlbW92ZUNsYXNzKCAnZGlzYWJsZWQtaW1hZ2UnICk7XG5cdFx0XHRcdFx0cmlnaHRfYnV0dG9uc19lbmFibGUgPSB0cnVlO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0aWYgKCBwYWdlcl9kYXRhLmlzX2ZpcnN0X3BhZ2UgKSB7XG5cdFx0XHRcdFx0bGVmdF9idXR0b25zX2Rpdi5hZGRDbGFzcyggJ2Rpc2FibGVkJyApO1xuXHRcdFx0XHRcdGxlZnRfYnV0dG9uc19kaXYuYWRkQ2xhc3MoICdkaXNhYmxlZC1pbWFnZScgKTtcblx0XHRcdFx0XHRsZWZ0X2J1dHRvbnNfZW5hYmxlID0gZmFsc2U7XG5cblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRsZWZ0X2J1dHRvbnNfZGl2LnJlbW92ZUNsYXNzKCAnZGlzYWJsZWQnICk7XG5cdFx0XHRcdFx0bGVmdF9idXR0b25zX2Rpdi5yZW1vdmVDbGFzcyggJ2Rpc2FibGVkLWltYWdlJyApO1xuXHRcdFx0XHRcdGxlZnRfYnV0dG9uc19lbmFibGUgPSB0cnVlO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0aWYgKCBsZW4gPT09IC0xIHx8ICggcGFnZXJfZGF0YS5pc19maXJzdF9wYWdlICYmIHBhZ2VyX2RhdGEuaXNfbGFzdF9wYWdlICkgKSB7XG5cblx0XHRcdFx0XHRsZWZ0X2J1dHRvbnNfZGl2LmFkZENsYXNzKCAnZGlzYWJsZWQnICk7XG5cdFx0XHRcdFx0bGVmdF9idXR0b25zX2Rpdi5hZGRDbGFzcyggJ2Rpc2FibGVkLWltYWdlJyApO1xuXHRcdFx0XHRcdGxlZnRfYnV0dG9uc19lbmFibGUgPSBmYWxzZTtcblx0XHRcdFx0XHRyaWdodF9idXR0b25zX2Rpdi5hZGRDbGFzcyggJ2Rpc2FibGVkJyApO1xuXHRcdFx0XHRcdHJpZ2h0X2J1dHRvbnNfZGl2LmFkZENsYXNzKCAnZGlzYWJsZWQtaW1hZ2UnICk7XG5cdFx0XHRcdFx0cmlnaHRfYnV0dG9uc19lbmFibGUgPSBmYWxzZTtcblxuXHRcdFx0XHRcdCR0aGlzLmhpZGUoKTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHQkdGhpcy5zaG93KCk7XG5cdFx0XHRcdH1cblxuXHRcdFx0fTtcblxuXHRcdHRoaXMuZWFjaCggZnVuY3Rpb24oKSB7XG5cblx0XHRcdHZhciBvID0gJC5tZXRhID8gJC5leHRlbmQoIHt9LCBvcHRzLCAkKCB0aGlzICkuZGF0YSgpICkgOiBvcHRzO1xuXG5cdFx0XHR2YXIgcGFnZXNfbGFiZWwgPSAkKCB0aGlzICkuZmluZCggJy5wYWdlLWxhYmVsLXNwYW4nICk7XG5cblx0XHRcdHBhZ2VzX2xhYmVsLnRleHQoICQuaTE4bi5fKCAnUGFnZScgKSApO1xuXG5cdFx0XHRsZWZ0X2J1dHRvbnNfZGl2ID0gJCggdGhpcyApLmZpbmQoICcubGVmdC1idXR0b25zLWRpdicgKTtcblx0XHRcdHJpZ2h0X2J1dHRvbnNfZGl2ID0gJCggdGhpcyApLmZpbmQoICcucmlnaHQtYnV0dG9ucy1kaXYnICk7XG5cblx0XHRcdHN0YXJ0ID0gJCggdGhpcyApLmZpbmQoICcuc3RhcnQnICk7XG5cdFx0XHRsYXN0ID0gJCggdGhpcyApLmZpbmQoICcubGFzdCcgKTtcblx0XHRcdG5leHQgPSAkKCB0aGlzICkuZmluZCggJy5uZXh0JyApO1xuXHRcdFx0ZW5kID0gJCggdGhpcyApLmZpbmQoICcuZW5kJyApO1xuXHRcdFx0cGFnaW5nX3NlbGVjdG9yID0gJCggdGhpcyApLmZpbmQoICcucGFnaW5nLXNlbGVjdG9yJyApO1xuXG5cdFx0XHRzdGFydC50ZXh0KCAkLmkxOG4uXyggJ1N0YXJ0JyApICk7XG5cdFx0XHRsYXN0LnRleHQoICQuaTE4bi5fKCAnUHJldmlvdXMnICkgKTtcblxuXHRcdFx0bmV4dC50ZXh0KCAkLmkxOG4uXyggJ05leHQnICkgKTtcblx0XHRcdGVuZC50ZXh0KCAkLmkxOG4uXyggJ0VuZCcgKSApO1xuXG5cdFx0XHQkKCB0aGlzICkuaGlkZSgpO1xuXG5cdFx0XHRzdGFydC5jbGljayggZnVuY3Rpb24oKSB7XG5cdFx0XHRcdGlmICggbGVmdF9idXR0b25zX2VuYWJsZSApIHtcblx0XHRcdFx0XHQkdGhpcy50cmlnZ2VyKCAncGFnaW5nJywgWydzdGFydCddICk7XG5cdFx0XHRcdH1cblx0XHRcdH0gKTtcblxuXHRcdFx0bGFzdC5jbGljayggZnVuY3Rpb24oKSB7XG5cdFx0XHRcdGlmICggbGVmdF9idXR0b25zX2VuYWJsZSApIHtcblx0XHRcdFx0XHQkdGhpcy50cmlnZ2VyKCAncGFnaW5nJywgWydsYXN0J10gKTtcblx0XHRcdFx0fVxuXHRcdFx0fSApO1xuXG5cdFx0XHRuZXh0LmNsaWNrKCBmdW5jdGlvbigpIHtcblx0XHRcdFx0aWYgKCByaWdodF9idXR0b25zX2VuYWJsZSApIHtcblx0XHRcdFx0XHQkdGhpcy50cmlnZ2VyKCAncGFnaW5nJywgWyduZXh0J10gKTtcblx0XHRcdFx0fVxuXHRcdFx0fSApO1xuXG5cdFx0XHRlbmQuY2xpY2soIGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRpZiAoIHJpZ2h0X2J1dHRvbnNfZW5hYmxlICkge1xuXHRcdFx0XHRcdCR0aGlzLnRyaWdnZXIoICdwYWdpbmcnLCBbJ2VuZCddICk7XG5cdFx0XHRcdH1cblx0XHRcdH0gKTtcblxuXHRcdFx0JCggcGFnaW5nX3NlbGVjdG9yICkuY2hhbmdlKCAkLnByb3h5KCBmdW5jdGlvbigpIHtcblxuXHRcdFx0XHQkKCBwYWdpbmdfc2VsZWN0b3IgKS5maW5kKCAnb3B0aW9uOnNlbGVjdGVkJyApLmVhY2goIGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdHZhciBwYWdlX251bWJlciA9ICQoIHRoaXMgKS5hdHRyKCAndmFsdWUnICk7XG5cdFx0XHRcdFx0JHRoaXMudHJpZ2dlciggJ3BhZ2luZycsIFsnZ29fdG8nLCBwYWdlX251bWJlcl0gKTtcblx0XHRcdFx0fSApO1xuXG5cdFx0XHR9LCB0aGlzICkgKTtcblxuXHRcdH0gKTtcblxuXHRcdHJldHVybiB0aGlzO1xuXG5cdH07XG5cblx0JC5mbi5QYWdpbmcyLmRlZmF1bHRzID0ge307XG5cdCQuZm4uUGFnaW5nMi5odG1sID0ge1xuXHRcdHBhZ2luZzogYDxkaXYgY2xhc3M9XCJwYWdpbmctZGl2XCI+PHNwYW4gY2xhc3M9XCJwYWdpbmctc3BhblwiPkNMSUNLIFRPIFNIT1cgTU9SRTwvc3Bhbj48L2Rpdj5gLFxuXHRcdHBhZ2luZzI6IGBcblx0XHRcdDxkaXYgY2xhc3M9XCJwYWdpbmctMi1kaXZcIj5cblx0XHRcdFx0PGRpdiBjbGFzcz1cImxlZnQtYnV0dG9ucy1kaXZcIj5cblx0XHRcdFx0XHQ8c3BhbiBjbGFzcz1cImRvdWJsZS1sZWZ0LWFycm93IHBpIHBpLWFuZ2xlLWRvdWJsZS1sZWZ0XCIgdGl0bGU9XCJTdGFydFwiPjwvc3Bhbj5cblx0XHRcdFx0XHQ8c3BhbiBjbGFzcz1cInBhZ2luZy0yLXNwYW4gc3RhcnRcIj48L3NwYW4+XG5cdFx0XHRcdFx0PHNwYW4gY2xhc3M9XCJsZWZ0LWFycm93IHBpIHBpLWFuZ2xlLWxlZnRcIj48L3NwYW4+XG5cdFx0XHRcdFx0PHNwYW4gY2xhc3M9XCJwYWdpbmctMi1zcGFuIGxhc3RcIj48L3NwYW4+XG5cdFx0XHRcdDwvZGl2PlxuXHRcdFx0XHQ8c3BhbiBjbGFzcz1cInBhZ2UtbGFiZWwtc3BhblwiPjwvc3Bhbj5cblx0XHRcdFx0PHNlbGVjdCBjbGFzcz1cInQtc2VsZWN0IHBhZ2luZy1zZWxlY3RvclwiPlxuXHRcdFx0XHQ8L3NlbGVjdD5cblx0XHRcdFx0PGRpdiBjbGFzcz1cInJpZ2h0LWJ1dHRvbnMtZGl2XCI+XG5cdFx0XHRcdFx0PHNwYW4gY2xhc3M9XCJwYWdpbmctMi1zcGFuIG5leHRcIj48L3NwYW4+XG5cdFx0XHRcdFx0PHNwYW4gY2xhc3M9XCJyaWdodC1hcnJvdyBwaSBwaS1hbmdsZS1yaWdodFwiPjwvc3Bhbj5cblx0XHRcdFx0XHQ8c3BhbiBjbGFzcz1cInBhZ2luZy0yLXNwYW4gZW5kXCI+PC9zcGFuPlxuXHRcdFx0XHRcdDxzcGFuIGNsYXNzPVwiZG91YmxlLXJpZ2h0LWFycm93IHBpIHBpLWFuZ2xlLWRvdWJsZS1yaWdodFwiPjwvc3Bhbj5cblx0XHRcdFx0PC9kaXY+XG5cdFx0XHQ8L2Rpdj5cblx0XHRgXG5cdH07XG5cbn0gKVxuKCBqUXVlcnkgKTsiXSwibmFtZXMiOltdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///5583\n")},121:(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{"use strict";eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"BaseViewController\": () => (/* binding */ BaseViewController)\n/* harmony export */ });\n/* harmony import */ var _views_TTBackboneView__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(6739);\n/* harmony import */ var _services_TimeTrexClientAPI__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(7526);\n/* harmony import */ var _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(2548);\n/* harmony import */ var _global_widgets_paging_Paging2_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(5583);\n/* harmony import */ var _global_widgets_paging_Paging2_js__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_global_widgets_paging_Paging2_js__WEBPACK_IMPORTED_MODULE_3__);\n/* harmony import */ var _global_Global__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(9490);\n/* harmony import */ var _services_HtmlTemplates__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(4578);\n/* provided dependency */ var _ = __webpack_require__(9050);\n/* provided dependency */ var $ = __webpack_require__(9755);\n/* provided dependency */ var jQuery = __webpack_require__(9755);\n\n\n // TODO: duplicated in merged js files.\n\n\n\n\nwindow.FormItemType = _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.FormItemType; // TODO: Eventually refactor to import only where these are used.\nwindow.WidgetNamesDic = _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.WidgetNamesDic; // TODO: Eventually refactor to import only where these are used.\n\n/* jshint ignore:start */\n\n//Don't check this file for now. Too many issues.\nclass BaseViewController extends _views_TTBackboneView__WEBPACK_IMPORTED_MODULE_0__.TTBackboneView {\n\tconstructor( options = {} ) {\n\t\t_.defaults( options, {\n\t\t\treal_this: null, //For super call in second level sub class\n\n\t\t\tsub_view_mode: false,\n\n\t\t\tedit_only_mode: false,\n\n\t\t\tcan_cache_controller: true, //if allow to cache current controller\n\n\t\t\tpermission_id: '',\n\t\t\tapi: null,\n\t\t\tuser_generic_data_api: null,\n\t\t\tall_columns: [],\n\t\t\tdisplay_columns: [],\n\t\t\tdefault_display_columns: [],\n\t\t\tscript_name: '',\n\t\t\tfilter_data: null, //current Filter data get from Search panel\n\t\t\ttemp_basic_filter_data: null,\n\t\t\ttemp_adv_filter_data: null,\n\t\t\tsortData: null, //Current Sort data get from search panel\n\t\t\tselect_layout: null,\n\t\t\tlayout_changed: false,\n\t\t\tsearch_panel: null,\n\t\t\tgrid: null,\n\t\t\tcontext_menu_name: '',\n\t\t\tnavigation_label: '',\n\t\t\tcontext_menu_array: [],\n\t\t\tt_grid_header_array: [],\n\n\t\t\t//Column Selector in search panel\n\t\t\tcolumn_selector: null,\n\n\t\t\tsort_by_selector: null,\n\n\t\t\tsave_search_as_input: null,\n\n\t\t\tprevious_saved_layout_selector: null,\n\n\t\t\tprevious_saved_layout_div: null,\n\n\t\t\tneed_select_layout_name: '', //Set this when save new layout to choose the new layout\n\n\t\t\tsearch_fields: null,\n\n\t\t\tbasic_search_field_ui_dic: {}, //Save AwesomeBox when they created\n\n\t\t\tadv_search_field_ui_dic: {}, //Save AwesomeBox when they created\n\n\t\t\tedit_view_ui_dic: {},\n\n\t\t\tedit_view_ui_validation_field_dic: {},\n\n\t\t\tedit_view_form_item_dic: {}, //Whole FormItem\n\n\t\t\tedit_view_error_ui_dic: {},\n\n\t\t\tedit_view: null,\n\n\t\t\tedit_view_tab: null,\n\n\t\t\tcurrent_edit_record: null, //Current edit record\n\n\t\t\trefresh_id: null, //Set this to refresh one record in grid view.\n\n\t\t\tnavigation: null, // Navigation widget in edit view\n\n\t\t\tis_mass_editing: false, //Set when mass edit\n\n\t\t\tis_viewing: false,\n\t\t\tis_viewing_detail: false,\n\t\t\tis_edit: false,\n\t\t\tis_add: false,\n\n\t\t\tunique_columns: [], //Set when Mass edit, mark which fields need to be disable\n\n\t\t\tlinked_fields: [],\n\n\t\t\tmass_edit_record_ids: [], // Mass edit records\n\n\t\t\tedit_view_tabs: [],\n\n\t\t\trefresh_sub_view: false,\n\n\t\t\tparent_key: null, //default filter when search\n\n\t\t\tparent_value: null, //default filter when search\n\n\t\t\tparent_edit_record: null,\n\n\t\t\ttotal_display_span: null,\n\n\t\t\tpaging_widget: null,\n\n\t\t\tpaging_widget_2: null, //Put in the bottom of data grid\n\n\t\t\tpager_data: null,\n\n\t\t\tviewId: null,\n\n\t\t\tinit_options_complete: false,\n\n\t\t\tno_result_box: null, // No Result Found Black cover when no result in grid\n\n\t\t\ttable_name_key: null,\n\n\t\t\tsub_log_view_controller: null,\n\n\t\t\tparent_view_controller: null, //Add this to call parent_view_controll cancel action when cancel from sub view\n\n\t\t\tui_id: '',\n\n\t\t\tis_changed: false, // Track if modified any fields in edit view\n\n\t\t\tconfirm_on_exit: false, //confirm before leaving the edit view even if no changes have been made\n\n\t\t\tedit_view_tpl: '', //Edit view html name\n\n\t\t\tsubMenuNavMap: null,\n\n\t\t\ttrySetGridSizeWhenTabShow: false, // Set sub view grid size when tab show instead when tab select\n\n\t\t\tcopied_record_id: '', // When copy as new, save copied reord's id\n\n\t\t\tcustom_field_api: null,\n\n\t\t\tlast_select_ids: null,\n\n\t\t\tsaving_layout_in_layout_tab: false, //Mark if save layout from Saved and layout tab. if so, don't switch tabs when set values to search panel\n\n\t\t\tneed_switch_to_context_menu: false,\n\n\t\t\tshow_search_tab: true,\n\n\t\t\tgrid_total_width: null,\n\n\t\t\tshow_warning_when_validation: false,\n\n\t\t\tpulse_time_dic: false,\n\n\t\t\tedit_view_close_icon: null,\n\n\t\t\tenable_validation: true,\n\n\t\t\t// _required_files: null,\n\n\t\t\ttab_model: null, //Tab definitions and a map to their callbacks.\n\n\t\t\tgrid_parent: null,\n\n\t\t\tcustom_fields: []\n\t\t} );\n\t\tsuper( options );\n\t}\n\n\t// getRequiredFiles() {\n\t// \t//override in child class\n\t// \treturn [];\n\t// }\n\n\t/**\n\t * When changing this function, you need to look for all occurences of this function because it was needed in several bases\n\t * BaseViewController, HomeViewController, BaseWizardController, QuickPunchBaseViewControler\n\t *\n\t * @returns {Array}\n\t */\n\t// filterRequiredFiles() {\n\t// \tDebug.Warn( 'Deprecated requirejs function. Replace usage immediately with webpack loaders.', 'BaseViewController.js', 'BaseViewController', 'filterRequiredFiles', 2 );\n\t//\n\t// \tvar retval = [];\n\t// \tvar required_files;\n\t//\n\t// \tif ( typeof this._required_files == 'object' ) {\n\t// \t\trequired_files = this._required_files;\n\t// \t} else {\n\t// \t\trequired_files = this.getRequiredFiles();\n\t// \t}\n\t//\n\t// \tif ( required_files && required_files[0] ) {\n\t// \t\tretval = required_files;\n\t// \t} else {\n\t// \t\tfor ( var edition_id in required_files ) {\n\t// \t\t\tif ( Global.getProductEdition() >= edition_id ) {\n\t// \t\t\t\tretval = retval.concat( required_files[edition_id] );\n\t// \t\t\t}\n\t// \t\t}\n\t// \t}\n\t//\n\t// \tDebug.Arr( retval, 'RETVAL', 'BaseViewController.js', 'BaseViewController', 'filterRequiredFiles', 10 );\n\t// \treturn retval;\n\t// }\n\n\tpreInit() {\n\t\t//override in child class\n\t}\n\n\tinitialize( options ) {\n\t\tDebug.Text( 'INITIALIZE', 'BaseViewController.js', 'BaseViewController', 'initialize', 10 );\n\t\t_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.setUINotready */ .x.setUINotready();\n\n\t\tsuper.initialize( options );\n\n\t\tTTPromise.add( 'init', 'init' );\n\t\tTTPromise.add( 'BaseViewController', 'initialize' );\n\t\t//trigger readystate update\n\t\tTTPromise.wait();\n\n\t\tvar $this = this;\n\t\tthis.layout_changed = false;\n\t\t// var required_files = this.filterRequiredFiles();\n\n\t\t// __non_webpack_require__( required_files, function() { // This is to prevent conflict with the Webpack Node require calls.\n\t\t// Debug.Warn( 'Deprecated requirejs function. Replace usage immediately with webpack loaders.', 'BaseViewController.js', 'BaseViewController', 'initialize', 2 );\n\n\t\tsetTimeout(function() { // #2662 This setTimeout is essential in keeping the code flow the same as when this code block has a requirejs callback. Otherwise it causes issues in many areas like Audit logs going blank, as the subview postInit function is called before its set in afterLoadView().\n\n\t\t\t$this.preInit( options );\n\n\t\t\t$this.options = options;\n\t\t\tif ( $this.options && _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( $this.options.can_cache_controller ) ) {\n\t\t\t\t$this.can_cache_controller = $this.options.can_cache_controller;\n\t\t\t}\n\n\t\t\tif ( $this.options && _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( $this.options.edit_only_mode ) ) {\n\t\t\t\t$this.edit_only_mode = $this.options.edit_only_mode;\n\t\t\t}\n\n\t\t\tif ( $this.options && _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( $this.options.sub_view_mode ) ) {\n\t\t\t\t$this.sub_view_mode = $this.options.sub_view_mode;\n\t\t\t} else {\n\t\t\t\t$this.sub_view_mode = false;\n\t\t\t}\n\n\t\t\tif ( $this.options && _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( $this.options.parent_view ) ) {\n\t\t\t\t$this.parent_view = $this.options.parent_view;\n\t\t\t}\n\n\t\t\tif ( $this.options && _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( $this.options.parent_view_controller ) ) {\n\t\t\t\t$this.parent_view_controller = $this.options.parent_view_controller;\n\t\t\t}\n\n\t\t\tif ( !$this.edit_only_mode ) {\n\n\t\t\t\tif ( $this.can_cache_controller ) {\n\t\t\t\t\tif ( !$this.sub_view_mode ) {\n\t\t\t\t\t\tLocalCacheData.current_open_primary_controller = $this;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tLocalCacheData.current_open_sub_controller = $this;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t//Reset main container id so it won't duplicate when in sub view. Like Audit view.\n\t\t\t\tvar root_container = $( $this.el );\n\t\t\t\tvar new_id = root_container.attr( 'id' ) + '_' + _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.getRandomNum */ .x.getRandomNum();\n\t\t\t\troot_container.attr( 'id', new_id );\n\t\t\t\t$this.el = '#' + new_id;\n\t\t\t\t$this.ui_id = new_id;\n\n\t\t\t\t$this.user_generic_data_api = _services_TimeTrexClientAPI__WEBPACK_IMPORTED_MODULE_1__/* .TTAPI.APIUserGenericData */ .y.APIUserGenericData;\n\n\t\t\t\t$this.total_display_span = $( $( $this.el ).find( '.total-number-span' )[0] );\n\n\t\t\t\t//$this shouldn't be displayed as it caused \"flashing\" of text and it wasn't translated either.\n\t\t\t\t//if ( $this.total_display_span ) {\n\t\t\t\t//$this.total_display_span.text( 'Displaying 0 - 0 of 0 total. Selected: 0' );\n\t\t\t\t//}\n\n\t\t\t\t//JS load Optimize\n\t\t\t\tif ( LocalCacheData.loadViewRequiredJSReady ) {\n\t\t\t\t\t//Init paging widget, next step, add widget to UI and bind events in setSelectLayout\n\t\t\t\t\tif ( LocalCacheData.paging_type === 0 ) {\n\t\t\t\t\t\t$this.paging_widget = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.loadWidgetByName */ .x.loadWidgetByName( _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.WidgetNamesDic.PAGING );\n\t\t\t\t\t} else {\n\t\t\t\t\t\t$this.paging_widget = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.loadWidgetByName */ .x.loadWidgetByName( _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.WidgetNamesDic.PAGING_2 );\n\t\t\t\t\t\t$this.paging_widget_2 = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.loadWidgetByName */ .x.loadWidgetByName( _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.WidgetNamesDic.PAGING_2 );\n\t\t\t\t\t\t$this.paging_widget = $this.paging_widget.Paging2();\n\t\t\t\t\t\t$this.paging_widget_2 = $this.paging_widget_2.Paging2();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t$this.ui_id = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.getRandomNum */ .x.getRandomNum();\n\t\t\t}\n\n\t\t\t//init all dic or array, or it will extends last viewcontroller's value. Why?\n\t\t\t$this.sub_log_view_controller = null;\n\t\t\t$this.edit_view_ui_dic = {};\n\t\t\t$this.edit_view_ui_validation_field_dic = {};\n\t\t\t$this.basic_search_field_ui_dic = {};\n\t\t\t$this.adv_search_field_ui_dic = {};\n\t\t\t$this.edit_view_tabs = [];\n\n\t\t\t$this.custom_field_api = _services_TimeTrexClientAPI__WEBPACK_IMPORTED_MODULE_1__/* .TTAPI.APICustomField */ .y.APICustomField;\n\n\t\t\t$this.initKeyboardEvent(); // register keyboard events if it's a main view\n\n\t\t\t$this.init( options );\n\t\t\t$this.postInit( options );\n\n\t\t\tTTPromise.resolve( 'BaseViewController', 'initialize' );\n\t\t\tTTPromise.resolve( 'init', 'init' );\n\t\t}, 1);\n\t}\n\n\tinit() {\n\t\t//override in child class\n\t}\n\n\tpostInit() {\n\t\t//override in child class\n\t}\n\n\tinitKeyboardEvent() {\n\n\t\tvar $this = this;\n\t\tif ( this.sub_view_mode || this.edit_only_mode ) {\n\t\t\treturn;\n\t\t}\n\n//\t\t$( this.el ).unbind( 'keydown' ).bind( 'keydown', function( e ) {\n//\n//\t\t\tif ( e.keyCode === 13 && !$this.search_panel.isCollapsed() ) {\n//\t\t\t\t$this.onSearch();\n//\t\t\t}\n//\n//\t\t} );\n\n\t\t$( this.el ).unbind( 'keyup' ).bind( 'keydown', function( e ) {\n\n\t\t\tif ( e.keyCode === 13 && $this.search_panel && !$this.search_panel.isCollapsed() ) {\n\n\t\t\t\t$this.onSearch();\n\t\t\t\t$( ':focus' ).blur(); //Make focus out of current view. pevent search too much when user keep click enter\n\t\t\t}\n\t\t} );\n\t}\n\n\t//Speical permission check for views, need override\n\tinitPermission() {\n\t}\n\n\t//Set this when setDefault menu\n\tsetTotalDisplaySpan() {\n\t\tif ( !this.total_display_span ) {\n\t\t\treturn;\n\t\t}\n\t\tvar totalRows;\n\t\tvar start;\n\t\tvar end;\n\t\tvar grid_selected_id_array = this.getGridSelectIdArray();\n\t\tvar grid_selected_length = 0;\n\t\t//Uncaught TypeError: Cannot read property 'length' of undefined\n\t\tif ( grid_selected_id_array ) {\n\t\t\tgrid_selected_length = grid_selected_id_array.length;\n\t\t}\n\n\t\tvar items_pre_page = 100;\n\t\tif ( LocalCacheData.getLoginUserPreference() ) {\n\t\t\tvar items_per_page = parseInt( LocalCacheData.getLoginUserPreference().items_per_page );\n\t\t}\n\n\t\tif ( LocalCacheData.paging_type === 0 ) {\n\t\t\tif ( this.pager_data ) {\n\t\t\t\ttotalRows = this.pager_data.total_rows;\n\t\t\t\tstart = 1;\n\t\t\t\tend = this.grid.getData().length;\n\t\t\t} else {\n\t\t\t\ttotalRows = 0;\n\t\t\t\tstart = 0;\n\t\t\t\tend = 0;\n\t\t\t}\n\t\t} else {\n\t\t\tif ( this.pager_data ) {\n\t\t\t\ttotalRows = this.pager_data.total_rows;\n\t\t\t\tstart = 0;\n\t\t\t\tend = 0;\n\n\t\t\t\tif ( this.pager_data.last_page_number > 1 ) {\n\t\t\t\t\tif ( !this.pager_data.is_last_page ) {\n\n\t\t\t\t\t\tstart = ( this.pager_data.current_page - 1 ) * items_per_page + 1;\n\t\t\t\t\t\tend = start + items_per_page - 1;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tstart = ( this.pager_data.current_page - 1 ) * items_per_page + 1;\n\t\t\t\t\t\tend = totalRows;\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\t\t\t\t\tstart = 1;\n\t\t\t\t\tend = totalRows;\n\t\t\t\t}\n\n\t\t\t} else {\n\n\t\t\t\ttotalRows = 0;\n\t\t\t\tstart = 0;\n\t\t\t\tend = 0;\n\t\t\t}\n\t\t}\n\n\t\t//Counting pages can be disabled, in which case totalRows returns FALSE unless the user is on the last page.\n\t\tvar totalInfo = start + ' - ' + end;\n\t\tif ( totalRows !== false ) {\n\t\t\ttotalInfo = totalInfo + ' ' + $.i18n._( 'of' ) + ' ' + totalRows + ' ' + $.i18n._( 'total' ) + '.';\n\t\t}\n\n\t\tthis.total_display_span.text( $.i18n._( 'Displaying' ) + ' ' + totalInfo + ' [ ' + $.i18n._( 'Selected' ) + ': ' + grid_selected_length + ' ]' );\n\t}\n\n\tisContextIconDisabled( id ) {\n\t\tvar context_menu_array = ContextMenuManager.getMenuModelByMenuId( this.determineContextMenuMountAttributes().id );\n\t\tvar len = context_menu_array.length;\n\n\t\tfor ( var i = 0; i < len; i++ ) {\n\t\t\tlet context_btn = context_menu_array[i];\n\t\t\tif ( context_menu_array[i].id === id ) {\n\t\t\t\tif ( context_btn.disabled || ( context_btn.hasOwnProperty( 'visible' ) && !context_btn.visible ) ) {\n\t\t\t\t\treturn true;\n\t\t\t\t} else {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn true; //Cannot find context menu button, return true as if button is disabled / cannot be used.\n\t}\n\n\tgetViewModeErrorMessage() {\n\t\t//Change error message depending on if edit context menu icon is available or not.\n\t\tif ( this.isContextIconDisabled( 'edit' ) ) {\n\t\t\treturn _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.view_mode_message */ .x.view_mode_message;\n\t\t}\n\n\t\treturn _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.view_mode_message */ .x.view_mode_message + ', ' + _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.view_mode_edit_message */ .x.view_mode_edit_message;\n\t}\n\n\t//Set right click menu for list view grid\n\tinitRightClickMenu( target_type ) {\n\t\t//Error: Object doesn't support property or method 'contextMenu' in /interface/html5/views/BaseViewController.js?v=7.4.6-20141027-132733 line 393\n\t\tif ( !$.hasOwnProperty( 'contextMenu' ) ) {\n\t\t\treturn;\n\t\t}\n\t\tvar $this = this;\n\n\t\tvar selector = '';\n\n\t\tswitch ( target_type ) {\n\t\t\tcase RightClickMenuType.LISTVIEW:\n\t\t\t\tselector = '#gbox_' + this.ui_id + '_grid';\n\t\t\t\tbreak;\n\t\t\tcase RightClickMenuType.EDITVIEW:\n\t\t\t\tselector = '#' + this.ui_id + '_edit_view_tab';\n\t\t\t\tbreak;\n\t\t\tcase RightClickMenuType.NORESULTBOX:\n\t\t\t\tselector = '#' + this.ui_id + '_no_result_box';\n\t\t\t\tbreak;\n\t\t\tcase RightClickMenuType.ABSENCE_GRID:\n\t\t\t\tselector = '#' + this.ui_id + '_absence_grid';\n\t\t\t\tbreak;\n\t\t\tcase RightClickMenuType.VIEW_ICON:\n\t\t\t\tselector = '#' + 'view_html';\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tselector = '#gbox_' + this.ui_id + '_grid';\n\t\t\t\tbreak;\n\n\t\t}\n\n\t\tif ( $( selector ).length == 0 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar items = this.getRightClickMenuItems();\n\n\t\tif ( !items || $.isEmptyObject( items ) ) {\n\t\t\treturn;\n\t\t}\n\t\t$.contextMenu( 'destroy', selector );\n\t\t$.contextMenu( {\n\t\t\tselector: selector,\n\t\t\tcallback: function( key, options ) {\n\t\t\t\t$this.onContextMenuClick( null, key );\n\t\t\t},\n\n\t\t\tonContextMenu: function() {\n\t\t\t\treturn false;\n\t\t\t},\n\t\t\titems: items\n\t\t} );\n\t}\n\n\tgetRightClickMenuItems() {\n\t\tvar $this = this;\n\n\t\tvar items = {};\n\t\tvar context_menu_array = ContextMenuManager.getMenuModelByMenuId( this.determineContextMenuMountAttributes().id );\n\t\tvar len = context_menu_array.length;\n\t\tfor ( var i = 0; i < len; i++ ) {\n\t\t\tvar context_btn = context_menu_array[i];\n\n\t\t\tif ( context_btn.visible === false || context_btn.action_group_header || context_btn.separator || !context_btn.show_on_right_click ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tvar label = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.htmlDecode */ .x.htmlDecode( context_btn.label.replace( ' ', ' ' ) );\n\t\t\tvar id = context_btn.id;\n\n\t\t\titems[id] = {\n\t\t\t\tname: label,\n\t\t\t\tdisabled: function( key ) {\n\t\t\t\t\treturn $this.isContextIconDisabled( key );\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\n\t\treturn items;\n\t}\n\n\t//Don't initOptions if edit_only_mode. Do it in sub views\n\tinitData() {\n\t\tvar $this = this;\n\n\t\t//Work around to init sub view after tab is shown.\n\t\t_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.removeViewTab */ .x.removeViewTab( this.viewId );\n\t\tProgressBar.showOverlay();\n\t\tif ( !$this.edit_only_mode ) {\n\n\t\t\t//Various views expect search fields to be built already, such as initOptions() in PunchesViewController or getAllColumns() in ScheduleViewController.\n\t\t\t//Because of that we need to wait for resolution of getCustomFields promise to avoid exceptions and breaking views.\n\t\t\tTTPromise.wait( 'BaseViewController', 'getCustomFields', function() {\n\t\t\t\t$this.initOptions();\n\t\t\t\t$this.getAllColumns( function() {\n\t\t\t\t\t$this.initLayout();\n\t\t\t\t} );\n\t\t\t} );\n\n\t\t\t//When on a sub view mode tab we want to disable certain context menu buttons of the parent view.\n\t\t\t//This is to help prevent users from using context menu buttons for the wrong view and deleting/copying records they did not intend to use.\n\t\t\tthis.onSubViewModeDisableParentContextMenuButtons();\n\t\t}\n\t}\n\n\tinitLayout() {\n\t\tvar $this = this;\n\t\t$this.getAllLayouts( function() {\n\t\t\t$this.getDefaultDisplayColumns( function() {\n\t\t\t\t$this.setSelectLayout();\n\t\t\t\t//$this.setGridColumnsWidth(); //This is done in setSelectLayout() and searchDone(), so no point in doing it multiple times.\n\t\t\t\t$this.search();\n\t\t\t} );\n\t\t} );\n\t}\n\n\t// edit_only_mode call this when open edit view. Not in initData\n\tinitOptions() {\n\t}\n\n\t// TODO: Consolidate id and menu container into one function.\n\t/**\n\t * Determine what id, mount point, and menu type are needed to create the context menu for a specific view/edit view, based on the current view state. Main, Edit View, Sub View etc.\n\t */\n\tdetermineContextMenuMountAttributes() {\n\t\tvar return_object = {\n\t\t\tid: null,\n\t\t\tparent_mount_point: null,\n\t\t\tmenu_type: null,\n\t\t\tparent_id: null\n\t\t};\n\n\t\t// Figure out parent type\n\n\t\t/* Be aware that if something is incorrectly matched here, it may try to match with a wrong menu, or existing other menu,\n\t\t * and thus may have the side effect of closing the wrong menu when a window is closed.\n\t\t * If that symptom happens, check the matching here.\n\t\t */\n\n\t\t// You can see an extensive list in setCurrentEditViewState().\n\t\tif( this.is_add\n\t\t\t|| this.is_viewing\n\t\t\t|| this.is_viewing_detail //Cannot use just LocalCacheData.current_doing_context_action === 'view_detail' as it gets overwritten to cancel.\n\t\t\t|| this.is_edit\n\t\t\t|| this.is_mass_editing\n\t\t\t|| this.is_mass_adding // Not tested, but as all the others from setCurrentEditViewState are now here, might as well add it.\n\t\t\t|| this.edit_only_mode\n\t\t\t|| LocalCacheData.current_doing_context_action === 'view_detail' //With is_viewing_detail we may no longer need this condition.\n\t\t\t|| LocalCacheData.current_doing_context_action === 'delete'\n\t\t) {\n\t\t\treturn_object = this.parseContextMenuEditViewAttributes();\n\t\t} else if( $( this.el ).parents( '.edit-view-tab-outside-sub-view' ).length > 0 && this.ui_id ) {\n\t\t\t// Using this approach rather than this.sub_view_mode, as some views have edit views still showing as subviews.\n\t\t\t// #VueContextMenu#SubViews# Old approach can be found in BaseVC.parseCustomContextModelForSubViews but its better to control it from here in one place.\n\t\t\t// These matches would previously match to main_view, but subviews should be different to main views.\n\t\t\treturn_object = this.parseContextMenuEditSubViewTabAttributes();\n\t\t}\n\t\telse if( this.ui_id ) {\n\t\t\treturn_object = this.parseContextMenuMainViewAttributes();\n\t\t} else {\n\t\t\t// If each view has a unique context menu, then this should never happen, as context menu should only be initiated once.\n\t\t\t// However, there are many cases where tabs repeatedly call this.buildContextMenu, whilst keeping the same view controller, so this is now a warning rather than an error.\n\t\t\tDebug.Error( 'Error: View state for '+ this.viewId +' ('+ this.ui_id +') does not match options.', 'BaseViewController.js', 'BaseViewController', 'determineContextMenuMountAttributes', 1 );\n\t\t}\n\n\t\t// Regardless of editview/main type above, there are some occasions when it detects as main menu, but its still within tabs.\n\t\t// Here it would be Edit View -> Tabs -> Subview. For example Attendance->Accrual Balance -> View.\n\t\t// The top icons are edit view for AccrualBalanceView.\n\t\t// The icons within Accrual tab are seen as a main menu for AccrualView.\n\t\t// Lets add these occurances into another type.\n\n\t\t// Get ID\n\t\treturn_object.id = ContextMenuManager.generateMenuId( return_object.menu_type, return_object.parent_id );\n\n\t\treturn return_object;\n\t}\n\n\tparseContextMenuEditViewAttributes() {\n\t\t// Designed to be overriden by views if behaviour needs to be different.\n\t\t// All the edit_view style windows. Although the edit_only ones have a slightly different this.ui_id value, but the code is the same.\n\t\tif( !this.edit_view_tab ) {\n\t\t\t// If mount point IS needed (not just menu ID), then this is a bug. Check if buildContextMenu is not called before edit_view_tab populated (common in views overriding BaseView functions like openEditView.\n\t\t\tDebug.Text( 'Warning: Unable to get full context menu mount data, edit_view_tab missing. Might be ok if mount point not needed. Check if buildContextMenu is not called before edit_view_tab populated (common in views overriding BaseView functions like openEditView ('+ this.viewId +'/'+ this.ui_id +')', 'BaseViewController.js', 'BaseViewController', 'parseContextMenuEditViewAttributes', 10 );\n\t\t}\n\t\tif( !this.ui_id ) {\n\t\t\tDebug.Error( 'Warning: Unable to get full context menu mount data, ui_id missing. ('+ this.viewId +'/'+ this.ui_id +')', 'BaseViewController.js', 'BaseViewController', 'parseContextMenuEditViewAttributes', 1 );\n\t\t}\n\t\treturn {\n\t\t\tparent_mount_point: this.edit_view_tab, // Note: When this function is called, the edit_view_tab might not be built yet, so parent mount could be null, thats ok if mount point not needed yet.\n\t\t\tparent_id: this.ui_id + '_edit_view_tab',\n\t\t\tmenu_type: 'editview_contextmenu',\n\t\t}\n\t}\n\tparseContextMenuMainViewAttributes() {\n\t\t// Designed to be overriden by views if behaviour needs to be different.\n\t\t// Main views\n\n\t\tif( !this.ui_id ) {\n\t\t\tDebug.Error( 'Warning: Unable to get full context menu mount data, ui_id missing. ('+ this.viewId +'/'+ this.ui_id +')', 'BaseViewController.js', 'BaseViewController', 'parseContextMenuEditViewAttributes', 1 );\n\t\t}\n\n\t\treturn {\n\t\t\tparent_mount_point: $( this.el ),\n\t\t\tparent_id: this.ui_id,\n\t\t\tmenu_type: 'listview_contextmenu',\n\t\t}\n\t}\n\n\tparseContextMenuEditSubViewTabAttributes() {\n\t\t// Designed to be overriden by views if behaviour needs to be different.\n\t\t// Based on main_contextmenu\n\n\t\tif( !this.ui_id ) {\n\t\t\tDebug.Error( 'Warning: Unable to get full context menu mount data, ui_id missing. ('+ this.viewId +'/'+ this.ui_id +')', 'BaseViewController.js', 'BaseViewController', 'parseContextMenuEditViewAttributes', 1 );\n\t\t}\n\n\t\treturn {\n\t\t\tparent_mount_point: $( this.el ),\n\t\t\tparent_id: this.ui_id,\n\t\t\tmenu_type: 'subview_contextmenu',\n\t\t}\n\t}\n\n\tgetDefaultContextMenuModel() {\n\n\t\tvar default_context_menu_model = {\n\t\t\t'groups': {\n\t\t\t\t'editor': {\n\t\t\t\t\tlabel: $.i18n._( 'Editor' ),\n\t\t\t\t\tid: 'editor',\n\t\t\t\t\tsort_order: 1000\n\t\t\t\t},\n\t\t\t\t'navigation': {\n\t\t\t\t\tlabel: $.i18n._( 'Navigation' ),\n\t\t\t\t\tid: 'navigation',\n\t\t\t\t\tsort_order: 8000\n\t\t\t\t},\n\t\t\t\t'other': {\n\t\t\t\t\tlabel: $.i18n._( 'Other' ),\n\t\t\t\t\tid: 'other',\n\t\t\t\t\tsort_order: 9000\n\t\t\t\t}\n\t\t\t},\n\n\t\t\t'icons': {}\n\t\t};\n\n\t\tdefault_context_menu_model['icons']['add'] = {\n\t\t\tlabel: $.i18n._( 'New' ),\n\t\t\tid: 'add',\n\t\t\tgroup: 'editor',\n\t\t\tvue_icon: 'tticon tticon-add_black_24dp',\n\t\t\tshow_on_right_click: true,\n\t\t\tsort_order: 1000\n\t\t};\n\n\t\tdefault_context_menu_model['icons']['view'] = {\n\t\t\tlabel: $.i18n._( 'View' ),\n\t\t\tid: 'view',\n\t\t\tgroup: 'editor',\n\t\t\tvue_icon: 'tticon tticon-visibility_black_24dp',\n\t\t\tshow_on_right_click: true,\n\t\t\tsort_order: 1010\n\t\t};\n\n\t\tdefault_context_menu_model['icons']['edit'] = {\n\t\t\tlabel: $.i18n._( 'Edit' ),\n\t\t\tid: 'edit',\n\t\t\tgroup: 'editor',\n\t\t\tvue_icon: 'tticon tticon-edit_black_24dp',\n\t\t\tshow_on_right_click: true,\n\t\t\tsort_order: 1020,\n\t\t\t//min_width: '85' /* Match with mass_edit so they can toggle without moving any menu items in UI */\n\t\t};\n\n\t\tdefault_context_menu_model['icons']['mass_edit'] = {\n\t\t\tlabel: $.i18n._( 'Mass Edit' ),\n\t\t\tid: 'mass_edit',\n\t\t\tgroup: 'editor',\n\t\t\tvue_icon: 'tticon tticon-edit_note_black_24dp',\n\t\t\tshow_on_right_click: true,\n\t\t\tvisible: false, // Ensures Mass Edit is not shown at start together with Edit. We only want one or the other.\n\t\t\tsort_order: 1030,\n\t\t\t//min_width: '85' /* Match with edit so they can toggle without moving any menu items in UI */\n\t\t};\n\n\t\tdefault_context_menu_model['icons']['delete_icon'] = {\n\t\t\tlabel: $.i18n._( 'Delete' ),\n\t\t\tid: 'delete_icon',\n\t\t\taction_group: 'delete',\n\t\t\tgroup: 'editor',\n\t\t\tvue_icon: 'tticon tticon-delete_black_24dp',\n\t\t\tshow_on_right_click: true,\n\t\t\tsort_order: 1040\n\t\t};\n\n\t\tdefault_context_menu_model['icons']['delete_and_next'] = {\n\t\t\tlabel: $.i18n._( 'Delete & Next' ),\n\t\t\tid: 'delete_and_next',\n\t\t\taction_group: 'delete',\n\t\t\tgroup: 'editor',\n\t\t\tvue_icon: 'tticon tticon-delete_black_24dp',\n\t\t\tsort_order: 1050\n\t\t};\n\n\t\tdefault_context_menu_model['icons']['copy'] = {\n\t\t\tlabel: $.i18n._( 'Copy' ),\n\t\t\tid: 'copy',\n\t\t\taction_group: 'copy',\n\t\t\tgroup: 'editor',\n\t\t\tvue_icon: 'tticon tticon-content_copy_black_24dp',\n\t\t\tshow_on_right_click: true,\n\t\t\tsort_order: 1060\n\t\t};\n\n\t\tdefault_context_menu_model['icons']['copy_as_new'] = {\n\t\t\tlabel: $.i18n._( 'Copy as New' ),\n\t\t\tid: 'copy_as_new',\n\t\t\taction_group: 'copy',\n\t\t\tgroup: 'editor',\n\t\t\tvue_icon: 'tticon tticon-content_copy_black_24dp',\n\t\t\tshow_on_right_click: true,\n\t\t\tsort_order: 1070\n\t\t};\n\n\t\tdefault_context_menu_model['icons']['save'] = {\n\t\t\tlabel: $.i18n._( 'Save' ),\n\t\t\tid: 'save',\n\t\t\taction_group: 'save',\n\t\t\tgroup: 'editor',\n\t\t\tvue_icon: 'tticon tticon-save_black_24dp',\n\t\t\tshow_on_right_click: true,\n\t\t\tsort_order: 1080\n\t\t};\n\n\t\tdefault_context_menu_model['icons']['save_and_continue'] = {\n\t\t\tlabel: $.i18n._( 'Save & Continue' ),\n\t\t\tid: 'save_and_continue',\n\t\t\taction_group: 'save',\n\t\t\tgroup: 'editor',\n\t\t\tvue_icon: 'tticon tticon-save_black_24dp',\n\t\t\tsort_order: 1090\n\t\t};\n\n\t\tdefault_context_menu_model['icons']['save_and_next'] = {\n\t\t\tlabel: $.i18n._( 'Save & Next' ),\n\t\t\tid: 'save_and_next',\n\t\t\taction_group: 'save',\n\t\t\tgroup: 'editor',\n\t\t\tvue_icon: 'tticon tticon-save_black_24dp',\n\t\t\tsort_order: 1100\n\t\t};\n\n\t\tdefault_context_menu_model['icons']['save_and_copy'] = {\n\t\t\tlabel: $.i18n._( 'Save & Copy' ),\n\t\t\tid: 'save_and_copy',\n\t\t\taction_group: 'save',\n\t\t\tgroup: 'editor',\n\t\t\tvue_icon: 'tticon tticon-save_black_24dp',\n\t\t\tsort_order: 1110\n\t\t};\n\n\t\tdefault_context_menu_model['icons']['save_and_new'] = {\n\t\t\tlabel: $.i18n._( 'Save & New' ),\n\t\t\tid: 'save_and_new',\n\t\t\taction_group: 'save',\n\t\t\tgroup: 'editor',\n\t\t\tvue_icon: 'tticon tticon-save_black_24dp',\n\t\t\tsort_order: 1120\n\t\t};\n\n\t\tdefault_context_menu_model['icons']['cancel'] = {\n\t\t\tlabel: $.i18n._( 'Cancel' ),\n\t\t\tid: 'cancel',\n\t\t\tgroup: 'editor',\n\t\t\tvue_icon: 'tticon tticon-cancel_black_24dp',\n\t\t\tsort_order: 1130\n\t\t};\n\n\t\tdefault_context_menu_model['icons']['export_excel'] = {\n\t\t\tlabel: $.i18n._( 'Export' ),\n\t\t\tid: 'export_excel',\n\t\t\tmenu_align: 'right',\n\t\t\taction_group: 'import_export',\n\t\t\tgroup: 'other',\n\t\t\tvue_icon: 'tticon tticon-file_upload_black_24dp',\n\t\t\tsort_order: 9000,\n\t\t\tmenu_force_active: true\n\t\t};\n\n\t\treturn default_context_menu_model;\n\t}\n\n\t// Overriden by ViewControllers with custom context menus.\n\tgetCustomContextMenuModel() {\n\t\tvar context_menu_model = {\n\t\t\tgroups: {},\n\t\t\texclude: [],\n\t\t\tinclude: ['default']\n\t\t};\n\n\t\treturn context_menu_model;\n\t}\n\tparseCustomContextModelForEditViews( context_menu_model ) {\n\n\t\t// #VueContextMenu# - Commenting out logic below as we want to have the menu type logic in one place (BaseVC.determineContextMenuMountAttributes)\n\t\t// if( this.is_add\n\t\t// \t|| this.is_viewing\n\t\t// \t|| this.is_edit\n\t\t// \t|| this.is_mass_editing\n\t\t// \t|| this.is_mass_adding // Not tested, but as all the others from setCurrentEditViewState are now here, might as well add it.\n\t\t// \t|| this.edit_only_mode\n\t\t// \t|| LocalCacheData.current_doing_context_action === 'view_detail'\n\t\t// ) {\n\t\tif( this.determineContextMenuMountAttributes().menu_type === 'editview_contextmenu' ) {\n\t\t\tcontext_menu_model.include.push( 'cancel' );\n\t\t}\n\n\t\treturn context_menu_model;\n\t}\n\tparseCustomContextModelForSubViews( context_menu_model ) {\n\t\t// If a view does not want this, override the function in that view and just return the untouched object.\n\t\t// #VueContextMenu#SubViews# Commenting out the logic below as we should just have the controlling logic in one place (BaseVC.determineContextMenuMountAttributes)\n\n\t\t// if( this.determineContextMenuMountAttributes().menu_type === 'subview_contextmenu'\n\t\t// \t|| (this.sub_view_mode\n\t\t// \t&& !this.is_edit\n\t\t// \t&& !this.is_viewing\n\t\t// \t&& LocalCacheData.current_doing_context_action !== 'view' // To ensure view state is carried forward across subview loads, as Accrual Balance -> Accrual View record results in this.is_viewing === false.\n\t\t// \t&& LocalCacheData.current_doing_context_action !== 'edit' // Note: See if these last 2 checks are still needed after subview_contextmenu check addition.\n\t\t// )) { // TODO: Does not seem to work for Audit log, as is_viewing is deliberately set to false.\n\t\tif( this.determineContextMenuMountAttributes().menu_type === 'subview_contextmenu' ) {\n\t\t\tcontext_menu_model.exclude.push( 'cancel' ); // Needed as subview grid menus dont need to be able to close the current window; the main context menu should do that.\n\t\t}\n\n\t\treturn context_menu_model;\n\t}\n\n\tbuildContextMenuModels() {\n\t\t// Note: Currently icons might still be hidden by the permissions code, due to the 'invisible-image' class, especially with this.edit_only_mode. See BaseViewController.setDefaultMenuAddIcon() as an example.\n\n\t\tlet icon_count = 1;\n\t\tlet context_menu_model = this.getCustomContextMenuModel();\n\n\t\t// Override for edit views.\n\t\tcontext_menu_model = this.parseCustomContextModelForEditViews( context_menu_model );\n\n\t\t// Override for subviews, as we want to remove Cancel. This is global, perhaps refactor into the individual getCustomContextMenuModel but that means duplicating the code in 100+ places.\n\t\tcontext_menu_model = this.parseCustomContextModelForSubViews( context_menu_model );\n\n\t\tif ( context_menu_model && ( context_menu_model.include || context_menu_model.exclude ) ) {\n\t\t\t//Context Menu\n\n\t\t\tlet default_context_menu_model = this.getDefaultContextMenuModel();\n\n\t\t\tlet final_context_menu_model = { 'icons': {}, 'groups': {} };\n\n\t\t\tif ( !context_menu_model.groups ) {\n\t\t\t\tcontext_menu_model.groups = {};\n\t\t\t}\n\n\t\t\t//Default to including all default icons.\n\t\t\tif ( !context_menu_model.include ) {\n\t\t\t\tcontext_menu_model.include = ['default'];\n\t\t\t}\n\n\t\t\t//If we don't include default, assume we want to include all default icons.\n\t\t\tif ( context_menu_model.include.indexOf( 'default' ) === -1 ) {\n\t\t\t\tcontext_menu_model.include.unshift( 'default' ); // Add to front, so custom icons can override a default icon id.\n\t\t\t}\n\n\t\t\t//Assign default groups.\n\t\t\tfor ( let x in default_context_menu_model.groups ) {\n\t\t\t\tdefault_context_menu_model.groups[x].sub_menus = [];\n\n\t\t\t\tfinal_context_menu_model.groups[x] = default_context_menu_model.groups[x];\n\t\t\t}\n\n\t\t\tfor ( let x in context_menu_model.groups ) {\n\t\t\t\tcontext_menu_model.groups[x].sub_menus = [];\n\n\t\t\t\tfinal_context_menu_model.groups[x] = context_menu_model.groups[x];\n\t\t\t}\n\n\t\t\t//Filter groups/icons\n\t\t\tif ( context_menu_model.hasOwnProperty( 'include' ) ) {\n\t\t\t\tif ( context_menu_model.include.constructor !== Array ) {\n\t\t\t\t\tcontext_menu_model.include = Array( context_menu_model.include );\n\t\t\t\t}\n\n\t\t\t\tfor ( let i in context_menu_model.include ) {\n\t\t\t\t\tlet current_include_element = context_menu_model.include[i];\n\t\t\t\t\tif( context_menu_model.include.hasOwnProperty( i )) {\n\t\t\t\t\t\tif ( current_include_element == 'default' ) {\n\t\t\t\t\t\t\tDebug.Text( 'Including All Default Icons...', 'BaseViewController.js', 'BaseViewController', 'buildContextMenuModels', 11 );\n\n\t\t\t\t\t\t\tfor ( let x in default_context_menu_model.icons ) {\n\t\t\t\t\t\t\t\taddIconToFinalModel( default_context_menu_model.icons[x] );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif ( typeof current_include_element !== 'object' && default_context_menu_model.icons[current_include_element] ) {\n\t\t\t\t\t\t\t\taddIconToFinalModel( default_context_menu_model.icons[current_include_element] );\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\taddIconToFinalModel( current_include_element );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfunction addIconToFinalModel( icon ) {\n\t\t\t\tif( !icon.sort_order && icon.group ) {\n\t\t\t\t\ticon.sort_order = final_context_menu_model.groups[ icon.group ].sort_order; // Rather than setting the default to 1000, lets set it to the start of the icon's group, so it appears in roughly the right area of the menu. Fixes e.g. TimeSheet & Export in Employee->Employees.\n\t\t\t\t}\n\t\t\t\t// TODO: Also need scenario for when there is no sort_order and no group. Currently this is caught as a console error via checks in ContextMenuManager.convertBackBoneMenuModelToPrimeVue.sort_compare\n\n\t\t\t\ticon.add_order = icon_count; // rather than calculating length each time, just track additions, as all icons should be added through here anyway.\n\t\t\t\tfinal_context_menu_model.icons[icon.id] = icon;\n\t\t\t\ticon_count++;\n\n\t\t\t\treturn icon;\n\t\t\t}\n\n\t\t\t// #2644 Include array is a mix of icon id strings and objects, this function flattens it to an array of strings for id comparision.\n\t\t\tfunction flattenMixedIdObjectArray( array ) {\n\t\t\t\treturn array.map( function( item ) {\n\t\t\t\t\treturn item.id || item;\n\t\t\t\t} );\n\t\t\t}\n\n\t\t\tlet tmp_included_icon_ids = flattenMixedIdObjectArray( context_menu_model.include );\n\n\t\t\t//Must go after include, so they can include a few icons, then exclude all.\n\t\t\tif ( context_menu_model.hasOwnProperty( 'exclude' ) ) {\n\t\t\t\tif ( context_menu_model.exclude.constructor !== Array ) {\n\t\t\t\t\tcontext_menu_model.exclude = Array( context_menu_model.exclude );\n\t\t\t\t}\n\n\t\t\t\tfor ( let j in context_menu_model.exclude ) {\n\t\t\t\t\tif( context_menu_model.exclude.hasOwnProperty( j )) {\n\t\t\t\t\t\tif ( context_menu_model.exclude[j] == 'default' ) {\n\t\t\t\t\t\t\tDebug.Text( 'Excluding All Default Icons...', 'BaseViewController.js', 'BaseViewController', 'buildContextMenuModels', 10 );\n\n\t\t\t\t\t\t\tfor ( let x in default_context_menu_model.icons ) {\n\t\t\t\t\t\t\t\tif ( tmp_included_icon_ids.indexOf( x ) === -1 ) { //Make sure we don't exclude one that is included. Compare against flattened/extracted include array, otherwise types do not match and all default icons are removed regardless if they exist in include.\n\t\t\t\t\t\t\t\t\tif ( final_context_menu_model.icons[x] ) {\n\t\t\t\t\t\t\t\t\t\tdelete final_context_menu_model.icons[x];\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tlet exclude_icon_id = context_menu_model.exclude[j];\n\t\t\t\t\t\t\tif ( final_context_menu_model.icons[exclude_icon_id] ) {\n\t\t\t\t\t\t\t\tdelete final_context_menu_model.icons[exclude_icon_id];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t//Build Menu\n\t\t\tlet groups = {};\n\t\t\tfor ( let x in final_context_menu_model.groups ) {\n\t\t\t\tgroups[x] = final_context_menu_model.groups[x];\n\t\t\t\tDebug.Text( 'Creating Ribbon Menu Group: ' + final_context_menu_model.groups[x].label, 'BaseViewController.js', 'BaseViewController', 'buildContextMenuModels', 11 );\n\t\t\t}\n\n\t\t\tfor ( let x in final_context_menu_model.icons ) {\n\n\t\t\t\t//Replace group string with object.\n\t\t\t\tif ( final_context_menu_model.icons[x] && final_context_menu_model.icons[x].group ) {\n\t\t\t\t\tif ( final_context_menu_model.icons[x].group.constructor === String ) {\n\t\t\t\t\t\tfinal_context_menu_model.icons[x].group = groups[final_context_menu_model.icons[x].group];\n\t\t\t\t\t} else if ( typeof final_context_menu_model.icons[x].group === 'object' ) {\n\t\t\t\t\t\t//The 2nd time the edit view is opened, icons manually passed in through 'include' already have the groups converted to objects, but the icons don't appear until we re-assign the group object again.\n\t\t\t\t\t\tfinal_context_menu_model.icons[x].group = groups[final_context_menu_model.icons[x].group.get( 'id' )];\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( final_context_menu_model.icons[x].hasOwnProperty( 'permission_result' ) == false ) {\n\t\t\t\t\tfinal_context_menu_model.icons[x].permission_result = true;\n\t\t\t\t}\n\t\t\t\tif ( !final_context_menu_model.icons[x].hasOwnProperty( 'permission' ) == false ) {\n\t\t\t\t\tfinal_context_menu_model.icons[x].permission = null;\n\t\t\t\t}\n\n\t\t\t\tDebug.Text( 'Creating Ribbon Menu Icon: ' + final_context_menu_model.icons[x].label, 'BaseViewController.js', 'BaseViewController', 'buildContextMenuModels', 11 );\n\n/*\t\t\t\t// TODO: This not an ideal way to do it, but not worth changing until a bigger refactor of the context menu is done at a later date.\n\t\t\t\tif ( final_context_menu_model.icons[x].items && final_context_menu_model.icons[x].items.length > 0 ) {\n\t\t\t\t\t// We use item to store the pre conversion and post conversion data. Therefore we must re-assign to a temp var, and reset.\n\t\t\t\t\tlet items_to_add = final_context_menu_model.icons[x].items;\n\n\t\t\t\t\t// Still store the original items so that the new Vue Menu can parse these.\n\t\t\t\t\tfinal_context_menu_model.icons[x].original_items = items_to_add;\n\n\t\t\t\t\t// Reset the items attribute to an empty array, ready for RibbonSubMenuNavItem to use later on. Still needs clearing to empty array in ContextMenuManager once the ribbonmenu is done with it.\n\t\t\t\t\tfinal_context_menu_model.icons[x].items = [];\n\t\t\t\t}*/\n\t\t\t}\n\n\t\t\t// #VueContextMenu# Pass the final context menu model to the Vue context menu.\n\t\t\tContextMenuManager.buildContextMenuModelFromBackbone( this.determineContextMenuMountAttributes().id, final_context_menu_model, this );\n\n\t\t} else {\n\t\t\t//Legacy fallback when no context menu model is defined.\n\t\t\t_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.sendErrorReport */ .x.sendErrorReport( 'ContextMenuModel error. No valid contextmenu model defined.' );\n\t\t}\n\t}\n\n\tunmountContextMenu() {\n\t\t// This should be able to handle various menu's as the determine menu id function will identify the right menu (view, edit etc)\n\t\tContextMenuManager.unmountContextMenu( this.determineContextMenuMountAttributes().id );\n\t}\n\n\tbuildContextMenu( setFocus ) {\n\t\tif ( this.current_edit_record && this.edit_only_mode == true && LocalCacheData.current_open_edit_only_controller && LocalCacheData.current_open_edit_only_controller.viewId != LocalCacheData.current_open_edit_only_controller.viewId ) { // #2542 - prevent early menu setup for views that have not been loaded into memory yet.\n\t\t\treturn null;\n\t\t}\n\t\tvar $this = this;\n\t\tif ( !_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( setFocus ) ) {\n\t\t\tsetFocus = true;\n\t\t}\n\n\t\tif ( !this.sub_view_mode ) {\n\t\t\tLocalCacheData.current_open_sub_controller = null; //Clean sub controller if current view is a main view\n\t\t} else {\n\t\t\t//When on a sub view mode tab we want to disable certain context menu buttons of the parent view.\n\t\t\t//This is to help prevent users from using context menu buttons for the wrong view and deleting/copying records they did not intend to use.\n\t\t\tthis.onSubViewModeDisableParentContextMenuButtons();\n\t\t}\n\n\t\t// Vue Context Menu initialization - #2838\n\t\t// Checks for existing menu, because for an edit_view, we dont want to start a new menu, we want to re-use it.\n\t\t// Otherwise we end up treating edit menus like new views, which is more complex given the html templates (report edit views are unique, as we now have a common template).\n\t\tlet menu_attributes = this.determineContextMenuMountAttributes();\n\n\t\tif( ContextMenuManager.getMenu( menu_attributes.id ) === undefined ) {\n\t\t\t// #VueContextMenu#Dynamic-EditView\n\t\t\tContextMenuManager.createAndMountMenu( menu_attributes.id, menu_attributes.parent_mount_point, this );\n\n\t\t\tif( menu_attributes && menu_attributes.parent_mount_point ) {\n\t\t\t\t// #VueContextMenu#context-border creation to put a border around a context menu and the contents it relates to. This will help users understand which context menu belongs to what if there is more than one menu on the page.\n\t\t\t\tvar context_parent = menu_attributes.parent_mount_point; // $('.edit-view-tab-bar');\n\t\t\t\tvar context_label = this.context_menu_name;\n\n\t\t\t\tcontext_parent.prepend(''+ context_label +'');\n\t\t\t\tcontext_parent.wrapInner('');\n\t\t\t} else {\n\t\t\t\t// If mount point is null, then this is a bug. Check if buildContextMenu is not called before edit_view_tab populated (common in views overriding BaseView functions like openEditView.\n\t\t\t\tDebug.Error( 'Error creating context-border for '+this.viewId+' ('+ menu_attributes.id +'/'+ this.ui_id +')', 'BaseViewController.js', 'BaseViewController', 'buildContextMenu', 10 );\n\t\t\t}\n\n\t\t\t// if( ( this.is_add || this.is_edit || this.edit_only_mode ) && this.edit_view_tab || LocalCacheData.current_doing_context_action === 'view_detail' ) { // REMEMBER TO UPDATE determineContextMenuMountAttributes!!\n\t\t\t// \t// #VueContextMenu#Dynamic-EditView - Consolidate this, as View is now in 1 place, and EditView in 2 places. <-- #TODO: is this comment still valid? Search the tag.\n\t\t\t// \t// Pop-up edit views, which overlay across an unrelated view ( appear anywhere basically ).\n\t\t\t// \tthis.context_edit_only_menu_id = ContextMenuManager.createAndMountMenu( menu_attributes.id, this.edit_view_tab, this );\n\t\t\t// } else if( this.ui_id ) {\n\t\t\t// \t// Normal Views\n\t\t\t// \tthis.context_menu_id = ContextMenuManager.createAndMountMenu( menu_attributes.id, $( $this.el ), this );\n\t\t\t// } else {\n\t\t\t// \t// If each view has a unique context menu, then this should never happen, as context menu should only be initiated once.\n\t\t\t// \t// However, there are many cases where tabs repeatedly call this.buildContextMenu, whilst keeping the same view controller, so this is now a warning rather than an error.\n\t\t\t// \tDebug.Error( 'Error during context menu mount. View state for ( '+ this.viewId +' ) does not match options.', 'BaseViewController.js', 'BaseViewController', 'buildContextMenu', 1 );\n\t\t\t// }\n\t\t} else {\n\t\t\t// This might be normal for situations like closing Edit Views, where the menu will already exist in the main view.\n\t\t\tDebug.Warn( 'Context Menu Manager ('+ menu_attributes.id +') already exists for: '+ this.viewId +' ('+ this.ui_id +')', 'BaseViewController.js', 'BaseViewController', 'buildContextMenu', 10 );\n\t\t}\n\n\t\tthis.buildContextMenuModels();\n\t\tLocalCacheData.currentShownContextMenuName = this.context_menu_name ? this.context_menu_name : menu_attributes.parent_id;\n\n\t}\n\n\tgetContextMenuGroupByName( menu, name, name_prefix ) {\n\t\tvar group;\n\t\tif ( name_prefix == undefined ) {\n\t\t\tname_prefix = this.viewId;\n\t\t}\n\n\t\tfor ( var i = 0; i < menu.attributes.sub_menu_groups.length; i++ ) {\n\t\t\tif ( menu.attributes.sub_menu_groups[i].id == name_prefix + name ) {\n\t\t\t\tgroup = menu.attributes.sub_menu_groups[i];\n\t\t\t}\n\t\t}\n\n\t\treturn group;\n\t}\n\n\tonReportMenuClick( id ) {\n\t}\n\n\t//Overridden in ReportBaseViewController.\n\tonContextMenuClick( context_btn, menu_name ) {\n\t\t// Vue notes: Luckily when Vue calls this menu, it does not need context_btn, as most places that use this function have the Global.isSet( menu_name ) check to just use menu_name as the id. However, MessageControlVC does use it.\n\t\tvar id;\n\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( menu_name ) ) {\n\t\t\tid = menu_name;\n\t\t} else {\n\n\t\t\tif ( context_btn.disabled ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tProgressBar.showOverlay();\n\t\t//This flag is turned off in ProgressBarManager::closeOverlay, or 2 seconds whichever happens first. Use 2 seconds as overseas users could see intermittant 2 second latencies and double click Save icons.\n\t\tif ( window.clickProcessing == true ) {\n\t\t\treturn;\n\t\t} else {\n\t\t\twindow.clickProcessing = true;\n\t\t\twindow.clickProcessingHandle = window.setTimeout( function() {\n\t\t\t\t//FIXME: Check to see if the progress bar is visible because a API call is taking a long time, and if so keep the overlay up longer.\n\t\t\t\tif ( window.clickProcessing == true ) {\n\t\t\t\t\twindow.clickProcessing = false;\n\t\t\t\t\tProgressBar.closeOverlay();\n\t\t\t\t\tTTPromise.wait();\n\t\t\t\t}\n\t\t\t}, _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.calcDebounceWaitTimeBasedOnNetwork */ .x.calcDebounceWaitTimeBasedOnNetwork( 2000 ) );\n\t\t}\n\n\t\t//Debug.Text( 'Context Menu Click: '+ id, 'BaseViewController.js', 'BaseViewController', 'onContextMenuClick', 10 );\n\n\t\t/**\n\t\t * Here where you see ProgressBar.showOverlay() it is how we prevent doubleclick from firing two single clicks\n\t\t */\n\n\t\tswitch ( id ) {\n\t\t\tcase 'add':\n\t\t\t\tthis.onAddClick();\n\t\t\t\tbreak;\n\t\t\tcase 'view':\n\t\t\t\tthis.onViewClick();\n\t\t\t\tbreak;\n\t\t\tcase 'save':\n\t\t\t\tthis.onSaveClick();\n\t\t\t\tbreak;\n\t\t\tcase 'save_and_next':\n\t\t\t\tthis.onSaveAndNextClick();\n\t\t\t\tbreak;\n\t\t\tcase 'save_and_continue':\n\t\t\t\tthis.onSaveAndContinue();\n\t\t\t\tbreak;\n\t\t\tcase 'save_and_new':\n\t\t\t\tthis.onSaveAndNewClick();\n\t\t\t\tbreak;\n\t\t\tcase 'save_and_copy':\n\t\t\t\tthis.onSaveAndCopy();\n\t\t\t\tbreak;\n\t\t\tcase 'edit':\n\t\t\t\tthis.onEditClick();\n\t\t\t\tbreak;\n\t\t\tcase 'mass_edit':\n\t\t\t\tthis.onMassEditClick();\n\t\t\t\tbreak;\n\t\t\tcase 'delete_icon':\n\t\t\t\tthis.onDeleteClick();\n\t\t\t\tbreak;\n\t\t\tcase 'delete_and_next':\n\t\t\t\tthis.onDeleteAndNextClick();\n\t\t\t\tbreak;\n\t\t\tcase 'copy':\n\t\t\t\tthis.onCopyClick();\n\t\t\t\tbreak;\n\t\t\tcase 'copy_as_new':\n\t\t\t\tthis.onCopyAsNewClick();\n\t\t\t\tbreak;\n\t\t\tcase 'cancel':\n\t\t\t\tthis.onCancelClick();\n\t\t\t\tProgressBar.closeOverlay();\n\t\t\t\tbreak;\n\t\t\tcase 'export_excel':\n\t\t\t\tthis.onExportClick( 'export' + this.api.key_name );\n\t\t\t\tProgressBar.closeOverlay();\n\t\t\t\tbreak;\n\t\t\tcase 'map':\n\t\t\t\tthis.onMapClick();\n\t\t\t\tProgressBar.closeOverlay();\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tthis.onCustomContextClick( id, context_btn );\n\t\t\t\tProgressBar.closeOverlay(); //FIXME: This may be closing the overlay too soon, allowing double-clicks to get through. For example when in Request Authorizations and hammer clicking \"Authorize\".\n\t\t\t\t//Debug.Text( 'Context Menu Click: '+ id +' Overlay closing...', 'BaseViewController.js', 'BaseViewController', 'onContextMenuClick', 10 );\n\t\t\t\tbreak;\n\t\t}\n\n\t\t_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.triggerAnalyticsContextMenuClick */ .x.triggerAnalyticsContextMenuClick( context_btn, menu_name );\n\t}\n\n\tonCustomContextClick( id ) {\n\t\treturn false; //FALSE tells onContextMenuClick() to keep processing.\n\t}\n\n\tonNavigationClick( id ) {\n\t\tthis.onContextMenuClick( id );\n\t}\n\n\tgetCurrentAPI() {\n\t\treturn this.api;\n\t}\n\n\tsetCurrentEditViewState( state ) {\n\t\tthis.is_viewing = false;\n\t\tthis.is_viewing_detail = false; //Clicked \"View Detail\" on audit log. Separate logic from regular view.\n\t\tthis.is_edit = false;\n\t\tthis.is_add = false;\n\t\tthis.is_mass_editing = false;\n\t\tthis.is_mass_adding = false;\n\t\tswitch ( state ) {\n\t\t\tcase 'view':\n\t\t\t\tthis.is_viewing = true;\n\t\t\t\tbreak;\n\t\t\tcase 'view_detail':\n\t\t\t\tthis.is_viewing_detail = true;\n\t\t\t\tbreak;\n\t\t\tcase 'new':\n\t\t\t\tthis.is_add = true;\n\t\t\t\tbreak;\n\t\t\tcase 'edit':\n\t\t\t\tthis.is_edit = true;\n\t\t\t\tbreak;\n\t\t\tcase 'mass_edit':\n\t\t\t\tthis.is_mass_editing = true;\n\t\t\t\tbreak;\n\t\t\t// case 'mass_add':\n\t\t\t// \t//this.is_add = true;\n\t\t\t// \tthis.is_mass_adding = true;\n\t\t\t// \tbreak;\n\n\t\t}\n\n\t\tLocalCacheData.previous_doing_context_action = LocalCacheData.current_doing_context_action;\n\t\tLocalCacheData.current_doing_context_action = state;\n\t}\n\n\trevertEditViewState() {\n\t\tthis.setCurrentEditViewState( LocalCacheData.previous_doing_context_action ? LocalCacheData.previous_doing_context_action : '' );\n\t}\n\n\tonAddClick( show_save_and_continue ) {\n\t\tvar $this = this;\n\t\tthis.setCurrentEditViewState( 'new' );\n\t\t$this.openEditView();\n\t\t//Error: Uncaught TypeError: undefined is not a function in /interface/html5/views/BaseViewController.js?v=8.0.0-20141117-111140 line 897\n\t\tif ( $this.api && typeof $this.api['get' + $this.api.key_name + 'DefaultData'] === 'function' ) {\n\t\t\t$this.api['get' + $this.api.key_name + 'DefaultData']( {\n\t\t\t\tonResult: function( result ) {\n\t\t\t\t\t$this.onAddResult( result );\n\t\t\t\t\tif ( show_save_and_continue ) {\n\t\t\t\t\t\t//Issue #3111 - If user is on a subview the tab will appear blank and the Save and Continue button will not show unless user switches to another tab.\n\t\t\t\t\t\t//Because of that when coming from a \"Save & New\" action, we need to make sure to show the Save and Continue button.\n\t\t\t\t\t\t$this.showSaveAndContinueButton();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} );\n\t\t}\n\t}\n\n\tonAddResult( result ) {\n\t\tvar $this = this;\n\t\tvar result_data = {};\n\n\t\tif ( result.getResult ) {\n\t\t\tresult_data = result.getResult();\n\t\t} else {\n\t\t\t//if not an api result, assume object is already the result of a call to getResult() and we will use it verbatim.\n\t\t\t//useful for passing in default values when adding new records before this function is called.\n\t\t\tresult_data = result;\n\t\t}\n\n\t\tif ( !result_data || result_data === true ) {\n\t\t\tresult_data = [];\n\t\t}\n\n\t\tresult_data.company = LocalCacheData.current_company.name;\n\n\t\tif ( $this.sub_view_mode && $this.parent_key ) {\n\t\t\tresult_data[$this.parent_key] = $this.parent_value;\n\t\t}\n\n\t\t$this.current_edit_record = result_data;\n\t\t$this.initEditView();\n\t}\n\n\tonDeleteAndNextClick() {\n\t\tTAlertManager.showConfirmAlert( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.delete_confirm_message */ .x.delete_confirm_message, null, function( result ) {\n\t\t\t// Using an anonymous function instead of reference, to ensure during debugging it is clear this function is called from DeleteAndNext, and not just Delete.\n\t\t\tthis.doDeleteClick( result, 'delete_and_next' );\n\t\t}.bind( this ) );\n\t}\n\n\tresetNavigationSourceData() {\n\t}\n\n\tgetDeleteSelectedRecordId() {\n\t\tvar retval = [];\n\t\tif ( this.edit_view && this.current_edit_record ) {\n\t\t\tretval.push( this.current_edit_record.id );\n\t\t} else {\n\t\t\tvar grid_selected_id_array = this.getGridSelectIdArray().slice(); //Use .slice() to make a copy of the IDs.\n\t\t\tif ( grid_selected_id_array.length ) {\n\t\t\t\tretval = grid_selected_id_array;\n\t\t\t} else {\n\t\t\t\tretval = null;\n\t\t\t}\n\n\t\t}\n\t\treturn retval;\n\t}\n\n\tdoDeleteClick( result, delete_type ) {\n\t\tif ( result ) {\n\t\t\tProgressBar.showOverlay();\n\t\t\tvar remove_ids = this.getDeleteSelectedRecordId();\n\t\t\tif ( remove_ids === [] ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis.setCurrentEditViewState( delete_type ? delete_type : 'delete' );\n\t\t\treturn this.doDeleteAPICall( remove_ids );\n\n\t\t} else {\n\t\t\tProgressBar.closeOverlay();\n\t\t}\n\t}\n\n\tdoDeleteAPICall( remove_ids, callback ) {\n\t\tvar current_api = this.getCurrentAPI();\n\n\t\tif ( !callback ) {\n\t\t\tcallback = {\n\t\t\t\tonResult: function( result ) {\n\t\t\t\t\tthis.onDeleteResult( result, remove_ids );\n\t\t\t\t}.bind( this )\n\t\t\t};\n\t\t}\n\t\treturn current_api['delete' + current_api.key_name]( remove_ids, callback );\n\t}\n\n\tonDeleteClick() {\n\t\tTAlertManager.showConfirmAlert( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.delete_confirm_message */ .x.delete_confirm_message, null, this.doDeleteClick.bind( this ) );\n\t}\n\n\tonDeleteResult( result, remove_ids ) {\n\t\tvar $this = this;\n\t\tProgressBar.closeOverlay();\n\t\tif ( result.isValid() ) {\n\n\t\t\tif ( LocalCacheData.current_doing_context_action === 'delete_and_next' ) {\n\t\t\t\t// store the index of the current item, before refreshing the search and losing the current context due to the deleted records\n\t\t\t\t$this.refresh_id = this.navigation.getNextSelectItemId();\n\n\t\t\t\t// refresh the grid to get the current dataset now that records have been deleted\n\t\t\t\t$this.search( false, null, null, function( result ) {\n\t\t\t\t\tvar current_grid_source = result.getResult();\n\n\t\t\t\t\tif ( $.type( current_grid_source ) !== 'array' || current_grid_source.length < 1 ) {\n\t\t\t\t\t\t// if after delete, there are no more records in the search, close edit view\n\t\t\t\t\t\t$this.removeEditView();\n\t\t\t\t\t\t$this.setDefaultMenu();\n\t\t\t\t\t\t// TODO: Should the above not simulate a cancel click? Could be an area for further refactor.\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// there are still records, load the new data\n\t\t\t\t\t\t$this.navigation.setSourceData( current_grid_source );\n\t\t\t\t\t\t$this.navigation.setPagerData( $this.pager_data );\n\n\t\t\t\t\t\t// if there is a valid id on the next record to load, do it\n\t\t\t\t\t\tif ( $this.refresh_id ) {\n\t\t\t\t\t\t\t$this.onRightOrLeftArrowClickCallBack( $this.refresh_id );\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// no valid next record, simulate a cancel click.\n\t\t\t\t\t\t\t$this.onCancelClick();\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t$this.onDeleteAndNextDone( result );\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t} else {\n\t\t\t\t$this.search();\n\t\t\t\t$this.onDeleteDone( result );\n\t\t\t\tif ( $this.edit_view && LocalCacheData.current_doing_context_action === 'delete' ) {\n\t\t\t\t\t$this.removeEditView();\n\t\t\t\t\t$this.setDefaultMenu();\n\t\t\t\t} else if ( !$this.edit_view ) {\n\t\t\t\t\t$this.setCurrentEditViewState( '' );\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\t// If some valid records were deleted, we need to refresh the search grid.\n\t\t\tif ( result.getRecordDetails().valid && result.getRecordDetails().valid > 0 ) {\n\t\t\t\t$this.search();\n\t\t\t}\n\t\t\t$this.revertEditViewState();\n\t\t\tTAlertManager.showErrorAlert( result );\n\t\t}\n\t}\n\n\tremoveDeletedRows( remove_ids ) {\n\t\tvar $this = this;\n\t\t$.each( remove_ids, function( index, value ) {\n\t\t\t$this.grid.grid.deleteRow( value );\n\t\t\t$this.paging_widget.minus();\n\n\t\t} );\n//\n//\t\tif ( this.grid.getGridParam( 'data' ).length === 0 ) {\n//\t\t\tthis.search();\n//\t\t}\n\n//\t\tthis.search();\n\n//\t\tvar grid_selected_id_array = this.getGridSelectIdArray();\n//\t\tvar grid_selected_length = grid_selected_id_array.length;\n//\n//\t\tif ( grid_selected_length === 0 ) {\n//\t\t\tthis.search();\n//\t\t}\n\t}\n\n\tclearNavigationData() {\n\t\tif ( this.navigation && this.navigation.setSourceData ) {\n\t\t\tthis.navigation.setSourceData( null );\n\t\t}\n\t}\n\n\tonSaveAndCopy( ignoreWarning ) {\n\t\tvar $this = this;\n\t\tif ( !_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( ignoreWarning ) ) {\n\t\t\tignoreWarning = false;\n\t\t}\n\t\tthis.is_add = true;\n\t\tthis.is_changed = false;\n\t\tLocalCacheData.current_doing_context_action = 'save_and_copy';\n\t\tvar record = this.current_edit_record;\n\t\trecord = this.uniformVariable( record );\n\n\t\tthis.clearNavigationData();\n\t\tthis.api['set' + this.api.key_name]( record, false, ignoreWarning, {\n\t\t\tonResult: function( result ) {\n\t\t\t\t$this.onSaveAndCopyResult( result );\n\t\t\t\t$this.clearSubViewControllers();\n\t\t\t}\n\t\t} );\n\t}\n\n\tonSaveAndCopyResult( result ) {\n\t\tvar $this = this;\n\t\tif ( result.isValid() ) {\n\t\t\tvar result_data = result.getResult();\n\t\t\tif ( result_data === true && $this.current_edit_record && $this.current_edit_record.id ) {\n\t\t\t\t$this.refresh_id = $this.current_edit_record.id;\n\t\t\t} else if ( TTUUID.isUUID( result_data ) && result_data != TTUUID.zero_id && result_data != TTUUID.not_exist_id ) {\n\t\t\t\t$this.refresh_id = result_data;\n\t\t\t}\n\t\t\t$this.search( false );\n\t\t\t$this.onCopyAsNewClick();\n\t\t} else {\n\t\t\t$this.setErrorMenu();\n\t\t\t$this.setErrorTips( result );\n\n\t\t}\n\t}\n\n\tonSaveAndNewClick( ignoreWarning ) {\n\t\tvar $this = this;\n\t\tif ( !_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( ignoreWarning ) ) {\n\t\t\tignoreWarning = false;\n\t\t}\n\t\tthis.setCurrentEditViewState( 'new' );\n\t\tvar record = this.current_edit_record;\n\t\trecord = this.uniformVariable( record );\n\t\tthis.api['set' + this.api.key_name]( record, false, ignoreWarning, {\n\t\t\tonResult: function( result ) {\n\t\t\t\t$this.onSaveAndNewResult( result );\n\t\t\t\tif ( $this.sub_view_mode ) {\n\t\t\t\t\t$this.clearSubViewControllers( false );\n\t\t\t\t} else {\n\t\t\t\t\t$this.clearSubViewControllers( true );\n\t\t\t\t\t$this.showSaveAndContinueButton();\n\t\t\t\t}\n\t\t\t}\n\t\t} );\n\t}\n\n\tonSaveAndNewResult( result ) {\n\t\tvar $this = this;\n\t\tif ( result.isValid() ) {\n\t\t\tvar result_data = result.getResult();\n\t\t\tif ( result_data === true && $this.current_edit_record && $this.current_edit_record.id ) {\n\t\t\t\t$this.refresh_id = $this.current_edit_record.id;\n\n\t\t\t} else if ( TTUUID.isUUID( result_data ) && result_data != TTUUID.zero_id && result_data != TTUUID.not_exist_id ) { // as new\n\t\t\t\t$this.refresh_id = result_data;\n\t\t\t}\n\n\t\t\t$this.saveInsideEditorData( function() {\n\t\t\t\t$this.search( false );\n\t\t\t\t$this.onAddClick( true );\n\t\t\t} );\n\t\t} else {\n\t\t\t$this.setErrorMenu();\n\t\t\t$this.setErrorTips( result );\n\n\t\t}\n\t}\n\n\tonSaveAndContinue( ignoreWarning ) {\n\t\tvar $this = this;\n\t\tif ( !_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( ignoreWarning ) ) {\n\t\t\tignoreWarning = false;\n\t\t}\n\t\t//Setting is_add false too early can cause determineContextMenuMountAttributes() to have unexpected side effects. However not setting it here might have other side effects.\n\t\t//$this.is_add = false;\n\t\tLocalCacheData.current_doing_context_action = 'save_and_continue';\n\t\tvar record = this.current_edit_record;\n\t\trecord = this.uniformVariable( record );\n\n\t\tthis.doSaveAPICall( record, ignoreWarning, {\n\t\t\tonResult: function( result ) {\n\t\t\t\t$this.onSaveAndContinueResult( result );\n\n\t\t\t}\n\t\t} );\n\t}\n\n\tonSaveAndContinueResult( result ) {\n\t\tvar $this = this;\n\t\tif ( result.isValid() ) {\n\t\t\tvar result_data = result.getResult();\n\t\t\tif ( result_data === true && $this.current_edit_record && $this.current_edit_record.id ) {\n\t\t\t\t$this.refresh_id = $this.current_edit_record.id;\n\n\t\t\t} else if ( result_data && TTUUID.isUUID( result_data ) && result_data != TTUUID.zero_id && result_data != TTUUID.not_exist_id ) {\n\t\t\t\t$this.refresh_id = result_data;\n\n\t\t\t}\n\n\t\t\t$this.saveInsideEditorData( function() {\n\t\t\t\t$this.search( false );\n\t\t\t\t$this.onEditClick( $this.refresh_id, true );\n\t\t\t\t$this.onSaveAndContinueDone( result );\n\t\t\t} );\n\n\t\t} else {\n\t\t\t$this.setErrorTips( result );\n\t\t\t$this.setErrorMenu();\n\t\t}\n\t}\n\n\tonSaveAndNextClick( ignoreWarning ) {\n\t\tvar $this = this;\n\t\tif ( !_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( ignoreWarning ) ) {\n\t\t\tignoreWarning = false;\n\t\t}\n\t\tthis.is_add = false;\n\t\tthis.is_changed = false;\n\n\t\tvar current_api = this.getCurrentAPI();\n\t\tvar record = this.current_edit_record;\n\t\tLocalCacheData.current_doing_context_action = 'save_and_next';\n\t\trecord = this.uniformVariable( record );\n\t\tcurrent_api['set' + current_api.key_name]( record, false, ignoreWarning, {\n\t\t\tonResult: function( result ) {\n\t\t\t\t$this.onSaveAndNextResult( result );\n\n\t\t\t}\n\t\t} );\n\t}\n\n\tonSaveAndNextResult( result ) {\n\t\tvar $this = this;\n\t\tif ( result.isValid() ) {\n\t\t\tvar result_data = result.getResult();\n\t\t\tif ( result_data === true && $this.current_edit_record && $this.current_edit_record.id ) {\n\t\t\t\t$this.refresh_id = $this.current_edit_record.id;\n\t\t\t} else if ( result_data && TTUUID.isUUID( result_data ) && result_data != TTUUID.zero_id && result_data != TTUUID.not_exist_id ) {\n\t\t\t\t$this.refresh_id = result_data;\n\t\t\t}\n\n\t\t\t$this.saveInsideEditorData( function() {\n\t\t\t\t$this.onRightArrowClick();\n\t\t\t\t$this.search( false );\n\t\t\t\t$this.onSaveAndNextDone( result );\n\t\t\t} );\n\n\t\t} else {\n\t\t\t$this.setErrorMenu();\n\t\t\t$this.setErrorTips( result );\n\n\t\t}\n\t}\n\n\tuniformVariable( records ) {\n\t\treturn records;\n\t}\n\n\tsaveInsideEditorData( callback ) {\n\t\t//override this stub function where neeed. Brought in to consolidate those view controllers that used this.\n\t\t/* Dev Note: #2644 If issues happen, read this:\n\t\t * Functions such as onSaveAndNextResult() had a saveInsideEditorData call, but the base view did not, but the rest of the function was the same.\n\t\t * During refactor of these functions like save and next result into the base view, a stub of saveInsideEditor had to be created as it was not there previously.\n\t\t */\n\n\t\tif ( callback ) {\n\t\t\tcallback();\n\t\t}\n\t}\n\n\tgetChangedFields() {\n\t\tvar retval = {};\n\t\tfor ( var key in this.edit_view_ui_dic ) {\n\t\t\tif ( !this.edit_view_ui_dic.hasOwnProperty( key ) ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tvar widget = this.edit_view_ui_dic[key];\n\n\t\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( widget.isChecked ) ) {\n\t\t\t\tif ( widget.isChecked() && widget.getEnabled() ) {\n\t\t\t\t\tretval[key] = this.current_edit_record[key]; // Note: Some view controllers use widget.getValue() instead of current_edit_record[key]\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn retval;\n\t}\n\n\t// overridden in view controllers where needed\n\t// this base version will simply extract and duplicate current edit record if an array of user_id's exist\n\t// parent function should check to confirm this.is_mass_adding is true\n\tbuildMassAddRecord( record ) {\n\t\tvar retval;\n\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isArray */ .x.isArray( record.user_id ) && record.user_id.length > 0 ) {\n\t\t\tretval = [];\n\t\t\t$.each( this.current_edit_record.user_id, function( index, value ) {\n\n\t\t\t\tvar commonRecord = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.clone */ .x.clone( record );\n\t\t\t\tcommonRecord.user_id = value;\n\t\t\t\tretval.push( commonRecord );\n\n\t\t\t} );\n\t\t} else {\n\t\t\tretval = record;\n\t\t}\n\n\t\treturn retval;\n\t}\n\n\tbuildMassEditSaveRecord( mass_edit_record_ids, changed_fields ) {\n\t\tvar $this = this;\n\t\tvar mass_records = [];\n\n\t\t$.each( mass_edit_record_ids, function( index, value ) {\n\t\t\tvar common_record = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.clone */ .x.clone( changed_fields );\n\t\t\tcommon_record.id = value;\n\t\t\tcommon_record = $this.uniformVariable( common_record );\n\t\t\tmass_records.push( common_record );\n\t\t} );\n\n\t\treturn mass_records;\n\t}\n\n\tonSaveClick( ignoreWarning ) {\n\t\tif ( !_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( ignoreWarning ) ) {\n\t\t\tignoreWarning = false;\n\t\t}\n\n\t\tvar record;\n\t\t//Setting is_add false too early can cause determineContextMenuMountAttributes() to have unexpected side effects. However not setting it here might have other side effects.\n\t\t//this.is_add = false;\n\t\tLocalCacheData.current_doing_context_action = 'save';\n\n\t\tif ( this.is_mass_editing ) {\n\t\t\tvar changed_fields = this.getChangedFields();\n\t\t\trecord = this.buildMassEditSaveRecord( this.mass_edit_record_ids, changed_fields );\n\n\t\t} else if ( this.is_mass_adding ) {\n\t\t\trecord = this.buildMassAddRecord( this.current_edit_record );\n\n\t\t} else {\n\t\t\trecord = this.current_edit_record;\n\t\t\trecord = this.uniformVariable( record );\n\t\t}\n\n\t\tthis.doSaveAPICall( record, ignoreWarning );\n\t}\n\n\tdoSaveAPICall( record, ignoreWarning, callback ) {\n\t\tvar current_api = this.getCurrentAPI();\n\n\t\tif ( !callback ) {\n\t\t\tcallback = {\n\t\t\t\tonResult: function( result ) {\n\t\t\t\t\tthis.onSaveResult( result );\n\t\t\t\t}.bind( this )\n\t\t\t};\n\t\t}\n\n\t\t//current_api.setIsIdempotent( true ); //Force to idempotent API call to avoid duplicate network requests from causing errors displayed to the user.\n\t\treturn current_api['set' + current_api.key_name]( record, false, ignoreWarning, callback );\n\t}\n\n\tonSaveResult( result ) {\n\t\tvar $this = this;\n\t\tif ( result.isValid() ) {\n\t\t\t//Setting is_add false too early can cause determineContextMenuMountAttributes() to have unexpected side effects. However not setting it here might have other side effects.\n\t\t\t//$this.is_add = false;\n\t\t\tvar result_data = result.getResult();\n\t\t\tif ( !this.edit_only_mode ) {\n\t\t\t\tif ( result_data === true && $this.current_edit_record && $this.current_edit_record.id ) {\n\t\t\t\t\t$this.refresh_id = $this.current_edit_record.id;\n\t\t\t\t} else if ( TTUUID.isUUID( result_data ) && result_data != TTUUID.zero_id && result_data != TTUUID.not_exist_id ) {\n\t\t\t\t\t$this.refresh_id = result_data;\n\t\t\t\t} else {\n\t\t\t\t\t$this.refresh_id = null;\n\t\t\t\t}\n\n\t\t\t\t$this.search();\n\t\t\t}\n\n\t\t\tvar on_save_done_result = $this.onSaveDone( result ); //post hook for onSaveResult\n\t\t\tif ( on_save_done_result == undefined || on_save_done_result == true ) {\n\t\t\t\t$this.removeEditView();\n\t\t\t}\n\t\t} else {\n\t\t\t$this.setErrorTips( result );\n\t\t\t$this.setErrorMenu();\n\t\t}\n\t}\n\n\t//post hook for onSaveResult\n\tonSaveDone( result ) {\n\t\treturn true;\n\t}\n\n\tonSaveAndContinueDone( result ) {\n\t}\n\n\tonSaveAndNextDone( result ) {\n\t}\n\n\tonDeleteDone( result ) {\n\t\tthis.removeDeletedRows();\n\t}\n\n\tonDeleteAndNextDone( result ) {\n\t}\n\n\tonMassEditClick() {\n\n\t\tvar $this = this;\n\t\tthis.setCurrentEditViewState( 'mass_edit' );\n\t\t$this.openEditView();\n\t\tvar filter = {};\n\t\tvar grid_selected_id_array = this.getGridSelectIdArray();\n\t\tvar grid_selected_length = grid_selected_id_array.length;\n\t\tthis.mass_edit_record_ids = [];\n\n\t\t$.each( grid_selected_id_array, function( index, value ) {\n\t\t\t$this.mass_edit_record_ids.push( value );\n\t\t} );\n\n\t\tfilter.filter_data = {};\n\t\tfilter.filter_data.id = this.mass_edit_record_ids;\n\n\t\tthis.api['getCommon' + this.api.key_name + 'Data']( filter, {\n\t\t\tonResult: function( result ) {\n\t\t\t\tvar result_data = result.getResult();\n\n\t\t\t\tif ( !result_data ) {\n\t\t\t\t\tresult_data = [];\n\t\t\t\t}\n\n\t\t\t\t$this.api['getOptions']( 'unique_columns', {\n\t\t\t\t\tonResult: function( result ) {\n\t\t\t\t\t\t$this.unique_columns = result.getResult();\n\t\t\t\t\t\t$this.api['getOptions']( 'linked_columns', {\n\t\t\t\t\t\t\tonResult: function( result1 ) {\n\t\t\t\t\t\t\t\t$this.linked_columns = result1.getResult();\n\t\t\t\t\t\t\t\tif ( $this.linked_columns === true ) {\n\t\t\t\t\t\t\t\t\t//there are no columns, you should be an empty array.\n\t\t\t\t\t\t\t\t\t$this.linked_columns = [];\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif ( $this.sub_view_mode && $this.parent_key ) {\n\t\t\t\t\t\t\t\t\tresult_data[$this.parent_key] = $this.parent_value;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t$this.current_edit_record = result_data;\n\t\t\t\t\t\t\t\t$this.initEditView();\n\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} );\n\n\t\t\t\t\t}\n\t\t\t\t} );\n\n\t\t\t}\n\t\t} );\n\t}\n\n\t/*\n\t * View Click handlers - Start\n\t */\n\tgetViewSelectedRecordId( record ) {\n\t\tvar retval = false;\n\t\tvar grid_selected_id_array = this.getGridSelectIdArray();\n\t\tvar grid_selected_length = grid_selected_id_array.length;\n\n\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( record ) ) {\n\t\t\t//Handle cases where record object is passed in, so we can extract the string ID.\n\t\t\t// As well where the string ID is passed in directly as a UUID and accept that too.\n\t\t\t// This is required to handle MyAccount -> Request Authorization, view any record, then refresh the browser.\n\t\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isObject */ .x.isObject( record ) && record.id ) {\n\t\t\t\tretval = record.id;\n\t\t\t} else if ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isString */ .x.isString( record ) && TTUUID.isUUID( record ) ) {\n\t\t\t\tretval = record;\n\t\t\t}\n\t\t} else {\n\t\t\tif ( grid_selected_length > 0 ) {\n\t\t\t\tretval = grid_selected_id_array[0];\n\t\t\t} else {\n\t\t\t\tretval = null;\n\t\t\t}\n\t\t}\n\n\t\treturn retval;\n\t}\n\n\tdoViewAPICall( filter, api_args ) {\n\t\tvar callback = { onResult: this.handleViewAPICallbackResult.bind( this ) };\n\t\tif ( api_args ) {\n\t\t\t// If api_args specified, use api_args.filter, and ignore function filter parameter.\n\t\t\tapi_args.push( callback );\n\t\t\treturn this.api['get' + this.api.key_name].apply( this.api, api_args );\n\t\t} else {\n\t\t\treturn this.api['get' + this.api.key_name]( filter, callback );\n\t\t}\n\t}\n\n\thandleViewAPICallbackResult( result ) {\n\t\tvar result_data;\n\t\tif ( result && result.getResult ) {\n\t\t\tresult_data = result.getResult();\n\n\t\t\t//Do any result manipulation processes here, such as combining IDs together into a composite.\n\t\t\tresult_data = this.processAPICallbackResult( result_data );\n\n\t\t\tif ( !result_data ) {\n\t\t\t\tresult_data = [];\n\t\t\t}\n\n\t\t\tresult_data = result_data[0];\n\t\t} else {\n\t\t\t//Do not call processAPICallbackResult() here as we assume all processing has been completed earlier.\n\t\t\tresult_data = result;\n\t\t}\n\n\t\tif ( !result_data ) {\n\t\t\tTAlertManager.showAlert( $.i18n._( 'Record does not exist.' ) );\n\t\t\treturn this.onCancelClick();\n\t\t} else {\n\t\t\treturn this.doViewClickResult( result_data );\n\t\t}\n\t}\n\n\tdoViewClickResult( result_data ) {\n\t\tthis.current_edit_record = result_data;\n\t\tthis.initEditView();\n\t\treturn this.clearCurrentSelectedRecord();\n\t}\n\n\tonViewClick( record, noRefreshUI ) {\n\t\tthis.setCurrentEditViewState( 'view' );\n\t\tthis.openEditView();\n\n\t\tvar record_id = this.getViewSelectedRecordId( record );\n\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isFalseOrNull */ .x.isFalseOrNull( record_id ) ) {\n\t\t\treturn;\n\t\t}\n\t\tthis.setCurrentSelectedRecord( record_id );\n\n\t\tvar filter = this.getAPIFilters();\n\n\t\treturn this.doViewAPICall( filter );\n\t}\n\n\tsetCurrentSelectedRecord( record ) {\n\t\tif ( record ) {\n\t\t\tthis.current_selected_record = record;\n\t\t\treturn true;\n\t\t}\n\n\t\treturn false;\n\t}\n\n\tgetCurrentSelectedRecord() {\n\t\treturn this.current_selected_record;\n\t}\n\n\tclearCurrentSelectedRecord() {\n\t\tdelete this.current_selected_record;\n\t\treturn true;\n\t}\n\n\t// do we need this, Mike created it but check with him, as it may have just been a potential idea, not used.\n\tgetRecordIdFromRecord( object ) {\n\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isObject */ .x.isObject( object ) ) {\n\t\t\treturn object_id;\n\t\t} else if ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isString */ .x.isString( object ) ) {\n\t\t\treturn object;\n\t\t}\n\n\t\treturn false;\n\t}\n\n\t/*\n\t * View Click handlers - End\n\t */\n\n\t/*\n\t * Common between View and Edit\n\t */\n\tprocessAPICallbackResult( result_data ) {\n\t\treturn result_data;\n\t}\n\n\tgetAPIFilters() {\n\t\t// override this function if view requires more filters\n\t\tvar record_id = this.getCurrentSelectedRecord();\n\t\tvar filter = {};\n\n\t\tfilter.filter_data = {};\n\t\tfilter.filter_data.id = [record_id];\n\n\t\treturn filter;\n\t}\n\n\t/*\n\t * Edit Click handlers - Start\n\t */\n\tgetEditSelectedRecordId( record ) {\n\t\tvar retval = false;\n\t\tvar grid_selected_id_array = this.getGridSelectIdArray();\n\t\tvar grid_selected_length = grid_selected_id_array.length;\n\n\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( record ) ) {\n\t\t\t//Handle cases where record object is passed in, so we can extract the string ID.\n\t\t\t// As well where the string ID is passed in directly as a UUID and accept that too.\n\t\t\t// This is required to handle editing any record, then refresh the browser.\n\t\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isObject */ .x.isObject( record ) && record.id ) {\n\t\t\t\tretval = record.id;\n\t\t\t} else if ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isString */ .x.isString( record ) && TTUUID.isUUID( record ) ) {\n\t\t\t\tretval = record;\n\t\t\t}\n\t\t} else {\n\t\t\t//Check for is_viewing and is_edit as the state may have changed from viewing to editing immediately before it got here.\n\t\t\t// Test this with: Attendance -> TimeSheet, Edit Punch, click Station field to view the station, then click \"Edit\" icon.\n\t\t\tif ( ( this.is_viewing || this.is_edit ) && this.current_edit_record && this.current_edit_record.id ) {\n\t\t\t\tretval = this.current_edit_record.id;\n\t\t\t} else if ( grid_selected_length > 0 ) {\n\t\t\t\tretval = grid_selected_id_array[0];\n\t\t\t} else {\n\t\t\t\tretval = null;\n\t\t\t}\n\t\t}\n\t\treturn retval;\n\t}\n\n\tdoEditAPICall( filter, api_args, callback ) {\n\t\tif ( !callback ) {\n\t\t\tcallback = { onResult: this.handleEditAPICallbackResult.bind( this ) };\n\t\t}\n\t\tif ( api_args ) {\n\t\t\t// If api_args specified, use api_args.filter, and ignore function filter parameter.\n\t\t\tapi_args.push( callback );\n\t\t\treturn this.api['get' + this.api.key_name].apply( this.api, api_args );\n\t\t} else {\n\t\t\treturn this.api['get' + this.api.key_name]( filter, callback );\n\t\t}\n\t}\n\n\thandleEditAPICallbackResult( result ) {\n\t\tvar result_data;\n\t\tif ( result.getResult ) {\n\t\t\tresult_data = result.getResult();\n\n\t\t\t//Do any result manipulation processes here, such as combining IDs together into a composite.\n\t\t\tresult_data = this.processAPICallbackResult( result_data );\n\n\t\t\tif ( !result_data ) {\n\t\t\t\tresult_data = [];\n\t\t\t}\n\n\t\t\tresult_data = result_data[0];\n\t\t} else {\n\t\t\t//Do not call processAPICallbackResult() here as we assume all processing has been completed earlier.\n\t\t\tresult_data = result;\n\t\t}\n\t\tif ( !result_data ) {\n\t\t\tTAlertManager.showAlert( $.i18n._( 'Record does not exist.' ) );\n\t\t\treturn this.onCancelClick();\n\t\t}\n\n\t\tif ( this.sub_view_mode && this.parent_key ) {\n\t\t\tresult_data[this.parent_key] = this.parent_value;\n\t\t}\n\t\treturn this.doEditClickResult( result_data );\n\t}\n\n\tdoEditClickResult( result_data ) {\n\t\tthis.current_edit_record = result_data;\n\t\tthis.initEditView();\n\t}\n\n\tonEditClick( record_id, noRefreshUI ) {\n\t\tthis.setCurrentEditViewState( 'edit' );\n\t\tthis.openEditView();\n\n\t\trecord_id = this.getEditSelectedRecordId( record_id );\n\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isFalseOrNull */ .x.isFalseOrNull( record_id ) ) {\n\t\t\treturn;\n\t\t}\n\t\tthis.setCurrentSelectedRecord( record_id );\n\n\t\tvar filter = this.getAPIFilters();\n\n\t\treturn this.doEditAPICall( filter );\n\t}\n\n\t/*\n\t * Edit Click handlers - End\n\t */\n\n\tonCopyClick() {\n\t\tif ( this.getGridSelectIdArray().length > 1 ) {\n\t\t\t//Warn user if they are trying to copy multiple records.\n\t\t\tTAlertManager.showConfirmAlert( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.copy_multiple_confirm_message */ .x.copy_multiple_confirm_message, null, ( answer ) => {\n\t\t\t\tif ( answer === true ) {\n\t\t\t\t\tthis.doCopyClick();\n\t\t\t\t}\n\t\t\t} );\n\t\t} else {\n\t\t\tthis.doCopyClick();\n\t\t}\n\t}\n\n\tdoCopyClick() {\n\t\tvar $this = this;\n\t\tvar copyIds = [];\n\t\t$this.is_add = false;\n\t\tif ( $this.edit_view ) {\n\t\t\tcopyIds.push( $this.current_edit_record.id );\n\t\t\tif ( this.is_changed ) {\n\t\t\t\tTAlertManager.showConfirmAlert( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.modify_alert_message */ .x.modify_alert_message, null, function( flag ) {\n\t\t\t\t\tif ( flag === true ) {\n\t\t\t\t\t\t$this.is_changed = false;\n\t\t\t\t\t\t$this._continueDoCopy( copyIds );\n\t\t\t\t\t}\n\t\t\t\t\tProgressBar.closeOverlay();\n\t\t\t\t} );\n\t\t\t} else {\n\t\t\t\t$this._continueDoCopy( copyIds );\n\t\t\t}\n\t\t} else {\n\t\t\tcopyIds = $this.getGridSelectIdArray().slice();\n\t\t\t$this._continueDoCopy( copyIds );\n\t\t}\n\t}\n\n\t_continueDoCopy( copyIds ) {\n\t\tvar $this = this;\n\t\tProgressBar.showOverlay();\n\n\t\t//$this.api.setIsIdempotent( true ); //Force to idempotent API call to avoid duplicate network requests from causing errors displayed to the user.\n\t\t$this.api['copy' + $this.api.key_name]( copyIds, {\n\t\t\tonResult: function( result ) {\n\t\t\t\t$this.onCopyResult( result );\n\n\t\t\t}\n\t\t} );\n\t}\n\n\tonCopyResult( result ) {\n\t\tvar $this = this;\n\n\t\tif ( result.isValid() ) {\n\t\t\t$this.search();\n\t\t\tif ( $this.edit_view ) {\n\t\t\t\t$this.removeEditView();\n\t\t\t}\n\n\t\t} else {\n\n\t\t\tTAlertManager.showErrorAlert( result );\n\n\t\t\tif ( result.getRecordDetails().total > 1 ) {\n\t\t\t\t$this.search();\n\t\t\t}\n\t\t}\n\t}\n\n\tonCopyAsNewClick() {\n\t\tvar $this = this;\n\t\tif ( this.is_changed ) {\n\t\t\tTAlertManager.showConfirmAlert( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.modify_alert_message */ .x.modify_alert_message, null, function( flag ) {\n\t\t\t\tif ( flag === true ) {\n\t\t\t\t\t$this._continueDoCopyAsNew();\n\t\t\t\t\tif ( $this.sub_view_mode ) {\n\t\t\t\t\t\t$this.clearSubViewControllers( false );\n\t\t\t\t\t} else {\n\t\t\t\t\t\t//Issue #3009 - Copy as new could cause blank tabs or old data to be shown instead of Save and Continue button.\n\t\t\t\t\t\t$this.clearSubViewControllers( true );\n\t\t\t\t\t\t$this.showSaveAndContinueButton();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tProgressBar.closeOverlay();\n\t\t\t} );\n\t\t} else {\n\t\t\tthis._continueDoCopyAsNew();\n\t\t\tif ( this.sub_view_mode ) {\n\t\t\t\tthis.clearSubViewControllers( false );\n\t\t\t} else {\n\t\t\t\t//Issue #3009 - Copy as new could cause blank tabs or old data to be shown instead of Save and Continue button.\n\t\t\t\tthis.clearSubViewControllers( true );\n\t\t\t\tthis.showSaveAndContinueButton();\n\t\t\t}\n\t\t}\n\t}\n\n\tcopyAsNewResetIds( data ) {\n\t\t//override where needed.\n\t\tdata.id = '';\n\t\treturn data;\n\t}\n\n\tshowSaveAndContinueButton() {\n\t\tif ( this.edit_view ) {\n\t\t\tlet save_and_continue_buttons = this.edit_view.find( '.save-and-continue-div' );\n\t\t\tif ( save_and_continue_buttons ) {\n\t\t\t\tsave_and_continue_buttons.css( 'display', 'block' );\n\t\t\t}\n\t\t}\n }\n\n\tclearSubViewControllers( force ) {\n\t\t//Issue #2915 - Sub view controllers should not be cleared while the user is on a sub view. For example when the user\n\t\t//clicks \"Copy as New\" on a record in the sub view and finishes using that sub view they are returned to\n\t\t//the primary controller and if data is wiped in that scenario the tab would be blank.\n\t\tif ( LocalCacheData.current_open_sub_controller == null || force ) {\n\t\t\t//Issue #2913 - Sub view data would remain on a view if a user viewed a sub view tab before clicking \"Copy as New\", \"Save & New\" and similar saving actions.\n\t\t\t//Clearing out the sub view controllers aims to prevent any old data from remaining.\n\t\t\t//If this does not happen the sub view HTML would remain and overlap with the \"Save & Continue\" message and in general show no longer relevant data.\n\t\t\tfor ( var property in LocalCacheData.current_open_primary_controller ) {\n\t\t\t\tif ( property.match( 'sub_([a-z_]*)view_controller' ) && LocalCacheData.current_open_primary_controller[property] && LocalCacheData.current_open_primary_controller[property].$el ) {\n\t\t\t\t\tDebug.Text( property, 'BaseViewController.js', 'BaseViewController', 'onSaveAndNextClick', 9 );\n\t\t\t\t\tLocalCacheData.current_open_primary_controller[property].$el.remove();\n\t\t\t\t\tLocalCacheData.current_open_primary_controller[property] = null;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tgetCopyAsNewFilter( filter ) {\n\t\t// override where needed.\n\t\treturn filter;\n\t}\n\n\t_continueDoCopyAsNew() {\n\t\tvar $this = this;\n\t\tthis.setCurrentEditViewState( 'new' );\n\t\tLocalCacheData.current_doing_context_action = 'copy_as_new';\n\n\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( this.edit_view ) ) {\n\t\t\tthis.current_edit_record = this.copyAsNewResetIds( this.current_edit_record );\n\t\t\tvar navigation_div = this.edit_view.find( '.navigation-div' );\n\t\t\tnavigation_div.css( 'display', 'none' );\n\t\t\tthis.setEditMenu();\n\t\t\tthis.setTabStatus(); // Show tabs based on permission. setCurrentEditRecordData has functions to set by record type. See #2687 - setTabStatus() must go before setCurrentEditRecordData(), otherwise Premium Policy Tabs incorrectly shown.\n\t\t\t//Issue #2913 - When using copy and save actions (\"Copy As New\", \"Save & Copy\", etc) on views with sub views such as \"Pay Periods\" on Pay Period Schedules\n\t\t\t//the sub view tab might appear blank. This is because these copy functions do not go through the same order of events as a regular add click.\n\t\t\t//Because of that we need to call onTabShow() to make sure the code that creates the \"Save and continue\" message and button triggers.\n\t\t\tthis.onTabShow();\n\t\t\tif ( !this.editor ) {\n\t\t\t\t// #2687 if an editor exists in the view/tabs, we do not want to call setCurrentEditRecordData() as it wipes out the editor data in one of its child functions initInsideEditorData().\n\t\t\t\tthis.setCurrentEditRecordData();\n\t\t\t}\n\t\t\tthis.is_changed = false;\n\t\t\tProgressBar.closeOverlay();\n\t\t} else {\n\t\t\tvar filter = {};\n\t\t\tvar grid_selected_id_array = this.getGridSelectIdArray();\n\t\t\tvar grid_selected_length = grid_selected_id_array.length;\n\t\t\tif ( grid_selected_length > 0 ) {\n\t\t\t\tvar selectedId = grid_selected_id_array[0];\n\t\t\t} else {\n\t\t\t\tTAlertManager.showAlert( $.i18n._( 'No selected record' ) );\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tfilter.filter_data = {};\n\t\t\tfilter.filter_data.id = [selectedId];\n\n\t\t\tfilter = this.getCopyAsNewFilter( filter );\n\n\t\t\tthis.api['get' + this.api.key_name]( filter, {\n\t\t\t\tonResult: function( result ) {\n\t\t\t\t\t$this.onCopyAsNewResult( result );\n\t\t\t\t}\n\t\t\t} );\n\t\t}\n\t}\n\n\tonCopyAsNewResult( result ) {\n\t\tvar result_data = result.getResult();\n\n\t\tif ( typeof result_data != 'object' ) {\n\t\t\tthis.onAddClick();\n\t\t\treturn;\n\t\t}\n\n\t\tthis.openEditView(); // Put it here is to avoid if the selected one is not existed in data or have deleted by other pragram. in this case, the edit view should not be opend.\n\n\t\tresult_data = result_data[0];\n\n\t\tresult_data = this.copyAsNewResetIds( result_data );\n\n\t\tif ( this.sub_view_mode && this.parent_key ) {\n\t\t\tresult_data[this.parent_key] = this.parent_value;\n\t\t}\n\n\t\tthis.current_edit_record = result_data;\n\t\tvar $this = this;\n\n\t\t$( '.PunchesEditView .edit-view-tab-bar' ).css( 'opacity', 1 );\n\t\t$( '.PunchesEditView .edit-view-tab' ).css( 'opacity', 1 );\n\t\t$this.initEditView();\n\t}\n\n\t/*\n\t 1. Job is switched.\n\t 2. If a Task is already selected (and its not Task=0), keep it selected *if its available* in the newly populated Task list.\n\t 3. If the task selected is *not* available in the Task list, or the selected Task=0, then check the default_item_id field from the Job and if its *not* 0 also, select that Task by default.\n\n\t 'job' argument must be an object, or false/null\n\t */\n\tsetJobItemValueWhenJobChanged( job, job_item_id_col_name, filter_data ) {\n\t\tvar $this = this;\n\n\t\tif ( job_item_id_col_name == undefined ) {\n\t\t\tjob_item_id_col_name = 'job_item_id';\n\t\t}\n\n\t\t//Error: Uncaught TypeError: Cannot set property 'job_item_id' of null in /interface/html5/#!m=TimeSheet&date=20150126&user_id=54286 line 6785\n\t\tif ( !$this.current_edit_record || !$this.edit_view_ui_dic[job_item_id_col_name] ) {\n\t\t\treturn;\n\t\t}\n\n\t\tTTPromise.add( 'BaseViewController', 'setJobItemValueWhenJobChanged' );\n\n\t\tif ( filter_data == undefined ) {\n\t\t\tfilter_data = { status_id: 10 };\n\t\t}\n\n\t\tif ( job != undefined && job != false ) {\n\t\t\tfilter_data['job_id'] = job.id; //Always filter by job\n\t\t}\n\n\t\tvar job_item_widget = $this.edit_view_ui_dic[job_item_id_col_name];\n\t\tvar current_job_item_id = job_item_widget.getValue();\n\t\tjob_item_widget.setSourceData( null );\n\t\tjob_item_widget.setCheckBox( true );\n\t\tthis.edit_view_ui_dic['job_item_quick_search'].setCheckBox( true );\n\n\t\tvar args = {};\n\t\targs.filter_data = filter_data;\n\t\t$this.edit_view_ui_dic[job_item_id_col_name].setDefaultArgs( args );\n\n\t\t//Make sure if current task is selected, that its still available on the new job.\n\t\tif ( current_job_item_id && current_job_item_id != TTUUID.zero_id ) {\n\t\t\tvar new_arg = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.clone */ .x.clone( args );\n\t\t\t//We are checking if the current selected record validates against the job costing criteria.\n\t\t\t//To avoid issues with pagination we are only checking against the current selected record.\n\t\t\tnew_arg.filter_data.id = current_job_item_id;\n\t\t\tnew_arg.filter_data.job_id = job.id;\n\t\t\tnew_arg.filter_columns = $this.edit_view_ui_dic[job_item_id_col_name].getColumnFilter();\n\t\t\t$this.job_item_api.getJobItem( new_arg, {\n\t\t\t\tonResult: function( result ) {\n\t\t\t\t\t//Error: Uncaught TypeError: Cannot set property 'job_item_id' of null in /interface/html5/#!m=TimeSheet&date=20150126&user_id=54286 line 6785\n\t\t\t\t\tif ( !$this.current_edit_record ) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tvar data = result.getResult();\n\n\t\t\t\t\t//Data must be an array of allowed id. If no results, data might be true or false from the API.\n\t\t\t\t\t//Convert this to an array so that data can contain TTUUID.not_exist_id.\n\t\t\t\t\t//This allows users to still select \"default\" or a different option that is not a normal record.\n\t\t\t\t\tif ( !Array.isArray( data ) ) {\n\t\t\t\t\t\tdata = [];\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( current_job_item_id === TTUUID.not_exist_id ) {\n\t\t\t\t\t\tdata.push( { id: TTUUID.not_exist_id } );\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( current_job_item_id === -2 ) {\n\t\t\t\t\t\tdata.push( { id: -2 } );\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( data.length == 0 ) {\n\t\t\t\t\t\tsetDefaultData( job_item_id_col_name );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} );\n\n\t\t} else {\n\t\t\tsetDefaultData( job_item_id_col_name );\n\t\t}\n\n\t\tfunction setDefaultData( job_item_id_col_name ) {\n\t\t\tif ( job_item_id_col_name == undefined ) {\n\t\t\t\tjob_item_id_col_name = 'job_item_id';\n\t\t\t}\n\t\t\tif ( $this.current_edit_record.hasOwnProperty( job_item_id_col_name ) ) {\n\t\t\t\tjob_item_widget.setValue( job.default_item_id );\n\t\t\t\t$this.current_edit_record[job_item_id_col_name] = job.default_item_id;\n\n\t\t\t\tif ( job.default_item_id === false || job.default_item_id === 0 || job.default_item_id === TTUUID.zero_id || job.default_item_id === TTUUID.not_exist_id ) {\n\t\t\t\t\t$this.edit_view_ui_dic.job_item_quick_search.setValue( '' );\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\tjob_item_widget.setValue( '' );\n\t\t\t\t$this.current_edit_record[job_item_id_col_name] = false;\n\t\t\t\t$this.edit_view_ui_dic.job_item_quick_search.setValue( '' );\n\t\t\t}\n\n\t\t\tTTPromise.resolve( 'BaseViewController', 'setJobItemValueWhenJobChanged' );\n\t\t}\n\t}\n\n\tsetJobValueWhenCriteriaChanged( job_id_col_name, filter_data ) {\n\t\tvar $this = this;\n\n\t\t//Error: Uncaught TypeError: Cannot set property 'job_id' of null in /interface/html5/#!m=TimeSheet&date=20150126&user_id=54286 line 6785\n\t\tif ( !$this.current_edit_record || !$this.edit_view_ui_dic[job_id_col_name] ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar job_widget = $this.edit_view_ui_dic[job_id_col_name];\n\t\tvar current_job_id = job_widget.getValue();\n\t\tjob_widget.setSourceData( null );\n\t\tjob_widget.setCheckBox( true );\n\t\tthis.edit_view_ui_dic['job_item_quick_search'].setCheckBox( true );\n\n\t\tvar args = {};\n\t\targs.filter_data = filter_data;\n\t\t$this.edit_view_ui_dic[job_id_col_name].setDefaultArgs( args );\n\n\t\t//Make sure if current job is selected, and that its still available after new criteria.\n\t\tif ( current_job_id && current_job_id != TTUUID.zero_id ) {\n\t\t\tvar new_arg = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.clone */ .x.clone( args );\n\t\t\t//We are checking if the current selected record validates against the job costing criteria.\n\t\t\t//To avoid issues with pagination we are only checking against the current selected record.\n\t\t\tnew_arg.filter_data.id = current_job_id;\n\t\t\tnew_arg.filter_columns = $this.edit_view_ui_dic[job_id_col_name].getColumnFilter();\n\t\t\t$this.job_api.getJob( new_arg, {\n\t\t\t\tonResult: function( result ) {\n\t\t\t\t\t//Error: Uncaught TypeError: Cannot set property 'job_id' of null in /interface/html5/#!m=TimeSheet&date=20150126&user_id=54286 line 6785\n\t\t\t\t\tif ( !$this.current_edit_record ) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tvar data = result.getResult();\n\n\t\t\t\t\t//Data must be an array of allowed id. If no results, data might be true or false from the API.\n\t\t\t\t\t//Convert this to an array so that data can contain TTUUID.not_exist_id.\n\t\t\t\t\t//This allows users to still select \"default\" or a different option that is not a normal record.\n\t\t\t\t\tif ( !Array.isArray( data ) ) {\n\t\t\t\t\t\tdata = [];\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( current_job_id === TTUUID.not_exist_id ) {\n\t\t\t\t\t\tdata.push( { id: TTUUID.not_exist_id } );\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( current_job_id === -2 ) {\n\t\t\t\t\t\tdata.push( { id: -2 } );\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( data.length == 0 ) {\n\t\t\t\t\t\tsetDefaultData( job_id_col_name );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} );\n\n\t\t} else {\n\t\t\tsetDefaultData( job_id_col_name );\n\t\t}\n\n\t\tfunction setDefaultData( job_id_col_name ) {\n\t\t\tif ( job_id_col_name == undefined ) {\n\t\t\t\tjob_id_col_name = 'job_id';\n\t\t\t}\n\t\t\tjob_widget.setValue( '' );\n\t\t\t$this.current_edit_record[job_id_col_name] = false;\n\t\t\t$this.edit_view_ui_dic.job_quick_search.setValue( '' );\n\t\t}\n\t}\n\n\tonJobQuickSearch( key, value, job_id_field, job_item_id_field, filter_data ) {\n\t\tvar $this = this;\n\n\t\tvar args = {};\n\n\t\tTTPromise.add( 'BaseViewController', 'onJobQuickSearch' );\n\n\t\tif ( job_id_field == undefined ) {\n\t\t\tjob_id_field = 'job_id';\n\t\t}\n\t\tif ( job_item_id_field == undefined ) {\n\t\t\tjob_item_id_field = 'job_item_id';\n\t\t}\n\n\t\t//Error: Uncaught TypeErro: Cannot read property 'setValue' of undefined in /interface/html5/#!m=TimeSheet&date=20141222&user_id=13566 line 6686\n\t\tif ( !$this.edit_view_ui_dic || !$this.edit_view_ui_dic[job_id_field] ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( key === 'job_quick_search' ) {\n\t\t\targs.filter_data = { manual_id: value, user_id: this.current_edit_record.user_id, status_id: '10' };\n\n\t\t\tif ( this.current_edit_record.branch_id ) {\n\t\t\t\targs.filter_data.punch_branch_id = this.current_edit_record.branch_id;\n\t\t\t}\n\n\t\t\tif ( this.current_edit_record.department_id ) {\n\t\t\t\targs.filter_data.punch_department_id = this.current_edit_record.department_id;\n\t\t\t}\n\n\t\t\tthis.job_api.getJob( args, {\n\t\t\t\tonResult: function( result ) {\n\t\t\t\t\t//Error: Uncaught TypeError: Cannot read property 'setValue' of undefined in /interface/html5/#!m=TimeSheet&date=20141222&user_id=13566 line 6686\n\t\t\t\t\tif ( !$this.edit_view_ui_dic || !$this.edit_view_ui_dic[job_id_field] ) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tvar result_data = result.getResult();\n\n\t\t\t\t\tif ( result_data.length > 0 ) {\n\t\t\t\t\t\t$this.edit_view_ui_dic[job_id_field].setValue( result_data[0].id );\n\t\t\t\t\t\t$this.current_edit_record[job_id_field] = result_data[0].id;\n\t\t\t\t\t\t$this.setJobItemValueWhenJobChanged( result_data[0], job_item_id_field, filter_data );\n\t\t\t\t\t} else {\n\t\t\t\t\t\t$this.edit_view_ui_dic[job_id_field].setValue( '' );\n\t\t\t\t\t\t$this.current_edit_record[job_id_field] = false;\n\t\t\t\t\t\t$this.setJobItemValueWhenJobChanged( false, job_item_id_field, filter_data );\n\t\t\t\t\t}\n\n\t\t\t\t\tTTPromise.resolve( 'BaseViewController', 'onJobQuickSearch' );\n\t\t\t\t}\n\t\t\t} );\n\n\t\t\t$this.edit_view_ui_dic['job_quick_search'].setCheckBox( true );\n\t\t\t$this.edit_view_ui_dic[job_id_field].setCheckBox( true );\n\t\t} else if ( key === 'job_item_quick_search' ) {\n\t\t\targs.filter_data = { manual_id: value, job_id: this.current_edit_record[job_id_field], status_id: '10' };\n\n\t\t\tthis.job_item_api.getJobItem( args, {\n\t\t\t\tonResult: function( result ) {\n\t\t\t\t\t//Error: Uncaught TypeError: Cannot read property 'setValue' of undefined in /interface/html5/#!m=TimeSheet&date=20141222&user_id=13566 line 6686\n\t\t\t\t\tif ( !$this.edit_view_ui_dic || !$this.edit_view_ui_dic[job_item_id_field] ) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tvar result_data = result.getResult();\n\t\t\t\t\tif ( result_data.length > 0 ) {\n\t\t\t\t\t\t$this.edit_view_ui_dic[job_item_id_field].setValue( result_data[0].id );\n\t\t\t\t\t\t$this.current_edit_record[job_item_id_field] = result_data[0].id;\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\t$this.edit_view_ui_dic[job_item_id_field].setValue( '' );\n\t\t\t\t\t\t$this.current_edit_record[job_item_id_field] = false;\n\t\t\t\t\t}\n\n\t\t\t\t\tTTPromise.resolve( 'BaseViewController', 'onJobQuickSearch' );\n\t\t\t\t}\n\t\t\t} );\n\n\t\t\tthis.edit_view_ui_dic['job_item_quick_search'].setCheckBox( true );\n\t\t\tthis.edit_view_ui_dic[job_item_id_field].setCheckBox( true );\n\t\t}\n\t}\n\n\tsetDepartmentValueWhenBranchChanged( department, department_id_col_name, filter_data ) {\n\t\tvar $this = this;\n\n\t\tif ( department_id_col_name == undefined ) {\n\t\t\tdepartment_id_col_name = 'department_id';\n\t\t}\n\n\t\tif ( !$this.current_edit_record || !$this.edit_view_ui_dic[department_id_col_name] ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar department_widget = $this.edit_view_ui_dic[department_id_col_name];\n\t\tvar current_department_id = department_widget.getValue();\n\t\tdepartment_widget.setSourceData( null );\n\t\tdepartment_widget.setCheckBox( true );\n\n\t\tvar args = {};\n\t\targs.filter_data = filter_data;\n\t\t$this.edit_view_ui_dic[department_id_col_name].setDefaultArgs( args );\n\n\t\t//Make sure if current department is selected, that its still available on the new job.\n\t\tif ( current_department_id && current_department_id != TTUUID.zero_id ) {\n\t\t\tvar new_arg = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.clone */ .x.clone( args );\n\t\t\t//We are checking if the current selected record validates against the job costing criteria.\n\t\t\t//To avoid issues with pagination we are only checking against the current selected record.\n\t\t\tnew_arg.filter_data.id = current_department_id;\n\t\t\tnew_arg.filter_columns = $this.edit_view_ui_dic[department_id_col_name].getColumnFilter();\n\t\t\t$this.department_api.getDepartment( new_arg, {\n\t\t\t\tonResult: function( result ) {\n\n\t\t\t\t\tif ( !$this.current_edit_record ) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tvar data = result.getResult();\n\n\t\t\t\t\t//Data must be an array of allowed id. If no results, data might be true or false from the API.\n\t\t\t\t\t//Convert this to an array so that data can contain TTUUID.not_exist_id.\n\t\t\t\t\t//This allows users to still select \"default\" or a different option that is not a normal record.\n\t\t\t\t\tif ( !Array.isArray( data ) ) {\n\t\t\t\t\t\tdata = [];\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( current_department_id === TTUUID.not_exist_id ) {\n\t\t\t\t\t\tdata.push( { id: TTUUID.not_exist_id } );\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( current_department_id === -2 ) {\n\t\t\t\t\t\tdata.push( { id: -2 } );\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( data.length === 0 ) {\n\t\t\t\t\t\tsetDefaultData( department_id_col_name );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} );\n\n\t\t} else {\n\t\t\tsetDefaultData( department_id_col_name );\n\t\t}\n\n\t\tfunction setDefaultData( department_id_col_name ) {\n\t\t\tif ( department_id_col_name == undefined ) {\n\t\t\t\tdepartment_id_col_name = 'department_id';\n\t\t\t}\n\t\t\tif ( $this.current_edit_record.hasOwnProperty( department_id_col_name ) ) {\n\t\t\t\tdepartment_widget.setValue( department.default_item_id );\n\t\t\t\t$this.current_edit_record[department_id_col_name] = department.default_item_id;\n\n\t\t\t\tif ( department.default_item_id === false || department.default_item_id === 0 || department.default_item_id === TTUUID.zero_id || department.default_item_id === TTUUID.not_exist_id ) {\n\t\t\t\t\t$this.edit_view_ui_dic.job_item_quick_search.setValue( '' );\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\tdepartment_widget.setValue( '' );\n\t\t\t\t$this.current_edit_record[department_id_col_name] = false;\n\t\t\t\t$this.edit_view_ui_dic.job_item_quick_search.setValue( '' );\n\t\t\t}\n\t\t}\n\t}\n\n\tsetPunchTagValuesWhenCriteriaChanged( filter_data, punch_tag_id_col_name ) {\n\t\tvar $this = this;\n\n\t\tif ( !$this.current_edit_record || !$this.edit_view_ui_dic[punch_tag_id_col_name] ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar punch_tag_widget = $this.edit_view_ui_dic[punch_tag_id_col_name];\n\t\tvar current_punch_tag_ids = punch_tag_widget.getValue();\n\t\tpunch_tag_widget.setSourceData( null );\n\n\t\tvar args = {};\n\t\targs.filter_data = filter_data;\n\t\tpunch_tag_widget.setDefaultArgs( args );\n\n\t\t//Make sure if current punch tags are selected, that they are still available on the new punch tag list.\n\t\tif ( current_punch_tag_ids && current_punch_tag_ids.length > 0 ) {\n\t\t\tvar new_arg = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.clone */ .x.clone( args );\n\t\t\tnew_arg.filter_data.id = current_punch_tag_ids;\n\t\t\t//Disabling paging to the API ($disable_paging = true) so that the user can have more punch tags selected than their preference for items per page.\n\t\t\t//Otherwise if they have 7 punch tags selected and their preference is 5, the api would only return 5 and 2 would be lost and unselected.\n\t\t\t$this.punch_tag_api.getPunchTag( new_arg, true,{\n\t\t\t\tonResult: function( punch_tag_result ) {\n\t\t\t\t\tif ( !$this.current_edit_record ) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tvar data = punch_tag_result.getResult();\n\n\t\t\t\t\t//Data must be an array of allowed punch tags. If no results, data might be true or false from the API.\n\t\t\t\t\t//Convert this to an array so that data can contain TTUUID.not_exist_id.\n\t\t\t\t\t//This allows users to still select \"default\" or a different option that is not a punch tag.\n\t\t\t\t\tif ( !Array.isArray( data ) ) {\n\t\t\t\t\t\tdata = [];\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( Array.isArray( data ) && Array.isArray( current_punch_tag_ids ) && current_punch_tag_ids.includes( TTUUID.not_exist_id ) ) {\n\t\t\t\t\t\tdata.push( { id: TTUUID.not_exist_id } );\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( Array.isArray( data ) && data.length > 0 ) {\n\t\t\t\t\t\tif ( current_punch_tag_ids !== TTUUID.zero_id && current_punch_tag_ids.length > 0 && $this.shouldUpdatePunchTags( current_punch_tag_ids, data ) ) {\n\t\t\t\t\t\t\t//Merge in users last selected punch tags in case they switched back to that selection.\n\t\t\t\t\t\t\t//Example: They have selected a New York branch punch tag but switch their selection to a different branch\n\t\t\t\t\t\t\t//and then back to New York. In that case we should reselect the New York punch tag.\n\t\t\t\t\t\t\tcurrent_punch_tag_ids = _.union( current_punch_tag_ids, $this.previous_punch_tag_selection );\n\t\t\t\t\t\t\t//Compare current selected punch tags and the list of punch tags from the API and remove invalid punch tags.\n\t\t\t\t\t\t\tvar intersected_values = current_punch_tag_ids.filter( punch_tag_id => data.some( punch_tag => punch_tag_id === punch_tag.id ) );\n\t\t\t\t\t\t\tpunch_tag_widget.setValue( intersected_values );\n\t\t\t\t\t\t\t$this.current_edit_record[punch_tag_id_col_name] = intersected_values;\n\t\t\t\t\t\t\t//Update manual IDs in punch_tag_quick_search.\n\t\t\t\t\t\t\tvar punch_tag_manual_ids = data.filter( punch_tag => intersected_values.includes( punch_tag.id ) ).map( ( { manual_id } ) => manual_id );\n\t\t\t\t\t\t\t$this.edit_view_ui_dic['punch_tag_quick_search'].setValue( punch_tag_manual_ids.join() );\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tsetDefaultData( punch_tag_id_col_name );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} );\n\n\t\t} else {\n\t\t\tsetDefaultData( punch_tag_id_col_name );\n\t\t}\n\n\t\tfunction setDefaultData( punch_tag_id_col_name ) {\n\t\t\tif ( $this.current_edit_record.hasOwnProperty( punch_tag_id_col_name ) ) {\n\t\t\t\tpunch_tag_widget.setValue( $this.default_punch_tag );\n\t\t\t\t$this.current_edit_record[punch_tag_id_col_name] = $this.default_punch_tag;\n\n\t\t\t\tif ( $this.default_punch_tag.length === 0 ) {\n\t\t\t\t\t$this.edit_view_ui_dic.punch_tag_quick_search.setValue( '' );\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\tpunch_tag_widget.setValue( '' );\n\t\t\t\t$this.current_edit_record[punch_tag_id_col_name] = false;\n\t\t\t\t$this.edit_view_ui_dic.punch_tag_quick_search.setValue( '' );\n\t\t\t}\n\t\t}\n\t}\n\n\tshouldUpdatePunchTags( current_punch_tag_ids, data ) {\n\t\t//If the current selected punch tags and previously user selected punch tags do not match we should check and update.\n\t\tif ( Array.isArray( this.previous_punch_tag_selection ) && this.previous_punch_tag_selection.every( punch_tag => current_punch_tag_ids.includes( punch_tag ) ) === false ) {\n\t\t\treturn true;\n\t\t}\n\t\t//If the data returned from the API does not contain every currently selected punch tag then we need to remove invalid tags.\n\t\tif ( current_punch_tag_ids.every( punch_tag_id => data.some( punch_tag => punch_tag.id === punch_tag_id ) ) === false ) {\n\t\t\treturn true;\n\t\t}\n\t}\n\n\tsetPunchTagQuickSearchManualIds( punch_tags, get_real_data ) {\n\t\tif ( punch_tags == false || !this.edit_view_ui_dic['punch_tag_quick_search'] || ( Array.isArray( punch_tags ) && punch_tags.length === 0 ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( punch_tags === TTUUID.not_exist_id || ( Array.isArray( punch_tags ) && punch_tags.includes( TTUUID.not_exist_id ) ) ) {\n\t\t\tthis.edit_view_ui_dic['punch_tag_quick_search'].setValue( '' );\n\t\t\treturn;\n\t\t}\n\n\t\tif ( get_real_data ) {\n\t\t\tvar $this = this;\n\t\t\tvar args = {};\n\t\t\targs.filter_data = { id: punch_tags };\n\t\t\tthis.punch_tag_api.getPunchTag( args, {\n\t\t\t\tonResult: function( result ) {\n\t\t\t\t\tvar data = result.getResult();\n\t\t\t\t\tvar manual_ids = [];\n\n\t\t\t\t\tfor ( var i = 0; i < data.length; i++ ) {\n\t\t\t\t\t\tmanual_ids.push( data[i].manual_id );\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( $this.edit_view_ui_dic && $this.edit_view_ui_dic['punch_tag_quick_search'] ) {\n\t\t\t\t\t\t$this.edit_view_ui_dic['punch_tag_quick_search'].setValue( manual_ids.join() );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} );\n\t\t} else {\n\t\t\tvar manual_ids = [];\n\t\t\tfor ( var i = 0; i < punch_tags.length; i++ ) {\n\t\t\t\tmanual_ids.push( punch_tags[i].manual_id );\n\t\t\t}\n\n\t\t\tif ( this.edit_view_ui_dic && this.edit_view_ui_dic['punch_tag_quick_search'] ) {\n\t\t\t\tthis.edit_view_ui_dic['punch_tag_quick_search'].setValue( manual_ids.join() );\n\t\t\t}\n\t\t}\n\t}\n\n\tonPunchTagQuickSearch( value, filter_data, punch_tag_id_col_name ) {\n\t\tvar $this = this;\n\n\t\tvar args = {};\n\n\t\tif ( !$this.edit_view_ui_dic || !$this.edit_view_ui_dic[punch_tag_id_col_name] ) {\n\t\t\treturn;\n\t\t}\n\n\t\targs.filter_data = filter_data;\n\t\targs.filter_data.manual_id = value.split( ',' );\n\n\t\tthis.punch_tag_api.GetPunchTag( args, {\n\t\t\tonResult: function( result ) {\n\t\t\t\tif ( !$this.edit_view_ui_dic || !$this.edit_view_ui_dic[punch_tag_id_col_name] ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tvar result_data = result.getResult();\n\n\t\t\t\t$this.edit_view_ui_dic[punch_tag_id_col_name].setSourceData( null );\n\n\t\t\t\tif ( result_data.length > 0 ) {\n\t\t\t\t\tvar punch_tags = result_data.map( punch_tag => punch_tag.id );\n\t\t\t\t\t$this.edit_view_ui_dic[punch_tag_id_col_name].setValue( punch_tags );\n\t\t\t\t\t$this.current_edit_record[punch_tag_id_col_name] = punch_tags;\n\t\t\t\t\t$this.previous_punch_tag_selection = punch_tags;\n\t\t\t\t} else {\n\t\t\t\t\t$this.edit_view_ui_dic[punch_tag_id_col_name].setValue( '' );\n\t\t\t\t\t$this.current_edit_record[punch_tag_id_col_name] = false;\n\t\t\t\t\t$this.previous_punch_tag_selection = [];\n\t\t\t\t}\n\n\t\t\t\tdelete args['manual_id'];\n\n\t\t\t}\n\t\t} );\n\n\t\tthis.edit_view_ui_dic['punch_tag_quick_search'].setCheckBox( true );\n\t\tthis.edit_view_ui_dic[punch_tag_id_col_name].setCheckBox( true );\n\t}\n\n\tgetPunchTagFilterData() {\n\t\tif ( !this.current_edit_record || !this.current_edit_record.user_id ) {\n\t\t\treturn {};\n\t\t}\n\n\t\tvar filter_data = {\n\t\t\tstatus_id: 10,\n\t\t\tuser_id: this.current_edit_record.user_id,\n\t\t\tbranch_id: this.current_edit_record.branch_id,\n\t\t\tdepartment_id: this.current_edit_record.department_id,\n\t\t\tjob_id: this.current_edit_record.job_id,\n\t\t\tjob_item_id: this.current_edit_record.job_item_id\n\t\t};\n\n\t\treturn filter_data;\n\t}\n\n\tonCancelClick( force_no_confirm, cancel_all, callback ) {\n\t\tTTPromise.add( 'base', 'onCancelClick' );\n\t\tvar $this = this;\n\t\t//#2342 This logic is also in onSubMenuClick click in RibbonViewController\n\t\tif ( !force_no_confirm\n\t\t\t&&\n\t\t\t(\n\t\t\t\t$this.is_changed == true\n\t\t\t\t|| ( LocalCacheData.current_open_primary_controller && LocalCacheData.current_open_primary_controller.edit_view && LocalCacheData.current_open_primary_controller.is_changed == true )\n\t\t\t\t|| ( LocalCacheData.current_open_report_controller && LocalCacheData.current_open_report_controller.is_changed == true )\n\t\t\t\t|| ( LocalCacheData.current_open_edit_only_controller && LocalCacheData.current_open_edit_only_controller.is_changed == true )\n\t\t\t\t|| ( LocalCacheData.current_open_sub_controller && LocalCacheData.current_open_sub_controller.edit_view && LocalCacheData.current_open_sub_controller.is_changed == true )\n\n\t\t\t) ) {\n\t\t\tthis.confirm_on_exit = true;\n\t\t}\n\n\t\tLocalCacheData.current_doing_context_action = 'cancel';\n\t\tif ( this.confirm_on_exit == true ) {\n\t\t\tTAlertManager.showConfirmAlert( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.modify_alert_message */ .x.modify_alert_message, null, function( clicked_yes ) {\n\t\t\t\tif ( clicked_yes === true ) {\n\t\t\t\t\tdoNext( force_no_confirm, cancel_all, callback );\n\t\t\t\t} else {\n\t\t\t\t\tTTPromise.reject( 'base', 'onCancelClick' );\n\t\t\t\t}\n\t\t\t} );\n\t\t} else {\n\t\t\tdoNext( force_no_confirm, cancel_all, callback );\n\t\t}\n\n\t\tfunction doNext( force_no_confirm, cancel_all, callback ) {\n\t\t\tif ( !$this.edit_view && $this.parent_view_controller && $this.sub_view_mode ) {\n\t\t\t\t$this.parent_view_controller.is_changed = false;\n\t\t\t\t$this.parent_view_controller.confirm_on_exit = false;\n\t\t\t\t$this.parent_view_controller.buildContextMenu( true );\n\t\t\t\t$this.parent_view_controller.onCancelClick( true ); //Force no confirm so we don't get two messages when cancelling from Edit Employee -> Wage (tab) -> Edit Wage.\n\t\t\t} else {\n\t\t\t\t$this.removeEditView( true );\n\t\t\t}\n\n\t\t\tif ( cancel_all ) {\n\t\t\t\tif ( LocalCacheData.current_open_edit_only_controller ) {\n\t\t\t\t\tLocalCacheData.current_open_edit_only_controller.onCancelClick( force_no_confirm, cancel_all );\n\t\t\t\t} else if ( LocalCacheData.current_open_sub_controller && LocalCacheData.current_open_sub_controller.edit_view ) {\n\t\t\t\t\tLocalCacheData.current_open_sub_controller.onCancelClick( force_no_confirm, cancel_all );\n\t\t\t\t} else if ( LocalCacheData.current_open_primary_controller && LocalCacheData.current_open_primary_controller.edit_view ) {\n\t\t\t\t\tLocalCacheData.current_open_primary_controller.onCancelClick( force_no_confirm, cancel_all );\n\t\t\t\t} else if ( LocalCacheData.current_open_report_controller ) {\n\t\t\t\t\tLocalCacheData.current_open_report_controller.onCancelClick( force_no_confirm, cancel_all );\n\t\t\t\t}\n\t\t\t}\n\t\t\tif ( callback ) {\n\t\t\t\tcallback();\n\t\t\t}\n\n\t\t\t_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.setUIInitComplete */ .x.setUIInitComplete();\n\t\t\tTTPromise.resolve( 'base', 'onCancelClick' );\n\t\t}\n\t}\n\n\t//Don't call super if override this function.\n\tonFormItemChange( target, doNotValidate ) {\n\t\t// Error: TypeError: this.current_edit_record is undefined in interface/html5/views/BaseViewController.js?v=9.0.7-20160202-113244 line 1691\n\t\tif ( !this.current_edit_record ) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.setIsChanged( target );\n\t\tthis.setMassEditingFieldsWhenFormChange( target );\n\t\tvar key = target.getField();\n\t\tthis.current_edit_record[key] = target.getValue();\n\n\t\tif ( !doNotValidate ) {\n\t\t\tthis.validate();\n\t\t}\n\t}\n\n\tsetIsChanged( target ) {\n\t\tvar key = target.getField();\n\t\tif ( this.current_edit_record && this.current_edit_record[key] != target.getValue() ) {\n\t\t\tthis.is_changed = true;\n\t\t}\n\t}\n\n\tonFormItemKeyUp( target ) {\n\t}\n\n\tonFormItemKeyDown( target ) {\n\t}\n\n\tsetMassEditingFieldsWhenFormChange( target ) {\n\t\tvar $this = this;\n\n\t\tif ( this.is_mass_editing ) {\n\t\t\tvar field = target.getField();\n\t\t\tvar linked_fields = [];\n\t\t\tvar is_linked_field = false;\n\t\t\t$.each( this.linked_columns, function( index, value ) {\n\t\t\t\tif ( value !== field ) {\n\t\t\t\t\tlinked_fields.push( value );\n\t\t\t\t} else {\n\t\t\t\t\tis_linked_field = true;\n\t\t\t\t}\n\t\t\t} );\n\n\t\t\tif ( is_linked_field ) {\n\t\t\t\t$.each( linked_fields, function( index, value ) {\n\t\t\t\t\tvar is_checked = $this.edit_view_ui_dic[field].isChecked();\n\t\t\t\t\t$this.edit_view_ui_dic[value].setCheckBox( is_checked );\n\t\t\t\t} );\n\t\t\t}\n\n\t\t}\n\t}\n\n\tinitEditViewTabs( tab_options ) {\n\t\tvar $this = this;\n\t\tif( tab_options === undefined ) {\n\t\t\ttab_options = {\n\t\t\t\tactivate: function( e, ui ) {\n\t\t\t\t\tif ( !$this.edit_view_tab || !$this.edit_view_tab.is( ':visible' ) ) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\t$this.onTabShow( e, ui );\n\t\t\t\t\t_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.triggerAnalyticsTabs */ .x.triggerAnalyticsTabs( e, ui );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tthis.setTabOVisibility( false );\n\n\t\tthis.edit_view_tab = this.edit_view_tab.tabs( tab_options );\n\n\t\tthis.edit_view_tab.off( 'click' ).on( 'click', function( e ) {\n\t\t\t$this.onTabIndexChange( e );\n\t\t} );\n\t}\n\n\tsetTabHtml( tab_model ) {\n\n\t\t// TODO: Go off tab_model not labels. Will need to do this anyway, as we trigger earlier.\n\t\t// HTML2JS TODO: For now this will just generate the tab labels, and once that works, we move on to the tab content div's.\n\t\t// TODO: This needs to be triggered sooner in BaseView.initEditViewUI as currently it happens after the .tabs() initialization and causing the class styles for tabs not to be added to the right tab elems, as they did not exist at the time to be added.\n\t\t// Maybe directly into initEditViewUI, as theres only 11 overrides for that.\n\n\t\tvar tab_bar_labels = this.edit_view.find( '.edit-view-tab-bar-label' );\n\t\tvar tab_bar_content; // insert after the label element.\n\t\t// find the html first, and check if its not already set.\n\t\tif( tab_bar_labels.children().length === 0 ) { // TODO: Perhaps in future also count number of children and compare against labels. If not matching, clear and start again.\n\t\t\t// No label elements found, likely using the new templating logic. Continue to generate the tab html.\n\n\t\t\t// Notes\n\t\t\t/* Fri Dec 17\n\t\t\tTODO:\n\t\t\t- 1. [Done]. First add the save and continue divs into templates as if subview.\n\t\t\t\t1b. Fix subview state issues on Employee->Employees tabs.\n\t\t\t- 2. then hardcode the hierarchy behaviour into its tab_model\n\t\t\t- 3. also hardcode potentially audit, but it might be covered by 1.\n\t\t\t- 4. qualifactions tab hardcoded with the subview things.\n\t\t\t- 5. sort out the first-column second column.\n\t\t\t--- either hardcode into the tab_model for number of columns or\n\t\t\t--- count the number of child elements in second column, and if zero, remove,\n\t\t\t\tand then add full width into the first column element.\n\t\t\t- 6. what was the subviewcontroller errors on some tabs. might be solved by 1. check employee view tabs.\n\t\t\t */\n\n\t\t\t// search for 'first-column full' - 73+ files\n\t\t\t// search for 'second-column' - 27 files\n\t\t\t// therefore first-column full width will be default, and second column will be specified in view controller, to avoid lots of avoidable editing of view files.\n\t\t\tfor ( let tab_id in tab_model ) {\n\t\t\t\t// Create and insert the label elements.\n\t\t\t\tvar new_tab_label_li = document.createElement( 'li' );\n\t\t\t\tvar new_tab_label_li_a = document.createElement( 'a' );\n\t\t\t\tnew_tab_label_li_a.setAttribute('ref', tab_id );\n\t\t\t\tnew_tab_label_li_a.setAttribute('href', '#' + tab_id );\n\t\t\t\tnew_tab_label_li.appendChild( new_tab_label_li_a );\n\n\t\t\t\ttab_bar_labels.append( new_tab_label_li ); // jQuery append()\n\t\t\t\t// TODO: Could also directly set the label value part here too in future.\n\t\t\t}\n\n\t\t} else {\n\t\t\t// Do nothing, labels already exist, likely from legacy html template loading.\n\t\t}\n\n\t\tvar tab_bar_parent = tab_bar_labels.parent();\n\t\tvar tab_bar_content_divs = tab_bar_parent.find( '.edit-view-tab-outside' );\n\n\t\tif( tab_bar_content_divs.children().length === 0 ) {\n\t\t\t// Create and insert the tab content divs\n\n\n\t\t\tfor ( let tab_id in tab_model ) {\n\t\t\t\t// Create and insert the label elements.\n\t\t\t\tlet tab_content_html = '';\n\t\t\t\tlet tab = tab_model[ tab_id ];\n\t\t\t\tlet is_sub_view = inferSubViewFromTab( tab ); // TODO: HTML2JS: Improve this to avoid inferring, by adding is_sub_view to relevant tab models.\n\n\t\t\t\tif( tab.html_template ) {\n\t\t\t\t\t// html template provided as override, do not use HtmlTemplatesGlobal. Only used for complex one-off tab html's.\n\t\t\t\t\ttab_content_html = tab.html_template;\n\t\t\t\t} else {\n\t\t\t\t\ttab_content_html = $( _services_HtmlTemplates__WEBPACK_IMPORTED_MODULE_5__/* .HtmlTemplatesGlobal.genericTab */ .H.genericTab({\n\t\t\t\t\t\ttab_id: tab_id,\n\t\t\t\t\t\tis_multi_column: tab.is_multi_column ? true : false,\n\t\t\t\t\t\tshow_permission_div: tab.show_permission_div ? true : false,\n\t\t\t\t\t\tis_sub_view: is_sub_view // to convert undefined's to false\n\t\t\t\t\t}));\n\t\t\t\t}\n\n\t\t\t\ttab_bar_parent.append( tab_content_html ); // Insert each new tab content at the end of tab_bar div (and after the ul.edit-view-tab-bar-label element, and other tab contents.)\n\t\t\t}\n\n\t\t\t// tab_bar.append( $( HtmlTemplatesGlobal.auditTab()) ); // after all the tab contents, add the audit tab. (TODO: handle situations where audit not needed). Auctually, audit should be in the list of tabs already. comment out for now.\n\n\t\t\t// switch ( tab_ref_key ) {\n\t\t\t// \tcase x:\n\t\t\t// \t\t// code block\n\t\t\t// \t\tbreak;\n\t\t\t// \tcase y:\n\t\t\t// \t\t// code block\n\t\t\t// \t\tbreak;\n\t\t\t// \tdefault:\n\t\t\t// \t// code block\n\t\t\t// }\n\n\t\t} else {\n\t\t\t// tab_bar_content_divs.length must be greater than 0\n\t\t\t// Do nothing, and no html will be affected.\n\t\t}\n\n\t\tfunction inferSubViewFromTab( tab ) {\n\t\t\tif ( tab.is_sub_view == true ) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tif( tab.init_callback === undefined ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tvar init_callback_string = tab.init_callback || '';\n\t\t\tvar infer_subview_tab_state = init_callback_string.toLowerCase().indexOf( 'sub' ) !== -1;\n\t\t\tif ( infer_subview_tab_state === true ) {\n\t\t\t\t// This one is a little more experimental (assumes all sub views have init callback functions named with 'sub'), but might work as temporary during refactor.\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\t// Nothing matched, return false by default.\n\t\t\treturn false;\n\t\t}\n\t}\n\n\tsetTabLabels( source ) {\n\t\tfor ( var key in source ) {\n\t\t\tthis.edit_view.find( 'a[ref=' + key + ']' ).text( source[key] );\n\t\t}\n\t}\n\n\tgetTabModel() {\n\t\treturn this.tab_model;\n\t}\n\n\tsetTabModel( model ) {\n\t\tvar tab_labels = {};\n\n\t\tfor ( var i in model ) {\n\t\t\t//If the model is \"true\", then use default models for audit/attachment tabs.\n\t\t\tif ( i == 'tab_audit' && model[i] === true ) {\n\t\t\t\tmodel['tab_audit'] = {\n\t\t\t\t\t'label': $.i18n._( 'Audit' ),\n\t\t\t\t\t'init_callback': 'initSubLogView',\n\t\t\t\t\t'display_on_mass_edit': false,\n\t\t\t\t\t'display_on_add': false\n\t\t\t\t};\n\t\t\t} else if ( i == 'tab_attachment' && model[i] === true ) {\n\t\t\t\tmodel['tab_attachment'] = {\n\t\t\t\t\t'label': $.i18n._( 'Attachment' ),\n\t\t\t\t\t'init_callback': 'initSubDocumentView',\n\t\t\t\t\t'display_on_mass_edit': false\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tif ( model[i].hasOwnProperty( 'label' ) && model[i].label != '' ) {\n\t\t\t\ttab_labels[i] = model[i].label;\n\t\t\t}\n\t\t}\n\n\t\tthis.tab_model = model;\n\t\tthis.setTabHtml( model );\n\t\tthis.initEditViewTabs();\n\t\tthis.setTabLabels( tab_labels );\n\n\t\treturn true;\n\t}\n\n\tonTabShow( e, ui ) {\n\t\tif ( !this.current_edit_record ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar key = this.getEditViewTabIndex();\n\t\tthis.editFieldResize( key );\n\n\t\tvar tab_model = this.getTabModel();\n\n\t\tif ( tab_model != null ) {\n\t\t\tif ( ui && ui.oldTab ) {\n\t\t\t\tvar prev_tab_name = ui.oldTab.find( 'a' )[0].getAttribute( 'href' ).substring( 1 );\n\t\t\t\tif ( tab_model[prev_tab_name] && tab_model[prev_tab_name].hasOwnProperty( 'on_exit_callback' ) && tab_model[prev_tab_name].on_exit_callback != '' ) {\n\t\t\t\t\tthis[tab_model[prev_tab_name].on_exit_callback]( prev_tab_name ); //Call mapped function to initialize the tab.\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t//ReFactored path to handle tabs based on a tab model mapping defined in each view class.\n\t\t\t//This abstracts the entry point for all tabs initializations to help with hiding/showing them and to reduce code duplication.\n\t\t\tvar tab_name = null;\n\t\t\tvar sub_view_div = null;\n\n\t\t\tvar tab_bar = this.edit_view.find( '.edit-view-tab-bar li.ui-tabs-active' ).find( 'a' );\n\t\t\tif ( tab_bar.length > 0 ) {\n\t\t\t\ttab_name = tab_bar[0].getAttribute( 'href' ).substring( 1 ); //Remove the '#';\n\t\t\t\tsub_view_div = this.edit_view_tab.find( '#' + tab_name ).find( '.first-column-sub-view' );\n\t\t\t}\n\n\t\t\tif ( sub_view_div && sub_view_div.length > 0 && this.tab_model[tab_name] && !this.tab_model[tab_name].initialized ) { //Only hide grid on first initialization as it has to load all the data. Otherwise the 2nd time the user goes to the tab they will see some minor \"flashing\"\n\t\t\t\tTTPromise.add( 'BaseViewController', 'onTabShow' );\n\t\t\t\tTTPromise.wait( 'BaseViewController', 'onTabShow', function() {\n\t\t\t\t\tsub_view_div.css( 'opacity', '1' );\n\t\t\t\t} );\n\n\t\t\t\tsub_view_div.css( 'opacity', '0' ); //Hide the grid while its loading/sizing.\n\t\t\t\tthis.tab_model[tab_name].initialized = true;\n\t\t\t}\n\n\t\t\tif ( tab_model[tab_name] ) {\n\t\t\t\t//this.edit_view_tab.find( '#'+ tab_name ).find( '.first-column-sub-view' ).css( 'display', 'block' );\n\t\t\t\t//Call the init_callback even if we are editing an existing record or creating a new one.\n\t\t\t\t// As some views (ie: OverTime Policy) need to control whats shown on each tab regardless of if we are editing or adding.\n\t\t\t\tif ( tab_model[tab_name].hasOwnProperty( 'init_callback' ) && tab_model[tab_name].init_callback != '' ) {\n\t\t\t\t\tthis[tab_model[tab_name].init_callback]( tab_name ); //Call mapped function to initialize the tab.\n\t\t\t\t} else {\n\t\t\t\t\t//Assume primary tab and build context menu.\n\t\t\t\t\tif ( this.current_edit_record.id && this.current_edit_record.id != TTUUID.zero_id ) {\n\t\t\t\t\t\tthis.setEditMenu();\n\t\t\t\t\t} else {\n\t\t\t\t\t\t//this.edit_view_tab.find( '#'+ tab_name ).find( '.first-column-sub-view' ).css( 'display', 'none' ); //This would prevent the grid from showing in Attendance -> TimeSheet, Accumulated Time view.\n\t\t\t\t\t\t//this.edit_view_tab.find( '#'+ tab_name ).find( '.first-column-sub-view' ).css( 'display', 'block' );\n\t\t\t\t\t\tthis.showSaveAndContinueButton();\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// if ( this.current_edit_record.id ) {\n\t\t\t\t// \t//this.edit_view_tab.find( '#'+ tab_name ).find( '.first-column-sub-view' ).css( 'display', 'block' );\n\t\t\t\t// \tif ( tab_model[tab_name].hasOwnProperty('init_callback') && tab_model[tab_name].init_callback != '' ) {\n\t\t\t\t// \t\tthis[tab_model[tab_name].init_callback]( tab_name ); //Call mapped function to initialize the tab.\n\t\t\t\t// \t} else {\n\t\t\t\t// \t\t//Assume primary tab and build context menu.\n\t\t\t\t// \t\tthis.buildContextMenu( true );\n\t\t\t\t// \t\tthis.setEditMenu();\n\t\t\t\t// \t}\n\t\t\t\t// } else {\n\t\t\t\t// \t//this.edit_view_tab.find( '#'+ tab_name ).find( '.first-column-sub-view' ).css( 'display', 'none' ); //This would prevent the grid from showing in Attendance -> TimeSheet, Accumulated Time view.\n\t\t\t\t// \t//this.edit_view_tab.find( '#'+ tab_name ).find( '.first-column-sub-view' ).css( 'display', 'block' );\n\t\t\t\t// \tthis.edit_view.find( '.save-and-continue-div' ).css( 'display', 'block' );\n\t\t\t\t// }\n\t\t\t} else {\n\t\t\t\t//Assume primary tab and build context menu.\n\t\t\t\tthis.buildContextMenu( true );\n\t\t\t\tthis.setEditMenu();\n\t\t\t}\n\t\t} else {\n\t\t\t//Handle most cases that one tab and on audit tab\n\t\t\tif ( key === 1 ) {\n\n\t\t\t\tif ( this.current_edit_record.id && this.current_edit_record.id != TTUUID.zero_id ) {\n\t\t\t\t\tthis.edit_view_tab.find( '#tab_audit' ).find( '.first-column-sub-view' ).css( 'display', 'block' );\n\t\t\t\t\tthis.initSubLogView( 'tab_audit' );\n\t\t\t\t} else {\n\n\t\t\t\t\tthis.edit_view_tab.find( '#tab_audit' ).find( '.first-column-sub-view' ).css( 'display', 'none' );\n\t\t\t\t\tthis.showSaveAndContinueButton();\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\tthis.buildContextMenu( true );\n\t\t\t\tthis.setEditMenu();\n\t\t\t}\n\t\t}\n\t}\n\n\t//When overriding this function, always call super() so it can handle tab_audit/tab_attachment on its own.\n\tcheckTabPermissions( tab ) {\n\t\tvar retval = true; //Most tabs are shown, so default to true.\n\n\t\tswitch ( tab ) {\n\t\t\tcase 'tab_audit':\n\t\t\t\tretval = this.subAuditValidate();\n\t\t\t\tbreak;\n\t\t\tcase 'tab_attachment':\n\t\t\t\tretval = this.subDocumentValidate();\n\t\t\t\tbreak;\n\t\t}\n\n\t\treturn retval;\n\t}\n\n\tsetTabStatus() {\n\t\t// exception that edit_view_tab is null\n\t\tif ( !this.edit_view_tab ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar tab_model = this.getTabModel();\n\n\t\tif ( tab_model != null ) {\n\t\t\tvar visible_tab_indexes = Array();\n\n\t\t\t//ReFactored path to handle tabs based on a tab model mapping defined in each view class.\n\t\t\t//This abstracts the entry point for all tabs initializations to help with hiding/showing them and to reduce code duplication.\n\t\t\tfor ( var i in tab_model ) {\n\t\t\t\tvar tab_index = $( this.edit_view_tab.find( 'ul li a[ref=\"' + i + '\"]' ) ).parent().index();\n\n\t\t\t\tif ( ( this.is_mass_editing && tab_model[i].hasOwnProperty( 'display_on_mass_edit' ) && tab_model[i].display_on_mass_edit == false )\n\t\t\t\t\t|| ( ( this.is_add || this.is_mass_adding ) && tab_model[i].hasOwnProperty( 'display_on_add' ) && tab_model[i].display_on_add == false ) ) {\n\t\t\t\t\t$( this.edit_view_tab.find( 'ul li a[ref=\"' + i + '\"]' ) ).parent().hide();\n\t\t\t\t} else {\n\t\t\t\t\tif ( this.checkTabPermissions( i ) == true ) {\n\t\t\t\t\t\t$( this.edit_view_tab.find( 'ul li a[ref=\"' + i + '\"]' ) ).parent().show();\n\t\t\t\t\t\tvisible_tab_indexes.push( tab_index );\n\t\t\t\t\t} else {\n\t\t\t\t\t\t$( this.edit_view_tab.find( 'ul li a[ref=\"' + i + '\"]' ) ).parent().hide();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t//Always start with the first tab that actually has permissions to be shown. This is important for sub-views like Edit Employee, Tax, New icon, where it shows only a single tab where there are really 5+ tabs just hidden.\n\t\t\tvisible_tab_indexes = visible_tab_indexes.sort( function( a, b ) {\n\t\t\t\treturn a - b;\n\t\t\t} ); //numeric sort.\n\n\t\t\tif ( visible_tab_indexes[0] ) {\n\t\t\t\tthis.edit_view_tab.tabs( 'option', 'active', visible_tab_indexes[0] );\n\t\t\t}\n\t\t} else {\n\t\t\t//Handle most cases that one tab and on audit tab\n\t\t\tif ( this.is_mass_editing ) {\n\n\t\t\t\t$( this.edit_view_tab.find( 'ul li a[ref=\"tab_audit\"]' ) ).parent().hide();\n\t\t\t\tthis.edit_view_tab.tabs( 'option', 'active', 0 );\n\n\t\t\t} else {\n\n\t\t\t\tif ( this.subAuditValidate() ) {\n\t\t\t\t\t$( this.edit_view_tab.find( 'ul li a[ref=\"tab_audit\"]' ) ).parent().show();\n\t\t\t\t} else {\n\t\t\t\t\t$( this.edit_view_tab.find( 'ul li a[ref=\"tab_audit\"]' ) ).parent().hide();\n\t\t\t\t\tthis.edit_view_tab.tabs( 'option', 'active', 0 );\n\t\t\t\t}\n\n\t\t\t}\n\t\t}\n\n\t\tthis.editFieldResize( 0 );\n\t}\n\n\tonTabIndexChange( e ) {\n\t\tTTPromise.add( 'BaseViewController', 'onTabIndexChange' );\n\t\tTTPromise.wait();\n\n\t\tif ( ( !this.sub_view_mode && !this.edit_only_mode ) || typeof this.initReport == 'function' ) {\n\t\t\tvar current_url = window.location.href;\n\n\t\t\tif ( current_url.indexOf( '&tab' ) > 0 ) {\n\t\t\t\tcurrent_url = current_url.substring( 0, current_url.indexOf( '&tab' ) );\n\t\t\t}\n\t\t\tvar tab_name = this.edit_view_tab.find( '.edit-view-tab-bar-label' ).children().eq( this.getEditViewTabIndex() ).text();\n\t\t\ttab_name = tab_name.replace( /\\/|\\s+/g, '' );\n\t\t\tcurrent_url = current_url + '&tab=' + tab_name;\n\n\t\t\t_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.setURLToBrowser */ .x.setURLToBrowser( current_url );\n\n\t\t}\n\n\t\tthis.hideErrorTips();\n\t\tTTPromise.resolve( 'BaseViewController', 'onTabIndexChange' );\n\t}\n\n\thideErrorTips() {\n\t\tfor ( var key in this.edit_view_error_ui_dic ) {\n\t\t\t//#2581 - Uncaught TypeError: this.edit_view_error_ui_dic[key].hideErrorTip is not a function\n\t\t\tif ( this.edit_view_error_ui_dic[key] && typeof this.edit_view_error_ui_dic[key].hideErrorTip == 'function' ) {\n\t\t\t\tthis.edit_view_error_ui_dic[key].hideErrorTip();\n\t\t\t}\n\t\t}\n\t\tthis.removeEditViewErrorTip();\n\t}\n\n\t//removed workarounds and comments for qtip1 when upgrading to qtip2.\n\tremoveEditViewErrorTip() {\n\t\tif ( $( '.qtip2-error-tip:visible' ) ) {\n\t\t\t$( '.qtip2-error-tip' ).remove();\n\t\t}\n\n\t}\n\n\tremoveEditViewWarningTip() {\n\t\tif ( $( '.qtip2-warning-tip:visible' ) ) {\n\t\t\t$( '.qtip2-warning-tip' ).remove();\n\t\t}\n\t}\n\n\tonCountryChange() {\n\t\tvar selectVal = this.edit_view_ui_dic['country'].getValue();\n\t\tthis.eSetProvince( selectVal, true );\n\t\tthis.clearErrorTips();\n\t\tthis.setEditMenu();\n\t}\n\n\t//Make sure this.current_edit_record is updated before validate\n\tvalidate( api ) {\n\t\tif ( this.enable_validation ) {\n\t\t\t//Allow alternate api to be validated.\n\t\t\tif ( api == undefined ) {\n\t\t\t\tvar api = this.api;\n\t\t\t}\n\n\t\t\tvar $this = this;\n\t\t\tvar record = {};\n\t\t\tif ( this.is_mass_editing ) {\n\t\t\t\tfor ( var key in this.edit_view_ui_dic ) {\n\n\t\t\t\t\tif ( !this.edit_view_ui_dic.hasOwnProperty( key ) ) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tvar widget = this.edit_view_ui_dic[key];\n\t\t\t\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( widget.isChecked ) ) {\n\t\t\t\t\t\tif ( widget.isChecked() && widget.getEnabled() ) {\n\t\t\t\t\t\t\trecord[key] = this.current_edit_record[key]; // Note: Some view controllers use widget.getValue() instead of current_edit_record[key]\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\trecord = this.current_edit_record;\n\t\t\t}\n\t\t\trecord = this.uniformVariable( record );\n\t\t\tapi['validate' + api.key_name]( record, {\n\t\t\t\tonResult: function( result ) {\n\t\t\t\t\t$this.validateResult( result );\n\t\t\t\t}\n\t\t\t} );\n\t\t} else {\n\t\t\tDebug.Text( 'Validation disabled', 'BaseViewController.js', 'BaseViewController', 'validate', 10 );\n\t\t}\n\t}\n\n\tvalidateResult( result ) {\n\t\tvar $this = this;\n\t\t$this.clearErrorTips(); //Always clear error\n\t\tif ( !$this.edit_view ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( !result ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( result.isValid() ) {\n\t\t\t$this.edit_view.attr( 'validate_complete', true );\n\t\t\t$this.setEditMenu();\n\t\t} else {\n\t\t\t$this.setErrorMenu();\n\t\t\t$this.setErrorTips( result, this.show_warning_when_validation );\n\n\t\t}\n\t}\n\n\tclearErrorTips() {\n\n\t\tfor ( var key in this.edit_view_error_ui_dic ) {\n\t\t\t//Error: Uncaught TypeError: Cannot read property 'clearErrorStyle' of undefined in /interface/html5/views/BaseViewController.js?v=8.0.0-20141117-111140 line 1779\n\t\t\tif ( !this.edit_view_error_ui_dic.hasOwnProperty( key ) || !this.edit_view_error_ui_dic[key] ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tthis.edit_view_error_ui_dic[key].clearErrorStyle();\n\t\t}\n\n\t\t// Error: Uncaught TypeError: Cannot read property 'interfaces' of undefined in interface/html5/framework/jquery.qtip.min.js?v=9.0.0-20150918-221906 line 15\n\t\tthis.removeEditViewErrorTip();\n\t\tthis.removeEditViewWarningTip();\n\t\t$( '.error-tab' ).removeClass( 'error-tab' );\n\t\t$( '.error-tab-hide' ).removeClass( 'error-tab-hide' );\n\t\t$( '.warning-tab' ).removeClass( 'warning-tab' );\n\t\t$( '.warning-tab-hide' ).removeClass( 'warning-tab-hide' );\n\t\t// Clear pulse on tabs\n\t\tif ( this.pulse_time_dic ) {\n\t\t\tfor ( var key1 in this.pulse_time_dic ) {\n\t\t\t\tclearInterval( this.pulse_time_dic[key1] );\n\t\t\t}\n\t\t\tthis.pulse_time_dic = {};\n\t\t}\n\t\tthis.edit_view_error_ui_dic = {};\n\n\t\t$( '.qtip .qtip2-error-tip' ).remove();\n\t}\n\n\t//Override this if more than one tab\n\tsetErrorTips( result, show_warning ) {\n\t\tthis.clearErrorTips();\n\t\tif ( !_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( show_warning ) ) {\n\t\t\tshow_warning = true;\n\t\t}\n\n\t\t//Error: Unable to get property 'find' of undefined or null reference in http://timeclock:8085/interface/html5/views/BaseViewController.js?v=7.4.3-20140926-105827 line 1769\n\t\tif ( !this.edit_view_tab ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar details = result.getDetails();\n\t\t// Only check first item\n\t\t// Error: Uncaught TypeError: Cannot call method 'hasOwnProperty' of undefined in /interface/html5/views/BaseViewController.js?v=9.0.0-20150822-134259 line 1879\n\t\t// Zero is not always the first element;\n\t\tvar first_el = 0;\n\t\tfor ( var first_el in details ) {\n\t\t\tbreak;\n\t\t}\n\n\t\tif ( details && details[first_el] && details[first_el].hasOwnProperty( 'error' ) ) {\n\t\t\tthis.setErrorTipsError( result );\n\t\t} else if ( details && details[first_el] && details[first_el].hasOwnProperty( 'warning' ) ) { //Error: TypeError: details[0] is undefined in https://greenacres.timetrex.com/interface/html5/views/BaseViewController.js?v=9.0.0-20150822-105118 line 1883\n\t\t\tif ( show_warning ) {\n\t\t\t\tthis.setErrorTipsWarning( result );\n\t\t\t}\n\t\t\tthis.setEditMenu();\n\t\t} else if ( result.getCode() == 'PERMISSION' || result.getCode() == 'VALIDATION' ) {\n\t\t\tTAlertManager.showErrorAlert( result );\n\t\t} else {\n\t\t\t// Make sure current codes work.\n\t\t\tthis.setErrorTipsError( result );\n\t\t}\n\t}\n\n\tsetErrorTipsWarning( result ) {\n\t\tvar $this = this;\n\t\tvar widget;\n\t\t// when do validation, only show warning no alert\n\t\tvar $current_doing_context_action = LocalCacheData.current_doing_context_action; //#2474 - LocalCacheData.current_doing_context_action can change to \"validate\" while waiting for user to respond to warning box.\n\t\tif ( $current_doing_context_action != 'validate' ) {\n\t\t\tTAlertManager.showWarningAlert( result, function( flag ) {\n\t\t\t\tif ( flag ) {\n\t\t\t\t\tswitch ( $current_doing_context_action ) {\n\t\t\t\t\t\tcase 'save':\n\t\t\t\t\t\t\t$this.onSaveClick( true );\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 'save_and_continue':\n\t\t\t\t\t\t\t$this.onSaveAndContinue( true );\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 'save_and_next':\n\t\t\t\t\t\t\t$this.onSaveAndNextClick( true );\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 'save_and_copy':\n\t\t\t\t\t\t\t$this.onSaveAndCopy( true );\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 'new':\n\t\t\t\t\t\t\t$this.onSaveAndNewClick( true );\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 'authorize': //Allow validation warnings to work when authorizing Request/TimeSheet/Expense.\n\t\t\t\t\t\t\t$this.onAuthorizationClick( true );\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t$this.show_warning_when_validation = true;\n\t\t\t\t}\n\t\t\t} );\n\t\t}\n\n\t\t//Error: Unable to get property 'warning' of undefined or null reference\n\t\tvar error_list = [];\n\t\tif ( result.getDetails().length == 1 ) {\n\t\t\terror_list = result.getDetails()[0].warning;\n\t\t}\n\t\tvar found_in_current_tab = false;\n\t\tfor ( var key in error_list ) {\n\t\t\tif ( !error_list.hasOwnProperty( key ) ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( this.edit_view_ui_dic[key] ) && this.edit_view_ui_dic[key].closest( document.documentElement ).length > 0 ) {\n\t\t\t\twidget = this.edit_view_ui_dic[key];\n\t\t\t} else if ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( this.edit_view_ui_validation_field_dic[key] ) ) {\n\t\t\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isArray */ .x.isArray( this.edit_view_ui_validation_field_dic[key] ) ) {\n\t\t\t\t\tvar len = this.edit_view_ui_validation_field_dic[key].length;\n\t\t\t\t\tfor ( var i = 0; i < len; i++ ) {\n\t\t\t\t\t\tvar item = this.edit_view_ui_validation_field_dic[key][i];\n\t\t\t\t\t\tif ( item.closest( document.documentElement ).length > 0 ) {\n\t\t\t\t\t\t\twidget = item;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else if ( this.edit_view_ui_validation_field_dic[key].closest( document.documentElement ).length > 0 ) {\n\t\t\t\t\twidget = this.edit_view_ui_validation_field_dic[key];\n\t\t\t\t} else {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t} else if ( key.indexOf( '_id' ) < 0 && _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( this.edit_view_ui_dic[key + '_id'] ) && this.edit_view_ui_dic[key + '_id'].closest( document.documentElement ).length > 0 ) {\n\t\t\t\twidget = this.edit_view_ui_dic[key + '_id'];\n\t\t\t} else {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif ( error_list[key] ) {\n\t\t\t\tvar show_error = false;\n\t\t\t\tif ( widget.is( ':visible' ) ) {\n\t\t\t\t\tshow_error = true;\n\t\t\t\t\tfound_in_current_tab = true;\n\t\t\t\t}\n\n\t\t\t\tif ( typeof widget.setErrorStyle === 'function' ) { //Fix JS exception: Uncaught TypeError: widget.setErrorStyle is not a function\n\t\t\t\t\twidget.setErrorStyle( error_list[key], show_error, true );\n\t\t\t\t}\n\n\t\t\t}\n\t\t\tthis.showErrorStatusOnTab( widget, false );\n\t\t\tthis.edit_view_error_ui_dic[key] = widget;\n\t\t}\n\t\tif ( !found_in_current_tab ) {\n\t\t\tthis.showEditViewError( result );\n\t\t}\n\t}\n\n\tshowErrorStatusOnTab( widget, isError ) {\n\t\tvar parentContainer = widget.parent();\n\t\tvar i = 0;\n\t\twhile ( !parentContainer.hasClass( 'edit-view-tab-outside' ) && i < 5 ) {\n\t\t\ti = i + 1;\n\t\t\tparentContainer = parentContainer.parent();\n\t\t}\n\t\tif ( parentContainer.hasClass( 'edit-view-tab-outside' ) ) {\n\t\t\tvar id = parentContainer.attr( 'id' );\n\t\t\tvar tab = this.edit_view.find( 'a[ref=\"' + id + '\"]' );\n\t\t\tif ( isError ) {\n\t\t\t\ttab.parent().addClass( 'error-tab' );\n\t\t\t\tthis.startPulse( id, tab.parent() );\n\t\t\t} else {\n\t\t\t\ttab.parent().addClass( 'warning-tab' );\n\t\t\t\tthis.startPulse( id, tab.parent(), true );\n\t\t\t}\n\n\t\t}\n\t}\n\n\tstartPulse( tab_id, target, is_warning ) {\n\t\tvar $this = this;\n\t\tif ( !this.pulse_time_dic ) {\n\t\t\tthis.pulse_time_dic = {};\n\t\t}\n\t\tif ( this.pulse_time_dic[tab_id] ) {\n\t\t\tcleanTimer( tab_id );\n\t\t}\n\t\tthis.pulse_time_dic[tab_id] = setInterval( function() {\n\t\t\tif ( is_warning ) {\n\t\t\t\tif ( target.hasClass( 'warning-tab-hide' ) ) {\n\t\t\t\t\ttarget.removeClass( 'warning-tab-hide' );\n\t\t\t\t} else if ( target.hasClass( 'warning-tab' ) ) {\n\t\t\t\t\ttarget.addClass( 'warning-tab-hide' );\n\t\t\t\t} else {\n\t\t\t\t\tcleanTimer( tab_id );\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif ( target.hasClass( 'error-tab-hide' ) ) {\n\t\t\t\t\ttarget.removeClass( 'error-tab-hide' );\n\t\t\t\t} else if ( target.hasClass( 'error-tab' ) ) {\n\t\t\t\t\ttarget.addClass( 'error-tab-hide' );\n\t\t\t\t\tcleanTimer( tab_id );\n\t\t\t\t\tsetTimeout( function() {\n\t\t\t\t\t\tif ( target.hasClass( 'error-tab-hide' ) ) {\n\t\t\t\t\t\t\ttarget.removeClass( 'error-tab-hide' );\n\t\t\t\t\t\t}\n\t\t\t\t\t\t$this.startPulse( tab_id, target, is_warning );\n\t\t\t\t\t}, 1700 );\n\t\t\t\t} else {\n\t\t\t\t\tcleanTimer( tab_id );\n\t\t\t\t}\n\t\t\t}\n\t\t}, 2000 );\n\n\t\tfunction cleanTimer( tab_id ) {\n\t\t\tclearInterval( $this.pulse_time_dic[tab_id] );\n\t\t\t$this.pulse_time_dic[tab_id] = null;\n\t\t}\n\t}\n\n\tsetErrorTipsError( result ) {\n\n\t\t//Error: TypeError: details[0] is undefined in interface/html5/views/BaseViewController.js?v=9.0.0-20150822-105118 line 1883\n\t\t// Zero is not always the firwst index.\n\t\tvar result_array = result.getDetails() ? result.getDetails() : {};\n\t\tvar first_el = 0;\n\t\tfor ( var first_el in result_array ) {\n\t\t\tbreak;\n\t\t}\n\t\tvar error_list = result_array ? result_array[first_el] : {};\n\t\tvar widget;\n\t\tif ( error_list && error_list.hasOwnProperty( 'error' ) ) {\n\t\t\terror_list = error_list.error;\n\t\t}\n\t\tvar found_in_current_tab = false;\n\t\tfor ( var key in error_list ) {\n\t\t\tif ( !error_list.hasOwnProperty( key ) ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( this.edit_view_ui_dic[key] ) && this.edit_view_ui_dic[key].closest( document.documentElement ).length > 0 ) {\n\t\t\t\twidget = this.edit_view_ui_dic[key];\n\t\t\t} else if ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( this.edit_view_ui_validation_field_dic[key] ) ) {\n\t\t\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isArray */ .x.isArray( this.edit_view_ui_validation_field_dic[key] ) ) {\n\t\t\t\t\tvar len = this.edit_view_ui_validation_field_dic[key].length;\n\t\t\t\t\tfor ( var i = 0; i < len; i++ ) {\n\t\t\t\t\t\tvar item = this.edit_view_ui_validation_field_dic[key][i];\n\t\t\t\t\t\tif ( item.closest( document.documentElement ).length > 0 ) {\n\t\t\t\t\t\t\twidget = item;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else if ( this.edit_view_ui_validation_field_dic[key].closest( document.documentElement ).length > 0 ) {\n\t\t\t\t\twidget = this.edit_view_ui_validation_field_dic[key];\n\t\t\t\t} else {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t} else if ( key.indexOf( '_id' ) < 0 && _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( this.edit_view_ui_dic[key + '_id'] ) && this.edit_view_ui_dic[key + '_id'].closest( document.documentElement ).length > 0 ) {\n\t\t\t\twidget = this.edit_view_ui_dic[key + '_id'];\n\t\t\t} else {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif ( widget.is( ':visible' ) ) {\n\t\t\t\t// Error: Uncaught TypeError: widget.setErrorStyle is not a function\n\t\t\t\tif ( widget.setErrorStyle && typeof widget.setErrorStyle == 'function' ) {\n\t\t\t\t\twidget.setErrorStyle( error_list[key], true );\n\t\t\t\t\tfound_in_current_tab = true;\n\t\t\t\t} else {\n\t\t\t\t\tDebug.Text( 'ERROR: widget.setErrorStyle is not a function.', 'BaseViewController.js', 'BaseViewController', null, 10 );\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Error: Uncaught TypeError: widget.setErrorStyle is not a function\n\t\t\t\tif ( widget.setErrorStyle && typeof widget.setErrorStyle == 'function' ) {\n\t\t\t\t\twidget.setErrorStyle( error_list[key] );\n\t\t\t\t} else {\n\t\t\t\t\tDebug.Text( 'ERROR: widget.setErrorStyle is not a function.', 'BaseViewController.js', 'BaseViewController', null, 10 );\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis.showErrorStatusOnTab( widget, true );\n\t\t\tthis.edit_view_error_ui_dic[key] = widget;\n\t\t}\n\t\tif ( !found_in_current_tab ) {\n\t\t\tthis.showEditViewError( result );\n\t\t}\n\t}\n\n\tshowEditViewError( result ) {\n\t\tvar details = result.getDetails()[0];\n\t\tvar isError = true;\n\t\t//Error: TypeError: details is undefined in interface/html5/views/BaseViewController.js?v=9.0.0-20150908-081451 line 2078\n\t\tif ( !details ) {\n\t\t\treturn;\n\t\t}\n\t\tif ( details.hasOwnProperty( 'error' ) ) {\n\t\t\tdetails = details.error;\n\t\t\tisError = true;\n\t\t} else if ( details.hasOwnProperty( 'warning' ) ) {\n\t\t\tisError = false;\n\t\t\tdetails = details.warning;\n\t\t}\n\t\tvar error_string = '';\n\t\tvar background_color = isError ? '#cb2e2e' : '#ffff00';\n\t\tvar color = isError ? '#fff' : '#000';\n\t\tvar border_color = isError ? '#CB2E2E' : '#e7be00';\n\n\t\terror_string = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.convertValidationErrorToString */ .x.convertValidationErrorToString( details );\n\n\t\tthis.removeEditViewErrorTip();\n\t\tthis.edit_view.find('.ui-helper-reset').qtip( {\n\t\t\tshow: {\n\t\t\t\twhen: false,\n\t\t\t\tready: true\n\t\t\t},\n\t\t\tevents: {\n\t\t\t\thide: function( event, api ) {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t}\n\t\t\t},\n\t\t\tcontent: error_string,\n\t\t\tstyle: {\n\t\t\t\tclasses: isError ? 'qtip2-error-tip' : 'qtip2-warning-tip', //used for styling and removal.\n\t\t\t\ttip: {\n\t\t\t\t\tcorner: 'bottom center'\n\t\t\t\t}\n\t\t\t},\n\t\t\tposition: {\n\t\t\t\tmy: 'bottom left',\n\t\t\t\tat: 'top center'\n\t\t\t}\n\t\t} );\n\t}\n\n\topenEditView() {\n\t\tif ( !this.edit_view ) {\n\t\t\tthis.initEditViewUI( this.viewId, this.edit_view_tpl );\n\t\t}\n\t}\n\n\tsetTabOVisibility( flag ) {\n\t\tvar tab0 = $( this.edit_view_tab.find( '.edit-view-tab' )[0] );\n\t\tif ( flag ) {\n\t\t\ttab0.css( 'opacity', 1 );\n\t\t\tthis.setEditViewTabSize();\n\t\t\tif ( this.edit_view_close_icon ) {\n\t\t\t\tthis.edit_view_close_icon.show();\n\t\t\t}\n\t\t} else {\n\t\t\tthis.edit_view_tab.find( 'ul li' ).hide();\n\t\t\ttab0.css( 'opacity', 0 );\n\t\t}\n\t}\n\n\t//set widget disablebility if view mode or edit mode\n\tsetEditViewWidgetsMode() {\n\t\tvar did_clean_dic = {};\n\t\tfor ( var key in this.edit_view_ui_dic ) {\n\t\t\tif ( !this.edit_view_ui_dic.hasOwnProperty( key ) ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tvar widget = this.edit_view_ui_dic[key];\n\t\t\twidget.css( 'opacity', 1 );\n\t\t\tvar column = widget.parent().parent().parent();\n\t\t\tvar tab_id = column.parent().attr( 'id' );\n\t\t\tif ( !column.hasClass( 'v-box' ) ) {\n\t\t\t\tif ( !did_clean_dic[tab_id] ) {\n\t\t\t\t\tdid_clean_dic[tab_id] = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif ( this.is_viewing ) {\n\t\t\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( widget.setEnabled ) ) {\n\t\t\t\t\twidget.setEnabled( false );\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( widget.setEnabled ) ) {\n\t\t\t\t\twidget.setEnabled( true );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t//Call this when edit view open\n\tinitEditViewUI( view_id, edit_view_file_name ) {\n\t\t_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.setUINotready */ .x.setUINotready();\n\t\tTTPromise.add( 'init', 'init' );\n\t\tTTPromise.wait();\n\n\t\tvar $this = this;\n\t\tif ( this.edit_view ) {\n\t\t\tthis.edit_view.remove();\n\t\t}\n\n\t\tthis.edit_view = $( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.loadViewSource */ .x.loadViewSource( view_id, edit_view_file_name, null, true ) );\n\n\t\tthis.edit_view_tab = $( this.edit_view.find( '.edit-view-tab-bar' ) );\n\t\tthis.edit_view_tab.css( 'opacity', 0 );\n\n\t\t//Give edt view tab a id, so we can load it when put right click menu on it\n\t\tthis.edit_view_tab.attr( 'id', this.ui_id + '_edit_view_tab' );\n\n\t\t// Moved into generic BaseView.initEditViewTabs\n\t\t// this.setTabOVisibility( false );\n\n\t\t// this.edit_view_tab = this.edit_view_tab.tabs( {\n\t\t// \tactivate: function( e, ui ) {\n\t\t// \t\tif ( !$this.edit_view_tab || !$this.edit_view_tab.is( ':visible' ) ) {\n\t\t// \t\t\treturn;\n\t\t// \t\t}\n\t\t//\n\t\t// \t\t$this.onTabShow( e, ui );\n\t\t// \t\tGlobal.triggerAnalyticsTabs( e, ui );\n\t\t// \t}\n\t\t// } );\n\n\t\t// this.edit_view_tab.off( 'click' ).on( 'click', function( e ) {\n\t\t// \t$this.onTabIndexChange( e );\n\t\t// } );\n\n\t\t_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.contentContainer */ .x.contentContainer().append( this.edit_view );\n\n\t\t// Moved to buildEditViewUI, as the init might only be called once, and the context menu needs to be rebuilt on every view build.\n\t\t// // After we add the edit_view to the page, add the context menu (Vue needs a valid id in dom)\n\t\t// if( ContextMenuManager.getMenu( this.determineContextMenuMountAttributes().id ) === undefined ) {\n\t\t// \tthis.buildContextMenu();\n\t\t// }\n\t\t// #VueContextMenu#Dynamic-EditView Once edit view html has loaded and mounted to DOM, then insert container for context_menu and initialise menu.\n\n\t\t// Testing to see if just having the code in buildContextMenu is enough.\n\t\t// if( !this.edit_view_context_menu ) {\n\t\t// \tvar context_menu_id = 'contextmenu-' + this.edit_view_tab.attr( 'id' );\n\t\t// \tthis.edit_view_context_menu = new ContextMenuManager( context_menu_id ); // #VueContextMenu# Initialize Vue ContextMenuManager here so that each view has their own unique one. Currently we are sharing one contextmenu, but most views use their own context menu manager instance. (Not required, just simplifies the refactor for now, and it might be used in future).\n\t\t//\n\t\t// \t// Create dynamic container for the vue context menu\n\t\t// \t// this.edit_view_context_menu.setContextMenuId( 'contextmenu-' + this.edit_view_tab.attr( 'id' ) ); // TODO: Potentially move this into param for constructor.\n\t\t// \tthis.edit_view_tab.prepend('');\n\t\t//\n\t\t// \t// Create and mount unique context menu for this view.\n\t\t// \tthis.edit_view_context_menu.mountContextMenu( '#' + this.edit_view_context_menu.menu_id );\n\t\t//\n\t\t// } else {\n\t\t// \t// If each view has a unique context menu, then this should never happen, as context menu should only be initiated once.\n\t\t// \t// However, there are many cases where tabs repeatedly call this.buildContextMenu, whilst keeping the same view controller, so this is now a warning rather than an error.\n\t\t// \tDebug.Text( 'Context Menu Manager already exists for: '+ this.viewId, 'BaseViewController.js', 'BaseViewController', 'buildContextMenu', 10 );\n\t\t// }\n\n\t\tthis.buildEditViewUI();\n\n\t\t$this.setEditViewTabHeight();\n\t\tTTPromise.wait( 'init', 'init', function() {\n\t\t\t$( '.edit-view-tab-bar' ).css( 'opacity', 1 );\n\t\t} );\n\t}\n\n\tsetEditViewTabHeight() {\n\t\tvar $this = this;\n\t}\n\n\t//Call this after initEditViewUI, usually after current_edit_record is set\n\tinitEditView() {\n\t\tthis.show_warning_when_validation = false;\n\t\t//Uncaught TypeError: Cannot read property 'find' of null in Timehseet Authorization view when quickly click Cancel from replay\n\t\tif ( !this.edit_view_tab ) {\n\t\t\treturn;\n\t\t}\n\t\tthis.setURL();\n\n\t\t// Overrides form with data from push notification and http get variables.\n\t\tthis.fillCurrentRecord();\n\n\t\tthis.setEditMenu(); //This is done in onTabeShow() later on, so it can probably be removed from here?\n\t\t//Remove cover once edit menu is set\n\t\tProgressBar.closeOverlay();\n\n\t\t//Error: Unable to get property 'find' of undefined or null reference in /interface/html5/views/BaseViewController.js?v=7.4.6-20141027-074127 line 2055\n\t\tif ( this.edit_view_tab ) {\n\t\t\tthis.edit_view_tab.find( 'ul li' ).show(); // All tabs are hidden when initEditView UI, show all of them before set status\n\t\t}\n\t\tthis.setTabStatus();\n\t\tthis.clearEditViewData();\n\t\tthis.setEditViewWidgetsMode();\n\t\tthis.setEditViewData();\n\t\tthis.setCustomFields();\n\t\tthis.setFocusToFirstInput();\n\t}\n\n\tsetCustomFields() {\n\t\tvar parent_table = this.getCustomFieldParentTable();\n\n\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.getFeatureFlag */ .x.getFeatureFlag( 'custom_field' ) == false || LocalCacheData.getCustomFieldData().parent_tables.includes( parent_table ) == false ) {\n\t\t\treturn;\n\t\t}\n\n\t\tTTPromise.wait( 'BaseViewController', 'getCustomFields', function() {\n\t\t\tif ( Array.isArray( this.custom_fields ) ) {\n\t\t\t\tthis.custom_fields.forEach( ( custom_field ) => {\n\t\t\t\t\tthis.buildCustomFieldUI( this.getPrefixedCustomFieldID( custom_field.id ), custom_field.name, custom_field.type_id, custom_field.meta_data );\n\t\t\t\t} );\n\n\t\t\t\tthis.editFieldResize( 0 );\n\t\t\t}\n\n\t\t\tthis.resetLastWidgetStyle();\n\t\t}.bind( this ) );\n\t}\n\n\tgetPrefixedCustomFieldID( id ) {\n\t\treturn 'custom_field-' + id;\n\t}\n\n\tgetCustomFieldsForView() {\n\t\tvar $this = this;\n\t\tvar parent_table = this.getCustomFieldParentTable();\n\n\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.getFeatureFlag */ .x.getFeatureFlag( 'custom_field' ) == false || LocalCacheData.getCustomFieldData().parent_tables.includes( parent_table ) == false ) {\n\t\t\tTTPromise.resolve( 'BaseViewController', 'getCustomFields' );\n\t\t\treturn;\n\t\t}\n\n\t\tvar filter = { filter_data: { parent_table: parent_table, status_id: 10 }, filter_sort: { display_order: 'asc', created_date: 'asc', id: 'asc' } };\n\n\t\tthis.custom_field_api.getCustomField( filter, true, {\n\t\t\tonResult: function( result ) {\n\t\t\t\tvar res_data = result.getResult();\n\t\t\t\tif ( Array.isArray( res_data ) ) {\n\t\t\t\t\t$this.custom_fields = res_data;\n\t\t\t\t}\n\n\t\t\t\tTTPromise.resolve( 'BaseViewController', 'getCustomFields' );\n\t\t\t}\n\t\t} );\n\t}\n\n\tgetCustomFieldReferenceField() {\n\t\treturn false;\n\t}\n\n\tbuildCustomFieldUI( field, label, type_id, meta_data ) {\n\n\t\tif ( !type_id ) {\n\t\t\treturn; //User does not have permissions to use custom fields\n\t\t}\n\n\t\tfield = this.convertCustomFieldFieldId( type_id, field );\n\n\t\tif ( this.getCustomFieldParentTable() === 'punch_control' ) {\n\t\t\t//Permissions can be dynamic for punch control custom fields and we need to check for them.\n\t\t\t//Permissions are for the non-'_id' custom fields.\n\t\t\tlet custom_field_id = field.replace( '_id', '' );\n\t\t\tif ( PermissionManager.validate( this.permission_id, 'edit_' + custom_field_id ) == false ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\tif ( !this.edit_view_tab ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar form_item_input;\n\t\tvar $this = this;\n\t\tvar tab0 = $( this.edit_view_tab.find( '.edit-view-tab-outside' )[0] );\n\t\tvar tab0_column1 = tab0.find( '.first-column' );\n\n\t\tif ( $this.edit_view_ui_dic[field] ) {\n\t\t\tform_item_input = $this.edit_view_ui_dic[field];\n\t\t\tform_item_input.setValue( $this.current_edit_record[field] );\n\t\t} else {\n\t\t\tlet form_array = $this.getCustomFieldFormInputByType( type_id, field, meta_data );\n\t\t\tform_item_input = form_array[0];\n\t\t\tlet widget_container = form_array[1];\n\n\t\t\tvar input_div = $this.addEditFieldToColumn( label, form_item_input, tab0_column1, '', widget_container );\n\t\t\tif ( this.getCustomFieldReferenceField() !== false && $this.edit_view_ui_dic[this.getCustomFieldReferenceField()] != undefined ) {\n\t\t\t\tinput_div.insertBefore( $this.edit_view_ui_dic[this.getCustomFieldReferenceField()].parent().parent() );\n\t\t\t}\n\n\t\t\tif ( this.current_edit_record ) {\n\t\t\t\tform_item_input.setValue( this.current_edit_record[field] );\n\t\t\t}\n\t\t}\n\t\tform_item_input.css( 'opacity', 1 );\n\n\t\tif ( $this.is_viewing ) {\n\t\t\tform_item_input.setEnabled( false );\n\t\t} else {\n\t\t\tform_item_input.setEnabled( true );\n\t\t}\n\n\t\tif ( this.is_mass_editing ) {\n\t\t\tform_item_input.setMassEditMode( true );\n\t\t}\n\t}\n\n\tconvertCustomFieldFieldId( type_id, field ) {\n\t\tif ( LocalCacheData.getCustomFieldData().conversion_field_types[type_id] ) {\n\t\t\treturn field + '_id';\n\t\t}\n\t\treturn field;\n\t}\n\n\tgetCustomFieldFormInputByType( type_id, field, meta_data ) {\n\t\tlet form_item_input;\n\t\tlet widget_container = null;\n\n\t\ttype_id = parseInt( type_id ); //Switch is strict on type, so we need to parseInt()\n\n\t\tswitch ( type_id ) {\n\t\t\tcase 100: //Text\n\t\t\t\tform_item_input = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.loadWidgetByName */ .x.loadWidgetByName( _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.FormItemType.TEXT_INPUT );\n\t\t\t\tform_item_input.TTextInput( { field: field } );\n\t\t\t\tform_item_input.css( 'minWidth', 300 );\n\t\t\t\tbreak;\n\t\t\tcase 110: //Textarea\n\t\t\t\tform_item_input = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.loadWidgetByName */ .x.loadWidgetByName( _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.FormItemType.TEXT_AREA );\n\t\t\t\tform_item_input.TTextArea( { field: field, width: '100%' } );\n\t\t\t\tbreak;\n\t\t\tcase 400: //Integer\n\t\t\tcase 410: //Decimal\n\t\t\t\tform_item_input = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.loadWidgetByName */ .x.loadWidgetByName( _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.FormItemType.TEXT_INPUT );\n\t\t\t\tform_item_input.TTextInput( { field: field } );\n\t\t\t\tform_item_input.css( 'minWidth', 300 );\n\t\t\t\tbreak;\n\t\t\tcase 420: //Currency\n\t\t\t\tform_item_input = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.loadWidgetByName */ .x.loadWidgetByName( _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.FormItemType.TEXT_INPUT );\n\t\t\t\tform_item_input.TTextInput( { field: field } );\n\t\t\t\tform_item_input.css( 'minWidth', 300 );\n\n\t\t\t\tvar widgetContainer = $( '' );\n\t\t\t\tlet currency = $( '' );\n\t\t\t\tlet code = $( '' );\n\n\t\t\t\twidgetContainer.append( currency );\n\t\t\t\twidgetContainer.append( form_item_input );\n\t\t\t\twidgetContainer.append( code );\n\t\t\t\tbreak;\n\t\t\tcase 500: //Checkbox\n\t\t\t\tform_item_input = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.loadWidgetByName */ .x.loadWidgetByName( _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.FormItemType.CHECKBOX );\n\t\t\t\tform_item_input.TCheckbox( { field: field } );\n\t\t\t\tbreak;\n\t\t\tcase 1000: //Date\n\t\t\t\tform_item_input = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.loadWidgetByName */ .x.loadWidgetByName( _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.FormItemType.DATE_PICKER );\n\t\t\t\tform_item_input.TDatePicker( { field: field } );\n\t\t\t\tbreak;\n\t\t\tcase 1010: //Date Range\n\t\t\t\tform_item_input = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.loadWidgetByName */ .x.loadWidgetByName( _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.FormItemType.DATE_PICKER );\n\t\t\t\tform_item_input.TRangePicker( { field: field, validation_field: 'date_stamp' } );\n\t\t\t\tbreak;\n\t\t\tcase 1100: //Time\n\t\t\t\tform_item_input = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.loadWidgetByName */ .x.loadWidgetByName( _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.FormItemType.TIME_PICKER );\n\t\t\t\tform_item_input.TTimePicker( { field: field } );\n\t\t\t\tbreak;\n\t\t\tcase 1110: //Time Range\n\t\t\t\t//TODO: Jeremy Time Range\n\t\t\t\tbreak;\n\t\t\tcase 1200: //Datetime\n\t\t\t\tform_item_input = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.loadWidgetByName */ .x.loadWidgetByName( _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.FormItemType.DATE_PICKER );\n\t\t\t\tform_item_input.TDatePicker( { field: field, mode: 'date_time' } );\n\t\t\t\tbreak;\n\t\t\tcase 1300: //Time Unit\n\t\t\t\tform_item_input = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.loadWidgetByName */ .x.loadWidgetByName( _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.FormItemType.TEXT_INPUT );\n\t\t\t\tform_item_input.TTextInput( { field: field, width: 120, mode: 'time_unit', need_parser_sec: true } );\n\t\t\t\tbreak;\n\t\t\tcase 2100: //Single-select Dropdown\n\t\t\t\tform_item_input = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.loadWidgetByName */ .x.loadWidgetByName( _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.FormItemType.AWESOME_BOX );\n\t\t\t\tform_item_input.AComboBox( {\n\t\t\t\t\tallow_multiple_selection: false,\n\t\t\t\t\tlayout_name: 'global_option_column', //Need dynamic layout name? global_option_column\n\t\t\t\t\tshow_search_inputs: true,\n\t\t\t\t\tset_empty: true,\n\t\t\t\t\tfield: field\n\t\t\t\t} );\n\t\t\t\tform_item_input.setSourceData( meta_data.validation.multi_select_items );\n\t\t\t\tbreak;\n\t\t\tcase 2110: //Multi-select Dropdown\n\t\t\t\tform_item_input = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.loadWidgetByName */ .x.loadWidgetByName( _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.FormItemType.AWESOME_BOX );\n\t\t\t\tform_item_input.AComboBox( {\n\t\t\t\t\tallow_multiple_selection: true,\n\t\t\t\t\tlayout_name: 'global_option_column', //Need dynamic layout name? global_option_column\n\t\t\t\t\tshow_search_inputs: true,\n\t\t\t\t\tset_empty: true,\n\t\t\t\t\tfield: field\n\t\t\t\t} );\n\t\t\t\tform_item_input.setSourceData( meta_data.validation.multi_select_items );\n\t\t}\n\n\t\treturn [form_item_input, widget_container];\n\t}\n\n\tresetLastWidgetStyle() {\n\n\t\tif ( !this.edit_view_tab || !this.edit_view ) {\n\t\t\treturn;\n\t\t}\n\t}\n\n\tgetCustomFieldParentTable() {\n\t\t//Punch views get their custom fields from the punch_control table.\n\t\tif ( this.table_name_key === 'punch' ) {\n\t\t\treturn 'punch_control';\n\t\t} else if ( this.viewId === 'TimeSheet' ) { //Timesheet view does not declare a table_name_key\n\t\t\treturn 'punch_control';\n\t\t}\n\n\t\treturn this.table_name_key;\n\t}\n\n\tsetURL() {\n\t\tvar a = '';\n\t\tswitch ( LocalCacheData.current_doing_context_action ) {\n\t\t\tcase 'new':\n\t\t\tcase 'edit':\n\t\t\tcase 'view':\n\t\t\t\ta = LocalCacheData.current_doing_context_action;\n\t\t\t\tbreak;\n\t\t\tcase 'copy_as_new':\n\t\t\t\ta = 'new';\n\t\t\t\tbreak;\n\t\t}\n\t\tif ( this.canSetURL() ) {\n\n\t\t\tvar tab_name = this.edit_view_tab ? this.edit_view_tab.find( '.edit-view-tab-bar-label' ).children().eq( this.getEditViewTabIndex() ).text() : '';\n\t\t\ttab_name = tab_name.replace( /\\/|\\s+/g, '' );\n\n\t\t\t//Error: Unable to get property 'id' of undefined or null reference in /interface/html5/views/BaseViewController.js?v=8.0.0-20141117-132941 line 2234\n\t\t\tif ( this.current_edit_record && this.current_edit_record.id ) {\n\t\t\t\tif ( a ) {\n\t\t\t\t\t_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.setURLToBrowser */ .x.setURLToBrowser( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.getBaseURL */ .x.getBaseURL() + '#!m=' + this.viewId + '&a=' + a + '&id=' + this.current_edit_record.id + '&tab=' + tab_name );\n\t\t\t\t} else {\n\t\t\t\t\t_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.setURLToBrowser */ .x.setURLToBrowser( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.getBaseURL */ .x.getBaseURL() + '#!m=' + this.viewId + '&id=' + this.current_edit_record.id );\n\t\t\t\t}\n\n\t\t\t\t_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.trackView */ .x.trackView( this.viewId, LocalCacheData.current_doing_context_action );\n\t\t\t} else {\n\t\t\t\tif ( a ) {\n\n\t\t\t\t\t//Edit a record which don't have id, schedule view Recurring Scedule\n\t\t\t\t\tif ( a === 'edit' ) {\n\t\t\t\t\t\t_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.setURLToBrowser */ .x.setURLToBrowser( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.getBaseURL */ .x.getBaseURL() + '#!m=' + this.viewId + '&a=' + 'new' +\n\t\t\t\t\t\t\t'&tab=' + tab_name );\n\t\t\t\t\t} else {\n\t\t\t\t\t\t_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.setURLToBrowser */ .x.setURLToBrowser( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.getBaseURL */ .x.getBaseURL() + '#!m=' + this.viewId + '&a=' + a +\n\t\t\t\t\t\t\t'&tab=' + tab_name );\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\t\t\t\t\t_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.setURLToBrowser */ .x.setURLToBrowser( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.getBaseURL */ .x.getBaseURL() + '#!m=' + this.viewId );\n\t\t\t\t}\n\t\t\t}\n\n\t\t}\n\t}\n\n\tcanSetURL() {\n\t\tif ( this.sub_view_mode || this.edit_only_mode ) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn true;\n\t}\n\n\tsetFocusToFirstInput() {\n\t\t//Do not set focus to first input in unit test mode as it causes a blink that is inconsistent in screenshots. Also disable on mobile mode so its not a jarring experience with the zoom changes on each page\n\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.UNIT_TEST_MODE */ .x.UNIT_TEST_MODE || $( 'body' ).hasClass( 'mobile-device-mode' ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( !this.is_viewing ) {\n\t\t\tif ( this.script_name === 'ScheduleView' ) {\n\t\t\t\tif ( this.edit_view_ui_dic.start_time ) {\n\t\t\t\t\tthis.edit_view_ui_dic.start_time.children().eq( 0 ).focus();\n\t\t\t\t\tthis.edit_view_ui_dic.start_time.children().eq( 0 )[0].select();\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor ( var key in this.edit_view_ui_dic ) {\n\n\t\t\t\t\tif ( !this.edit_view_ui_dic.hasOwnProperty( key ) ) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tvar widget = this.edit_view_ui_dic[key];\n\n\t\t\t\t\tif ( widget.is( ':visible' ) === true ) {\n\t\t\t\t\t\tif ( widget.hasClass( 't-text-input' ) && !widget.attr( 'readonly' ) ) {\n\t\t\t\t\t\t\twidget.focus();\n\t\t\t\t\t\t\twidget[0].select();\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t} else if ( widget.hasClass( 't-time-picker-div' ) && !widget.children().eq( 0 ).attr( 'readonly' ) ) {\n\t\t\t\t\t\t\twidget.children().eq( 0 ).focus();\n\t\t\t\t\t\t\twidget.children().eq( 0 )[0].select();\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t} else if ( widget.hasClass( 't-date-picker-div' ) && !widget.children().eq( 0 ).attr( 'readonly' ) ) {\n\t\t\t\t\t\t\twidget.children().eq( 0 ).focus();\n\t\t\t\t\t\t\twidget.children().eq( 0 )[0].select();\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\t\t\t}\n\n\t\t}\n\t}\n\n\tinitNavigationWidget( navigation_widget_div ) {\n\t\tif ( !this.navigation ) {\n\t\t\tthis.navigation = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.loadWidgetByName */ .x.loadWidgetByName( _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.FormItemType.AWESOME_BOX );\n\t\t\tnavigation_widget_div.append( this.navigation );\n\t\t} else {\n\t\t\tnavigation_widget_div.append( this.navigation );\n\t\t}\n\t\tthis.setNavigationArrowsStatus();\n\t}\n\n\tbuildEditViewUI() {\n\t\tvar $this = this;\n\n\t\t//No navigation when edit only mode\n\n\t\t// #VueContextMenu# After we add the edit_view to the page in initEditViewUI(), add the context menu (Vue needs a valid id in dom)\n\t\tif( ContextMenuManager.getMenu( this.determineContextMenuMountAttributes().id ) === undefined ) {\n\t\t\tthis.buildContextMenu();\n\t\t} else {\n\t\t\tDebug.Warn( 'Context Menu ('+ this.determineContextMenuMountAttributes().id +') already exists for: '+ this.viewId, 'BaseViewController.js', 'BaseViewController', 'buildEditViewUI', 10 );\n\t\t}\n\n\t\tif ( this.edit_view ) {\n\t\t\tif ( !this.edit_only_mode ) {\n\t\t\t\tvar navigation_div = this.edit_view.find( '.navigation-div' );\n\t\t\t\tvar label = navigation_div.find( '.navigation-label' );\n\t\t\t\tvar left_click = navigation_div.find( '.left-click' );\n\t\t\t\tvar right_click = navigation_div.find( '.right-click' );\n\t\t\t\tvar navigation_widget_div = navigation_div.find( '.navigation-widget-div' );\n\t\t\t\tthis.initNavigationWidget( navigation_widget_div );\n\t\t\t\tleft_click.attr( 'src', _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.getRealImagePath */ .x.getRealImagePath( 'images/left_arrow.svg' ) );\n\t\t\t\tright_click.attr( 'src', _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.getRealImagePath */ .x.getRealImagePath( 'images/right_arrow.svg' ) );\n\t\t\t\tlabel.text( this.navigation_label );\n\n\t\t\t}\n\n\t\t\tthis.edit_view_close_icon = this.edit_view.find( '.close-icon' );\n\t\t\tthis.edit_view_close_icon.hide();\n\n\t\t\tthis.edit_view_close_icon.click( function() {\n\t\t\t\t$this.onCloseIconClick();\n\t\t\t} );\n\t\t}\n\n\t\tif( this.edit_only_mode ) {\n\n\t\t}\n\n\t\tthis.edit_view_ui_dic = {};\n\t\tthis.edit_view_ui_validation_field_dic = {};\n\t\tthis.edit_view_form_item_dic = {};\n\t\tthis.edit_view_error_ui_dic = {};\n\t}\n\n\tonCloseIconClick() {\n\t\tthis.onCancelClick();\n\t\t_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.triggerAnalyticsNavigationOther */ .x.triggerAnalyticsNavigationOther( 'close-X', 'click', this.viewId );\n\t}\n\n\tsetWidgetVisible( widgets ) {\n\t\tvar widget = widgets;\n\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isArray */ .x.isArray( widgets ) ) {\n\t\t\tfor ( var i = 0; i < widgets.length; i++ ) {\n\t\t\t\twidget = widgets[i];\n\t\t\t\twidget.css( 'opacity', 1 );\n\t\t\t}\n\t\t} else {\n\t\t\twidget.css( 'opacity', 1 );\n\t\t}\n\t}\n\n\t//widgetContainer: add widget to custom container\n\t//saveFormItemDiv: if cache current formItemDiv and use it later\n\taddEditFieldToColumn( label, widgets, column, firstOrLastRecord, widgetContainer, saveFormItemDiv, setResizeEvent, saveFormItemDivKey, hasKeyEvent, customLabelWidget ) {\n\n\t\tvar $this = this;\n\t\tvar form_item = $( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.loadWidgetByName */ .x.loadWidgetByName( _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.WidgetNamesDic.EDIT_VIEW_FORM_ITEM ) );\n\t\tvar form_item_label_div = form_item.find( '.edit-view-form-item-label-div' );\n\t\tvar form_item_label = form_item.find( '.edit-view-form-item-label' );\n\t\tvar form_item_input_div = form_item.find( '.edit-view-form-item-input-div' );\n\t\tvar widget = widgets;\n\n\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isArray */ .x.isArray( widgets ) ) {\n\t\t\tfor ( var i = 0; i < widgets.length; i++ ) {\n\t\t\t\twidget = widgets[i];\n\t\t\t\twidget.css( 'opacity', 0 );\n\t\t\t}\n\t\t} else {\n\t\t\twidget.css( 'opacity', 0 );\n\t\t}\n\n\t\tif ( customLabelWidget ) {\n\t\t\tform_item_label.parent().append( customLabelWidget );\n\t\t\tform_item_label.remove();\n\t\t} else {\n\t\t\tform_item_label.text( label ); // Remove ':' to match Figma design.\n\t\t\tif ( label && label.indexOf( '\\n' ) !== -1 ) {\n\t\t\t\tform_item_label.html( form_item_label.html().replace( /\\n/g, ' ' ) ); //Allow newlines (\\n) to be accepted in labels. Used by T4 Report. Use this instead of .html() directly as its introduces XSS\n\t\t\t}\n\t\t}\n\n\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( widgetContainer ) ) {\n\n\t\t\tform_item_input_div.append( widgetContainer );\n\n\t\t} else {\n\t\t\tform_item_input_div.append( widget );\n\t\t}\n\n\t\tcolumn.append( form_item );\n\n\t\t//set height to text area\n\t\tif ( form_item.height() > 35 ) {\n\t\t\tform_item_label_div.css( 'height', form_item.height() );\n\t\t} else if ( widget.hasClass( 'a-dropdown' ) ) {\n\t\t\tform_item_label_div.css( 'height', 240 );\n\t\t}\n\n\t\t//these aren't hit uniformly for every field so the vertical resize events will be disabled in unit test mode.\n\t\tif ( setResizeEvent && !_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.UNIT_TEST_MODE */ .x.UNIT_TEST_MODE ) {\n\t\t\tform_item.unbind( 'resize' ).bind( 'resize', function() {\n\t\t\t\t//When switching tabs, the heights are all -1, which causes \"flashing\" when the user returns back to the original tab and all the heights need to be set again.\n\t\t\t\t// To prevent this, only change heights if they are > 0.\n\t\t\t\tif ( form_item_label_div.height() !== form_item.height() && form_item.height() > 0 ) {\n\t\t\t\t\tform_item_label_div.css( 'height', form_item.height() );\n\t\t\t\t}\n\t\t\t} );\n\t\t\twidget.unbind( 'setSize' ).bind( 'setSize', function() {\n\t\t\t\tform_item_label_div.css( 'height', widget.height() + 10 );\n\t\t\t} );\n\t\t}\n\n\t\tif ( !label ) {\n\t\t\tform_item_input_div.remove();\n\t\t\tform_item_label_div.remove();\n\n\t\t\tform_item.append( widget );\n\t\t\twidget.css( 'opacity', 1 );\n\n\t\t\tif ( saveFormItemDiv && saveFormItemDivKey ) {\n\t\t\t\tthis.edit_view_form_item_dic[saveFormItemDivKey] = form_item;\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\n\t\tif ( saveFormItemDiv ) {\n\n\t\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isArray */ .x.isArray( widgets ) ) {\n\t\t\t\tthis.edit_view_form_item_dic[widgets[0].getField()] = form_item;\n\t\t\t} else {\n\t\t\t\tthis.edit_view_form_item_dic[widget.getField()] = form_item;\n\t\t\t}\n\n\t\t}\n\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isArray */ .x.isArray( widgets ) ) {\n\n\t\t\tfor ( var i = 0; i < widgets.length; i++ ) {\n\t\t\t\twidget = widgets[i];\n\t\t\t\tthis.edit_view_ui_dic[widget.getField()] = widget;\n\t\t\t\tsetValidationDic();\n\n\t\t\t\twidget.unbind( 'formItemChange' ).bind( 'formItemChange', function( e, target, doNotValidate ) {\n\t\t\t\t\t$this.onFormItemChange( target, doNotValidate );\n\t\t\t\t} );\n\n\t\t\t\tif ( hasKeyEvent ) {\n\t\t\t\t\twidget.unbind( 'formItemKeyUp' ).bind( 'formItemKeyUp', function( e, target ) {\n\t\t\t\t\t\t$this.onFormItemKeyUp( target );\n\t\t\t\t\t} );\n\n\t\t\t\t\twidget.unbind( 'formItemKeyDown' ).bind( 'formItemKeyDown', function( e, target ) {\n\t\t\t\t\t\t$this.onFormItemKeyDown( target );\n\t\t\t\t\t} );\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tthis.edit_view_ui_dic[widget.getField()] = widget;\n\t\t\tsetValidationDic();\n\n\t\t\twidget.bind( 'formItemChange', function( e, target, doNotValidate ) {\n\t\t\t\t$this.onFormItemChange( target, doNotValidate );\n\t\t\t} );\n\n\t\t\tif ( hasKeyEvent ) {\n\t\t\t\twidget.bind( 'formItemKeyUp', function( e, target ) {\n\t\t\t\t\t$this.onFormItemKeyUp( target );\n\t\t\t\t} );\n\n\t\t\t\twidget.bind( 'formItemKeyDown', function( e, target ) {\n\t\t\t\t\t$this.onFormItemKeyDown( target );\n\t\t\t\t} );\n\t\t\t}\n\t\t}\n\n\t\tfunction setValidationDic() {\n\t\t\tif ( widget.hasOwnProperty( 'getValidationField' ) && widget.getValidationField() ) {\n\t\t\t\tif ( $this.edit_view_ui_validation_field_dic[widget.getValidationField()] ) {\n\t\t\t\t\tif ( !_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isArray */ .x.isArray( $this.edit_view_ui_validation_field_dic[widget.getValidationField()] ) ) {\n\t\t\t\t\t\t$this.edit_view_ui_validation_field_dic[widget.getValidationField()] = [$this.edit_view_ui_validation_field_dic[widget.getValidationField()], widget];\n\t\t\t\t\t} else {\n\t\t\t\t\t\t$this.edit_view_ui_validation_field_dic[widget.getValidationField()].push( widget );\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t$this.edit_view_ui_validation_field_dic[widget.getValidationField()] = widget;\n\t\t\t\t}\n\n\t\t\t}\n\t\t}\n\n\t\treturn form_item;\n\t}\n\n\t//Set fields label to same size\n\teditFieldResize( index ) {\n\n\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( index ) ) {\n\n\t\t} else {\n\t\t\tindex = this.getEditViewTabIndex();\n\t\t}\n\n\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( this.edit_view_tabs[index] ) && !_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isFalseOrNull */ .x.isFalseOrNull( this.edit_view_tabs[index] ) && this.edit_view_tabs[index].length > 0 ) {\n\t\t\tvar tab_div = this.edit_view_tabs[index];\n\t\t\tfor ( var i = 0; i < tab_div.length; i++ ) {\n\t\t\t\tvar tab_column_div = tab_div[i].find( '.edit-view-form-item-label-div' );\n\t\t\t\tvar tab_column_sub_div = tab_div[i].find( '.edit-view-form-item-sub-label-div > span' );\n\t\t\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( tab_column_sub_div ) && tab_column_sub_div.length > 0 ) {\n\t\t\t\t\tthis.setEditFieldSize( tab_column_sub_div );\n\t\t\t\t}\n\t\t\t\tthis.setEditFieldSize( tab_column_div );\n\t\t\t}\n\t\t}\n\t}\n\n\tsetEditFieldSize( tab_column_div, width ) {\n\n\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( width ) ) {\n\n\t\t\ttab_column_div.each( function() {\n\t\t\t\t$( this ).width( width );\n\t\t\t} );\n\n\t\t} else {\n\n\t\t\tvar item_label_div_width = [];\n\t\t\ttab_column_div.each( function() {\n\n\t\t\t\tif ( $( this ).width() === 0 ) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\n\t\t\t\t$( this ).css( 'width', 'auto' );\n\n\t\t\t\titem_label_div_width.push( $( this ).width() );\n\t\t\t} );\n\n\t\t\titem_label_div_width.sort( function( a, b ) {\n\t\t\t\treturn ( b - a );\n\t\t\t} );\n\n\t\t\ttab_column_div.each( function() {\n\t\t\t\tif ( item_label_div_width[0] >= 0 ) { // #2701 - Do not set width if value is negative. Happens when trying to calculate width of something on another tab not currently visible.\n\t\t\t\t\t$( this ).width( item_label_div_width[0] + 1 );\n\t\t\t\t}\n\t\t\t} );\n\t\t}\n\t}\n\n\tsetNavigation() {\n\n\t\tvar $this = this;\n\n\t\t//Error: Unable to get value of the property 'getGridParam': object is null or undefined in /interface/html5/views/BaseViewController.js?v=8.0.0-20141230-103725 line 2575\n\t\tif ( !this.grid ) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.navigation.setPossibleDisplayColumns( this.buildDisplayColumnsByColumnModel( this.grid.getColumnModel() ), this.buildDisplayColumns( this.default_display_columns ) );\n\t\tthis.navigation.unbind( 'onClose' ).bind( 'onClose', () => {\n\t\t\tthis.setNavigationArrowsEnabled();\n\t\t} );\n\t\tthis.navigation.unbind( 'formItemChange' ).bind( 'formItemChange', function( e, target ) {\n\n\t\t\tvar key = target.getField();\n\t\t\tvar next_select_item_id = target.getValue();\n\n\t\t\tif ( !next_select_item_id ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( next_select_item_id !== $this.current_edit_record.id ) {\n\t\t\t\tProgressBar.showOverlay();\n\n\t\t\t\tif ( $this.is_viewing ) {\n\t\t\t\t\t$this.onViewClick( next_select_item_id ); //Dont refresh UI\n\t\t\t\t} else {\n\t\t\t\t\t$this.onEditClick( next_select_item_id ); //Dont refresh UI\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\t_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.triggerAnalyticsEditViewNavigation */ .x.triggerAnalyticsEditViewNavigation( 'navigation', $this.viewId );\n\n\t\t} );\n\t}\n\n\tclearEditViewData() {\n\t\tfor ( var key in this.edit_view_ui_dic ) {\n\t\t\tif ( !this.edit_view_ui_dic.hasOwnProperty( key ) ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif ( _.isFunction( this.edit_view_ui_dic[key].setEmptyValueAndShowLoading ) ) {\n\t\t\t\tthis.edit_view_ui_dic[key].setEmptyValueAndShowLoading();\n\t\t\t} else {\n\t\t\t\tthis.edit_view_ui_dic[key].setValue( null );\n\t\t\t}\n\t\t\tthis.edit_view_ui_dic[key].clearErrorStyle();\n\t\t}\n\t}\n\n\t//Called after set current_edit_record\n\tsetEditViewData() {\n\t\tthis.is_changed = false;\n\t\tthis.initEditViewData();\n\t\tthis.initTabData();\n\t\tthis.switchToProperTab();\n\t}\n\n\tswitchToProperTab() {\n\t\tif ( LocalCacheData.getAllURLArgs() &&\n\t\t\tLocalCacheData.getAllURLArgs().hasOwnProperty( 'tab' ) &&\n\t\t\tLocalCacheData.getAllURLArgs().tab.length > 0 &&\n\t\t\tLocalCacheData.current_open_primary_controller.viewId === this.viewId ) {\n\n\t\t\tvar target_node = this.edit_view_tab.find( '.edit-view-tab-bar-label' ).children().filter( function() {\n\t\t\t\tvar value = $( this ).text().replace( /\\/|\\s+/g, '' );\n\t\t\t\treturn value === LocalCacheData.getAllURLArgs().tab;\n\t\t\t} );\n\n\t\t\tvar target_index = 0;\n\t\t\tif ( target_node.length > 0 ) {\n\t\t\t\ttarget_node = $( target_node[0] );\n\t\t\t\ttarget_index = target_node.index();\n\t\t\t}\n\t\t\tthis.edit_view_tab.tabs( 'option', 'active', target_index );\n\t\t}\n\t}\n\n\t//Call this from setEditViewData\n\t// This is called to initialize data for the first/primary tab, and is called from many views. So it needs to stay even after fully refactored to use tab_model.\n\tinitTabData() {\n\t\tvar tab_model = this.getTabModel();\n\t\tif ( tab_model != null ) {\n\t\t\tthis.onTabShow();\n\t\t} else {\n\t\t\tvar current_tab_index = this.getEditViewTabIndex();\n\t\t\t//Handle most case that one tab and one audit tab\n\t\t\tif ( current_tab_index === 1 ) {\n\t\t\t\tif ( this.current_edit_record.id && this.current_edit_record.id != TTUUID.zero_id ) {\n\t\t\t\t\tthis.edit_view_tab.find( '#tab_audit' ).find( '.first-column-sub-view' ).css( 'display', 'block' );\n\t\t\t\t\tthis.initSubLogView( 'tab_audit' );\n\t\t\t\t} else {\n\t\t\t\t\tthis.edit_view_tab.find( '#tab_audit' ).find( '.first-column-sub-view' ).css( 'display', 'none' );\n\t\t\t\t\tthis.showSaveAndContinueButton();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tgetEditViewTabIndex() {\n\t\treturn this.edit_view.find( '.edit-view-tab-bar li.ui-tabs-active' ).index();\n\t}\n\n\tgetEditViewActiveTabName() {\n\t\tif( !this.edit_view ) {\n\t\t\treturn false;\n\t\t}\n\t\treturn this.edit_view.find( '.edit-view-tab-bar li.ui-tabs-active' ).attr( 'aria-controls' );\n\t}\n\n\tneedShowNavigation() {\n\t\tif ( this.current_edit_record && _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( this.current_edit_record.id ) && this.current_edit_record.id ) {\n\t\t\treturn true;\n\t\t} else {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t//Call this from setEditViewData\n\tinitEditViewData() {\n\t\tvar $this = this;\n\n\t\t//add this.grid to fix exception\n\t\t//Error: Unable to get property 'getGridParam' of undefined or null reference in /interface/html5/views/BaseViewController.js?v=7.4.3-20140924-090129 line 2523\n\t\tif ( !this.edit_only_mode && this.navigation && this.grid ) {\n\n\t\t\tvar grid_current_page_items = this.grid.getData();\n\n\t\t\tvar navigation_div = this.edit_view.find( '.navigation-div' );\n\n\t\t\t//Error: TypeError: this.current_edit_record is undefined in /interface/html5/views/BaseViewController.js?v=8.0.0-20141230-103725 line 2673\n\t\t\tif ( this.needShowNavigation() ) {\n\t\t\t\tnavigation_div.css( 'display', 'block' );\n\t\t\t\t//Set Navigation Awesomebox\n\n\t\t\t\t//#3175 - Get current navigation data if it exists so that we do not overwrite it when switching records.\n\t\t\t\t//For example when clicking the right arrow on the last record of page 1 brings you to page 2. Page 2 data was being reset.\n\t\t\t\t//In that scenario we want to keep navigation data from page 2 and not overwrite it with the grid data from the list view.\n\t\t\t\tlet current_navigation_data = this.navigation.getSourceData();\n\t\t\t\tlet current_pager_data = this.navigation.getPagerData();\n\n\t\t\t\t//#2349 - update source data every time so that it doesn't go unrefreshed in the case of saving a new record or deleting exiting\n\t\t\t\tthis.navigation.setSourceData( current_navigation_data ? current_navigation_data : grid_current_page_items );\n\t\t\t\tthis.navigation.setPagerData( current_pager_data ? current_pager_data: this.pager_data );\n\t\t\t\t//init navigation only when open edit view\n\t\t\t\tif ( !this.navigation.getSourceData() ) {\n\t\t\t\t\tif ( LocalCacheData.getLoginUserPreference() ) {\n\t\t\t\t\t\tthis.navigation.setRowPerPage( LocalCacheData.getLoginUserPreference().items_per_page );\n\t\t\t\t\t}\n\t\t\t\t\tthis.navigation.setPagerData( this.pager_data );\n\n\t\t\t\t\tvar default_args = {};\n\t\t\t\t\tdefault_args.filter_data = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.convertLayoutFilterToAPIFilter */ .x.convertLayoutFilterToAPIFilter( this.select_layout );\n\t\t\t\t\tdefault_args.filter_sort = this.select_layout.data.filter_sort;\n\t\t\t\t\tthis.navigation.setDefaultArgs( default_args );\n\t\t\t\t}\n\n\t\t\t\tthis.navigation.setValue( this.current_edit_record );\n\n\t\t\t} else {\n\t\t\t\tnavigation_div.css( 'display', 'none' );\n\t\t\t}\n\t\t}\n\n\t\tthis.setUIWidgetFieldsToCurrentEditRecord();\n\n\t\tif ( this.is_mass_editing ) {\n\t\t\tfor ( var key in this.edit_view_ui_dic ) {\n\n\t\t\t\tif ( !this.edit_view_ui_dic.hasOwnProperty( key ) ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\t//JS Exception: \"this.unique_columns.indexOf is not a function\"\n\t\t\t\tif ( this.unique_columns && this.unique_columns.length > 0 && this.unique_columns.indexOf( key ) != -1 ) {\n\t\t\t\t\t$this.edit_view_ui_dic[key].css( 'opacity', '0' );\n\t\t\t\t\tif ( $this.edit_view_ui_dic[key].setEnabled ) {\n\t\t\t\t\t\t$this.edit_view_ui_dic[key].setEnabled( false );\n\t\t\t\t\t}\n\t\t\t\t\tif ( $this.edit_view_ui_dic[key].setMassEditMode ) {\n\t\t\t\t\t\t$this.edit_view_ui_dic[key].setMassEditMode( false );\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tvar widget = this.edit_view_ui_dic[key];\n\t\t\t\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( widget.setMassEditMode ) ) {\n\t\t\t\t\t\twidget.setMassEditMode( true );\n\t\t\t\t\t}\n\t\t\t\t\t$this.edit_view_ui_dic[key].css( 'opacity', '1' );\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tfor ( var key in this.edit_view_ui_dic ) {\n\t\t\t\t$this.edit_view_ui_dic[key].css( 'opacity', '1' );\n\t\t\t}\n\t\t}\n\n\t\tthis.setNavigationArrowsEnabled( true );\n\n\t\t// Create this function alone because of the column value of view is different from each other, some columns need to be handle specially. and easily to rewrite this function in sub-class.\n\n\t\tthis.setCurrentEditRecordData();\n\n\t\t//Init *Please save this record before modifying any related data* box\n\t\tthis.edit_view.find( '.save-and-continue-div' ).SaveAndContinueBox( { related_view_controller: this } );\n\t\tthis.edit_view.find( '.save-and-continue-div' ).css( 'display', 'none' );\n\t}\n\n\tsetUIWidgetFieldsToCurrentEditRecord() {\n\t\tvar $this = this;\n\n\t\t$this.old_current_edit_record = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.clone */ .x.clone( $this.current_edit_record ); //Save the current edit record before any changes are made so we can later check what fields may have changed.\n\n\t\tif ( $this.current_edit_record === true ) {\n\t\t\t$this.current_edit_record = {};\n\t\t};\n\n\t\tfor ( var key in this.edit_view_ui_dic ) {\n\t\t\tif ( !this.edit_view_ui_dic.hasOwnProperty( key ) ) {\n\t\t\t\tcontinue;\n\t\t\t}\n//\t\t\t//Set all UI field to current edit record, we need validate all UI field when save and validate\n\t\t\t//use != to ingore string or number, value from html is string.\n\t\t\t//Error: TypeError: $this.current_edit_record is undefined in /interface/html5/views/BaseViewController.js?v=8.0.0-20141117-122453 line 2702\n\t\t\tif ( $this.current_edit_record && !_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( $this.current_edit_record[key] ) ) {\n\t\t\t\t$this.current_edit_record[key] = false;\n\t\t\t}\n\n\t\t}\n\t}\n\n\t/**\n\t * Set default data into current_edit_record\n\t *\n\t * @param columnsArr\n\t * @param force\n\t *\n\t * if force is true set the current_edit_record and populate edit_view_ui_dic\n\t * this is used in view controllers (RequestViewController::setRequestFormDefaultData) where the api call for default values is late\n\t *\n\t */\n\tsetDefaultData( columnsArr, force ) {\n\t\tvar $this = this;\n\t\t$.each( columnsArr, function( field, value ) {\n\t\t\tif ( force != true && _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( $this.current_edit_record[field] ) ) {\n\t\t\t\t//do nothing\n\t\t\t} else {\n\t\t\t\tif ( force == true ) {\n\t\t\t\t\tif ( $this.edit_view_ui_dic[field] ) {\n\t\t\t\t\t\t$this.edit_view_ui_dic[field].setValue( value );\n\t\t\t\t\t\t$this.current_edit_record[field] = value;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t$this.current_edit_record[field] = value;\n\t\t\t\t}\n\t\t\t}\n\t\t} );\n\t}\n\n\tcollectUIDataToCurrentEditRecord() {\n\t\tif ( this.is_mass_editing ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar $this = this;\n\t\tfor ( var key in this.edit_view_ui_dic ) {\n\t\t\tif ( !this.edit_view_ui_dic.hasOwnProperty( key ) ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tvar widget = this.edit_view_ui_dic[key];\n\n\t\t\t//only check dropdownlist\n\t\t\tif ( !widget.hasClass( 't-select' ) ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tvar value = widget.getValue();\n\n//\t\t\t//Set all UI field to current edit record, we need validate all UI field when save and validate\n\t\t\t//use != to ingore string or number, value from html is string.\n\t\t\t//is visible make sure the widget is shown on screen of current select type\n\n\t\t\t//Error: TypeError: undefined is not an object (evaluating '$this.current_edit_record[key]') in /interface/html5/views/BaseViewController.js?v=8.0.0-20141230-124906 line 2792\n\t\t\tif ( value && $this.current_edit_record && $this.current_edit_record[key] != value ) {\n\n\t\t\t\tif ( !value || value === '0' || ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isArray */ .x.isArray( value ) && value.length === 0 ) ) {\n\t\t\t\t\t$this.current_edit_record[key] = false;\n\t\t\t\t} else {\n\t\t\t\t\t$this.current_edit_record[key] = value;\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t}\n\t}\n\n\tsetCurrentEditRecordData() {\n\t\t//Set current edit record data to all widgets\n\t\tfor ( var key in this.current_edit_record ) {\n\n\t\t\tif ( !this.current_edit_record.hasOwnProperty( key ) ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tvar widget = this.edit_view_ui_dic[key];\n\t\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( widget ) ) {\n\t\t\t\tswitch ( key ) {\n\t\t\t\t\tcase 'country': //popular case\n\t\t\t\t\t\tthis.setCountryValue( widget, key );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\twidget.setValue( this.current_edit_record[key] );\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t}\n\t\t}\n\n\t\tthis.collectUIDataToCurrentEditRecord();\n\t\tthis.setEditViewDataDone();\n\t}\n\n\tsetCountryValue( widget, key ) {\n\t\tif ( !this.current_edit_record['province'] ) {\n\t\t\tthis.eSetProvince( this.current_edit_record[key], true );\n\t\t} else {\n\t\t\tthis.eSetProvince( this.current_edit_record[key] );\n\t\t}\n\t\twidget.setValue( this.current_edit_record[key] );\n\t}\n\n\tputInputToInsideFormItem( form_item_input, label ) {\n\t\tvar form_item = $( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.loadWidgetByName */ .x.loadWidgetByName( _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.WidgetNamesDic.EDIT_VIEW_SUB_FORM_ITEM ) );\n//\t\tvar form_item_label_div = form_item.find( '.edit-view-form-item-label-div' );\n//\n//\t\tform_item_label_div.attr( 'class', 'edit-view-form-item-sub-label-div' );\n\n\t\tvar form_item_label = form_item.find( '.edit-view-form-item-label' );\n\t\tvar form_item_input_div = form_item.find( '.edit-view-form-item-input-div' );\n\t\tform_item.addClass( 'remove-margin' );\n\n\t\tform_item_label.text( $.i18n._( label ) );\n\n\t\tform_item_input_div.append( form_item_input );\n\n\t\treturn form_item;\n\t}\n\n\t//set tab 0 visible after all data set done. This be hide when init edit view data\n\tsetEditViewDataDone() {\n\t\t// Remove this on 14.9.14 because adding tab url support, ned set url when tab index change and\n\t\t// need know waht's current doing action. See if this cause any problem\n\t\t//LocalCacheData.current_doing_context_action = '';\n\t\tthis.setTabOVisibility( true );\n\t\tTTPromise.resolve( 'init', 'init' );\n\n\t\t$( '.edit-view-tab-bar' ).css( 'opacity', 1 );\n\t}\n\n\tsetNavigationArrowsStatus() {\n\t\tif ( !this.edit_view ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar left_arrow = this.edit_view.find( '.left-click' );\n\t\tvar right_arrow = this.edit_view.find( '.right-click' );\n\t\tvar $this = this;\n\n\t\tleft_arrow.off( 'click' ).on( 'click', _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.debounce */ .x.debounce( function NavigationLeftArrowClick( e ) {\n\t\t\tif ( !left_arrow.hasClass( 'disabled' ) ) {\n\t\t\t\t$this.onLeftArrowClick();\n\t\t\t}\n\n\t\t}, _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.calcDebounceWaitTimeBasedOnNetwork */ .x.calcDebounceWaitTimeBasedOnNetwork(), true ) );\n\n\t\tright_arrow.off( 'click' ).on( 'click', _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.debounce */ .x.debounce( function NavigationRightArrowClick( e ) {\n\t\t\tif ( !right_arrow.hasClass( 'disabled' ) ) {\n\t\t\t\t$this.onRightArrowClick();\n\t\t\t}\n\n\t\t}, _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.calcDebounceWaitTimeBasedOnNetwork */ .x.calcDebounceWaitTimeBasedOnNetwork(), true ) );\n\t}\n\n\tsetNavigationArrowsEnabled( check_search ) {\n\t\tif ( !this.edit_view ) {\n\t\t\treturn;\n\t\t}\n\n\t\t//If search data exists, search when making a record change to ensure arrow status will reflect the search result\n\t\tif ( check_search && this.navigation && typeof this.navigation.buildUnSelectGridFilter == 'function' ) {\n\t\t\t//Run this condition first to avoid flashing arrows enabling/disabling.\n\t\t\tvar data = this.navigation.buildUnSelectGridFilter();\n\t\t\tif ( data && data.filter_data && Object.keys( data.filter_data ).length !== 0 ) {\n\t\t\t\tthis.navigation.onADropDownSearch( 'unselect_grid', undefined, undefined, () => {\n\t\t\t\t\tthis.setNavigationArrowsEnabled( false );\n\t\t\t\t} );\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tvar left_arrow = this.edit_view.find( '.left-click' );\n\t\tvar right_arrow = this.edit_view.find( '.right-click' );\n\n\t\tleft_arrow.removeClass( 'disabled' );\n\t\tright_arrow.removeClass( 'disabled' );\n\n\t\t//TypeError: this.navigation.getSelectIndex is not a function\n\t\t//navigation could not be initial in cases, for example in Request new view\n\t\tif ( !this.navigation || !( this.navigation.hasOwnProperty( 'getSelectIndex' ) ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar selected_index = this.navigation.getSelectIndex();\n\t\tvar source_data = this.navigation.getSourceData();\n\n\t\tif ( !source_data || ( Array.isArray( source_data ) && source_data.length === 0 ) ) {\n\t\t\t//No records in navigation box, so make sure arrows are disbled.\n\t\t\tleft_arrow.addClass( 'disabled' );\n\t\t\tright_arrow.addClass( 'disabled' );\n\t\t\treturn;\n\t\t}\n\n\t\tvar current_pager_data = this.navigation.getPagerData();\n\n\t\t// It's possible the navigation don't have a pager data, like Timesheet edit view, so it's become a no page navigation.\n\t\tif ( !current_pager_data ) {\n\t\t\tif ( selected_index === 0 ) {\n\t\t\t\tleft_arrow.addClass( 'disabled' );\n\t\t\t}\n\n\t\t\tif ( selected_index === source_data.length - 1 ) {\n\t\t\t\tright_arrow.addClass( 'disabled' );\n\t\t\t}\n\t\t} else {\n\t\t\tif ( selected_index === 0 && current_pager_data.current_page === 1 ) {\n\t\t\t\tleft_arrow.addClass( 'disabled' );\n\t\t\t}\n\n\t\t\tif ( selected_index === source_data.length - 1 && current_pager_data.current_page === current_pager_data.last_page_number ) {\n\t\t\t\tright_arrow.addClass( 'disabled' );\n\t\t\t}\n\t\t}\n\t}\n\n\tonLeftArrowClick( cancel_callback ) {\n\t\tvar $this = this;\n\n\t\tif ( this.is_changed ) {\n\t\t\tTAlertManager.showConfirmAlert( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.modify_alert_message */ .x.modify_alert_message, null, function( flag ) {\n\t\t\t\tif ( flag === true ) {\n\t\t\t\t\t$this.is_changed = false;\n\t\t\t\t\tdoLeftArrowClick();\n\t\t\t\t}\n\t\t\t\tProgressBar.closeOverlay();\n\t\t\t} );\n\t\t} else {\n\t\t\tdoLeftArrowClick();\n\t\t}\n\n\t\t_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.triggerAnalyticsEditViewNavigation */ .x.triggerAnalyticsEditViewNavigation( 'left-arrow', this.viewId );\n\n\t\tfunction doLeftArrowClick() {\n\t\t\tvar selected_index = $this.navigation.getSelectIndex();\n\t\t\tvar source_data = $this.navigation.getSourceData();\n\t\t\tvar current_pager_data = $this.navigation.getPagerData();\n\t\t\tvar next_select_item;\n\t\t\tif ( selected_index > 0 ) {\n\t\t\t\tnext_select_item = $this.navigation.getItemByIndex( selected_index - 1 );\n\t\t\t\t$this.onRightOrLeftArrowClickCallBack( next_select_item );\n\t\t\t} else if ( selected_index === 0 && current_pager_data && current_pager_data.current_page > 1 ) {\n\t\t\t\t$this.navigation.onADropDownSearch( 'unselect_grid', current_pager_data.current_page - 1, 'last', function( result ) {\n\t\t\t\t\tnext_select_item = result;\n\t\t\t\t\t$this.onRightOrLeftArrowClickCallBack( next_select_item );\n\t\t\t\t} );\n\t\t\t} else {\n\t\t\t\t$this.onCancelClick( null, null, cancel_callback );\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t}\n\n\trefreshCurrentRecord() {\n\t\tvar next_select_item = this.navigation.getItemByIndex( this.navigation.getSelectIndex() );\n\t\tProgressBar.showOverlay();\n\t\tif ( this.is_viewing ) {\n\t\t\tthis.onViewClick( next_select_item.id ); //Dont refresh UI\n\t\t} else {\n\t\t\tthis.onEditClick( next_select_item.id ); //Dont refresh UI\n\t\t}\n\n\t\tthis.setNavigationArrowsEnabled();\n\t}\n\n\t//exists for RecurringScheduleControlView due to the unique way we handle the ids there. (Change: That view no longer uses composite IDs)\n\tgetRightArrowClickSelectedIndex( selected_index ) {\n\t\treturn selected_index;\n\t}\n\n\tonRightArrowClick( cancel_callback ) {\n\t\tvar $this = this;\n\t\tif ( this.is_changed ) {\n\t\t\tTAlertManager.showConfirmAlert( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.modify_alert_message */ .x.modify_alert_message, null, function( flag ) {\n\t\t\t\tif ( flag === true ) {\n\t\t\t\t\t$this.is_changed = false;\n\t\t\t\t\tdoRightArrowClick();\n\t\t\t\t}\n\t\t\t\tProgressBar.closeOverlay();\n\t\t\t} );\n\t\t} else {\n\t\t\tdoRightArrowClick();\n\t\t}\n\n\t\t_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.triggerAnalyticsEditViewNavigation */ .x.triggerAnalyticsEditViewNavigation( 'right-arrow', this.viewId );\n\n\t\tfunction doRightArrowClick() {\n\t\t\tvar selected_index = $this.getRightArrowClickSelectedIndex( $this.navigation.getSelectIndex() );\n\t\t\tvar source_data = $this.navigation.getSourceData();\n\t\t\tvar current_pager_data = $this.navigation.getPagerData();\n\t\t\tvar next_select_item;\n\t\t\t//Error: Uncaught TypeError: Cannot read property 'length' of null in /interface/html5/views/BaseViewController.js?v=8.0.0-20141230-125919 line 2956\n\t\t\tif ( !source_data ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( selected_index < ( source_data.length - 1 ) ) {\n\t\t\t\t// next_select_item = $this.navigation.getItemByIndex( (selected_index + 1) );\n\t\t\t\tnext_select_item = $this.navigation.getItemByIndex( $this.navigation.getSelectIndex() + 1 );\n\t\t\t\t$this.onRightOrLeftArrowClickCallBack( next_select_item );\n\n\t\t\t\t//Error: Unable to get property 'current_page' of undefined or null reference in interface/html5/views/BaseViewController.js?v=9.0.0-20151016-102254 line 3204\n\t\t\t} else if ( selected_index === ( source_data.length - 1 ) && current_pager_data && current_pager_data.current_page < current_pager_data.last_page_number ) {\n\t\t\t\t$this.navigation.onADropDownSearch( 'unselect_grid', current_pager_data.current_page + 1, 'first', function( result ) {\n\t\t\t\t\tnext_select_item = result;\n\t\t\t\t\t$this.onRightOrLeftArrowClickCallBack( next_select_item );\n\t\t\t\t} );\n\t\t\t} else {\n\t\t\t\t$this.onCancelClick( null, null, cancel_callback );\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t}\n\n\tonRightOrLeftArrowClickCallBack( next_select_item ) {\n\t\tProgressBar.showOverlay();\n\t\tif ( this.is_viewing ) {\n\t\t\tthis.onViewClick( next_select_item ); //Dont refresh UI\n\t\t} else {\n\t\t\tthis.onEditClick( next_select_item.id ); //Dont refresh UI\n\t\t}\n\t\tthis.setNavigationArrowsEnabled();\n\t\tif ( this.sub_log_view_controller ) {\n\t\t\tthis.sub_log_view_controller.search();\n\t\t}\n\t}\n\n\tsetParentContextMenuAfterSubViewClose() {\n\t\t//Error: Uncaught TypeError: Cannot read property 'buildContextMenu' of null in /interface/html5/views/BaseViewController.js?v=7.4.6-20141027-085016 line 2887\n\t\tif ( !this.parent_view_controller ) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.parent_view_controller.buildContextMenu();\n\n\t\tif ( this.parent_view_controller.edit_view ) {\n\t\t\tthis.parent_view_controller.setEditMenu();\n\t\t} else {\n\t\t\tthis.parent_view_controller.setDefaultMenu();\n\t\t}\n\t}\n\n\t//This should only be used on its own if removeEditView is causing flashing.\n\t//This function should only really be called from onViewClick (see RequestViewCommonController.js)\n\tclearEditView() {\n\t\tif ( this.edit_view ) {\n\t\t\tthis.clearErrorTips();\n\t\t\tthis.edit_view.remove();\n\t\t}\n\t\tthis.edit_view = null;\n\t\tthis.edit_view_tab = null;\n\t}\n\n\tremoveEditView() {\n\t\tthis.unmountContextMenu();\n\t\tthis.clearEditView();\n\t\tthis.setCurrentEditViewState( '' );\n\t\tthis.is_changed = false;\n\t\tthis.confirm_on_exit = false;\n\t\tthis.mass_edit_record_ids = [];\n\n\t\tif ( this.edit_only_mode ) {\n\t\t\tvar current_url = window.location.href;\n\t\t\tif ( current_url.indexOf( '&sm' ) > 0 ) {\n\t\t\t\tcurrent_url = current_url.substring( 0, current_url.indexOf( '&sm' ) );\n\t\t\t\t_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.setURLToBrowser */ .x.setURLToBrowser( current_url );\n\t\t\t}\n\n\t\t\tLocalCacheData.current_open_edit_only_controller = null;\n\t\t}\n\n\t\t// reset parent context menu if edit only mode\n\n\t\tif ( !this.edit_only_mode ) {\n\t\t\t//#2777 - If the user goes to Employee -> Employees, click on Wage tab, then goes to Employee -> Employees again, the Context Menu will be incorrect and still be for the \"Wage\" record and not the proper \"Employee\" record.\n\t\t\t//This tries to detect when the context menu doesn't match the view and forces it to be rebuilt completely.\n\n\t\t\tthis.buildContextMenu( true );\n\t\t\tthis.setDefaultMenu();\n\t\t} else {\n\t\t\tthis.setParentContextMenuAfterSubViewClose();\n\t\t}\n\t\tthis.reSetURL();\n\t\t//If there is a action in url, add it back. So we have correct url when set tabs urls\n\t\t//This caused a bug where whenever saving a punch on Attendance ->TimeSheet, it would re-open the edit view, same with navigating between weeks, or even deleting punches in some cases.\n\t\t//This need to put under reSetUrl and need clean url_agrs until it set from onViewChange in router again\n\t\tif ( LocalCacheData.getAllURLArgs() && LocalCacheData.getAllURLArgs().a ) {\n\t\t\tLocalCacheData.current_doing_context_action = LocalCacheData.getAllURLArgs().a;\n\t\t}\n\n\t\tthis.sub_log_view_controller = null;\n\t\tthis.edit_view_ui_dic = {};\n\t\tthis.edit_view_ui_validation_field_dic = {};\n\t\tthis.edit_view_form_item_dic = {};\n\t\tthis.edit_view_error_ui_dic = {};\n\t\tthis.current_edit_record = null;\n\n\t\tif ( this.sub_document_view_controller ) {\n\t\t\tthis.sub_document_view_controller = null;\n\t\t}\n\t}\n\n\treSetURL() {\n\t\tif ( this.canSetURL() ) {\n\t\t\tvar args = '#!m=' + this.viewId;\n\t\t\t_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.setURLToBrowser */ .x.setURLToBrowser( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.getBaseURL */ .x.getBaseURL() + args );\n\t\t\tLocalCacheData.setAllURLArgs( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.buildArgDic */ .x.buildArgDic( args.split( '&' ) ) );\n\t\t}\n\t}\n\n\tgetGridSelectIdArray() {\n\t\tif ( !this.grid ) {\n\t\t\treturn []; //Return empty array so .length on the result doesn't fail with Cannot read property 'length' of undefined\n\t\t}\n\n\t\treturn this.grid.getSelectedRows();\n\t}\n\n\tsetDefaultMenuAddIcon( context_btn, grid_selected_length, pId ) {\n\t\tif ( !this.addPermissionValidate( pId ) || this.edit_only_mode ) {\n\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\t}\n\t}\n\n\tsetDefaultMenuEditIcon( context_btn, grid_selected_length, p_id ) {\n\t\tif ( !this.editPermissionValidate( p_id ) || this.edit_only_mode ) {\n\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t}\n\n\t\t// Updated to toggle with mass edit icon in new menu - Note: This logic is duplicated in TimeSheetViewController.\n\t\tif ( grid_selected_length === 1 && this.editOwnerOrChildPermissionValidate( p_id ) ) {\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, true );\n\t\t} else {\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t\tif ( grid_selected_length !== 0 ) {\n\t\t\t\t// This ensures the edit icon is still visible when nothing is selected, but should still be disabled. (to keep consistency with old design)\n\t\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t\t}\n\t\t}\n\t}\n\n\tsetDefaultMenuViewIcon( context_btn, grid_selected_length, p_id ) {\n\t\tif ( !this.viewPermissionValidate( p_id ) || this.edit_only_mode ) {\n\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\t}\n\n\t\tif ( grid_selected_length === 1 && this.viewOwnerOrChildPermissionValidate() ) {\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, true );\n\t\t} else {\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t}\n\t}\n\n\tsetDefaultMenuMassEditIcon( context_btn, grid_selected_length, pId ) {\n\t\tif ( !this.editPermissionValidate( pId ) || this.edit_only_mode ) {\n\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t}\n\n\t\t// updated to toggle with mass edit icon in new menu\n\t\tif ( grid_selected_length > 1 ) {\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, true );\n\t\t} else {\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t}\n\t}\n\n\tsetDefaultMenuCopyIcon( context_btn, grid_selected_length, pId ) {\n\t\tif ( !this.copyPermissionValidate( pId ) || this.edit_only_mode ) {\n\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\t}\n\n\t\tif ( grid_selected_length >= 1 ) {\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, true );\n\t\t} else {\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t}\n\t}\n\n\tsetDefaultMenuDeleteIcon( context_btn, grid_selected_length, pId ) {\n\t\tif ( !this.deletePermissionValidate( pId ) || this.edit_only_mode ) {\n\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\t}\n\n\t\tif ( grid_selected_length >= 1 && this.deleteOwnerOrChildPermissionValidate( pId ) ) {\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, true );\n\t\t} else {\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t}\n\t}\n\n\tsetDefaultMenuDeleteAndNextIcon( context_btn, grid_selected_length, pId ) {\n\t\tif ( !this.deletePermissionValidate( pId ) || this.edit_only_mode ) {\n\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\t}\n\n\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t}\n\n\tsetDefaultMenuSaveIcon( context_btn, grid_selected_length, pId ) {\n\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t}\n\n\tsetDefaultMenuSaveAndNextIcon( context_btn, grid_selected_length, pId ) {\n\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t}\n\n\tsetDefaultMenuSaveAndCopyIcon( context_btn, grid_selected_length, pId ) {\n\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t}\n\n\tsetDefaultMenuSaveAndContinueIcon( context_btn, grid_selected_length, pId ) {\n\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t}\n\n\tsetDefaultMenuSaveAndAddIcon( context_btn, grid_selected_length, pId ) {\n\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t}\n\n\tsetDefaultMenuCopyAsNewIcon( context_btn, grid_selected_length, pId ) {\n\t\tif ( ( !this.copyAsNewPermissionValidate( pId ) ) || this.edit_only_mode ) {\n\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\t}\n\n\t\tif ( grid_selected_length === 1 ) {\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, true );\n\t\t} else {\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t}\n\t}\n\n\tsetDefaultMenuLoginIcon( context_btn, grid_selected_length, pId ) {\n\t\tif ( !PermissionManager.validate( 'company', 'login_other_user' ) ) {\n\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\t}\n\n\t\tif ( this.getGridSelectIdArray().length !== 1 ) {\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t}\n\t}\n\n\tsetDefaultMenuCancelIcon( context_btn, grid_selected_length, pId ) {\n\t\tif ( !this.sub_view_mode ) {\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t}\n\t}\n\n\tsetDefaultMenuExportIcon( context_btn, grid_selected_length, pId ) {\n\t\tif ( this.edit_only_mode || this.is_viewing || this.is_edit || this.is_add ) {\n\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t} else if ( grid_selected_length == 0 || this.grid == undefined ) {\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t}\n\t}\n\n\tsetDefaultMenuImportIcon( context_btn, grid_selected_length, pId ) {\n\t\tif ( !this.addPermissionValidate( pId ) || this.edit_only_mode ) {\n\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\t}\n\t}\n\n\tsetDefaultMenuPermissionWizardIcon( context_btn, pId ) {\n\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t}\n\n\tsetEditMenuPermissionWizardIcon( context_btn, pId ) {\n\t}\n\n\tsetEditMenuImportIcon( context_btn ) {\n\t\tif ( this.edit_only_mode || this.is_viewing || this.is_edit || this.is_add ) {\n\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t}\n\t}\n\n\tsetEditMenuAddIcon( context_btn, pId ) {\n\t\tif ( !this.addPermissionValidate( pId ) || this.edit_only_mode ) {\n\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\t}\n\n\t\tif ( this.is_add == true ) {\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t}\n\t}\n\n\tsetEditMenuEditIcon( context_btn, pId ) {\n\t\tif ( !this.editPermissionValidate( pId ) || this.edit_only_mode || this.is_mass_editing ) {\n\t\t\t//Not shown in edit only mode or mass edit. Mass edit should only show mass edit (need to set that part in mass edit icon).\n\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t}\n\n\t\tif ( !this.is_viewing || !this.editOwnerOrChildPermissionValidate( pId ) ) {\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t}\n\t}\n\n\tsetEditMenuNavEditIcon( context_btn, p_id ) {\n\t\tif ( !this.editPermissionValidate( p_id ) || this.edit_only_mode ) {\n\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\t}\n\t}\n\n\tsetEditMenuNavViewIcon( context_btn, p_id ) {\n\t\tif ( !this.viewPermissionValidate( p_id ) || this.edit_only_mode ) {\n\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\t}\n\t}\n\n\tsetEditMenuViewIcon( context_btn, pId ) {\n\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t}\n\n\tsetEditMenuMassEditIcon( context_btn, pId ) {\n\t\tif ( !this.editPermissionValidate( pId ) || this.edit_only_mode || !this.is_mass_editing ) {\n\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\t}\n\n\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t}\n\n\tsetEditMenuDeleteIcon( context_btn, pId ) {\n\t\tif ( !this.deletePermissionValidate( pId ) || this.edit_only_mode ) {\n\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\t}\n\n\t\tif ( ( !this.current_edit_record || !this.current_edit_record.id ) || !this.deleteOwnerOrChildPermissionValidate( pId ) ) {\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t}\n\t}\n\n\tsetEditMenuDeleteAndNextIcon( context_btn, pId ) {\n\t\tif ( !this.deletePermissionValidate( pId ) || this.edit_only_mode ) {\n\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\t}\n\n\t\tif ( ( !this.current_edit_record || !this.current_edit_record.id ) || !this.deleteOwnerOrChildPermissionValidate( pId ) ) {\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t}\n\t}\n\n\tsetEditMenuCopyIcon( context_btn, pId ) {\n\t\tif ( !this.copyPermissionValidate( pId ) || this.edit_only_mode ) {\n\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\t}\n\n\t\tif ( !this.current_edit_record || !this.current_edit_record.id ) {\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t}\n\t}\n\n\tsetEditMenuCopyAndAddIcon( context_btn, pId ) {\n\t\tif ( !this.copyAsNewPermissionValidate( pId ) || this.edit_only_mode ) {\n\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\t}\n\n\t\tif ( ( !this.current_edit_record || !this.current_edit_record.id ) || this.is_viewing ) {\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t}\n\t}\n\n\tsetEditMenuSaveIcon( context_btn, pId ) {\n\n\t\tthis.saveValidate( context_btn, pId );\n\n\t\tif ( this.is_viewing ) {\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t}\n\t}\n\n\tsetEditMenuSaveAndContinueIcon( context_btn, pId ) {\n\t\tthis.saveAndContinueValidate( context_btn, pId );\n\n\t\tif ( this.is_mass_adding || this.is_mass_editing || this.is_viewing ) {\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t}\n\t}\n\n\tsetEditMenuSaveAndCopyIcon( context_btn, pId ) {\n\t\tthis.saveAndCopyValidate( context_btn, pId );\n\n\t\tif ( this.is_mass_editing || this.is_viewing ) {\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t}\n\t}\n\n\tsetEditMenuSaveAndNextIcon( context_btn, pId ) {\n\t\tif ( !this.editPermissionValidate( pId ) || this.edit_only_mode ) {\n\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\t}\n\n\t\tif ( ( !this.current_edit_record || !this.current_edit_record.id ) || this.is_viewing ) {\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t}\n\t}\n\n\tsetEditMenuSaveAndAddIcon( context_btn, pId ) {\n\t\tthis.saveAndNewValidate( context_btn, pId );\n\n\t\tif ( this.is_viewing || this.is_mass_editing ) {\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t}\n\t}\n\n\tsetEditMenuCancelIcon( context_btn, pId ) {\n\t}\n\n\tifContextButtonExist( value ) {\n\t\tvar context_menu_array = ContextMenuManager.getMenuModelByMenuId( this.determineContextMenuMountAttributes().id );\n\t\tvar len = context_menu_array.length;\n\t\tfor ( var i = 0; i < len; i++ ) {\n\t\t\tlet context_btn = context_menu_array[i];\n\t\t\tlet id = context_menu_array[i].id;\n\t\t\tif ( id === value && context_btn.visible ) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\tonSubViewModeDisableParentContextMenuButtons() {\n\t\t//When on a sub view mode tab we want to disable certain context menu buttons of the parent view.\n\t\t//This is to help prevent users from using context menu buttons for the wrong view and deleting/copying records they did not intend to use.\n\t\tif ( this.sub_view_mode && this.parent_view_controller ) {\n\t\t\tvar parent_context_menu_array = ContextMenuManager.getMenuModelByMenuId( this.parent_view_controller.determineContextMenuMountAttributes().id );\n\t\t\tvar len = parent_context_menu_array.length;\n\n\t\t\tfor ( var i = 0; i < len; i++ ) {\n\t\t\t\tlet context_btn = parent_context_menu_array[i];\n\t\t\t\tlet id = parent_context_menu_array[i].id;\n\n\t\t\t\t//Switch instead of if/else incase we want differences between buttons in future, easier to read than long conditional.\n\t\t\t\tswitch ( id ) {\n\t\t\t\t\tcase 'add':\n\t\t\t\t\tcase 'delete_icon':\n\t\t\t\t\tcase 'delete_and_next':\n\t\t\t\t\tcase 'copy':\n\t\t\t\t\tcase 'copy_as_new':\n\t\t\t\t\tcase 'save_and_copy':\n\t\t\t\t\tcase 'save_and_new':\n\t\t\t\t\t\tContextMenuManager.disableMenuItem( this.parent_view_controller.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\thideJumpToMenu() {\n\t\t//Jump to should be hidden on all \"new\" record views and only available when editing a record.\n\t\t//This is to prevent users from using the jump to button to navigating to broken or blank pages.\n\t\tif ( this.is_add || this.is_mass_adding ) {\n\t\t\tvar context_menu_array = ContextMenuManager.getMenuModelByMenuId( this.determineContextMenuMountAttributes().id );\n\n\t\t\tfor ( var i = 0; i < context_menu_array.length; i++ ) {\n\t\t\t\tif ( context_menu_array[i].action_group === 'jump_to' ) {\n\t\t\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_menu_array[i].id, false );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t//Call this when select grid row\n\t//Call this when setLayout\n\tsetDefaultMenu( doNotSetFocus, grid_selected_length ) {\n\t\t//Check if there is a current_company object at all.\n\t\tif ( LocalCacheData.isLocalCacheExists( 'current_company' ) == false ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tthis.setTotalDisplaySpan();\n\n\t\tvar context_menu_array = ContextMenuManager.getMenuModelByMenuId( this.determineContextMenuMountAttributes().id );\n\t\tvar len = context_menu_array.length;\n\t\tif ( grid_selected_length === undefined ) {\n\t\t\tvar grid_selected_id_array = this.getGridSelectIdArray();\n\t\t\tgrid_selected_length = grid_selected_id_array.length;\n\t\t}\n\n\t\tfor ( var i = 0; i < len; i++ ) {\n\t\t\tlet context_btn = context_menu_array[i];\n\t\t\tlet id = context_menu_array[i].id;\n\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, true );\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, true );\n\n\t\t\tswitch ( id ) {\n\t\t\t\tcase 'add':\n\t\t\t\t\tthis.setDefaultMenuAddIcon( context_btn, grid_selected_length );\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'edit':\n\t\t\t\t\tthis.setDefaultMenuEditIcon( context_btn, grid_selected_length );\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'view':\n\t\t\t\t\tthis.setDefaultMenuViewIcon( context_btn, grid_selected_length );\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'mass_edit':\n\t\t\t\t\tthis.setDefaultMenuMassEditIcon( context_btn, grid_selected_length );\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'copy':\n\t\t\t\t\tthis.setDefaultMenuCopyIcon( context_btn, grid_selected_length );\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'delete_icon':\n\t\t\t\t\tthis.setDefaultMenuDeleteIcon( context_btn, grid_selected_length );\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'delete_and_next':\n\t\t\t\t\tthis.setDefaultMenuDeleteAndNextIcon( context_btn, grid_selected_length );\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'save':\n\t\t\t\t\tthis.setDefaultMenuSaveIcon( context_btn, grid_selected_length );\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'save_and_next':\n\t\t\t\t\tthis.setDefaultMenuSaveAndNextIcon( context_btn, grid_selected_length );\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'save_and_continue':\n\t\t\t\t\tthis.setDefaultMenuSaveAndContinueIcon( context_btn, grid_selected_length );\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'save_and_new':\n\t\t\t\t\tthis.setDefaultMenuSaveAndAddIcon( context_btn, grid_selected_length );\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'save_and_copy':\n\t\t\t\t\tthis.setDefaultMenuSaveAndCopyIcon( context_btn, grid_selected_length );\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'copy_as_new':\n\t\t\t\t\tthis.setDefaultMenuCopyAsNewIcon( context_btn, grid_selected_length );\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'login':\n\t\t\t\t\tthis.setDefaultMenuLoginIcon( context_btn, grid_selected_length );\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'cancel':\n\t\t\t\t\tthis.setDefaultMenuCancelIcon( context_btn, grid_selected_length );\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'import_icon':\n\t\t\t\t\tthis.setDefaultMenuImportIcon( context_btn, grid_selected_length );\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'permission_wizard':\n\t\t\t\t\tthis.setDefaultMenuPermissionWizardIcon( context_btn, grid_selected_length );\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'map':\n\t\t\t\t\tthis.setDefaultMenuMapIcon( context_btn, grid_selected_length );\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'export_excel':\n\t\t\t\t\tthis.setDefaultMenuExportIcon( context_btn, grid_selected_length );\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tthis.setCustomDefaultMenuIcon( id, context_btn, grid_selected_length );\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t}\n\n\t\tthis.initRightClickMenu();\n\t}\n\n\tsetCustomDefaultMenuIcon( id, context_btn, grid_selected_length ) {\n\t\treturn false; //FALSE tells setCustomDefaultMenuIcon() to keep processing.\n\t}\n\n\tsetEditMenu() {\n\t\tvar context_menu_array = ContextMenuManager.getMenuModelByMenuId( this.determineContextMenuMountAttributes().id );\n\n\t\tvar len = context_menu_array.length;\n\t\tfor ( var i = 0; i < len; i++ ) {\n\t\t\tlet context_btn = context_menu_array[i];\n\t\t\tlet id = context_menu_array[i].id;\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, true );\n\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, true );\n\n\t\t\tif ( this.is_mass_editing ) {\n\t\t\t\tswitch ( id ) {\n\t\t\t\t\tcase 'save':\n\t\t\t\t\t\tthis.setEditMenuSaveIcon( context_btn );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'edit':\n\t\t\t\t\t\tthis.setEditMenuEditIcon( context_btn );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'cancel':\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tswitch ( id ) {\n\t\t\t\tcase 'add':\n\t\t\t\t\tthis.setEditMenuAddIcon( context_btn );\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'edit':\n\t\t\t\t\tthis.setEditMenuEditIcon( context_btn );\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'view':\n\t\t\t\t\tthis.setEditMenuViewIcon( context_btn );\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'mass_edit':\n\t\t\t\t\tthis.setEditMenuMassEditIcon( context_btn );\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'copy':\n\t\t\t\t\tthis.setEditMenuCopyIcon( context_btn );\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'delete_icon':\n\t\t\t\t\tthis.setEditMenuDeleteIcon( context_btn );\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'delete_and_next':\n\t\t\t\t\tthis.setEditMenuDeleteAndNextIcon( context_btn );\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'save':\n\t\t\t\t\tthis.setEditMenuSaveIcon( context_btn );\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'save_and_continue':\n\t\t\t\t\tthis.setEditMenuSaveAndContinueIcon( context_btn );\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'save_and_new':\n\t\t\t\t\tthis.setEditMenuSaveAndAddIcon( context_btn );\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'save_and_next':\n\t\t\t\t\tthis.setEditMenuSaveAndNextIcon( context_btn );\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'save_and_copy':\n\t\t\t\t\tthis.setEditMenuSaveAndCopyIcon( context_btn );\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'copy_as_new':\n\t\t\t\t\tthis.setEditMenuCopyAndAddIcon( context_btn );\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'cancel':\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'import_icon':\n\t\t\t\t\tthis.setEditMenuImportIcon( context_btn );\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'permission_wizard':\n\t\t\t\t\tthis.setEditMenuPermissionWizardIcon( context_btn );\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'login':\n\t\t\t\t\tthis.setEditMenuLoginIcon( context_btn );\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'map':\n\t\t\t\t\tthis.setEditMenuMapIcon( context_btn );\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'export_excel':\n\t\t\t\t\tthis.setDefaultMenuExportIcon( context_btn );\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tthis.setCustomEditMenuIcon( id, context_btn );\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tthis.hideJumpToMenu();\n\t\tthis.initRightClickMenu( RightClickMenuType.EDITVIEW );\n\t}\n\n\tsetCustomEditMenuIcon( id, context_btn ) {\n\t\treturn false; //FALSE tells setCustomEditMenuIcon() to keep processing.\n\t}\n\n\tsetDefaultMenuMapIcon( context_btn ) {\n\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.getProductEdition */ .x.getProductEdition() <= 10 ) {\n\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\t}\n\n\t\tvar show = false;\n\t\tif ( this.grid ) {\n\t\t\tvar selected_items = this.getSelectedItems();\n\t\t\tDebug.Arr( selected_items, 'selected items', 'BaseViewController.js', 'BaseViewController', 'setDefaultMenuMapIcon', 10 );\n\t\t\tif ( selected_items.length > 0 ) {\n\t\t\t\tfor ( var x = 0; x < selected_items.length; x++ ) {\n\t\t\t\t\tif ( selected_items[x] && selected_items[x].latitude && selected_items[x].longitude ) {\n\t\t\t\t\t\tshow = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif ( show ) {\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, true );\n\t\t} else {\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t}\n\t}\n\n\tsetEditMenuMapIcon( context_btn ) {\n\t\tthis.setDefaultMenuMapIcon( context_btn );\n\t}\n\n\tsetEditMenuLoginIcon( context_btn ) {\n\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t}\n\n\tsetErrorMenu() {\n\t\tvar context_menu_array = ContextMenuManager.getMenuModelByMenuId( this.determineContextMenuMountAttributes().id );\n\t\tvar len = context_menu_array.length;\n\n\t\tfor ( var i = 0; i < len; i++ ) {\n\t\t\tlet context_btn = context_menu_array[i];\n\t\t\tlet id = context_menu_array[i].id;\n\n\t\t\tif ( context_menu_array[i].split_button_active_item ) {\n\t\t\t\t//Temporarily sets split button to ignore resetting of the active item. This stops active split button item from resetting.\n\t\t\t\t//Example if doing \"Save & Continue\" we do not want the button to switch back to \"Save\" just because validation failed.\n\t\t\t\tContextMenuManager.freezeSplitButtonActiveItem( this.determineContextMenuMountAttributes().id, context_btn.id );\n\t\t\t}\n\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, true );\n\n\t\t\tswitch ( id ) {\n\t\t\t\tcase 'cancel':\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t}\n\t}\n\n\trender() {\n\t\tvar $this = this;\n\n\t\t$( window ).off( 'resize.edit_tabs' ).on( 'resize.edit_tabs', _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.debounce */ .x.debounce( function() {\n\t\t\tif ( $this.edit_view ) {\n\t\t\t\t$this.setEditViewTabSize();\n\t\t\t}\n\t\t}, 200 ) );\n\n\t\tTTPromise.add( 'BaseViewController', 'getCustomFields' );\n\n\t\tthis.getCustomFieldsForView();\n\n\t\t//Create search panel only when show as a main view\n\n\t\tif ( !this.sub_view_mode && !this.edit_only_mode && !this.tree_mode ) {\n\t\t\tvar search_panel_w = $( $.fn.SearchPanel.html.search_panel );\n\n\t\t\t$( this.el ).prepend( search_panel_w );\n\n\t\t\tif ( !this.show_search_tab ) {\n\t\t\t\tsearch_panel_w.hide();\n\t\t\t}\n\n\t\t\tthis.search_panel = search_panel_w.SearchPanel( { viewController: this } );\n\n\t\t\tthis.search_panel.on( 'searchTabSelect', function() {\n\t\t\t\t$this.onSearchTabSelect;\n\t\t\t} );\n\n\t\t\tTTPromise.wait( 'BaseViewController', 'getCustomFields', function() {\n\t\t\t\tthis.buildSearchFields();\n\t\t\t\tthis.buildCustomFieldSearchFields()\n\t\t\t\tthis.buildBasicSearchUI();\n\t\t\t\tthis.buildAdvancedSearchUI();\n\t\t\t\tthis.buildSearchAndLayoutUI();\n\n\t\t\t\t//Work around that the li offset is empty in chrome\n\t\t\t\tsetTimeout( function() {\n\t\t\t\t\t$this.setCurrentViewPosition();\n\t\t\t\t}, 500 );\n\t\t\t}.bind( this ) );\n\n\t\t}\n\t}\n\n\tsetCurrentViewPosition() {\n\t\tvar current_view_div = this.search_panel.find( '.layout-selector-div' );\n\t\tvar saved_layout_li = this.search_panel.find( 'a[ref=\\'saved_layout\\']' ).parent();\n\t\t// Error: Unable to get property 'left' of undefined or null reference in /interface/html5/views/BaseViewController.js?v=8.0.6-20150417-083849 line 3691\n\t\tif ( !current_view_div || !saved_layout_li || !saved_layout_li.offset() ) {\n\t\t\treturn;\n\t\t}\n\t\t// Now controlled from CSS in SearchPanel.css Dont understand why there is a complex left: x JS calc, right position seems better and more consistent.\n\t\t// current_view_div.css( 'left', saved_layout_li.offset().left + saved_layout_li.width() - 60 ); // Change to 60 is trial and error trying to prevent current view dropdown from overlapping in new layout design\n\t}\n\n\t//Build fields when search tab change\n\tonSearchTabSelect( e, e1, ui ) {\n\t\tvar tab_id = $( ui ).prop( 'id' );\n\n\t\tswitch ( tab_id ) {\n\t\t\tcase 'basic_search':\n\n\t\t\t\tif ( this.search_panel.getLastSelectTabId() !== 'saved_layout' ) {\n\t\t\t\t\tthis.getSearchPanelFilter( 1, true );\n\t\t\t\t\tthis.buildBasicSearchUI();\n\t\t\t\t\tthis.setSearchPanelFilter( false, 0 );\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\t\t\tcase 'adv_search':\n\t\t\t\tif ( this.search_panel.getLastSelectTabId() !== 'saved_layout' ) {\n\t\t\t\t\tthis.getSearchPanelFilter( 0, true );\n\t\t\t\t\tthis.buildAdvancedSearchUI();\n\t\t\t\t\tthis.setSearchPanelFilter( false, 1 );\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\t\t\tcase 'saved_layout':\n\t\t\t\tthis.getSearchPanelFilter( this.search_panel.getLastSelectTabIndex() );\n\t\t}\n\t}\n\n\tinitDropDownOptions( options, callBack ) {\n\t\tlet $this = this;\n\t\tlet api_groups = {};\n\n\t\t//Fill any values that are not set and group option calls by their API endpoint.\n\t\tfor ( let i = 0; i < options.length; i++ ) {\n\t\t\tlet option = options[i];\n\t\t\tif ( !_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( option.api ) ) {\n\t\t\t\toption.api = this.api;\n\t\t\t}\n\t\t\tif ( !_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( option.field_name ) || !option.field_name ) {\n\t\t\t\toption.field_name = option.option_name + '_id';\n\t\t\t}\n\t\t\tif ( !_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( option.parent ) || !option.parent ) {\n\t\t\t\toption.parent = null;\n\t\t\t}\n\n\t\t\t//Group getOption calls by their API endpoint.\n\t\t\tif ( !api_groups[option.api.className] ) {\n\t\t\t\tapi_groups[option.api.className] = [];\n\t\t\t}\n\t\t\tapi_groups[option.api.className].push( option );\n\t\t}\n\n\t\t//Call getOptionsBatch on each requested API\n\t\tlet completed_api_calls = 0;\n\t\tfor ( let api_class in api_groups ) {\n\t\t\tif ( Array.isArray( api_groups[api_class] ) === false ) {\n\t\t\t\t//Issue #3223 - Error: Uncaught TypeError: api_groups[api_class].reduce is not a function\n\t\t\t\t//The cause for this exception is unknown as the above code is syncronous and should always produce\n\t\t\t\t//the same results given the same input. However, for some reason api_groups[api_class] is not an always an array.\n\t\t\t\t//This change is simply meant to prevent the error from being thrown.\n\t\t\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( callBack ) ) {\n\t\t\t\t\tcallBack();\n\t\t\t\t}\n\t\t\t\tDebug.Text( 'Unexpected error api_groups[api_class] is not an array.', 'BaseViewController.js', 'BaseViewController', 'initDropDownOptions', 9 );\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t//Reduce data sent to API with only data required for the API.\n\t\t\tlet data = api_groups[api_class].reduce( ( new_obj, option ) => ( new_obj[option.option_name] = option.parent, new_obj ), {} );\n\t\t\t_services_TimeTrexClientAPI__WEBPACK_IMPORTED_MODULE_1__/* .TTAPI */ .y[api_class].getOptionsBatch( data, {\n\t\t\t\tonResult: function( response ) {\n\t\t\t\t\tlet results = response.getResult();\n\t\t\t\t\tif ( results && Object.keys( results ).length > 0 ) {\n\t\t\t\t\t\tfor ( let option in results ) {\n\t\t\t\t\t\t\tlet option_data = results[option];\n\t\t\t\t\t\t\tlet option_field_info = api_groups[api_class].find( icon => icon.option_name === option );\n\t\t\t\t\t\t\t//Set view controller variables and field data\n\t\t\t\t\t\t\t$this[option + '_array'] = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.buildRecordArray */ .x.buildRecordArray( option_data );\n\t\t\t\t\t\t\tif ( !$this.sub_view_mode ) {\n\t\t\t\t\t\t\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( $this.basic_search_field_ui_dic[option_field_info.field_name] ) ) {\n\t\t\t\t\t\t\t\t\t$this.basic_search_field_ui_dic[option_field_info.field_name].setSourceData( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.buildRecordArray */ .x.buildRecordArray( option_data ) );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( $this.adv_search_field_ui_dic[option_field_info.field_name] ) ) {\n\t\t\t\t\t\t\t\t\t$this.adv_search_field_ui_dic[option_field_info.field_name].setSourceData( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.buildRecordArray */ .x.buildRecordArray( option_data ) );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tcompleted_api_calls++;\n\n\t\t\t\t\tif ( Object.keys( api_groups ).length === completed_api_calls && _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( callBack ) ) {\n\t\t\t\t\t\t//Only call the callback when all API calls have completed.\n\t\t\t\t\t\tcallBack( response );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} );\n\t\t}\n\t}\n\n\tbuildWidgetContainerWithTextTip( widget, tip ) {\n\t\tvar h_box = $( '' );\n\n\t\tvar text_box = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.loadWidgetByName */ .x.loadWidgetByName( _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.FormItemType.TEXT );\n\t\ttext_box.css( 'margin-left', '10px' );\n\t\ttext_box.TText();\n\t\ttext_box.setValue( tip );\n\n\t\th_box.append( widget );\n\t\th_box.append( text_box );\n\n\t\treturn h_box;\n\t}\n\n\t//Set option list for search panel and edit view\n\tinitDropDownOption( option_name, field_name, api, callBack, array_name ) {\n\t\tvar $this = this;\n\t\tif ( !_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( api ) ) {\n\t\t\tapi = this.api;\n\t\t}\n\n\t\tif ( !_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( field_name ) || !field_name ) {\n\t\t\tfield_name = option_name + '_id';\n\t\t}\n\t\tapi.getOptions( option_name, {\n\t\t\tonResult: function( res ) {\n\t\t\t\tvar result = res.getResult();\n\n\t\t\t\tif ( array_name ) {\n\t\t\t\t\t$this[array_name] = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.buildRecordArray */ .x.buildRecordArray( result );\n\t\t\t\t} else {\n\n\t\t\t\t\t$this[option_name + '_array'] = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.buildRecordArray */ .x.buildRecordArray( result );\n\t\t\t\t}\n\n\t\t\t\tif ( !$this.sub_view_mode ) {\n\n\t\t\t\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( $this.basic_search_field_ui_dic[field_name] ) ) {\n\t\t\t\t\t\t$this.basic_search_field_ui_dic[field_name].setSourceData( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.buildRecordArray */ .x.buildRecordArray( result ) );\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( $this.adv_search_field_ui_dic[field_name] ) ) {\n\t\t\t\t\t\t$this.adv_search_field_ui_dic[field_name].setSourceData( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.buildRecordArray */ .x.buildRecordArray( result ) );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( callBack ) ) {\n\t\t\t\t\tcallBack( res );\n\t\t\t\t}\n\n\t\t\t}\n\t\t} );\n\t}\n\n\tclearSearchPanel() {\n\n\t\tfor ( var key in this.basic_search_field_ui_dic ) {\n\t\t\tvar search_input = this.basic_search_field_ui_dic[key];\n\t\t\tsearch_input.setValue( null );\n\t\t}\n\n\t\tfor ( var key in this.adv_search_field_ui_dic ) {\n\t\t\tsearch_input = this.adv_search_field_ui_dic[key];\n\t\t\tsearch_input.setValue( null );\n\t\t}\n\t}\n\n\tonSearch() {\n\t\tTTPromise.add( 'init', 'init' );\n\t\tTTPromise.wait();\n\n\t\tvar do_update = false;\n\n\t\t//don't keep temp filter any more, set them when change tab\n\t\tthis.temp_adv_filter_data = null;\n\t\tthis.temp_basic_filter_data = null;\n\t\tthis.getSearchPanelFilter();\n\t\tif ( this.search_panel.getLayoutsArray() && this.search_panel.getLayoutsArray().length > 0 ) {\n\t\t\tvar default_layout_id = $( this.previous_saved_layout_selector ).children( 'option:contains(\\'' + BaseViewController.default_layout_name + '\\')' ).attr( 'value' );\n\n\t\t\tif ( !default_layout_id ) {\n\t\t\t\tthis.onSaveNewLayout( BaseViewController.default_layout_name );\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tvar layout_name = BaseViewController.default_layout_name;\n\n\t\t} else if ( this.show_search_tab ) {\n\t\t\tthis.onSaveNewLayout( BaseViewController.default_layout_name );\n\t\t\treturn;\n\t\t} else if ( !this.show_search_tab ) {\n\t\t\tthis.search();\n\t\t\tthis.setGridHeaderStyle();\n\t\t\treturn;\n\t\t}\n\n\t\tvar sort_filter = this.getSearchPanelSortFilter();\n\t\tvar selected_display_columns = this.getSearchPanelDisplayColumns();\n\n\t\tvar filter_data = this.getValidSearchFilter();\n\n\t\tvar args = {};\n\t\targs.id = default_layout_id;\n\t\targs.data = {};\n\t\targs.data.display_columns = selected_display_columns;\n\t\targs.data.filter_data = filter_data;\n\t\targs.data.filter_sort = sort_filter;\n\n\t\tProgressBar.showOverlay();\n\t\tvar $this = this;\n\t\tthis.user_generic_data_api.setUserGenericData( args, {\n\t\t\tonResult: function( res ) {\n\n\t\t\t\tif ( res.isValid() ) {\n\t\t\t\t\t$this.clearViewLayoutCache();\n\t\t\t\t\t$this.clearAwesomeboxLayoutCache();\n\t\t\t\t\t$this.need_select_layout_name = layout_name;\n\t\t\t\t\t$this.initLayout();\n\t\t\t\t}\n\t\t\t}\n\t\t} );\n\t}\n\n\tonClearSearch() {\n\t\tvar do_update = false;\n\t\tif ( this.search_panel.getLayoutsArray() && this.search_panel.getLayoutsArray().length > 0 ) {\n\t\t\tvar default_layout_id = $( this.previous_saved_layout_selector ).children( 'option:contains(\\'' + BaseViewController.default_layout_name + '\\')' ).attr( 'value' );\n\n\t\t\tif ( !default_layout_id ) {\n\t\t\t\tthis.clearSearchPanel();\n\t\t\t\tthis.filter_data = null;\n\t\t\t\tthis.temp_adv_filter_data = null;\n\t\t\t\tthis.temp_basic_filter_data = null;\n\t\t\t\tthis.column_selector.setSelectGridData( this.default_display_columns );\n\t\t\t\tthis.sort_by_selector.setValue( null );\n\n\t\t\t\tthis.onSaveNewLayout( BaseViewController.default_layout_name );\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tvar layout_name = BaseViewController.default_layout_name;\n\t\t\tthis.clearSearchPanel();\n\t\t\tthis.filter_data = null;\n\t\t\tthis.temp_adv_filter_data = null;\n\t\t\tthis.temp_basic_filter_data = null;\n\t\t\tdo_update = true;\n\n\t\t} else {\n\n\t\t\tthis.clearSearchPanel();\n\t\t\tthis.filter_data = null;\n\t\t\tthis.temp_adv_filter_data = null;\n\t\t\tthis.temp_basic_filter_data = null;\n\t\t\tthis.column_selector.setSelectGridData( this.default_display_columns );\n\t\t\tthis.sort_by_selector.setValue( null );\n\n\t\t\tthis.onSaveNewLayout( BaseViewController.default_layout_name );\n\t\t\treturn;\n\n\t\t}\n\n//\t\tthis.column_selector.setSelectGridData( this.default_display_columns );\n\n\t\tthis.sort_by_selector.setValue( null );\n\n\t\tvar sort_filter = this.getSearchPanelSortFilter();\n\t\tvar selected_display_columns = this.getSearchPanelDisplayColumns();\n\t\tvar filter_data = this.getValidSearchFilter();\n\n\t\tif ( do_update ) {\n\t\t\tvar args = {};\n\t\t\targs.id = default_layout_id;\n\t\t\targs.data = {};\n\t\t\targs.data.display_columns = selected_display_columns;\n\t\t\targs.data.filter_data = filter_data;\n\t\t\targs.data.filter_sort = sort_filter;\n\n\t\t}\n\n\t\tvar $this = this;\n\t\tthis.user_generic_data_api.setUserGenericData( args, {\n\t\t\tonResult: function( res ) {\n\n\t\t\t\tif ( res.isValid() ) {\n\t\t\t\t\t$this.clearViewLayoutCache();\n\t\t\t\t\t$this.need_select_layout_name = layout_name;\n\t\t\t\t\t$this.initLayout();\n\t\t\t\t}\n\n\t\t\t}\n\t\t} );\n\t}\n\n\tonSaveNewLayout( default_layout_name ) {\n\n\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( default_layout_name ) ) {\n\t\t\tvar layout_name = default_layout_name;\n\t\t} else {\n\t\t\tlayout_name = this.save_search_as_input.getValue();\n\t\t}\n\n\t\tif ( !layout_name || layout_name.length < 1 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar sort_filter = this.getSearchPanelSortFilter();\n\t\tvar selected_display_columns = this.getSearchPanelDisplayColumns();\n\t\tvar filter_data = this.getValidSearchFilter();\n\n\t\tvar args = {};\n\t\targs.script = this.script_name;\n\t\targs.name = layout_name;\n\t\targs.is_default = false;\n\t\targs.data = {};\n\t\targs.data.display_columns = selected_display_columns;\n\t\targs.data.filter_data = filter_data;\n\t\targs.data.filter_sort = sort_filter;\n\n\t\tvar $this = this;\n\n\t\tvar a_layout_name = ALayoutCache.layout_dic[this.script_name];\n\t\tif ( a_layout_name && ALayoutCache.layout_dic[a_layout_name] ) {\n\t\t\tALayoutCache.layout_dic[a_layout_name] = null;\n\t\t}\n\n\t\tthis.user_generic_data_api.setUserGenericData( args, {\n\t\t\tonResult: function( res ) {\n\n\t\t\t\tif ( res.isValid() ) {\n\t\t\t\t\t$this.clearAwesomeboxLayoutCache();\n\t\t\t\t\t$this.clearViewLayoutCache();\n\t\t\t\t\t$this.need_select_layout_name = layout_name;\n\t\t\t\t\t$this.initLayout();\n\n\t\t\t\t} else {\n\t\t\t\t\tTAlertManager.showErrorAlert( res );\n\t\t\t\t}\n\n\t\t\t}\n\t\t} );\n\t}\n\n\tonUpdateLayout() {\n\n\t\tvar selectId = $( this.previous_saved_layout_selector ).children( 'option:selected' ).attr( 'value' );\n\t\tvar layout_name = $( this.previous_saved_layout_selector ).children( 'option:selected' ).text();\n\n\t\tvar sort_filter = this.getSearchPanelSortFilter();\n\t\tvar selected_display_columns = this.getSearchPanelDisplayColumns();\n\t\tvar filter_data = this.getValidSearchFilter();\n\n\t\tvar args = {};\n\t\targs.id = selectId;\n\t\targs.data = {};\n\t\targs.data.display_columns = selected_display_columns;\n\t\targs.data.filter_data = filter_data;\n\t\targs.data.filter_sort = sort_filter;\n\n\t\tvar $this = this;\n\n\t\tvar a_layout_name = ALayoutCache.layout_dic[this.script_name];\n\t\tif ( a_layout_name && ALayoutCache.layout_dic[a_layout_name] ) {\n\t\t\tALayoutCache.layout_dic[a_layout_name] = null;\n\t\t}\n\n\t\tthis.user_generic_data_api.setUserGenericData( args, {\n\t\t\tonResult: function( res ) {\n\n\t\t\t\tif ( res.isValid() ) {\n\t\t\t\t\t$this.clearAwesomeboxLayoutCache();\n\t\t\t\t\t$this.clearViewLayoutCache();\n\t\t\t\t\t$this.need_select_layout_name = layout_name;\n\t\t\t\t\t$this.initLayout();\n\t\t\t\t}\n\n\t\t\t}\n\t\t} );\n\t}\n\n\tclearViewLayoutCache() {\n\t\tif ( LocalCacheData.view_layout_cache && LocalCacheData.view_layout_cache[this.script_name] ) {\n\t\t\tLocalCacheData.view_layout_cache[this.script_name] = null;\n\t\t}\n\t}\n\n\tclearAwesomeboxLayoutCache() {\n\t\t// Removed saved view layout for awesomebox if it existed.\n\t\tif ( ALayoutCache.layout_dic && ALayoutCache.layout_dic[this.script_name] ) {\n\t\t\tALayoutCache.layout_dic[ALayoutCache.layout_dic[this.script_name]] = null;\n\t\t}\n\t}\n\n\tonDeleteLayout() {\n\t\tvar selectId = $( this.previous_saved_layout_selector ).children( 'option:selected' ).attr( 'value' );\n\n\t\tvar $this = this;\n\t\tthis.user_generic_data_api.deleteUserGenericData( selectId, {\n\t\t\tonResult: function( res ) {\n\t\t\t\tif ( res.isValid() ) {\n\t\t\t\t\t$this.clearAwesomeboxLayoutCache();\n\t\t\t\t\t$this.clearViewLayoutCache();\n\t\t\t\t\t$this.need_select_layout_name = $this.select_layout.name;\n\t\t\t\t\t$this.initLayout();\n\t\t\t\t}\n\n\t\t\t}\n\t\t} );\n\t}\n\n\tbuildSearchFields() {\n\t\t//Override in all subview\n\t}\n\n\tbuildCustomFieldSearchFields() {\n\t\tif ( !this.search_fields ) {\n\t\t\tthis.search_fields = [];\n\t\t}\n\n\t\tthis.custom_fields.forEach( ( field ) => {\n\t\t\tif ( field.enable_search ) {\n\n\t\t\t\tlet field_settings = {\n\t\t\t\t\tlabel: field.name,\n\t\t\t\t\tin_column: 1,\n\t\t\t\t\tfield: this.getPrefixedCustomFieldID( field.id ),\n\t\t\t\t\tbasic_search: false,\n\t\t\t\t\tadv_search: true,\n\t\t\t\t};\n\n\t\t\t\tlet type_id = parseInt( field.type_id );\n\n\t\t\t\tswitch ( type_id ) {\n\t\t\t\t\tcase 500: //Checkbox\n\t\t\t\t\t\tfield_settings.form_item_type = _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.FormItemType.AWESOME_BOX;\n\t\t\t\t\t\tfield_settings.multiple = false;\n\t\t\t\t\t\tfield_settings.layout_name = 'global_option_column';\n\t\t\t\t\t\tfield_settings.addition_source_function = ( target, source_data ) => {\n\t\t\t\t\t\t\tsource_data = [\n\t\t\t\t\t\t\t\t{ value: TTUUID.zero_id, label: '-- ' + $.i18n._( 'ANY' ) + ' --' },\n\t\t\t\t\t\t\t\t{ value: true, label: $.i18n._( 'Yes' ) },\n\t\t\t\t\t\t\t\t{ value: false, label: $.i18n._( 'No' ) }\n\t\t\t\t\t\t\t];\n\t\t\t\t\t\t\treturn source_data;\n\t\t\t\t\t\t};\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 1000: //Date\n\t\t\t\t\t\tfield_settings.form_item_type = _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.FormItemType.DATE_PICKER;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t// case 1010: //Date Range Search Disabled\n\t\t\t\t\t// \tfield_settings.form_item_type = FormItemType.DATE_PICKER;\n\t\t\t\t\t// \tbreak;\n\t\t\t\t\tcase 1100: //Time\n\t\t\t\t\t\tfield_settings.form_item_type = _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.FormItemType.TIME_PICKER;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 1200: //Datetime\n\t\t\t\t\t\tfield_settings.form_item_type = _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.FormItemType.DATE_PICKER;\n\t\t\t\t\t\tfield_settings.mode = 'date_time';\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 1300: //Time Unit\n\t\t\t\t\t\tfield_settings.form_item_type = _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.FormItemType.TEXT_INPUT;\n\t\t\t\t\t\tfield_settings.mode = 'time_unit';\n\t\t\t\t\t\tfield_settings.need_parser_sec = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 2100: //Single-select dropdown\n\t\t\t\t\tcase 2110: //Multi-select dropdown\n\t\t\t\t\t\tfield_settings.form_item_type = _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.FormItemType.AWESOME_BOX;\n\t\t\t\t\t\tfield_settings.multiple = false;\n\t\t\t\t\t\tfield_settings.layout_name = 'global_option_column';\n\t\t\t\t\t\tfield_settings.addition_source_function = ( target, source_data ) => {\n\t\t\t\t\t\t\tsource_data = []; //Overwriting source data to empty array.\n\t\t\t\t\t\t\tif ( field.meta_data.validation.multi_select_items ) {\n\t\t\t\t\t\t\t\tfield.meta_data.validation.multi_select_items.forEach( ( item ) => {\n\t\t\t\t\t\t\t\t\tsource_data.push( {\n\t\t\t\t\t\t\t\t\t\tid: item.id,\n\t\t\t\t\t\t\t\t\t\tvalue: item.id,\n\t\t\t\t\t\t\t\t\t\tlabel: item.label\n\t\t\t\t\t\t\t\t\t} );\n\t\t\t\t\t\t\t\t} );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn source_data;\n\t\t\t\t\t\t};\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tfield_settings.form_item_type = _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.FormItemType.TEXT_INPUT;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t}\n\n\t\t\t\tthis.search_fields.push( new SearchField( field_settings ) );\n\t\t\t}\n\t\t} );\n\t}\n\n\tbuildBasicSearchUI() {\n\t\tif ( !this.search_fields ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar basic_search_div = this.search_panel.find( 'div #basic_search_content_div' );\n\n\t\tvar len = this.search_fields.length;\n\t\tvar $this = this;\n\n\t\tvar column1 = basic_search_div.find( '.first-column' );\n\t\tvar column2 = basic_search_div.find( '.second-column' );\n\t\tvar column3 = basic_search_div.find( '.third-column' );\n\n\t\tvar already_created_ui = false;\n\t\t$.each( this.search_fields, function( index, search_field ) {\n\t\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( $this.basic_search_field_ui_dic[search_field.get( 'field' )] ) ) {\n\t\t\t\talready_created_ui = true;\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tif ( !search_field.get( 'basic_search' ) ) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\t// var form_item = $( Global.loadWidget( 'global/widgets/search_panel/FormItem.html' ) ); // TODO: #3023: Delete this line once widget html converted and no longer need this quick reference for the old format.\n\t\t\tvar form_item = $( $.fn.SearchPanel.html.form_item );\n\t\t\tvar form_item_label = form_item.find( '.form-item-label' );\n\t\t\tvar form_item_input_div = form_item.find( '.form-item-input-div' );\n\t\t\tvar form_item_input = $this.getFormItemInput( search_field );\n\t\t\tform_item_label.text( search_field.get( 'label' ) );\n\t\t\tform_item_input_div.append( form_item_input );\n\n\t\t\tswitch ( search_field.get( 'in_column' ) ) {\n\t\t\t\tcase 1:\n\t\t\t\t\tcolumn1.append( form_item );\n\t\t\t\t\tcolumn1.append( '' );\n\t\t\t\t\tbreak;\n\t\t\t\tcase 2:\n\t\t\t\t\tcolumn2.append( form_item );\n\t\t\t\t\tcolumn2.append( '' );\n\t\t\t\t\tbreak;\n\t\t\t\tcase 3:\n\t\t\t\t\tcolumn3.append( form_item );\n\t\t\t\t\tcolumn3.append( '' );\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t$this.basic_search_field_ui_dic[search_field.get( 'field' )] = form_item_input;\n\t\t} );\n\n\t\tif ( !already_created_ui ) {\n\t\t\tthis.onBuildBasicUIFinished();\n\t\t}\n\t}\n\n\tbuildAdvancedSearchUI() {\n\t\tif ( !this.search_fields ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar advSearchDiv = this.search_panel.find( 'div #adv_search_content_div' );\n\n\t\tvar $this = this;\n\n\t\tvar column1 = advSearchDiv.find( '.first-column' );\n\t\tvar column2 = advSearchDiv.find( '.second-column' );\n\t\tvar column3 = advSearchDiv.find( '.third-column' );\n\n\t\tvar already_created_ui = false;\n\t\tvar no_adv_ui = true;\n\n\t\t$.each( this.search_fields, function( index, search_field ) {\n\n\t\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( $this.adv_search_field_ui_dic[search_field.get( 'field' )] ) ) {\n\t\t\t\talready_created_ui = true;\n\t\t\t\tno_adv_ui = false;\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tif ( !search_field.get( 'adv_search' ) ) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\tvar form_item = $( $.fn.SearchPanel.html.form_item );\n\t\t\tvar form_item_label = form_item.find( '.form-item-label' );\n\t\t\tvar form_item_input_div = form_item.find( '.form-item-input-div' );\n\t\t\tvar form_item_input = $this.getFormItemInput( search_field );\n\t\t\tform_item_label.text( search_field.get( 'label' ) );\n\t\t\tform_item_input_div.append( form_item_input );\n\n\t\t\tswitch ( search_field.get( 'in_column' ) ) {\n\t\t\t\tcase 1:\n\t\t\t\t\tcolumn1.append( form_item );\n\t\t\t\t\tcolumn1.append( '' );\n\t\t\t\t\tbreak;\n\t\t\t\tcase 2:\n\t\t\t\t\tcolumn2.append( form_item );\n\t\t\t\t\tcolumn2.append( '' );\n\t\t\t\t\tbreak;\n\t\t\t\tcase 3:\n\t\t\t\t\tcolumn3.append( form_item );\n\t\t\t\t\tcolumn3.append( '' );\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t$this.adv_search_field_ui_dic[search_field.get( 'field' )] = form_item_input;\n\t\t\tno_adv_ui = false;\n\t\t} );\n\n\t\tif ( no_adv_ui ) {\n\n\t\t\tthis.search_panel.hideAdvSearchPanel();\n\t\t}\n\n\t\tif ( !already_created_ui ) {\n\t\t\tthis.onBuildAdvUIFinished();\n\t\t}\n\t}\n\n\tonSetSearchFilterFinished() {\n\t}\n\n\tonBuildAdvUIFinished() {\n\t\t//Always override in sub class\n\t}\n\n\tonBuildBasicUIFinished() {\n\t\t//Always override in sub class\n\t}\n\n\tgetFormItemInput( search_field ) {\n\t\tvar input;\n\t\tvar form_type = search_field.get( 'form_item_type' );\n\n\t\tswitch ( form_type ) {\n\t\t\tcase _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.FormItemType.AWESOME_BOX:\n\t\t\t\tinput = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.loadWidgetByName */ .x.loadWidgetByName( _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.FormItemType.AWESOME_BOX );\n\t\t\t\tvar show_search = false;\n\t\t\t\tvar key;\n\n\t\t\t\tif ( search_field.get( 'layout_name' ) !== 'global_option_column' && search_field.get( 'layout_name' ) !== 'global_tree_column' ) {\n\t\t\t\t\tshow_search = true;\n\t\t\t\t\tkey = 'id';\n\t\t\t\t} else {\n\n\t\t\t\t\tif ( search_field.get( 'layout_name' ) === 'global_tree_column' ) {\n\t\t\t\t\t\tkey = 'id';\n\t\t\t\t\t} else {\n\t\t\t\t\t\tkey = 'value';\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t\tinput.AComboBox( {\n\t\t\t\t\tapi_class: search_field.get( 'api_class' ),\n\t\t\t\t\tallow_multiple_selection: search_field.get( 'multiple' ),\n\t\t\t\t\tlayout_name: search_field.get( 'layout_name' ),\n\t\t\t\t\ttree_mode: search_field.get( 'tree_mode' ),\n\t\t\t\t\tdefault_args: search_field.get( 'default_args' ),\n\t\t\t\t\tshow_search_inputs: show_search,\n\t\t\t\t\tset_any: search_field.get( 'set_any' ),\n\t\t\t\t\taddition_source_function: search_field.get( 'addition_source_function' ),\n\t\t\t\t\tscript_name: search_field.get( 'script_name' ),\n\t\t\t\t\tcustom_first_label: search_field.get( 'custom_first_label' ),\n\t\t\t\t\tkey: key,\n\t\t\t\t\tsearch_panel_model: true,\n\t\t\t\t\tfield: search_field.get( 'field' )\n\t\t\t\t} );\n\n\t\t\t\tif ( search_field.get( 'customSearchFilter' ) ) {\n\t\t\t\t\tinput.customSearchFilter = search_field.get( 'customSearchFilter' );\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\t\t\tcase _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.FormItemType.TEXT_INPUT:\n\t\t\t\tinput = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.loadWidgetByName */ .x.loadWidgetByName( _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.FormItemType.TEXT_INPUT );\n\t\t\t\tinput.TTextInput( {\n\t\t\t\t\tfield: search_field.get( 'field' ),\n\t\t\t\t\tneed_parser_sec: search_field.get( 'need_parser_sec' ),\n\t\t\t\t\tmode: search_field.get( 'mode' ),\n\t\t\t\t} );\n\t\t\t\tbreak;\n\t\t\tcase _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.FormItemType.TIME_PICKER:\n\t\t\t\tinput = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.loadWidgetByName */ .x.loadWidgetByName( _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.FormItemType.TIME_PICKER );\n\t\t\t\tinput.TTimePicker( {\n\t\t\t\t\tfield: search_field.get( 'field' )\n\t\t\t\t} );\n\t\t\t\tbreak;\n\t\t\tcase _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.FormItemType.PASSWORD_INPUT:\n\t\t\t\tinput = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.loadWidgetByName */ .x.loadWidgetByName( _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.FormItemType.PASSWORD_INPUT );\n\t\t\t\tinput.TTextInput( {\n\t\t\t\t\tfield: search_field.get( 'field' )\n\t\t\t\t} );\n\t\t\t\tbreak;\n\t\t\tcase _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.FormItemType.COMBO_BOX:\n\t\t\t\tinput = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.loadWidgetByName */ .x.loadWidgetByName( _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.FormItemType.COMBO_BOX );\n\t\t\t\tinput.TComboBox( {\n\t\t\t\t\tfield: search_field.get( 'field' ),\n\t\t\t\t\tset_any: true\n\t\t\t\t} );\n\t\t\t\tbreak;\n\t\t\tcase _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.FormItemType.TAG_INPUT:\n\t\t\t\tinput = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.loadWidgetByName */ .x.loadWidgetByName( _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.FormItemType.TAG_INPUT );\n\t\t\t\tinput.TTagInput( {\n\t\t\t\t\tfield: search_field.get( 'field' ),\n\t\t\t\t\tobject_type_id: search_field.get( 'object_type_id' )\n\t\t\t\t} );\n\n\t\t\t\tbreak;\n\t\t\tcase _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.FormItemType.DATE_PICKER:\n\t\t\t\tinput = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.loadWidgetByName */ .x.loadWidgetByName( form_type );\n\t\t\t\tinput = $( input );\n\t\t\t\tinput.TDatePicker( {\n\t\t\t\t\tfield: search_field.get( 'field' ),\n\t\t\t\t\tmode: search_field.get( 'mode' ),\n\t\t\t\t} );\n\n\t\t\t\tbreak;\n\t\t\tcase _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.FormItemType.CHECKBOX:\n\t\t\t\tinput = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.loadWidgetByName */ .x.loadWidgetByName( _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.FormItemType.CHECKBOX );\n\t\t\t\tinput.TCheckbox( {\n\t\t\t\t\tfield: search_field.get( 'field' )\n\t\t\t\t} );\n\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tDebug.Error( 'ERROR: Form type does not exist: '+ form_type, 'BaseViewController.js', 'BaseViewController', 'getFormItemInput', 2 );\n\t\t\t\tbreak;\n\t\t}\n\n\t\treturn input;\n\t}\n\n\tbuildSearchAndLayoutUI() {\n\t\tvar layout_div = this.search_panel.find( 'div #saved_layout_content_div' );\n\n\t\t//Display Columns\n\n\t\tvar form_item = $( $.fn.SearchPanel.html.form_item );\n\t\tvar form_item_label = form_item.find( '.form-item-label' );\n\t\tvar form_item_input_div = form_item.find( '.form-item-input-div' );\n\n\t\tthis.column_selector = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.loadWidgetByName */ .x.loadWidgetByName( _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.FormItemType.AWESOME_DROPDOWN );\n\n\t\tthis.column_selector = this.column_selector.ADropDown( {\n\t\t\tdisplay_show_all: false,\n\t\t\tid: this.ui_id + '_column_selector',\n\t\t\tkey: 'value',\n\t\t\tallow_drag_to_order: true,\n\t\t\tdisplay_close_btn: false,\n\t\t\tdisplay_column_settings: false,\n\t\t\tmax_height: 150\n\t\t} );\n\t\tthis.column_selector.on( 'formItemChange', function() {\n\t\t\t$this.layout_changed = true;\n\t\t} );\n\n\t\tform_item_label.text( $.i18n._( 'Display Columns' ) );\n\t\tform_item_label.addClass( 'SearchPanel-displayColumns-label' );\n\t\tform_item_input_div.append( this.column_selector );\n\n\t\tlayout_div.append( form_item );\n\n\t\tlayout_div.append( '' );\n\n\t\tthis.column_selector.setColumns( [\n\t\t\t{ name: 'label', index: 'label', label: $.i18n._( 'Column Name' ), width: 100, sortable: false }\n\t\t] );\n\n\t\t//Sort By\n\t\tform_item = $( $.fn.SearchPanel.html.form_item );\n\t\tform_item_label = form_item.find( '.form-item-label' );\n\t\tform_item_input_div = form_item.find( '.form-item-input-div' );\n\t\tthis.sort_by_selector = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.loadWidgetByName */ .x.loadWidgetByName( _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.FormItemType.AWESOME_BOX );\n\t\tthis.sort_by_selector = this.sort_by_selector.AComboBox( {\n\t\t\tallow_drag_to_order: true,\n\t\t\tallow_multiple_selection: true,\n\t\t\tset_empty: true,\n\t\t\tlayout_name: 'global_sort_columns'\n\t\t} );\n\n\t\tform_item_label.text( $.i18n._( 'Sort By' ) );\n\t\tform_item_input_div.append( this.sort_by_selector );\n\n\t\tlayout_div.append( form_item );\n\n\t\tlayout_div.append( '' );\n\n\t\t//Save and update layout\n\n\t\tform_item = $( $.fn.SearchPanel.html.form_item );\n\t\tform_item_label = form_item.find( '.form-item-label' );\n\t\tform_item_input_div = form_item.find( '.form-item-input-div' );\n\n\t\tform_item_label.text( $.i18n._( 'Save Search As' ) );\n\n\t\tthis.save_search_as_input = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.loadWidgetByName */ .x.loadWidgetByName( _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.FormItemType.TEXT_INPUT );\n\t\tthis.save_search_as_input.TTextInput();\n\n\t\tvar save_btn = $( '' );\n\n\t\tform_item_input_div.append( this.save_search_as_input );\n\t\tform_item_input_div.append( save_btn );\n\n\t\tvar $this = this;\n\t\tsave_btn.click( function() {\n\t\t\t$this.saving_layout_in_layout_tab = true;\n\t\t\t$this.onSaveNewLayout();\n\t\t\t$this.search();\n\t\t} );\n\n\t\t//Previous Saved Layout\n\n\t\tthis.previous_saved_layout_div = $( '' );\n\n\t\tform_item_input_div.append( this.previous_saved_layout_div );\n\n\t\tform_item_label = $( '' + $.i18n._( 'Previous Saved Searches' ) + ':' );\n\t\tthis.previous_saved_layout_div.append( form_item_label );\n\n\t\tthis.previous_saved_layout_selector = $( '