1$(function () { 2 //restoring delayClick functionality for kendo, new version of jquery doesn't have this 3 //kendo has a dependency on it. 4 if (typeof kendo !== 'undefined' && kendo.support && !kendo.support.delayedClick) { 5 kendo.support.delayedClick = function () { 6 return true; 7 } 8 } 9}) 10 11// Microsoft Ajax `String.format` replacement (for MVC page) 12if (!$.isFunction(String.format)) { 13 String.format = function () { 14 var s = arguments[0]; 15 for (var i = 0; i < arguments.length - 1; i++) { 16 var reg = new RegExp("\\{" + i + "\\}", "gm"); 17 s = s.replace(reg, arguments[i + 1]).replace('{{', '{').replace('}}', '}'); 18 } 19 return s; 20 }; 21} 22 23// Extends jQuery with browser.isIE check 24// $.browser.isIE() 25$.extend({ 26 browser: { 27 isIE: function () { 28 return (window.navigator.userAgent.indexOf("MSIE ") > 0) || (window.navigator.userAgent.indexOf("Trident/") > 0); 29 } 30 } 31}); 32 33 34function detectIEVersion() { 35 var ua = window.navigator.userAgent; 36 37 var msie = ua.indexOf('MSIE '); 38 if (msie > 0) { 39 // IE 10 or older => return version number 40 return parseInt(ua.substring(msie + 5, ua.indexOf('.', msie)), 10); 41 } 42 43 var trident = ua.indexOf('Trident/'); 44 if (trident > 0) { 45 // IE 11 => return version number 46 var rv = ua.indexOf('rv:'); 47 return parseInt(ua.substring(rv + 3, ua.indexOf('.', rv)), 10); 48 } 49 50 var edge = ua.indexOf('Edge/'); 51 if (edge > 0) { 52 // Edge (IE 12+) => return version number 53 return parseInt(ua.substring(edge + 5, ua.indexOf('.', edge)), 10); 54 } 55} 56 57 58// jQuery plugin that adds progress spinner to elements 59// $(el).progressloader(); // Show spinner 60// $(el).progressloader({show: false}); // Hide spinner 61$.fn.progressloader = function (customOptions) { 62 63 var options = $.extend("", $.fn.progressloader.defaultOptions, customOptions); 64 65 return this.each(function (e) { 66 67 var $element = $(this); 68 69 // $element is a jQuery object. The element must have a position:relative style applied 70 kendo.ui.progress($element, options.show); 71 72 }); 73}; 74 75$.fn.progressloader.defaultOptions = { 76 show: true 77}; 78 79// Add Progress Spinner to element 80// showProgressSpinner("#element"); // Show spinner 81// showProgressSpinner("#element", false); // Hide spinner 82// The el must have a position:relative style applied 83function ShowSpinner(el, show) { 84 show = (show != null && show != "undefined") ? show : true; 85 86 $(el).progressloader({ 87 show: show 88 }); 89} 90 91var erecruit = { 92 Strings: {} 93}; 94 95Object.assign(erecruit, 96 { 97 Notes: 98 { 99 // itemid is scheduleditemid if for confirmation but can be either note or scheduleditem id for deletion (depending on action) 100 DoAction: function (itemid, action, confirmtext) { 101 if (confirmtext && confirmtext != "" && !window.confirm(confirmtext)) 102 return false; 103 104 $.ajax( 105 { 106 url: baseUrl + "Services/NoteService.asmx/" + action, 107 data: "{ itemid: '" + itemid + "', by: '" + erecruitcache.Current.UserID + "' }", 108 dataType: "json", type: "POST", contentType: "application/json; charset=utf-8", 109 success: function (result) { 110 result = $.parseJSON(result.d); 111 112 $(document).trigger("Note_Updated", 113 { 114 'UpdateAction': action, 115 'ItemID': itemid 116 }); 117 }, 118 error: function (err) { 119 alert(erecruit.String.TheItemWasNotUpdated + "\n" + $.parseJSON(err.responseText).Message); 120 } 121 }); 122 } 123 }, 124 CoolTips: 125 { 126 // divs to put into places while loading 127 MainLoaderDiv: "<div class='cooltiploading main'><img src='" + baseUrl + "Mvc/Content/Images/ajaxloader_small.gif' title='" + erecruit.Strings.Loading + "' /></div>", 128 TabLoaderDiv: "<div class='cooltiploading'><img src='" + baseUrl + "Mvc/Content/Images/ajaxloader_small.gif' title='" + erecruit.Strings.Loading + "' /></div>", 129 LoadingSpinner: "<div class='loading-container'> <div class='loading-blocker'></div><div class='loading-spinner'></div></div>", //new loading spinner from erecruit style guide 130 // Defines options at the top of a cooltip that don't need an ajax load 131 ImmediateOptions: 132 { 133 Options: /* Localized text and tooltip properties post loading erecruit.js in source file 'LocalizationErecruitJs.cshtml' */ 134 { 135 // {0} is always context, {1} is always refid 136 open: { text: "", iconUrl: baseUrl + "Mvc/Content/Images/icons/14/open.png", js: "OpenPage('{0}', 'manage', '{1}');" }, 137 newnote: { text: "", iconUrl: baseUrl + "Mvc/Content/Images/icons/note_add.png", clicktip: "data-tipsource='ManageScheduledItem, app/BL/ScheduledItem/ScheduledItem' data-tipmode='norc' data-tipargs=\"{{ AboutType: '{0}', ReferenceID:'{1}'}}\"" }, 138 newscheduleditem: { text: "", iconUrl: baseUrl + "Mvc/Content/Images/icons/calendar_add.png", clicktip: "data-tipsource='ManageScheduledItem, app/BL/ScheduledItem/ScheduledItem' data-tipmode='norc' data-tipargs=\"{{ AboutType: '{0}', ReferenceID:'{1}', WithItem: true}}\"" }, 139 newtask: { text: "", iconUrl: baseUrl + "Mvc/Content/Images/icons/task_add.png", clicktip: "data-tipsource='ManageScheduledItem, app/BL/ScheduledItem/ScheduledItem' data-tipmode='norc' data-tipargs=\"{{AboutType:'{0}', ReferenceID:'{1}', WithItem: true, TypeID: 110 }}\"" }, 140 openattachment: { iconUrl: baseUrl + "Mvc/Content/Images/icons/14/open.png", js: "require(['app/BL/Attachment/AttachmentPreview'], function (ap) { ap.OpenAttachment('{1}'); });" }, 141 openattachmentinwindow: { iconUrl: baseUrl + "Mvc/Content/Images/icons/14/open.png", js: "require(['app/BL/Attachment/AttachmentPreview'], function (ap) { ap.OpenAttachmentInWindow('" + baseUrl + "', '{1}'); });" }, 142 downloadattachment: { iconUrl: baseUrl + "Mvc/Content/Images/icons/14/open.png", js: "window.open('" + baseUrl + "Pages/General/ShowAttachment.aspx?refid={1}&mode=Download')" }, 143 email: { iconUrl: baseUrl + "Mvc/Content/Images/icons/14/newemail.png", js: "OpenPage('email', 'send', '{0}id_{1}', 'tomode={0}&ids={1}');" }, 144 emailcandidate: { iconUrl: baseUrl + "Mvc/Content/Images/icons/14/newemail.png", js: "OpenPage('email', 'send', '{0}id_{1}', 'tomode=candidate&referrer={0}:{1}');" }, 145 emailcontact: { iconUrl: baseUrl + "Mvc/Content/Images/icons/14/newemail.png", js: "OpenPage('email', 'send', '{0}id_{1}', 'tomode=contact&referrer={0}:{1}');" }, 146 emailaddress: { iconUrl: baseUrl + "Mvc/Content/Images/icons/14/newemail.png", js: "OpenPage('email', 'send', '{0}id_{1}', 'tomode={0}&ids={1}&to={3}');" }, 147 emailaddressthroughoutlook: { iconUrl: baseUrl + "Mvc/Content/Images/icons/14/newemail.png", js: "window.top.location='mailto:{2}{4}'" }, 148 copyemailaddress: { iconUrl: baseUrl + "Mvc/Content/Images/icons/copy.png", js: "window.prompt(" + erecruit.Strings.CopyToClipboard + ", '{3}');" }, 149 newcontact: { iconUrl: baseUrl + "Mvc/Content/Images/icons/14/newcontact.png", js: "OpenPage('contact', 'new', '{0}id_{1}', '{0}id={1}');" }, 150 newposition: { iconUrl: baseUrl + "Mvc/Content/Images/icons/14/newposition.png", js: "OpenPage('position', 'new', '{0}id_{1}', '{0}id={1}');" }, 151 newagreement: { iconUrl: baseUrl + "Mvc/Content/Images/icons/14/newagreement.png", js: "OpenPage('agreement', 'new', '{0}id_{1}', '{0}id={1}');" }, 152 newmatch: { iconUrl: baseUrl + "Mvc/Content/Images/icons/14/newmatch.png", js: "OpenPage('match', 'new', '{0}id_{1}', '{0}id={1}');" }, 153 newquickplacement: { iconUrl: baseUrl + "Mvc/Content/Images/icons/14/newmatch.png", js: "OpenPage('match', 'new', '{0}id_{1}', 'quickplacement=true&{0}id={1}');" }, 154 newopportunity: { iconUrl: baseUrl + "Mvc/Content/Images/icons/14/newopportunity.png", js: "OpenPage('opportunity', 'new', '{0}id_{1}', '{0}id={1}');" }, 155 newlegalcase: { iconUrl: baseUrl + "Mvc/Content/Images/icons/14/newlegalcase.png", js: "OpenPage('legalcase', 'new', '{0}id_{1}', '{0}id={1}');" }, 156 opencandidatefromdatafield: { iconUrl: baseUrl + "Mvc/Content/Images/icons/14/open.png", js: "OpenPage('candidate', 'manage', '{0}');" }, 157 openpositionfromdatafield: { iconUrl: baseUrl + "Mvc/Content/Images/icons/14/open.png", js: "OpenPage('position', 'manage', '{0}');" }, 158 editall: { text: "", iconUrl: baseUrl + "Mvc/Content/Images/icons/14/edit.png", clicktip: "data-tipname='{0}/editall' data-tipmode='norc' data-tipcontext='{0}' data-tiprefid='{1}'" }, 159 bulkedithours: { text: "", iconUrl: baseUrl + "Mvc/Content/Images/icons/14/edit.png", clicktip: "data-tipname='{0}/bulkedithours' data-tipmode='norc' data-tipcontext='{0}' data-tiprefid='{1}'" }, 160 findrelevantpositions: { iconUrl: baseUrl + "Mvc/Content/Images/icons/14/position.png", js: "OpenSearchPage('position', 'SimilarToCandidate','sourceCandidateId={1}');" }, 161 findrelevantcandidates: { iconUrl: baseUrl + "Mvc/Content/Images/icons/14/candidate.png", js: "OpenSearchPage('candidate', 'SimilarToPosition','sourcePositionId={1}');" }, 162 manageloginaccess: { iconUrl: baseUrl + "Mvc/Content/Images/icons/key.png", clicktip: "data-tipname='provision' data-tipmode='norc' data-tipcontext='{0}' data-tiprefid='{1}'" } 163 }, 164 // Resolves an option for an element 165 ResolveOne: function (option, element) { 166 // catch special options in here 167 if (option == this.Options.opencandidatefromdatafield) // assumes presense of data-candidateid 168 { 169 return "<div " + 170 "class='rcoption' " + 171 "title=\"" + option.tooltip + "\" " + 172 "onclick=\"" + String.format(option.js, $(element).data("candidateid")) + "\">" + 173 "<img align='top' width='14' src='" + option.iconUrl + "'>" + option.text + 174 "</div>"; 175 } 176 else if (option == this.Options.openpositionfromdatafield) // assumes presense of data-positionid 177 { 178 return "<div " + 179 "class='rcoption' " + 180 "title=\"" + option.tooltip + "\" " + 181 "onclick=\"" + String.format(option.js, $(element).data("positionid")) + "\">" + 182 "<img align='top' width='14' src='" + option.iconUrl + "'>" + option.text + 183 "</div>"; 184 } 185 else if (option == this.Options.emailaddress || option == this.Options.emailaddressthroughoutlook || option == this.Options.copyemailaddress) // assumes presense of data-fullname and data-email 186 { 187 return "<div " + 188 "class='rcoption' " + 189 "title=\"" + String.format(option.tooltip, $(element).data("tipcontext"), $(element).data("tiprefid"), $(element).data("fullname"), $(element).data("email")) + "\" " + 190 "onclick=\"" + String.format(option.js, $(element).data("tipcontext"), $(element).data("tiprefid"), encodeURIComponent($(element).data("fullname")).replace(/'/g, "%27"), $(element).data("email"), ($(element).data("fullname") == "" ? $(element).data("email") : " <" + $(element).data("email") + ">")) + "\">" + 191 "<img align='top' width='14' src='" + option.iconUrl + "'>" + option.text + 192 "</div>"; 193 } 194 else { 195 if (option.clicktip == null) // regular option 196 { 197 return "<div " + 198 "class='rcoption' " + 199 "title=\"" + String.format(option.tooltip, $(element).data("tipcontext"), $(element).data("tiprefid")) + "\" " + 200 "onclick=\"" + String.format(option.js, $(element).data("tipcontext"), $(element).data("tiprefid")) + "\">" + 201 "<img align='top' width='14' src='" + option.iconUrl + "'>" + option.text + 202 "</div>"; 203 } 204 else // clicktip 205 { 206 return "<div class='rcoption' title=\"" + String.format(option.tooltip, $(element).data("tipcontext"), $(element).data("tiprefid")) + "\">" + 207 "<div class='clicktip' " + String.format(option.clicktip, $(element).data("tipcontext"), $(element).data("tiprefid")) + "><img align='top' width='14' src='" + option.iconUrl + "'>" + option.text + "</div></div>"; 208 } 209 } 210 }, 211 // Gets a list of all resolved options for an element 212 ResolveOptions: function (options, element) { 213 var returnlist = ""; 214 215 for (var i = 0; i < options.length; i++) { 216 if (options[i] != null) 217 returnlist += this.ResolveOne(options[i], element); 218 } 219 220 return returnlist == "" ? returnlist : 221 "<div class='rcoptions ui-helper-clearfix'>" + returnlist + "</div>"; 222 }, 223 // Given an element, figures out the context and returns a list of ImmediateOptions.Option 224 GetElementOptions: function (element) { 225 226 // data-tipimmediateoptionscontext="emailaddress" 227 // for when you want to override the immidiate options but don't have an actual about type to do it with 228 if ($(element).data("tipimmediateoptionscontext") != null) { 229 switch ($(element).data("tipimmediateoptionscontext")) { 230 case "emailaddress": return [erecruit.CoolTips.ImmediateOptions.Options.emailaddress, erecruit.CoolTips.ImmediateOptions.Options.emailaddressthroughoutlook]; 231 } 232 } 233 else { 234 var context = $(element).data("tipcontext"); 235 236 if (isLegalCaseAboutTypeEnabled) 237 erecruit.CoolTips.ImmediateOptions.Options.newlegalcase = null; 238
239 switch (erecruitcache.Current.LoggedInAsMode) { 240 case "Vendor": 241 switch (context) { 242 case "candidate": return [erecruit.CoolTips.ImmediateOptions.Options.open, erecruit.CoolTips.ImmediateOptions.Options.editall, erecruit.CoolTips.ImmediateOptions.Options.newnote, erecruit.CoolTips.ImmediateOptions.Options.newscheduleditem, erecruit.CoolTips.ImmediateOptions.Options.newtask, erecruit.CoolTips.ImmediateOptions.Options.email, erecruit.CoolTips.ImmediateOptions.Options.newmatch]; 243 case "position": return [erecruit.CoolTips.ImmediateOptions.Options.open, erecruit.CoolTips.ImmediateOptions.Options.newmatch]; 244 case "match": return [erecruit.CoolTips.ImmediateOptions.Options.open, erecruit.CoolTips.ImmediateOptions.Options.newnote, erecruit.CoolTips.ImmediateOptions.Options.emailcandidate]; 245 case "timesheet": return [erecruit.CoolTips.ImmediateOptions.Options.open, erecruit.CoolTips.ImmediateOptions.Options.newnote]; 246 case "attachment": return [erecruit.CoolTips.ImmediateOptions.Options.openattachment, erecruit.CoolTips.ImmediateOptions.Options.openattachmentinwindow, erecruit.CoolTips.ImmediateOptions.Options.downloadattachment]; 247 case "contact": return []; 248 } 249 case "VendorManager": 250 switch (context) { 251 case "candidate": return [erecruit.CoolTips.ImmediateOptions.Options.open, erecruit.CoolTips.ImmediateOptions.Options.newnote, erecruit.CoolTips.ImmediateOptions.Options.newscheduleditem, erecruit.CoolTips.ImmediateOptions.Options.newtask, erecruit.CoolTips.ImmediateOptions.Options.email]; 252 case "contact": return [erecruit.CoolTips.ImmediateOptions.Options.open, erecruit.CoolTips.ImmediateOptions.Options.newnote, erecruit.CoolTips.ImmediateOptions.Options.newscheduleditem, erecruit.CoolTips.ImmediateOptions.Options.newtask, erecruit.CoolTips.ImmediateOptions.Options.email, erecruit.CoolTips.ImmediateOptions.Options.newposition, erecruit.CoolTips.ImmediateOptions.Options.newagreement, erecruit.CoolTips.ImmediateOptions.Options.newopportunity]; 253 case "company": return [erecruit.CoolTips.ImmediateOptions.Options.open, erecruit.CoolTips.ImmediateOptions.Options.newnote, erecruit.CoolTips.ImmediateOptions.Options.newscheduleditem, erecruit.CoolTips.ImmediateOptions.Options.newtask, erecruit.CoolTips.ImmediateOptions.Options.newcontact, erecruit.CoolTips.ImmediateOptions.Options.newposition, erecruit.CoolTips.ImmediateOptions.Options.newagreement]; 254 case "position": return [erecruit.CoolTips.ImmediateOptions.Options.open, erecruit.CoolTips.ImmediateOptions.Options.editall, erecruit.CoolTips.ImmediateOptions.Options.newnote, erecruit.CoolTips.ImmediateOptions.Options.newscheduleditem, erecruit.CoolTips.ImmediateOptions.Options.newtask]; 255 case "match": return [erecruit.CoolTips.ImmediateOptions.Options.open, erecruit.CoolTips.ImmediateOptions.Options.editall, erecruit.CoolTips.ImmediateOptions.Options.newnote, erecruit.CoolTips.ImmediateOptions.Options.newscheduleditem, erecruit.CoolTips.ImmediateOptions.Options.newtask, erecruit.CoolTips.ImmediateOptions.Options.emailcandidate, erecruit.CoolTips.ImmediateOptions.Options.emailcontact]; 256 case "candidateapplication": return [erecruit.CoolTips.ImmediateOptions.Options.opencandidatefromdatafield, erecruit.CoolTips.ImmediateOptions.Options.openpositionfromdatafield, erecruit.CoolTips.ImmediateOptions.Options.newnote, erecruit.CoolTips.ImmediateOptions.Options.newscheduleditem, erecruit.CoolTips.ImmediateOptions.Options.newtask]; 257 case "agreement": return [erecruit.CoolTips.ImmediateOptions.Options.open, erecruit.CoolTips.ImmediateOptions.Options.newnote, erecruit.CoolTips.ImmediateOptions.Options.newscheduleditem, erecruit.CoolTips.ImmediateOptions.Options.newtask]; 258 case "opportunity": return [erecruit.CoolTips.ImmediateOptions.Options.open, erecruit.CoolTips.ImmediateOptions.Options.newnote, erecruit.CoolTips.ImmediateOptions.Options.newscheduleditem, erecruit.CoolTips.ImmediateOptions.Options.newtask, erecruit.CoolTips.ImmediateOptions.Options.newcontact]; 259 case "legalcase": return [erecruit.CoolTips.ImmediateOptions.Options.open, erecruit.CoolTips.ImmediateOptions.Options.newnote, erecruit.CoolTips.ImmediateOptions.Options.newscheduleditem, erecruit.CoolTips.ImmediateOptions.Options.newtask]; 260 case "marketingcampaign": return [erecruit.CoolTips.ImmediateOptions.Options.open, erecruit.CoolTips.ImmediateOptions.Options.newnote, erecruit.CoolTips.ImmediateOptions.Options.newscheduleditem, erecruit.CoolTips.ImmediateOptions.Options.newtask]; 261 case "timesheet": return [erecruit.CoolTips.ImmediateOptions.Options.open, erecruit.CoolTips.ImmediateOptions.Options.newnote, erecruit.CoolTips.ImmediateOptions.Options.newscheduleditem, erecruit.CoolTips.ImmediateOptions.Options.newtask]; 262 case "attachment": return [erecruit.CoolTips.ImmediateOptions.Options.openattachment, erecruit.CoolTips.ImmediateOptions.Options.openattachmentinwindow, erecruit.CoolTips.ImmediateOptions.Options.downloadattachment]; 263 case "seed": return [erecruit.CoolTips.ImmediateOptions.Options.open, erecruit.CoolTips.ImmediateOptions.Options.newnote, erecruit.CoolTips.ImmediateOptions.Options.newscheduleditem, erecruit.CoolTips.ImmediateOptions.Options.newtask]; 264 case "clientproject": return [erecruit.CoolTips.ImmediateOptions.Options.open, erecruit.CoolTips.ImmediateOptions.Options.newnote, erecruit.CoolTips.ImmediateOptions.Options.newscheduleditem, erecruit.CoolTips.ImmediateOptions.Options.newtask, erecruit.CoolTips.ImmediateOptions.Options.newposition]; 265 } 266 default: 267 switch (context) { 268 case "candidate": return [erecruit.CoolTips.ImmediateOptions.Options.open, erecruit.CoolTips.ImmediateOptions.Options.editall, erecruit.CoolTips.ImmediateOptions.Options.newnote, erecruit.CoolTips.ImmediateOptions.Options.newscheduleditem, erecruit.CoolTips.ImmediateOptions.Options.newtask, erecruit.CoolTips.ImmediateOptions.Options.email, erecruit.CoolTips.ImmediateOptions.Options.newmatch, erecruit.CoolTips.ImmediateOptions.Options.newquickplacement, erecruit.CoolTips.ImmediateOptions.Options.newopportunity, erecruit.CoolTips.ImmediateOptions.Options.findrelevantpositions]; 269 case "contact": return [erecruit.CoolTips.ImmediateOptions.Options.open, erecruit.CoolTips.ImmediateOptions.Options.newnote, erecruit.CoolTips.ImmediateOptions.Options.newscheduleditem, erecruit.CoolTips.ImmediateOptions.Options.newtask, erecruit.CoolTips.ImmediateOptions.Options.email, erecruit.CoolTips.ImmediateOptions.Options.newposition, erecruit.CoolTips.ImmediateOptions.Options.new
269agreement, erecruit.CoolTips.ImmediateOptions.Options.newopportunity, erecruit.CoolTips.ImmediateOptions.Options.manageloginaccess]; 270 case "company": return [erecruit.CoolTips.ImmediateOptions.Options.open, erecruit.CoolTips.ImmediateOptions.Options.newnote, erecruit.CoolTips.ImmediateOptions.Options.newscheduleditem, erecruit.CoolTips.ImmediateOptions.Options.newtask, erecruit.CoolTips.ImmediateOptions.Options.newcontact, erecruit.CoolTips.ImmediateOptions.Options.newposition, erecruit.CoolTips.ImmediateOptions.Options.newagreement, erecruit.CoolTips.ImmediateOptions.Options.newopportunity]; 271 case "position": return [erecruit.CoolTips.ImmediateOptions.Options.open, erecruit.CoolTips.ImmediateOptions.Options.editall, erecruit.CoolTips.ImmediateOptions.Options.newnote, erecruit.CoolTips.ImmediateOptions.Options.newscheduleditem, erecruit.CoolTips.ImmediateOptions.Options.newtask, erecruit.CoolTips.ImmediateOptions.Options.newmatch, erecruit.CoolTips.ImmediateOptions.Options.newquickplacement, erecruit.CoolTips.ImmediateOptions.Options.findrelevantcandidates]; 272 case "match": return [erecruit.CoolTips.ImmediateOptions.Options.open, erecruit.CoolTips.ImmediateOptions.Options.editall, erecruit.CoolTips.ImmediateOptions.Options.newnote, erecruit.CoolTips.ImmediateOptions.Options.newscheduleditem, erecruit.CoolTips.ImmediateOptions.Options.newtask, erecruit.CoolTips.ImmediateOptions.Options.emailcandidate, erecruit.CoolTips.ImmediateOptions.Options.emailcontact]; 273 case "candidateapplication": return [erecruit.CoolTips.ImmediateOptions.Options.newmatch, erecruit.CoolTips.ImmediateOptions.Options.newquickplacement, erecruit.CoolTips.ImmediateOptions.Options.opencandidatefromdatafield, erecruit.CoolTips.ImmediateOptions.Options.openpositionfromdatafield, erecruit.CoolTips.ImmediateOptions.Options.newnote, erecruit.CoolTips.ImmediateOptions.Options.newscheduleditem, erecruit.CoolTips.ImmediateOptions.Options.newtask]; 274 case "agreement": return [erecruit.CoolTips.ImmediateOptions.Options.open, erecruit.CoolTips.ImmediateOptions.Options.newnote, erecruit.CoolTips.ImmediateOptions.Options.newscheduleditem, erecruit.CoolTips.ImmediateOptions.Options.newtask]; 275 case "opportunity": return [erecruit.CoolTips.ImmediateOptions.Options.open, erecruit.CoolTips.ImmediateOptions.Options.newnote, erecruit.CoolTips.ImmediateOptions.Options.newscheduleditem, erecruit.CoolTips.ImmediateOptions.Options.newtask, erecruit.CoolTips.ImmediateOptions.Options.newcontact, erecruit.CoolTips.ImmediateOptions.Options.newposition, erecruit.CoolTips.ImmediateOptions.Options.newlegalcase]; 276 case "legalcase": return [erecruit.CoolTips.ImmediateOptions.Options.open, erecruit.CoolTips.ImmediateOptions.Options.newnote, erecruit.CoolTips.ImmediateOptions.Options.newscheduleditem, erecruit.CoolTips.ImmediateOptions.Options.newtask]; 277 case "marketingcampaign": return [erecruit.CoolTips.ImmediateOptions.Options.open, erecruit.CoolTips.ImmediateOptions.Options.newnote, erecruit.CoolTips.ImmediateOptions.Options.newscheduleditem, erecruit.CoolTips.ImmediateOptions.Options.newtask]; 278 case "timesheet": 279 if (erecruitcache.Current.LoggedInAsMode == "Recruiter") { 280 return [erecruit.CoolTips.ImmediateOptions.Options.open, erecruit.CoolTips.ImmediateOptions.Options.newnote, erecruit.CoolTips.ImmediateOptions.Options.newscheduleditem, erecruit.CoolTips.ImmediateOptions.Options.newtask, erecruit.CoolTips.ImmediateOptions.Options.bulkedithours]; 281 } else { 282 return [erecruit.CoolTips.ImmediateOptions.Options.open]; 283 } 284 case "attachment": return [erecruit.CoolTips.ImmediateOptions.Options.openattachment, erecruit.CoolTips.ImmediateOptions.Options.openattachmentinwindow, erecruit.CoolTips.ImmediateOptions.Options.downloadattachment]; 285 case "seed": return [erecruit.CoolTips.ImmediateOptions.Options.open, erecruit.CoolTips.ImmediateOptions.Options.newnote, erecruit.CoolTips.ImmediateOptions.Options.newscheduleditem, erecruit.CoolTips.ImmediateOptions.Options.newtask]; 286 case "clientproject": return [erecruit.CoolTips.ImmediateOptions.Options.open, erecruit.CoolTips.ImmediateOptions.Options.newnote, erecruit.CoolTips.ImmediateOptions.Options.newscheduleditem, erecruit.CoolTips.ImmediateOptions.Options.newtask, erecruit.CoolTips.ImmediateOptions.Options.newposition]; 287 } 288 } 289 } 290 291 return []; 292 } 293 }, 294 // Defines methods and options that get and load widgets into the cooltip body 295 Widgets: 296 { 297 // returns common parameters used by most cooltips 298 GetCommonParameters: function (element) { 299 var tipdata = $(element).data("tipdata"); 300 if (typeof tipdata !== "string") tipdata = JSON.stringify(tipdata); 301 return { 302 "AboutType": $(element).data("tipcontext"), 303 "ReferenceID": $(element).data("tiprefid"),
304 "LoggedInAsMode": erecruitcache.Current.LoggedInAsMode, 305 "CurrentUserID": erecruitcache.Current.UserID, 306 "CurrentEntityID": erecruitcache.Current.EntityID, 307 "AdditionalData": encodeURIComponent(tipdata).replace(/'/g, "%27") 308 }; 309 }, 310 // Figures out what ajax, if any, is required for given mode and context 311 RequiredAjax: function (element) { 312 var mode = $(element).data("tipmode"); 313 var context = $(element).data("tipcontext"); 314 315 switch (mode) { 316 case "overview": 317 switch (context) { 318 case "candidate": return { Tabs: { Main: true, Counts: ["Skill", "Match", "Note", "Involved"] } }; 319 case "contact": return { Tabs: { Main: true, Counts: ["Position", "Match", "Note", "Involved"] } }; 320 case "company": return { Tabs: { Main: true, Counts: ["Skill", "Contact", "Position", "Match", "Note", "Involved"] } }; 321 case "position": return { Tabs: { Main: true, Counts: ["Skill", "Match", "Note", "Involved"] } }; 322 case "seed": return { Tabs: { Main: true, Counts: ["Note", "Involved"] } }; 323 case "clientproject": return { Tabs: { Main: true, Counts: ["Match", "Note", "Position"] } }; 324 case "recruiter": return { Tabs: null, Widget: context + "overview" }; 325 case "scheduleditem": return { Tabs: null, Widget: context + "overview" }; 326 case "opportunity": 327 if (isLegalCaseAboutTypeEnabled) 328 return { Tabs: { Main: true, Counts: ["LegalCase", "Position", "Note"] } }; 329 else 330 return { Tabs: { Main: true, Counts: ["Position", "Note"] } }; 331 } 332 break; 333 default: // no mode - just a tipname 334 if ($(element).data("tipname") != null) 335 return { Widget: $(element).data("tipname") }; 336 else if ($(element).data("tipsource")) 337 return { Source: $(element).data("tipsource"), Args: $(element).data("tipargs") }; 338 } 339 340 return null; 341 }, 342 // gets the html for a specific widget 343 // takes { Widget: widgetname, Mode: "replace", Where: element for mode, CoolTip: element of tip, Data: use if loading not from cooltip to directly pass required data) } 344 GetWidget: function (config, withSession) { 345 if (config.Source) { 346 // This is a Knockout-powered widget 347 // The tipsource parameter should have the form "ClassName, app/Path/To/Module" 348 // The tipargs parameter may be either an array or a single value 349 // The erecruit.autobind function is defined in /App_Themes/Default/js/autobind.ts 350 erecruit.autobind(config.Source, config.Args, 351 function () { 352 var where = $("<div " + ((config.Style !== undefined && config.Style["style"] !== undefined) ? "style='" + config.Style["style"] + "'" : "") + ">").insertBefore(config.Where); 353 config.Where.remove(); 354 return where; 355 }, 356 function (where, viewModel) { 357 where.data("ViewModel", viewModel).trigger("ViewModelLoaded", viewModel); 358 Tipped.refresh(where[0]); 359 if (viewModel.AutobindComplete) { 360 viewModel.AutobindComplete(where); 361 } 362 }); 363 364 return; 365 } 366 367 var data = config.CoolTip ? 368 JSON.stringify(this.GetCommonParameters(config.CoolTip)) : 369 config.Data; 370 371 function success(result) { 372 373 if (!ismvcget) { 374 result = result.d; // not sure why... see other comment 375 } 376 377 var $result = $(result); 378 switch (config.Mode) { 379 case "replace": 380 config.Where.before($result).remove(); 381 break; 382 case "replaceinside": 383 config.Where.html($result); 384 break; 385 default: 386 alert(erecruit.Strings.WidgetModeNotSupported + config.Mode); 387 } 388 389 erecruit.CoolTips.Widgets.LoadAutoWidgets($result); 390 //after jquery update $(document).ready() and $(function(){}) (which most of the time are the same based in jquery docs) 391 //are behaving a little bit different which is causing issues with tipped, since it requires to have UI final rendered before we call tipped.refresh 392 //set timeout makes sure refresh is pushed at the end of the queue and runs when UI is final 393 window.setTimeout(function () { 394 Tipped.refresh($result[0]); 395 }) 396 } 397 398 function error(err) { 399 switch (config.Mode) { 400 case "replace": 401 case "replaceinside": 402 config.Where.replaceWith("<div class='warning messaging'>" + erecruit.Strings.OhNoYourWidgetCouldntBeLoaded + "<br />" + err.responseText + "</div>"); 403 break; 404 } 405 406 Tipped.refresh(config.Where[0]); 407 } 408 409 var ismvcget = !!config.TipURL; 410 411 $.ajax({
412 type: ismvcget ? "GET" : "POST", 413 contentType: ismvcget ? "application/x-www-form-urlencoded; charset=utf-8" : "application/json; charset=utf-8", 414 url: ismvcget ? config.TipURL : baseUrl + "Services/CoolTipService.asmx/GetWidget" + (withSession ? "WithSession" : ""), 415 data: ismvcget ? null : "{'widgetname':'" + config.Widget + "','data':'" + data + "'}", 416 dataType: ismvcget ? "html" : "json", 417 success: success, 418 error: error 419 }); 420 }, 421 // Loads the widgets according to tip mode and context 422 // should only be called if requiredajax is not null 423 LoadWidgets: function (requiredajax, content, element) { 424 var context = $(element).data("tipcontext"); 425 var refid = $(element).data("tiprefid"); 426 var usesession = (typeof $(this).attr('data-session') != 'undefined' && $(this).attr('data-session') && $(this).data("session") == 'disabled') ? false : true; 427 var mode = $(element).data("tipmode"); 428 429 if (mode == "overview" && erecruitcache.Current.LoggedInAsMode != "Recruiter" && erecruitcache.Current.LoggedInAsMode != "VendorManager") { 430 $(".cooltiploading.main", content).replaceWith("<div class='warning messaging'>" + erecruit.Strings.ThisFeatureIsAvailableOnlyToRecruiterAndVendorManager + "</div>"); 431 } 432 else 433 // if Tabs is true, then this must have a name and therefore, we must call spview 434 // if counts are also true, then show the name and counts as tabs 435 if (requiredajax.Tabs != null) { 436 $.ajax( 437 { 438 type: "POST", 439 contentType: "application/json; charset=utf-8", 440 url: baseUrl + "Services/CoolTipService.asmx/GetCounts", 441 data: "{'abouttype':'" + context + "','referenceid':'" + refid + "','userid':'" + erecruitcache.Current.UserID + "','loggedinas':'" + erecruitcache.Current.LoggedInAsMode + "','entityid':'" + erecruitcache.Current.EntityID + "'}", 442 dataType: "json", 443 success: function (result) { 444 result = result.d; // I have no idea why this is needed but for some reason the json is coming as an object under a property called "d". :-/ - [if] It's used to prevent JSON hijack attack 445 var tabs = ""; 446 447 // main tab 448 if (requiredajax.Tabs.Main) 449 tabs += "<li data-widgetname='" + context + "overview'><a href='#tab-Main'><img align='top' height='14' width='14' src='" + baseUrl + "Mvc/Content/Images/icons/abouttypes/" + erecruitcache.Lookup.AboutType(context) + ".png' /> " + result.Name + "</a></li>"; 450 451 // count tabs 452 for (var i = 0; i < requiredajax.Tabs.Counts.length; i++) 453 tabs += "<li style='float: right;' data-widgetname='" + requiredajax.Tabs.Counts[i].toString() + "List'><a href='#tab-" + requiredajax.Tabs.Counts[i] + "Count' title='" + requiredajax.Tabs.Counts[i] + " " + erecruit.Strings.Count + "'><img align='top' width='14px' height='14px' style='margin-right: 3px;' src='" + baseUrl + "Mvc/Content/Images/icons/" + requiredajax.Tabs.Counts[i] + ".png' />" + result[requiredajax.Tabs.Counts[i] + "Count"] + "</a></li>"; 454 455 tabs = "<div class='cooltiptabs'><ul>" + tabs + "</ul>"; 456 457 // main (overview) tab body 458 tabs += "<div id='tab-Main'>" + erecruit.CoolTips.TabLoaderDiv + "</div>"; 459 460 // when a tab is selected, if tab body contains the loader div, it means it needs to be loaded 461 for (var i = 0; i < requiredajax.Tabs.Counts.length; i++) 462 tabs += "<div id='tab-" + requiredajax.Tabs.Counts[i] + "Count'>" + erecruit.CoolTips.TabLoaderDiv + "</div>"; 463 464 tabs += "</div>"; 465 466 // replace loader with tabs 467 $(".cooltiploading.main", content).before(tabs).remove(); 468 469 // tabify tabs 470 $(".cooltiptabs", content).tabs( 471 { 472 create: function (event, ui) { 473 if ($(".cooltiploading", ui.panel).length > 0) { 474 erecruit.CoolTips.Widgets.GetWidget( 475 { 476 Widget: ui.tab.data("widgetname"), 477 Mode: "replace", 478 Where: $(".cooltiploading", ui.panel), 479 CoolTip: element 480 }, usesession); 481 } 482 483 Tipped.refresh(element); 484 }, 485 activate: function (event, ui) { 486 if ($(".cooltiploading", ui.newPanel).length > 0) { 487 erecruit.CoolTips.Widgets.GetWidget( 488 { 489 Widget: ui.newTab.data("widgetname"), 490 Mode: "replace", 491 Where: $(".cooltiploading", ui.newPanel), 492 CoolTip: element 493 }, usesession); 494 } 495 496 if (ui && ui.newPanel) { 497 Tipped.refresh(ui.newPanel[0]); 498 } 499 Tipped.refresh(element); 500 } 501 });
502 503 Tipped.refresh(element); 504 }, 505 error: function (err) { 506 $(".cooltiploading.main", content).replaceWith("<div class='warning messaging'>" + erecruit.Strings.OhNoYourWidgetCouldntBeLoaded + "<br />" + err.responseText + "</div>"); 507 } 508 }); 509 } 510 else // must be trying to open one widget 511 { 512 erecruit.CoolTips.Widgets.GetWidget( 513 { 514 Widget: requiredajax.Widget, 515 Source: requiredajax.Source, 516 Args: requiredajax.Args, 517 Mode: "replace", 518 Where: $(".cooltiploading.main", content), 519 CoolTip: element 520 }, usesession); 521 } 522 }, 523 // checks for existence of .autowidget and loads them 524 LoadAutoWidgets: function (root) { 525 $.each($(".autowidget:not('.loading')", root || document), function (i, el) { 526 $(el).addClass('loading'); 527 var usesession = (typeof $(this).attr('data-session') != 'undefined' && $(this).attr('data-session') && $(this).data("session") == 'disabled') ? false : true; 528 529 erecruit.CoolTips.Widgets.GetWidget( 530 { 531 Widget: $(this).data("tipname"), 532 TipURL: $(this).data("tipurl"), 533 Source: $(this).data("tipsource"), 534 Args: $(this).data("tipargs"), 535 Mode: "replace", 536 Where: $(this), 537 CoolTip: el, 538 Style: $(this).data("tipstyle") 539 }, usesession); 540 }); 541 } 542 }, 543 // element has the following data items: tipmode, tipcontext, tiprefid, tipname, tipdata 544 // mode can be overview, norc 545 // context is abouttype name lowercase 546 // refid is referenceid 547 // tipname is the name of the tip if mode is not overview 548 // tipdata is json 549 LoadCoolTip: function (content, element) { 550 var mode = $(element).data("tipmode"); 551 552 var isOverview = (mode == "overview" && erecruitcache.Current.LoggedInAsMode != "Recruiter" && erecruitcache.Current.LoggedInAsMode != "VendorManager"); 553 554 var immediateoptions = mode != "norc" && !isOverview ? 555 erecruit.CoolTips.ImmediateOptions.ResolveOptions(erecruit.CoolTips.ImmediateOptions.GetElementOptions(element), element) : 556 ""; 557 558 var requiredajax = erecruit.CoolTips.Widgets.RequiredAjax(element); 559 var loaderdiv = requiredajax != null ? erecruit.CoolTips.MainLoaderDiv : ""; 560 561 if (immediateoptions != "") 562 $(".cooltiploading.main", content).before(immediateoptions); 563 564 $(".cooltiploading.main", content).before("<div class='cooltipmessage bordered' style='display: none; margin: 5px 0; clear: both;'>backup messagebox</div>") 565 566 if (requiredajax != null) 567 erecruit.CoolTips.Widgets.LoadWidgets(requiredajax, content, element); 568 else 569 $(".cooltiploading.main", content).remove(); 570 }, 571 _findMessageDiv: function (widgetid, create) { 572 var messagediv = $("#" + widgetid + "_message"); 573 if (!messagediv.length) messagediv = $(".cooltipmessage:first", $("#" + widgetid).closest(".t_Tooltip")); 574 if (!messagediv.length) messagediv = $(".cooltipmessage:first", $("#" + widgetid)); 575 if (!messagediv.length && create) messagediv = $("<div>", { 'class': 'cooltipmessage' }).prependTo("#" + widgetid); 576 577 return messagediv; 578 }, 579 // shows a message above a widget. message type is Info, Warning or Error 580 // widgetid_message is not found, travel up the dom from source to the closest .cooltipmessage and show it there 581 ShowMessage: function (widgetid, messagetype, message) { 582 var messagediv = erecruit.CoolTips._findMessageDiv(widgetid, true); 583 var refresh = function () { Tipped.refresh(messagediv[0]); }; 584 585 messagediv 586 .hide() 587 .removeClass("info error warning") 588 .addClass(messagetype.toLowerCase()) 589 .html("<div title='" + erecruit.Strings.CloseMessage + "' class=\"close\" onclick=\"erecruit.CoolTips.HideMessage('" + widgetid + "', $(this).closest('.cooltipmessage'))\"></div>" + message) 590 .slideDown("fast", refresh); 591 refresh();
592 }, 593 HideMessage: function (widgetid, cooltipmessage) { 594 var d = erecruit.CoolTips._findMessageDiv(widgetid, false); 595 if (!d.length && cooltipmessage) d = cooltipmessage; 596 d.slideUp("fast", function () { Tipped.refresh(d[0]); }); 597 }, 598 ClearMessages: function (widgetid) { 599 var messagediv = erecruit.CoolTips._findMessageDiv(widgetid, true); 600 var refresh = function () { Tipped.refresh(messagediv[0]); }; 601 messagediv.empty().hide(); 602 refresh(); 603 }, 604 // hides all the cooltips for a selector 605 HideCoolTips: function (selector) { 606 $(selector).each(function () { 607 Tipped.hide(erecruit.CoolTips.FakeTrigger(this)); 608 }); 609 }, 610 611 FakeTrigger: function (element, value) { 612 var key = "{8E0A03B5-02BE-4EA6-B011-616AC8FD1FFC}"; 613 var $e = $(element); 614 if (value === undefined) { 615 return $e.data(key); 616 } 617 else { 618 $e.data(key, value); 619 erecruit.CoolTips.RealTrigger(value, $e); 620 } 621 }, 622 623 RealTrigger: function (elementOrContentOrFakeTrigger, value) { 624 var key = "{34AC4343-7A38-4683-8292-D56C1875F5BE}"; 625 var $e = $(elementOrContentOrFakeTrigger); 626 var fakeTrigger = erecruit.CoolTips.FakeTrigger($e) || Tipped.findElement($e[0]) || $e; 627 return value === undefined ? $(fakeTrigger).data(key) : $(fakeTrigger).data(key, value); 628 }, 629 630 // hides the cooltip and causes the next click to recreate it 631 // if reload is true, calls click on the original trigger effectively reopening the tip 632 HideAndReset: function (id, timeout, callback, reload) { 633 var el = erecruit.CoolTips.RealTrigger("#" + id) 634 var fakeTrigger = erecruit.CoolTips.FakeTrigger(el); 635 636 window.setTimeout(function () { 637 Tipped.hide(fakeTrigger); 638 if (el) el.data("tiploaded", false); 639 Tipped.remove(fakeTrigger); 640 641 if (reload != null && reload && el) 642 el.trigger('click'); 643 644 if (callback != null) 645 callback(el); 646 }, timeout); 647 }, 648 // reloads a widget in place. pass either a widgetid or any element inside a widget 649 ReloadInPlace: function (selector, reloaddata) { 650 var wrapper = $(selector).closest(".widgetwrapper"); 651 var usesession = (typeof wrapper.attr('data-session') != 'undefined' && wrapper.attr('data-session') && wrapper.data("session") == 'disabled') ? false : true; 652 if (wrapper.length > 0) { 653 erecruit.CoolTips.Widgets.GetWidget( 654 { 655 Widget: wrapper.data("widgetname"), 656 Mode: "replace", 657 Where: wrapper, 658 Data: (reloaddata == null ? wrapper.data("reloaddata") : reloaddata), 659 TipURL: wrapper.data("tipurl") 660 }, usesession); 661 } 662 }, 663 Initialize: function () { 664 // var is overwritten when MVC tips were introduced (erecruit.js loaded multiple times per frame) 665 // lets save this at the body level instead so MVC and ASP can share 666 $(document.body).data('tipcount', 0); 667 erecruit.CoolTips.handlingtipclick = false; 668 function InitCommon(e) { 669 var $this = $(this); 670 var fakeTrigger = erecruit.CoolTips.FakeTrigger($this); 671 var isfirsttime = $this.data("tiploaded") != "true"; 672 var target = $this.data("tiptarget") || 'element'; 673 var hook = $this.data("tiphook") || (e.data.click == "right" ? 'righttop' : 'rightmiddle'); 674 var tipUrl = $this.data("tipurl"); 675 var tipElement = $this.data("tipelement"); 676 677 if (isfirsttime) { 678 var insidetooltip = ($this.parents(".t_Tooltip").length > 0); 679 680 if (!fakeTrigger) { 681 erecruit.CoolTips.FakeTrigger($this, fakeTrigger = $("<div class='__fake_trigger'>").appendTo("body")); 682 } 683 fakeTrigger.css({ position: 'absolute', 'z-index': -1000 }) 684 .position({ my: "left top", at: "left top", of: $this }) 685 .width($this.width()).height($this.height()); 686 687 var loader; 688 if ($this.data("tipshowspinner"))//if cooltip has data-tipshowspinner="true" then show a loading spinner while loading 689 { 690 //NOTE: in this version we dynamically add, show and later destroy the spinner 691 //other option would be to create it once and then show/hide but that would be more usefull if we extract spinner functionality as separate class and use it where needed 692 loader = $(erecruit.CoolTips.LoadingSpinner).insertAfter($this).addClass("show"); 693 } 694 else { 695 loader = null; 696 } 697 698 Tipped.create(fakeTrigger[0], tipUrl || tipElement || function () { return erecruit.CoolTips.MainLoaderDiv; }, 699 { 700 skin: 'erecruitDefault', 701 ajax: !!tipUrl, 702 fixed: true, 703 inline: !!tipElement, 704 // because of event delegation, must close cooltips manually on document click to be able to maintain stack properly 705 hideOn: false, 706 hideOthers: !insidetooltip, 707 closeButton: (e.data.click == "left"), 708 showOn: e.data.click == "right" ? 'contextmenu' : "click", 709 target: target, 710 // zindex has to be set to maintain stack properly 711 zIndex: 2000000, 712 hook: hook, 713 onShow: function (content, element) { 714 if (loader) {//if there is loading spinner remove it 715 loader.remove(); 716 } 717 var isfirsttime = $this.data("tiploaded") != "true"; 718 var tipcount = $(document.body).data('tipcount'); 719 $this.data("tiporder", ++tipcount); 720 $(document.body).data('tipcount', tipcount); 721 722 if (isfirsttime) { 723 erecruit.CoolTips.LoadCoolTip(content, $this[0]); 724 $this.data("tiploaded", "true"); 725 } 726 }, 727 onHide: function (content, element) { 728 var wrapper = $(content).find(".widgetwrapper")[0]; 729 if ($this.hasClass("clicktip") && !$this.hasClass("dont-close-tipstack")) { 730 CloseTipStackAbove(content); 731 } 732 733 if (wrapper) { 734 var id = wrapper.id.split("wrapper_")[1]; 735 $(document).trigger("CoolTip_Hidden", { WidgetID: id }); 736 } 737 738 var mct = $(content).find(":data(erecruit.CoolTips.ManagedCooltipFrame)"); 739 if (mct) { 740 //Unwrap the cooltip frame and call OnHide if it's defined 741 var mcf = mct.data("erecruit.CoolTips.ManagedCooltipFrame"); 742 if (mcf && mcf.OnHide) mcf.OnHide(); 743 } 744 } 745 });
746 } 747 748 Tipped.show(fakeTrigger[0]); 749 return false; 750 } 751 752 // For all infotip blue skin cooltips which height dimension is larger then page body 753 // we need to make them scrollable 754 require(['app/Controls/Tipped'], function (tipped) { 755 tipped.getExtender().makeScrollable(); 756 }); 757 758 function InitHover(e) { 759 var tiptrigger = $(this); 760 761 if (tiptrigger.hasClass("infotip")) { 762 Tipped.create(this, tiptrigger.attr("title"), 763 { 764 skin: 'blue', 765 showDelay: tiptrigger.hasClass('fast') ? 0 : 2000, 766 maxWidth: tiptrigger.hasClass('wide') ? 500 : 230 767 }); 768 } 769 else if (tiptrigger.hasClass("errortip")) { 770 var content = ""; 771 772 if (tiptrigger.hasClass("has-validation") && tiptrigger.hasClass("input-validation-error")) { 773 content = function () { return tiptrigger.parent().find("span[generated='true']").html() }; 774 } 775 else if (tiptrigger.hasClass("has-validation") && !tiptrigger.hasClass("input-validation-error")) { 776 content = ""; 777 } 778 else { 779 content = tiptrigger.attr("title"); 780 } 781 782 if (content != "") { 783 Tipped.create(this, content, 784 { 785 skin: 'red', 786 showDelay: 0, 787 maxWidth: 230 788 }); 789 } 790 } 791 else if (tiptrigger.hasClass('menutip')) { 792 if (tiptrigger.data('tiploaded') != true) { 793 // string to object 794 var params = eval('(' + tiptrigger.data('tipdata') + ')'); 795 var hook = tiptrigger.data('tiphook'); 796 var aboutType = tiptrigger.data('tipcontext'); 797 var referenceId = tiptrigger.data('tiprefid'); 798 799 // object to parameter list 800 var str = ""; 801 for (var key in params) { 802 if (str != "") { 803 str += "&"; 804 } 805 str += key + "=" + params[key]; 806 } 807 808 var menuUrl = 809 baseUrl + 810 'MVC/Menu/' + 811 tiptrigger.data('tipname') + '/' + 812 (aboutType != undefined ? aboutType + '/' : '') + 813 (referenceId != undefined ? referenceId + '/' : '') + 814 (str != "" ? '?' + str : ''); 815 816 Tipped.create(tiptrigger, menuUrl, { 817 skin: 'white', 818 ajax: true, 819 hook: hook, 820 onShow: function (c, e) { 821 $(c).children('.clicktip').data('tiptarget', tiptrigger[0].id); 822 } 823 });
824 825 tiptrigger.data('tiploaded', true); 826 } 827 } 828 } 829 830 function CloseTipStackAbove(tip) { 831 var tips = $(".t_Tooltip"); 832 var opentips = []; 833 $.each(tips, function (i, el) { 834 //necessary for firefox - reasonable ways to detect tipped's version of visibility are unreliable in firefox 835 if ($(el).css("top") != "-10000px") { 836 opentips.push(el); 837 } 838 }); 839 if (opentips.length > 0) { 840 var highestclicktip = 0; 841 var curtiporder = (tip != null) ? $(erecruit.CoolTips.RealTrigger(tip)).data("tiporder") : 0; 842 843 //find the tiporder of the highest clicktip 844 $.each(opentips, function (i, el) { 845 var tipelement = $(erecruit.CoolTips.RealTrigger(el)); 846 var tiporder = tipelement.data("tiporder"); 847 848 if (tipelement.hasClass("clicktip") && tiporder > highestclicktip) 849 highestclicktip = tipelement.data("tiporder"); 850 }); 851 852 // traverse tips, check order of each and close any that are higher order unless there is a clicktip that's even higher 853 $.each(opentips, function (i, el) { 854 var tipelement = $(erecruit.CoolTips.RealTrigger(el)); 855 var tiporder = tipelement.data("tiporder"); 856 857 if (tiporder > curtiporder && tiporder > highestclicktip) { 858 Tipped.hide(erecruit.CoolTips.FakeTrigger(tipelement)); 859 } 860 }); 861 } 862 } 863 864 // YOU ONLY NEED TO INIT ONCE PER PAGE 865 // init rightclick tips 866 $(document).off("contextmenu", ".cooltip").on("contextmenu", ".cooltip", { click: "right" }, InitCommon); 867 868 // init leftclick tips 869 $(document).off("click", ".clicktip").on("click", ".clicktip", { click: "left" }, InitCommon); 870 // init leftclick cooltips (opened via left click but behaves like a cooltip without an x to close) 871 $(document).off("click", ".coolclicktip").on("click", ".coolclicktip", { click: "right" }, InitCommon); 872 // init infotips 873 $(document).off("mouseenter", ".infotip, .errortip").on("mouseenter", ".infotip, .errortip", InitHover); 874 // init rcoption black tips 875 $(document).off("mouseenter", ".rcoption").on("mouseenter", ".rcoption", function () { Tipped.create(this) }); 876 // init 'quicktips' 877 $(document).off('mouseenter', '.menutip').on('mouseenter', '.menutip', InitHover); 878 879 // init click handling and stacking 880 $(document).off("click", ".t_Tooltip").on("click", ".t_Tooltip", function (e) { 881 erecruit.CoolTips.handlingtipclick = true; 882 CloseTipStackAbove(this); 883 }); 884 885 // OTK (2019-08-28): This is a patch to support correct tooltip stack closing behavior 886 // At one time there will have been several Initialize closures run. 887 // However, we have to ensure there at that time there is just *one* click handler that 888 // handles tip closing along the stack. The following hack will do the trick. 889 // *** BEGIN HACK *** 890 erecruit.CoolTips.clickHandler = erecruit.CoolTips.clickHandler || function (e) { 891 if (!erecruit.CoolTips.handlingtipclick) { 892 CloseTipStackAbove(null); 893 } 894 erecruit.CoolTips.handlingtipclick = false; 895 } 896 // init closing on click outside 897 if (erecruit.CoolTips.clickHandler.isClickBound === undefined) { 898 erecruit.CoolTips.clickHandler.isClickBound = true; 899 $(document).on("click", erecruit.CoolTips.clickHandler); 900 } 901 // *** END HACK *** 902 // init autowidgets 903 erecruit.CoolTips.Widgets.LoadAutoWidgets(); 904 } 905 }, 906 Controls: 907 { 908 InitializeFields: function (scopeid, callback, scope) { 909 require(['app/Localization/LocalizationService', 'app/Localization/LocalizationUtils'], function (localization, localizationInit) { 910 var localService = localization.GetService(); 911 912 $("#" + scopeid + " input[data-inputtype='list']").each(function (index) { 913 $(this).dropdown({ 914 minLength: 0, 915 allowEmpty: true, 916 initSelectedValue: $(this).val() == null || $(this).val() == '' ? null : $(this).val(), 917 source: $(this).data("values"), 918 select: function (event, ui) { 919 // must do this to keep state 920 $(this).dropdown("option", "selectedItem", ui.item); 921 $(this).val(ui.item.label); 922 return false; 923 } 924 });
925 }); 926 927 $("#" + scopeid + " input[data-inputtype='date']:enabled").each(function (index) { 928 var el = $(this); 929 930 $(this).datepicker({ 931 changeMonth: true, 932 changeYear: true, 933 numberOfMonths: 3, 934 showOtherMonths: true, 935 selectOtherMonths: true, 936 buttonImage: baseUrl + "Mvc/Content/images/icons/calendar.png", 937 buttonImageOnly: true, 938 showOn: 'both', 939 beforeShow: function () { 940 var strCtrl = $(this).attr("startDate-ControlId"); 941 var endCtrl = $(this).attr("endDate-ControlId"); 942 if (strCtrl) { 943 $date = new Date($("#" + strCtrl).val()); 944 $(this).datepicker("option", "minDate", new Date($date.setDate($date.getDate() + 1))); 945 } 946 if (endCtrl) { 947 $date = new Date($("#" + endCtrl).val()); 948 $(this).datepicker("option", "maxDate", new Date($date.setDate($date.getDate() - 1))); 949 } 950 } 951 }); 952 953 el.data("fn-get-value", function () { 954 var d = formatDate(el.val()); 955 return d ? d : ""; 956 }); 957 }); 958 959 $("#" + scopeid + " input[data-inputtype='datetime']:enabled").each(function (index) { 960 var el = $(this), 961 val = el.val(), 962 time = formatTime(val), 963 date = formatDate(val), 964 tp = $("<input type=\"text\" style=\"width: 85px; margin-left: 5px;\" />") 965 .insertAfter(this) 966 .val(time); 967 968 el.val(date); 969 970 el.datepicker({ 971 changeMonth: true, 972 changeYear: true, 973 numberOfMonths: 3, 974 showOtherMonths: true, 975 selectOtherMonths: true, 976 buttonImage: baseUrl + "Mvc/Content/images/icons/calendar.png", 977 buttonImageOnly: true, 978 showOn: 'both', 979 beforeShow: function () { 980 var strCtrl = $(this).attr("startDate-ControlId"); 981 var endCtrl = $(this).attr("endDate-ControlId"); 982 if (strCtrl) { 983 $date = new Date($("#" + strCtrl).val()); 984 $(this).datepicker("option", "minDate", new Date($date.setDate($date.getDate() + 1))); 985 } 986 if (endCtrl) { 987 $date = new Date($("#" + endCtrl).val()); 988 $(this).datepicker("option", "maxDate", new Date($date.setDate($date.getDate() - 1))); 989 } 990 } 991 }); 992 993 // Add time-picker 994 tp.timepicker({ 995 showLeadingZero: false, 996 showPeriod: localService.IsHour12Format(), 997 showPeriodLabels: localService.IsHour12Format() 998 }).after("<img title='" + erecruit.Strings.ChooseTime + "' src='" + baseUrl + "Mvc/Content/Images/icons/time.png' width='16' height='16' />"); 999 1000 el.data("fn-get-value", function () { 1001 var d = formatDate(el.val()); 1002 return d ? d + " " + tp.val() : ""; 1003 }); 1004 }); 1005 1006 function formatDate(dateValue) { 1007 return dateTimeFormat(dateValue, { 1008 day: 'numeric', 1009 year: 'numeric', 1010 month: 'numeric', 1011 hour12: undefined 1012 }); 1013 } 1014 1015 function formatTime(dateValue) { 1016 return dateTimeFormat(dateValue, { 1017 hour: 'numeric', 1018 minute: 'numeric', 1019 hour12: localService.IsHour12Format() 1020 }); 1021 } 1022 1023 function dateTimeFormat(dateValue, format) { 1024 var d = localService.ParseDate(dateValue, { 1025 day: 'numeric', 1026 year: 'numeric', 1027 month: 'numeric', 1028 hour: 'numeric', 1029 minute: 'numeric', 1030 hour12: localService.IsHour12Format() 1031 }); 1032 1033 d = d ? d : localService.ParseDate(dateValue, format); 1034 return d ? localService.FormatDate(d, format) : null; 1035 } 1036 1037 $("#" + scopeid + " select[data-inputtype='multiselect']").each(function (index) { 1038 $(this).multiselect({ 1039 source: $(this).data("source"), 1040 selectedValues: $(this).data("selectedvalues") || $(this).val() || [] 1041 }); 1042 }); 1043 1044 localizationInit.LocalizeNumericInputs(scope); 1045 1046 callback && callback.call(scope || this); 1047 }); 1048 }, 1049 } 1050 }); 1051 1052// extending jquery ui datepicker 1053$.datepicker.setDefaults({ 1054 beforeShow: function () { 1055 // stop datepicker click event propagation to prevent tooltips closing 1056 $("#ui-datepicker-div").on("click", function (event) { 1057 event.stopPropagation(); 1058 }); 1059 } 1060}); 1061 1062// extending jquery ui autocomplete 1063$.widget("erecruit.dropdown", $.ui.autocomplete, 1064 { 1065 options: 1066 { 1067 position: { my: "left top", at: "left bottom", collision: "flip", offset: "0 -1" }, 1068 // if set, will highlight on create for local data sources 1069 initSelectedValue: null, 1070 // this gets updated when the selected item is manually changed 1071 // there's no need to set this in the options - initSelectedValue is enough to prefill the value 1072 selectedItem: null, 1073 allowEmpty: false, 1074 allowCustomValues: false, 1075 // adds support for showing the label in the input when doing arrow up or down through the list 1076 focus: function (event, ui) { 1077 $(this).val(ui.item.label); 1078 return false; 1079 } 1080 }, 1081 // adds support for initSelectedValue 1082 // adds support for opening menu on focus and click 1083 // adds support for not closing cooltip when selecting item 1084 _create: function () { 1085 var self = this; 1086 1087 if (this.element && typeof this.element.attr('data-source') != 'undefined' && this.element.attr('data-source') && this.element.data("source") != '') { 1088 this.options.source = this.element.data("source"); 1089 } 1090 1091 $.ui.autocomplete.prototype._create.call(this); 1092 1093 if (this.options.initSelectedValue != null) { 1094 this.select(this.options.initSelectedValue); 1095 } 1096 else if (this.element && typeof this.element.attr('data-selectedvalue') != 'undefined' && this.element.attr('data-selectedvalue') && this.element.data("selectedvalue") != '') { 1097 this.select(this.element.data("selectedvalue")); 1098 } 1099 1100 this.element 1101 .focus(function () { $(this).dropdown("search", ""); }) 1102 .on('click',function () { 1103 $(this).dropdown("search", ""); 1104 $(this).trigger('select'); 1105 }); 1106 1107 this.menu.element.on('click',function (e) { e.stopPropagation(); }); 1108 }, 1109 // adds support for enabled=true/false, icon, and tooltip 1110 _renderItem: function (ul, item) { 1111 // if not defined, assume enabled 1112 var enabled = (item.enabled == undefined || item.enabled); 1113 var tooltip = (item.tooltip != null && item.tooltip != "") ? item.tooltip : ""; 1114 1115 return $("<li></li>") 1116 .data("item.autocomplete", item) 1117 .append(enabled ? 1118 "<a style='background-color: " + (item.color != "" ? item.color : "auto") + ";' title='" + tooltip + "'>" + item.label + (item.icon == null || item.icon == "" ? "" : "<img style='margin-left: 3px; float: right' src='" + item.icon + "'>") + (item.additionalData || "") + "</a>" : 1119 "<span title='" + tooltip + "' style='padding: .2em .4em; line-height: 1.5; border: 1px solid transparent' class='ui-state-disabled'>" + item.label + "</span>") 1120 .appendTo(ul); 1121 }, 1122 // adds support for reverting to previous value if left with a typed in value instead of a selected one 1123 _change: function (event) { 1124 if (this.element.val() == "" && this.options.allowEmpty) { 1125 // trying to change it to nothing 1126 this.options.selectedItem = null; 1127 } 1128 else if (this.options.allowCustomValues && Array.isArray(this.options.source) && this.element.val() != "") { 1129 // add custom value? 1130 var value = this.element.val(); 1131 this.options.selectedItem = $.grep(this.options.source, function (el) { return el.value == value; })[0]; 1132 if (this.options.selectedItem == null) { 1133 // add an new option and select it 1134 var item = new Object(); 1135 item.label = value; 1136 item.value = value;
1137 this.options.source.push(item); 1138 this.options.selectedItem = $.grep(this.options.source, function (el) { return el.value == value; })[0]; 1139 } 1140 } 1141 else { 1142 var isdifferent = this.options.selectedItem == undefined || this.options.selectedItem.label != this.element.val(); 1143 1144 if (isdifferent) { 1145 if (this.options.selectedItem != null) 1146 this.element.val(this.options.selectedItem.label); 1147 else 1148 this.element.val(""); 1149 } 1150 } 1151 1152 $(this.element).trigger("autocompletechange", { item: this.options.selectedItem }); 1153 1154 $.ui.autocomplete.prototype._change.call(this, event); 1155 }, 1156 select: function (value) { 1157 if (Array.isArray(this.options.source)) { 1158 this.options.selectedItem = $.grep(this.options.source, function (el) { return el.value == value; })[0]; 1159 if (this.options.selectedItem != null) { 1160 this.element.val(this.options.selectedItem.label); 1161 this._trigger("select", null, { item: this.options.selectedItem }); 1162 } 1163 } 1164 else { 1165 var self = this; 1166 1167 self.element.addClass("ui-autocomplete-loading"); 1168 1169 this.options.source({ term: value }, function (data) { 1170 if (data.length > 0) { 1171 self.options.selectedItem = $.grep(data, function (el) { return el.value == value; })[0]; 1172 if (self.options.selectedItem != null) { 1173 self.element.val(self.options.selectedItem.label); 1174 self._trigger("select", null, { item: self.options.selectedItem }); 1175 } 1176 } 1177 1178 self.element.removeClass("ui-autocomplete-loading"); 1179 }); 1180 } 1181 }, 1182 clear: function () { 1183 this.options.selectedItem = null; 1184 this.element.val(""); 1185 } 1186 }); 1187 1188$.widget("erecruit.multiselect", 1189 { 1190 options: 1191 { 1192 position: { my: "left top", at: "left bottom", collision: "flip", offset: "0 -1" }, 1193 selectedValues: [] 1194 }, 1195 1196 _create: function () { 1197 var self = this, 1198 select = this.select = this.element.hide(), 1199 wrapper = this.wrapper = $("<span>") 1200 .insertAfter(select); 1201 1202 select.attr("multiple", "multiple"); 1203 var input = this.input = $("<input>") 1204 .appendTo(wrapper) 1205 .autocomplete({ 1206 source: self.options.source, 1207 appendTo: "body", 1208 minLength: 0, 1209 close: function (event, ui) { 1210 self._setDisplay(self._getItemsFromValues(self.options.selectedValues)); 1211 } 1212 }); 1213 1214 input.data("ui-autocomplete")._renderItem = function (ul, item) { 1215 $(ul).on("click", function (event) { 1216 event.stopPropagation(); 1217 }); 1218 var enabled = (item.enabled == undefined || item.enabled); 1219 var tooltip = (item.tooltip != null && item.tooltip != "") ? item.tooltip : ""; 1220 1221 var li = $("<li>") 1222 .data("ui-autocomplete-item", item) 1223 .append(enabled ? "<label><input type='checkbox' />" + item.label + "</label>" : "<label><input title='" + tooltip + "' type='checkbox' disabled='disabled' />" + item.label + "</label>") 1224 .appendTo(ul); 1225 1226 $('input', li).on('change',function () { 1227 var value = $(this).parent().parent().data("ui-autocomplete-item").value; 1228 1229 //update the selectedValues based on what's actually selected 1230 if ($(this).is(":checked")) { 1231 //Add this item's value to the selectedValues array 1232 if ($.inArray(value, self.options.selectedValues) == -1) self.options.selectedValues.push(value); 1233 } 1234 else { 1235 var t = []; 1236 for (var i = 0; i < self.options.selectedValues.length; i++) 1237 if (self.options.selectedValues[i] != value) t.push(self.options.selectedValues[i]); 1238 1239 self.options.selectedValues = t; 1240 } 1241 }); 1242 1243 if ($.inArray(item.value, self.options.selectedValues) > -1) { 1244 $('input', li).attr("checked", "checked"); 1245 } 1246 return li; 1247 }; 1248 1249 input.on('click',function () { 1250 if (input.autocomplete("widget").is(":visible")) { 1251 input.autocomplete("close"); 1252 return; 1253 } 1254 $(input).val(""); 1255 //display the drop down with all options 1256 input.autocomplete("search", ""); 1257 }); 1258 1259 this.sep = this.options.sep || ";"; 1260 this.sep = String.prototype.trim.call(this.sep ? this.sep : '') + " "; 1261 1262 this._setDisplay(this._getItemsFromValues(this.options.selectedValues)); 1263 }, 1264 destroy: function () { 1265 this.wrapper.remove(); 1266 this.element.show(); 1267 $.Widget.prototype.destory.call(this); 1268 }, 1269 _getItemsFromValues: function (values) { 1270 var items = []; 1271 //display the label of the selected options 1272 for (var i = 0; i < this.options.source.length; i++) { 1273 if ($.inArray(this.options.source[i].value, this.options.selectedValues) > -1) 1274 items.push(this.options.source[i]); 1275 } 1276 return items; 1277 }, 1278 //Sets the display for the drop down and synchronizes the underlying select object 1279 _setDisplay: function (items) { 1280 var sep = ""; 1281 var display = ""; 1282 $(this.select).empty(); 1283 1284 for (var i = 0; i < items.length; i++) { 1285 display += sep + items[i].label; 1286 sep = this.sep; 1287 1288 $("<option>") 1289 .attr("value", items[i].value) 1290 .attr("selected", "selected") 1291 .append(items[i].label) 1292 .appendTo(this.select); 1293 } 1294 1295 $(this.input).val(display); 1296 } 1297 });
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.